@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,63 @@
1
+ {
2
+ "name": "dropdown-menu",
3
+ "type": "primitive",
4
+ "description": "`DropdownMenu.*`, `menu` (the slots). Client (\"use client\").",
5
+ "files": [
6
+ {
7
+ "path": "dropdown-menu/dropdown-menu.tsx",
8
+ "content": "// 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"
9
+ },
10
+ {
11
+ "path": "dropdown-menu/index.ts",
12
+ "content": "/** @krizaka/ui/dropdown-menu — `DropdownMenu.*`, `menu` (the slots). Client (\"use client\"). */\nexport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n type DropdownMenuContentProps,\n DropdownMenuItem,\n type DropdownMenuItemProps,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n menu,\n} from \"./dropdown-menu\";\n"
13
+ },
14
+ {
15
+ "path": "floating.ts",
16
+ "content": "// The one surface of everything that floats next to its trigger (popover, menu, tooltip): a raised surface, a border,\n// the large shadow and the `kz-pop` entrance from the side Radix measured (`--radix-*-transform-origin`).\nexport const floating =\n \"kz-pop z-50 rounded-lg border border-border-default bg-surface-2 text-fg shadow-lg outline-hidden\";\n"
17
+ }
18
+ ],
19
+ "dependencies": [
20
+ "radix-ui@^1.7.0",
21
+ "tailwind-variants@^3.3.1"
22
+ ],
23
+ "registryDependencies": [
24
+ "cn"
25
+ ],
26
+ "demo": {
27
+ "path": "demos/dropdown-menu.tsx",
28
+ "content": "import { Button } from \"@krizaka/ui/button\";\nimport { DropdownMenu } from \"@krizaka/ui/dropdown-menu\";\n\nconst icon = (d: string) => (\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d={d} />\n </svg>\n);\n\nexport default function DropdownMenuDemo({ defaultOpen = false }: { defaultOpen?: boolean }) {\n return (\n <DropdownMenu.Root defaultOpen={defaultOpen} modal={false}>\n <DropdownMenu.Trigger asChild>\n <Button variant=\"outline\">Actions</Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"center\">\n <DropdownMenu.Label>Video</DropdownMenu.Label>\n <DropdownMenu.Item>{icon(\"M12 20h9M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4Z\")}Edit</DropdownMenu.Item>\n <DropdownMenu.Item>{icon(\"M4 12v8h16v-8M16 6l-4-4-4 4M12 2v13\")}Share</DropdownMenu.Item>\n <DropdownMenu.Item disabled>{icon(\"M12 3v12M7 10l5 5 5-5M5 21h14\")}Download</DropdownMenu.Item>\n <DropdownMenu.CheckboxItem checked>Pinned to the profile</DropdownMenu.CheckboxItem>\n <DropdownMenu.Separator />\n <DropdownMenu.Item tone=\"danger\">{icon(\"M3 6h18M8 6V4h8v2M19 6l-1 14H6L5 6\")}Delete</DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n );\n}\n"
29
+ },
30
+ "props": [
31
+ {
32
+ "component": "DropdownMenuContent",
33
+ "description": "",
34
+ "props": [
35
+ {
36
+ "name": "container",
37
+ "type": "HTMLElement | null",
38
+ "default": null,
39
+ "description": "The element the portal renders into (default: document.body).",
40
+ "required": false
41
+ }
42
+ ]
43
+ },
44
+ {
45
+ "component": "DropdownMenuItem",
46
+ "description": "An action. `tone=\"danger\"` for a destructive one; `onSelect` runs it (the menu closes).",
47
+ "props": [
48
+ {
49
+ "name": "tone",
50
+ "type": "\"danger\" | \"default\"",
51
+ "default": null,
52
+ "description": "`danger` for a destructive action: the icon and the highlight carry the danger, the label stays legible.",
53
+ "required": false
54
+ }
55
+ ]
56
+ },
57
+ {
58
+ "component": "DropdownMenuCheckboxItem",
59
+ "description": "A toggled option: `checked` + `onCheckedChange`.",
60
+ "props": []
61
+ }
62
+ ]
63
+ }
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "empty-state",
3
+ "type": "primitive",
4
+ "description": "`EmptyState`. Server-safe.",
5
+ "files": [
6
+ {
7
+ "path": "empty-state/empty-state.tsx",
8
+ "content": "// 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"
9
+ },
10
+ {
11
+ "path": "empty-state/index.ts",
12
+ "content": "/** @krizaka/ui/empty-state — `EmptyState`. Server-safe. */\nexport { EmptyState, emptyState, type EmptyStateProps } from \"./empty-state\";\n"
13
+ }
14
+ ],
15
+ "dependencies": [
16
+ "tailwind-variants@^3.3.1"
17
+ ],
18
+ "registryDependencies": [],
19
+ "demo": {
20
+ "path": "demos/empty-state.tsx",
21
+ "content": "import { EmptyState } from \"@krizaka/ui/empty-state\";\n\nconst ICON = (\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\" />\n <path d=\"m10 9 5 3-5 3z\" />\n </svg>\n);\n\nexport default function EmptyStateDemo() {\n return <EmptyState icon={ICON} title=\"No videos yet\" description=\"The videos you publish appear here.\" />;\n}\n"
22
+ },
23
+ "props": [
24
+ {
25
+ "component": "EmptyState",
26
+ "description": "",
27
+ "props": [
28
+ {
29
+ "name": "title",
30
+ "type": "ReactNode",
31
+ "default": null,
32
+ "description": "What is empty, in a few words (\"No videos yet\").",
33
+ "required": true
34
+ },
35
+ {
36
+ "name": "action",
37
+ "type": "ReactNode",
38
+ "default": null,
39
+ "description": "What to do next: a Button, a link.",
40
+ "required": false
41
+ },
42
+ {
43
+ "name": "description",
44
+ "type": "ReactNode",
45
+ "default": null,
46
+ "description": "Why, or what will fill it.",
47
+ "required": false
48
+ },
49
+ {
50
+ "name": "icon",
51
+ "type": "ReactNode",
52
+ "default": null,
53
+ "description": "A decorative icon (hidden from assistive technology).",
54
+ "required": false
55
+ }
56
+ ]
57
+ }
58
+ ]
59
+ }
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "field",
3
+ "type": "primitive",
4
+ "description": "`Field.Root/Label/Hint/Error`, `Input`, `Textarea`, `Select`. Server-safe.",
5
+ "files": [
6
+ {
7
+ "path": "field/field.tsx",
8
+ "content": "// Server-safe. The label ↔ control wiring is HTML (htmlFor / id, aria-describedby): no context.\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { cn } from \"../cn\";\n\nexport const field = tv({\n slots: {\n root: \"flex flex-col gap-1.5\",\n label: \"text-xs font-semibold text-fg-secondary\",\n control:\n \"flex h-11 w-full rounded-lg border border-border-default bg-surface-2 px-3 text-sm text-fg placeholder:text-fg-muted \" +\n \"transition-[border-color,box-shadow] focus-visible:border-accent focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring \" +\n \"disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-danger aria-invalid:ring-danger/30\",\n hint: \"text-xs text-fg-secondary\",\n // The danger token is too light for small text on a light surface: the message is a text role, the dot says danger.\n error: \"flex items-center gap-1.5 text-xs font-medium text-fg before:h-1.5 before:w-1.5 before:shrink-0 before:rounded-full before:bg-danger\",\n selectWrap: \"relative flex w-full\",\n chevron: \"pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-fg-secondary\",\n },\n});\nconst s = field();\n\nexport const Field = {\n Root: ({ className, ...props }: React.ComponentProps<\"div\">) => <div className={s.root({ className })} {...props} />,\n Label: ({ className, ...props }: React.ComponentProps<\"label\">) => <label className={s.label({ className })} {...props} />,\n Hint: ({ className, ...props }: React.ComponentProps<\"p\">) => <p className={s.hint({ className })} {...props} />,\n Error: ({ className, ...props }: React.ComponentProps<\"p\">) => <p role=\"alert\" className={s.error({ className })} {...props} />,\n};\n\ntype ControlProps = {\n /** Marks the control invalid: aria-invalid and data-invalid (pair it with a `Field.Error` in aria-describedby). */\n invalid?: boolean;\n};\n\nconst invalidProps = (invalid?: boolean) => (invalid ? { \"aria-invalid\": true as const, \"data-invalid\": \"\" } : {});\n\nexport function Input({ invalid, className, ...props }: React.ComponentProps<\"input\"> & ControlProps) {\n return <input {...invalidProps(invalid)} className={s.control({ className })} {...props} />;\n}\n\nexport function Textarea({ invalid, className, ...props }: React.ComponentProps<\"textarea\"> & ControlProps) {\n return <textarea {...invalidProps(invalid)} className={s.control({ className: cn(\"h-auto min-h-24 py-2\", className) })} {...props} />;\n}\n\n/** A native <select>, styled like the other controls (the platform's menu: accessible and right on phones). */\nexport function Select({ invalid, className, ...props }: React.ComponentProps<\"select\"> & ControlProps) {\n return (\n <span className={s.selectWrap()}>\n <select {...invalidProps(invalid)} className={s.control({ className: cn(\"appearance-none pr-9\", className) })} {...props} />\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden className={s.chevron()}>\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </span>\n );\n}\n"
9
+ },
10
+ {
11
+ "path": "field/index.ts",
12
+ "content": "/** @krizaka/ui/field — `Field.Root/Label/Hint/Error`, `Input`, `Textarea`, `Select`. Server-safe. */\nexport { Field, field, Input, Select, Textarea } from \"./field\";\n"
13
+ }
14
+ ],
15
+ "dependencies": [
16
+ "tailwind-variants@^3.3.1"
17
+ ],
18
+ "registryDependencies": [
19
+ "cn"
20
+ ],
21
+ "demo": {
22
+ "path": "demos/field.tsx",
23
+ "content": "import { Field, Input } from \"@krizaka/ui/field\";\n\nexport default function FieldDemo() {\n return (\n <Field.Root>\n <Field.Label htmlFor=\"email\">Email</Field.Label>\n <Input id=\"email\" type=\"email\" aria-describedby=\"email-hint\" placeholder=\"you@example.com\" />\n <Field.Hint id=\"email-hint\">We never share it.</Field.Hint>\n </Field.Root>\n );\n}\n"
24
+ },
25
+ "props": [
26
+ {
27
+ "component": "Input",
28
+ "description": "",
29
+ "props": [
30
+ {
31
+ "name": "invalid",
32
+ "type": "boolean",
33
+ "default": null,
34
+ "description": "Marks the control invalid: aria-invalid and data-invalid (pair it with a `Field.Error` in aria-describedby).",
35
+ "required": false
36
+ }
37
+ ]
38
+ },
39
+ {
40
+ "component": "Select",
41
+ "description": "A native <select>, styled like the other controls (the platform's menu: accessible and right on phones).",
42
+ "props": [
43
+ {
44
+ "name": "invalid",
45
+ "type": "boolean",
46
+ "default": null,
47
+ "description": "Marks the control invalid: aria-invalid and data-invalid (pair it with a `Field.Error` in aria-describedby).",
48
+ "required": false
49
+ }
50
+ ]
51
+ },
52
+ {
53
+ "component": "Textarea",
54
+ "description": "",
55
+ "props": [
56
+ {
57
+ "name": "invalid",
58
+ "type": "boolean",
59
+ "default": null,
60
+ "description": "Marks the control invalid: aria-invalid and data-invalid (pair it with a `Field.Error` in aria-describedby).",
61
+ "required": false
62
+ }
63
+ ]
64
+ }
65
+ ]
66
+ }
@@ -0,0 +1,320 @@
1
+ {
2
+ "name": "@krizaka/ui",
3
+ "version": "2.0.0-beta.4",
4
+ "items": [
5
+ {
6
+ "name": "alert",
7
+ "type": "primitive",
8
+ "description": "`Alert`, `alertVariants`. Server-safe.",
9
+ "dependencies": [
10
+ "tailwind-variants@^3.3.1"
11
+ ],
12
+ "registryDependencies": []
13
+ },
14
+ {
15
+ "name": "avatar",
16
+ "type": "primitive",
17
+ "description": "`Avatar`, `Avatar.Group`. Client (\"use client\").",
18
+ "dependencies": [
19
+ "radix-ui@^1.7.0",
20
+ "tailwind-variants@^3.3.1"
21
+ ],
22
+ "registryDependencies": []
23
+ },
24
+ {
25
+ "name": "badge",
26
+ "type": "primitive",
27
+ "description": "`Badge`, `badgeVariants`. Server-safe.",
28
+ "dependencies": [
29
+ "tailwind-variants@^3.3.1"
30
+ ],
31
+ "registryDependencies": []
32
+ },
33
+ {
34
+ "name": "button",
35
+ "type": "primitive",
36
+ "description": "`Button`, `IconButton`, `buttonVariants`. Server-safe.",
37
+ "dependencies": [
38
+ "radix-ui@^1.7.0",
39
+ "tailwind-variants@^3.3.1"
40
+ ],
41
+ "registryDependencies": []
42
+ },
43
+ {
44
+ "name": "card",
45
+ "type": "primitive",
46
+ "description": "`Card.*`, `card` (the slots). Server-safe.",
47
+ "dependencies": [
48
+ "radix-ui@^1.7.0",
49
+ "tailwind-variants@^3.3.1"
50
+ ],
51
+ "registryDependencies": [
52
+ "cn"
53
+ ]
54
+ },
55
+ {
56
+ "name": "checkbox",
57
+ "type": "primitive",
58
+ "description": "`Checkbox` (checked · unchecked · indeterminate), `checkbox` (the slots). Client (\"use client\").",
59
+ "dependencies": [
60
+ "radix-ui@^1.7.0",
61
+ "tailwind-variants@^3.3.1"
62
+ ],
63
+ "registryDependencies": []
64
+ },
65
+ {
66
+ "name": "chip",
67
+ "type": "primitive",
68
+ "description": "`Chip` (selectable, removable), `Chip.Group` (single · multiple), `chip` (the slots). Client (\"use client\").",
69
+ "dependencies": [
70
+ "radix-ui@^1.7.0",
71
+ "tailwind-variants@^3.3.1"
72
+ ],
73
+ "registryDependencies": []
74
+ },
75
+ {
76
+ "name": "cn",
77
+ "type": "primitive",
78
+ "description": "Merges Tailwind classes: the last one wins — a product's `className` overrides the primitive's. The merge engine is tailwind-merge as tailwind-variants ships it (the one `tv` uses), so the platform carries a single copy of it. tailwind-variants bundles that engine since 3.3 (it never imports the `tailwind-merge` package, an optional peer): hence `tailwind-variants ^3.3.1` and no `tailwind-merge` dependency — `scripts/consumer.mjs` checks it on a clean install of the packed package.",
79
+ "dependencies": [
80
+ "clsx@^2.1.1",
81
+ "tailwind-variants@^3.3.1"
82
+ ],
83
+ "registryDependencies": []
84
+ },
85
+ {
86
+ "name": "command",
87
+ "type": "primitive",
88
+ "description": "`Command.*` (cmdk) and `CommandDialog`, `command` (the slots). Client (\"use client\").",
89
+ "dependencies": [
90
+ "cmdk@^1.1.1",
91
+ "radix-ui@^1.7.0",
92
+ "tailwind-variants@^3.3.1"
93
+ ],
94
+ "registryDependencies": [
95
+ "cn",
96
+ "dialog"
97
+ ]
98
+ },
99
+ {
100
+ "name": "confirm-button",
101
+ "type": "primitive",
102
+ "description": "`ConfirmButton` (two steps: arm, then confirm). Client (\"use client\").",
103
+ "dependencies": [
104
+ "radix-ui@^1.7.0"
105
+ ],
106
+ "registryDependencies": [
107
+ "button",
108
+ "cn"
109
+ ]
110
+ },
111
+ {
112
+ "name": "countdown",
113
+ "type": "primitive",
114
+ "description": "`Countdown`, `useCountdown`, `splitDuration`. Client (\"use client\").",
115
+ "dependencies": [
116
+ "tailwind-variants@^3.3.1"
117
+ ],
118
+ "registryDependencies": []
119
+ },
120
+ {
121
+ "name": "dialog",
122
+ "type": "primitive",
123
+ "description": "`Dialog.*`, `Sheet`, `AlertDialog`, `dialog` (the slots). Client (\"use client\").",
124
+ "dependencies": [
125
+ "radix-ui@^1.7.0",
126
+ "tailwind-variants@^3.3.1"
127
+ ],
128
+ "registryDependencies": [
129
+ "button"
130
+ ]
131
+ },
132
+ {
133
+ "name": "dropdown-menu",
134
+ "type": "primitive",
135
+ "description": "`DropdownMenu.*`, `menu` (the slots). Client (\"use client\").",
136
+ "dependencies": [
137
+ "radix-ui@^1.7.0",
138
+ "tailwind-variants@^3.3.1"
139
+ ],
140
+ "registryDependencies": [
141
+ "cn"
142
+ ]
143
+ },
144
+ {
145
+ "name": "empty-state",
146
+ "type": "primitive",
147
+ "description": "`EmptyState`. Server-safe.",
148
+ "dependencies": [
149
+ "tailwind-variants@^3.3.1"
150
+ ],
151
+ "registryDependencies": []
152
+ },
153
+ {
154
+ "name": "field",
155
+ "type": "primitive",
156
+ "description": "`Field.Root/Label/Hint/Error`, `Input`, `Textarea`, `Select`. Server-safe.",
157
+ "dependencies": [
158
+ "tailwind-variants@^3.3.1"
159
+ ],
160
+ "registryDependencies": [
161
+ "cn"
162
+ ]
163
+ },
164
+ {
165
+ "name": "kbd",
166
+ "type": "primitive",
167
+ "description": "`Kbd`, `kbdVariants`. Server-safe.",
168
+ "dependencies": [
169
+ "tailwind-variants@^3.3.1"
170
+ ],
171
+ "registryDependencies": []
172
+ },
173
+ {
174
+ "name": "page-header",
175
+ "type": "primitive",
176
+ "description": "`PageHeader`, `pageHeader` (the slots). Server-safe.",
177
+ "dependencies": [
178
+ "tailwind-variants@^3.3.1"
179
+ ],
180
+ "registryDependencies": []
181
+ },
182
+ {
183
+ "name": "popover",
184
+ "type": "primitive",
185
+ "description": "`Popover.*`. Client (\"use client\").",
186
+ "dependencies": [
187
+ "radix-ui@^1.7.0"
188
+ ],
189
+ "registryDependencies": [
190
+ "cn"
191
+ ]
192
+ },
193
+ {
194
+ "name": "progress",
195
+ "type": "primitive",
196
+ "description": "`Progress` (bar · ring, indeterminate), `progress` (the slots). Server-safe.",
197
+ "dependencies": [
198
+ "tailwind-variants@^3.3.1"
199
+ ],
200
+ "registryDependencies": []
201
+ },
202
+ {
203
+ "name": "radio-group",
204
+ "type": "primitive",
205
+ "description": "`RadioGroup.Root/Item/Card`, `radioGroup` (the slots). Client (\"use client\").",
206
+ "dependencies": [
207
+ "radix-ui@^1.7.0",
208
+ "tailwind-variants@^3.3.1"
209
+ ],
210
+ "registryDependencies": []
211
+ },
212
+ {
213
+ "name": "separator",
214
+ "type": "primitive",
215
+ "description": "`Separator`, `separatorVariants` (Radix). Server-safe.",
216
+ "dependencies": [
217
+ "radix-ui@^1.7.0",
218
+ "tailwind-variants@^3.3.1"
219
+ ],
220
+ "registryDependencies": []
221
+ },
222
+ {
223
+ "name": "skeleton",
224
+ "type": "primitive",
225
+ "description": "`Skeleton`, `skeletonVariants`. Server-safe.",
226
+ "dependencies": [
227
+ "tailwind-variants@^3.3.1"
228
+ ],
229
+ "registryDependencies": []
230
+ },
231
+ {
232
+ "name": "slider",
233
+ "type": "primitive",
234
+ "description": "`Slider` (one value or a range), `slider` (the slots). Client (\"use client\").",
235
+ "dependencies": [
236
+ "radix-ui@^1.7.0",
237
+ "tailwind-variants@^3.3.1"
238
+ ],
239
+ "registryDependencies": []
240
+ },
241
+ {
242
+ "name": "slot",
243
+ "type": "primitive",
244
+ "description": "`Slot` (what `asChild` renders) and `VisuallyHidden` (a name for assistive technology only), from Radix.",
245
+ "dependencies": [
246
+ "radix-ui@^1.7.0"
247
+ ],
248
+ "registryDependencies": []
249
+ },
250
+ {
251
+ "name": "spinner",
252
+ "type": "primitive",
253
+ "description": "`Spinner`, `spinnerVariants`. Server-safe.",
254
+ "dependencies": [
255
+ "tailwind-variants@^3.3.1"
256
+ ],
257
+ "registryDependencies": []
258
+ },
259
+ {
260
+ "name": "stat",
261
+ "type": "primitive",
262
+ "description": "`Stat`, `stat` (the slots). Server-safe.",
263
+ "dependencies": [
264
+ "tailwind-variants@^3.3.1"
265
+ ],
266
+ "registryDependencies": []
267
+ },
268
+ {
269
+ "name": "switch",
270
+ "type": "primitive",
271
+ "description": "`Switch`, `switchVariants`. Client (\"use client\").",
272
+ "dependencies": [
273
+ "radix-ui@^1.7.0",
274
+ "tailwind-variants@^3.3.1"
275
+ ],
276
+ "registryDependencies": []
277
+ },
278
+ {
279
+ "name": "tabs",
280
+ "type": "primitive",
281
+ "description": "`Tabs.Root/List/Trigger/Content` (variant underline · segmented · pills), `tabs` (the slots). Client (\"use client\").",
282
+ "dependencies": [
283
+ "radix-ui@^1.7.0",
284
+ "tailwind-variants@^3.3.1"
285
+ ],
286
+ "registryDependencies": []
287
+ },
288
+ {
289
+ "name": "theme",
290
+ "type": "primitive",
291
+ "description": "`ThemeScript`, `ThemeProvider`, `useTheme`, `ThemeToggle`. Client (\"use client\").",
292
+ "dependencies": [],
293
+ "registryDependencies": [
294
+ "button"
295
+ ]
296
+ },
297
+ {
298
+ "name": "toast",
299
+ "type": "primitive",
300
+ "description": "`Toaster` (sonner, styled by roles), `toast`. Client (\"use client\").",
301
+ "dependencies": [
302
+ "sonner@^2.0.8"
303
+ ],
304
+ "registryDependencies": [
305
+ "cn"
306
+ ]
307
+ },
308
+ {
309
+ "name": "tooltip",
310
+ "type": "primitive",
311
+ "description": "`Tooltip`, `TooltipProvider`. Client (\"use client\").",
312
+ "dependencies": [
313
+ "radix-ui@^1.7.0"
314
+ ],
315
+ "registryDependencies": [
316
+ "cn"
317
+ ]
318
+ }
319
+ ]
320
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "kbd",
3
+ "type": "primitive",
4
+ "description": "`Kbd`, `kbdVariants`. Server-safe.",
5
+ "files": [
6
+ {
7
+ "path": "kbd/index.ts",
8
+ "content": "/** @krizaka/ui/kbd — `Kbd`, `kbdVariants`. Server-safe. */\nexport { Kbd, type KbdProps, kbdVariants } from \"./kbd\";\n"
9
+ },
10
+ {
11
+ "path": "kbd/kbd.tsx",
12
+ "content": "// 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"
13
+ }
14
+ ],
15
+ "dependencies": [
16
+ "tailwind-variants@^3.3.1"
17
+ ],
18
+ "registryDependencies": [],
19
+ "demo": {
20
+ "path": "demos/kbd.tsx",
21
+ "content": "import { Kbd } from \"@krizaka/ui/kbd\";\n\nexport default function KbdDemo() {\n return <Kbd>Esc</Kbd>;\n}\n"
22
+ },
23
+ "props": [
24
+ {
25
+ "component": "Kbd",
26
+ "description": "",
27
+ "props": [
28
+ {
29
+ "name": "size",
30
+ "type": "\"sm\" | \"md\"",
31
+ "default": "md",
32
+ "description": "sm · md.",
33
+ "required": false
34
+ }
35
+ ]
36
+ }
37
+ ]
38
+ }
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "page-header",
3
+ "type": "primitive",
4
+ "description": "`PageHeader`, `pageHeader` (the slots). Server-safe.",
5
+ "files": [
6
+ {
7
+ "path": "page-header/index.ts",
8
+ "content": "/** @krizaka/ui/page-header — `PageHeader`, `pageHeader` (the slots). Server-safe. */\nexport { PageHeader, pageHeader, type PageHeaderProps } from \"./page-header\";\n"
9
+ },
10
+ {
11
+ "path": "page-header/page-header.tsx",
12
+ "content": "// Server-safe. The top of a page: an optional breadcrumb, the title (h1), a description and the page's actions.\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nexport const pageHeader = tv({\n slots: {\n root: \"flex flex-col gap-3 border-b border-border-subtle pb-6\",\n breadcrumb: \"text-xs text-fg-secondary\",\n row: \"flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between\",\n text: \"flex min-w-0 flex-col gap-1.5\",\n title: \"font-display text-2xl font-black tracking-tight text-fg sm:text-3xl\",\n description: \"max-w-2xl text-sm text-fg-secondary\",\n actions: \"flex shrink-0 flex-wrap items-center gap-2\",\n },\n});\nconst s = pageHeader();\n\nexport type PageHeaderProps = Omit<React.ComponentProps<\"div\">, \"title\"> & {\n /** The title of the page (an `h1`, or `as=\"h2\"`). */\n title: React.ReactNode;\n /** A sentence under the title. */\n description?: React.ReactNode;\n /** The page's actions: Buttons, a DropdownMenu. */\n actions?: React.ReactNode;\n /** A breadcrumb (the product's own <nav aria-label>), shown above the title. */\n breadcrumb?: React.ReactNode;\n /** The heading level of the title: `h1` for a page, `h2` for a section that looks like one. */\n as?: \"h1\" | \"h2\";\n};\n\nexport function PageHeader({ title, description, actions, breadcrumb, as: Heading = \"h1\", className, ...props }: PageHeaderProps) {\n return (\n <div className={s.root({ className })} {...props}>\n {breadcrumb && <div className={s.breadcrumb()}>{breadcrumb}</div>}\n <div className={s.row()}>\n <div className={s.text()}>\n <Heading className={s.title()}>{title}</Heading>\n {description && <p className={s.description()}>{description}</p>}\n </div>\n {actions && <div className={s.actions()}>{actions}</div>}\n </div>\n </div>\n );\n}\n"
13
+ }
14
+ ],
15
+ "dependencies": [
16
+ "tailwind-variants@^3.3.1"
17
+ ],
18
+ "registryDependencies": [],
19
+ "demo": {
20
+ "path": "demos/page-header.tsx",
21
+ "content": "import { PageHeader } from \"@krizaka/ui/page-header\";\n\nexport default function PageHeaderDemo() {\n return <PageHeader title=\"Payouts\" description=\"Your earnings are paid every Monday to the account on file.\" />;\n}\n"
22
+ },
23
+ "props": [
24
+ {
25
+ "component": "PageHeader",
26
+ "description": "",
27
+ "props": [
28
+ {
29
+ "name": "title",
30
+ "type": "ReactNode",
31
+ "default": null,
32
+ "description": "The title of the page (an `h1`, or `as=\"h2\"`).",
33
+ "required": true
34
+ },
35
+ {
36
+ "name": "actions",
37
+ "type": "ReactNode",
38
+ "default": null,
39
+ "description": "The page's actions: Buttons, a DropdownMenu.",
40
+ "required": false
41
+ },
42
+ {
43
+ "name": "as",
44
+ "type": "\"h1\" | \"h2\"",
45
+ "default": "h1",
46
+ "description": "The heading level of the title: `h1` for a page, `h2` for a section that looks like one.",
47
+ "required": false
48
+ },
49
+ {
50
+ "name": "breadcrumb",
51
+ "type": "ReactNode",
52
+ "default": null,
53
+ "description": "A breadcrumb (the product's own <nav aria-label>), shown above the title.",
54
+ "required": false
55
+ },
56
+ {
57
+ "name": "description",
58
+ "type": "ReactNode",
59
+ "default": null,
60
+ "description": "A sentence under the title.",
61
+ "required": false
62
+ }
63
+ ]
64
+ }
65
+ ]
66
+ }