@krizaka/ui 2.0.0-beta.1 → 2.0.0-beta.3
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.
- package/README.md +44 -3
- package/dist/alert.d.ts +2 -0
- package/dist/alert.js.map +1 -1
- package/dist/avatar.d.ts +5 -0
- package/dist/avatar.js.map +1 -1
- package/dist/badge.d.ts +12 -0
- package/dist/badge.js.map +1 -1
- package/dist/button-8La7l0V4.d.ts +83 -0
- package/dist/button.d.ts +19 -0
- package/dist/button.js.map +1 -1
- package/dist/card.d.ts +24 -1
- package/dist/card.js +1 -1
- package/dist/card.js.map +1 -1
- package/dist/checkbox.d.ts +52 -0
- package/dist/checkbox.js +42 -0
- package/dist/checkbox.js.map +1 -0
- package/dist/chip.d.ts +120 -0
- package/dist/chip.js +93 -0
- package/dist/chip.js.map +1 -0
- package/dist/chunk-3X5MVH54.js +121 -0
- package/dist/chunk-3X5MVH54.js.map +1 -0
- package/dist/{chunk-RLOXWF2G.js → chunk-5AXLA4LK.js} +1 -1
- package/dist/chunk-5AXLA4LK.js.map +1 -0
- package/dist/{chunk-CPMZS4XA.js → chunk-FJDSLNXK.js} +1 -1
- package/dist/chunk-FJDSLNXK.js.map +1 -0
- package/dist/{chunk-QRG5RYEI.js → chunk-ZUD4U22H.js} +1 -1
- package/dist/chunk-ZUD4U22H.js.map +1 -0
- package/dist/cn.d.ts +3 -0
- package/dist/cn.js +1 -1
- package/dist/command.d.ts +159 -0
- package/dist/command.js +111 -0
- package/dist/command.js.map +1 -0
- package/dist/confirm-button.d.ts +23 -0
- package/dist/confirm-button.js +85 -0
- package/dist/confirm-button.js.map +1 -0
- package/dist/countdown.d.ts +3 -0
- package/dist/countdown.js.map +1 -1
- package/dist/dialog-GQ4Nvuyf.d.ts +157 -0
- package/dist/dialog.d.ts +12 -131
- package/dist/dialog.js +27 -91
- package/dist/dialog.js.map +1 -1
- package/dist/dropdown-menu.d.ts +1 -0
- package/dist/dropdown-menu.js +1 -1
- package/dist/dropdown-menu.js.map +1 -1
- package/dist/empty-state.d.ts +2 -0
- package/dist/empty-state.js.map +1 -1
- package/dist/field.js +1 -1
- package/dist/kbd.d.ts +7 -1
- package/dist/kbd.js.map +1 -1
- package/dist/motion.css +7 -1
- package/dist/page-header.d.ts +2 -0
- package/dist/page-header.js.map +1 -1
- package/dist/popover.js +1 -1
- package/dist/progress.d.ts +92 -0
- package/dist/progress.js +85 -0
- package/dist/progress.js.map +1 -0
- package/dist/radio-group.d.ts +77 -0
- package/dist/radio-group.js +48 -0
- package/dist/radio-group.js.map +1 -0
- package/dist/skeleton.d.ts +7 -1
- package/dist/skeleton.js.map +1 -1
- package/dist/slider.d.ts +90 -0
- package/dist/slider.js +82 -0
- package/dist/slider.js.map +1 -0
- package/dist/spinner.d.ts +5 -0
- package/dist/spinner.js.map +1 -1
- package/dist/stat.d.ts +2 -0
- package/dist/stat.js.map +1 -1
- package/dist/switch.d.ts +76 -0
- package/dist/switch.js +38 -0
- package/dist/switch.js.map +1 -0
- package/dist/tabs.d.ts +86 -0
- package/dist/tabs.js +60 -0
- package/dist/tabs.js.map +1 -0
- package/dist/theme.d.ts +11 -60
- package/dist/theme.js +4 -2
- package/dist/theme.js.map +1 -1
- package/dist/toast.js +1 -1
- package/dist/tooltip.d.ts +3 -0
- package/dist/tooltip.js +1 -1
- package/dist/tooltip.js.map +1 -1
- package/package.json +146 -6
- package/registry/alert.json +59 -0
- package/registry/avatar.json +114 -0
- package/registry/badge.json +59 -0
- package/registry/button.json +115 -0
- package/registry/card.json +154 -0
- package/registry/checkbox.json +46 -0
- package/registry/chip.json +164 -0
- package/registry/cn.json +21 -0
- package/registry/command.json +162 -0
- package/registry/confirm-button.json +104 -0
- package/registry/countdown.json +84 -0
- package/registry/demos/alert.d.ts +5 -0
- package/registry/demos/alert.js +12 -0
- package/registry/demos/alert.tsx +15 -0
- package/registry/demos/avatar.d.ts +5 -0
- package/registry/demos/avatar.js +14 -0
- package/registry/demos/avatar.tsx +13 -0
- package/registry/demos/badge.d.ts +5 -0
- package/registry/demos/badge.js +11 -0
- package/registry/demos/badge.tsx +5 -0
- package/registry/demos/button.d.ts +5 -0
- package/registry/demos/button.js +11 -0
- package/registry/demos/button.tsx +5 -0
- package/registry/demos/card.d.ts +5 -0
- package/registry/demos/card.js +30 -0
- package/registry/demos/card.tsx +37 -0
- package/registry/demos/checkbox.d.ts +5 -0
- package/registry/demos/checkbox.js +11 -0
- package/registry/demos/checkbox.tsx +5 -0
- package/registry/demos/chip.d.ts +5 -0
- package/registry/demos/chip.js +15 -0
- package/registry/demos/chip.tsx +11 -0
- package/registry/demos/cn.d.ts +7 -0
- package/registry/demos/cn.js +17 -0
- package/registry/demos/cn.tsx +9 -0
- package/registry/demos/command.d.ts +5 -0
- package/registry/demos/command.js +32 -0
- package/registry/demos/command.tsx +28 -0
- package/registry/demos/confirm-button.d.ts +5 -0
- package/registry/demos/confirm-button.js +12 -0
- package/registry/demos/confirm-button.tsx +13 -0
- package/registry/demos/countdown.d.ts +5 -0
- package/registry/demos/countdown.js +13 -0
- package/registry/demos/countdown.tsx +10 -0
- package/registry/demos/dialog.d.ts +7 -0
- package/registry/demos/dialog.js +29 -0
- package/registry/demos/dialog.tsx +31 -0
- package/registry/demos/dropdown-menu.d.ts +7 -0
- package/registry/demos/dropdown-menu.js +36 -0
- package/registry/demos/dropdown-menu.tsx +27 -0
- package/registry/demos/empty-state.d.ts +5 -0
- package/registry/demos/empty-state.js +15 -0
- package/registry/demos/empty-state.tsx +12 -0
- package/registry/demos/field.d.ts +5 -0
- package/registry/demos/field.js +15 -0
- package/registry/demos/field.tsx +11 -0
- package/registry/demos/kbd.d.ts +5 -0
- package/registry/demos/kbd.js +11 -0
- package/registry/demos/kbd.tsx +5 -0
- package/registry/demos/page-header.d.ts +5 -0
- package/registry/demos/page-header.js +11 -0
- package/registry/demos/page-header.tsx +5 -0
- package/registry/demos/popover.d.ts +7 -0
- package/registry/demos/popover.js +25 -0
- package/registry/demos/popover.tsx +31 -0
- package/registry/demos/progress.d.ts +5 -0
- package/registry/demos/progress.js +11 -0
- package/registry/demos/progress.tsx +5 -0
- package/registry/demos/radio-group.d.ts +5 -0
- package/registry/demos/radio-group.js +16 -0
- package/registry/demos/radio-group.tsx +14 -0
- package/registry/demos/separator.d.ts +5 -0
- package/registry/demos/separator.js +15 -0
- package/registry/demos/separator.tsx +11 -0
- package/registry/demos/skeleton.d.ts +5 -0
- package/registry/demos/skeleton.js +20 -0
- package/registry/demos/skeleton.tsx +16 -0
- package/registry/demos/slider.d.ts +5 -0
- package/registry/demos/slider.js +11 -0
- package/registry/demos/slider.tsx +5 -0
- package/registry/demos/slot.d.ts +5 -0
- package/registry/demos/slot.js +14 -0
- package/registry/demos/slot.tsx +13 -0
- package/registry/demos/spinner.d.ts +5 -0
- package/registry/demos/spinner.js +11 -0
- package/registry/demos/spinner.tsx +5 -0
- package/registry/demos/stat.d.ts +5 -0
- package/registry/demos/stat.js +11 -0
- package/registry/demos/stat.tsx +5 -0
- package/registry/demos/switch.d.ts +5 -0
- package/registry/demos/switch.js +11 -0
- package/registry/demos/switch.tsx +5 -0
- package/registry/demos/tabs.d.ts +5 -0
- package/registry/demos/tabs.js +22 -0
- package/registry/demos/tabs.tsx +28 -0
- package/registry/demos/theme.d.ts +5 -0
- package/registry/demos/theme.js +11 -0
- package/registry/demos/theme.tsx +9 -0
- package/registry/demos/toast.d.ts +8 -0
- package/registry/demos/toast.js +29 -0
- package/registry/demos/toast.tsx +31 -0
- package/registry/demos/tooltip.d.ts +7 -0
- package/registry/demos/tooltip.js +15 -0
- package/registry/demos/tooltip.tsx +15 -0
- package/registry/dialog.json +218 -0
- package/registry/dropdown-menu.json +63 -0
- package/registry/empty-state.json +59 -0
- package/registry/field.json +66 -0
- package/registry/index.json +320 -0
- package/registry/kbd.json +38 -0
- package/registry/page-header.json +66 -0
- package/registry/popover.json +44 -0
- package/registry/progress.json +80 -0
- package/registry/radio-group.json +64 -0
- package/registry/separator.json +25 -0
- package/registry/skeleton.json +38 -0
- package/registry/slider.json +95 -0
- package/registry/slot.json +31 -0
- package/registry/spinner.json +45 -0
- package/registry/stat.json +66 -0
- package/registry/switch.json +53 -0
- package/registry/tabs.json +44 -0
- package/registry/theme.json +78 -0
- package/registry/toast.json +54 -0
- package/registry/tooltip.json +91 -0
- package/dist/chunk-CPMZS4XA.js.map +0 -1
- package/dist/chunk-QRG5RYEI.js.map +0 -1
- package/dist/chunk-RLOXWF2G.js.map +0 -1
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "command",
|
|
3
|
+
"type": "primitive",
|
|
4
|
+
"description": "`Command.*` (cmdk) and `CommandDialog`, `command` (the slots). Client (\"use client\").",
|
|
5
|
+
"files": [
|
|
6
|
+
{
|
|
7
|
+
"path": "command/command.tsx",
|
|
8
|
+
"content": "// 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"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"path": "command/index.ts",
|
|
12
|
+
"content": "/** @krizaka/ui/command — `Command.*` (cmdk) and `CommandDialog`, `command` (the slots). Client (\"use client\"). */\nexport {\n Command,\n command,\n CommandDialog,\n type CommandDialogProps,\n CommandEmpty,\n type CommandEmptyProps,\n CommandGroup,\n CommandInput,\n type CommandInputProps,\n CommandItem,\n CommandList,\n type CommandListProps,\n CommandLoading,\n CommandRoot,\n type CommandRootProps,\n CommandSeparator,\n CommandShortcut,\n} from \"./command\";\n"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"dependencies": [
|
|
16
|
+
"cmdk@^1.1.1",
|
|
17
|
+
"radix-ui@^1.7.0",
|
|
18
|
+
"tailwind-variants@^3.3.1"
|
|
19
|
+
],
|
|
20
|
+
"registryDependencies": [
|
|
21
|
+
"cn",
|
|
22
|
+
"dialog"
|
|
23
|
+
],
|
|
24
|
+
"demo": {
|
|
25
|
+
"path": "demos/command.tsx",
|
|
26
|
+
"content": "import { Command } from \"@krizaka/ui/command\";\n\nexport default function CommandDemo() {\n return (\n <Command.Root label=\"Commands\" className=\"w-[28rem] max-w-full rounded-xl border border-border-default shadow-lg\">\n <Command.Input placeholder=\"Type a command or search\" />\n <Command.List label=\"Suggestions\">\n <Command.Empty emptyLabel=\"Nothing matches.\" />\n <Command.Group heading=\"Pages\">\n <Command.Item>\n Home\n <Command.Shortcut>G H</Command.Shortcut>\n </Command.Item>\n <Command.Item>\n Wallet\n <Command.Shortcut>G W</Command.Shortcut>\n </Command.Item>\n <Command.Item disabled>Studio</Command.Item>\n </Command.Group>\n <Command.Separator />\n <Command.Group heading=\"Actions\">\n <Command.Item keywords={[\"video\", \"new\"]}>Upload a video</Command.Item>\n <Command.Item>Switch the theme</Command.Item>\n </Command.Group>\n </Command.List>\n </Command.Root>\n );\n}\n"
|
|
27
|
+
},
|
|
28
|
+
"props": [
|
|
29
|
+
{
|
|
30
|
+
"component": "CommandRoot",
|
|
31
|
+
"description": "The palette: `value` / `onValueChange` (the active item), `shouldFilter`, `filter`, `loop`.",
|
|
32
|
+
"props": [
|
|
33
|
+
{
|
|
34
|
+
"name": "label",
|
|
35
|
+
"type": "string",
|
|
36
|
+
"default": null,
|
|
37
|
+
"description": "Accessible label for this command menu. Not shown visibly.\nThe accessible name of the palette — passed translated (\"Search\", \"Commands\").",
|
|
38
|
+
"required": false
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"component": "CommandInput",
|
|
44
|
+
"description": "The search field (`value` / `onValueChange` for the query), with a magnifier.",
|
|
45
|
+
"props": [
|
|
46
|
+
{
|
|
47
|
+
"name": "placeholder",
|
|
48
|
+
"type": "string",
|
|
49
|
+
"default": null,
|
|
50
|
+
"description": "What to type — passed translated. The input is named by the palette's `label`.",
|
|
51
|
+
"required": true
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"name": "trailing",
|
|
55
|
+
"type": "ReactNode",
|
|
56
|
+
"default": null,
|
|
57
|
+
"description": "After the input, inside the bar: a spinner, a clear button.",
|
|
58
|
+
"required": false
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"component": "CommandList",
|
|
64
|
+
"description": "",
|
|
65
|
+
"props": [
|
|
66
|
+
{
|
|
67
|
+
"name": "label",
|
|
68
|
+
"type": "string",
|
|
69
|
+
"default": null,
|
|
70
|
+
"description": "Accessible label for this List of suggestions. Not shown visibly.\nThe accessible name of the list of results — passed translated (\"Suggestions\", \"Results\").",
|
|
71
|
+
"required": false
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"component": "CommandEmpty",
|
|
77
|
+
"description": "Shown by cmdk only when no item matches.",
|
|
78
|
+
"props": [
|
|
79
|
+
{
|
|
80
|
+
"name": "emptyLabel",
|
|
81
|
+
"type": "ReactNode",
|
|
82
|
+
"default": null,
|
|
83
|
+
"description": "Shown when nothing matches — passed translated.",
|
|
84
|
+
"required": true
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"component": "CommandLoading",
|
|
90
|
+
"description": "While results load (`label` is announced).",
|
|
91
|
+
"props": []
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"component": "CommandGroup",
|
|
95
|
+
"description": "A group of items under a `heading`.",
|
|
96
|
+
"props": []
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"component": "CommandItem",
|
|
100
|
+
"description": "An option: `onSelect` on Enter or click, `value` and `keywords` for the filter, `disabled`.",
|
|
101
|
+
"props": []
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"component": "CommandSeparator",
|
|
105
|
+
"description": "A line between groups. Decorative (`role=\"none\"`): cmdk's own separator is a role a listbox may not hold (axe).",
|
|
106
|
+
"props": []
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"component": "CommandShortcut",
|
|
110
|
+
"description": "A keyboard hint at the end of an item.",
|
|
111
|
+
"props": []
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"component": "CommandDialog",
|
|
115
|
+
"description": "The palette in a dialog (Radix: focus trap, Escape, focus return). The dialog is named by `label`; it has no close\nbutton — Escape and a click outside close it — and the input takes the focus when it opens.",
|
|
116
|
+
"props": [
|
|
117
|
+
{
|
|
118
|
+
"name": "contentProps",
|
|
119
|
+
"type": "Omit<DialogContentProps & RefAttributes<HTMLDivElement> & DialogVariants & { closeLabel?: string; hideClose: true; } & { ...; }, \"children\" | ... 1 more ... | \"hideClose\">",
|
|
120
|
+
"default": null,
|
|
121
|
+
"description": "Passed to `Dialog.Content`: `size`, `container`, `className` of the dialog.",
|
|
122
|
+
"required": false
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"name": "defaultOpen",
|
|
126
|
+
"type": "boolean",
|
|
127
|
+
"default": null,
|
|
128
|
+
"description": "Open at first, uncontrolled.",
|
|
129
|
+
"required": false
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"name": "footer",
|
|
133
|
+
"type": "ReactNode",
|
|
134
|
+
"default": null,
|
|
135
|
+
"description": "Under the palette, inside the dialog: shortcuts, a \"see all results\" link.",
|
|
136
|
+
"required": false
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"name": "label",
|
|
140
|
+
"type": "string",
|
|
141
|
+
"default": null,
|
|
142
|
+
"description": "Accessible label for this command menu. Not shown visibly.\nThe accessible name of the palette — passed translated (\"Search\", \"Commands\").",
|
|
143
|
+
"required": false
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"name": "onOpenChange",
|
|
147
|
+
"type": "((open: boolean) => void)",
|
|
148
|
+
"default": null,
|
|
149
|
+
"description": "Called when it opens or closes (Escape, a click outside, a shortcut of the product).",
|
|
150
|
+
"required": false
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"name": "open",
|
|
154
|
+
"type": "boolean",
|
|
155
|
+
"default": null,
|
|
156
|
+
"description": "Open or closed (controlled), with `onOpenChange`.",
|
|
157
|
+
"required": false
|
|
158
|
+
}
|
|
159
|
+
]
|
|
160
|
+
}
|
|
161
|
+
]
|
|
162
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "confirm-button",
|
|
3
|
+
"type": "primitive",
|
|
4
|
+
"description": "`ConfirmButton` (two steps: arm, then confirm). Client (\"use client\").",
|
|
5
|
+
"files": [
|
|
6
|
+
{
|
|
7
|
+
"path": "confirm-button/confirm-button.tsx",
|
|
8
|
+
"content": "// Client (a state). A destructive action confirmed by a second press, never `window.confirm`: the first press arms it\n// and says what will happen (`confirmLabel`, announced politely), the second runs `onConfirm`. It disarms by itself\n// after `timeoutMs`, on Escape, and when the focus leaves. The danger is the border and the tint; the words stay a\n// text role (contrast AA in both themes).\nimport { VisuallyHidden } from \"radix-ui\";\nimport * as React from \"react\";\n\nimport { Button, type ButtonProps } from \"../button/button\";\nimport { cn } from \"../cn\";\n\nexport const confirmArmed = \"border border-danger bg-danger/20 text-fg hover:border-danger hover:bg-danger/30\";\n\nexport type ConfirmButtonProps = Omit<ButtonProps, \"onClick\" | \"asChild\"> & {\n /** What the second press does, in words — shown and announced once armed (\"Delete for good?\"). Passed translated. */\n confirmLabel: string;\n /** The accessible name while idle, for an icon-only button (the confirm label names it once armed). */\n label?: string;\n /** Runs on the second press. */\n onConfirm: () => void;\n /** Disarms after this many milliseconds (4000 by default). */\n timeoutMs?: number;\n /** What it shows once armed (default: its children, then `confirmLabel`). */\n armedContent?: React.ReactNode;\n /** Notified when it arms and disarms. */\n onArmedChange?: (armed: boolean) => void;\n};\n\n/** A two-step button: press to arm, press again within `timeoutMs` to confirm. State: `data-armed`. */\nexport function ConfirmButton({\n confirmLabel,\n label,\n onConfirm,\n timeoutMs = 4000,\n onArmedChange,\n armedContent,\n variant = \"ghost\",\n className,\n children,\n onBlur,\n onKeyDown,\n ...props\n}: ConfirmButtonProps) {\n const [armed, setArmedState] = React.useState(false);\n const armedRef = React.useRef(false);\n const onArmedChangeRef = React.useRef(onArmedChange);\n React.useEffect(() => {\n onArmedChangeRef.current = onArmedChange;\n }, [onArmedChange]);\n const setArmed = React.useCallback((next: boolean) => {\n if (armedRef.current === next) return;\n armedRef.current = next;\n setArmedState(next);\n onArmedChangeRef.current?.(next);\n }, []);\n React.useEffect(() => {\n if (!armed) return;\n const timer = window.setTimeout(() => setArmed(false), timeoutMs);\n return () => window.clearTimeout(timer);\n }, [armed, timeoutMs, setArmed]);\n const name = armed ? confirmLabel : label;\n return (\n <>\n <Button\n variant={variant}\n aria-label={name}\n title={name}\n data-armed={armed ? \"\" : undefined}\n className={cn(armed && confirmArmed, className)}\n onClick={() => {\n if (!armed) return setArmed(true);\n setArmed(false);\n onConfirm();\n }}\n onBlur={(event) => {\n onBlur?.(event);\n setArmed(false);\n }}\n onKeyDown={(event) => {\n onKeyDown?.(event);\n if (armed && event.key === \"Escape\") {\n event.stopPropagation();\n setArmed(false);\n }\n }}\n {...props}\n >\n {armed\n ? (armedContent ?? (\n <>\n {children}\n <span>{confirmLabel}</span>\n </>\n ))\n : children}\n </Button>\n <VisuallyHidden.Root aria-live=\"polite\">{armed ? confirmLabel : \"\"}</VisuallyHidden.Root>\n </>\n );\n}\n"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"path": "confirm-button/index.ts",
|
|
12
|
+
"content": "/** @krizaka/ui/confirm-button — `ConfirmButton` (two steps: arm, then confirm). Client (\"use client\"). */\nexport { confirmArmed, ConfirmButton, type ConfirmButtonProps } from \"./confirm-button\";\n"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"dependencies": [
|
|
16
|
+
"radix-ui@^1.7.0"
|
|
17
|
+
],
|
|
18
|
+
"registryDependencies": [
|
|
19
|
+
"button",
|
|
20
|
+
"cn"
|
|
21
|
+
],
|
|
22
|
+
"demo": {
|
|
23
|
+
"path": "demos/confirm-button.tsx",
|
|
24
|
+
"content": "\"use client\";\n\nimport { ConfirmButton } from \"@krizaka/ui/confirm-button\";\n\nexport default function ConfirmButtonDemo() {\n return (\n <ConfirmButton label=\"Delete the comment\" confirmLabel=\"Delete?\" size=\"sm\" onConfirm={() => {}}>\n <svg viewBox=\"0 0 24 24\" className=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M3 6h18M8 6V4h8v2M19 6l-1 14H6L5 6\" />\n </svg>\n </ConfirmButton>\n );\n}\n"
|
|
25
|
+
},
|
|
26
|
+
"props": [
|
|
27
|
+
{
|
|
28
|
+
"component": "ConfirmButton",
|
|
29
|
+
"description": "A two-step button: press to arm, press again within `timeoutMs` to confirm. State: `data-armed`.",
|
|
30
|
+
"props": [
|
|
31
|
+
{
|
|
32
|
+
"name": "confirmLabel",
|
|
33
|
+
"type": "string",
|
|
34
|
+
"default": null,
|
|
35
|
+
"description": "What the second press does, in words — shown and announced once armed (\"Delete for good?\"). Passed translated.",
|
|
36
|
+
"required": true
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"name": "onConfirm",
|
|
40
|
+
"type": "() => void",
|
|
41
|
+
"default": null,
|
|
42
|
+
"description": "Runs on the second press.",
|
|
43
|
+
"required": true
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"name": "armedContent",
|
|
47
|
+
"type": "ReactNode",
|
|
48
|
+
"default": null,
|
|
49
|
+
"description": "What it shows once armed (default: its children, then `confirmLabel`).",
|
|
50
|
+
"required": false
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"name": "label",
|
|
54
|
+
"type": "string",
|
|
55
|
+
"default": null,
|
|
56
|
+
"description": "The accessible name while idle, for an icon-only button (the confirm label names it once armed).",
|
|
57
|
+
"required": false
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"name": "loading",
|
|
61
|
+
"type": "boolean",
|
|
62
|
+
"default": null,
|
|
63
|
+
"description": "Disables and signals the wait (aria-busy, data-loading) — the product adds a spinner if it wants one.",
|
|
64
|
+
"required": false
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"name": "onArmedChange",
|
|
68
|
+
"type": "((armed: boolean) => void)",
|
|
69
|
+
"default": null,
|
|
70
|
+
"description": "Notified when it arms and disarms.",
|
|
71
|
+
"required": false
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"name": "shape",
|
|
75
|
+
"type": "\"rounded\" | \"pill\"",
|
|
76
|
+
"default": "rounded",
|
|
77
|
+
"description": "rounded · pill.",
|
|
78
|
+
"required": false
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"name": "size",
|
|
82
|
+
"type": "\"icon\" | \"sm\" | \"md\" | \"lg\"",
|
|
83
|
+
"default": "md",
|
|
84
|
+
"description": "sm · md · lg, or `icon` (a square).",
|
|
85
|
+
"required": false
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"name": "timeoutMs",
|
|
89
|
+
"type": "number",
|
|
90
|
+
"default": "4000",
|
|
91
|
+
"description": "Disarms after this many milliseconds (4000 by default).",
|
|
92
|
+
"required": false
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"name": "variant",
|
|
96
|
+
"type": "\"danger\" | \"primary\" | \"secondary\" | \"outline\" | \"ghost\"",
|
|
97
|
+
"default": "ghost",
|
|
98
|
+
"description": "The look: `primary` (the accent), `secondary` (a raised surface), `outline`, `ghost`, `danger`.",
|
|
99
|
+
"required": false
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "countdown",
|
|
3
|
+
"type": "primitive",
|
|
4
|
+
"description": "`Countdown`, `useCountdown`, `splitDuration`. Client (\"use client\").",
|
|
5
|
+
"files": [
|
|
6
|
+
{
|
|
7
|
+
"path": "countdown/core.ts",
|
|
8
|
+
"content": "// 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"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"path": "countdown/countdown.tsx",
|
|
12
|
+
"content": "// 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"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"path": "countdown/index.ts",
|
|
16
|
+
"content": "/** @krizaka/ui/countdown — `Countdown`, `useCountdown`, `splitDuration`. Client (\"use client\"). */\nexport { countdownParts, type CountdownUnits, splitDuration, useCountdown } from \"./core\";\nexport { Countdown, type CountdownProps } from \"./countdown\";\n"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"dependencies": [
|
|
20
|
+
"tailwind-variants@^3.3.1"
|
|
21
|
+
],
|
|
22
|
+
"registryDependencies": [],
|
|
23
|
+
"demo": {
|
|
24
|
+
"path": "demos/countdown.tsx",
|
|
25
|
+
"content": "\"use client\";\n\nimport { Countdown } from \"@krizaka/ui/countdown\";\nimport { useState } from \"react\";\n\nexport default function CountdownDemo() {\n // One hour, two minutes and three seconds from the first render.\n const [target] = useState(() => Date.now() + 3_723_000);\n return <Countdown target={target} units={{ d: \"d\", h: \"h\", m: \"m\", s: \"s\" }} label=\"Ends in\" />;\n}\n"
|
|
26
|
+
},
|
|
27
|
+
"props": [
|
|
28
|
+
{
|
|
29
|
+
"component": "Countdown",
|
|
30
|
+
"description": "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).\nWords come from the app: `units` are the short unit labels. `role=\"timer\"` without live announcements — the app\nannounces what matters. State: `data-urgent`, `data-ended`.\n\nThe danger role is large-text safe (≥ 3:1) from `size=\"md\"`; at `size=\"sm\"` an urgent countdown in light mode is\nunder the 4.5:1 of small text.",
|
|
31
|
+
"props": [
|
|
32
|
+
{
|
|
33
|
+
"name": "label",
|
|
34
|
+
"type": "string",
|
|
35
|
+
"default": null,
|
|
36
|
+
"description": "Accessible name, e.g. \"Ends in\".",
|
|
37
|
+
"required": true
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "target",
|
|
41
|
+
"type": "string | number | Date",
|
|
42
|
+
"default": null,
|
|
43
|
+
"description": "The moment it counts down to: a Date, an ISO string or epoch milliseconds.",
|
|
44
|
+
"required": true
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"name": "units",
|
|
48
|
+
"type": "CountdownUnits",
|
|
49
|
+
"default": null,
|
|
50
|
+
"description": "The short unit labels, passed translated.",
|
|
51
|
+
"required": true
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"name": "className",
|
|
55
|
+
"type": "string",
|
|
56
|
+
"default": null,
|
|
57
|
+
"description": "Classes merged last, over the primitive's.",
|
|
58
|
+
"required": false
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"name": "size",
|
|
62
|
+
"type": "\"sm\" | \"md\" | \"lg\"",
|
|
63
|
+
"default": "md",
|
|
64
|
+
"description": "sm · md · lg (the danger role is large-text safe from `md`).",
|
|
65
|
+
"required": false
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"name": "skewMs",
|
|
69
|
+
"type": "number",
|
|
70
|
+
"default": "0",
|
|
71
|
+
"description": "Server clock − this clock, in milliseconds.",
|
|
72
|
+
"required": false
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"name": "urgentBelowMs",
|
|
76
|
+
"type": "number",
|
|
77
|
+
"default": "60000",
|
|
78
|
+
"description": "Below this many milliseconds it turns urgent (`text-danger`, the last segment pulses). Default 60 s.",
|
|
79
|
+
"required": false
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// registry/demos/alert.tsx
|
|
4
|
+
import { Alert } from "@krizaka/ui/alert";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
var INFO = /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M12 16v-4M12 8h.01M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20Z" }) });
|
|
7
|
+
function AlertDemo() {
|
|
8
|
+
return /* @__PURE__ */ jsx(Alert, { title: "New payout schedule", icon: INFO, children: "Payouts now arrive every Monday." });
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
AlertDemo as default
|
|
12
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Alert } from "@krizaka/ui/alert";
|
|
2
|
+
|
|
3
|
+
const INFO = (
|
|
4
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
5
|
+
<path d="M12 16v-4M12 8h.01M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20Z" />
|
|
6
|
+
</svg>
|
|
7
|
+
);
|
|
8
|
+
|
|
9
|
+
export default function AlertDemo() {
|
|
10
|
+
return (
|
|
11
|
+
<Alert title="New payout schedule" icon={INFO}>
|
|
12
|
+
Payouts now arrive every Monday.
|
|
13
|
+
</Alert>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// registry/demos/avatar.tsx
|
|
4
|
+
import { Avatar } from "@krizaka/ui/avatar";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
var PORTRAIT = "data:image/svg+xml;utf8," + encodeURIComponent(
|
|
7
|
+
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80"><rect width="80" height="80" fill="#3b82f6"/><circle cx="40" cy="31" r="14" fill="#dbeafe"/><path d="M12 80a28 24 0 0 1 56 0z" fill="#dbeafe"/></svg>'
|
|
8
|
+
);
|
|
9
|
+
function AvatarDemo() {
|
|
10
|
+
return /* @__PURE__ */ jsx(Avatar, { src: PORTRAIT, alt: "Oussama", fallback: "OA" });
|
|
11
|
+
}
|
|
12
|
+
export {
|
|
13
|
+
AvatarDemo as default
|
|
14
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Avatar } from "@krizaka/ui/avatar";
|
|
2
|
+
|
|
3
|
+
// A self-contained portrait (no network).
|
|
4
|
+
const PORTRAIT =
|
|
5
|
+
"data:image/svg+xml;utf8," +
|
|
6
|
+
encodeURIComponent(
|
|
7
|
+
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80"><rect width="80" height="80" fill="#3b82f6"/>' +
|
|
8
|
+
'<circle cx="40" cy="31" r="14" fill="#dbeafe"/><path d="M12 80a28 24 0 0 1 56 0z" fill="#dbeafe"/></svg>',
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
export default function AvatarDemo() {
|
|
12
|
+
return <Avatar src={PORTRAIT} alt="Oussama" fallback="OA" />;
|
|
13
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// registry/demos/badge.tsx
|
|
4
|
+
import { Badge } from "@krizaka/ui/badge";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
function BadgeDemo() {
|
|
7
|
+
return /* @__PURE__ */ jsx(Badge, { children: "New" });
|
|
8
|
+
}
|
|
9
|
+
export {
|
|
10
|
+
BadgeDemo as default
|
|
11
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// registry/demos/button.tsx
|
|
4
|
+
import { Button } from "@krizaka/ui/button";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
function ButtonDemo() {
|
|
7
|
+
return /* @__PURE__ */ jsx(Button, { variant: "primary", children: "Continue" });
|
|
8
|
+
}
|
|
9
|
+
export {
|
|
10
|
+
ButtonDemo as default
|
|
11
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// registry/demos/card.tsx
|
|
4
|
+
import { Badge } from "@krizaka/ui/badge";
|
|
5
|
+
import { Card } from "@krizaka/ui/card";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
var COVER = "data:image/svg+xml;utf8," + encodeURIComponent(
|
|
8
|
+
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 90"><defs><linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#1e3a8a"/><stop offset="1" stop-color="#7c3aed"/></linearGradient></defs><rect width="160" height="90" fill="url(#g)"/><circle cx="118" cy="30" r="14" fill="#fde68a"/><path d="M0 90 50 44l30 28 22-18 58 36z" fill="#0f172a" opacity=".55"/></svg>'
|
|
9
|
+
);
|
|
10
|
+
function CardDemo() {
|
|
11
|
+
return /* @__PURE__ */ jsxs(Card.Root, { children: [
|
|
12
|
+
/* @__PURE__ */ jsxs(Card.Media, { children: [
|
|
13
|
+
/* @__PURE__ */ jsx(Card.Image, { src: COVER }),
|
|
14
|
+
/* @__PURE__ */ jsx(Card.Overlay, { children: /* @__PURE__ */ jsx(Badge, { tone: "scrim", children: "4K" }) }),
|
|
15
|
+
/* @__PURE__ */ jsx(Card.Overlay, { corner: "bottom-right", children: /* @__PURE__ */ jsx(Badge, { tone: "scrim", children: "12:04" }) })
|
|
16
|
+
] }),
|
|
17
|
+
/* @__PURE__ */ jsxs(Card.Body, { children: [
|
|
18
|
+
/* @__PURE__ */ jsx(Card.Title, { children: "Night ride across the city" }),
|
|
19
|
+
/* @__PURE__ */ jsx(Card.Description, { children: "Ten minutes of neon, rain and empty avenues, filmed in one take." }),
|
|
20
|
+
/* @__PURE__ */ jsxs(Card.Footer, { children: [
|
|
21
|
+
/* @__PURE__ */ jsx("span", { children: "1.2k views" }),
|
|
22
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "\xB7" }),
|
|
23
|
+
/* @__PURE__ */ jsx("span", { children: "2 days ago" })
|
|
24
|
+
] })
|
|
25
|
+
] })
|
|
26
|
+
] });
|
|
27
|
+
}
|
|
28
|
+
export {
|
|
29
|
+
CardDemo as default
|
|
30
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Badge } from "@krizaka/ui/badge";
|
|
2
|
+
import { Card } from "@krizaka/ui/card";
|
|
3
|
+
|
|
4
|
+
// A self-contained cover (no network).
|
|
5
|
+
const COVER =
|
|
6
|
+
"data:image/svg+xml;utf8," +
|
|
7
|
+
encodeURIComponent(
|
|
8
|
+
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 90"><defs><linearGradient id="g" x1="0" y1="0" x2="1" y2="1">' +
|
|
9
|
+
'<stop offset="0" stop-color="#1e3a8a"/><stop offset="1" stop-color="#7c3aed"/></linearGradient></defs>' +
|
|
10
|
+
'<rect width="160" height="90" fill="url(#g)"/><circle cx="118" cy="30" r="14" fill="#fde68a"/>' +
|
|
11
|
+
'<path d="M0 90 50 44l30 28 22-18 58 36z" fill="#0f172a" opacity=".55"/></svg>',
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
export default function CardDemo() {
|
|
15
|
+
return (
|
|
16
|
+
<Card.Root>
|
|
17
|
+
<Card.Media>
|
|
18
|
+
<Card.Image src={COVER} />
|
|
19
|
+
<Card.Overlay>
|
|
20
|
+
<Badge tone="scrim">4K</Badge>
|
|
21
|
+
</Card.Overlay>
|
|
22
|
+
<Card.Overlay corner="bottom-right">
|
|
23
|
+
<Badge tone="scrim">12:04</Badge>
|
|
24
|
+
</Card.Overlay>
|
|
25
|
+
</Card.Media>
|
|
26
|
+
<Card.Body>
|
|
27
|
+
<Card.Title>Night ride across the city</Card.Title>
|
|
28
|
+
<Card.Description>Ten minutes of neon, rain and empty avenues, filmed in one take.</Card.Description>
|
|
29
|
+
<Card.Footer>
|
|
30
|
+
<span>1.2k views</span>
|
|
31
|
+
<span aria-hidden>·</span>
|
|
32
|
+
<span>2 days ago</span>
|
|
33
|
+
</Card.Footer>
|
|
34
|
+
</Card.Body>
|
|
35
|
+
</Card.Root>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// registry/demos/checkbox.tsx
|
|
4
|
+
import { Checkbox } from "@krizaka/ui/checkbox";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
function CheckboxDemo() {
|
|
7
|
+
return /* @__PURE__ */ jsx(Checkbox, { children: "I accept the terms of use" });
|
|
8
|
+
}
|
|
9
|
+
export {
|
|
10
|
+
CheckboxDemo as default
|
|
11
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// registry/demos/chip.tsx
|
|
4
|
+
import { Chip } from "@krizaka/ui/chip";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
function ChipDemo() {
|
|
7
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
8
|
+
/* @__PURE__ */ jsx(Chip, { children: "Subtitles" }),
|
|
9
|
+
/* @__PURE__ */ jsx(Chip, { defaultSelected: true, children: "HD" }),
|
|
10
|
+
/* @__PURE__ */ jsx(Chip, { disabled: true, children: "4K" })
|
|
11
|
+
] });
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
ChipDemo as default
|
|
15
|
+
};
|