{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "media-player",
  "type": "registry:ui",
  "title": "Media Player",
  "description": "A styled native <video controls> / <audio controls> with multiple <source> formats, <track> captions, a poster, and aspect-ratio framing. The browser ships the entire accessible playback UI — play, scrub, volume, captions, fullscreen, Picture-in-Picture — so there are no custom controls and zero JavaScript.",
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/ui/media-player.tsx",
      "type": "registry:ui",
      "target": "components/ui/media-player.tsx",
      "content": "/** @jsxImportSource hono/jsx */\nimport type { Child } from \"hono/jsx\"\nimport { cn, type ClassValue } from \"@/registry/lib/cn\"\n\n// Media Player — shadcn-htmx, htmx v4 + Tailwind v4.\n//\n// A styled native <video controls> / <audio controls>. The browser ships a\n// complete, accessible playback UI — play/pause, scrubber, volume, captions\n// toggle, fullscreen, Picture-in-Picture — so we render the real platform\n// element and only frame it (rounded card, aspect-ratio, poster). No custom\n// controls, no JavaScript: the platform already does playback, and we never\n// emulate a feature the browser ships (see AGENTS.md rule 4).\n//\n// Multiple <source> children let the browser pick the first format it can\n// decode (webm → mp4 fallback, etc.); <track kind=\"captions\"> overlays\n// WebVTT subtitles/captions the native UI can toggle.\n//\n// Built on:\n//   - <video> — embeds a media player with native controls (play, seek,\n//     volume, fullscreen, PiP). `controls`, `poster`, `preload`, `loop`,\n//     `muted`, `playsinline`, `crossorigin`, `width`/`height`.\n//       repos/mdn/files/en-us/web/html/reference/elements/video/index.md\n//   - <audio> — same playback API without a visual frame; the native\n//     control bar is the whole UI.\n//       repos/mdn/files/en-us/web/html/reference/elements/audio/index.md\n//   - <source> — one media resource per format; the browser uses the first\n//     it can play. `src` + `type` (MIME, optionally with codecs).\n//       repos/mdn/files/en-us/web/html/reference/elements/source/index.md\n//   - <track> — timed WebVTT text track (captions/subtitles/descriptions/\n//     chapters). `kind`, `src`, `srclang`, `label`, `default`.\n//       repos/mdn/files/en-us/web/html/reference/elements/track/index.md\n//\n// CSS framing reuses the aspect-ratio approach (native `aspect-ratio`, no\n// padding hack):\n//   repos/mdn/files/en-us/web/css/reference/properties/aspect-ratio/index.md\n//\n// Accessibility:\n//   - Native controls are keyboard-operable and labelled by the user agent.\n//   - Provide a <track kind=\"captions\"> for spoken content (WCAG 1.2.2).\n//   - When no caption track exists, pass `ariaLabel` so AT announces what\n//     the player plays. The text inside the element is the no-support\n//     fallback shown to browsers that can't render <video>/<audio>.\n\nexport type MediaSource = {\n  // URL of the media resource.\n  src: string\n  // MIME type, optionally with a codecs parameter, e.g. 'video/webm',\n  // 'video/mp4; codecs=\"avc1.42E01E\"'. Lets the browser skip formats it\n  // can't decode without downloading them.\n  type?: string\n}\n\nexport type MediaTrackKind =\n  | \"captions\"\n  | \"subtitles\"\n  | \"descriptions\"\n  | \"chapters\"\n  | \"metadata\"\n\nexport type MediaTrack = {\n  // Address of the .vtt WebVTT file (same-origin unless the player carries a\n  // crossorigin attribute).\n  src: string\n  // How the timed text is used. Defaults to \"subtitles\" per the spec.\n  kind?: MediaTrackKind\n  // BCP 47 language tag, required when kind is \"subtitles\".\n  srclang?: string\n  // Human-readable name shown in the native captions menu.\n  label?: string\n  // Enable this track by default (at most one per media element).\n  default?: boolean\n}\n\nexport type MediaPlayerKind = \"video\" | \"audio\"\n\nconst root =\n  \"group/media-player relative block w-full overflow-hidden rounded-lg border bg-card\"\n\n// The media element itself. For video we stretch it to the framed box and\n// letterbox with object-contain (cover would crop the picture); audio is a\n// full-width native control bar.\nconst mediaClasses: Record<MediaPlayerKind, string> = {\n  video: \"block size-full bg-black object-contain\",\n  audio: \"block w-full\",\n}\n\n// Turn a \"w/h\" ratio string or number into a Tailwind aspect utility,\n// mirroring registry/ui/aspect-ratio.tsx so the two components frame media\n// identically.\nconst NAMED_RATIO: Record<string, string> = {\n  \"1/1\": \"aspect-square\",\n  \"16/9\": \"aspect-video\",\n}\n\nfunction ratioClass(ratio: number | string): string {\n  if (typeof ratio === \"number\") return `aspect-[${ratio}]`\n  const key = ratio.replace(/\\s+/g, \"\")\n  return NAMED_RATIO[key] ?? `aspect-[${key}]`\n}\n\ntype MediaPlayerProps = {\n  // \"video\" (default) frames a <video> in an aspect-ratio box; \"audio\"\n  // renders a full-width <audio> control bar.\n  kind?: MediaPlayerKind\n  // Single source shortcut. For multiple formats pass `sources` instead.\n  src?: string\n  // Multiple encodings, tried in order until one plays.\n  sources?: MediaSource[]\n  // Caption / subtitle tracks (WebVTT).\n  tracks?: MediaTrack[]\n  // Video only: image shown before the first frame is available.\n  poster?: string\n  // Width-to-height frame ratio for video (ignored for audio). A number\n  // (1.778) or a \"w/h\" string (\"16/9\", \"4/3\"). Defaults to 16:9.\n  ratio?: number | string\n  // Native playback hints / flags.\n  controls?: boolean\n  preload?: \"none\" | \"metadata\" | \"auto\"\n  loop?: boolean\n  muted?: boolean\n  autoplay?: boolean\n  // Video only: play inline rather than forcing fullscreen on mobile.\n  playsinline?: boolean\n  // CORS mode for cross-origin media (needed for cross-origin tracks).\n  crossorigin?: \"anonymous\" | \"use-credentials\"\n  // Accessible name when there is no caption track to identify the media.\n  ariaLabel?: string\n  class?: ClassValue\n  id?: string\n  // No-support fallback content (links to download the media, etc.). Also\n  // receives <source>/<track> if you'd rather pass them as children than via\n  // the `sources` / `tracks` props.\n  children?: Child\n  // Forward hx-*, data-*, aria-*, and standard attributes onto the root.\n  [key: string]: unknown\n}\n\nexport function MediaPlayer(props: MediaPlayerProps) {\n  const {\n    kind = \"video\",\n    src,\n    sources,\n    tracks,\n    poster,\n    ratio = \"16/9\",\n    controls = true,\n    preload,\n    loop,\n    muted,\n    autoplay,\n    playsinline,\n    crossorigin,\n    ariaLabel,\n    class: className,\n    id,\n    children,\n    ...rest\n  } = props\n\n  const isVideo = kind === \"video\"\n\n  const sourceEls = (sources ?? []).map((s) => (\n    <source data-slot=\"media-player-source\" src={s.src} type={s.type} />\n  ))\n\n  const trackEls = (tracks ?? []).map((t) => (\n    <track\n      data-slot=\"media-player-track\"\n      kind={t.kind ?? \"subtitles\"}\n      src={t.src}\n      srclang={t.srclang}\n      label={t.label}\n      default={t.default}\n    />\n  ))\n\n  const common = {\n    \"data-slot\": \"media-player-media\",\n    src,\n    controls: controls ? true : undefined,\n    preload,\n    loop: loop ? true : undefined,\n    muted: muted ? true : undefined,\n    autoplay: autoplay ? true : undefined,\n    crossorigin,\n    \"aria-label\": ariaLabel,\n  }\n\n  const media = isVideo ? (\n    <video\n      {...common}\n      poster={poster}\n      playsinline={playsinline ? true : undefined}\n      class={mediaClasses.video}\n    >\n      {sourceEls}\n      {trackEls}\n      {children}\n    </video>\n  ) : (\n    <audio {...common} class={mediaClasses.audio}>\n      {sourceEls}\n      {trackEls}\n      {children}\n    </audio>\n  )\n\n  return (\n    <div\n      id={id}\n      data-slot=\"media-player\"\n      data-kind={kind}\n      class={cn(root, isVideo && ratioClass(ratio), !isVideo && \"p-2\", className)}\n      {...rest}\n    >\n      {media}\n    </div>\n  )\n}\n"
    },
    {
      "path": "registry/jinja2/media-player.html",
      "type": "registry:file",
      "target": "templates/components/media-player.html",
      "content": "{# Media Player macro — shadcn-htmx, htmx v4 + Tailwind v4.\n   Mirrors registry/ui/media-player.tsx.\n\n   A styled native <video controls> / <audio controls>. The browser ships\n   the full accessible playback UI (play, seek, volume, captions, fullscreen,\n   PiP); we only frame it. Zero JS — we never emulate platform features.\n     MDN <video>:  repos/mdn/files/en-us/web/html/reference/elements/video/index.md\n     MDN <audio>:  repos/mdn/files/en-us/web/html/reference/elements/audio/index.md\n     MDN <source>: repos/mdn/files/en-us/web/html/reference/elements/source/index.md\n     MDN <track>:  repos/mdn/files/en-us/web/html/reference/elements/track/index.md\n\n   `sources` is a list of {src, type} dicts; `tracks` a list of\n   {src, kind, srclang, label, default} dicts. The slotted {{ caller() }} is\n   the no-support fallback (download links, etc.).\n\n   Usage:\n     {% from \"components/media-player.html\" import media_player %}\n     {% call media_player(\n          sources=[{\"src\": \"/clip.webm\", \"type\": \"video/webm\"},\n                   {\"src\": \"/clip.mp4\",  \"type\": \"video/mp4\"}],\n          tracks=[{\"src\": \"/clip.en.vtt\", \"kind\": \"captions\",\n                   \"srclang\": \"en\", \"label\": \"English\", \"default\": True}],\n          poster=\"/poster.jpg\") %}\n       <a href=\"/clip.mp4\">Download the video</a>\n     {% endcall %} #}\n\n{% macro media_player(kind=\"video\", src=none, sources=[], tracks=[], poster=none, ratio=\"16/9\", controls=true, preload=none, loop=false, muted=false, autoplay=false, playsinline=false, crossorigin=none, aria_label=none, id=none, extra_class=\"\", **attrs) %}\n{%- set is_video = kind == \"video\" -%}\n{%- set ratio_class -%}\n{%- if ratio == \"1/1\" -%}aspect-square{%- elif ratio == \"16/9\" -%}aspect-video{%- else -%}aspect-[{{ ratio | replace(' ', '') }}]{%- endif -%}\n{%- endset -%}\n<div\n  {%- if id %} id=\"{{ id }}\"{% endif %}\n  data-slot=\"media-player\"\n  data-kind=\"{{ kind }}\"\n  class=\"group/media-player relative block w-full overflow-hidden rounded-lg border bg-card {% if is_video %}{{ ratio_class }}{% else %}p-2{% endif %} {{ extra_class }}\"\n  {%- for k, v in attrs.items() %} {{ k|replace('_','-') }}=\"{{ v }}\"{% endfor %}>\n  {%- if is_video %}\n  <video data-slot=\"media-player-media\"\n         {%- if src %} src=\"{{ src }}\"{% endif %}\n         {%- if controls %} controls{% endif %}\n         {%- if poster %} poster=\"{{ poster }}\"{% endif %}\n         {%- if preload %} preload=\"{{ preload }}\"{% endif %}\n         {%- if loop %} loop{% endif %}\n         {%- if muted %} muted{% endif %}\n         {%- if autoplay %} autoplay{% endif %}\n         {%- if playsinline %} playsinline{% endif %}\n         {%- if crossorigin %} crossorigin=\"{{ crossorigin }}\"{% endif %}\n         {%- if aria_label %} aria-label=\"{{ aria_label }}\"{% endif %}\n         class=\"block size-full bg-black object-contain\">\n    {%- for s in sources %}\n    <source data-slot=\"media-player-source\" src=\"{{ s.src }}\"{% if s.type %} type=\"{{ s.type }}\"{% endif %}>\n    {%- endfor %}\n    {%- for t in tracks %}\n    <track data-slot=\"media-player-track\" kind=\"{{ t.kind | default('subtitles') }}\" src=\"{{ t.src }}\"{% if t.srclang %} srclang=\"{{ t.srclang }}\"{% endif %}{% if t.label %} label=\"{{ t.label }}\"{% endif %}{% if t.default %} default{% endif %}>\n    {%- endfor %}\n    {{ caller() }}\n  </video>\n  {%- else %}\n  <audio data-slot=\"media-player-media\"\n         {%- if src %} src=\"{{ src }}\"{% endif %}\n         {%- if controls %} controls{% endif %}\n         {%- if preload %} preload=\"{{ preload }}\"{% endif %}\n         {%- if loop %} loop{% endif %}\n         {%- if muted %} muted{% endif %}\n         {%- if autoplay %} autoplay{% endif %}\n         {%- if crossorigin %} crossorigin=\"{{ crossorigin }}\"{% endif %}\n         {%- if aria_label %} aria-label=\"{{ aria_label }}\"{% endif %}\n         class=\"block w-full\">\n    {%- for s in sources %}\n    <source data-slot=\"media-player-source\" src=\"{{ s.src }}\"{% if s.type %} type=\"{{ s.type }}\"{% endif %}>\n    {%- endfor %}\n    {%- for t in tracks %}\n    <track data-slot=\"media-player-track\" kind=\"{{ t.kind | default('subtitles') }}\" src=\"{{ t.src }}\"{% if t.srclang %} srclang=\"{{ t.srclang }}\"{% endif %}{% if t.label %} label=\"{{ t.label }}\"{% endif %}{% if t.default %} default{% endif %}>\n    {%- endfor %}\n    {{ caller() }}\n  </audio>\n  {%- endif %}\n</div>\n{% endmacro %}\n"
    },
    {
      "path": "registry/go-templates/media-player.tmpl",
      "type": "registry:file",
      "target": "components/media-player.tmpl",
      "content": "{{/*\n  Media Player template — shadcn-htmx, htmx v4 + Tailwind v4.\n  Mirrors registry/ui/media-player.tsx.\n\n  A styled native <video controls> / <audio controls>. The browser ships the\n  full accessible playback UI (play, seek, volume, captions, fullscreen, PiP);\n  we only frame it. Zero JS — we never emulate platform features.\n    MDN <video>:  repos/mdn/files/en-us/web/html/reference/elements/video/index.md\n    MDN <audio>:  repos/mdn/files/en-us/web/html/reference/elements/audio/index.md\n    MDN <source>: repos/mdn/files/en-us/web/html/reference/elements/source/index.md\n    MDN <track>:  repos/mdn/files/en-us/web/html/reference/elements/track/index.md\n\n      type MediaSource struct { Src, Type string }\n      type MediaTrack  struct { Src, Kind, Srclang, Label string; Default bool }\n      type MediaPlayerArgs struct {\n          Kind        string        // \"video\" (default) | \"audio\"\n          Src         string        // single-source shortcut\n          Sources     []MediaSource\n          Tracks      []MediaTrack\n          Poster      string        // video only\n          Ratio       string        // \"16/9\" (default) | \"1/1\" | \"4/3\" | …\n          Controls    bool          // default true (pass explicitly)\n          Preload     string        // none | metadata | auto\n          Loop        bool\n          Muted       bool\n          Autoplay    bool\n          Playsinline bool          // video only\n          Crossorigin string        // anonymous | use-credentials\n          AriaLabel   string\n          ID          string\n          Class       string\n          Body        template.HTML // no-support fallback (download links)\n      }\n*/}}\n\n{{define \"media-player\"}}\n{{- $kind := or .Kind \"video\" -}}\n{{- $isVideo := eq $kind \"video\" -}}\n{{- $ratio := or .Ratio \"16/9\" -}}\n{{- $ratioClass := printf \"aspect-[%s]\" $ratio -}}\n{{- if eq $ratio \"1/1\" -}}{{- $ratioClass = \"aspect-square\" -}}{{- else if eq $ratio \"16/9\" -}}{{- $ratioClass = \"aspect-video\" -}}{{- end -}}\n<div {{if .ID}}id=\"{{.ID}}\" {{end}}data-slot=\"media-player\" data-kind=\"{{$kind}}\" class=\"group/media-player relative block w-full overflow-hidden rounded-lg border bg-card {{if $isVideo}}{{$ratioClass}}{{else}}p-2{{end}} {{.Class}}\">\n  {{- if $isVideo}}\n  <video data-slot=\"media-player-media\"{{if .Src}} src=\"{{.Src}}\"{{end}}{{if .Controls}} controls{{end}}{{if .Poster}} poster=\"{{.Poster}}\"{{end}}{{if .Preload}} preload=\"{{.Preload}}\"{{end}}{{if .Loop}} loop{{end}}{{if .Muted}} muted{{end}}{{if .Autoplay}} autoplay{{end}}{{if .Playsinline}} playsinline{{end}}{{if .Crossorigin}} crossorigin=\"{{.Crossorigin}}\"{{end}}{{if .AriaLabel}} aria-label=\"{{.AriaLabel}}\"{{end}} class=\"block size-full bg-black object-contain\">\n    {{- range .Sources}}\n    <source data-slot=\"media-player-source\" src=\"{{.Src}}\"{{if .Type}} type=\"{{.Type}}\"{{end}}>\n    {{- end}}\n    {{- range .Tracks}}\n    <track data-slot=\"media-player-track\" kind=\"{{or .Kind \"subtitles\"}}\" src=\"{{.Src}}\"{{if .Srclang}} srclang=\"{{.Srclang}}\"{{end}}{{if .Label}} label=\"{{.Label}}\"{{end}}{{if .Default}} default{{end}}>\n    {{- end}}\n    {{htmlSafe .Body}}\n  </video>\n  {{- else}}\n  <audio data-slot=\"media-player-media\"{{if .Src}} src=\"{{.Src}}\"{{end}}{{if .Controls}} controls{{end}}{{if .Preload}} preload=\"{{.Preload}}\"{{end}}{{if .Loop}} loop{{end}}{{if .Muted}} muted{{end}}{{if .Autoplay}} autoplay{{end}}{{if .Crossorigin}} crossorigin=\"{{.Crossorigin}}\"{{end}}{{if .AriaLabel}} aria-label=\"{{.AriaLabel}}\"{{end}} class=\"block w-full\">\n    {{- range .Sources}}\n    <source data-slot=\"media-player-source\" src=\"{{.Src}}\"{{if .Type}} type=\"{{.Type}}\"{{end}}>\n    {{- end}}\n    {{- range .Tracks}}\n    <track data-slot=\"media-player-track\" kind=\"{{or .Kind \"subtitles\"}}\" src=\"{{.Src}}\"{{if .Srclang}} srclang=\"{{.Srclang}}\"{{end}}{{if .Label}} label=\"{{.Label}}\"{{end}}{{if .Default}} default{{end}}>\n    {{- end}}\n    {{htmlSafe .Body}}\n  </audio>\n  {{- end}}\n</div>\n{{end}}\n"
    },
    {
      "path": "registry/phoenix/media_player.ex",
      "type": "registry:file",
      "target": "lib/my_app_web/components/media_player.ex",
      "content": "defmodule ShadcnHtmx.Components.MediaPlayer do\n  @moduledoc \"\"\"\n  Media Player — shadcn-htmx, htmx v4 + Tailwind v4 for Phoenix.\n\n  Mirrors registry/ui/media-player.tsx.\n\n  A styled native `<video controls>` / `<audio controls>`. The browser ships\n  the full accessible playback UI — play/pause, scrubber, volume, captions\n  toggle, fullscreen, Picture-in-Picture — so we render the real platform\n  element and only frame it (rounded card, aspect-ratio, poster). No custom\n  controls, no JavaScript: we never emulate a feature the browser ships.\n\n    * MDN <video>:\n      repos/mdn/files/en-us/web/html/reference/elements/video/index.md\n    * MDN <audio>:\n      repos/mdn/files/en-us/web/html/reference/elements/audio/index.md\n    * MDN <source>:\n      repos/mdn/files/en-us/web/html/reference/elements/source/index.md\n    * MDN <track>:\n      repos/mdn/files/en-us/web/html/reference/elements/track/index.md\n\n  `:source` slots are <source> rows ({src, type}); `:track` slots are\n  WebVTT <track> rows ({src, kind, srclang, label, default}). The inner block\n  is the no-support fallback (download links).\n\n  ## Examples\n\n      <.media_player poster=\"/poster.jpg\">\n        <:source src=\"/clip.webm\" type=\"video/webm\" />\n        <:source src=\"/clip.mp4\" type=\"video/mp4\" />\n        <:track src=\"/clip.en.vtt\" kind=\"captions\" srclang=\"en\" label=\"English\" default />\n        <a href=\"/clip.mp4\">Download the video</a>\n      </.media_player>\n\n      <.media_player kind=\"audio\">\n        <:source src=\"/song.mp3\" type=\"audio/mpeg\" />\n      </.media_player>\n  \"\"\"\n\n  use Phoenix.Component\n\n  @root \"group/media-player relative block w-full overflow-hidden rounded-lg border bg-card\"\n\n  attr :kind, :string, default: \"video\", values: ~w(video audio)\n  attr :src, :string, default: nil\n  attr :poster, :string, default: nil\n  attr :ratio, :string, default: \"16/9\"\n  attr :controls, :boolean, default: true\n  attr :preload, :string, default: nil\n  attr :loop, :boolean, default: false\n  attr :muted, :boolean, default: false\n  attr :autoplay, :boolean, default: false\n  attr :playsinline, :boolean, default: false\n  attr :crossorigin, :string, default: nil\n  attr :aria_label, :string, default: nil\n  attr :class, :string, default: nil\n  attr :rest, :global\n\n  slot :source do\n    attr :src, :string, required: true\n    attr :type, :string\n  end\n\n  slot :track do\n    attr :src, :string, required: true\n    attr :kind, :string\n    attr :srclang, :string\n    attr :label, :string\n    attr :default, :boolean\n  end\n\n  slot :inner_block\n\n  def media_player(assigns) do\n    assigns =\n      assigns\n      |> assign(:root, @root)\n      |> assign(:is_video, assigns.kind == \"video\")\n      |> assign(:ratio_class, ratio_class(assigns.ratio))\n\n    ~H\"\"\"\n    <div\n      data-slot=\"media-player\"\n      data-kind={@kind}\n      class={[\n        @root,\n        @is_video && @ratio_class,\n        !@is_video && \"p-2\",\n        @class\n      ]}\n      {@rest}\n    >\n      <video\n        :if={@is_video}\n        data-slot=\"media-player-media\"\n        src={@src}\n        controls={@controls}\n        poster={@poster}\n        preload={@preload}\n        loop={@loop}\n        muted={@muted}\n        autoplay={@autoplay}\n        playsinline={@playsinline}\n        crossorigin={@crossorigin}\n        aria-label={@aria_label}\n        class=\"block size-full bg-black object-contain\"\n      >\n        <source\n          :for={s <- @source}\n          data-slot=\"media-player-source\"\n          src={s.src}\n          type={Map.get(s, :type)}\n        />\n        <track\n          :for={t <- @track}\n          data-slot=\"media-player-track\"\n          kind={Map.get(t, :kind, \"subtitles\")}\n          src={t.src}\n          srclang={Map.get(t, :srclang)}\n          label={Map.get(t, :label)}\n          default={Map.get(t, :default, false)}\n        />\n        {render_slot(@inner_block)}\n      </video>\n      <audio\n        :if={!@is_video}\n        data-slot=\"media-player-media\"\n        src={@src}\n        controls={@controls}\n        preload={@preload}\n        loop={@loop}\n        muted={@muted}\n        autoplay={@autoplay}\n        crossorigin={@crossorigin}\n        aria-label={@aria_label}\n        class=\"block w-full\"\n      >\n        <source\n          :for={s <- @source}\n          data-slot=\"media-player-source\"\n          src={s.src}\n          type={Map.get(s, :type)}\n        />\n        <track\n          :for={t <- @track}\n          data-slot=\"media-player-track\"\n          kind={Map.get(t, :kind, \"subtitles\")}\n          src={t.src}\n          srclang={Map.get(t, :srclang)}\n          label={Map.get(t, :label)}\n          default={Map.get(t, :default, false)}\n        />\n        {render_slot(@inner_block)}\n      </audio>\n    </div>\n    \"\"\"\n  end\n\n  defp ratio_class(\"1/1\"), do: \"aspect-square\"\n  defp ratio_class(\"16/9\"), do: \"aspect-video\"\n  defp ratio_class(ratio), do: \"aspect-[#{String.replace(ratio, \" \", \"\")}]\"\nend\n"
    },
    {
      "path": "registry/html/media-player.html",
      "type": "registry:file",
      "target": "snippets/media-player.html",
      "content": "<!--\n  shadcn-htmx — raw HTML media-player snippets.\n\n  A styled native <video controls> / <audio controls>. The browser ships the\n  full accessible playback UI (play, seek, volume, captions, fullscreen, PiP);\n  we only frame it with a rounded card + native aspect-ratio. Zero JavaScript\n  — Tailwind theme tokens only, and we never emulate platform features.\n\n    MDN <video>:  repos/mdn/files/en-us/web/html/reference/elements/video/index.md\n    MDN <audio>:  repos/mdn/files/en-us/web/html/reference/elements/audio/index.md\n    MDN <source>: repos/mdn/files/en-us/web/html/reference/elements/source/index.md\n    MDN <track>:  repos/mdn/files/en-us/web/html/reference/elements/track/index.md\n\n  ROOT (video): group/media-player relative block w-full overflow-hidden\n                rounded-lg border bg-card  +  aspect utility (aspect-video, …)\n  ROOT (audio): same, swap the aspect utility for p-2\n  MEDIA:        video → block size-full bg-black object-contain\n                audio → block w-full\n-->\n\n<!-- Video, 16:9, multiple formats + English captions + poster -->\n<div data-slot=\"media-player\" data-kind=\"video\"\n     class=\"group/media-player relative block w-full overflow-hidden rounded-lg border bg-card aspect-video\">\n  <video data-slot=\"media-player-media\" controls preload=\"metadata\"\n         poster=\"/poster.jpg\" playsinline\n         class=\"block size-full bg-black object-contain\">\n    <source data-slot=\"media-player-source\" src=\"/clip.webm\" type=\"video/webm\">\n    <source data-slot=\"media-player-source\" src=\"/clip.mp4\" type=\"video/mp4\">\n    <track data-slot=\"media-player-track\" kind=\"captions\" src=\"/clip.en.vtt\"\n           srclang=\"en\" label=\"English\" default>\n    <!-- No-support fallback -->\n    Your browser does not support the video element.\n    <a href=\"/clip.mp4\">Download the MP4 video</a>.\n  </video>\n</div>\n\n<!-- Audio — native control bar is the whole UI -->\n<div data-slot=\"media-player\" data-kind=\"audio\"\n     class=\"group/media-player relative block w-full overflow-hidden rounded-lg border bg-card p-2\">\n  <audio data-slot=\"media-player-media\" controls preload=\"metadata\"\n         aria-label=\"Episode 12 — The Platform Strikes Back\"\n         class=\"block w-full\">\n    <source data-slot=\"media-player-source\" src=\"/episode-12.ogg\" type=\"audio/ogg\">\n    <source data-slot=\"media-player-source\" src=\"/episode-12.mp3\" type=\"audio/mpeg\">\n    Your browser does not support the audio element.\n    <a href=\"/episode-12.mp3\">Download the MP3</a>.\n  </audio>\n</div>\n"
    }
  ]
}
