@krizaka/ui 2.0.0-beta.1 → 2.0.0-beta.2
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 +14 -3
- package/dist/button-G5qY4qSY.d.ts +68 -0
- package/dist/card.js +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 +97 -0
- package/dist/chip.js +93 -0
- package/dist/chip.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-5FRYKFTO.js +121 -0
- package/dist/chunk-5FRYKFTO.js.map +1 -0
- package/dist/{chunk-CPMZS4XA.js → chunk-FJDSLNXK.js} +1 -1
- package/dist/chunk-FJDSLNXK.js.map +1 -0
- package/dist/cn.d.ts +3 -0
- package/dist/cn.js +1 -1
- package/dist/command.d.ts +156 -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/dialog-DGBY2grk.d.ts +147 -0
- package/dist/dialog.d.ts +4 -131
- package/dist/dialog.js +26 -90
- package/dist/dialog.js.map +1 -1
- package/dist/dropdown-menu.js +1 -1
- package/dist/field.js +1 -1
- package/dist/motion.css +7 -1
- package/dist/popover.js +1 -1
- package/dist/progress.d.ts +87 -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/slider.d.ts +88 -0
- package/dist/slider.js +82 -0
- package/dist/slider.js.map +1 -0
- package/dist/switch.d.ts +72 -0
- package/dist/switch.js +38 -0
- package/dist/switch.js.map +1 -0
- package/dist/tabs.d.ts +83 -0
- package/dist/tabs.js +60 -0
- package/dist/tabs.js.map +1 -0
- package/dist/theme.d.ts +2 -59
- package/dist/toast.js +1 -1
- package/dist/tooltip.js +1 -1
- package/package.json +134 -5
- package/dist/chunk-CPMZS4XA.js.map +0 -1
- package/dist/chunk-RLOXWF2G.js.map +0 -1
package/README.md
CHANGED
|
@@ -27,8 +27,9 @@ is one CSS file. The primitives: **React 19** and Tailwind CSS v4 with the Kriza
|
|
|
27
27
|
|
|
28
28
|
## Primitives
|
|
29
29
|
|
|
30
|
-
> 2.0 beta: the atoms,
|
|
31
|
-
> menus, tooltips)
|
|
30
|
+
> 2.0 beta: the atoms, the structure of a page and what opens over it (cards, dialogs, sheets, toasts, popovers,
|
|
31
|
+
> menus, tooltips), then navigation and input (tabs, chips, switches, sliders, checkboxes, radios, the command palette,
|
|
32
|
+
> the two-step confirm button, progress).
|
|
32
33
|
|
|
33
34
|
### Install
|
|
34
35
|
|
|
@@ -129,7 +130,7 @@ Colours are roles of the preset (`bg-surface-2`, `text-fg-secondary`, `border-bo
|
|
|
129
130
|
| `@krizaka/ui/spinner` | `Spinner` (`label`, `size`) | server |
|
|
130
131
|
| `@krizaka/ui/countdown` | `Countdown` (`target`, `label`, `units`, `size`, `urgentBelowMs`, `skewMs`), `useCountdown`, `splitDuration` | client |
|
|
131
132
|
| `@krizaka/ui/card` | `Card.Root` (`asChild`, `reveal`, `radius` md·lg·xl, `tone` default·elevated·glass, `interactive`), `Card.Media` (`aspect` video·square·portrait·auto), `Card.Image` (`fallback`), `Card.Overlay` (`corner`), `Card.Body` (`padding`), `Card.Title` (`as`), `Card.Description`, `Card.Stat` (`label`), `Card.Footer`; `card` (the slots) | server |
|
|
132
|
-
| `@krizaka/ui/dialog` | `Dialog.Root/Trigger/Content/Header/Title/Description/Body/Footer/Close` (`placement` center·bottom·right, `size` sm·md·lg, `closeLabel` required), `Sheet` (= `placement="bottom"`), `AlertDialog` (`title`, `description`, `confirmLabel`, `cancelLabel`, `tone` danger·primary, async `onConfirm`, `trigger`) | client |
|
|
133
|
+
| `@krizaka/ui/dialog` | `Dialog.Root/Trigger/Content/Header/Title/Description/Body/Footer/Close` (`placement` center·bottom·right, `size` sm·md·lg, `closeLabel` required unless `hideClose`, `dismissible={false}`: no close on Escape or outside click), `Sheet` (= `placement="bottom"`), `AlertDialog` (`title`, `description`, `confirmLabel`, `cancelLabel`, `tone` danger·primary, async `onConfirm`, `trigger`) | client |
|
|
133
134
|
| `@krizaka/ui/toast` | `Toaster` (sonner styled by roles: `label`, `closeLabel`, `position`, `closeButton`; `richColors` off), `toast` (`.success/.warning/.error/.info/.custom`…) | client |
|
|
134
135
|
| `@krizaka/ui/popover` | `Popover.Root/Trigger/Anchor/Content/Close` | client |
|
|
135
136
|
| `@krizaka/ui/dropdown-menu` | `DropdownMenu.Root/Trigger/Content/Item/CheckboxItem/Label/Separator/Group` (`Item` `tone` default·danger), `menu` (the slots) | client |
|
|
@@ -139,6 +140,15 @@ Colours are roles of the preset (`bg-surface-2`, `text-fg-secondary`, `border-bo
|
|
|
139
140
|
| `@krizaka/ui/alert` | `Alert` (`tone` info·success·warning·danger, `icon`, `title`, `action`; `role="alert"` for danger and warning, `status` otherwise), `alertVariants` | server |
|
|
140
141
|
| `@krizaka/ui/separator` | `Separator` (`orientation`, `decorative`, Radix), `separatorVariants` | server |
|
|
141
142
|
| `@krizaka/ui/kbd` | `Kbd` (`size` sm·md), `kbdVariants` | server |
|
|
143
|
+
| `@krizaka/ui/tabs` | `Tabs.Root/List/Trigger/Content` (`variant` underline·segmented·pills on the root, `orientation`, `value`/`defaultValue` + `onValueChange`), `tabs` (the slots) | client |
|
|
144
|
+
| `@krizaka/ui/chip` | `Chip` (`selected`/`defaultSelected` + `onSelectedChange`, `size` sm·md; `removable` + `removeLabel` + `onRemove`), `Chip.Group` (`type` single·multiple, `label`, `required` for single), `chip` (the slots) | client |
|
|
145
|
+
| `@krizaka/ui/switch` | `Switch` (`checked`/`defaultChecked` + `onCheckedChange`, `label` unless a visible label names it, `size` sm·md, `invalid`), `switchVariants` | client |
|
|
146
|
+
| `@krizaka/ui/slider` | `Slider` (`value`: a number or a `[min, max]` range, `onValueChange`, `onValueCommit`, `label`, `thumbLabels`, `formatValue` → aria-valuetext, `showLabel`, `origin`), `slider` (the slots) | client |
|
|
147
|
+
| `@krizaka/ui/checkbox` | `Checkbox` (`checked` true·false·"indeterminate" + `onCheckedChange`, `invalid`, its words as children) — sits in a `Field` | client |
|
|
148
|
+
| `@krizaka/ui/radio-group` | `RadioGroup.Root` (`label`, `orientation`, `invalid`), `RadioGroup.Item` (a dot and its words), `RadioGroup.Card` (a whole card is the radio) | client |
|
|
149
|
+
| `@krizaka/ui/command` | `Command.Root` (`label`, `shouldFilter`…) `/Input` (`placeholder`, `trailing`) `/List` (`label`) `/Empty` (`emptyLabel`) `/Loading/Group/Item/Separator/Shortcut` on cmdk; `CommandDialog` (`label`, `open`/`onOpenChange`, `footer`, `contentProps`) | client |
|
|
150
|
+
| `@krizaka/ui/confirm-button` | `ConfirmButton` (two presses: `confirmLabel`, `onConfirm`, `timeoutMs` 4000, `label` for an icon, `armedContent`; the `Button` variants), `confirmArmed` | client |
|
|
151
|
+
| `@krizaka/ui/progress` | `Progress` (`variant` bar·ring, `size` sm·md·lg, `value`/`max`, indeterminate without a value, `label`, `valueText`, a ring's centre as children) | server |
|
|
142
152
|
| `@krizaka/ui` | the marks, `MotionObserver`, `RotatingWord`, `cx` (unchanged) | client |
|
|
143
153
|
| `@krizaka/ui/native` | the marks for React Native (unchanged) | native |
|
|
144
154
|
| `@krizaka/ui/motion.css`, `@krizaka/ui/tailwind.css` | the motion signature; the `@source` of the primitives' classes | CSS |
|
|
@@ -208,6 +218,7 @@ import { MotionObserver, RotatingWord } from "@krizaka/ui";
|
|
|
208
218
|
| `kz-lift` | A card rising under the pointer |
|
|
209
219
|
| `kz-gradient-text`, `kz-marquee` | Drifting gradient text, endless bands |
|
|
210
220
|
| `kz-overlay`, `kz-dialog`, `kz-pop`, `kz-fade` | Backdrops, dialogs (from the bottom on phones), menus, views swapped in place |
|
|
221
|
+
| `kz-progress` | The indeterminate progress bar's travelling segment |
|
|
211
222
|
|
|
212
223
|
With Tailwind CSS v4, give every transition the same easing:
|
|
213
224
|
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import * as tailwind_variants from 'tailwind-variants';
|
|
2
|
+
import { VariantProps } from 'tailwind-variants';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
|
|
5
|
+
declare const buttonVariants: tailwind_variants.TVReturnType<{
|
|
6
|
+
variant: {
|
|
7
|
+
primary: "bg-accent text-on-accent shadow-sm hover:bg-accent-hover";
|
|
8
|
+
secondary: "border border-border-default bg-surface-2 text-fg hover:border-border-strong hover:bg-surface-3";
|
|
9
|
+
outline: "border border-border-default bg-transparent text-fg hover:border-accent hover:text-accent";
|
|
10
|
+
ghost: "text-fg-secondary hover:bg-surface-2 hover:text-fg";
|
|
11
|
+
danger: "border border-danger/50 bg-danger/10 text-fg hover:border-danger hover:bg-danger/20";
|
|
12
|
+
};
|
|
13
|
+
size: {
|
|
14
|
+
sm: "h-8 px-3 text-xs";
|
|
15
|
+
md: "h-10 px-4 text-sm";
|
|
16
|
+
lg: "h-12 px-6 text-sm";
|
|
17
|
+
icon: "h-10 w-10";
|
|
18
|
+
};
|
|
19
|
+
shape: {
|
|
20
|
+
rounded: "rounded-lg";
|
|
21
|
+
pill: "rounded-full";
|
|
22
|
+
};
|
|
23
|
+
}, undefined, string, {
|
|
24
|
+
variant: {
|
|
25
|
+
primary: "bg-accent text-on-accent shadow-sm hover:bg-accent-hover";
|
|
26
|
+
secondary: "border border-border-default bg-surface-2 text-fg hover:border-border-strong hover:bg-surface-3";
|
|
27
|
+
outline: "border border-border-default bg-transparent text-fg hover:border-accent hover:text-accent";
|
|
28
|
+
ghost: "text-fg-secondary hover:bg-surface-2 hover:text-fg";
|
|
29
|
+
danger: "border border-danger/50 bg-danger/10 text-fg hover:border-danger hover:bg-danger/20";
|
|
30
|
+
};
|
|
31
|
+
size: {
|
|
32
|
+
sm: "h-8 px-3 text-xs";
|
|
33
|
+
md: "h-10 px-4 text-sm";
|
|
34
|
+
lg: "h-12 px-6 text-sm";
|
|
35
|
+
icon: "h-10 w-10";
|
|
36
|
+
};
|
|
37
|
+
shape: {
|
|
38
|
+
rounded: "rounded-lg";
|
|
39
|
+
pill: "rounded-full";
|
|
40
|
+
};
|
|
41
|
+
}, undefined, tailwind_variants.TVReturnTypeLike<{
|
|
42
|
+
variant: {
|
|
43
|
+
primary: "bg-accent text-on-accent shadow-sm hover:bg-accent-hover";
|
|
44
|
+
secondary: "border border-border-default bg-surface-2 text-fg hover:border-border-strong hover:bg-surface-3";
|
|
45
|
+
outline: "border border-border-default bg-transparent text-fg hover:border-accent hover:text-accent";
|
|
46
|
+
ghost: "text-fg-secondary hover:bg-surface-2 hover:text-fg";
|
|
47
|
+
danger: "border border-danger/50 bg-danger/10 text-fg hover:border-danger hover:bg-danger/20";
|
|
48
|
+
};
|
|
49
|
+
size: {
|
|
50
|
+
sm: "h-8 px-3 text-xs";
|
|
51
|
+
md: "h-10 px-4 text-sm";
|
|
52
|
+
lg: "h-12 px-6 text-sm";
|
|
53
|
+
icon: "h-10 w-10";
|
|
54
|
+
};
|
|
55
|
+
shape: {
|
|
56
|
+
rounded: "rounded-lg";
|
|
57
|
+
pill: "rounded-full";
|
|
58
|
+
};
|
|
59
|
+
}, undefined>>;
|
|
60
|
+
type ButtonVariants = VariantProps<typeof buttonVariants>;
|
|
61
|
+
type ButtonProps = React.ComponentProps<"button"> & ButtonVariants & {
|
|
62
|
+
/** Renders the child (e.g. a <Link>) instead of the <button>, with props, classes and ref merged. */
|
|
63
|
+
asChild?: boolean;
|
|
64
|
+
/** Disables and signals the wait (aria-busy, data-loading) — the product adds a spinner if it wants one. */
|
|
65
|
+
loading?: boolean;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export type { ButtonProps as B, ButtonVariants as a };
|
package/dist/card.js
CHANGED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as tailwind_variants from 'tailwind-variants';
|
|
2
|
+
import { Checkbox as Checkbox$1 } from 'radix-ui';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
|
|
5
|
+
declare const checkbox: tailwind_variants.TVReturnType<{
|
|
6
|
+
[key: string]: {
|
|
7
|
+
[key: string]: tailwind_variants.ClassValue | {
|
|
8
|
+
indicator?: tailwind_variants.ClassValue;
|
|
9
|
+
label?: tailwind_variants.ClassValue;
|
|
10
|
+
root?: tailwind_variants.ClassValue;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
} | {
|
|
14
|
+
[x: string]: {
|
|
15
|
+
[x: string]: tailwind_variants.ClassValue | {
|
|
16
|
+
indicator?: tailwind_variants.ClassValue;
|
|
17
|
+
label?: tailwind_variants.ClassValue;
|
|
18
|
+
root?: tailwind_variants.ClassValue;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
} | {}, {
|
|
22
|
+
root: string;
|
|
23
|
+
indicator: string;
|
|
24
|
+
label: string;
|
|
25
|
+
}, undefined, {
|
|
26
|
+
[key: string]: {
|
|
27
|
+
[key: string]: tailwind_variants.ClassValue | {
|
|
28
|
+
indicator?: tailwind_variants.ClassValue;
|
|
29
|
+
label?: tailwind_variants.ClassValue;
|
|
30
|
+
root?: tailwind_variants.ClassValue;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
} | {}, {
|
|
34
|
+
root: string;
|
|
35
|
+
indicator: string;
|
|
36
|
+
label: string;
|
|
37
|
+
}, tailwind_variants.TVReturnTypeLike<unknown, {
|
|
38
|
+
root: string;
|
|
39
|
+
indicator: string;
|
|
40
|
+
label: string;
|
|
41
|
+
}>>;
|
|
42
|
+
type CheckboxProps = Omit<React.ComponentProps<typeof Checkbox$1.Root>, "children"> & {
|
|
43
|
+
/** Marks it invalid: aria-invalid and data-invalid (pair it with a `Field.Error` in aria-describedby). */
|
|
44
|
+
invalid?: boolean;
|
|
45
|
+
/** The text next to the box, clickable: the box and its words in one `<label>`. Otherwise name it with
|
|
46
|
+
* `Field.Label htmlFor` or `aria-label`. */
|
|
47
|
+
children?: React.ReactNode;
|
|
48
|
+
};
|
|
49
|
+
/** A checkbox: `checked`/`defaultChecked` (`true` · `false` · `"indeterminate"`) + `onCheckedChange`. */
|
|
50
|
+
declare function Checkbox({ invalid, className, children, ...props }: CheckboxProps): React.JSX.Element;
|
|
51
|
+
|
|
52
|
+
export { Checkbox, type CheckboxProps, checkbox };
|
package/dist/checkbox.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/checkbox/checkbox.tsx
|
|
4
|
+
import { Checkbox as CheckboxPrimitive } from "radix-ui";
|
|
5
|
+
import { tv } from "tailwind-variants";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
var checkbox = tv({
|
|
8
|
+
slots: {
|
|
9
|
+
root: "peer inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-md border border-border-strong bg-surface-1 text-on-accent transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-surface-0 hover:border-accent disabled:cursor-not-allowed disabled:opacity-40 data-[state=checked]:border-accent data-[state=checked]:bg-accent data-[state=indeterminate]:border-accent data-[state=indeterminate]:bg-accent aria-invalid:border-danger aria-invalid:ring-danger/30",
|
|
10
|
+
indicator: "flex items-center justify-center",
|
|
11
|
+
label: "flex cursor-pointer items-start gap-3 text-sm text-fg has-disabled:cursor-not-allowed has-disabled:opacity-60"
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
function Check() {
|
|
15
|
+
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", className: "h-3.5 w-3.5", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" }) });
|
|
16
|
+
}
|
|
17
|
+
function Dash() {
|
|
18
|
+
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", className: "h-3.5 w-3.5", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M5 12h14" }) });
|
|
19
|
+
}
|
|
20
|
+
function Checkbox({ invalid, className, children, ...props }) {
|
|
21
|
+
const s = checkbox();
|
|
22
|
+
const box = /* @__PURE__ */ jsx(
|
|
23
|
+
CheckboxPrimitive.Root,
|
|
24
|
+
{
|
|
25
|
+
"aria-invalid": invalid || void 0,
|
|
26
|
+
"data-invalid": invalid ? "" : void 0,
|
|
27
|
+
className: s.root({ className: children ? "mt-0.5" : className }),
|
|
28
|
+
...props,
|
|
29
|
+
children: /* @__PURE__ */ jsx(CheckboxPrimitive.Indicator, { className: s.indicator(), children: props.checked === "indeterminate" ? /* @__PURE__ */ jsx(Dash, {}) : /* @__PURE__ */ jsx(Check, {}) })
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
if (!children) return box;
|
|
33
|
+
return /* @__PURE__ */ jsxs("label", { className: s.label({ className }), children: [
|
|
34
|
+
box,
|
|
35
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0", children })
|
|
36
|
+
] });
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
Checkbox,
|
|
40
|
+
checkbox
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=checkbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/checkbox/checkbox.tsx"],"sourcesContent":["// Client. Radix Checkbox: role=\"checkbox\", aria-checked (true · false · mixed), Space toggles, a hidden input inside a\n// form. It sits in a `Field` like the other controls: `<Field.Label htmlFor={id}>`, `invalid`, aria-describedby.\nimport { Checkbox as CheckboxPrimitive } from \"radix-ui\";\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nexport const checkbox = tv({\n slots: {\n root:\n \"peer inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-md border border-border-strong bg-surface-1 text-on-accent transition-colors \" +\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 \"hover:border-accent disabled:cursor-not-allowed disabled:opacity-40 \" +\n \"data-[state=checked]:border-accent data-[state=checked]:bg-accent data-[state=indeterminate]:border-accent data-[state=indeterminate]:bg-accent \" +\n \"aria-invalid:border-danger aria-invalid:ring-danger/30\",\n indicator: \"flex items-center justify-center\",\n label: \"flex cursor-pointer items-start gap-3 text-sm text-fg has-disabled:cursor-not-allowed has-disabled:opacity-60\",\n },\n});\n\nfunction Check() {\n return (\n <svg viewBox=\"0 0 24 24\" className=\"h-3.5 w-3.5\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n );\n}\n\nfunction Dash() {\n return (\n <svg viewBox=\"0 0 24 24\" className=\"h-3.5 w-3.5\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" aria-hidden>\n <path d=\"M5 12h14\" />\n </svg>\n );\n}\n\nexport type CheckboxProps = Omit<React.ComponentProps<typeof CheckboxPrimitive.Root>, \"children\"> & {\n /** Marks it invalid: aria-invalid and data-invalid (pair it with a `Field.Error` in aria-describedby). */\n invalid?: boolean;\n /** The text next to the box, clickable: the box and its words in one `<label>`. Otherwise name it with\n * `Field.Label htmlFor` or `aria-label`. */\n children?: React.ReactNode;\n};\n\n/** A checkbox: `checked`/`defaultChecked` (`true` · `false` · `\"indeterminate\"`) + `onCheckedChange`. */\nexport function Checkbox({ invalid, className, children, ...props }: CheckboxProps) {\n const s = checkbox();\n const box = (\n <CheckboxPrimitive.Root\n aria-invalid={invalid || undefined}\n data-invalid={invalid ? \"\" : undefined}\n className={s.root({ className: children ? \"mt-0.5\" : className })}\n {...props}\n >\n <CheckboxPrimitive.Indicator className={s.indicator()}>\n {props.checked === \"indeterminate\" ? <Dash /> : <Check />}\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n );\n if (!children) return box;\n return (\n <label className={s.label({ className })}>\n {box}\n <span className=\"min-w-0\">{children}</span>\n </label>\n );\n}\n"],"mappings":";;;AAEA,SAAS,YAAY,yBAAyB;AAE9C,SAAS,UAAU;AAkBb,cAsCF,YAtCE;AAhBC,IAAM,WAAW,GAAG;AAAA,EACzB,OAAO;AAAA,IACL,MACE;AAAA,IAKF,WAAW;AAAA,IACX,OAAO;AAAA,EACT;AACF,CAAC;AAED,SAAS,QAAQ;AACf,SACE,oBAAC,SAAI,SAAQ,aAAY,WAAU,eAAc,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SAAQ,eAAW,MACzJ,8BAAC,UAAK,GAAE,mBAAkB,GAC5B;AAEJ;AAEA,SAAS,OAAO;AACd,SACE,oBAAC,SAAI,SAAQ,aAAY,WAAU,eAAc,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,eAAW,MAClI,8BAAC,UAAK,GAAE,YAAW,GACrB;AAEJ;AAWO,SAAS,SAAS,EAAE,SAAS,WAAW,UAAU,GAAG,MAAM,GAAkB;AAClF,QAAM,IAAI,SAAS;AACnB,QAAM,MACJ;AAAA,IAAC,kBAAkB;AAAA,IAAlB;AAAA,MACC,gBAAc,WAAW;AAAA,MACzB,gBAAc,UAAU,KAAK;AAAA,MAC7B,WAAW,EAAE,KAAK,EAAE,WAAW,WAAW,WAAW,UAAU,CAAC;AAAA,MAC/D,GAAG;AAAA,MAEJ,8BAAC,kBAAkB,WAAlB,EAA4B,WAAW,EAAE,UAAU,GACjD,gBAAM,YAAY,kBAAkB,oBAAC,QAAK,IAAK,oBAAC,SAAM,GACzD;AAAA;AAAA,EACF;AAEF,MAAI,CAAC,SAAU,QAAO;AACtB,SACE,qBAAC,WAAM,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,GACpC;AAAA;AAAA,IACD,oBAAC,UAAK,WAAU,WAAW,UAAS;AAAA,KACtC;AAEJ;","names":[]}
|
package/dist/chip.d.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import * as tailwind_variants from 'tailwind-variants';
|
|
2
|
+
import { VariantProps } from 'tailwind-variants';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
|
|
5
|
+
declare const chip: tailwind_variants.TVReturnType<{
|
|
6
|
+
size: {
|
|
7
|
+
sm: {
|
|
8
|
+
base: string;
|
|
9
|
+
};
|
|
10
|
+
md: {
|
|
11
|
+
base: string;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
}, {
|
|
15
|
+
group: string;
|
|
16
|
+
base: string;
|
|
17
|
+
remove: string;
|
|
18
|
+
}, undefined, {
|
|
19
|
+
size: {
|
|
20
|
+
sm: {
|
|
21
|
+
base: string;
|
|
22
|
+
};
|
|
23
|
+
md: {
|
|
24
|
+
base: string;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
}, {
|
|
28
|
+
group: string;
|
|
29
|
+
base: string;
|
|
30
|
+
remove: string;
|
|
31
|
+
}, tailwind_variants.TVReturnTypeLike<{
|
|
32
|
+
size: {
|
|
33
|
+
sm: {
|
|
34
|
+
base: string;
|
|
35
|
+
};
|
|
36
|
+
md: {
|
|
37
|
+
base: string;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
}, {
|
|
41
|
+
group: string;
|
|
42
|
+
base: string;
|
|
43
|
+
remove: string;
|
|
44
|
+
}>>;
|
|
45
|
+
type ChipVariants = VariantProps<typeof chip>;
|
|
46
|
+
type ToggleChipProps = Omit<React.ComponentProps<"button">, "value" | "defaultValue"> & ChipVariants & {
|
|
47
|
+
/** Inside `Chip.Group`: the value this chip stands for (required there, ignored alone). */
|
|
48
|
+
value?: string;
|
|
49
|
+
/** Alone: pressed or not (`defaultSelected` uncontrolled), `onSelectedChange` on every press. */
|
|
50
|
+
selected?: boolean;
|
|
51
|
+
defaultSelected?: boolean;
|
|
52
|
+
onSelectedChange?: (selected: boolean) => void;
|
|
53
|
+
removable?: false;
|
|
54
|
+
};
|
|
55
|
+
type RemovableChipProps = Omit<React.ComponentProps<"span">, "onSelect"> & ChipVariants & {
|
|
56
|
+
/** A static chip (a chosen tag, an applied filter) with a remove button. */
|
|
57
|
+
removable: true;
|
|
58
|
+
/** The accessible name of the remove button — passed translated, e.g. "Remove #night". */
|
|
59
|
+
removeLabel: string;
|
|
60
|
+
onRemove: () => void;
|
|
61
|
+
disabled?: boolean;
|
|
62
|
+
};
|
|
63
|
+
type ChipProps = ToggleChipProps | RemovableChipProps;
|
|
64
|
+
/** A selectable pill (`selected` / `onSelectedChange`), an item of `Chip.Group` (`value`), or `removable`. */
|
|
65
|
+
declare function ChipBase(props: ChipProps): React.JSX.Element;
|
|
66
|
+
type GroupBase = Omit<React.ComponentProps<"div">, "defaultValue" | "dir"> & ChipVariants & {
|
|
67
|
+
/** The group's accessible name — passed translated ("Filter by format"). */
|
|
68
|
+
label?: string;
|
|
69
|
+
orientation?: "horizontal" | "vertical";
|
|
70
|
+
/** Arrow keys wrap from the last chip to the first (default `true`). */
|
|
71
|
+
loop?: boolean;
|
|
72
|
+
disabled?: boolean;
|
|
73
|
+
};
|
|
74
|
+
type ChipGroupProps = (GroupBase & {
|
|
75
|
+
/** One choice: the chips behave as radios. */
|
|
76
|
+
type: "single";
|
|
77
|
+
value?: string;
|
|
78
|
+
defaultValue?: string;
|
|
79
|
+
onValueChange?: (value: string) => void;
|
|
80
|
+
/** Keeps one chip selected: pressing the selected chip does not clear it (default `false`). */
|
|
81
|
+
required?: boolean;
|
|
82
|
+
}) | (GroupBase & {
|
|
83
|
+
/** Any number of choices: the chips are pressed buttons. */
|
|
84
|
+
type: "multiple";
|
|
85
|
+
value?: string[];
|
|
86
|
+
defaultValue?: string[];
|
|
87
|
+
onValueChange?: (value: string[]) => void;
|
|
88
|
+
required?: never;
|
|
89
|
+
});
|
|
90
|
+
/** Chips that choose together: `type` single · multiple, `value`/`defaultValue` + `onValueChange`. */
|
|
91
|
+
declare function ChipGroup({ label, size, className, children, ...props }: ChipGroupProps): React.JSX.Element;
|
|
92
|
+
/** `Chip` (selectable, removable) and `Chip.Group` (single · multiple). */
|
|
93
|
+
declare const Chip: typeof ChipBase & {
|
|
94
|
+
Group: typeof ChipGroup;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export { Chip, ChipGroup, type ChipGroupProps, type ChipProps, type ChipVariants, chip };
|
package/dist/chip.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/chip/chip.tsx
|
|
4
|
+
import { Toggle as TogglePrimitive, ToggleGroup as ToggleGroupPrimitive } from "radix-ui";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { tv } from "tailwind-variants";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
var chip = tv({
|
|
9
|
+
slots: {
|
|
10
|
+
group: "flex flex-wrap items-center gap-2 data-[orientation=vertical]:flex-col data-[orientation=vertical]:items-stretch",
|
|
11
|
+
base: "inline-flex shrink-0 select-none items-center justify-center gap-1.5 whitespace-nowrap rounded-full border font-semibold transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-40 border-border-default bg-surface-1 text-fg-secondary hover:border-border-strong hover:text-fg data-[state=on]:border-accent data-[state=on]:bg-accent-soft data-[state=on]:text-fg",
|
|
12
|
+
remove: "-mr-1.5 inline-flex h-6 w-6 items-center justify-center rounded-full text-fg-secondary transition-colors hover:bg-surface-3 hover:text-fg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
|
|
13
|
+
},
|
|
14
|
+
variants: {
|
|
15
|
+
size: { sm: { base: "h-7 px-3 text-xs" }, md: { base: "h-9 px-3.5 text-xs" } }
|
|
16
|
+
},
|
|
17
|
+
defaultVariants: { size: "md" }
|
|
18
|
+
});
|
|
19
|
+
var ChipGroupContext = React.createContext(null);
|
|
20
|
+
function RemoveIcon() {
|
|
21
|
+
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", className: "h-3.5 w-3.5", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) });
|
|
22
|
+
}
|
|
23
|
+
function ChipBase(props) {
|
|
24
|
+
const group = React.useContext(ChipGroupContext);
|
|
25
|
+
if (props.removable) {
|
|
26
|
+
const { removable: _removable2, removeLabel, onRemove, disabled, size: size2, className: className2, children, ...rest2 } = props;
|
|
27
|
+
const s2 = chip({ size: size2 ?? group?.size });
|
|
28
|
+
return /* @__PURE__ */ jsxs("span", { "data-removable": "", className: s2.base({ className: className2 }), ...rest2, children: [
|
|
29
|
+
children,
|
|
30
|
+
/* @__PURE__ */ jsx("button", { type: "button", "aria-label": removeLabel, title: removeLabel, disabled, onClick: onRemove, className: s2.remove(), children: /* @__PURE__ */ jsx(RemoveIcon, {}) })
|
|
31
|
+
] });
|
|
32
|
+
}
|
|
33
|
+
const { removable: _removable, value, selected, defaultSelected, onSelectedChange, size, className, ...rest } = props;
|
|
34
|
+
const s = chip({ size: size ?? group?.size });
|
|
35
|
+
if (group) {
|
|
36
|
+
if (value === void 0) throw new Error("Chip: a chip inside Chip.Group needs a `value`.");
|
|
37
|
+
return /* @__PURE__ */ jsx(ToggleGroupPrimitive.Item, { value, className: s.base({ className }), ...rest });
|
|
38
|
+
}
|
|
39
|
+
return /* @__PURE__ */ jsx(
|
|
40
|
+
TogglePrimitive.Root,
|
|
41
|
+
{
|
|
42
|
+
pressed: selected,
|
|
43
|
+
defaultPressed: defaultSelected,
|
|
44
|
+
onPressedChange: onSelectedChange,
|
|
45
|
+
className: s.base({ className }),
|
|
46
|
+
...rest
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
function ChipGroup({ label, size, className, children, ...props }) {
|
|
51
|
+
const s = chip({ size });
|
|
52
|
+
const context = React.useMemo(() => ({ size }), [size]);
|
|
53
|
+
const common = { "aria-label": label, className: s.group({ className }) };
|
|
54
|
+
let group;
|
|
55
|
+
if (props.type === "single") {
|
|
56
|
+
const { type: _type, value, defaultValue, onValueChange, required, ...rest } = props;
|
|
57
|
+
group = /* @__PURE__ */ jsx(SingleGroup, { ...rest, ...common, value, defaultValue, onValueChange, required, children });
|
|
58
|
+
} else {
|
|
59
|
+
const { type: _type, required: _required, ...rest } = props;
|
|
60
|
+
group = /* @__PURE__ */ jsx(ToggleGroupPrimitive.Root, { type: "multiple", ...rest, ...common, children });
|
|
61
|
+
}
|
|
62
|
+
return /* @__PURE__ */ jsx(ChipGroupContext.Provider, { value: context, children: group });
|
|
63
|
+
}
|
|
64
|
+
function SingleGroup({
|
|
65
|
+
value,
|
|
66
|
+
defaultValue,
|
|
67
|
+
onValueChange,
|
|
68
|
+
required,
|
|
69
|
+
...props
|
|
70
|
+
}) {
|
|
71
|
+
const [inner, setInner] = React.useState(defaultValue ?? "");
|
|
72
|
+
const current = value ?? inner;
|
|
73
|
+
return /* @__PURE__ */ jsx(
|
|
74
|
+
ToggleGroupPrimitive.Root,
|
|
75
|
+
{
|
|
76
|
+
type: "single",
|
|
77
|
+
value: current,
|
|
78
|
+
onValueChange: (next) => {
|
|
79
|
+
if (required && !next) return;
|
|
80
|
+
if (value === void 0) setInner(next);
|
|
81
|
+
onValueChange?.(next);
|
|
82
|
+
},
|
|
83
|
+
...props
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
var Chip = Object.assign(ChipBase, { Group: ChipGroup });
|
|
88
|
+
export {
|
|
89
|
+
Chip,
|
|
90
|
+
ChipGroup,
|
|
91
|
+
chip
|
|
92
|
+
};
|
|
93
|
+
//# sourceMappingURL=chip.js.map
|
package/dist/chip.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/chip/chip.tsx"],"sourcesContent":["// Client (a context). A chip is a pressable pill: alone it is a Radix Toggle (aria-pressed), inside `Chip.Group` an\n// item of a Radix Toggle Group (roving focus with the arrows; `single` = radio semantics, `multiple` = pressed\n// buttons). A `removable` chip is a static label with its own remove button (two buttons cannot nest).\nimport { Toggle as TogglePrimitive, ToggleGroup as ToggleGroupPrimitive } from \"radix-ui\";\nimport * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nexport const chip = tv({\n slots: {\n group: \"flex flex-wrap items-center gap-2 data-[orientation=vertical]:flex-col data-[orientation=vertical]:items-stretch\",\n base:\n \"inline-flex shrink-0 select-none items-center justify-center gap-1.5 whitespace-nowrap rounded-full border font-semibold transition-colors \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-40 \" +\n \"border-border-default bg-surface-1 text-fg-secondary hover:border-border-strong hover:text-fg \" +\n \"data-[state=on]:border-accent data-[state=on]:bg-accent-soft data-[state=on]:text-fg\",\n remove:\n \"-mr-1.5 inline-flex h-6 w-6 items-center justify-center rounded-full text-fg-secondary transition-colors hover:bg-surface-3 hover:text-fg \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n },\n variants: {\n size: { sm: { base: \"h-7 px-3 text-xs\" }, md: { base: \"h-9 px-3.5 text-xs\" } },\n },\n defaultVariants: { size: \"md\" },\n});\n\nexport type ChipVariants = VariantProps<typeof chip>;\n\ntype GroupContext = { size: ChipVariants[\"size\"] };\nconst ChipGroupContext = React.createContext<GroupContext | null>(null);\n\nfunction RemoveIcon() {\n return (\n <svg viewBox=\"0 0 24 24\" className=\"h-3.5 w-3.5\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" aria-hidden>\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n );\n}\n\ntype ToggleChipProps = Omit<React.ComponentProps<\"button\">, \"value\" | \"defaultValue\"> &\n ChipVariants & {\n /** Inside `Chip.Group`: the value this chip stands for (required there, ignored alone). */\n value?: string;\n /** Alone: pressed or not (`defaultSelected` uncontrolled), `onSelectedChange` on every press. */\n selected?: boolean;\n defaultSelected?: boolean;\n onSelectedChange?: (selected: boolean) => void;\n removable?: false;\n };\n\ntype RemovableChipProps = Omit<React.ComponentProps<\"span\">, \"onSelect\"> &\n ChipVariants & {\n /** A static chip (a chosen tag, an applied filter) with a remove button. */\n removable: true;\n /** The accessible name of the remove button — passed translated, e.g. \"Remove #night\". */\n removeLabel: string;\n onRemove: () => void;\n disabled?: boolean;\n };\n\nexport type ChipProps = ToggleChipProps | RemovableChipProps;\n\n/** A selectable pill (`selected` / `onSelectedChange`), an item of `Chip.Group` (`value`), or `removable`. */\nfunction ChipBase(props: ChipProps) {\n const group = React.useContext(ChipGroupContext);\n if (props.removable) {\n const { removable: _removable, removeLabel, onRemove, disabled, size, className, children, ...rest } = props;\n const s = chip({ size: size ?? group?.size });\n return (\n <span data-removable=\"\" className={s.base({ className })} {...rest}>\n {children}\n <button type=\"button\" aria-label={removeLabel} title={removeLabel} disabled={disabled} onClick={onRemove} className={s.remove()}>\n <RemoveIcon />\n </button>\n </span>\n );\n }\n const { removable: _removable, value, selected, defaultSelected, onSelectedChange, size, className, ...rest } = props;\n const s = chip({ size: size ?? group?.size });\n if (group) {\n if (value === undefined) throw new Error(\"Chip: a chip inside Chip.Group needs a `value`.\");\n return <ToggleGroupPrimitive.Item value={value} className={s.base({ className })} {...rest} />;\n }\n return (\n <TogglePrimitive.Root\n pressed={selected}\n defaultPressed={defaultSelected}\n onPressedChange={onSelectedChange}\n className={s.base({ className })}\n {...rest}\n />\n );\n}\n\ntype GroupBase = Omit<React.ComponentProps<\"div\">, \"defaultValue\" | \"dir\"> &\n ChipVariants & {\n /** The group's accessible name — passed translated (\"Filter by format\"). */\n label?: string;\n orientation?: \"horizontal\" | \"vertical\";\n /** Arrow keys wrap from the last chip to the first (default `true`). */\n loop?: boolean;\n disabled?: boolean;\n };\n\nexport type ChipGroupProps =\n | (GroupBase & {\n /** One choice: the chips behave as radios. */\n type: \"single\";\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n /** Keeps one chip selected: pressing the selected chip does not clear it (default `false`). */\n required?: boolean;\n })\n | (GroupBase & {\n /** Any number of choices: the chips are pressed buttons. */\n type: \"multiple\";\n value?: string[];\n defaultValue?: string[];\n onValueChange?: (value: string[]) => void;\n required?: never;\n });\n\n/** Chips that choose together: `type` single · multiple, `value`/`defaultValue` + `onValueChange`. */\nexport function ChipGroup({ label, size, className, children, ...props }: ChipGroupProps) {\n const s = chip({ size });\n const context = React.useMemo(() => ({ size }), [size]);\n const common = { \"aria-label\": label, className: s.group({ className }) };\n let group: React.ReactNode;\n if (props.type === \"single\") {\n const { type: _type, value, defaultValue, onValueChange, required, ...rest } = props;\n group = <SingleGroup {...rest} {...common} value={value} defaultValue={defaultValue} onValueChange={onValueChange} required={required}>{children}</SingleGroup>;\n } else {\n const { type: _type, required: _required, ...rest } = props;\n group = (\n <ToggleGroupPrimitive.Root type=\"multiple\" {...rest} {...common}>\n {children}\n </ToggleGroupPrimitive.Root>\n );\n }\n return <ChipGroupContext.Provider value={context}>{group}</ChipGroupContext.Provider>;\n}\n\n/** Radix's single group, plus `required`: the value is held here so that an empty change can be refused. */\nfunction SingleGroup({\n value,\n defaultValue,\n onValueChange,\n required,\n ...props\n}: Omit<GroupBase, \"size\" | \"label\"> & {\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n required?: boolean;\n}) {\n const [inner, setInner] = React.useState(defaultValue ?? \"\");\n const current = value ?? inner;\n return (\n <ToggleGroupPrimitive.Root\n type=\"single\"\n value={current}\n onValueChange={(next) => {\n if (required && !next) return;\n if (value === undefined) setInner(next);\n onValueChange?.(next);\n }}\n {...props}\n />\n );\n}\n\n/** `Chip` (selectable, removable) and `Chip.Group` (single · multiple). */\nexport const Chip = Object.assign(ChipBase, { Group: ChipGroup });\n"],"mappings":"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","names":["_removable","size","className","rest","s"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cn.ts"],"sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { cn as merge } from \"tailwind-variants\";\n\nexport type { ClassValue };\n\n/**\n * Merges Tailwind classes: the last one wins — a product's `className` overrides the primitive's. The merge engine is\n * tailwind-merge as tailwind-variants ships it (the one `tv` uses), so the platform carries a single copy of it.\n * tailwind-variants bundles that engine since 3.3 (it never imports the `tailwind-merge` package, an optional peer):\n * hence `tailwind-variants ^3.3.1` and no `tailwind-merge` dependency — `scripts/consumer.mjs` checks it on a clean\n * install of the packed package.\n */\nexport function cn(...inputs: ClassValue[]): string {\n return merge(clsx(inputs)) ?? \"\";\n}\n"],"mappings":";;;AAAA,SAA0B,YAAY;AACtC,SAAS,MAAM,aAAa;AAWrB,SAAS,MAAM,QAA8B;AAClD,SAAO,MAAM,KAAK,MAAM,CAAC,KAAK;AAChC;","names":[]}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
IconButton
|
|
4
|
+
} from "./chunk-QRG5RYEI.js";
|
|
5
|
+
|
|
6
|
+
// src/dialog/dialog.tsx
|
|
7
|
+
import { Dialog as DialogPrimitive } from "radix-ui";
|
|
8
|
+
import { tv } from "tailwind-variants";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
var dialog = tv({
|
|
11
|
+
slots: {
|
|
12
|
+
overlay: "kz-overlay fixed inset-0 z-50 bg-overlay backdrop-blur-xs",
|
|
13
|
+
content: "kz-dialog fixed z-50 flex flex-col overflow-hidden border border-border-default bg-surface-1 text-fg shadow-lg focus:outline-hidden",
|
|
14
|
+
close: "absolute right-3 top-3 h-9 w-9",
|
|
15
|
+
header: "flex flex-col gap-1 px-5 pb-2 pr-14 pt-5",
|
|
16
|
+
title: "text-base font-bold text-fg",
|
|
17
|
+
description: "text-sm text-fg-secondary",
|
|
18
|
+
body: "min-h-0 flex-1 overflow-y-auto px-5 pb-5",
|
|
19
|
+
footer: "flex flex-wrap items-center justify-end gap-2 border-t border-border-subtle px-5 py-4 pb-[max(1rem,env(safe-area-inset-bottom))]"
|
|
20
|
+
},
|
|
21
|
+
variants: {
|
|
22
|
+
placement: {
|
|
23
|
+
center: { content: "left-1/2 top-1/2 max-h-[85dvh] w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 rounded-xl" },
|
|
24
|
+
/* A sheet: anchored at the bottom on a phone, centred from `sm` up. */
|
|
25
|
+
bottom: {
|
|
26
|
+
content: "inset-x-0 bottom-0 max-h-[92dvh] rounded-t-[1.75rem] sm:bottom-auto sm:left-1/2 sm:top-1/2 sm:w-full sm:-translate-x-1/2 sm:-translate-y-1/2 sm:rounded-[1.75rem]"
|
|
27
|
+
},
|
|
28
|
+
right: { content: "inset-y-0 right-0 h-full w-full max-w-md rounded-none border-y-0 border-r-0" }
|
|
29
|
+
},
|
|
30
|
+
size: { sm: { content: "sm:max-w-sm" }, md: { content: "sm:max-w-md" }, lg: { content: "sm:max-w-2xl" } }
|
|
31
|
+
},
|
|
32
|
+
defaultVariants: { placement: "center", size: "md" }
|
|
33
|
+
});
|
|
34
|
+
var s = dialog();
|
|
35
|
+
function CloseIcon() {
|
|
36
|
+
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", className: "h-4 w-4", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) });
|
|
37
|
+
}
|
|
38
|
+
var prevent = (event) => event.preventDefault();
|
|
39
|
+
function DialogContent({
|
|
40
|
+
placement,
|
|
41
|
+
size,
|
|
42
|
+
closeLabel,
|
|
43
|
+
hideClose,
|
|
44
|
+
dismissible = true,
|
|
45
|
+
container,
|
|
46
|
+
className,
|
|
47
|
+
children,
|
|
48
|
+
onEscapeKeyDown,
|
|
49
|
+
onPointerDownOutside,
|
|
50
|
+
onInteractOutside,
|
|
51
|
+
...props
|
|
52
|
+
}) {
|
|
53
|
+
const v = dialog({ placement, size });
|
|
54
|
+
return /* @__PURE__ */ jsxs(DialogPrimitive.Portal, { container, children: [
|
|
55
|
+
/* @__PURE__ */ jsx(DialogPrimitive.Overlay, { className: v.overlay() }),
|
|
56
|
+
/* @__PURE__ */ jsxs(
|
|
57
|
+
DialogPrimitive.Content,
|
|
58
|
+
{
|
|
59
|
+
"data-placement": placement ?? "center",
|
|
60
|
+
"data-dismissible": dismissible ? void 0 : "false",
|
|
61
|
+
className: v.content({ className }),
|
|
62
|
+
onEscapeKeyDown: dismissible ? onEscapeKeyDown : chain(onEscapeKeyDown, prevent),
|
|
63
|
+
onPointerDownOutside: dismissible ? onPointerDownOutside : chain(onPointerDownOutside, prevent),
|
|
64
|
+
onInteractOutside: dismissible ? onInteractOutside : chain(onInteractOutside, prevent),
|
|
65
|
+
...props,
|
|
66
|
+
children: [
|
|
67
|
+
children,
|
|
68
|
+
!hideClose && /* @__PURE__ */ jsx(DialogPrimitive.Close, { asChild: true, children: /* @__PURE__ */ jsx(IconButton, { label: closeLabel, variant: "ghost", shape: "pill", className: v.close(), children: /* @__PURE__ */ jsx(CloseIcon, {}) }) })
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
)
|
|
72
|
+
] });
|
|
73
|
+
}
|
|
74
|
+
function chain(handler, then) {
|
|
75
|
+
return (event) => {
|
|
76
|
+
handler?.(event);
|
|
77
|
+
then(event);
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function DialogHeader({ className, ...props }) {
|
|
81
|
+
return /* @__PURE__ */ jsx("div", { className: s.header({ className }), ...props });
|
|
82
|
+
}
|
|
83
|
+
function DialogTitle({ className, ...props }) {
|
|
84
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Title, { className: s.title({ className }), ...props });
|
|
85
|
+
}
|
|
86
|
+
function DialogDescription({ className, ...props }) {
|
|
87
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Description, { className: s.description({ className }), ...props });
|
|
88
|
+
}
|
|
89
|
+
function DialogBody({ className, ...props }) {
|
|
90
|
+
return /* @__PURE__ */ jsx("div", { className: s.body({ className }), ...props });
|
|
91
|
+
}
|
|
92
|
+
function DialogFooter({ className, ...props }) {
|
|
93
|
+
return /* @__PURE__ */ jsx("div", { className: s.footer({ className }), ...props });
|
|
94
|
+
}
|
|
95
|
+
var Dialog = {
|
|
96
|
+
Root: DialogPrimitive.Root,
|
|
97
|
+
Trigger: DialogPrimitive.Trigger,
|
|
98
|
+
Close: DialogPrimitive.Close,
|
|
99
|
+
Content: DialogContent,
|
|
100
|
+
Header: DialogHeader,
|
|
101
|
+
Title: DialogTitle,
|
|
102
|
+
Description: DialogDescription,
|
|
103
|
+
Body: DialogBody,
|
|
104
|
+
Footer: DialogFooter
|
|
105
|
+
};
|
|
106
|
+
function Sheet(props) {
|
|
107
|
+
return /* @__PURE__ */ jsx(DialogContent, { placement: "bottom", ...props });
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export {
|
|
111
|
+
dialog,
|
|
112
|
+
DialogContent,
|
|
113
|
+
DialogHeader,
|
|
114
|
+
DialogTitle,
|
|
115
|
+
DialogDescription,
|
|
116
|
+
DialogBody,
|
|
117
|
+
DialogFooter,
|
|
118
|
+
Dialog,
|
|
119
|
+
Sheet
|
|
120
|
+
};
|
|
121
|
+
//# sourceMappingURL=chunk-5FRYKFTO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/dialog/dialog.tsx"],"sourcesContent":["// Client (a portal). Radix does the focus trap, the scroll lock, Escape, the outside click, aria-modal, the\n// aria-labelledby / aria-describedby wiring and the focus return: this file only holds the shape.\nimport { Dialog as DialogPrimitive } from \"radix-ui\";\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nimport { IconButton } from \"../button/button\";\n\nexport const dialog = tv({\n slots: {\n overlay: \"kz-overlay fixed inset-0 z-50 bg-overlay backdrop-blur-xs\",\n content:\n \"kz-dialog fixed z-50 flex flex-col overflow-hidden border border-border-default bg-surface-1 text-fg shadow-lg focus:outline-hidden\",\n close: \"absolute right-3 top-3 h-9 w-9\",\n header: \"flex flex-col gap-1 px-5 pb-2 pr-14 pt-5\",\n title: \"text-base font-bold text-fg\",\n description: \"text-sm text-fg-secondary\",\n body: \"min-h-0 flex-1 overflow-y-auto px-5 pb-5\",\n footer:\n \"flex flex-wrap items-center justify-end gap-2 border-t border-border-subtle px-5 py-4 pb-[max(1rem,env(safe-area-inset-bottom))]\",\n },\n variants: {\n placement: {\n center: { content: \"left-1/2 top-1/2 max-h-[85dvh] w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 rounded-xl\" },\n /* A sheet: anchored at the bottom on a phone, centred from `sm` up. */\n bottom: {\n content:\n \"inset-x-0 bottom-0 max-h-[92dvh] rounded-t-[1.75rem] sm:bottom-auto sm:left-1/2 sm:top-1/2 sm:w-full \" +\n \"sm:-translate-x-1/2 sm:-translate-y-1/2 sm:rounded-[1.75rem]\",\n },\n right: { content: \"inset-y-0 right-0 h-full w-full max-w-md rounded-none border-y-0 border-r-0\" },\n },\n size: { sm: { content: \"sm:max-w-sm\" }, md: { content: \"sm:max-w-md\" }, lg: { content: \"sm:max-w-2xl\" } },\n },\n defaultVariants: { placement: \"center\", size: \"md\" },\n});\nconst s = dialog();\n\nexport type DialogVariants = VariantProps<typeof dialog>;\n\nfunction CloseIcon() {\n return (\n <svg viewBox=\"0 0 24 24\" className=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" aria-hidden>\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n );\n}\n\ntype CloseButtonProps =\n | {\n /** The accessible name of the close button — passed translated. */\n closeLabel: string;\n /** Leaves the close button out (the content brings its own way out, or none: see `dismissible`). */\n hideClose?: false;\n }\n | { closeLabel?: string; hideClose: true };\n\nexport type DialogContentProps = React.ComponentProps<typeof DialogPrimitive.Content> &\n DialogVariants &\n CloseButtonProps & {\n /**\n * `false`: Escape and a click outside do not close it (a gate the user must answer: age, terms). It still closes\n * through `open` / `onOpenChange` and any `Dialog.Close` inside. Default `true`.\n */\n dismissible?: boolean;\n /** The element the portal renders into (default: document.body). */\n container?: HTMLElement | null;\n };\n\nconst prevent = (event: Event) => event.preventDefault();\n\n/** The dialog itself, portalled over a dimmed overlay, with a close button. Give it a `Dialog.Title`. */\nexport function DialogContent({\n placement,\n size,\n closeLabel,\n hideClose,\n dismissible = true,\n container,\n className,\n children,\n onEscapeKeyDown,\n onPointerDownOutside,\n onInteractOutside,\n ...props\n}: DialogContentProps) {\n const v = dialog({ placement, size });\n return (\n <DialogPrimitive.Portal container={container}>\n <DialogPrimitive.Overlay className={v.overlay()} />\n <DialogPrimitive.Content\n data-placement={placement ?? \"center\"}\n data-dismissible={dismissible ? undefined : \"false\"}\n className={v.content({ className })}\n onEscapeKeyDown={dismissible ? onEscapeKeyDown : chain(onEscapeKeyDown, prevent)}\n onPointerDownOutside={dismissible ? onPointerDownOutside : chain(onPointerDownOutside, prevent)}\n onInteractOutside={dismissible ? onInteractOutside : chain(onInteractOutside, prevent)}\n {...props}\n >\n {children}\n {!hideClose && (\n <DialogPrimitive.Close asChild>\n <IconButton label={closeLabel as string} variant=\"ghost\" shape=\"pill\" className={v.close()}>\n <CloseIcon />\n </IconButton>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Content>\n </DialogPrimitive.Portal>\n );\n}\n\nfunction chain<E extends Event>(handler: ((event: E) => void) | undefined, then: (event: E) => void) {\n return (event: E) => {\n handler?.(event);\n then(event);\n };\n}\n\nexport function DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div className={s.header({ className })} {...props} />;\n}\n\nexport function DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) {\n return <DialogPrimitive.Title className={s.title({ className })} {...props} />;\n}\n\nexport function DialogDescription({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Description>) {\n return <DialogPrimitive.Description className={s.description({ className })} {...props} />;\n}\n\nexport function DialogBody({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div className={s.body({ className })} {...props} />;\n}\n\nexport function DialogFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div className={s.footer({ className })} {...props} />;\n}\n\n/** `Dialog.Root/Trigger/Content/Header/Title/Description/Body/Footer/Close`. `open`/`defaultOpen` + `onOpenChange`. */\nexport const Dialog = {\n Root: DialogPrimitive.Root,\n Trigger: DialogPrimitive.Trigger,\n Close: DialogPrimitive.Close,\n Content: DialogContent,\n Header: DialogHeader,\n Title: DialogTitle,\n Description: DialogDescription,\n Body: DialogBody,\n Footer: DialogFooter,\n};\n\n/** `Omit` that keeps the close-button union (`closeLabel` required unless `hideClose`). */\ntype DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;\n\nexport type SheetProps = DistributiveOmit<DialogContentProps, \"placement\">;\n\n/** A sheet is a dialog anchored at the bottom (centred from `sm` up): `Dialog.Content placement=\"bottom\"`. */\nexport function Sheet(props: SheetProps) {\n return <DialogContent placement=\"bottom\" {...props} />;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cn.ts"],"sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { cn as merge } from \"tailwind-variants\";\n\nexport type { ClassValue };\n\n/**\n * Merges Tailwind classes: the last one wins — a product's `className` overrides the primitive's. The merge engine is\n * tailwind-merge as tailwind-variants ships it (the one `tv` uses), so the platform carries a single copy of it.\n * tailwind-variants bundles that engine since 3.3 (it never imports the `tailwind-merge` package, an optional peer):\n * hence `tailwind-variants ^3.3.1` and no `tailwind-merge` dependency — `scripts/consumer.mjs` checks it on a clean\n * install of the packed package.\n */\nexport function cn(...inputs: ClassValue[]): string {\n return merge(clsx(inputs)) ?? \"\";\n}\n"],"mappings":";AAAA,SAA0B,YAAY;AACtC,SAAS,MAAM,aAAa;AAWrB,SAAS,MAAM,QAA8B;AAClD,SAAO,MAAM,KAAK,MAAM,CAAC,KAAK;AAChC;","names":[]}
|
package/dist/cn.d.ts
CHANGED
|
@@ -4,6 +4,9 @@ export { ClassValue } from 'clsx';
|
|
|
4
4
|
/**
|
|
5
5
|
* Merges Tailwind classes: the last one wins — a product's `className` overrides the primitive's. The merge engine is
|
|
6
6
|
* tailwind-merge as tailwind-variants ships it (the one `tv` uses), so the platform carries a single copy of it.
|
|
7
|
+
* tailwind-variants bundles that engine since 3.3 (it never imports the `tailwind-merge` package, an optional peer):
|
|
8
|
+
* hence `tailwind-variants ^3.3.1` and no `tailwind-merge` dependency — `scripts/consumer.mjs` checks it on a clean
|
|
9
|
+
* install of the packed package.
|
|
7
10
|
*/
|
|
8
11
|
declare function cn(...inputs: ClassValue[]): string;
|
|
9
12
|
|