Files
bitvid/components/edit-video-modal.html
T
thePR0M3TH3ANandClaude Opus 4.8 c62114557c feat(webseed): manage multiple web seeds in the edit modal (slice 3/3)
Completes end-to-end multi-webseed support: the editor can now see, add, and
remove every web seed a video carries.

- magnetShared: promote normalizeWebSeedList to a shared export (videoNotePayload
  now imports it) and add setMagnetWebSeeds(), which replaces a magnet's COMPLETE
  ws= set with exactly the requested list. ensureWebSeeds is append-only, so
  without set-semantics a webseed a user deleted would linger in the magnet;
  setMagnetWebSeeds strips the existing ws= params first, making removal stick.
- edit-video-modal.html: the single "Web seed (ws=)" input becomes a "Web seeds
  (one per line)" textarea with backup-origin help text.
- EditModal: open() populates the field from extractAllWebSeeds() (every seed,
  not just the first). On save, when the field was manually edited the magnet's
  ws set is rebuilt from the field via setMagnetWebSeeds (true add/remove);
  otherwise existing seeds are preserved untouched. The content `ws` field still
  stores the primary (first) seed while the magnet carries the full set.

Mutation-verified (no-strip and no-add both fail the removal/add tests); build,
relevant lints (inline-styles, tokens, innerHTML), and full unit suite green.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-19 08:52:11 -04:00

968 lines
39 KiB
HTML

<!-- components/edit-video-modal.html -->
<div
id="editVideoModal"
class="bv-modal hidden items-start md:items-center"
role="dialog"
aria-modal="true"
tabindex="-1"
data-ds="new"
>
<div id="editVideoModalOverlay" class="bv-modal-backdrop"></div>
<div class="bv-modal__panel modal-sheet max-h-modal-shell overflow-y-auto" tabindex="-1">
<div class="modal-header">
<h2 class="text-xl font-bold text-text">Edit Video Note</h2>
<button id="closeEditVideoModal" class="modal-close">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>
</div>
<div class="modal-body space-y-6">
<p class="text-sm text-muted">
Fields that already have values are locked. Click <strong>Edit field</strong> to make changes.
</p>
<form id="editVideoForm" class="space-y-5">
<div class="space-y-1">
<label for="editVideoTitle" class="block text-sm font-medium text-text">
Title
</label>
<div class="flex flex-col gap-2 sm:flex-row">
<input
type="text"
id="editVideoTitle"
class="flex-1 input"
placeholder="Video title"
/>
<button
type="button"
class="btn-ghost focus-ring hidden text-xs font-semibold uppercase tracking-wide"
data-edit-target="editVideoTitle"
>
Edit field
</button>
</div>
</div>
<!-- NOTE: Keep this NIP-71 markup in sync with the upload and revert modals. -->
<div
class="space-y-4 rounded-lg border border-border/70 bg-overlay-black/30 p-4"
id="editNip71EventDetails"
data-nip71-section="event-details"
>
<fieldset
id="editNip71KindFieldset"
class="space-y-2"
data-nip71-fieldset="kind"
>
<legend class="text-sm font-semibold text-text">
NIP-71 event type
</legend>
<p class="text-xs text-muted">
Choose the video format. <span class="font-medium text-muted-strong">Kind 21</span> is a full video, while
<span class="font-medium text-muted-strong">Kind 22</span> is a short.
</p>
<div
class="form-control"
role="radiogroup"
aria-labelledby="editNip71KindFieldset"
>
<div class="menu sm:flex-row sm:flex-wrap sm:py-0" role="presentation">
<label class="menu__item gap-3 px-0 py-0" for="editNip71KindLong">
<input
type="radio"
name="editNip71Kind"
id="editNip71KindLong"
value="21"
checked
data-nip71-input="kind"
class="h-4 w-4 border-border bg-panel text-info focus:ring-info"
/>
<span class="text-sm text-text">Normal video (kind 21)</span>
</label>
<label class="menu__item gap-3 px-0 py-0" for="editNip71KindShort">
<input
type="radio"
name="editNip71Kind"
id="editNip71KindShort"
value="22"
data-nip71-input="kind"
class="h-4 w-4 border-border bg-panel text-info focus:ring-info"
/>
<span class="text-sm text-text">Short video (kind 22)</span>
</label>
</div>
</div>
</fieldset>
<div class="grid gap-4 md:grid-cols-2" data-nip71-grid="metadata">
<div class="space-y-2">
<label for="editNip71PublishedAt" class="block text-sm font-medium text-text">
Published at
</label>
<input
type="datetime-local"
id="editNip71PublishedAt"
data-nip71-input="published_at"
class="input"
/>
<p class="text-xs text-muted">
Set the canonical publish time for cross-client ordering.
</p>
</div>
<div class="space-y-2">
<label for="editNip71AltText" class="block text-sm font-medium text-text">
Alt text
</label>
<input
type="text"
id="editNip71AltText"
data-nip71-input="alt"
placeholder="Describe the visuals for screen readers"
class="input"
/>
<p class="text-xs text-muted">
Plain-language fallback shown when the media cannot load.
</p>
</div>
<div class="space-y-2">
<label for="editNip71Duration" class="block text-sm font-medium text-text">
Duration (seconds)
</label>
<input
type="number"
id="editNip71Duration"
min="0"
step="0.001"
data-nip71-input="duration"
class="input"
/>
<p class="text-xs text-muted">
Optional legacy fallback in seconds (fractions allowed) for clients that expect a top-level duration.
</p>
</div>
<div class="space-y-2">
<label for="editNip71ContentWarning" class="block text-sm font-medium text-text">
Content warning
</label>
<input
type="text"
id="editNip71ContentWarning"
data-nip71-input="content-warning"
placeholder="e.g., Flashing lights"
class="input"
/>
<p class="text-xs text-muted">
Leave blank if the video is safe for all audiences.
</p>
</div>
</div>
<div class="space-y-2">
<label for="editNip71Summary" class="block text-sm font-medium text-text">
Summary
</label>
<textarea
id="editNip71Summary"
rows="3"
data-nip71-input="summary"
class="textarea"
placeholder="Short synopsis used as the Nostr content field"
></textarea>
<p class="text-xs text-muted">
This becomes the event content. Keep it concise for Nostr readers.
</p>
</div>
</div>
<fieldset
id="editNip71TagsFieldset"
class="space-y-6 rounded-lg border border-border/70 bg-overlay-black/30 p-4"
data-nip71-section="tags"
>
<legend class="relative text-sm font-semibold text-text">
<span class="inline-block -ml-2 rounded px-2 bg-overlay-black/30">NIP-71 tags</span>
</legend>
<p class="text-xs text-muted">
Use the controls below to describe media variants, captions, chapters, participants, and references.
</p>
<section class="space-y-4" aria-labelledby="editNip71ImetaLabel" data-nip71-repeater="imeta">
<div class="flex items-center justify-between">
<h3 id="editNip71ImetaLabel" class="text-sm font-medium text-text">Image metadata (imeta)</h3>
<button
type="button"
class="btn-ghost focus-ring text-xs font-semibold"
data-nip71-add="imeta"
aria-describedby="editNip71ImetaHelp"
>
Add variant
</button>
</div>
<p id="editNip71ImetaHelp" class="text-xs text-muted">
Provide dimensions, MIME type, and resource links for each variant. Nested repeaters let you attach multiple
<code>image</code>, <code>fallback</code>, or <code>service</code> values.
</p>
<div id="editNip71ImetaList" class="space-y-4" data-nip71-list="imeta"></div>
<template id="editNip71ImetaTemplate" data-nip71-template="imeta">
<article class="card space-y-3 bg-surface/60 p-4" data-nip71-entry="imeta">
<div class="grid gap-3 md:grid-cols-2">
<div class="space-y-2">
<label class="block text-xs font-medium text-muted-strong">
MIME type (<code>m</code>)
</label>
<input
type="text"
data-nip71-field="m"
placeholder="video/mp4"
class="input"
/>
<p class="text-3xs text-muted">RFC 2046 media type for this encoding.</p>
</div>
<div class="space-y-2">
<label class="block text-xs font-medium text-muted-strong">
Pixel dimensions (<code>dim</code>)
</label>
<input
type="text"
data-nip71-field="dim"
placeholder="1920x1080"
class="input"
/>
<p class="text-3xs text-muted">Formatted as widthxheight.</p>
</div>
<div class="space-y-2">
<label class="block text-xs font-medium text-muted-strong">
Streaming URL (<code>url</code>)
</label>
<input
type="url"
data-nip71-field="url"
placeholder="https://cdn.example.com/variant.m3u8"
class="input"
/>
<p class="text-3xs text-muted">HTTPS variant URL shared across clients.</p>
</div>
<div class="space-y-2">
<label class="block text-xs font-medium text-muted-strong">
Magnet (<code>x</code>)
</label>
<input
type="text"
data-nip71-field="x"
placeholder="magnet:?xt=urn:btih:..."
class="input"
/>
<p class="text-3xs text-muted">Optional magnet pointer if the variant is seeded via P2P.</p>
</div>
<div class="space-y-2">
<label class="block text-xs font-medium text-muted-strong">
Duration seconds (<code>duration</code>)
</label>
<input
type="number"
data-nip71-field="duration"
min="0"
step="0.001"
placeholder="29.97"
class="input"
/>
<p class="text-3xs text-muted">Fractional seconds supported; clients use this for precise timelines.</p>
</div>
<div class="space-y-2">
<label class="block text-xs font-medium text-muted-strong">
Bitrate bps (<code>bitrate</code>)
</label>
<input
type="number"
data-nip71-field="bitrate"
min="0"
step="1"
placeholder="3500000"
class="input"
/>
<p class="text-3xs text-muted">Average bits per second for this variant.</p>
</div>
</div>
<div class="space-y-3" data-nip71-nested="image">
<div class="flex items-center justify-between">
<h4 class="text-xs font-semibold uppercase tracking-wide text-muted">Image values</h4>
<button
type="button"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-nested-add="image"
>
Add image URL
</button>
</div>
<div class="space-y-2" data-nip71-nested-list="image"></div>
<template data-nip71-nested-template="image">
<div class="flex items-center gap-2" data-nip71-nested-entry="image">
<input
type="url"
placeholder="https://cdn.example.com/poster.jpg"
data-nip71-nested-field="image"
class="flex-1 input"
/>
<button
type="button"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-remove="nested"
aria-label="Remove image URL"
>
Remove
</button>
</div>
</template>
</div>
<div class="space-y-3" data-nip71-nested="fallback">
<div class="flex items-center justify-between">
<h4 class="text-xs font-semibold uppercase tracking-wide text-muted">Fallback URLs</h4>
<button
type="button"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-nested-add="fallback"
>
Add fallback
</button>
</div>
<div class="space-y-2" data-nip71-nested-list="fallback"></div>
<template data-nip71-nested-template="fallback">
<div class="flex items-center gap-2" data-nip71-nested-entry="fallback">
<input
type="url"
placeholder="https://cdn.backup.net/video.mp4"
data-nip71-nested-field="fallback"
class="flex-1 input"
/>
<button
type="button"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-remove="nested"
aria-label="Remove fallback URL"
>
Remove
</button>
</div>
</template>
</div>
<div class="space-y-3" data-nip71-nested="service">
<div class="flex items-center justify-between">
<h4 class="text-xs font-semibold uppercase tracking-wide text-muted">Services</h4>
<button
type="button"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-nested-add="service"
>
Add service
</button>
</div>
<div class="space-y-2" data-nip71-nested-list="service"></div>
<template data-nip71-nested-template="service">
<div class="flex items-center gap-2" data-nip71-nested-entry="service">
<input
type="text"
placeholder="https://api.example.com"
data-nip71-nested-field="service"
class="flex-1 input"
/>
<button
type="button"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-remove="nested"
aria-label="Remove service entry"
>
Remove
</button>
</div>
</template>
</div>
<div class="flex justify-end">
<button
type="button"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-remove="imeta"
>
Remove variant
</button>
</div>
</article>
</template>
</section>
<section class="space-y-4" aria-labelledby="editNip71TextTracksLabel" data-nip71-repeater="text-track">
<div class="flex items-center justify-between">
<h3 id="editNip71TextTracksLabel" class="text-sm font-medium text-text">
Caption &amp; subtitle tracks (text-track)
</h3>
<button
type="button"
class="btn-ghost focus-ring text-xs font-semibold"
data-nip71-add="text-track"
aria-describedby="editNip71TextTracksHelp"
>
Add track
</button>
</div>
<p id="editNip71TextTracksHelp" class="text-xs text-muted">
Supply caption or subtitle URLs along with file type and language so players can surface accessibility features.
</p>
<div id="editNip71TextTrackList" class="space-y-4" data-nip71-list="text-track"></div>
<template id="editNip71TextTrackTemplate" data-nip71-template="text-track">
<article class="card space-y-3 bg-surface/60 p-4" data-nip71-entry="text-track">
<div class="grid gap-3 md:grid-cols-3">
<div class="space-y-2">
<label class="block text-xs font-medium text-muted-strong">Track URL</label>
<input
type="url"
data-nip71-field="url"
placeholder="https://cdn.example.com/subs.vtt"
class="input"
/>
</div>
<div class="space-y-2">
<label class="block text-xs font-medium text-muted-strong">Type</label>
<input
type="text"
data-nip71-field="type"
placeholder="text/vtt"
class="input"
/>
</div>
<div class="space-y-2">
<label class="block text-xs font-medium text-muted-strong">Language</label>
<input
type="text"
data-nip71-field="language"
placeholder="en"
class="input"
/>
</div>
</div>
<div class="flex justify-end">
<button
type="button"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-remove="text-track"
>
Remove track
</button>
</div>
</article>
</template>
</section>
<section class="space-y-4" aria-labelledby="editNip71SegmentsLabel" data-nip71-repeater="segment">
<div class="flex items-center justify-between">
<h3 id="editNip71SegmentsLabel" class="text-sm font-medium text-text">Chapters &amp; segments (segment)</h3>
<button
type="button"
class="btn-ghost focus-ring text-xs font-semibold"
data-nip71-add="segment"
aria-describedby="editNip71SegmentsHelp"
>
Add segment
</button>
</div>
<p id="editNip71SegmentsHelp" class="text-xs text-muted">
Outline chapters with start and end times, titles, and optional thumbnails.
</p>
<div id="editNip71SegmentList" class="space-y-4" data-nip71-list="segment"></div>
<template id="editNip71SegmentTemplate" data-nip71-template="segment">
<article class="card space-y-3 bg-surface/60 p-4" data-nip71-entry="segment">
<div class="grid gap-3 md:grid-cols-2">
<div class="space-y-2">
<label class="block text-xs font-medium text-muted-strong">Start (seconds)</label>
<input
type="number"
data-nip71-field="start"
min="0"
step="1"
class="input"
/>
</div>
<div class="space-y-2">
<label class="block text-xs font-medium text-muted-strong">End (seconds)</label>
<input
type="number"
data-nip71-field="end"
min="0"
step="1"
class="input"
/>
</div>
<div class="space-y-2">
<label class="block text-xs font-medium text-muted-strong">Title</label>
<input
type="text"
data-nip71-field="title"
placeholder="Chapter title"
class="input"
/>
</div>
<div class="space-y-2">
<label class="block text-xs font-medium text-muted-strong">Thumbnail URL</label>
<input
type="url"
data-nip71-field="thumbnail"
placeholder="https://cdn.example.com/frame.jpg"
class="input"
/>
</div>
</div>
<div class="flex justify-end">
<button
type="button"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-remove="segment"
>
Remove segment
</button>
</div>
</article>
</template>
</section>
<section class="space-y-4" aria-labelledby="editNip71HashtagsLabel" data-nip71-repeater="t">
<div class="flex items-center justify-between">
<h3 id="editNip71HashtagsLabel" class="text-sm font-medium text-text">Hashtags (<code>t</code>)</h3>
<button
type="button"
class="btn-ghost focus-ring text-xs font-semibold"
data-nip71-add="t"
>
Add hashtag
</button>
</div>
<p class="text-xs text-muted">
Enter keywords; leading <code>#</code> characters are stripped automatically when saving.
</p>
<div id="editNip71HashtagList" class="space-y-2" data-nip71-list="t"></div>
<template id="editNip71HashtagTemplate" data-nip71-template="t">
<div class="flex items-center gap-2" data-nip71-entry="t">
<input
type="text"
data-nip71-field="value"
placeholder="#nostr"
class="flex-1 input"
/>
<button
type="button"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-remove="t"
>
Remove
</button>
</div>
</template>
</section>
<section class="space-y-4" aria-labelledby="editNip71ParticipantsLabel" data-nip71-repeater="p">
<div class="flex items-center justify-between">
<h3 id="editNip71ParticipantsLabel" class="text-sm font-medium text-text">Participants (<code>p</code>)</h3>
<button
type="button"
class="btn-ghost focus-ring text-xs font-semibold"
data-nip71-add="p"
>
Add participant
</button>
</div>
<div id="editNip71ParticipantList" class="space-y-3" data-nip71-list="p"></div>
<template id="editNip71ParticipantTemplate" data-nip71-template="p">
<article class="card space-y-3 bg-surface/60 p-4" data-nip71-entry="p">
<div class="grid gap-3 md:grid-cols-2">
<div class="space-y-2">
<label class="block text-xs font-medium text-muted-strong">Participant pubkey</label>
<input
type="text"
data-nip71-field="pubkey"
placeholder="npub1... or hex"
class="input"
/>
</div>
<div class="space-y-2">
<label class="block text-xs font-medium text-muted-strong">Relay hint</label>
<input
type="text"
data-nip71-field="relay"
placeholder="wss://relay.example.com"
class="input"
/>
</div>
</div>
<div class="flex justify-end">
<button
type="button"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-remove="p"
>
Remove participant
</button>
</div>
</article>
</template>
</section>
<section class="space-y-4" aria-labelledby="editNip71ReferencesLabel" data-nip71-repeater="r">
<div class="flex items-center justify-between">
<h3 id="editNip71ReferencesLabel" class="text-sm font-medium text-text">Reference links (<code>r</code>)</h3>
<button
type="button"
class="btn-ghost focus-ring text-xs font-semibold"
data-nip71-add="r"
>
Add reference
</button>
</div>
<div id="editNip71ReferenceList" class="space-y-2" data-nip71-list="r"></div>
<template id="editNip71ReferenceTemplate" data-nip71-template="r">
<div class="flex items-center gap-2" data-nip71-entry="r">
<input
type="url"
data-nip71-field="url"
placeholder="https://example.com/context"
class="flex-1 input"
/>
<button
type="button"
class="btn-ghost focus-ring text-3xs font-medium"
data-nip71-remove="r"
>
Remove
</button>
</div>
</template>
</section>
</fieldset>
<div class="space-y-1">
<label for="editVideoUrl" class="block text-sm font-medium text-text">
Hosted video URL (https)
</label>
<div class="flex flex-col gap-2 sm:flex-row">
<input
type="url"
id="editVideoUrl"
class="flex-1 input"
placeholder="https://cdn.example.com/video.mp4"
/>
<button
type="button"
class="btn-ghost focus-ring hidden text-xs font-semibold uppercase tracking-wide"
data-edit-target="editVideoUrl"
>
Edit field
</button>
</div>
</div>
<div class="space-y-1">
<label for="editVideoWs" class="block text-sm font-medium text-text">
Web seeds (ws=, one per line)
</label>
<div class="flex flex-col gap-2 sm:flex-row">
<textarea
id="editVideoWs"
rows="2"
class="flex-1 textarea"
placeholder="https://cdn.example.com/video.mp4&#10;https://backup.example.com/video.mp4"
></textarea>
<button
type="button"
class="btn-ghost focus-ring hidden text-xs font-semibold uppercase tracking-wide"
data-edit-target="editVideoWs"
>
Edit field
</button>
</div>
<p class="text-xs text-muted">
Add a backup origin so the swarm keeps streaming if the primary is
overloaded. Each must serve the exact same file.
</p>
</div>
<div class="space-y-1">
<label for="editVideoXs" class="block text-sm font-medium text-text">
.torrent URL (xs=)
</label>
<div class="flex flex-col gap-2 sm:flex-row">
<input
type="url"
id="editVideoXs"
class="flex-1 input"
placeholder="https://cdn.example.com/video.torrent"
/>
<button
type="button"
class="btn-ghost focus-ring hidden text-xs font-semibold uppercase tracking-wide"
data-edit-target="editVideoXs"
>
Edit field
</button>
</div>
</div>
<div class="space-y-1">
<label for="editVideoMagnet" class="block text-sm font-medium text-text">
Magnet link
</label>
<div class="flex flex-col gap-2 sm:flex-row">
<input
type="text"
id="editVideoMagnet"
class="flex-1 input"
placeholder="magnet:?xt=urn:btih:..."
/>
<button
type="button"
class="btn-ghost focus-ring hidden text-xs font-semibold uppercase tracking-wide"
data-edit-target="editVideoMagnet"
>
Edit field
</button>
</div>
</div>
<div class="space-y-1">
<label for="editVideoThumbnail" class="block text-sm font-medium text-text">
Thumbnail URL
</label>
<div class="flex flex-col gap-2 sm:flex-row">
<input
type="url"
id="editVideoThumbnail"
class="flex-1 input"
placeholder="https://cdn.example.com/preview.jpg"
/>
<button
type="button"
class="btn-ghost focus-ring hidden text-xs font-semibold uppercase tracking-wide"
data-edit-target="editVideoThumbnail"
>
Edit field
</button>
</div>
</div>
<div class="space-y-1">
<label for="editVideoDescription" class="block text-sm font-medium text-text">
Description
</label>
<div class="flex flex-col gap-2">
<textarea
id="editVideoDescription"
rows="4"
class="textarea"
placeholder="What is this video about?"
></textarea>
<button
type="button"
class="btn-ghost focus-ring hidden self-start text-xs font-semibold uppercase tracking-wide"
data-edit-target="editVideoDescription"
>
Edit field
</button>
</div>
</div>
<div class="space-y-1">
<span id="editVideoVisibilityLabel" class="block text-sm font-medium text-text">
Visibility
</span>
<div
class="space-y-3 rounded-md border border-border/70 bg-overlay-black/30 p-3"
role="group"
aria-labelledby="editVideoVisibilityLabel"
data-visibility-toggle
>
<div class="flex flex-wrap items-center gap-2 sm:justify-between">
<div
class="video-visibility-toggle"
data-visibility-options
>
<button
type="button"
class="video-visibility-toggle__option focus-ring"
data-visibility-option="public"
aria-pressed="false"
>
Public
</button>
<button
type="button"
class="video-visibility-toggle__option focus-ring"
data-visibility-option="private"
aria-pressed="false"
>
Private
</button>
</div>
<input
type="checkbox"
id="editVideoIsPrivate"
class="hidden"
data-default-checked="false"
aria-hidden="true"
/>
</div>
<p class="text-xs text-muted" data-visibility-helper>
Private notes stay visible only to you. Switch back to public when you're ready to share.
</p>
<button
type="button"
class="btn-ghost focus-ring hidden text-xs font-semibold uppercase tracking-wide"
data-edit-target="editVideoIsPrivate"
>
Edit field
</button>
</div>
</div>
<div class="space-y-2">
<label
for="editVideoIsNsfw"
id="editVideoIsNsfwLabel"
class="block text-sm font-medium text-text"
>
NSFW content
</label>
<div
class="form-control"
role="group"
aria-labelledby="editVideoIsNsfwLabel"
>
<label class="menu__item gap-3 px-0 py-0 text-left" for="editVideoIsNsfw">
<input
type="checkbox"
id="editVideoIsNsfw"
class="checkbox"
data-default-checked="false"
/>
<span class="text-sm text-muted-strong">
Mark as sensitive to blur previews and gate playback.
</span>
</label>
</div>
<div class="flex justify-end">
<button
type="button"
class="btn-ghost focus-ring hidden text-xs font-semibold uppercase tracking-wide"
data-edit-target="editVideoIsNsfw"
>
Edit field
</button>
</div>
</div>
<div class="space-y-2">
<label
for="editVideoIsForKids"
id="editVideoIsForKidsLabel"
class="block text-sm font-medium text-text"
>
Made for kids
</label>
<div
class="form-control"
role="group"
aria-labelledby="editVideoIsForKidsLabel"
>
<label class="menu__item gap-3 px-0 py-0 text-left" for="editVideoIsForKids">
<input
type="checkbox"
id="editVideoIsForKids"
class="checkbox"
data-default-checked="false"
/>
<span class="text-sm text-muted-strong">
Flag kid-friendly videos to adjust recommendations and controls.
</span>
</label>
</div>
<div class="flex justify-end">
<button
type="button"
class="btn-ghost focus-ring hidden text-xs font-semibold uppercase tracking-wide"
data-edit-target="editVideoIsForKids"
>
Edit field
</button>
</div>
</div>
<div class="space-y-2">
<label
for="editEnableComments"
id="editEnableCommentsLabel"
class="block text-sm font-medium text-text"
>
Enable comments
</label>
<div
class="form-control"
role="group"
aria-labelledby="editEnableCommentsLabel"
>
<label class="menu__item gap-3 px-0 py-0 text-left" for="editEnableComments">
<input
type="checkbox"
id="editEnableComments"
class="checkbox"
data-default-checked="true"
checked
/>
<span class="text-sm text-muted-strong">
Allow replies once comment threads are available.
</span>
</label>
</div>
<div class="flex justify-end">
<button
type="button"
class="btn-ghost focus-ring hidden text-xs font-semibold uppercase tracking-wide"
data-edit-target="editEnableComments"
>
Edit field
</button>
</div>
</div>
<div class="flex flex-col gap-3 sm:flex-row sm:justify-end">
<button
type="button"
id="cancelEditVideo"
class="btn-ghost focus-ring w-full sm:w-auto"
>
Cancel
</button>
<button
type="submit"
id="submitEditVideo"
class="btn focus-ring w-full sm:w-auto"
>
Save changes
</button>
</div>
</form>
</div>
</div>
</div>