@krizaka/ui 3.24.0 → 3.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/README.md +7 -0
  2. package/dist/account-menu.d.ts +163 -0
  3. package/dist/account-menu.js +211 -0
  4. package/dist/account-menu.js.map +1 -0
  5. package/dist/app-shell.js +4 -4
  6. package/dist/changelog-page.d.ts +13 -1
  7. package/dist/changelog-page.js +20 -0
  8. package/dist/changelog-page.js.map +1 -1
  9. package/dist/{chunk-CEJDH6SA.js → chunk-2PNLHZLT.js} +23 -3
  10. package/dist/chunk-2PNLHZLT.js.map +1 -0
  11. package/dist/chunk-C7LTF5CC.js +21 -0
  12. package/dist/chunk-C7LTF5CC.js.map +1 -0
  13. package/dist/{chunk-F7FVPPBB.js → chunk-LYOPPBMC.js} +2 -2
  14. package/dist/{chunk-AFY35UCB.js → chunk-P7GZR5CU.js} +3 -1
  15. package/dist/{chunk-AFY35UCB.js.map → chunk-P7GZR5CU.js.map} +1 -1
  16. package/dist/code-block.js +1 -1
  17. package/dist/cover-hero.d.ts +125 -0
  18. package/dist/cover-hero.js +82 -0
  19. package/dist/cover-hero.js.map +1 -0
  20. package/dist/data-table.js +2 -2
  21. package/dist/docs-nav.js +3 -16
  22. package/dist/docs-nav.js.map +1 -1
  23. package/dist/dropdown-menu.d.ts +12 -1
  24. package/dist/dropdown-menu.js +25 -2
  25. package/dist/dropdown-menu.js.map +1 -1
  26. package/dist/filter-bar.js +1 -1
  27. package/dist/genui.js +2 -2
  28. package/dist/media-gallery.d.ts +73 -0
  29. package/dist/media-gallery.js +42 -0
  30. package/dist/media-gallery.js.map +1 -0
  31. package/dist/opening-hours.d.ts +124 -0
  32. package/dist/opening-hours.js +48 -0
  33. package/dist/opening-hours.js.map +1 -0
  34. package/dist/rail-nav.js +1 -1
  35. package/dist/service-card.d.ts +168 -0
  36. package/dist/service-card.js +112 -0
  37. package/dist/service-card.js.map +1 -0
  38. package/dist/slot-picker.d.ts +119 -0
  39. package/dist/slot-picker.js +46 -0
  40. package/dist/slot-picker.js.map +1 -0
  41. package/dist/sticky-action.d.ts +12 -0
  42. package/dist/sticky-action.js +14 -0
  43. package/dist/sticky-action.js.map +1 -0
  44. package/package.json +106 -6
  45. package/registry/account-menu.json +280 -0
  46. package/registry/achievement.json +1 -1
  47. package/registry/action-bar.json +1 -1
  48. package/registry/activity-feed.json +3 -3
  49. package/registry/alert.json +1 -1
  50. package/registry/app-header.json +1 -1
  51. package/registry/app-shell.json +1 -1
  52. package/registry/argument-card.json +1 -1
  53. package/registry/audio-player.json +1 -1
  54. package/registry/auth-layout.json +1 -1
  55. package/registry/avatar.json +1 -1
  56. package/registry/badge.json +1 -1
  57. package/registry/button.json +1 -1
  58. package/registry/captcha.json +1 -1
  59. package/registry/card-grid.json +1 -1
  60. package/registry/card.json +3 -3
  61. package/registry/catalogue-page.json +1 -1
  62. package/registry/changelog-page.json +3 -3
  63. package/registry/chat.json +1 -1
  64. package/registry/checkbox.json +1 -1
  65. package/registry/chip-link.json +1 -1
  66. package/registry/chip.json +1 -1
  67. package/registry/choice-grid.json +1 -1
  68. package/registry/code-block.json +1 -1
  69. package/registry/combobox.json +1 -1
  70. package/registry/command.json +1 -1
  71. package/registry/comparison-table.json +1 -1
  72. package/registry/component-page.json +1 -1
  73. package/registry/confirm-button.json +1 -1
  74. package/registry/contact-page.json +1 -1
  75. package/registry/continue-prompt.json +1 -1
  76. package/registry/countdown.json +1 -1
  77. package/registry/cover-hero.json +246 -0
  78. package/registry/cta-panel.json +1 -1
  79. package/registry/dashboard-layout.json +1 -1
  80. package/registry/data-table.json +1 -1
  81. package/registry/date-picker.json +1 -1
  82. package/registry/decision-list.json +1 -1
  83. package/registry/description-list.json +1 -1
  84. package/registry/detail-layout.json +1 -1
  85. package/registry/dialog.json +1 -1
  86. package/registry/docs-article-page.json +1 -1
  87. package/registry/docs-hub-page.json +1 -1
  88. package/registry/docs-layout.json +1 -1
  89. package/registry/docs-nav.json +1 -1
  90. package/registry/document-viewer.json +1 -1
  91. package/registry/dropdown-menu.json +33 -3
  92. package/registry/empty-state.json +1 -1
  93. package/registry/error-page.json +1 -1
  94. package/registry/examples/account-menu/default.d.ts +4 -0
  95. package/registry/examples/account-menu/default.js +28 -0
  96. package/registry/examples/account-menu/default.tsx +22 -0
  97. package/registry/examples/cover-hero/plain.d.ts +4 -0
  98. package/registry/examples/cover-hero/plain.js +12 -0
  99. package/registry/examples/cover-hero/plain.tsx +7 -0
  100. package/registry/examples/cover-hero/shop.d.ts +4 -0
  101. package/registry/examples/cover-hero/shop.js +27 -0
  102. package/registry/examples/cover-hero/shop.tsx +20 -0
  103. package/registry/examples/media-gallery/shop.d.ts +4 -0
  104. package/registry/examples/media-gallery/shop.js +22 -0
  105. package/registry/examples/media-gallery/shop.tsx +18 -0
  106. package/registry/examples/opening-hours/week.d.ts +4 -0
  107. package/registry/examples/opening-hours/week.js +28 -0
  108. package/registry/examples/opening-hours/week.tsx +22 -0
  109. package/registry/examples/service-card/services.d.ts +4 -0
  110. package/registry/examples/service-card/services.js +15 -0
  111. package/registry/examples/service-card/services.tsx +12 -0
  112. package/registry/examples/slot-picker/times.d.ts +4 -0
  113. package/registry/examples/slot-picker/times.js +27 -0
  114. package/registry/examples/slot-picker/times.tsx +23 -0
  115. package/registry/examples/sticky-action/phone.d.ts +4 -0
  116. package/registry/examples/sticky-action/phone.js +15 -0
  117. package/registry/examples/sticky-action/phone.tsx +14 -0
  118. package/registry/field.json +1 -1
  119. package/registry/file-upload.json +1 -1
  120. package/registry/filter-bar.json +1 -1
  121. package/registry/force-update-screen.json +1 -1
  122. package/registry/form.json +3 -3
  123. package/registry/gallery-page.json +1 -1
  124. package/registry/genui.json +1 -1
  125. package/registry/glow-card.json +1 -1
  126. package/registry/goal-gauge.json +1 -1
  127. package/registry/how-it-works-page.json +1 -1
  128. package/registry/image-cropper.json +1 -1
  129. package/registry/index.json +226 -5
  130. package/registry/iso.json +1 -1
  131. package/registry/kanban.json +1 -1
  132. package/registry/kbd.json +1 -1
  133. package/registry/landing-page.json +1 -1
  134. package/registry/landscape.json +1 -1
  135. package/registry/legal-page.json +1 -1
  136. package/registry/link-card.json +3 -3
  137. package/registry/list.json +1 -1
  138. package/registry/loader.json +1 -1
  139. package/registry/longform-page.json +1 -1
  140. package/registry/maintenance-screen.json +1 -1
  141. package/registry/map.json +2 -2
  142. package/registry/markdown.json +1 -1
  143. package/registry/marketing-layout.json +1 -1
  144. package/registry/marquee.json +1 -1
  145. package/registry/mascot-quote.json +1 -1
  146. package/registry/mascot-state.json +1 -1
  147. package/registry/mascots.json +1 -1
  148. package/registry/match-dialog.json +1 -1
  149. package/registry/media-capture.json +3 -3
  150. package/registry/media-gallery.json +144 -0
  151. package/registry/media-grid.json +3 -3
  152. package/registry/meta-row.json +1 -1
  153. package/registry/meter.json +1 -1
  154. package/registry/nav-bar.json +2 -2
  155. package/registry/number-ticker.json +1 -1
  156. package/registry/opening-hours.json +178 -0
  157. package/registry/page-header.json +1 -1
  158. package/registry/page-hero.json +3 -3
  159. package/registry/page.json +7 -7
  160. package/registry/pagination.json +1 -1
  161. package/registry/photo-grid.json +1 -1
  162. package/registry/pointer-light.json +1 -1
  163. package/registry/popover.json +1 -1
  164. package/registry/pricing-page.json +1 -1
  165. package/registry/product-page.json +1 -1
  166. package/registry/profile-card.json +1 -1
  167. package/registry/progress.json +1 -1
  168. package/registry/promise-card.json +1 -1
  169. package/registry/radio-group.json +1 -1
  170. package/registry/rail-nav.json +2 -2
  171. package/registry/recipes.json +1 -1
  172. package/registry/scroll-stage.json +1 -1
  173. package/registry/search-field.json +1 -1
  174. package/registry/section-backdrop.json +1 -1
  175. package/registry/separator.json +1 -1
  176. package/registry/service-card.json +358 -0
  177. package/registry/settings-layout.json +1 -1
  178. package/registry/showcase.json +1 -1
  179. package/registry/site-footer.json +2 -2
  180. package/registry/sites.json +1 -1
  181. package/registry/skeleton.json +3 -3
  182. package/registry/skip-link.json +1 -1
  183. package/registry/slider.json +1 -1
  184. package/registry/slot-picker.json +222 -0
  185. package/registry/slot.json +1 -1
  186. package/registry/spinner.json +1 -1
  187. package/registry/split-view.json +1 -1
  188. package/registry/stage-banner.json +1 -1
  189. package/registry/stat.json +1 -1
  190. package/registry/status-page.json +1 -1
  191. package/registry/step-progress.json +1 -1
  192. package/registry/step-showcase.json +1 -1
  193. package/registry/stepper.json +1 -1
  194. package/registry/sticky-action.json +108 -0
  195. package/registry/swipe-deck.json +1 -1
  196. package/registry/switch.json +1 -1
  197. package/registry/tabs.json +1 -1
  198. package/registry/tag-input.json +1 -1
  199. package/registry/tag-selector.json +1 -1
  200. package/registry/terminal-replay.json +1 -1
  201. package/registry/theme.json +1 -1
  202. package/registry/toast.json +1 -1
  203. package/registry/toc.json +1 -1
  204. package/registry/tooltip.json +1 -1
  205. package/registry/tree-view.json +1 -1
  206. package/registry/update-prompt.json +1 -1
  207. package/registry/verified-badge.json +1 -1
  208. package/registry/vertical-video.json +5 -5
  209. package/registry/video-player.json +3 -3
  210. package/registry/video-trimmer.json +1 -1
  211. package/registry/virtual.json +1 -1
  212. package/registry/waveform.json +1 -1
  213. package/dist/chunk-CEJDH6SA.js.map +0 -1
  214. /package/dist/{chunk-F7FVPPBB.js.map → chunk-LYOPPBMC.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cn.ts","../src/docs-nav/docs-nav.tsx"],"sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { cnMerge, type TWMergeConfig } from \"tailwind-variants\";\n\nexport type { ClassValue };\n\n/**\n * The preset's own utilities, told to the merge engine: the material (BRAND.md §6: `bg-sheen`, `bg-fill-shade`,\n * `bg-halo` are background images; `shadow-raised` · `-floating` · `-overlay` · `-glow` are shadows; `inset-shadow-edge`\n * · `-edge-fill` · `-well` are inset shadows). Unknown, tailwind-merge would take `bg-sheen` for a colour and drop the\n * `bg-surface-2` it lies on.\n */\nexport const twMergeConfig: TWMergeConfig = {\n extend: {\n classGroups: {\n \"bg-image\": [\"bg-sheen\", \"bg-fill-shade\", \"bg-halo\"],\n shadow: [\"shadow-raised\", \"shadow-floating\", \"shadow-overlay\", \"shadow-glow\", \"shadow-glow-lg\"],\n \"inset-shadow\": [\"inset-shadow-edge\", \"inset-shadow-edge-fill\", \"inset-shadow-well\"],\n },\n },\n};\n\nconst mergeConfig = { twMergeConfig };\n\n/**\n * Merges Tailwind classes: the last one wins — a product's `className` overrides the primitive's. The merge engine is\n * tailwind-merge as tailwind-variants ships it (the one `tv` uses), so the platform carries a single copy of it.\n * tailwind-variants bundles that engine since 3.3 (it never imports the `tailwind-merge` package, an optional peer):\n * hence `tailwind-variants ^3.3.1` and no `tailwind-merge` dependency — `scripts/consumer.mjs` checks it on a clean\n * install of the packed package.\n */\nexport function cn(...inputs: ClassValue[]): string {\n return cnMerge(clsx(inputs))(mergeConfig) ?? \"\";\n}\n\n","// Server-safe. The pages of a documentation, grouped: a quiet list of links, each group a native `details` (open when it\n// holds the current page), only the current page marked. No state: the app tells which page is current.\nimport * as React from \"react\";\n\nimport { cn } from \"../cn\";\nimport type { LinkComponent } from \"../page-hero\";\n\nexport type DocsNavGroup = {\n /** A stable key. */\n id: string;\n /** The group's name — one word or two. */\n title: React.ReactNode;\n /** Its pages: a short, one-line title each. */\n items: readonly { href: string; label: React.ReactNode }[];\n};\n\nexport type DocsNavProps = Omit<React.HTMLAttributes<HTMLElement>, \"children\"> & {\n /** The navigation's accessible name (`Documentation`). */\n label: string;\n /** The groups, in order. */\n groups: readonly DocsNavGroup[];\n /** The `href` of the page being read. */\n current?: string;\n /** The app's link component (Next's `Link`). */\n linkAs?: LinkComponent;\n};\n\n/** The pages of the documentation in groups; the group of the current page is open, the others fold. */\nexport function DocsNav({ label, groups, current, linkAs, className, ...props }: DocsNavProps) {\n const L = linkAs ?? \"a\";\n return (\n <nav aria-label={label} className={cn(\"flex flex-col gap-1 text-sm\", className)} {...props}>\n {groups.map((g) => {\n const open = g.items.some((i) => i.href === current) || !current;\n return (\n <details key={g.id} open={open} className=\"group py-1\">\n <summary className=\"flex cursor-pointer list-none items-center justify-between rounded-md px-3 py-1.5 text-xs font-semibold uppercase tracking-wider text-fg-muted marker:content-none hover:text-fg focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring [&::-webkit-details-marker]:hidden\">\n {g.title}\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\" className=\"h-3.5 w-3.5 fill-none stroke-current stroke-2 transition-transform group-open:rotate-180 motion-reduce:transition-none\">\n <path d=\"m6 9 6 6 6-6\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </summary>\n <ul className=\"mt-1 flex flex-col gap-0.5 border-l border-border-subtle\">\n {g.items.map((i) => (\n <li key={i.href}>\n <L\n href={i.href}\n aria-current={i.href === current ? \"page\" : undefined}\n className=\"-ml-px block truncate border-l border-transparent px-3 py-1.5 text-fg-secondary no-underline transition-colors hover:text-fg focus-visible:outline-2 focus-visible:outline-ring aria-[current=page]:border-accent aria-[current=page]:font-semibold aria-[current=page]:text-fg\"\n >\n {i.label}\n </L>\n </li>\n ))}\n </ul>\n </details>\n );\n })}\n </nav>\n );\n}\n"],"mappings":";AAAA,SAA0B,YAAY;AACtC,SAAS,eAAmC;AAUrC,IAAM,gBAA+B;AAAA,EAC1C,QAAQ;AAAA,IACN,aAAa;AAAA,MACX,YAAY,CAAC,YAAY,iBAAiB,SAAS;AAAA,MACnD,QAAQ,CAAC,iBAAiB,mBAAmB,kBAAkB,eAAe,gBAAgB;AAAA,MAC9F,gBAAgB,CAAC,qBAAqB,0BAA0B,mBAAmB;AAAA,IACrF;AAAA,EACF;AACF;AAEA,IAAM,cAAc,EAAE,cAAc;AAS7B,SAAS,MAAM,QAA8B;AAClD,SAAO,QAAQ,KAAK,MAAM,CAAC,EAAE,WAAW,KAAK;AAC/C;;;ACIY,SAGI,KAHJ;AARL,SAAS,QAAQ,EAAE,OAAO,QAAQ,SAAS,QAAQ,WAAW,GAAG,MAAM,GAAiB;AAC7F,QAAM,IAAI,UAAU;AACpB,SACE,oBAAC,SAAI,cAAY,OAAO,WAAW,GAAG,+BAA+B,SAAS,GAAI,GAAG,OAClF,iBAAO,IAAI,CAAC,MAAM;AACjB,UAAM,OAAO,EAAE,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,OAAO,KAAK,CAAC;AACzD,WACE,qBAAC,aAAmB,MAAY,WAAU,cACxC;AAAA,2BAAC,aAAQ,WAAU,ySAChB;AAAA,UAAE;AAAA,QACH,oBAAC,SAAI,SAAQ,aAAY,eAAY,QAAO,WAAU,SAAQ,WAAU,0HACtE,8BAAC,UAAK,GAAE,gBAAe,eAAc,SAAQ,gBAAe,SAAQ,GACtE;AAAA,SACF;AAAA,MACA,oBAAC,QAAG,WAAU,4DACX,YAAE,MAAM,IAAI,CAAC,MACZ,oBAAC,QACC;AAAA,QAAC;AAAA;AAAA,UACC,MAAM,EAAE;AAAA,UACR,gBAAc,EAAE,SAAS,UAAU,SAAS;AAAA,UAC5C,WAAU;AAAA,UAET,YAAE;AAAA;AAAA,MACL,KAPO,EAAE,IAQX,CACD,GACH;AAAA,SAnBY,EAAE,EAoBhB;AAAA,EAEJ,CAAC,GACH;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../src/docs-nav/docs-nav.tsx"],"sourcesContent":["// Server-safe. The pages of a documentation, grouped: a quiet list of links, each group a native `details` (open when it\n// holds the current page), only the current page marked. No state: the app tells which page is current.\nimport * as React from \"react\";\n\nimport { cn } from \"../cn\";\nimport type { LinkComponent } from \"../page-hero\";\n\nexport type DocsNavGroup = {\n /** A stable key. */\n id: string;\n /** The group's name — one word or two. */\n title: React.ReactNode;\n /** Its pages: a short, one-line title each. */\n items: readonly { href: string; label: React.ReactNode }[];\n};\n\nexport type DocsNavProps = Omit<React.HTMLAttributes<HTMLElement>, \"children\"> & {\n /** The navigation's accessible name (`Documentation`). */\n label: string;\n /** The groups, in order. */\n groups: readonly DocsNavGroup[];\n /** The `href` of the page being read. */\n current?: string;\n /** The app's link component (Next's `Link`). */\n linkAs?: LinkComponent;\n};\n\n/** The pages of the documentation in groups; the group of the current page is open, the others fold. */\nexport function DocsNav({ label, groups, current, linkAs, className, ...props }: DocsNavProps) {\n const L = linkAs ?? \"a\";\n return (\n <nav aria-label={label} className={cn(\"flex flex-col gap-1 text-sm\", className)} {...props}>\n {groups.map((g) => {\n const open = g.items.some((i) => i.href === current) || !current;\n return (\n <details key={g.id} open={open} className=\"group py-1\">\n <summary className=\"flex cursor-pointer list-none items-center justify-between rounded-md px-3 py-1.5 text-xs font-semibold uppercase tracking-wider text-fg-muted marker:content-none hover:text-fg focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring [&::-webkit-details-marker]:hidden\">\n {g.title}\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\" className=\"h-3.5 w-3.5 fill-none stroke-current stroke-2 transition-transform group-open:rotate-180 motion-reduce:transition-none\">\n <path d=\"m6 9 6 6 6-6\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </summary>\n <ul className=\"mt-1 flex flex-col gap-0.5 border-l border-border-subtle\">\n {g.items.map((i) => (\n <li key={i.href}>\n <L\n href={i.href}\n aria-current={i.href === current ? \"page\" : undefined}\n className=\"-ml-px block truncate border-l border-transparent px-3 py-1.5 text-fg-secondary no-underline transition-colors hover:text-fg focus-visible:outline-2 focus-visible:outline-ring aria-[current=page]:border-accent aria-[current=page]:font-semibold aria-[current=page]:text-fg\"\n >\n {i.label}\n </L>\n </li>\n ))}\n </ul>\n </details>\n );\n })}\n </nav>\n );\n}\n"],"mappings":";;;;;AAoCY,SAGI,KAHJ;AARL,SAAS,QAAQ,EAAE,OAAO,QAAQ,SAAS,QAAQ,WAAW,GAAG,MAAM,GAAiB;AAC7F,QAAM,IAAI,UAAU;AACpB,SACE,oBAAC,SAAI,cAAY,OAAO,WAAW,GAAG,+BAA+B,SAAS,GAAI,GAAG,OAClF,iBAAO,IAAI,CAAC,MAAM;AACjB,UAAM,OAAO,EAAE,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,OAAO,KAAK,CAAC;AACzD,WACE,qBAAC,aAAmB,MAAY,WAAU,cACxC;AAAA,2BAAC,aAAQ,WAAU,ySAChB;AAAA,UAAE;AAAA,QACH,oBAAC,SAAI,SAAQ,aAAY,eAAY,QAAO,WAAU,SAAQ,WAAU,0HACtE,8BAAC,UAAK,GAAE,gBAAe,eAAc,SAAQ,gBAAe,SAAQ,GACtE;AAAA,SACF;AAAA,MACA,oBAAC,QAAG,WAAU,4DACX,YAAE,MAAM,IAAI,CAAC,MACZ,oBAAC,QACC;AAAA,QAAC;AAAA;AAAA,UACC,MAAM,EAAE;AAAA,UACR,gBAAc,EAAE,SAAS,UAAU,SAAS;AAAA,UAC5C,WAAU;AAAA,UAET,YAAE;AAAA;AAAA,MACL,KAPO,EAAE,IAQX,CACD,GACH;AAAA,SAnBY,EAAE,EAoBhB;AAAA,EAEJ,CAAC,GACH;AAEJ;","names":[]}
@@ -55,6 +55,12 @@ type DropdownMenuItemProps = React.ComponentProps<typeof DropdownMenu$1.Item> &
55
55
  declare function DropdownMenuItem({ tone, className, ...props }: DropdownMenuItemProps): React.JSX.Element;
56
56
  /** A toggled option: `checked` + `onCheckedChange`. */
57
57
  declare function DropdownMenuCheckboxItem({ className, children, ...props }: React.ComponentProps<typeof DropdownMenu$1.CheckboxItem>): React.JSX.Element;
58
+ /** A submenu's trigger: an item that opens `DropdownMenu.SubContent`, with a chevron. */
59
+ declare function DropdownMenuSubTrigger({ className, children, ...props }: React.ComponentProps<typeof DropdownMenu$1.SubTrigger>): React.JSX.Element;
60
+ /** The submenu's panel (same material as the menu). */
61
+ declare function DropdownMenuSubContent({ sideOffset, collisionPadding, className, ...props }: React.ComponentProps<typeof DropdownMenu$1.SubContent>): React.JSX.Element;
62
+ /** One choice among several (`DropdownMenu.RadioGroup` holds the value): a language, a sort order. */
63
+ declare function DropdownMenuRadioItem({ className, children, ...props }: React.ComponentProps<typeof DropdownMenu$1.RadioItem>): React.JSX.Element;
58
64
  declare function DropdownMenuLabel({ className, ...props }: React.ComponentProps<typeof DropdownMenu$1.Label>): React.JSX.Element;
59
65
  declare function DropdownMenuSeparator({ className, ...props }: React.ComponentProps<typeof DropdownMenu$1.Separator>): React.JSX.Element;
60
66
  /** `DropdownMenu.Root/Trigger/Content/Item/CheckboxItem/Label/Separator/Group`. `open`/`defaultOpen` + `onOpenChange`. */
@@ -67,6 +73,11 @@ declare const DropdownMenu: {
67
73
  Label: typeof DropdownMenuLabel;
68
74
  Separator: typeof DropdownMenuSeparator;
69
75
  Group: React.ForwardRefExoticComponent<DropdownMenu$1.DropdownMenuGroupProps & React.RefAttributes<HTMLDivElement>>;
76
+ Sub: React.FC<DropdownMenu$1.DropdownMenuSubProps>;
77
+ SubTrigger: typeof DropdownMenuSubTrigger;
78
+ SubContent: typeof DropdownMenuSubContent;
79
+ RadioGroup: React.ForwardRefExoticComponent<DropdownMenu$1.DropdownMenuRadioGroupProps & React.RefAttributes<HTMLDivElement>>;
80
+ RadioItem: typeof DropdownMenuRadioItem;
70
81
  };
71
82
 
72
- export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, type DropdownMenuContentProps, DropdownMenuItem, type DropdownMenuItemProps, DropdownMenuLabel, DropdownMenuSeparator, menu };
83
+ export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, type DropdownMenuContentProps, DropdownMenuItem, type DropdownMenuItemProps, DropdownMenuLabel, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSubContent, DropdownMenuSubTrigger, menu };
@@ -12,7 +12,7 @@ import { tv } from "tailwind-variants";
12
12
  import { jsx, jsxs } from "react/jsx-runtime";
13
13
  var menu = tv({
14
14
  slots: {
15
- content: cn(floating, "min-w-48 max-h-(--radix-dropdown-menu-content-available-height) overflow-y-auto p-1 origin-(--radix-dropdown-menu-content-transform-origin)"),
15
+ content: cn(floating, "min-w-48 max-h-(--radix-dropdown-menu-content-available-height) overflow-y-auto overflow-x-hidden overscroll-contain p-1 origin-(--radix-dropdown-menu-content-transform-origin)"),
16
16
  item: "relative flex cursor-pointer select-none items-center gap-2 rounded-md px-2.5 py-2 text-sm text-fg outline-hidden transition-colors data-highlighted:bg-surface-3 data-disabled:pointer-events-none data-disabled:opacity-40 [&>svg]:h-4 [&>svg]:w-4 [&>svg]:shrink-0 [&>svg]:text-fg-secondary",
17
17
  indicator: "ml-auto flex h-4 w-4 items-center justify-center text-fg-accent",
18
18
  label: "px-2.5 pb-1 pt-2 text-[11px] font-semibold uppercase tracking-wider text-fg-secondary",
@@ -38,6 +38,21 @@ function DropdownMenuCheckboxItem({ className, children, ...props }) {
38
38
  /* @__PURE__ */ jsx(MenuPrimitive.ItemIndicator, { className: s.indicator(), children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" }) }) })
39
39
  ] });
40
40
  }
41
+ function DropdownMenuSubTrigger({ className, children, ...props }) {
42
+ return /* @__PURE__ */ jsxs(MenuPrimitive.SubTrigger, { className: s.item({ className: cn("data-[state=open]:bg-surface-3", className) }), ...props, children: [
43
+ children,
44
+ /* @__PURE__ */ jsx("svg", { className: "ml-auto !h-4 !w-4 text-fg-secondary", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" }) })
45
+ ] });
46
+ }
47
+ function DropdownMenuSubContent({ sideOffset = 4, collisionPadding = 8, className, ...props }) {
48
+ return /* @__PURE__ */ jsx(MenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(MenuPrimitive.SubContent, { sideOffset, collisionPadding, className: s.content({ className: cn("max-h-(--radix-dropdown-menu-content-available-height)", className) }), ...props }) });
49
+ }
50
+ function DropdownMenuRadioItem({ className, children, ...props }) {
51
+ return /* @__PURE__ */ jsxs(MenuPrimitive.RadioItem, { className: s.item({ className }), ...props, children: [
52
+ children,
53
+ /* @__PURE__ */ jsx(MenuPrimitive.ItemIndicator, { className: s.indicator(), children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" }) }) })
54
+ ] });
55
+ }
41
56
  function DropdownMenuLabel({ className, ...props }) {
42
57
  return /* @__PURE__ */ jsx(MenuPrimitive.Label, { className: s.label({ className }), ...props });
43
58
  }
@@ -52,7 +67,12 @@ var DropdownMenu = {
52
67
  CheckboxItem: DropdownMenuCheckboxItem,
53
68
  Label: DropdownMenuLabel,
54
69
  Separator: DropdownMenuSeparator,
55
- Group: MenuPrimitive.Group
70
+ Group: MenuPrimitive.Group,
71
+ Sub: MenuPrimitive.Sub,
72
+ SubTrigger: DropdownMenuSubTrigger,
73
+ SubContent: DropdownMenuSubContent,
74
+ RadioGroup: MenuPrimitive.RadioGroup,
75
+ RadioItem: DropdownMenuRadioItem
56
76
  };
57
77
  export {
58
78
  DropdownMenu,
@@ -60,7 +80,10 @@ export {
60
80
  DropdownMenuContent,
61
81
  DropdownMenuItem,
62
82
  DropdownMenuLabel,
83
+ DropdownMenuRadioItem,
63
84
  DropdownMenuSeparator,
85
+ DropdownMenuSubContent,
86
+ DropdownMenuSubTrigger,
64
87
  menu
65
88
  };
66
89
  //# sourceMappingURL=dropdown-menu.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/dropdown-menu/dropdown-menu.tsx"],"sourcesContent":["// Client (a portal). Radix does the roving focus, the arrows, Home/End, typeahead, Escape and the focus return.\nimport { DropdownMenu as MenuPrimitive } from \"radix-ui\";\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { cn } from \"../cn\";\nimport { floating } from \"../floating\";\n\nexport const menu = tv({\n slots: {\n content: cn(floating, \"min-w-48 max-h-(--radix-dropdown-menu-content-available-height) overflow-y-auto p-1 origin-(--radix-dropdown-menu-content-transform-origin)\"),\n item:\n \"relative flex cursor-pointer select-none items-center gap-2 rounded-md px-2.5 py-2 text-sm text-fg outline-hidden transition-colors \" +\n \"data-highlighted:bg-surface-3 data-disabled:pointer-events-none data-disabled:opacity-40 [&>svg]:h-4 [&>svg]:w-4 [&>svg]:shrink-0 \" +\n \"[&>svg]:text-fg-secondary\",\n indicator: \"ml-auto flex h-4 w-4 items-center justify-center text-fg-accent\",\n label: \"px-2.5 pb-1 pt-2 text-[11px] font-semibold uppercase tracking-wider text-fg-secondary\",\n separator: \"-mx-1 my-1 h-px bg-border-subtle\",\n },\n variants: {\n // The label reads in the danger text role (≥ 4.5:1 on the menu surface, both themes); the icon and the highlight\n // carry the danger fill.\n tone: { default: {}, danger: { item: \"text-fg-danger data-highlighted:bg-danger/15 [&>svg]:text-danger\" } },\n },\n defaultVariants: { tone: \"default\" },\n});\nconst s = menu();\n\nexport type DropdownMenuContentProps = React.ComponentProps<typeof MenuPrimitive.Content> & {\n /** The element the portal renders into (default: document.body). */\n container?: HTMLElement | null;\n};\n\nexport function DropdownMenuContent({ sideOffset = 6, align = \"end\", collisionPadding = 8, container, className, ...props }: DropdownMenuContentProps) {\n return (\n <MenuPrimitive.Portal container={container}>\n <MenuPrimitive.Content sideOffset={sideOffset} align={align} collisionPadding={collisionPadding} className={s.content({ className })} {...props} />\n </MenuPrimitive.Portal>\n );\n}\n\nexport type DropdownMenuItemProps = React.ComponentProps<typeof MenuPrimitive.Item> & {\n /** `danger` for a destructive action: the icon and the highlight carry the danger, the label stays legible. */\n tone?: \"default\" | \"danger\";\n};\n\n/** An action. `tone=\"danger\"` for a destructive one; `onSelect` runs it (the menu closes). */\nexport function DropdownMenuItem({ tone, className, ...props }: DropdownMenuItemProps) {\n return <MenuPrimitive.Item data-tone={tone ?? \"default\"} className={menu({ tone }).item({ className })} {...props} />;\n}\n\n/** A toggled option: `checked` + `onCheckedChange`. */\nexport function DropdownMenuCheckboxItem({ className, children, ...props }: React.ComponentProps<typeof MenuPrimitive.CheckboxItem>) {\n return (\n <MenuPrimitive.CheckboxItem className={s.item({ className })} {...props}>\n {children}\n <MenuPrimitive.ItemIndicator className={s.indicator()}>\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n </MenuPrimitive.ItemIndicator>\n </MenuPrimitive.CheckboxItem>\n );\n}\n\nexport function DropdownMenuLabel({ className, ...props }: React.ComponentProps<typeof MenuPrimitive.Label>) {\n return <MenuPrimitive.Label className={s.label({ className })} {...props} />;\n}\n\nexport function DropdownMenuSeparator({ className, ...props }: React.ComponentProps<typeof MenuPrimitive.Separator>) {\n return <MenuPrimitive.Separator className={s.separator({ className })} {...props} />;\n}\n\n/** `DropdownMenu.Root/Trigger/Content/Item/CheckboxItem/Label/Separator/Group`. `open`/`defaultOpen` + `onOpenChange`. */\nexport const DropdownMenu = {\n Root: MenuPrimitive.Root,\n Trigger: MenuPrimitive.Trigger,\n Content: DropdownMenuContent,\n Item: DropdownMenuItem,\n CheckboxItem: DropdownMenuCheckboxItem,\n Label: DropdownMenuLabel,\n Separator: DropdownMenuSeparator,\n Group: MenuPrimitive.Group,\n};\n"],"mappings":";;;;;;;;;AACA,SAAS,gBAAgB,qBAAqB;AAE9C,SAAS,UAAU;AAiCb,cAkBF,YAlBE;AA5BC,IAAM,OAAO,GAAG;AAAA,EACrB,OAAO;AAAA,IACL,SAAS,GAAG,UAAU,6IAA6I;AAAA,IACnK,MACE;AAAA,IAGF,WAAW;AAAA,IACX,OAAO;AAAA,IACP,WAAW;AAAA,EACb;AAAA,EACA,UAAU;AAAA;AAAA;AAAA,IAGR,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,EAAE,MAAM,mEAAmE,EAAE;AAAA,EAC5G;AAAA,EACA,iBAAiB,EAAE,MAAM,UAAU;AACrC,CAAC;AACD,IAAM,IAAI,KAAK;AAOR,SAAS,oBAAoB,EAAE,aAAa,GAAG,QAAQ,OAAO,mBAAmB,GAAG,WAAW,WAAW,GAAG,MAAM,GAA6B;AACrJ,SACE,oBAAC,cAAc,QAAd,EAAqB,WACpB,8BAAC,cAAc,SAAd,EAAsB,YAAwB,OAAc,kBAAoC,WAAW,EAAE,QAAQ,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO,GACnJ;AAEJ;AAQO,SAAS,iBAAiB,EAAE,MAAM,WAAW,GAAG,MAAM,GAA0B;AACrF,SAAO,oBAAC,cAAc,MAAd,EAAmB,aAAW,QAAQ,WAAW,WAAW,KAAK,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AACrH;AAGO,SAAS,yBAAyB,EAAE,WAAW,UAAU,GAAG,MAAM,GAA4D;AACnI,SACE,qBAAC,cAAc,cAAd,EAA2B,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAC/D;AAAA;AAAA,IACD,oBAAC,cAAc,eAAd,EAA4B,WAAW,EAAE,UAAU,GAClD,8BAAC,SAAI,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,OAAM,eAAc,SAAQ,gBAAe,SAAQ,eAAW,MACnI,8BAAC,UAAK,GAAE,mBAAkB,GAC5B,GACF;AAAA,KACF;AAEJ;AAEO,SAAS,kBAAkB,EAAE,WAAW,GAAG,MAAM,GAAqD;AAC3G,SAAO,oBAAC,cAAc,OAAd,EAAoB,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AAC5E;AAEO,SAAS,sBAAsB,EAAE,WAAW,GAAG,MAAM,GAAyD;AACnH,SAAO,oBAAC,cAAc,WAAd,EAAwB,WAAW,EAAE,UAAU,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AACpF;AAGO,IAAM,eAAe;AAAA,EAC1B,MAAM,cAAc;AAAA,EACpB,SAAS,cAAc;AAAA,EACvB,SAAS;AAAA,EACT,MAAM;AAAA,EACN,cAAc;AAAA,EACd,OAAO;AAAA,EACP,WAAW;AAAA,EACX,OAAO,cAAc;AACvB;","names":[]}
1
+ {"version":3,"sources":["../src/dropdown-menu/dropdown-menu.tsx"],"sourcesContent":["// Client (a portal). Radix does the roving focus, the arrows, Home/End, typeahead, Escape and the focus return.\nimport { DropdownMenu as MenuPrimitive } from \"radix-ui\";\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { cn } from \"../cn\";\nimport { floating } from \"../floating\";\n\nexport const menu = tv({\n slots: {\n content: cn(floating, \"min-w-48 max-h-(--radix-dropdown-menu-content-available-height) overflow-y-auto overflow-x-hidden overscroll-contain p-1 origin-(--radix-dropdown-menu-content-transform-origin)\"),\n item:\n \"relative flex cursor-pointer select-none items-center gap-2 rounded-md px-2.5 py-2 text-sm text-fg outline-hidden transition-colors \" +\n \"data-highlighted:bg-surface-3 data-disabled:pointer-events-none data-disabled:opacity-40 [&>svg]:h-4 [&>svg]:w-4 [&>svg]:shrink-0 \" +\n \"[&>svg]:text-fg-secondary\",\n indicator: \"ml-auto flex h-4 w-4 items-center justify-center text-fg-accent\",\n label: \"px-2.5 pb-1 pt-2 text-[11px] font-semibold uppercase tracking-wider text-fg-secondary\",\n separator: \"-mx-1 my-1 h-px bg-border-subtle\",\n },\n variants: {\n // The label reads in the danger text role (≥ 4.5:1 on the menu surface, both themes); the icon and the highlight\n // carry the danger fill.\n tone: { default: {}, danger: { item: \"text-fg-danger data-highlighted:bg-danger/15 [&>svg]:text-danger\" } },\n },\n defaultVariants: { tone: \"default\" },\n});\nconst s = menu();\n\nexport type DropdownMenuContentProps = React.ComponentProps<typeof MenuPrimitive.Content> & {\n /** The element the portal renders into (default: document.body). */\n container?: HTMLElement | null;\n};\n\nexport function DropdownMenuContent({ sideOffset = 6, align = \"end\", collisionPadding = 8, container, className, ...props }: DropdownMenuContentProps) {\n return (\n <MenuPrimitive.Portal container={container}>\n <MenuPrimitive.Content sideOffset={sideOffset} align={align} collisionPadding={collisionPadding} className={s.content({ className })} {...props} />\n </MenuPrimitive.Portal>\n );\n}\n\nexport type DropdownMenuItemProps = React.ComponentProps<typeof MenuPrimitive.Item> & {\n /** `danger` for a destructive action: the icon and the highlight carry the danger, the label stays legible. */\n tone?: \"default\" | \"danger\";\n};\n\n/** An action. `tone=\"danger\"` for a destructive one; `onSelect` runs it (the menu closes). */\nexport function DropdownMenuItem({ tone, className, ...props }: DropdownMenuItemProps) {\n return <MenuPrimitive.Item data-tone={tone ?? \"default\"} className={menu({ tone }).item({ className })} {...props} />;\n}\n\n/** A toggled option: `checked` + `onCheckedChange`. */\nexport function DropdownMenuCheckboxItem({ className, children, ...props }: React.ComponentProps<typeof MenuPrimitive.CheckboxItem>) {\n return (\n <MenuPrimitive.CheckboxItem className={s.item({ className })} {...props}>\n {children}\n <MenuPrimitive.ItemIndicator className={s.indicator()}>\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n </MenuPrimitive.ItemIndicator>\n </MenuPrimitive.CheckboxItem>\n );\n}\n\n/** A submenu's trigger: an item that opens `DropdownMenu.SubContent`, with a chevron. */\nexport function DropdownMenuSubTrigger({ className, children, ...props }: React.ComponentProps<typeof MenuPrimitive.SubTrigger>) {\n return (\n <MenuPrimitive.SubTrigger className={s.item({ className: cn(\"data-[state=open]:bg-surface-3\", className) })} {...props}>\n {children}\n <svg className=\"ml-auto !h-4 !w-4 text-fg-secondary\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n </MenuPrimitive.SubTrigger>\n );\n}\n\n/** The submenu's panel (same material as the menu). */\nexport function DropdownMenuSubContent({ sideOffset = 4, collisionPadding = 8, className, ...props }: React.ComponentProps<typeof MenuPrimitive.SubContent>) {\n return (\n <MenuPrimitive.Portal>\n <MenuPrimitive.SubContent sideOffset={sideOffset} collisionPadding={collisionPadding} className={s.content({ className: cn(\"max-h-(--radix-dropdown-menu-content-available-height)\", className) })} {...props} />\n </MenuPrimitive.Portal>\n );\n}\n\n/** One choice among several (`DropdownMenu.RadioGroup` holds the value): a language, a sort order. */\nexport function DropdownMenuRadioItem({ className, children, ...props }: React.ComponentProps<typeof MenuPrimitive.RadioItem>) {\n return (\n <MenuPrimitive.RadioItem className={s.item({ className })} {...props}>\n {children}\n <MenuPrimitive.ItemIndicator className={s.indicator()}>\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n </MenuPrimitive.ItemIndicator>\n </MenuPrimitive.RadioItem>\n );\n}\n\nexport function DropdownMenuLabel({ className, ...props }: React.ComponentProps<typeof MenuPrimitive.Label>) {\n return <MenuPrimitive.Label className={s.label({ className })} {...props} />;\n}\n\nexport function DropdownMenuSeparator({ className, ...props }: React.ComponentProps<typeof MenuPrimitive.Separator>) {\n return <MenuPrimitive.Separator className={s.separator({ className })} {...props} />;\n}\n\n/** `DropdownMenu.Root/Trigger/Content/Item/CheckboxItem/Label/Separator/Group`. `open`/`defaultOpen` + `onOpenChange`. */\nexport const DropdownMenu = {\n Root: MenuPrimitive.Root,\n Trigger: MenuPrimitive.Trigger,\n Content: DropdownMenuContent,\n Item: DropdownMenuItem,\n CheckboxItem: DropdownMenuCheckboxItem,\n Label: DropdownMenuLabel,\n Separator: DropdownMenuSeparator,\n Group: MenuPrimitive.Group,\n Sub: MenuPrimitive.Sub,\n SubTrigger: DropdownMenuSubTrigger,\n SubContent: DropdownMenuSubContent,\n RadioGroup: MenuPrimitive.RadioGroup,\n RadioItem: DropdownMenuRadioItem,\n};\n"],"mappings":";;;;;;;;;AACA,SAAS,gBAAgB,qBAAqB;AAE9C,SAAS,UAAU;AAiCb,cAkBF,YAlBE;AA5BC,IAAM,OAAO,GAAG;AAAA,EACrB,OAAO;AAAA,IACL,SAAS,GAAG,UAAU,kLAAkL;AAAA,IACxM,MACE;AAAA,IAGF,WAAW;AAAA,IACX,OAAO;AAAA,IACP,WAAW;AAAA,EACb;AAAA,EACA,UAAU;AAAA;AAAA;AAAA,IAGR,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,EAAE,MAAM,mEAAmE,EAAE;AAAA,EAC5G;AAAA,EACA,iBAAiB,EAAE,MAAM,UAAU;AACrC,CAAC;AACD,IAAM,IAAI,KAAK;AAOR,SAAS,oBAAoB,EAAE,aAAa,GAAG,QAAQ,OAAO,mBAAmB,GAAG,WAAW,WAAW,GAAG,MAAM,GAA6B;AACrJ,SACE,oBAAC,cAAc,QAAd,EAAqB,WACpB,8BAAC,cAAc,SAAd,EAAsB,YAAwB,OAAc,kBAAoC,WAAW,EAAE,QAAQ,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO,GACnJ;AAEJ;AAQO,SAAS,iBAAiB,EAAE,MAAM,WAAW,GAAG,MAAM,GAA0B;AACrF,SAAO,oBAAC,cAAc,MAAd,EAAmB,aAAW,QAAQ,WAAW,WAAW,KAAK,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AACrH;AAGO,SAAS,yBAAyB,EAAE,WAAW,UAAU,GAAG,MAAM,GAA4D;AACnI,SACE,qBAAC,cAAc,cAAd,EAA2B,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAC/D;AAAA;AAAA,IACD,oBAAC,cAAc,eAAd,EAA4B,WAAW,EAAE,UAAU,GAClD,8BAAC,SAAI,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,OAAM,eAAc,SAAQ,gBAAe,SAAQ,eAAW,MACnI,8BAAC,UAAK,GAAE,mBAAkB,GAC5B,GACF;AAAA,KACF;AAEJ;AAGO,SAAS,uBAAuB,EAAE,WAAW,UAAU,GAAG,MAAM,GAA0D;AAC/H,SACE,qBAAC,cAAc,YAAd,EAAyB,WAAW,EAAE,KAAK,EAAE,WAAW,GAAG,kCAAkC,SAAS,EAAE,CAAC,GAAI,GAAG,OAC9G;AAAA;AAAA,IACD,oBAAC,SAAI,WAAU,uCAAsC,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SAAQ,eAAW,MACjL,8BAAC,UAAK,GAAE,iBAAgB,GAC1B;AAAA,KACF;AAEJ;AAGO,SAAS,uBAAuB,EAAE,aAAa,GAAG,mBAAmB,GAAG,WAAW,GAAG,MAAM,GAA0D;AAC3J,SACE,oBAAC,cAAc,QAAd,EACC,8BAAC,cAAc,YAAd,EAAyB,YAAwB,kBAAoC,WAAW,EAAE,QAAQ,EAAE,WAAW,GAAG,0DAA0D,SAAS,EAAE,CAAC,GAAI,GAAG,OAAO,GACjN;AAEJ;AAGO,SAAS,sBAAsB,EAAE,WAAW,UAAU,GAAG,MAAM,GAAyD;AAC7H,SACE,qBAAC,cAAc,WAAd,EAAwB,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAC5D;AAAA;AAAA,IACD,oBAAC,cAAc,eAAd,EAA4B,WAAW,EAAE,UAAU,GAClD,8BAAC,SAAI,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,OAAM,eAAc,SAAQ,gBAAe,SAAQ,eAAW,MACnI,8BAAC,UAAK,GAAE,mBAAkB,GAC5B,GACF;AAAA,KACF;AAEJ;AAEO,SAAS,kBAAkB,EAAE,WAAW,GAAG,MAAM,GAAqD;AAC3G,SAAO,oBAAC,cAAc,OAAd,EAAoB,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AAC5E;AAEO,SAAS,sBAAsB,EAAE,WAAW,GAAG,MAAM,GAAyD;AACnH,SAAO,oBAAC,cAAc,WAAd,EAAwB,WAAW,EAAE,UAAU,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AACpF;AAGO,IAAM,eAAe;AAAA,EAC1B,MAAM,cAAc;AAAA,EACpB,SAAS,cAAc;AAAA,EACvB,SAAS;AAAA,EACT,MAAM;AAAA,EACN,cAAc;AAAA,EACd,OAAO;AAAA,EACP,WAAW;AAAA,EACX,OAAO,cAAc;AAAA,EACrB,KAAK,cAAc;AAAA,EACnB,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY,cAAc;AAAA,EAC1B,WAAW;AACb;","names":[]}
@@ -5,7 +5,7 @@ import {
5
5
  filterBar,
6
6
  readFilterParams,
7
7
  writeFilterParams
8
- } from "./chunk-CEJDH6SA.js";
8
+ } from "./chunk-2PNLHZLT.js";
9
9
  import "./chunk-7UCPGXKN.js";
10
10
  import "./chunk-D3T54RSL.js";
11
11
  import "./chunk-J3NC6ER4.js";
package/dist/genui.js CHANGED
@@ -7,12 +7,12 @@ import {
7
7
  } from "./chunk-MQPC3P4T.js";
8
8
  import {
9
9
  DataTable
10
- } from "./chunk-F7FVPPBB.js";
10
+ } from "./chunk-LYOPPBMC.js";
11
11
  import "./chunk-7Z4KHPFC.js";
12
12
  import "./chunk-JXLDUDTD.js";
13
13
  import "./chunk-DZU6RMYD.js";
14
14
  import "./chunk-KVDB4GXV.js";
15
- import "./chunk-CEJDH6SA.js";
15
+ import "./chunk-2PNLHZLT.js";
16
16
  import "./chunk-7UCPGXKN.js";
17
17
  import "./chunk-D3T54RSL.js";
18
18
  import "./chunk-J3NC6ER4.js";
@@ -0,0 +1,73 @@
1
+ import * as tailwind_variants from 'tailwind-variants';
2
+ import * as React from 'react';
3
+
4
+ declare const mediaGallery: tailwind_variants.TVReturnType<{
5
+ [key: string]: {
6
+ [key: string]: tailwind_variants.ClassValue | {
7
+ root?: tailwind_variants.ClassValue;
8
+ media?: tailwind_variants.ClassValue;
9
+ caption?: tailwind_variants.ClassValue;
10
+ tile?: tailwind_variants.ClassValue;
11
+ };
12
+ };
13
+ } | {
14
+ [x: string]: {
15
+ [x: string]: tailwind_variants.ClassValue | {
16
+ root?: tailwind_variants.ClassValue;
17
+ media?: tailwind_variants.ClassValue;
18
+ caption?: tailwind_variants.ClassValue;
19
+ tile?: tailwind_variants.ClassValue;
20
+ };
21
+ };
22
+ } | {}, {
23
+ root: string;
24
+ tile: string;
25
+ media: string;
26
+ caption: string;
27
+ }, undefined, {
28
+ [key: string]: {
29
+ [key: string]: tailwind_variants.ClassValue | {
30
+ root?: tailwind_variants.ClassValue;
31
+ media?: tailwind_variants.ClassValue;
32
+ caption?: tailwind_variants.ClassValue;
33
+ tile?: tailwind_variants.ClassValue;
34
+ };
35
+ };
36
+ } | {}, {
37
+ root: string;
38
+ tile: string;
39
+ media: string;
40
+ caption: string;
41
+ }, tailwind_variants.TVReturnTypeLike<unknown, {
42
+ root: string;
43
+ tile: string;
44
+ media: string;
45
+ caption: string;
46
+ }>>;
47
+ type GalleryMedia = {
48
+ /** A stable id. */
49
+ id: string;
50
+ /** The still: a photo, or the poster of a loop. */
51
+ src: string;
52
+ /** What it shows, in words. */
53
+ alt: string;
54
+ /** A muted loop: WebM first, MP4 for Safari. */
55
+ video?: {
56
+ webm?: string;
57
+ mp4?: string;
58
+ };
59
+ /** One line over the foot of the tile. */
60
+ caption?: string;
61
+ /** `wide` for a landscape source (4:3 tile); the default tile is a 3:4 portrait. */
62
+ shape?: "portrait" | "wide";
63
+ };
64
+ type MediaGalleryProps = Omit<React.ComponentProps<"ul">, "children"> & {
65
+ /** The photos and loops, the featured one first. */
66
+ items: readonly GalleryMedia[];
67
+ /** The gallery's accessible name, passed translated. */
68
+ label: string;
69
+ };
70
+ /** Photos and loops in tiles, the first featured; loops play while seen. */
71
+ declare function MediaGallery({ items, label, className, ...props }: MediaGalleryProps): React.JSX.Element;
72
+
73
+ export { type GalleryMedia, MediaGallery, type MediaGalleryProps, mediaGallery };
@@ -0,0 +1,42 @@
1
+ "use client";
2
+
3
+ // src/media-gallery/media-gallery.tsx
4
+ import * as React from "react";
5
+ import { tv } from "tailwind-variants";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ var mediaGallery = tv({
8
+ slots: {
9
+ root: "m-0 grid list-none grid-cols-2 gap-2 p-0 sm:gap-3 md:grid-cols-4",
10
+ tile: "group relative isolate m-0 aspect-[3/4] overflow-hidden rounded-xl border border-border-default bg-media data-[shape=wide]:aspect-[4/3] data-[featured]:col-span-2 data-[featured]:aspect-[4/3] md:data-[featured]:aspect-auto",
11
+ media: "absolute inset-0 h-full w-full object-cover transition-transform duration-500 motion-safe:group-hover:scale-105",
12
+ caption: "pointer-events-none absolute inset-x-0 bottom-0 bg-linear-to-t from-scrim-strong to-transparent p-3 pt-8 text-xs font-semibold text-fg-on-media"
13
+ }
14
+ });
15
+ var s = mediaGallery();
16
+ function Tile({ item, featured }) {
17
+ const ref = React.useRef(null);
18
+ const [play, setPlay] = React.useState(false);
19
+ React.useEffect(() => {
20
+ const node = ref.current;
21
+ if (!item.video || !node || window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
22
+ const io = new IntersectionObserver(([entry]) => setPlay(Boolean(entry?.isIntersecting)), { rootMargin: "120px" });
23
+ io.observe(node);
24
+ return () => io.disconnect();
25
+ }, [item.video]);
26
+ return /* @__PURE__ */ jsx("li", { ref, className: s.tile(), "data-featured": featured ? "" : void 0, "data-shape": item.shape ?? "portrait", children: /* @__PURE__ */ jsxs("figure", { className: "m-0 h-full w-full", children: [
27
+ /* @__PURE__ */ jsx("img", { src: item.src, alt: item.alt, loading: "lazy", decoding: "async", className: s.media() }),
28
+ play && item.video && /* @__PURE__ */ jsxs("video", { className: s.media(), poster: item.src, autoPlay: true, muted: true, loop: true, playsInline: true, preload: "none", "aria-hidden": true, tabIndex: -1, children: [
29
+ item.video.webm && /* @__PURE__ */ jsx("source", { src: item.video.webm, type: "video/webm" }),
30
+ item.video.mp4 && /* @__PURE__ */ jsx("source", { src: item.video.mp4, type: "video/mp4" })
31
+ ] }),
32
+ item.caption && /* @__PURE__ */ jsx("figcaption", { className: s.caption(), children: item.caption })
33
+ ] }) });
34
+ }
35
+ function MediaGallery({ items, label, className, ...props }) {
36
+ return /* @__PURE__ */ jsx("ul", { "aria-label": label, className: s.root({ className }), ...props, children: items.map((item, i) => /* @__PURE__ */ jsx(Tile, { item, featured: i === 0 && items.length > 2 }, item.id)) });
37
+ }
38
+ export {
39
+ MediaGallery,
40
+ mediaGallery
41
+ };
42
+ //# sourceMappingURL=media-gallery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/media-gallery/media-gallery.tsx"],"sourcesContent":["// Client (the reader's motion preference). A shop's photos and loops in tiles: the first is the featured one, loops play\n// muted while their tile is on screen (a still under reduced motion), a caption rides the foot of a tile.\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nexport const mediaGallery = tv({\n slots: {\n root: \"m-0 grid list-none grid-cols-2 gap-2 p-0 sm:gap-3 md:grid-cols-4\",\n tile:\n \"group relative isolate m-0 aspect-[3/4] overflow-hidden rounded-xl border border-border-default bg-media data-[shape=wide]:aspect-[4/3] \" +\n // The featured tile takes two columns; from md up it has no ratio of its own and stretches to the height of the row its neighbours set.\n \"data-[featured]:col-span-2 data-[featured]:aspect-[4/3] md:data-[featured]:aspect-auto\",\n media: \"absolute inset-0 h-full w-full object-cover transition-transform duration-500 motion-safe:group-hover:scale-105\",\n caption: \"pointer-events-none absolute inset-x-0 bottom-0 bg-linear-to-t from-scrim-strong to-transparent p-3 pt-8 text-xs font-semibold text-fg-on-media\",\n },\n});\nconst s = mediaGallery();\n\nexport type GalleryMedia = {\n /** A stable id. */\n id: string;\n /** The still: a photo, or the poster of a loop. */\n src: string;\n /** What it shows, in words. */\n alt: string;\n /** A muted loop: WebM first, MP4 for Safari. */\n video?: { webm?: string; mp4?: string };\n /** One line over the foot of the tile. */\n caption?: string;\n /** `wide` for a landscape source (4:3 tile); the default tile is a 3:4 portrait. */\n shape?: \"portrait\" | \"wide\";\n};\n\nexport type MediaGalleryProps = Omit<React.ComponentProps<\"ul\">, \"children\"> & {\n /** The photos and loops, the featured one first. */\n items: readonly GalleryMedia[];\n /** The gallery's accessible name, passed translated. */\n label: string;\n};\n\nfunction Tile({ item, featured }: { item: GalleryMedia; featured: boolean }) {\n const ref = React.useRef<HTMLLIElement>(null);\n const [play, setPlay] = React.useState(false);\n React.useEffect(() => {\n const node = ref.current;\n if (!item.video || !node || window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches) return;\n const io = new IntersectionObserver(([entry]) => setPlay(Boolean(entry?.isIntersecting)), { rootMargin: \"120px\" });\n io.observe(node);\n return () => io.disconnect();\n }, [item.video]);\n return (\n <li ref={ref} className={s.tile()} data-featured={featured ? \"\" : undefined} data-shape={item.shape ?? \"portrait\"}>\n <figure className=\"m-0 h-full w-full\">\n <img src={item.src} alt={item.alt} loading=\"lazy\" decoding=\"async\" className={s.media()} />\n {play && item.video && (\n <video className={s.media()} poster={item.src} autoPlay muted loop playsInline preload=\"none\" aria-hidden tabIndex={-1}>\n {item.video.webm && <source src={item.video.webm} type=\"video/webm\" />}\n {item.video.mp4 && <source src={item.video.mp4} type=\"video/mp4\" />}\n </video>\n )}\n {item.caption && <figcaption className={s.caption()}>{item.caption}</figcaption>}\n </figure>\n </li>\n );\n}\n\n/** Photos and loops in tiles, the first featured; loops play while seen. */\nexport function MediaGallery({ items, label, className, ...props }: MediaGalleryProps) {\n return (\n <ul aria-label={label} className={s.root({ className })} {...props}>\n {items.map((item, i) => (\n <Tile key={item.id} item={item} featured={i === 0 && items.length > 2} />\n ))}\n </ul>\n );\n}\n"],"mappings":";;;AAEA,YAAY,WAAW;AACvB,SAAS,UAAU;AAkDX,cAEE,YAFF;AAhDD,IAAM,eAAe,GAAG;AAAA,EAC7B,OAAO;AAAA,IACL,MAAM;AAAA,IACN,MACE;AAAA,IAGF,OAAO;AAAA,IACP,SAAS;AAAA,EACX;AACF,CAAC;AACD,IAAM,IAAI,aAAa;AAwBvB,SAAS,KAAK,EAAE,MAAM,SAAS,GAA8C;AAC3E,QAAM,MAAY,aAAsB,IAAI;AAC5C,QAAM,CAAC,MAAM,OAAO,IAAU,eAAS,KAAK;AAC5C,EAAM,gBAAU,MAAM;AACpB,UAAM,OAAO,IAAI;AACjB,QAAI,CAAC,KAAK,SAAS,CAAC,QAAQ,OAAO,WAAW,kCAAkC,EAAE,QAAS;AAC3F,UAAM,KAAK,IAAI,qBAAqB,CAAC,CAAC,KAAK,MAAM,QAAQ,QAAQ,OAAO,cAAc,CAAC,GAAG,EAAE,YAAY,QAAQ,CAAC;AACjH,OAAG,QAAQ,IAAI;AACf,WAAO,MAAM,GAAG,WAAW;AAAA,EAC7B,GAAG,CAAC,KAAK,KAAK,CAAC;AACf,SACE,oBAAC,QAAG,KAAU,WAAW,EAAE,KAAK,GAAG,iBAAe,WAAW,KAAK,QAAW,cAAY,KAAK,SAAS,YACrG,+BAAC,YAAO,WAAU,qBAChB;AAAA,wBAAC,SAAI,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,SAAQ,QAAO,UAAS,SAAQ,WAAW,EAAE,MAAM,GAAG;AAAA,IACxF,QAAQ,KAAK,SACZ,qBAAC,WAAM,WAAW,EAAE,MAAM,GAAG,QAAQ,KAAK,KAAK,UAAQ,MAAC,OAAK,MAAC,MAAI,MAAC,aAAW,MAAC,SAAQ,QAAO,eAAW,MAAC,UAAU,IACjH;AAAA,WAAK,MAAM,QAAQ,oBAAC,YAAO,KAAK,KAAK,MAAM,MAAM,MAAK,cAAa;AAAA,MACnE,KAAK,MAAM,OAAO,oBAAC,YAAO,KAAK,KAAK,MAAM,KAAK,MAAK,aAAY;AAAA,OACnE;AAAA,IAED,KAAK,WAAW,oBAAC,gBAAW,WAAW,EAAE,QAAQ,GAAI,eAAK,SAAQ;AAAA,KACrE,GACF;AAEJ;AAGO,SAAS,aAAa,EAAE,OAAO,OAAO,WAAW,GAAG,MAAM,GAAsB;AACrF,SACE,oBAAC,QAAG,cAAY,OAAO,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAC1D,gBAAM,IAAI,CAAC,MAAM,MAChB,oBAAC,QAAmB,MAAY,UAAU,MAAM,KAAK,MAAM,SAAS,KAAzD,KAAK,EAAuD,CACxE,GACH;AAEJ;","names":[]}
@@ -0,0 +1,124 @@
1
+ import * as tailwind_variants from 'tailwind-variants';
2
+ import * as React from 'react';
3
+
4
+ declare const openingHours: tailwind_variants.TVReturnType<{
5
+ [key: string]: {
6
+ [key: string]: tailwind_variants.ClassValue | {
7
+ root?: tailwind_variants.ClassValue;
8
+ summary?: tailwind_variants.ClassValue;
9
+ dot?: tailwind_variants.ClassValue;
10
+ status?: tailwind_variants.ClassValue;
11
+ state?: tailwind_variants.ClassValue;
12
+ detail?: tailwind_variants.ClassValue;
13
+ today?: tailwind_variants.ClassValue;
14
+ chevron?: tailwind_variants.ClassValue;
15
+ list?: tailwind_variants.ClassValue;
16
+ row?: tailwind_variants.ClassValue;
17
+ day?: tailwind_variants.ClassValue;
18
+ hours?: tailwind_variants.ClassValue;
19
+ };
20
+ };
21
+ } | {
22
+ [x: string]: {
23
+ [x: string]: tailwind_variants.ClassValue | {
24
+ root?: tailwind_variants.ClassValue;
25
+ summary?: tailwind_variants.ClassValue;
26
+ dot?: tailwind_variants.ClassValue;
27
+ status?: tailwind_variants.ClassValue;
28
+ state?: tailwind_variants.ClassValue;
29
+ detail?: tailwind_variants.ClassValue;
30
+ today?: tailwind_variants.ClassValue;
31
+ chevron?: tailwind_variants.ClassValue;
32
+ list?: tailwind_variants.ClassValue;
33
+ row?: tailwind_variants.ClassValue;
34
+ day?: tailwind_variants.ClassValue;
35
+ hours?: tailwind_variants.ClassValue;
36
+ };
37
+ };
38
+ } | {}, {
39
+ root: string;
40
+ summary: string;
41
+ dot: string;
42
+ status: string;
43
+ state: string;
44
+ detail: string;
45
+ today: string;
46
+ chevron: string;
47
+ list: string;
48
+ row: string;
49
+ day: string;
50
+ hours: string;
51
+ }, undefined, {
52
+ [key: string]: {
53
+ [key: string]: tailwind_variants.ClassValue | {
54
+ root?: tailwind_variants.ClassValue;
55
+ summary?: tailwind_variants.ClassValue;
56
+ dot?: tailwind_variants.ClassValue;
57
+ status?: tailwind_variants.ClassValue;
58
+ state?: tailwind_variants.ClassValue;
59
+ detail?: tailwind_variants.ClassValue;
60
+ today?: tailwind_variants.ClassValue;
61
+ chevron?: tailwind_variants.ClassValue;
62
+ list?: tailwind_variants.ClassValue;
63
+ row?: tailwind_variants.ClassValue;
64
+ day?: tailwind_variants.ClassValue;
65
+ hours?: tailwind_variants.ClassValue;
66
+ };
67
+ };
68
+ } | {}, {
69
+ root: string;
70
+ summary: string;
71
+ dot: string;
72
+ status: string;
73
+ state: string;
74
+ detail: string;
75
+ today: string;
76
+ chevron: string;
77
+ list: string;
78
+ row: string;
79
+ day: string;
80
+ hours: string;
81
+ }, tailwind_variants.TVReturnTypeLike<unknown, {
82
+ root: string;
83
+ summary: string;
84
+ dot: string;
85
+ status: string;
86
+ state: string;
87
+ detail: string;
88
+ today: string;
89
+ chevron: string;
90
+ list: string;
91
+ row: string;
92
+ day: string;
93
+ hours: string;
94
+ }>>;
95
+ type OpeningDay = {
96
+ /** A stable id (`mon`, `1`). */
97
+ id: string;
98
+ /** The day's name, translated (`Lundi`). */
99
+ label: string;
100
+ /** The day's hours, formatted by the app (`8 h – 12 h, 13 h – 17 h`); the app's word for closed when there are none. */
101
+ hours: string;
102
+ };
103
+ type OpeningStatus = {
104
+ /** Open at this moment. */
105
+ open: boolean;
106
+ /** The state in words (`Open now`, `Closed`). */
107
+ label: string;
108
+ /** What follows (`closes at 5 pm`, `opens tomorrow at 8 am`). */
109
+ detail?: string;
110
+ };
111
+ type OpeningHoursProps = Omit<React.ComponentProps<"details">, "children"> & {
112
+ /** The week, in reading order. */
113
+ days: readonly OpeningDay[];
114
+ /** The id of today's day: its row is marked (`aria-current="date"`) and its hours show on the closed row. */
115
+ today?: string;
116
+ /** Open or closed right now, in words. */
117
+ status: OpeningStatus;
118
+ /** The name of the list (`Hours`), passed translated. */
119
+ label: string;
120
+ };
121
+ /** The weekly hours in one row — open now, closes at… — that unfolds into the week, today highlighted. */
122
+ declare function OpeningHours({ days, today, status, label, className, ...props }: OpeningHoursProps): React.JSX.Element;
123
+
124
+ export { type OpeningDay, OpeningHours, type OpeningHoursProps, type OpeningStatus, openingHours };
@@ -0,0 +1,48 @@
1
+ import {
2
+ ChevronGlyph
3
+ } from "./chunk-XCBVFMNV.js";
4
+
5
+ // src/opening-hours/opening-hours.tsx
6
+ import { tv } from "tailwind-variants";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ var openingHours = tv({
9
+ slots: {
10
+ root: "group/hours rounded-xl border border-border-default bg-surface-1 text-fg",
11
+ summary: "flex min-h-14 cursor-pointer list-none items-center gap-3 rounded-xl px-4 py-3 outline-hidden marker:hidden focus-visible:ring-2 focus-visible:ring-ring [&::-webkit-details-marker]:hidden",
12
+ dot: "h-2.5 w-2.5 shrink-0 rounded-full bg-fg-muted data-[open=true]:bg-success data-[open=true]:motion-safe:animate-pulse",
13
+ status: "flex min-w-0 flex-1 flex-col leading-tight",
14
+ state: "text-sm font-bold text-fg",
15
+ detail: "text-xs text-fg-secondary",
16
+ today: "hidden shrink-0 text-sm tabular-nums text-fg-secondary sm:block",
17
+ chevron: "h-4 w-4 shrink-0 text-fg-secondary transition-transform group-open/hours:rotate-180 motion-reduce:transition-none",
18
+ list: "m-0 flex list-none flex-col gap-0.5 border-t border-border-subtle p-2 sm:p-3",
19
+ row: "flex items-baseline justify-between gap-4 rounded-lg px-2 py-1.5 text-sm text-fg-secondary data-[today]:bg-accent-soft data-[today]:font-bold data-[today]:text-fg",
20
+ day: "shrink-0",
21
+ hours: "text-right tabular-nums"
22
+ }
23
+ });
24
+ var s = openingHours();
25
+ function OpeningHours({ days, today, status, label, className, ...props }) {
26
+ const todayHours = days.find((d) => d.id === today)?.hours;
27
+ return /* @__PURE__ */ jsxs("details", { className: s.root({ className }), ...props, children: [
28
+ /* @__PURE__ */ jsxs("summary", { className: s.summary(), children: [
29
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, "data-open": status.open, className: s.dot() }),
30
+ /* @__PURE__ */ jsxs("span", { className: s.status(), children: [
31
+ /* @__PURE__ */ jsx("span", { className: s.state(), children: status.label }),
32
+ status.detail && /* @__PURE__ */ jsx("span", { className: s.detail(), children: status.detail })
33
+ ] }),
34
+ todayHours && /* @__PURE__ */ jsx("span", { className: s.today(), children: todayHours }),
35
+ /* @__PURE__ */ jsx(ChevronGlyph, { className: s.chevron() }),
36
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: label })
37
+ ] }),
38
+ /* @__PURE__ */ jsx("ul", { className: s.list(), "aria-label": label, children: days.map((day) => /* @__PURE__ */ jsxs("li", { className: s.row(), "data-today": day.id === today ? "" : void 0, "aria-current": day.id === today ? "date" : void 0, children: [
39
+ /* @__PURE__ */ jsx("span", { className: s.day(), children: day.label }),
40
+ /* @__PURE__ */ jsx("span", { className: s.hours(), children: day.hours })
41
+ ] }, day.id)) })
42
+ ] });
43
+ }
44
+ export {
45
+ OpeningHours,
46
+ openingHours
47
+ };
48
+ //# sourceMappingURL=opening-hours.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/opening-hours/opening-hours.tsx"],"sourcesContent":["// Server-safe: no hook, no context (a native <details>). A shop's weekly hours in one quiet row — « Open now · closes at 5 pm »\n// and today's hours — that unfolds into the whole week with today marked. The app computes the status and formats the\n// times (the shop's zone and the reader's locale are its business); this block only lays them out.\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { ChevronGlyph } from \"../glyphs\";\n\nexport const openingHours = tv({\n slots: {\n root: \"group/hours rounded-xl border border-border-default bg-surface-1 text-fg\",\n summary:\n \"flex min-h-14 cursor-pointer list-none items-center gap-3 rounded-xl px-4 py-3 outline-hidden marker:hidden focus-visible:ring-2 focus-visible:ring-ring [&::-webkit-details-marker]:hidden\",\n dot: \"h-2.5 w-2.5 shrink-0 rounded-full bg-fg-muted data-[open=true]:bg-success data-[open=true]:motion-safe:animate-pulse\",\n status: \"flex min-w-0 flex-1 flex-col leading-tight\",\n state: \"text-sm font-bold text-fg\",\n detail: \"text-xs text-fg-secondary\",\n today: \"hidden shrink-0 text-sm tabular-nums text-fg-secondary sm:block\",\n chevron: \"h-4 w-4 shrink-0 text-fg-secondary transition-transform group-open/hours:rotate-180 motion-reduce:transition-none\",\n list: \"m-0 flex list-none flex-col gap-0.5 border-t border-border-subtle p-2 sm:p-3\",\n row: \"flex items-baseline justify-between gap-4 rounded-lg px-2 py-1.5 text-sm text-fg-secondary data-[today]:bg-accent-soft data-[today]:font-bold data-[today]:text-fg\",\n day: \"shrink-0\",\n hours: \"text-right tabular-nums\",\n },\n});\nconst s = openingHours();\n\nexport type OpeningDay = {\n /** A stable id (`mon`, `1`). */\n id: string;\n /** The day's name, translated (`Lundi`). */\n label: string;\n /** The day's hours, formatted by the app (`8 h – 12 h, 13 h – 17 h`); the app's word for closed when there are none. */\n hours: string;\n};\n\nexport type OpeningStatus = {\n /** Open at this moment. */\n open: boolean;\n /** The state in words (`Open now`, `Closed`). */\n label: string;\n /** What follows (`closes at 5 pm`, `opens tomorrow at 8 am`). */\n detail?: string;\n};\n\nexport type OpeningHoursProps = Omit<React.ComponentProps<\"details\">, \"children\"> & {\n /** The week, in reading order. */\n days: readonly OpeningDay[];\n /** The id of today's day: its row is marked (`aria-current=\"date\"`) and its hours show on the closed row. */\n today?: string;\n /** Open or closed right now, in words. */\n status: OpeningStatus;\n /** The name of the list (`Hours`), passed translated. */\n label: string;\n};\n\n/** The weekly hours in one row — open now, closes at… — that unfolds into the week, today highlighted. */\nexport function OpeningHours({ days, today, status, label, className, ...props }: OpeningHoursProps) {\n const todayHours = days.find((d) => d.id === today)?.hours;\n return (\n <details className={s.root({ className })} {...props}>\n <summary className={s.summary()}>\n <span aria-hidden data-open={status.open} className={s.dot()} />\n <span className={s.status()}>\n <span className={s.state()}>{status.label}</span>\n {status.detail && <span className={s.detail()}>{status.detail}</span>}\n </span>\n {todayHours && <span className={s.today()}>{todayHours}</span>}\n <ChevronGlyph className={s.chevron()} />\n <span className=\"sr-only\">{label}</span>\n </summary>\n <ul className={s.list()} aria-label={label}>\n {days.map((day) => (\n <li key={day.id} className={s.row()} data-today={day.id === today ? \"\" : undefined} aria-current={day.id === today ? \"date\" : undefined}>\n <span className={s.day()}>{day.label}</span>\n <span className={s.hours()}>{day.hours}</span>\n </li>\n ))}\n </ul>\n </details>\n );\n}\n"],"mappings":";;;;;AAIA,SAAS,UAAU;AA0DX,cACA,YADA;AAtDD,IAAM,eAAe,GAAG;AAAA,EAC7B,OAAO;AAAA,IACL,MAAM;AAAA,IACN,SACE;AAAA,IACF,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,SAAS;AAAA,IACT,MAAM;AAAA,IACN,KAAK;AAAA,IACL,KAAK;AAAA,IACL,OAAO;AAAA,EACT;AACF,CAAC;AACD,IAAM,IAAI,aAAa;AAgChB,SAAS,aAAa,EAAE,MAAM,OAAO,QAAQ,OAAO,WAAW,GAAG,MAAM,GAAsB;AACnG,QAAM,aAAa,KAAK,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK,GAAG;AACrD,SACE,qBAAC,aAAQ,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAC7C;AAAA,yBAAC,aAAQ,WAAW,EAAE,QAAQ,GAC5B;AAAA,0BAAC,UAAK,eAAW,MAAC,aAAW,OAAO,MAAM,WAAW,EAAE,IAAI,GAAG;AAAA,MAC9D,qBAAC,UAAK,WAAW,EAAE,OAAO,GACxB;AAAA,4BAAC,UAAK,WAAW,EAAE,MAAM,GAAI,iBAAO,OAAM;AAAA,QACzC,OAAO,UAAU,oBAAC,UAAK,WAAW,EAAE,OAAO,GAAI,iBAAO,QAAO;AAAA,SAChE;AAAA,MACC,cAAc,oBAAC,UAAK,WAAW,EAAE,MAAM,GAAI,sBAAW;AAAA,MACvD,oBAAC,gBAAa,WAAW,EAAE,QAAQ,GAAG;AAAA,MACtC,oBAAC,UAAK,WAAU,WAAW,iBAAM;AAAA,OACnC;AAAA,IACA,oBAAC,QAAG,WAAW,EAAE,KAAK,GAAG,cAAY,OAClC,eAAK,IAAI,CAAC,QACT,qBAAC,QAAgB,WAAW,EAAE,IAAI,GAAG,cAAY,IAAI,OAAO,QAAQ,KAAK,QAAW,gBAAc,IAAI,OAAO,QAAQ,SAAS,QAC5H;AAAA,0BAAC,UAAK,WAAW,EAAE,IAAI,GAAI,cAAI,OAAM;AAAA,MACrC,oBAAC,UAAK,WAAW,EAAE,MAAM,GAAI,cAAI,OAAM;AAAA,SAFhC,IAAI,EAGb,CACD,GACH;AAAA,KACF;AAEJ;","names":[]}
package/dist/rail-nav.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  ChevronGlyph
4
- } from "./chunk-AFY35UCB.js";
4
+ } from "./chunk-P7GZR5CU.js";
5
5
  import {
6
6
  cn
7
7
  } from "./chunk-WU4VLSEA.js";