@krizaka/ui 2.0.0-beta.2 → 2.0.0-beta.4

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 (187) hide show
  1. package/README.md +98 -6
  2. package/dist/alert.d.ts +2 -0
  3. package/dist/alert.js.map +1 -1
  4. package/dist/avatar.d.ts +5 -0
  5. package/dist/avatar.js.map +1 -1
  6. package/dist/badge.d.ts +12 -0
  7. package/dist/badge.js.map +1 -1
  8. package/dist/{button-G5qY4qSY.d.ts → button-8La7l0V4.d.ts} +15 -0
  9. package/dist/button.d.ts +19 -0
  10. package/dist/button.js.map +1 -1
  11. package/dist/card.d.ts +24 -1
  12. package/dist/card.js.map +1 -1
  13. package/dist/chip.d.ts +23 -0
  14. package/dist/chip.js.map +1 -1
  15. package/dist/{chunk-5FRYKFTO.js → chunk-3X5MVH54.js} +2 -2
  16. package/dist/chunk-3X5MVH54.js.map +1 -0
  17. package/dist/{chunk-QRG5RYEI.js → chunk-ZUD4U22H.js} +1 -1
  18. package/dist/chunk-ZUD4U22H.js.map +1 -0
  19. package/dist/command.d.ts +4 -1
  20. package/dist/command.js +2 -2
  21. package/dist/command.js.map +1 -1
  22. package/dist/confirm-button.d.ts +1 -1
  23. package/dist/confirm-button.js +1 -1
  24. package/dist/countdown.d.ts +3 -0
  25. package/dist/countdown.js.map +1 -1
  26. package/dist/{dialog-DGBY2grk.d.ts → dialog-GQ4Nvuyf.d.ts} +10 -0
  27. package/dist/dialog.d.ts +9 -1
  28. package/dist/dialog.js +2 -2
  29. package/dist/dialog.js.map +1 -1
  30. package/dist/dropdown-menu.d.ts +1 -0
  31. package/dist/dropdown-menu.js.map +1 -1
  32. package/dist/empty-state.d.ts +2 -0
  33. package/dist/empty-state.js.map +1 -1
  34. package/dist/kbd.d.ts +7 -1
  35. package/dist/kbd.js.map +1 -1
  36. package/dist/native.d.ts +471 -3
  37. package/dist/native.js +1005 -36
  38. package/dist/native.js.map +1 -1
  39. package/dist/page-header.d.ts +2 -0
  40. package/dist/page-header.js.map +1 -1
  41. package/dist/progress.d.ts +5 -0
  42. package/dist/progress.js.map +1 -1
  43. package/dist/skeleton.d.ts +7 -1
  44. package/dist/skeleton.js.map +1 -1
  45. package/dist/slider.d.ts +2 -0
  46. package/dist/slider.js.map +1 -1
  47. package/dist/spinner.d.ts +5 -0
  48. package/dist/spinner.js.map +1 -1
  49. package/dist/stat.d.ts +2 -0
  50. package/dist/stat.js.map +1 -1
  51. package/dist/switch.d.ts +7 -3
  52. package/dist/switch.js.map +1 -1
  53. package/dist/tabs.d.ts +4 -1
  54. package/dist/tabs.js.map +1 -1
  55. package/dist/theme.d.ts +10 -2
  56. package/dist/theme.js +4 -2
  57. package/dist/theme.js.map +1 -1
  58. package/dist/tooltip.d.ts +3 -0
  59. package/dist/tooltip.js.map +1 -1
  60. package/package.json +31 -8
  61. package/registry/alert.json +59 -0
  62. package/registry/avatar.json +114 -0
  63. package/registry/badge.json +59 -0
  64. package/registry/button.json +115 -0
  65. package/registry/card.json +154 -0
  66. package/registry/checkbox.json +46 -0
  67. package/registry/chip.json +164 -0
  68. package/registry/cn.json +21 -0
  69. package/registry/command.json +162 -0
  70. package/registry/confirm-button.json +104 -0
  71. package/registry/countdown.json +84 -0
  72. package/registry/demos/alert.d.ts +5 -0
  73. package/registry/demos/alert.js +12 -0
  74. package/registry/demos/alert.tsx +15 -0
  75. package/registry/demos/avatar.d.ts +5 -0
  76. package/registry/demos/avatar.js +14 -0
  77. package/registry/demos/avatar.tsx +13 -0
  78. package/registry/demos/badge.d.ts +5 -0
  79. package/registry/demos/badge.js +11 -0
  80. package/registry/demos/badge.tsx +5 -0
  81. package/registry/demos/button.d.ts +5 -0
  82. package/registry/demos/button.js +11 -0
  83. package/registry/demos/button.tsx +5 -0
  84. package/registry/demos/card.d.ts +5 -0
  85. package/registry/demos/card.js +30 -0
  86. package/registry/demos/card.tsx +37 -0
  87. package/registry/demos/checkbox.d.ts +5 -0
  88. package/registry/demos/checkbox.js +11 -0
  89. package/registry/demos/checkbox.tsx +5 -0
  90. package/registry/demos/chip.d.ts +5 -0
  91. package/registry/demos/chip.js +15 -0
  92. package/registry/demos/chip.tsx +11 -0
  93. package/registry/demos/cn.d.ts +7 -0
  94. package/registry/demos/cn.js +17 -0
  95. package/registry/demos/cn.tsx +9 -0
  96. package/registry/demos/command.d.ts +5 -0
  97. package/registry/demos/command.js +32 -0
  98. package/registry/demos/command.tsx +28 -0
  99. package/registry/demos/confirm-button.d.ts +5 -0
  100. package/registry/demos/confirm-button.js +12 -0
  101. package/registry/demos/confirm-button.tsx +13 -0
  102. package/registry/demos/countdown.d.ts +5 -0
  103. package/registry/demos/countdown.js +13 -0
  104. package/registry/demos/countdown.tsx +10 -0
  105. package/registry/demos/dialog.d.ts +7 -0
  106. package/registry/demos/dialog.js +29 -0
  107. package/registry/demos/dialog.tsx +31 -0
  108. package/registry/demos/dropdown-menu.d.ts +7 -0
  109. package/registry/demos/dropdown-menu.js +36 -0
  110. package/registry/demos/dropdown-menu.tsx +27 -0
  111. package/registry/demos/empty-state.d.ts +5 -0
  112. package/registry/demos/empty-state.js +15 -0
  113. package/registry/demos/empty-state.tsx +12 -0
  114. package/registry/demos/field.d.ts +5 -0
  115. package/registry/demos/field.js +15 -0
  116. package/registry/demos/field.tsx +11 -0
  117. package/registry/demos/kbd.d.ts +5 -0
  118. package/registry/demos/kbd.js +11 -0
  119. package/registry/demos/kbd.tsx +5 -0
  120. package/registry/demos/page-header.d.ts +5 -0
  121. package/registry/demos/page-header.js +11 -0
  122. package/registry/demos/page-header.tsx +5 -0
  123. package/registry/demos/popover.d.ts +7 -0
  124. package/registry/demos/popover.js +25 -0
  125. package/registry/demos/popover.tsx +31 -0
  126. package/registry/demos/progress.d.ts +5 -0
  127. package/registry/demos/progress.js +11 -0
  128. package/registry/demos/progress.tsx +5 -0
  129. package/registry/demos/radio-group.d.ts +5 -0
  130. package/registry/demos/radio-group.js +16 -0
  131. package/registry/demos/radio-group.tsx +14 -0
  132. package/registry/demos/separator.d.ts +5 -0
  133. package/registry/demos/separator.js +15 -0
  134. package/registry/demos/separator.tsx +11 -0
  135. package/registry/demos/skeleton.d.ts +5 -0
  136. package/registry/demos/skeleton.js +20 -0
  137. package/registry/demos/skeleton.tsx +16 -0
  138. package/registry/demos/slider.d.ts +5 -0
  139. package/registry/demos/slider.js +11 -0
  140. package/registry/demos/slider.tsx +5 -0
  141. package/registry/demos/slot.d.ts +5 -0
  142. package/registry/demos/slot.js +14 -0
  143. package/registry/demos/slot.tsx +13 -0
  144. package/registry/demos/spinner.d.ts +5 -0
  145. package/registry/demos/spinner.js +11 -0
  146. package/registry/demos/spinner.tsx +5 -0
  147. package/registry/demos/stat.d.ts +5 -0
  148. package/registry/demos/stat.js +11 -0
  149. package/registry/demos/stat.tsx +5 -0
  150. package/registry/demos/switch.d.ts +5 -0
  151. package/registry/demos/switch.js +11 -0
  152. package/registry/demos/switch.tsx +5 -0
  153. package/registry/demos/tabs.d.ts +5 -0
  154. package/registry/demos/tabs.js +22 -0
  155. package/registry/demos/tabs.tsx +28 -0
  156. package/registry/demos/theme.d.ts +5 -0
  157. package/registry/demos/theme.js +11 -0
  158. package/registry/demos/theme.tsx +9 -0
  159. package/registry/demos/toast.d.ts +8 -0
  160. package/registry/demos/toast.js +29 -0
  161. package/registry/demos/toast.tsx +31 -0
  162. package/registry/demos/tooltip.d.ts +7 -0
  163. package/registry/demos/tooltip.js +15 -0
  164. package/registry/demos/tooltip.tsx +15 -0
  165. package/registry/dialog.json +218 -0
  166. package/registry/dropdown-menu.json +63 -0
  167. package/registry/empty-state.json +59 -0
  168. package/registry/field.json +66 -0
  169. package/registry/index.json +320 -0
  170. package/registry/kbd.json +38 -0
  171. package/registry/page-header.json +66 -0
  172. package/registry/popover.json +44 -0
  173. package/registry/progress.json +80 -0
  174. package/registry/radio-group.json +64 -0
  175. package/registry/separator.json +25 -0
  176. package/registry/skeleton.json +38 -0
  177. package/registry/slider.json +95 -0
  178. package/registry/slot.json +31 -0
  179. package/registry/spinner.json +45 -0
  180. package/registry/stat.json +66 -0
  181. package/registry/switch.json +53 -0
  182. package/registry/tabs.json +44 -0
  183. package/registry/theme.json +78 -0
  184. package/registry/toast.json +54 -0
  185. package/registry/tooltip.json +91 -0
  186. package/dist/chunk-5FRYKFTO.js.map +0 -1
  187. package/dist/chunk-QRG5RYEI.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/button/button.tsx"],"sourcesContent":["// Server-safe: no hook, no context. `buttonVariants` styles a <Link> or a Server Component without the component.\nimport { Slot } from \"radix-ui\";\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nexport const buttonVariants = tv({\n base:\n \"inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap font-semibold transition-all \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-surface-0 \" +\n \"disabled:pointer-events-none disabled:opacity-40 data-loading:cursor-progress active:scale-[0.98]\",\n variants: {\n variant: {\n primary: \"bg-accent text-on-accent shadow-sm hover:bg-accent-hover\",\n secondary: \"border border-border-default bg-surface-2 text-fg hover:border-border-strong hover:bg-surface-3\",\n outline: \"border border-border-default bg-transparent text-fg hover:border-accent hover:text-accent\",\n ghost: \"text-fg-secondary hover:bg-surface-2 hover:text-fg\",\n // The danger token is invariant and too light for small text on a light surface (3.6:1): the label stays a\n // text role, the border and the tint carry the danger.\n danger: \"border border-danger/50 bg-danger/10 text-fg hover:border-danger hover:bg-danger/20\",\n },\n size: { sm: \"h-8 px-3 text-xs\", md: \"h-10 px-4 text-sm\", lg: \"h-12 px-6 text-sm\", icon: \"h-10 w-10\" },\n shape: { rounded: \"rounded-lg\", pill: \"rounded-full\" },\n },\n defaultVariants: { variant: \"secondary\", size: \"md\", shape: \"rounded\" },\n});\n\nexport type ButtonVariants = VariantProps<typeof buttonVariants>;\n\nexport type ButtonProps = React.ComponentProps<\"button\"> &\n ButtonVariants & {\n /**\n * The look: `primary` (the accent), `secondary` (a raised surface), `outline`, `ghost`, `danger`.\n * @default \"secondary\"\n */\n variant?: ButtonVariants[\"variant\"];\n /**\n * sm · md · lg, or `icon` (a square).\n * @default \"md\"\n */\n size?: ButtonVariants[\"size\"];\n /**\n * rounded · pill.\n * @default \"rounded\"\n */\n shape?: ButtonVariants[\"shape\"];\n /** Renders the child (e.g. a <Link>) instead of the <button>, with props, classes and ref merged. */\n asChild?: boolean;\n /** Disables and signals the wait (aria-busy, data-loading) — the product adds a spinner if it wants one. */\n loading?: boolean;\n };\n\nexport function Button({ asChild, loading, variant, size, shape, className, disabled, ...props }: ButtonProps) {\n const Comp = asChild ? Slot.Root : \"button\";\n return (\n <Comp\n type={asChild ? undefined : \"button\"}\n aria-busy={loading || undefined}\n data-loading={loading ? \"\" : undefined}\n data-variant={variant ?? \"secondary\"}\n disabled={asChild ? undefined : disabled || loading}\n aria-disabled={asChild && (disabled || loading) ? true : undefined}\n className={buttonVariants({ variant, size, shape, className })}\n {...props}\n />\n );\n}\n\nexport type IconButtonProps = Omit<ButtonProps, \"size\"> & {\n /** The accessible name (and tooltip) of the button — required, passed translated. */\n label: string;\n /**\n * sm · md · lg, or `icon` (a square).\n * @default \"icon\"\n */\n size?: ButtonProps[\"size\"];\n};\n\n/** An icon-only button: `label` is required, it is its accessible name. */\nexport function IconButton({ label, size = \"icon\", ...props }: IconButtonProps) {\n return <Button aria-label={label} title={label} size={size} {...props} />;\n}\n"],"mappings":";;;AACA,SAAS,YAAY;AAErB,SAAS,UAA6B;AAmDlC;AAjDG,IAAM,iBAAiB,GAAG;AAAA,EAC/B,MACE;AAAA,EAGF,UAAU;AAAA,IACR,SAAS;AAAA,MACP,SAAS;AAAA,MACT,WAAW;AAAA,MACX,SAAS;AAAA,MACT,OAAO;AAAA;AAAA;AAAA,MAGP,QAAQ;AAAA,IACV;AAAA,IACA,MAAM,EAAE,IAAI,oBAAoB,IAAI,qBAAqB,IAAI,qBAAqB,MAAM,YAAY;AAAA,IACpG,OAAO,EAAE,SAAS,cAAc,MAAM,eAAe;AAAA,EACvD;AAAA,EACA,iBAAiB,EAAE,SAAS,aAAa,MAAM,MAAM,OAAO,UAAU;AACxE,CAAC;AA2BM,SAAS,OAAO,EAAE,SAAS,SAAS,SAAS,MAAM,OAAO,WAAW,UAAU,GAAG,MAAM,GAAgB;AAC7G,QAAM,OAAO,UAAU,KAAK,OAAO;AACnC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,UAAU,SAAY;AAAA,MAC5B,aAAW,WAAW;AAAA,MACtB,gBAAc,UAAU,KAAK;AAAA,MAC7B,gBAAc,WAAW;AAAA,MACzB,UAAU,UAAU,SAAY,YAAY;AAAA,MAC5C,iBAAe,YAAY,YAAY,WAAW,OAAO;AAAA,MACzD,WAAW,eAAe,EAAE,SAAS,MAAM,OAAO,UAAU,CAAC;AAAA,MAC5D,GAAG;AAAA;AAAA,EACN;AAEJ;AAaO,SAAS,WAAW,EAAE,OAAO,OAAO,QAAQ,GAAG,MAAM,GAAoB;AAC9E,SAAO,oBAAC,UAAO,cAAY,OAAO,OAAO,OAAO,MAAa,GAAG,OAAO;AACzE;","names":[]}
package/dist/command.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as tailwind_variants from 'tailwind-variants';
2
2
  import { Command as Command$1 } from 'cmdk';
3
3
  import * as React from 'react';
4
- import { D as DialogContentProps } from './dialog-DGBY2grk.js';
4
+ import { D as DialogContentProps } from './dialog-GQ4Nvuyf.js';
5
5
  import 'radix-ui';
6
6
 
7
7
  declare const command: tailwind_variants.TVReturnType<{
@@ -137,8 +137,11 @@ declare const Command: {
137
137
  Shortcut: typeof CommandShortcut;
138
138
  };
139
139
  type CommandDialogProps = Omit<CommandRootProps, "title"> & {
140
+ /** Open or closed (controlled), with `onOpenChange`. */
140
141
  open?: boolean;
142
+ /** Open at first, uncontrolled. */
141
143
  defaultOpen?: boolean;
144
+ /** Called when it opens or closes (Escape, a click outside, a shortcut of the product). */
142
145
  onOpenChange?: (open: boolean) => void;
143
146
  /** Under the palette, inside the dialog: shortcuts, a "see all results" link. */
144
147
  footer?: React.ReactNode;
package/dist/command.js CHANGED
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import {
3
3
  DialogContent
4
- } from "./chunk-5FRYKFTO.js";
5
- import "./chunk-QRG5RYEI.js";
4
+ } from "./chunk-3X5MVH54.js";
5
+ import "./chunk-ZUD4U22H.js";
6
6
  import {
7
7
  cn
8
8
  } from "./chunk-5AXLA4LK.js";
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/command/command.tsx"],"sourcesContent":["// Client. A command palette on cmdk: the combobox / listbox roles, the active option (aria-activedescendant), the\n// arrows, Home / End, Enter, and the filtering (turn it off with `shouldFilter={false}` when the server searches).\n// `CommandDialog` puts it in the platform's Dialog. Words arrive as props.\nimport { Command as CommandPrimitive } from \"cmdk\";\nimport { Dialog as DialogPrimitive } from \"radix-ui\";\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { cn } from \"../cn\";\nimport { DialogContent, type DialogContentProps } from \"../dialog/dialog\";\n\nexport const command = tv({\n slots: {\n root: \"flex h-full w-full flex-col overflow-hidden bg-surface-1 text-fg\",\n inputWrap: \"flex items-center gap-3 border-b border-border-default px-4\",\n icon: \"h-5 w-5 shrink-0 text-fg-secondary\",\n input:\n \"h-13 w-full min-w-0 flex-1 bg-transparent text-sm text-fg outline-hidden placeholder:text-fg-muted disabled:cursor-not-allowed disabled:opacity-50 sm:text-base\",\n list: \"max-h-[min(60dvh,26rem)] scroll-py-2 overflow-y-auto overscroll-contain p-2\",\n empty: \"px-3 py-8 text-center text-sm text-fg-secondary\",\n loading: \"px-3 py-6 text-center text-sm text-fg-secondary\",\n group:\n \"[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:pb-1.5 [&_[cmdk-group-heading]]:pt-3 [&_[cmdk-group-heading]]:text-xs \" +\n \"[&_[cmdk-group-heading]]:font-semibold [&_[cmdk-group-heading]]:uppercase [&_[cmdk-group-heading]]:tracking-wider [&_[cmdk-group-heading]]:text-fg-secondary\",\n item:\n \"relative flex cursor-pointer select-none items-center gap-3 rounded-lg px-3 py-2.5 text-sm text-fg outline-hidden transition-colors \" +\n \"before:absolute before:inset-y-2 before:left-0 before:w-0.5 before:rounded-full before:bg-transparent \" +\n \"data-[selected=true]:bg-surface-2 data-[selected=true]:before:bg-accent data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-40\",\n separator: \"-mx-2 my-1 h-px bg-border-subtle\",\n shortcut: \"ml-auto text-xs tracking-widest text-fg-secondary\",\n },\n});\nconst s = command();\n\nfunction SearchIcon({ className }: { className?: string }) {\n return (\n <svg viewBox=\"0 0 24 24\" className={className} fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <circle cx=\"11\" cy=\"11\" r=\"7\" />\n <path d=\"m20 20-3.5-3.5\" />\n </svg>\n );\n}\n\nexport type CommandRootProps = React.ComponentProps<typeof CommandPrimitive> & {\n /** The accessible name of the palette — passed translated (\"Search\", \"Commands\"). */\n label: string;\n};\n\n/** The palette: `value` / `onValueChange` (the active item), `shouldFilter`, `filter`, `loop`. */\nexport function CommandRoot({ className, ...props }: CommandRootProps) {\n return <CommandPrimitive className={s.root({ className })} {...props} />;\n}\n\nexport type CommandInputProps = Omit<React.ComponentProps<typeof CommandPrimitive.Input>, \"placeholder\"> & {\n /** What to type — passed translated. The input is named by the palette's `label`. */\n placeholder: string;\n /** After the input, inside the bar: a spinner, a clear button. */\n trailing?: React.ReactNode;\n};\n\n/** The search field (`value` / `onValueChange` for the query), with a magnifier. */\nexport function CommandInput({ className, placeholder, trailing, ...props }: CommandInputProps) {\n return (\n <div className={s.inputWrap()} cmdk-input-wrapper=\"\">\n <SearchIcon className={s.icon()} />\n <CommandPrimitive.Input placeholder={placeholder} className={s.input({ className })} {...props} />\n {trailing}\n </div>\n );\n}\n\nexport type CommandListProps = React.ComponentProps<typeof CommandPrimitive.List> & {\n /** The accessible name of the list of results — passed translated (\"Suggestions\", \"Results\"). */\n label: string;\n};\n\nexport function CommandList({ className, ...props }: CommandListProps) {\n return <CommandPrimitive.List className={s.list({ className })} {...props} />;\n}\n\nexport type CommandEmptyProps = Omit<React.ComponentProps<typeof CommandPrimitive.Empty>, \"children\"> & {\n /** Shown when nothing matches — passed translated. */\n emptyLabel: React.ReactNode;\n};\n\n/** Shown by cmdk only when no item matches. */\nexport function CommandEmpty({ className, emptyLabel, ...props }: CommandEmptyProps) {\n return (\n <CommandPrimitive.Empty className={s.empty({ className })} {...props}>\n {emptyLabel}\n </CommandPrimitive.Empty>\n );\n}\n\n/** While results load (`label` is announced). */\nexport function CommandLoading({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Loading>) {\n return <CommandPrimitive.Loading className={s.loading({ className })} {...props} />;\n}\n\n/** A group of items under a `heading`. */\nexport function CommandGroup({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Group>) {\n return <CommandPrimitive.Group className={s.group({ className })} {...props} />;\n}\n\n/** An option: `onSelect` on Enter or click, `value` and `keywords` for the filter, `disabled`. */\nexport function CommandItem({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Item>) {\n return <CommandPrimitive.Item className={s.item({ className })} {...props} />;\n}\n\n/** A line between groups. Decorative (`role=\"none\"`): cmdk's own separator is a role a listbox may not hold (axe). */\nexport function CommandSeparator({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div role=\"none\" className={s.separator({ className })} {...props} />;\n}\n\n/** A keyboard hint at the end of an item. */\nexport function CommandShortcut({ className, ...props }: React.ComponentProps<\"span\">) {\n return <span className={s.shortcut({ className })} {...props} />;\n}\n\n/** `Command.Root/Input/List/Empty/Loading/Group/Item/Separator/Shortcut`. */\nexport const Command = {\n Root: CommandRoot,\n Input: CommandInput,\n List: CommandList,\n Empty: CommandEmpty,\n Loading: CommandLoading,\n Group: CommandGroup,\n Item: CommandItem,\n Separator: CommandSeparator,\n Shortcut: CommandShortcut,\n};\n\nexport type CommandDialogProps = Omit<CommandRootProps, \"title\"> & {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Under the palette, inside the dialog: shortcuts, a \"see all results\" link. */\n footer?: React.ReactNode;\n /** Passed to `Dialog.Content`: `size`, `container`, `className` of the dialog. */\n contentProps?: Omit<Extract<DialogContentProps, { hideClose: true }>, \"hideClose\" | \"children\" | \"placement\">;\n};\n\n/**\n * The palette in a dialog (Radix: focus trap, Escape, focus return). The dialog is named by `label`; it has no close\n * button — Escape and a click outside close it — and the input takes the focus when it opens.\n */\nexport function CommandDialog({ open, defaultOpen, onOpenChange, footer, contentProps, label, className, children, ...props }: CommandDialogProps) {\n const { className: contentClassName, ...content } = contentProps ?? {};\n return (\n <DialogPrimitive.Root open={open} defaultOpen={defaultOpen} onOpenChange={onOpenChange}>\n <DialogContent\n hideClose\n size=\"lg\"\n aria-describedby={undefined}\n className={cn(\"top-[12dvh] translate-y-0 sm:top-[14dvh]\", contentClassName)}\n {...content}\n >\n <DialogPrimitive.Title className=\"sr-only\">{label}</DialogPrimitive.Title>\n <CommandRoot label={label} className={className} {...props}>\n {children}\n </CommandRoot>\n {footer}\n </DialogContent>\n </DialogPrimitive.Root>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/command/command.tsx"],"sourcesContent":["// Client. A command palette on cmdk: the combobox / listbox roles, the active option (aria-activedescendant), the\n// arrows, Home / End, Enter, and the filtering (turn it off with `shouldFilter={false}` when the server searches).\n// `CommandDialog` puts it in the platform's Dialog. Words arrive as props.\nimport { Command as CommandPrimitive } from \"cmdk\";\nimport { Dialog as DialogPrimitive } from \"radix-ui\";\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { cn } from \"../cn\";\nimport { DialogContent, type DialogContentProps } from \"../dialog/dialog\";\n\nexport const command = tv({\n slots: {\n root: \"flex h-full w-full flex-col overflow-hidden bg-surface-1 text-fg\",\n inputWrap: \"flex items-center gap-3 border-b border-border-default px-4\",\n icon: \"h-5 w-5 shrink-0 text-fg-secondary\",\n input:\n \"h-13 w-full min-w-0 flex-1 bg-transparent text-sm text-fg outline-hidden placeholder:text-fg-muted disabled:cursor-not-allowed disabled:opacity-50 sm:text-base\",\n list: \"max-h-[min(60dvh,26rem)] scroll-py-2 overflow-y-auto overscroll-contain p-2\",\n empty: \"px-3 py-8 text-center text-sm text-fg-secondary\",\n loading: \"px-3 py-6 text-center text-sm text-fg-secondary\",\n group:\n \"[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:pb-1.5 [&_[cmdk-group-heading]]:pt-3 [&_[cmdk-group-heading]]:text-xs \" +\n \"[&_[cmdk-group-heading]]:font-semibold [&_[cmdk-group-heading]]:uppercase [&_[cmdk-group-heading]]:tracking-wider [&_[cmdk-group-heading]]:text-fg-secondary\",\n item:\n \"relative flex cursor-pointer select-none items-center gap-3 rounded-lg px-3 py-2.5 text-sm text-fg outline-hidden transition-colors \" +\n \"before:absolute before:inset-y-2 before:left-0 before:w-0.5 before:rounded-full before:bg-transparent \" +\n \"data-[selected=true]:bg-surface-2 data-[selected=true]:before:bg-accent data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-40\",\n separator: \"-mx-2 my-1 h-px bg-border-subtle\",\n shortcut: \"ml-auto text-xs tracking-widest text-fg-secondary\",\n },\n});\nconst s = command();\n\nfunction SearchIcon({ className }: { className?: string }) {\n return (\n <svg viewBox=\"0 0 24 24\" className={className} fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <circle cx=\"11\" cy=\"11\" r=\"7\" />\n <path d=\"m20 20-3.5-3.5\" />\n </svg>\n );\n}\n\nexport type CommandRootProps = React.ComponentProps<typeof CommandPrimitive> & {\n /** The accessible name of the palette — passed translated (\"Search\", \"Commands\"). */\n label: string;\n};\n\n/** The palette: `value` / `onValueChange` (the active item), `shouldFilter`, `filter`, `loop`. */\nexport function CommandRoot({ className, ...props }: CommandRootProps) {\n return <CommandPrimitive className={s.root({ className })} {...props} />;\n}\n\nexport type CommandInputProps = Omit<React.ComponentProps<typeof CommandPrimitive.Input>, \"placeholder\"> & {\n /** What to type — passed translated. The input is named by the palette's `label`. */\n placeholder: string;\n /** After the input, inside the bar: a spinner, a clear button. */\n trailing?: React.ReactNode;\n};\n\n/** The search field (`value` / `onValueChange` for the query), with a magnifier. */\nexport function CommandInput({ className, placeholder, trailing, ...props }: CommandInputProps) {\n return (\n <div className={s.inputWrap()} cmdk-input-wrapper=\"\">\n <SearchIcon className={s.icon()} />\n <CommandPrimitive.Input placeholder={placeholder} className={s.input({ className })} {...props} />\n {trailing}\n </div>\n );\n}\n\nexport type CommandListProps = React.ComponentProps<typeof CommandPrimitive.List> & {\n /** The accessible name of the list of results — passed translated (\"Suggestions\", \"Results\"). */\n label: string;\n};\n\nexport function CommandList({ className, ...props }: CommandListProps) {\n return <CommandPrimitive.List className={s.list({ className })} {...props} />;\n}\n\nexport type CommandEmptyProps = Omit<React.ComponentProps<typeof CommandPrimitive.Empty>, \"children\"> & {\n /** Shown when nothing matches — passed translated. */\n emptyLabel: React.ReactNode;\n};\n\n/** Shown by cmdk only when no item matches. */\nexport function CommandEmpty({ className, emptyLabel, ...props }: CommandEmptyProps) {\n return (\n <CommandPrimitive.Empty className={s.empty({ className })} {...props}>\n {emptyLabel}\n </CommandPrimitive.Empty>\n );\n}\n\n/** While results load (`label` is announced). */\nexport function CommandLoading({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Loading>) {\n return <CommandPrimitive.Loading className={s.loading({ className })} {...props} />;\n}\n\n/** A group of items under a `heading`. */\nexport function CommandGroup({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Group>) {\n return <CommandPrimitive.Group className={s.group({ className })} {...props} />;\n}\n\n/** An option: `onSelect` on Enter or click, `value` and `keywords` for the filter, `disabled`. */\nexport function CommandItem({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Item>) {\n return <CommandPrimitive.Item className={s.item({ className })} {...props} />;\n}\n\n/** A line between groups. Decorative (`role=\"none\"`): cmdk's own separator is a role a listbox may not hold (axe). */\nexport function CommandSeparator({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div role=\"none\" className={s.separator({ className })} {...props} />;\n}\n\n/** A keyboard hint at the end of an item. */\nexport function CommandShortcut({ className, ...props }: React.ComponentProps<\"span\">) {\n return <span className={s.shortcut({ className })} {...props} />;\n}\n\n/** `Command.Root/Input/List/Empty/Loading/Group/Item/Separator/Shortcut`. */\nexport const Command = {\n Root: CommandRoot,\n Input: CommandInput,\n List: CommandList,\n Empty: CommandEmpty,\n Loading: CommandLoading,\n Group: CommandGroup,\n Item: CommandItem,\n Separator: CommandSeparator,\n Shortcut: CommandShortcut,\n};\n\nexport type CommandDialogProps = Omit<CommandRootProps, \"title\"> & {\n /** Open or closed (controlled), with `onOpenChange`. */\n open?: boolean;\n /** Open at first, uncontrolled. */\n defaultOpen?: boolean;\n /** Called when it opens or closes (Escape, a click outside, a shortcut of the product). */\n onOpenChange?: (open: boolean) => void;\n /** Under the palette, inside the dialog: shortcuts, a \"see all results\" link. */\n footer?: React.ReactNode;\n /** Passed to `Dialog.Content`: `size`, `container`, `className` of the dialog. */\n contentProps?: Omit<Extract<DialogContentProps, { hideClose: true }>, \"hideClose\" | \"children\" | \"placement\">;\n};\n\n/**\n * The palette in a dialog (Radix: focus trap, Escape, focus return). The dialog is named by `label`; it has no close\n * button — Escape and a click outside close it — and the input takes the focus when it opens.\n */\nexport function CommandDialog({ open, defaultOpen, onOpenChange, footer, contentProps, label, className, children, ...props }: CommandDialogProps) {\n const { className: contentClassName, ...content } = contentProps ?? {};\n return (\n <DialogPrimitive.Root open={open} defaultOpen={defaultOpen} onOpenChange={onOpenChange}>\n <DialogContent\n hideClose\n size=\"lg\"\n aria-describedby={undefined}\n className={cn(\"top-[12dvh] translate-y-0 sm:top-[14dvh]\", contentClassName)}\n {...content}\n >\n <DialogPrimitive.Title className=\"sr-only\">{label}</DialogPrimitive.Title>\n <CommandRoot label={label} className={className} {...props}>\n {children}\n </CommandRoot>\n {footer}\n </DialogContent>\n </DialogPrimitive.Root>\n );\n}\n"],"mappings":"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","names":[]}
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { B as ButtonProps } from './button-G5qY4qSY.js';
2
+ import { B as ButtonProps } from './button-8La7l0V4.js';
3
3
  import 'tailwind-variants';
4
4
 
5
5
  declare const confirmArmed = "border border-danger bg-danger/20 text-fg hover:border-danger hover:bg-danger/30";
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  Button
4
- } from "./chunk-QRG5RYEI.js";
4
+ } from "./chunk-ZUD4U22H.js";
5
5
  import {
6
6
  cn
7
7
  } from "./chunk-5AXLA4LK.js";
@@ -20,6 +20,7 @@ type CountdownUnits = {
20
20
  declare function countdownParts(ms: number, units: CountdownUnits): [number, string][];
21
21
 
22
22
  type CountdownProps = {
23
+ /** The moment it counts down to: a Date, an ISO string or epoch milliseconds. */
23
24
  target: Date | string | number;
24
25
  /** Server clock − this clock, in milliseconds. */
25
26
  skewMs?: number;
@@ -27,9 +28,11 @@ type CountdownProps = {
27
28
  units: CountdownUnits;
28
29
  /** Below this many milliseconds it turns urgent (`text-danger`, the last segment pulses). Default 60 s. */
29
30
  urgentBelowMs?: number;
31
+ /** sm · md · lg (the danger role is large-text safe from `md`). */
30
32
  size?: "sm" | "md" | "lg";
31
33
  /** Accessible name, e.g. "Ends in". */
32
34
  label: string;
35
+ /** Classes merged last, over the primitive's. */
33
36
  className?: string;
34
37
  };
35
38
  /**
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/countdown/core.ts","../src/countdown/countdown.tsx"],"sourcesContent":["// The countdown's clock, shared by the web (`@krizaka/ui/countdown`) and native renders: no DOM import.\nimport { useSyncExternalStore } from \"react\";\n\n// One clock for every countdown on the page: it ticks each second while someone listens.\nconst listeners = new Set<() => void>();\nlet timer: ReturnType<typeof setInterval> | null = null;\n\nfunction subscribe(listener: () => void) {\n listeners.add(listener);\n timer ??= setInterval(() => listeners.forEach((l) => l()), 1000);\n return () => {\n listeners.delete(listener);\n if (listeners.size === 0 && timer) {\n clearInterval(timer);\n timer = null;\n }\n };\n}\n\nconst nowSecond = () => Math.floor(Date.now() / 1000) * 1000;\n\n/** Milliseconds left until `target` (never negative), ticking every second. `skewMs` = server clock − this clock. */\nexport function useCountdown(target: Date | string | number, skewMs = 0): number {\n const now = useSyncExternalStore(subscribe, nowSecond, nowSecond);\n return Math.max(0, new Date(target).getTime() - (now + skewMs));\n}\n\n/** Splits a duration into days, hours, minutes and seconds. */\nexport function splitDuration(ms: number): { d: number; h: number; m: number; s: number } {\n const total = Math.max(0, Math.floor(ms / 1000));\n return { d: Math.floor(total / 86400), h: Math.floor((total % 86400) / 3600), m: Math.floor((total % 3600) / 60), s: total % 60 };\n}\n\n/** The short unit labels, passed translated (e.g. `{ d: \"d\", h: \"h\", m: \"m\", s: \"s\" }`). */\nexport type CountdownUnits = { d: string; h: string; m: string; s: string };\n\n/** The three segments shown: days, hours, minutes when there are days; else hours, minutes, seconds. */\nexport function countdownParts(ms: number, units: CountdownUnits): [number, string][] {\n const { d, h, m, s } = splitDuration(ms);\n return d > 0 ? [[d, units.d], [h, units.h], [m, units.m]] : [[h, units.h], [m, units.m], [s, units.s]];\n}\n","// Client: the clock is a hook.\nimport { tv } from \"tailwind-variants\";\n\nimport { countdownParts, type CountdownUnits, useCountdown } from \"./core\";\n\nconst countdown = tv({\n slots: {\n root: \"inline-flex items-baseline gap-1.5 font-display font-black tabular-nums tracking-tight text-fg\",\n segment: \"inline-flex items-baseline\",\n unit: \"ml-0.5 text-[0.5em] font-bold uppercase text-fg-secondary\",\n },\n variants: {\n size: { sm: { root: \"text-sm\" }, md: { root: \"text-xl\" }, lg: { root: \"text-3xl sm:text-4xl\" } },\n urgent: { true: { root: \"text-danger\" } },\n },\n defaultVariants: { size: \"md\" },\n});\n\nexport type CountdownProps = {\n target: Date | string | number;\n /** Server clock − this clock, in milliseconds. */\n skewMs?: number;\n /** The short unit labels, passed translated. */\n units: CountdownUnits;\n /** Below this many milliseconds it turns urgent (`text-danger`, the last segment pulses). Default 60 s. */\n urgentBelowMs?: number;\n size?: \"sm\" | \"md\" | \"lg\";\n /** Accessible name, e.g. \"Ends in\". */\n label: string;\n className?: string;\n};\n\n/**\n * Time left until a moment, as segments (2d 04h 13m 09s — days only when there are some) in tabular figures. Under\n * `urgentBelowMs` it turns to the danger role and its last segment pulses (no motion under prefers-reduced-motion).\n * Words come from the app: `units` are the short unit labels. `role=\"timer\"` without live announcements — the app\n * announces what matters. State: `data-urgent`, `data-ended`.\n *\n * The danger role is large-text safe (≥ 3:1) from `size=\"md\"`; at `size=\"sm\"` an urgent countdown in light mode is\n * under the 4.5:1 of small text.\n */\nexport function Countdown({ target, skewMs = 0, units, urgentBelowMs = 60_000, size = \"md\", label, className }: CountdownProps) {\n const ms = useCountdown(target, skewMs);\n const urgent = ms > 0 && ms < urgentBelowMs;\n const parts = countdownParts(ms, units);\n const s = countdown({ size, urgent });\n return (\n <span\n role=\"timer\"\n aria-label={label}\n data-urgent={urgent ? \"\" : undefined}\n data-ended={ms === 0 ? \"\" : undefined}\n suppressHydrationWarning\n className={s.root({ className })}\n >\n {parts.map(([value, unit], i) => (\n <span key={unit} className={s.segment({ className: urgent && i === parts.length - 1 ? \"motion-safe:animate-pulse\" : undefined })}>\n {String(value).padStart(2, \"0\")}\n <span className={s.unit()}>{unit}</span>\n </span>\n ))}\n </span>\n );\n}\n"],"mappings":";;;AACA,SAAS,4BAA4B;AAGrC,IAAM,YAAY,oBAAI,IAAgB;AACtC,IAAI,QAA+C;AAEnD,SAAS,UAAU,UAAsB;AACvC,YAAU,IAAI,QAAQ;AACtB,YAAU,YAAY,MAAM,UAAU,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,GAAI;AAC/D,SAAO,MAAM;AACX,cAAU,OAAO,QAAQ;AACzB,QAAI,UAAU,SAAS,KAAK,OAAO;AACjC,oBAAc,KAAK;AACnB,cAAQ;AAAA,IACV;AAAA,EACF;AACF;AAEA,IAAM,YAAY,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,IAAI;AAGjD,SAAS,aAAa,QAAgC,SAAS,GAAW;AAC/E,QAAM,MAAM,qBAAqB,WAAW,WAAW,SAAS;AAChE,SAAO,KAAK,IAAI,GAAG,IAAI,KAAK,MAAM,EAAE,QAAQ,KAAK,MAAM,OAAO;AAChE;AAGO,SAAS,cAAc,IAA4D;AACxF,QAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,GAAI,CAAC;AAC/C,SAAO,EAAE,GAAG,KAAK,MAAM,QAAQ,KAAK,GAAG,GAAG,KAAK,MAAO,QAAQ,QAAS,IAAI,GAAG,GAAG,KAAK,MAAO,QAAQ,OAAQ,EAAE,GAAG,GAAG,QAAQ,GAAG;AAClI;AAMO,SAAS,eAAe,IAAY,OAA2C;AACpF,QAAM,EAAE,GAAG,GAAG,GAAG,EAAE,IAAI,cAAc,EAAE;AACvC,SAAO,IAAI,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;AACvG;;;ACvCA,SAAS,UAAU;AAuDX,SAEE,KAFF;AAnDR,IAAM,YAAY,GAAG;AAAA,EACnB,OAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,MAAM;AAAA,EACR;AAAA,EACA,UAAU;AAAA,IACR,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,GAAG,IAAI,EAAE,MAAM,UAAU,GAAG,IAAI,EAAE,MAAM,uBAAuB,EAAE;AAAA,IAC/F,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,EAAE;AAAA,EAC1C;AAAA,EACA,iBAAiB,EAAE,MAAM,KAAK;AAChC,CAAC;AAyBM,SAAS,UAAU,EAAE,QAAQ,SAAS,GAAG,OAAO,gBAAgB,KAAQ,OAAO,MAAM,OAAO,UAAU,GAAmB;AAC9H,QAAM,KAAK,aAAa,QAAQ,MAAM;AACtC,QAAM,SAAS,KAAK,KAAK,KAAK;AAC9B,QAAM,QAAQ,eAAe,IAAI,KAAK;AACtC,QAAM,IAAI,UAAU,EAAE,MAAM,OAAO,CAAC;AACpC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY;AAAA,MACZ,eAAa,SAAS,KAAK;AAAA,MAC3B,cAAY,OAAO,IAAI,KAAK;AAAA,MAC5B,0BAAwB;AAAA,MACxB,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC;AAAA,MAE9B,gBAAM,IAAI,CAAC,CAAC,OAAO,IAAI,GAAG,MACzB,qBAAC,UAAgB,WAAW,EAAE,QAAQ,EAAE,WAAW,UAAU,MAAM,MAAM,SAAS,IAAI,8BAA8B,OAAU,CAAC,GAC5H;AAAA,eAAO,KAAK,EAAE,SAAS,GAAG,GAAG;AAAA,QAC9B,oBAAC,UAAK,WAAW,EAAE,KAAK,GAAI,gBAAK;AAAA,WAFxB,IAGX,CACD;AAAA;AAAA,EACH;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../src/countdown/core.ts","../src/countdown/countdown.tsx"],"sourcesContent":["// The countdown's clock, shared by the web (`@krizaka/ui/countdown`) and native renders: no DOM import.\nimport { useSyncExternalStore } from \"react\";\n\n// One clock for every countdown on the page: it ticks each second while someone listens.\nconst listeners = new Set<() => void>();\nlet timer: ReturnType<typeof setInterval> | null = null;\n\nfunction subscribe(listener: () => void) {\n listeners.add(listener);\n timer ??= setInterval(() => listeners.forEach((l) => l()), 1000);\n return () => {\n listeners.delete(listener);\n if (listeners.size === 0 && timer) {\n clearInterval(timer);\n timer = null;\n }\n };\n}\n\nconst nowSecond = () => Math.floor(Date.now() / 1000) * 1000;\n\n/** Milliseconds left until `target` (never negative), ticking every second. `skewMs` = server clock − this clock. */\nexport function useCountdown(target: Date | string | number, skewMs = 0): number {\n const now = useSyncExternalStore(subscribe, nowSecond, nowSecond);\n return Math.max(0, new Date(target).getTime() - (now + skewMs));\n}\n\n/** Splits a duration into days, hours, minutes and seconds. */\nexport function splitDuration(ms: number): { d: number; h: number; m: number; s: number } {\n const total = Math.max(0, Math.floor(ms / 1000));\n return { d: Math.floor(total / 86400), h: Math.floor((total % 86400) / 3600), m: Math.floor((total % 3600) / 60), s: total % 60 };\n}\n\n/** The short unit labels, passed translated (e.g. `{ d: \"d\", h: \"h\", m: \"m\", s: \"s\" }`). */\nexport type CountdownUnits = { d: string; h: string; m: string; s: string };\n\n/** The three segments shown: days, hours, minutes when there are days; else hours, minutes, seconds. */\nexport function countdownParts(ms: number, units: CountdownUnits): [number, string][] {\n const { d, h, m, s } = splitDuration(ms);\n return d > 0 ? [[d, units.d], [h, units.h], [m, units.m]] : [[h, units.h], [m, units.m], [s, units.s]];\n}\n","// Client: the clock is a hook.\nimport { tv } from \"tailwind-variants\";\n\nimport { countdownParts, type CountdownUnits, useCountdown } from \"./core\";\n\nconst countdown = tv({\n slots: {\n root: \"inline-flex items-baseline gap-1.5 font-display font-black tabular-nums tracking-tight text-fg\",\n segment: \"inline-flex items-baseline\",\n unit: \"ml-0.5 text-[0.5em] font-bold uppercase text-fg-secondary\",\n },\n variants: {\n size: { sm: { root: \"text-sm\" }, md: { root: \"text-xl\" }, lg: { root: \"text-3xl sm:text-4xl\" } },\n urgent: { true: { root: \"text-danger\" } },\n },\n defaultVariants: { size: \"md\" },\n});\n\nexport type CountdownProps = {\n /** The moment it counts down to: a Date, an ISO string or epoch milliseconds. */\n target: Date | string | number;\n /** Server clock − this clock, in milliseconds. */\n skewMs?: number;\n /** The short unit labels, passed translated. */\n units: CountdownUnits;\n /** Below this many milliseconds it turns urgent (`text-danger`, the last segment pulses). Default 60 s. */\n urgentBelowMs?: number;\n /** sm · md · lg (the danger role is large-text safe from `md`). */\n size?: \"sm\" | \"md\" | \"lg\";\n /** Accessible name, e.g. \"Ends in\". */\n label: string;\n /** Classes merged last, over the primitive's. */\n className?: string;\n};\n\n/**\n * Time left until a moment, as segments (2d 04h 13m 09s — days only when there are some) in tabular figures. Under\n * `urgentBelowMs` it turns to the danger role and its last segment pulses (no motion under prefers-reduced-motion).\n * Words come from the app: `units` are the short unit labels. `role=\"timer\"` without live announcements — the app\n * announces what matters. State: `data-urgent`, `data-ended`.\n *\n * The danger role is large-text safe (≥ 3:1) from `size=\"md\"`; at `size=\"sm\"` an urgent countdown in light mode is\n * under the 4.5:1 of small text.\n */\nexport function Countdown({ target, skewMs = 0, units, urgentBelowMs = 60_000, size = \"md\", label, className }: CountdownProps) {\n const ms = useCountdown(target, skewMs);\n const urgent = ms > 0 && ms < urgentBelowMs;\n const parts = countdownParts(ms, units);\n const s = countdown({ size, urgent });\n return (\n <span\n role=\"timer\"\n aria-label={label}\n data-urgent={urgent ? \"\" : undefined}\n data-ended={ms === 0 ? \"\" : undefined}\n suppressHydrationWarning\n className={s.root({ className })}\n >\n {parts.map(([value, unit], i) => (\n <span key={unit} className={s.segment({ className: urgent && i === parts.length - 1 ? \"motion-safe:animate-pulse\" : undefined })}>\n {String(value).padStart(2, \"0\")}\n <span className={s.unit()}>{unit}</span>\n </span>\n ))}\n </span>\n );\n}\n"],"mappings":";;;AACA,SAAS,4BAA4B;AAGrC,IAAM,YAAY,oBAAI,IAAgB;AACtC,IAAI,QAA+C;AAEnD,SAAS,UAAU,UAAsB;AACvC,YAAU,IAAI,QAAQ;AACtB,YAAU,YAAY,MAAM,UAAU,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,GAAI;AAC/D,SAAO,MAAM;AACX,cAAU,OAAO,QAAQ;AACzB,QAAI,UAAU,SAAS,KAAK,OAAO;AACjC,oBAAc,KAAK;AACnB,cAAQ;AAAA,IACV;AAAA,EACF;AACF;AAEA,IAAM,YAAY,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,IAAI;AAGjD,SAAS,aAAa,QAAgC,SAAS,GAAW;AAC/E,QAAM,MAAM,qBAAqB,WAAW,WAAW,SAAS;AAChE,SAAO,KAAK,IAAI,GAAG,IAAI,KAAK,MAAM,EAAE,QAAQ,KAAK,MAAM,OAAO;AAChE;AAGO,SAAS,cAAc,IAA4D;AACxF,QAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,GAAI,CAAC;AAC/C,SAAO,EAAE,GAAG,KAAK,MAAM,QAAQ,KAAK,GAAG,GAAG,KAAK,MAAO,QAAQ,QAAS,IAAI,GAAG,GAAG,KAAK,MAAO,QAAQ,OAAQ,EAAE,GAAG,GAAG,QAAQ,GAAG;AAClI;AAMO,SAAS,eAAe,IAAY,OAA2C;AACpF,QAAM,EAAE,GAAG,GAAG,GAAG,EAAE,IAAI,cAAc,EAAE;AACvC,SAAO,IAAI,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;AACvG;;;ACvCA,SAAS,UAAU;AA0DX,SAEE,KAFF;AAtDR,IAAM,YAAY,GAAG;AAAA,EACnB,OAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,MAAM;AAAA,EACR;AAAA,EACA,UAAU;AAAA,IACR,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,GAAG,IAAI,EAAE,MAAM,UAAU,GAAG,IAAI,EAAE,MAAM,uBAAuB,EAAE;AAAA,IAC/F,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,EAAE;AAAA,EAC1C;AAAA,EACA,iBAAiB,EAAE,MAAM,KAAK;AAChC,CAAC;AA4BM,SAAS,UAAU,EAAE,QAAQ,SAAS,GAAG,OAAO,gBAAgB,KAAQ,OAAO,MAAM,OAAO,UAAU,GAAmB;AAC9H,QAAM,KAAK,aAAa,QAAQ,MAAM;AACtC,QAAM,SAAS,KAAK,KAAK,KAAK;AAC9B,QAAM,QAAQ,eAAe,IAAI,KAAK;AACtC,QAAM,IAAI,UAAU,EAAE,MAAM,OAAO,CAAC;AACpC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY;AAAA,MACZ,eAAa,SAAS,KAAK;AAAA,MAC3B,cAAY,OAAO,IAAI,KAAK;AAAA,MAC5B,0BAAwB;AAAA,MACxB,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC;AAAA,MAE9B,gBAAM,IAAI,CAAC,CAAC,OAAO,IAAI,GAAG,MACzB,qBAAC,UAAgB,WAAW,EAAE,QAAQ,EAAE,WAAW,UAAU,MAAM,MAAM,SAAS,IAAI,8BAA8B,OAAU,CAAC,GAC5H;AAAA,eAAO,KAAK,EAAE,SAAS,GAAG,GAAG;AAAA,QAC9B,oBAAC,UAAK,WAAW,EAAE,KAAK,GAAI,gBAAK;AAAA,WAFxB,IAGX,CACD;AAAA;AAAA,EACH;AAEJ;","names":[]}
@@ -111,6 +111,16 @@ type CloseButtonProps = {
111
111
  hideClose: true;
112
112
  };
113
113
  type DialogContentProps = React.ComponentProps<typeof Dialog$1.Content> & DialogVariants & CloseButtonProps & {
114
+ /**
115
+ * center · bottom (a sheet on a phone, centred from `sm` up) · right (a side panel, full height).
116
+ * @default "center"
117
+ */
118
+ placement?: DialogVariants["placement"];
119
+ /**
120
+ * sm · md · lg: the width of the dialog.
121
+ * @default "md"
122
+ */
123
+ size?: DialogVariants["size"];
114
124
  /**
115
125
  * `false`: Escape and a click outside do not close it (a gate the user must answer: age, terms). It still closes
116
126
  * through `open` / `onOpenChange` and any `Dialog.Close` inside. Default `true`.
package/dist/dialog.d.ts CHANGED
@@ -1,19 +1,26 @@
1
1
  import * as React from 'react';
2
- export { a as Dialog, b as DialogBody, c as DialogContent, D as DialogContentProps, d as DialogDescription, e as DialogFooter, f as DialogHeader, g as DialogTitle, h as DialogVariants, S as Sheet, i as SheetProps, j as dialog } from './dialog-DGBY2grk.js';
2
+ export { a as Dialog, b as DialogBody, c as DialogContent, D as DialogContentProps, d as DialogDescription, e as DialogFooter, f as DialogHeader, g as DialogTitle, h as DialogVariants, S as Sheet, i as SheetProps, j as dialog } from './dialog-GQ4Nvuyf.js';
3
3
  import 'tailwind-variants';
4
4
  import 'radix-ui';
5
5
 
6
6
  type AlertDialogProps = {
7
+ /** Open or closed (controlled), with `onOpenChange`. */
7
8
  open?: boolean;
9
+ /** Open at first, uncontrolled. */
8
10
  defaultOpen?: boolean;
11
+ /** Called when it opens or closes (never while `onConfirm` is pending). */
9
12
  onOpenChange?: (open: boolean) => void;
10
13
  /** The element that opens the dialog (rendered as is, `asChild`): a Button, an IconButton. */
11
14
  trigger?: React.ReactNode;
15
+ /** The question asked ("Delete this video?"): the dialog's accessible name. */
12
16
  title: React.ReactNode;
17
+ /** What the action does and what it costs: the dialog's description. */
13
18
  description?: React.ReactNode;
14
19
  /** More content between the description and the actions. */
15
20
  children?: React.ReactNode;
21
+ /** The words of the confirm button — passed translated. */
16
22
  confirmLabel: string;
23
+ /** The words of the cancel button (it takes the focus at open) — passed translated. */
17
24
  cancelLabel: string;
18
25
  /** `danger` for a destructive action (delete, leave, cancel a payment). */
19
26
  tone?: "danger" | "primary";
@@ -21,6 +28,7 @@ type AlertDialogProps = {
21
28
  onConfirm: () => void | Promise<unknown>;
22
29
  /** The element the portal renders into (default: document.body). */
23
30
  container?: HTMLElement | null;
31
+ /** Classes of the dialog's content, merged last. */
24
32
  className?: string;
25
33
  };
26
34
  declare function AlertDialog({ open: openProp, defaultOpen, onOpenChange, trigger, title, description, children, confirmLabel, cancelLabel, tone, onConfirm, container, className, }: AlertDialogProps): React.JSX.Element;
package/dist/dialog.js CHANGED
@@ -9,10 +9,10 @@ import {
9
9
  DialogTitle,
10
10
  Sheet,
11
11
  dialog
12
- } from "./chunk-5FRYKFTO.js";
12
+ } from "./chunk-3X5MVH54.js";
13
13
  import {
14
14
  Button
15
- } from "./chunk-QRG5RYEI.js";
15
+ } from "./chunk-ZUD4U22H.js";
16
16
 
17
17
  // src/dialog/alert-dialog.tsx
18
18
  import { AlertDialog as AlertDialogPrimitive } from "radix-ui";
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/dialog/alert-dialog.tsx"],"sourcesContent":["// Client. A confirmation that interrupts: Radix AlertDialog (role=\"alertdialog\", no outside click, focus on Cancel).\n// `onConfirm` may be async: the dialog stays open with the confirm button loading until it settles, closes when it\n// resolves, and stays open when it rejects (the product shows the error).\nimport { AlertDialog as AlertDialogPrimitive } from \"radix-ui\";\nimport * as React from \"react\";\n\nimport { Button } from \"../button/button\";\nimport { dialog } from \"./dialog\";\n\nconst s = dialog({ placement: \"center\", size: \"sm\" });\n\nexport type AlertDialogProps = {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** The element that opens the dialog (rendered as is, `asChild`): a Button, an IconButton. */\n trigger?: React.ReactNode;\n title: React.ReactNode;\n description?: React.ReactNode;\n /** More content between the description and the actions. */\n children?: React.ReactNode;\n confirmLabel: string;\n cancelLabel: string;\n /** `danger` for a destructive action (delete, leave, cancel a payment). */\n tone?: \"danger\" | \"primary\";\n /** Runs on confirm. A promise keeps the dialog open and the button loading until it settles. */\n onConfirm: () => void | Promise<unknown>;\n /** The element the portal renders into (default: document.body). */\n container?: HTMLElement | null;\n className?: string;\n};\n\nexport function AlertDialog({\n open: openProp,\n defaultOpen = false,\n onOpenChange,\n trigger,\n title,\n description,\n children,\n confirmLabel,\n cancelLabel,\n tone = \"primary\",\n onConfirm,\n container,\n className,\n}: AlertDialogProps) {\n const [openState, setOpenState] = React.useState(defaultOpen);\n const [pending, setPending] = React.useState(false);\n const open = openProp ?? openState;\n\n const setOpen = (next: boolean) => {\n if (openProp === undefined) setOpenState(next);\n onOpenChange?.(next);\n };\n\n const confirm = async () => {\n setPending(true);\n try {\n await onConfirm();\n setOpen(false);\n } catch {\n // Stays open: the product reports the failure (a toast, an inline error) and the person may retry.\n } finally {\n setPending(false);\n }\n };\n\n return (\n <AlertDialogPrimitive.Root open={open} onOpenChange={(next) => (pending ? undefined : setOpen(next))}>\n {trigger && <AlertDialogPrimitive.Trigger asChild>{trigger}</AlertDialogPrimitive.Trigger>}\n <AlertDialogPrimitive.Portal container={container}>\n <AlertDialogPrimitive.Overlay className={s.overlay()} />\n <AlertDialogPrimitive.Content\n data-tone={tone}\n aria-busy={pending || undefined}\n className={s.content({ className })}\n onEscapeKeyDown={(event) => pending && event.preventDefault()}\n >\n <div className={s.header({ className: \"pr-5\" })}>\n <AlertDialogPrimitive.Title className={s.title()}>{title}</AlertDialogPrimitive.Title>\n {description && <AlertDialogPrimitive.Description className={s.description()}>{description}</AlertDialogPrimitive.Description>}\n </div>\n {children && <div className={s.body()}>{children}</div>}\n <div className={s.footer()}>\n <AlertDialogPrimitive.Cancel asChild>\n <Button variant=\"ghost\" disabled={pending}>\n {cancelLabel}\n </Button>\n </AlertDialogPrimitive.Cancel>\n <Button variant={tone === \"danger\" ? \"danger\" : \"primary\"} loading={pending} onClick={confirm}>\n {confirmLabel}\n </Button>\n </div>\n </AlertDialogPrimitive.Content>\n </AlertDialogPrimitive.Portal>\n </AlertDialogPrimitive.Root>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAGA,SAAS,eAAe,4BAA4B;AACpD,YAAY,WAAW;AAkEL,cASR,YATQ;AA7DlB,IAAM,IAAI,OAAO,EAAE,WAAW,UAAU,MAAM,KAAK,CAAC;AAuB7C,SAAS,YAAY;AAAA,EAC1B,MAAM;AAAA,EACN,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AACF,GAAqB;AACnB,QAAM,CAAC,WAAW,YAAY,IAAU,eAAS,WAAW;AAC5D,QAAM,CAAC,SAAS,UAAU,IAAU,eAAS,KAAK;AAClD,QAAM,OAAO,YAAY;AAEzB,QAAM,UAAU,CAAC,SAAkB;AACjC,QAAI,aAAa,OAAW,cAAa,IAAI;AAC7C,mBAAe,IAAI;AAAA,EACrB;AAEA,QAAM,UAAU,YAAY;AAC1B,eAAW,IAAI;AACf,QAAI;AACF,YAAM,UAAU;AAChB,cAAQ,KAAK;AAAA,IACf,QAAQ;AAAA,IAER,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF;AAEA,SACE,qBAAC,qBAAqB,MAArB,EAA0B,MAAY,cAAc,CAAC,SAAU,UAAU,SAAY,QAAQ,IAAI,GAC/F;AAAA,eAAW,oBAAC,qBAAqB,SAArB,EAA6B,SAAO,MAAE,mBAAQ;AAAA,IAC3D,qBAAC,qBAAqB,QAArB,EAA4B,WAC3B;AAAA,0BAAC,qBAAqB,SAArB,EAA6B,WAAW,EAAE,QAAQ,GAAG;AAAA,MACtD;AAAA,QAAC,qBAAqB;AAAA,QAArB;AAAA,UACC,aAAW;AAAA,UACX,aAAW,WAAW;AAAA,UACtB,WAAW,EAAE,QAAQ,EAAE,UAAU,CAAC;AAAA,UAClC,iBAAiB,CAAC,UAAU,WAAW,MAAM,eAAe;AAAA,UAE5D;AAAA,iCAAC,SAAI,WAAW,EAAE,OAAO,EAAE,WAAW,OAAO,CAAC,GAC5C;AAAA,kCAAC,qBAAqB,OAArB,EAA2B,WAAW,EAAE,MAAM,GAAI,iBAAM;AAAA,cACxD,eAAe,oBAAC,qBAAqB,aAArB,EAAiC,WAAW,EAAE,YAAY,GAAI,uBAAY;AAAA,eAC7F;AAAA,YACC,YAAY,oBAAC,SAAI,WAAW,EAAE,KAAK,GAAI,UAAS;AAAA,YACjD,qBAAC,SAAI,WAAW,EAAE,OAAO,GACvB;AAAA,kCAAC,qBAAqB,QAArB,EAA4B,SAAO,MAClC,8BAAC,UAAO,SAAQ,SAAQ,UAAU,SAC/B,uBACH,GACF;AAAA,cACA,oBAAC,UAAO,SAAS,SAAS,WAAW,WAAW,WAAW,SAAS,SAAS,SAAS,SACnF,wBACH;AAAA,eACF;AAAA;AAAA;AAAA,MACF;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../src/dialog/alert-dialog.tsx"],"sourcesContent":["// Client. A confirmation that interrupts: Radix AlertDialog (role=\"alertdialog\", no outside click, focus on Cancel).\n// `onConfirm` may be async: the dialog stays open with the confirm button loading until it settles, closes when it\n// resolves, and stays open when it rejects (the product shows the error).\nimport { AlertDialog as AlertDialogPrimitive } from \"radix-ui\";\nimport * as React from \"react\";\n\nimport { Button } from \"../button/button\";\nimport { dialog } from \"./dialog\";\n\nconst s = dialog({ placement: \"center\", size: \"sm\" });\n\nexport type AlertDialogProps = {\n /** Open or closed (controlled), with `onOpenChange`. */\n open?: boolean;\n /** Open at first, uncontrolled. */\n defaultOpen?: boolean;\n /** Called when it opens or closes (never while `onConfirm` is pending). */\n onOpenChange?: (open: boolean) => void;\n /** The element that opens the dialog (rendered as is, `asChild`): a Button, an IconButton. */\n trigger?: React.ReactNode;\n /** The question asked (\"Delete this video?\"): the dialog's accessible name. */\n title: React.ReactNode;\n /** What the action does and what it costs: the dialog's description. */\n description?: React.ReactNode;\n /** More content between the description and the actions. */\n children?: React.ReactNode;\n /** The words of the confirm button — passed translated. */\n confirmLabel: string;\n /** The words of the cancel button (it takes the focus at open) — passed translated. */\n cancelLabel: string;\n /** `danger` for a destructive action (delete, leave, cancel a payment). */\n tone?: \"danger\" | \"primary\";\n /** Runs on confirm. A promise keeps the dialog open and the button loading until it settles. */\n onConfirm: () => void | Promise<unknown>;\n /** The element the portal renders into (default: document.body). */\n container?: HTMLElement | null;\n /** Classes of the dialog's content, merged last. */\n className?: string;\n};\n\nexport function AlertDialog({\n open: openProp,\n defaultOpen = false,\n onOpenChange,\n trigger,\n title,\n description,\n children,\n confirmLabel,\n cancelLabel,\n tone = \"primary\",\n onConfirm,\n container,\n className,\n}: AlertDialogProps) {\n const [openState, setOpenState] = React.useState(defaultOpen);\n const [pending, setPending] = React.useState(false);\n const open = openProp ?? openState;\n\n const setOpen = (next: boolean) => {\n if (openProp === undefined) setOpenState(next);\n onOpenChange?.(next);\n };\n\n const confirm = async () => {\n setPending(true);\n try {\n await onConfirm();\n setOpen(false);\n } catch {\n // Stays open: the product reports the failure (a toast, an inline error) and the person may retry.\n } finally {\n setPending(false);\n }\n };\n\n return (\n <AlertDialogPrimitive.Root open={open} onOpenChange={(next) => (pending ? undefined : setOpen(next))}>\n {trigger && <AlertDialogPrimitive.Trigger asChild>{trigger}</AlertDialogPrimitive.Trigger>}\n <AlertDialogPrimitive.Portal container={container}>\n <AlertDialogPrimitive.Overlay className={s.overlay()} />\n <AlertDialogPrimitive.Content\n data-tone={tone}\n aria-busy={pending || undefined}\n className={s.content({ className })}\n onEscapeKeyDown={(event) => pending && event.preventDefault()}\n >\n <div className={s.header({ className: \"pr-5\" })}>\n <AlertDialogPrimitive.Title className={s.title()}>{title}</AlertDialogPrimitive.Title>\n {description && <AlertDialogPrimitive.Description className={s.description()}>{description}</AlertDialogPrimitive.Description>}\n </div>\n {children && <div className={s.body()}>{children}</div>}\n <div className={s.footer()}>\n <AlertDialogPrimitive.Cancel asChild>\n <Button variant=\"ghost\" disabled={pending}>\n {cancelLabel}\n </Button>\n </AlertDialogPrimitive.Cancel>\n <Button variant={tone === \"danger\" ? \"danger\" : \"primary\"} loading={pending} onClick={confirm}>\n {confirmLabel}\n </Button>\n </div>\n </AlertDialogPrimitive.Content>\n </AlertDialogPrimitive.Portal>\n </AlertDialogPrimitive.Root>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAGA,SAAS,eAAe,4BAA4B;AACpD,YAAY,WAAW;AA0EL,cASR,YATQ;AArElB,IAAM,IAAI,OAAO,EAAE,WAAW,UAAU,MAAM,KAAK,CAAC;AA+B7C,SAAS,YAAY;AAAA,EAC1B,MAAM;AAAA,EACN,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AACF,GAAqB;AACnB,QAAM,CAAC,WAAW,YAAY,IAAU,eAAS,WAAW;AAC5D,QAAM,CAAC,SAAS,UAAU,IAAU,eAAS,KAAK;AAClD,QAAM,OAAO,YAAY;AAEzB,QAAM,UAAU,CAAC,SAAkB;AACjC,QAAI,aAAa,OAAW,cAAa,IAAI;AAC7C,mBAAe,IAAI;AAAA,EACrB;AAEA,QAAM,UAAU,YAAY;AAC1B,eAAW,IAAI;AACf,QAAI;AACF,YAAM,UAAU;AAChB,cAAQ,KAAK;AAAA,IACf,QAAQ;AAAA,IAER,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF;AAEA,SACE,qBAAC,qBAAqB,MAArB,EAA0B,MAAY,cAAc,CAAC,SAAU,UAAU,SAAY,QAAQ,IAAI,GAC/F;AAAA,eAAW,oBAAC,qBAAqB,SAArB,EAA6B,SAAO,MAAE,mBAAQ;AAAA,IAC3D,qBAAC,qBAAqB,QAArB,EAA4B,WAC3B;AAAA,0BAAC,qBAAqB,SAArB,EAA6B,WAAW,EAAE,QAAQ,GAAG;AAAA,MACtD;AAAA,QAAC,qBAAqB;AAAA,QAArB;AAAA,UACC,aAAW;AAAA,UACX,aAAW,WAAW;AAAA,UACtB,WAAW,EAAE,QAAQ,EAAE,UAAU,CAAC;AAAA,UAClC,iBAAiB,CAAC,UAAU,WAAW,MAAM,eAAe;AAAA,UAE5D;AAAA,iCAAC,SAAI,WAAW,EAAE,OAAO,EAAE,WAAW,OAAO,CAAC,GAC5C;AAAA,kCAAC,qBAAqB,OAArB,EAA2B,WAAW,EAAE,MAAM,GAAI,iBAAM;AAAA,cACxD,eAAe,oBAAC,qBAAqB,aAArB,EAAiC,WAAW,EAAE,YAAY,GAAI,uBAAY;AAAA,eAC7F;AAAA,YACC,YAAY,oBAAC,SAAI,WAAW,EAAE,KAAK,GAAI,UAAS;AAAA,YACjD,qBAAC,SAAI,WAAW,EAAE,OAAO,GACvB;AAAA,kCAAC,qBAAqB,QAArB,EAA4B,SAAO,MAClC,8BAAC,UAAO,SAAQ,SAAQ,UAAU,SAC/B,uBACH,GACF;AAAA,cACA,oBAAC,UAAO,SAAS,SAAS,WAAW,WAAW,WAAW,SAAS,SAAS,SAAS,SACnF,wBACH;AAAA,eACF;AAAA;AAAA;AAAA,MACF;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
@@ -48,6 +48,7 @@ type DropdownMenuContentProps = React.ComponentProps<typeof DropdownMenu$1.Conte
48
48
  };
49
49
  declare function DropdownMenuContent({ sideOffset, align, collisionPadding, container, className, ...props }: DropdownMenuContentProps): React.JSX.Element;
50
50
  type DropdownMenuItemProps = React.ComponentProps<typeof DropdownMenu$1.Item> & {
51
+ /** `danger` for a destructive action: the icon and the highlight carry the danger, the label stays legible. */
51
52
  tone?: "default" | "danger";
52
53
  };
53
54
  /** An action. `tone="danger"` for a destructive one; `onSelect` runs it (the menu closes). */
@@ -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-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 danger token is too light for small text on a light surface: the label stays a text role, the icon and the\n // highlight carry the danger.\n tone: { default: {}, danger: { item: \"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> & { tone?: \"default\" | \"danger\" };\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,cAeF,YAfE;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,oDAAoD,EAAE;AAAA,EAC7F;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;AAKO,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 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-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 danger token is too light for small text on a light surface: the label stays a text role, the icon and the\n // highlight carry the danger.\n tone: { default: {}, danger: { item: \"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,oDAAoD,EAAE;AAAA,EAC7F;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":[]}
@@ -53,7 +53,9 @@ declare const emptyState: tailwind_variants.TVReturnType<{
53
53
  type EmptyStateProps = Omit<React.ComponentProps<"div">, "title"> & {
54
54
  /** A decorative icon (hidden from assistive technology). */
55
55
  icon?: React.ReactNode;
56
+ /** What is empty, in a few words ("No videos yet"). */
56
57
  title: React.ReactNode;
58
+ /** Why, or what will fill it. */
57
59
  description?: React.ReactNode;
58
60
  /** What to do next: a Button, a link. */
59
61
  action?: React.ReactNode;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/empty-state/empty-state.tsx"],"sourcesContent":["// Server-safe. What a list, a search or a panel says when it has nothing to show — every word is a prop.\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nexport const emptyState = tv({\n slots: {\n root: \"flex flex-col items-center justify-center gap-3 rounded-xl border border-dashed border-border-default px-6 py-10 text-center\",\n icon: \"flex h-12 w-12 items-center justify-center rounded-full bg-surface-2 text-fg-secondary [&>svg]:h-6 [&>svg]:w-6\",\n title: \"text-sm font-semibold text-fg\",\n description: \"max-w-sm text-sm text-fg-secondary\",\n action: \"mt-1 flex flex-wrap items-center justify-center gap-2\",\n },\n});\nconst s = emptyState();\n\nexport type EmptyStateProps = Omit<React.ComponentProps<\"div\">, \"title\"> & {\n /** A decorative icon (hidden from assistive technology). */\n icon?: React.ReactNode;\n title: React.ReactNode;\n description?: React.ReactNode;\n /** What to do next: a Button, a link. */\n action?: React.ReactNode;\n};\n\nexport function EmptyState({ icon, title, description, action, className, ...props }: EmptyStateProps) {\n return (\n <div role=\"status\" className={s.root({ className })} {...props}>\n {icon && (\n <div aria-hidden className={s.icon()}>\n {icon}\n </div>\n )}\n <p className={s.title()}>{title}</p>\n {description && <p className={s.description()}>{description}</p>}\n {action && <div className={s.action()}>{action}</div>}\n </div>\n );\n}\n"],"mappings":";AAEA,SAAS,UAAU;AAwBf,SAEI,KAFJ;AAtBG,IAAM,aAAa,GAAG;AAAA,EAC3B,OAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,QAAQ;AAAA,EACV;AACF,CAAC;AACD,IAAM,IAAI,WAAW;AAWd,SAAS,WAAW,EAAE,MAAM,OAAO,aAAa,QAAQ,WAAW,GAAG,MAAM,GAAoB;AACrG,SACE,qBAAC,SAAI,MAAK,UAAS,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OACtD;AAAA,YACC,oBAAC,SAAI,eAAW,MAAC,WAAW,EAAE,KAAK,GAChC,gBACH;AAAA,IAEF,oBAAC,OAAE,WAAW,EAAE,MAAM,GAAI,iBAAM;AAAA,IAC/B,eAAe,oBAAC,OAAE,WAAW,EAAE,YAAY,GAAI,uBAAY;AAAA,IAC3D,UAAU,oBAAC,SAAI,WAAW,EAAE,OAAO,GAAI,kBAAO;AAAA,KACjD;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../src/empty-state/empty-state.tsx"],"sourcesContent":["// Server-safe. What a list, a search or a panel says when it has nothing to show — every word is a prop.\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nexport const emptyState = tv({\n slots: {\n root: \"flex flex-col items-center justify-center gap-3 rounded-xl border border-dashed border-border-default px-6 py-10 text-center\",\n icon: \"flex h-12 w-12 items-center justify-center rounded-full bg-surface-2 text-fg-secondary [&>svg]:h-6 [&>svg]:w-6\",\n title: \"text-sm font-semibold text-fg\",\n description: \"max-w-sm text-sm text-fg-secondary\",\n action: \"mt-1 flex flex-wrap items-center justify-center gap-2\",\n },\n});\nconst s = emptyState();\n\nexport type EmptyStateProps = Omit<React.ComponentProps<\"div\">, \"title\"> & {\n /** A decorative icon (hidden from assistive technology). */\n icon?: React.ReactNode;\n /** What is empty, in a few words (\"No videos yet\"). */\n title: React.ReactNode;\n /** Why, or what will fill it. */\n description?: React.ReactNode;\n /** What to do next: a Button, a link. */\n action?: React.ReactNode;\n};\n\nexport function EmptyState({ icon, title, description, action, className, ...props }: EmptyStateProps) {\n return (\n <div role=\"status\" className={s.root({ className })} {...props}>\n {icon && (\n <div aria-hidden className={s.icon()}>\n {icon}\n </div>\n )}\n <p className={s.title()}>{title}</p>\n {description && <p className={s.description()}>{description}</p>}\n {action && <div className={s.action()}>{action}</div>}\n </div>\n );\n}\n"],"mappings":";AAEA,SAAS,UAAU;AA0Bf,SAEI,KAFJ;AAxBG,IAAM,aAAa,GAAG;AAAA,EAC3B,OAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,QAAQ;AAAA,EACV;AACF,CAAC;AACD,IAAM,IAAI,WAAW;AAad,SAAS,WAAW,EAAE,MAAM,OAAO,aAAa,QAAQ,WAAW,GAAG,MAAM,GAAoB;AACrG,SACE,qBAAC,SAAI,MAAK,UAAS,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OACtD;AAAA,YACC,oBAAC,SAAI,eAAW,MAAC,WAAW,EAAE,KAAK,GAChC,gBACH;AAAA,IAEF,oBAAC,OAAE,WAAW,EAAE,MAAM,GAAI,iBAAM;AAAA,IAC/B,eAAe,oBAAC,OAAE,WAAW,EAAE,YAAY,GAAI,uBAAY;AAAA,IAC3D,UAAU,oBAAC,SAAI,WAAW,EAAE,OAAO,GAAI,kBAAO;AAAA,KACjD;AAEJ;","names":[]}
package/dist/kbd.d.ts CHANGED
@@ -18,7 +18,13 @@ declare const kbdVariants: tailwind_variants.TVReturnType<{
18
18
  md: "h-6 min-w-6 px-1.5 text-xs";
19
19
  };
20
20
  }, undefined>>;
21
- type KbdProps = React.ComponentProps<"kbd"> & VariantProps<typeof kbdVariants>;
21
+ type KbdProps = React.ComponentProps<"kbd"> & {
22
+ /**
23
+ * sm · md.
24
+ * @default "md"
25
+ */
26
+ size?: VariantProps<typeof kbdVariants>["size"];
27
+ };
22
28
  declare function Kbd({ size, className, ...props }: KbdProps): React.JSX.Element;
23
29
 
24
30
  export { Kbd, type KbdProps, kbdVariants };
package/dist/kbd.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/kbd/kbd.tsx"],"sourcesContent":["// Server-safe. A key, or a shortcut of several (`<Kbd>⌘</Kbd><Kbd>K</Kbd>`).\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nexport const kbdVariants = tv({\n base:\n \"inline-flex shrink-0 items-center justify-center rounded-md border border-border-default border-b-2 bg-surface-2 \" +\n \"font-mono font-semibold text-fg-secondary\",\n variants: { size: { sm: \"h-5 min-w-5 px-1 text-[10px]\", md: \"h-6 min-w-6 px-1.5 text-xs\" } },\n defaultVariants: { size: \"md\" },\n});\n\nexport type KbdProps = React.ComponentProps<\"kbd\"> & VariantProps<typeof kbdVariants>;\n\nexport function Kbd({ size, className, ...props }: KbdProps) {\n return <kbd className={kbdVariants({ size, className })} {...props} />;\n}\n"],"mappings":";AAEA,SAAS,UAA6B;AAa7B;AAXF,IAAM,cAAc,GAAG;AAAA,EAC5B,MACE;AAAA,EAEF,UAAU,EAAE,MAAM,EAAE,IAAI,gCAAgC,IAAI,6BAA6B,EAAE;AAAA,EAC3F,iBAAiB,EAAE,MAAM,KAAK;AAChC,CAAC;AAIM,SAAS,IAAI,EAAE,MAAM,WAAW,GAAG,MAAM,GAAa;AAC3D,SAAO,oBAAC,SAAI,WAAW,YAAY,EAAE,MAAM,UAAU,CAAC,GAAI,GAAG,OAAO;AACtE;","names":[]}
1
+ {"version":3,"sources":["../src/kbd/kbd.tsx"],"sourcesContent":["// Server-safe. A key, or a shortcut of several (`<Kbd>⌘</Kbd><Kbd>K</Kbd>`).\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nexport const kbdVariants = tv({\n base:\n \"inline-flex shrink-0 items-center justify-center rounded-md border border-border-default border-b-2 bg-surface-2 \" +\n \"font-mono font-semibold text-fg-secondary\",\n variants: { size: { sm: \"h-5 min-w-5 px-1 text-[10px]\", md: \"h-6 min-w-6 px-1.5 text-xs\" } },\n defaultVariants: { size: \"md\" },\n});\n\nexport type KbdProps = React.ComponentProps<\"kbd\"> & {\n /**\n * sm · md.\n * @default \"md\"\n */\n size?: VariantProps<typeof kbdVariants>[\"size\"];\n};\n\nexport function Kbd({ size, className, ...props }: KbdProps) {\n return <kbd className={kbdVariants({ size, className })} {...props} />;\n}\n"],"mappings":";AAEA,SAAS,UAA6B;AAmB7B;AAjBF,IAAM,cAAc,GAAG;AAAA,EAC5B,MACE;AAAA,EAEF,UAAU,EAAE,MAAM,EAAE,IAAI,gCAAgC,IAAI,6BAA6B,EAAE;AAAA,EAC3F,iBAAiB,EAAE,MAAM,KAAK;AAChC,CAAC;AAUM,SAAS,IAAI,EAAE,MAAM,WAAW,GAAG,MAAM,GAAa;AAC3D,SAAO,oBAAC,SAAI,WAAW,YAAY,EAAE,MAAM,UAAU,CAAC,GAAI,GAAG,OAAO;AACtE;","names":[]}