@zentauri-ui/zentauri-components 1.8.2 → 1.8.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 +107 -20
- package/cli/cli.integration.test.ts +77 -2
- package/cli/index.mjs +53 -0
- package/cli/registry.json +126 -0
- package/cli/rewrite-imports.mjs +4 -1
- package/dist/{chunk-ABOZ5QIX.js → chunk-466QDL44.js} +5 -12
- package/dist/chunk-466QDL44.js.map +1 -0
- package/dist/chunk-4ZP444GA.mjs +19 -0
- package/dist/chunk-4ZP444GA.mjs.map +1 -0
- package/dist/{chunk-HDO5ZM2S.mjs → chunk-CIEZFHCO.mjs} +3 -10
- package/dist/chunk-CIEZFHCO.mjs.map +1 -0
- package/dist/{chunk-QQ6F4LZK.js → chunk-JFS5PJSH.js} +5 -5
- package/dist/{chunk-QQ6F4LZK.js.map → chunk-JFS5PJSH.js.map} +1 -1
- package/dist/chunk-MUP7DVQR.js +26 -0
- package/dist/chunk-MUP7DVQR.js.map +1 -0
- package/dist/{chunk-ASJQP53L.mjs → chunk-VARQ7W4G.mjs} +3 -3
- package/dist/{chunk-ASJQP53L.mjs.map → chunk-VARQ7W4G.mjs.map} +1 -1
- package/dist/design-system/tokens.js +32 -0
- package/dist/design-system/tokens.js.map +1 -0
- package/dist/design-system/tokens.mjs +3 -0
- package/dist/design-system/tokens.mjs.map +1 -0
- package/dist/ui/buttons/animated.js +4 -3
- package/dist/ui/buttons/animated.js.map +1 -1
- package/dist/ui/buttons/animated.mjs +2 -1
- package/dist/ui/buttons/animated.mjs.map +1 -1
- package/dist/ui/buttons.js +5 -4
- package/dist/ui/buttons.mjs +3 -2
- package/dist/ui/dynamic-stepper.js +5 -4
- package/dist/ui/dynamic-stepper.js.map +1 -1
- package/dist/ui/dynamic-stepper.mjs +3 -2
- package/dist/ui/dynamic-stepper.mjs.map +1 -1
- package/dist/ui/pagination.js +5 -4
- package/dist/ui/pagination.js.map +1 -1
- package/dist/ui/pagination.mjs +2 -1
- package/dist/ui/pagination.mjs.map +1 -1
- package/package.json +8 -2
- package/src/ui/context-menu/context-menu.test.tsx +30 -0
- package/src/ui/modal/modal.test.tsx +24 -0
- package/src/ui/peer-isolation.test.ts +81 -0
- package/src/ui/select/select.test.tsx +98 -2
- package/dist/chunk-ABOZ5QIX.js.map +0 -1
- package/dist/chunk-HDO5ZM2S.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -11,29 +11,41 @@ The library targets **React 18+** apps that use **Tailwind CSS v4** (or an equiv
|
|
|
11
11
|
|
|
12
12
|
Published artifacts live under `dist/`. Imports use **per-entry subpaths**: `@zentauri-ui/zentauri-components/ui/<area>` for static UI, `@zentauri-ui/zentauri-components/ui/<area>/animated` where a motion bundle exists, `@zentauri-ui/zentauri-components/charts/<type>` for Recharts-powered chart primitives, and `@zentauri-ui/zentauri-components/hooks/<entry>` for React hooks (and shared helpers under `hooks/utils`). Base UI entries do **not** re-export animated components; motion lives on its own entry so optional `framer-motion` usage stays tree-shakeable and chunk-friendly. Each entry resolves to its own ESM (`.mjs`), CJS (`.js`), and types (`.d.ts`) so bundlers pull only what you import. Most apps rely on Tailwind scanning the package sources (see installation); a separate CSS import is not required for that setup.
|
|
13
13
|
|
|
14
|
+
## Current package surface
|
|
15
|
+
|
|
16
|
+
| Surface | Count | Import shape |
|
|
17
|
+
| ------------------- | ----: | ----------------------------------------------------- |
|
|
18
|
+
| Static UI entries | 42 | `@zentauri-ui/zentauri-components/ui/<name>` |
|
|
19
|
+
| Animated UI entries | 27 | `@zentauri-ui/zentauri-components/ui/<name>/animated` |
|
|
20
|
+
| Chart entries | 9 | `@zentauri-ui/zentauri-components/charts/<type>` |
|
|
21
|
+
| Hook entries | 28 | `@zentauri-ui/zentauri-components/hooks/<entry>` |
|
|
22
|
+
|
|
23
|
+
`spinner` is the only animated-only UI area. Import it from `@zentauri-ui/zentauri-components/ui/spinner/animated`; there is no `@zentauri-ui/zentauri-components/ui/spinner` static entry.
|
|
24
|
+
|
|
14
25
|
## Package status and test coverage
|
|
15
26
|
|
|
16
27
|
| Metric | Result |
|
|
17
28
|
| ---------- | ---------------- |
|
|
18
|
-
| Test files |
|
|
19
|
-
| Tests |
|
|
29
|
+
| Test files | 76 passed (76) |
|
|
30
|
+
| Tests | 548 passed (548) |
|
|
20
31
|
|
|
21
32
|
| Area | Test files | Tests |
|
|
22
33
|
| --------------------------- | ---------- | ----- |
|
|
23
|
-
| Components and UI utilities |
|
|
34
|
+
| Components and UI utilities | 46 | 433 |
|
|
24
35
|
| React hooks | 28 | 101 |
|
|
25
|
-
| CLI and import rewriting | 2 |
|
|
36
|
+
| CLI and import rewriting | 2 | 14 |
|
|
26
37
|
|
|
27
38
|
### Per-suite snapshot
|
|
28
39
|
|
|
29
40
|
| Suite | Tests |
|
|
30
41
|
| ----------------------------------------------------------------------- | ----: |
|
|
31
42
|
| `src/ui/dynamic-stepper/dynamic-stepper.test.tsx` | 8 |
|
|
32
|
-
| `src/ui/select/select.test.tsx` |
|
|
43
|
+
| `src/ui/select/select.test.tsx` | 10 |
|
|
33
44
|
| `src/charts/charts.test.tsx` | 6 |
|
|
34
|
-
| `src/ui/modal/modal.test.tsx` |
|
|
45
|
+
| `src/ui/modal/modal.test.tsx` | 10 |
|
|
35
46
|
| `src/ui/drawer/drawer.test.tsx` | 7 |
|
|
36
|
-
| `
|
|
47
|
+
| `src/ui/peer-isolation.test.ts` | 29 |
|
|
48
|
+
| `cli/cli.integration.test.ts` | 9 |
|
|
37
49
|
| `src/ui/buttons/button.test.tsx` | 41 |
|
|
38
50
|
| `src/ui/inputs/input.test.tsx` | 40 |
|
|
39
51
|
| `src/ui/marquee/marquee.test.tsx` | 10 |
|
|
@@ -43,7 +55,7 @@ Published artifacts live under `dist/`. Imports use **per-entry subpaths**: `@ze
|
|
|
43
55
|
| `src/ui/checkbox/checkbox.test.tsx` | 6 |
|
|
44
56
|
| `src/ui/popover/popover.test.tsx` | 4 |
|
|
45
57
|
| `src/ui/command/command.test.tsx` | 7 |
|
|
46
|
-
| `src/ui/context-menu/context-menu.test.tsx` |
|
|
58
|
+
| `src/ui/context-menu/context-menu.test.tsx` | 10 |
|
|
47
59
|
| `src/ui/copy-button/copy-button.test.tsx` | 8 |
|
|
48
60
|
| `src/ui/kbd/kbd.test.tsx` | 7 |
|
|
49
61
|
| `src/ui/tooltip/tooltip.test.tsx` | 4 |
|
|
@@ -106,12 +118,12 @@ Published artifacts live under `dist/`. Imports use **per-entry subpaths**: `@ze
|
|
|
106
118
|
|
|
107
119
|
## Package exports
|
|
108
120
|
|
|
109
|
-
| Subpath | Description
|
|
110
|
-
| ----------------------------------------------------- |
|
|
111
|
-
| `@zentauri-ui/zentauri-components/ui/<name>` | Single UI area: static primitives, compound parts, variants, and types. Does **not** include Framer Motion–based animated exports.
|
|
112
|
-
| `@zentauri-ui/zentauri-components/ui/<name>/animated` | Motion entry for that area when published: animated components, motion presets, and related types (depends on **framer-motion**).
|
|
113
|
-
| `@zentauri-ui/zentauri-components/charts/<type>` | Responsive Recharts chart entry for `area`, `bar`, `stacked-bar`, `radar`, `scatter`, `bubble`, `funnel`, `line`, or `pie`, with shared variants, palettes, and exported chart prop types.
|
|
114
|
-
| `@zentauri-ui/zentauri-components/hooks/<entry>` | One hook module or `utils` (`cn`, `clampPage`, `range` from `src/lib/utils.ts`). Entries match files under `src/hooks/` (see **React hooks**).
|
|
121
|
+
| Subpath | Description |
|
|
122
|
+
| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
123
|
+
| `@zentauri-ui/zentauri-components/ui/<name>` | Single UI area: static primitives, compound parts, variants, and types. Does **not** include Framer Motion–based animated exports. |
|
|
124
|
+
| `@zentauri-ui/zentauri-components/ui/<name>/animated` | Motion entry for that area when published: animated components, motion presets, and related types (depends on **framer-motion**). |
|
|
125
|
+
| `@zentauri-ui/zentauri-components/charts/<type>` | Responsive Recharts chart entry for `area`, `bar`, `stacked-bar`, `radar`, `scatter`, `bubble`, `funnel`, `line`, or `pie`, with shared variants, palettes, and exported chart prop types. |
|
|
126
|
+
| `@zentauri-ui/zentauri-components/hooks/<entry>` | One hook module or `utils` (`cn`, `clampPage`, `range` from `src/lib/utils.ts`). Entries match files under `src/hooks/` (see **React hooks**). |
|
|
115
127
|
|
|
116
128
|
The UI `<name>` segment matches the folder under `src/ui/` (for example `accordion`, `select`, `empty-state`, `buttons` for `Button`, `inputs` for `Input`, `typography` for `Heading` / `Text` and related primitives). The hooks `<entry>` is the file stem (for example `useMediaQuery`, `usePagination`) or `utils`.
|
|
117
129
|
|
|
@@ -124,7 +136,7 @@ Only a subset of UI areas publish a `/animated` entry (see **Components**). Some
|
|
|
124
136
|
|
|
125
137
|
Published motion entries (same `<name>` as the base UI folder):
|
|
126
138
|
|
|
127
|
-
`accordion`, `alert`, `avatar`, `badge`, `buttons`, `card`, `checkbox`, `divider`, `drawer`, `empty-state`, `inputs`, `modal`, `popover`, `progress`, `radio-group`, `skeleton`, `spinner`, `table`, `tabs`, `toast`, `toggle`, `tooltip`, `tree-view`
|
|
139
|
+
`accordion`, `alert`, `avatar`, `badge`, `buttons`, `card`, `checkbox`, `command`, `copy-button`, `divider`, `drawer`, `empty-state`, `inputs`, `kbd`, `modal`, `popover`, `progress`, `radio-group`, `skeleton`, `spinner`, `table`, `tabs`, `timeline`, `toast`, `toggle`, `tooltip`, `tree-view`
|
|
128
140
|
|
|
129
141
|
**Spinner:** only the motion entry is built—import from `@zentauri-ui/zentauri-components/ui/spinner/animated` (there is no separate `ui/spinner` static bundle).
|
|
130
142
|
|
|
@@ -142,6 +154,7 @@ Import static primitives from `@zentauri-ui/zentauri-components/ui/<subpath>` wh
|
|
|
142
154
|
| --------------- | ----------------- | ---------------------------------- |
|
|
143
155
|
| Accordion | `accordion` | `accordion/animated` |
|
|
144
156
|
| Alert | `alert` | `alert/animated` |
|
|
157
|
+
| Animated number | `animated-number` | — |
|
|
145
158
|
| Avatar | `avatar` | `avatar/animated` |
|
|
146
159
|
| Badge | `badge` | `badge/animated` |
|
|
147
160
|
| Breadcrumb | `breadcrumb` | — |
|
|
@@ -169,7 +182,7 @@ Import static primitives from `@zentauri-ui/zentauri-components/ui/<subpath>` wh
|
|
|
169
182
|
| Rating | `rating` | — |
|
|
170
183
|
| Radio group | `radio-group` | `radio-group/animated` |
|
|
171
184
|
| Scroll area | `scroll-area` | — |
|
|
172
|
-
| Search | `search` |
|
|
185
|
+
| Search | `search` | — |
|
|
173
186
|
| Select | `select` | — |
|
|
174
187
|
| Skeleton | `skeleton` | `skeleton/animated` |
|
|
175
188
|
| Slider | `slider` | — |
|
|
@@ -177,6 +190,7 @@ Import static primitives from `@zentauri-ui/zentauri-components/ui/<subpath>` wh
|
|
|
177
190
|
| Stepper | `stepper` | — |
|
|
178
191
|
| Table | `table` | `table/animated` |
|
|
179
192
|
| Tabs | `tabs` | `tabs/animated` |
|
|
193
|
+
| Timeline | `timeline` | `timeline/animated` |
|
|
180
194
|
| Toast | `toast` | `toast/animated` |
|
|
181
195
|
| Toggle | `toggle` | `toggle/animated` |
|
|
182
196
|
| Tooltip | `tooltip` | `tooltip/animated` |
|
|
@@ -655,9 +669,10 @@ Defaults look like this; edit `resolvedPaths` and `aliases` so they match your a
|
|
|
655
669
|
|
|
656
670
|
### Registry (`cli/registry.json`)
|
|
657
671
|
|
|
658
|
-
- **`components`**: sorted list of folder names under **`src/ui/`**, plus chart entries from **`src/charts/<type>`**, that `add` may copy. The file is **generated**; the canonical build
|
|
672
|
+
- **`components`**: sorted list of folder names under **`src/ui/`**, plus chart entries from **`src/charts/<type>`**, that `add` may copy. The file is **generated**; the canonical build lists live in **`tsup.config.ts`** as `uiComponentNames`, `uiAnimatedComponentNames`, and `chartEntryNames`, so animated-only entries such as **`spinner`** stay aligned with the CLI.
|
|
659
673
|
- **`hooks`**: sorted list of folder names under **`src/hooks/`** that `add hook` may copy; generated from **`hooksEntryNames`** in **`tsup.config.ts`** (same entries as published `…/hooks/<name>` subpaths).
|
|
660
|
-
- **`nameAliases`**: optional map from a CLI token to a real folder name
|
|
674
|
+
- **`nameAliases`**: optional map from a CLI token to a real folder name: `button` → `buttons`, `input` → `inputs` (singular forms while folders stay plural), and `chart-<type>` → `charts/<type>` for every chart (so `add chart-line` and `add charts/line` are equivalent).
|
|
675
|
+
- **`peerHints`**: generated map from a component/chart name to the **optional peer dependencies** its source imports (`framer-motion` for components that ship an `animated/` variant, `react-icons` where icons are used, `recharts` for every chart). After `add`, the CLI prints a deduplicated install hint built from this map, so you never have to guess which peers a vendored component needs.
|
|
661
676
|
|
|
662
677
|
Example: these are equivalent when `nameAliases` is configured:
|
|
663
678
|
|
|
@@ -668,6 +683,45 @@ zentauri-components add buttons
|
|
|
668
683
|
|
|
669
684
|
After `add`, imports inside copied `.ts`/`.tsx` files are rewritten using your `aliases`; test files (`*.test.*`, `*.spec.*`) from the package are not copied.
|
|
670
685
|
|
|
686
|
+
### Worked examples
|
|
687
|
+
|
|
688
|
+
```bash
|
|
689
|
+
# A static UI primitive — copies src/ui/buttons plus the shared design-system tokens it imports.
|
|
690
|
+
zentauri-ui add button
|
|
691
|
+
|
|
692
|
+
# A chart — copies src/charts/line and the shared chart frame; CLI hints `recharts`.
|
|
693
|
+
zentauri-ui add charts/line
|
|
694
|
+
|
|
695
|
+
# A hook on its own — copies src/hooks/useClipboard (plus any sibling hooks it imports).
|
|
696
|
+
zentauri-ui add hook useClipboard
|
|
697
|
+
```
|
|
698
|
+
|
|
699
|
+
### Vendored destination structure
|
|
700
|
+
|
|
701
|
+
Given the default `components.json`, running `zentauri-ui add button charts/line` then `add hook useClipboard` produces:
|
|
702
|
+
|
|
703
|
+
```
|
|
704
|
+
your-app/
|
|
705
|
+
├── components.json
|
|
706
|
+
└── src/
|
|
707
|
+
├── components/
|
|
708
|
+
│ ├── design-system/ # shared token + variant strings (copied once, never overwritten)
|
|
709
|
+
│ │ └── button.ts
|
|
710
|
+
│ └── ui/
|
|
711
|
+
│ ├── buttons/ # the component folder (index.ts, button.tsx, variants.ts, …)
|
|
712
|
+
│ └── charts/
|
|
713
|
+
│ ├── shared/ # chart frame + helpers shared by every chart
|
|
714
|
+
│ └── line/ # the requested chart entry only
|
|
715
|
+
├── hooks/
|
|
716
|
+
│ └── useClipboard/ # hooks pulled in by components or `add hook`
|
|
717
|
+
└── lib/
|
|
718
|
+
└── utils.ts # cn() helper, created from the package template if missing
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
- `design-system/` lands beside `ui/` (one level up from `resolvedPaths.ui`) so vendored components keep their `../../design-system/*` imports working without a new alias. Existing files there are left untouched on re-add.
|
|
722
|
+
- Charts always land under `<ui>/charts/`, with a single shared `charts/shared/` folder regardless of how many chart types you add.
|
|
723
|
+
- Re-adding a component overwrites that component's files but preserves your `design-system/` and `lib/utils.ts` edits.
|
|
724
|
+
|
|
671
725
|
### When to use the CLI vs npm imports
|
|
672
726
|
|
|
673
727
|
| Approach | Best when |
|
|
@@ -681,14 +735,47 @@ Tailwind still needs to see the classes your **copied** files use—point `@sour
|
|
|
681
735
|
|
|
682
736
|
https://zentauri-ui.vercel.app/
|
|
683
737
|
|
|
738
|
+
## Accessibility checklist for contributors
|
|
739
|
+
|
|
740
|
+
Every new or changed component should clear this bar before it merges. The
|
|
741
|
+
highest-risk primitives (overlays and keyboard-heavy controls) are expected to
|
|
742
|
+
have explicit tests for the items below.
|
|
743
|
+
|
|
744
|
+
**Semantics & ARIA**
|
|
745
|
+
|
|
746
|
+
- [ ] Correct landmark/role for the pattern (`dialog`, `menu`/`menuitem`, `listbox`/`option`, `tab`/`tabpanel`, `slider`, `tree`/`treeitem`, …).
|
|
747
|
+
- [ ] State is announced: `aria-expanded`, `aria-selected`, `aria-checked`, `aria-disabled`, `aria-current` as appropriate.
|
|
748
|
+
- [ ] Overlays set `aria-modal` and wire `aria-labelledby` / `aria-describedby` to the rendered title/description.
|
|
749
|
+
- [ ] Compound parts are linked by id (`aria-controls`, `aria-haspopup`) rather than relying on DOM proximity.
|
|
750
|
+
|
|
751
|
+
**Keyboard**
|
|
752
|
+
|
|
753
|
+
- [ ] All interactive parts are reachable and operable by keyboard (Enter/Space activate; Arrow keys navigate where the role implies it).
|
|
754
|
+
- [ ] Roving tabindex for composite widgets (one tab stop; arrows move within).
|
|
755
|
+
- [ ] Dismissible surfaces close on `Escape`.
|
|
756
|
+
- [ ] Focus moves into an opened overlay and **returns to the trigger** on close.
|
|
757
|
+
|
|
758
|
+
**Disabled & edge states**
|
|
759
|
+
|
|
760
|
+
- [ ] Disabled items are skipped by keyboard navigation and ignore pointer activation, and expose `aria-disabled`.
|
|
761
|
+
- [ ] SSR-safe: no access to `window`/`document` during render (guard effects; the package targets React 18+ server rendering).
|
|
762
|
+
|
|
763
|
+
**Motion**
|
|
764
|
+
|
|
765
|
+
- [ ] Animated entries respect `prefers-reduced-motion` (use `usePrefersReducedMotion` / Framer Motion's `useReducedMotion`).
|
|
766
|
+
- [ ] `framer-motion` stays out of static entries — enforced by `src/ui/peer-isolation.test.ts`. Charts stay isolated to `src/charts/*`.
|
|
767
|
+
|
|
768
|
+
Add or extend the component's `*.test.tsx` to cover the items that apply; see
|
|
769
|
+
`modal`, `select`, and `context-menu` tests for worked examples.
|
|
770
|
+
|
|
684
771
|
## Development
|
|
685
772
|
|
|
686
773
|
From this package directory in the monorepo:
|
|
687
774
|
|
|
688
775
|
- `pnpm build` (or `npm run build`) — production bundle via `tsup` (Rollup treeshake + `scripts/prepend-use-client.mjs` via `onSuccess` so each UI entry under `dist/ui/`, the chart entry under `dist/charts/`, and `dist/ui/<name>/animated.*` starts with `"use client"` where needed)
|
|
689
776
|
- `pnpm dev` — `tsup` watch mode (same `onSuccess` hook after each rebuild)
|
|
690
|
-
- `pnpm test` / `pnpm test:watch` — **Vitest** and **Testing Library** unit tests // covered
|
|
691
|
-
- **`pnpm run generate:registry`** — runs `scripts/generate-registry.mjs`, which reads **`uiComponentNames`**, **`chartEntryNames`**, and **`hooksEntryNames`** from `tsup.config.ts`,
|
|
777
|
+
- `pnpm test` / `pnpm test:watch` — **Vitest** and **Testing Library** unit tests // covered 548 test cases in total
|
|
778
|
+
- **`pnpm run generate:registry`** — runs `scripts/generate-registry.mjs`, which reads **`uiComponentNames`**, **`uiAnimatedComponentNames`**, **`chartEntryNames`**, and **`hooksEntryNames`** from `tsup.config.ts`, applies fixed **`nameAliases`**, scans each component/chart source to build **`peerHints`**, and writes **`cli/registry.json`** (`components` + `hooks` + `peerHints`). Run this after adding or renaming UI/chart areas or hook entries so the CLI stays in sync (the script prints counts).
|
|
692
779
|
|
|
693
780
|
## Github Release log
|
|
694
781
|
|
|
@@ -9,8 +9,8 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
9
9
|
const packageRoot = join(__dirname, "..");
|
|
10
10
|
const cliEntry = join(packageRoot, "cli", "index.mjs");
|
|
11
11
|
|
|
12
|
-
function runCli(cwd: string, args: string[]) {
|
|
13
|
-
execFileSync(process.execPath, [cliEntry, ...args], {
|
|
12
|
+
function runCli(cwd: string, args: string[]): string {
|
|
13
|
+
return execFileSync(process.execPath, [cliEntry, ...args], {
|
|
14
14
|
cwd,
|
|
15
15
|
encoding: "utf8",
|
|
16
16
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -84,4 +84,79 @@ describe("zentauri-ui CLI", () => {
|
|
|
84
84
|
rmSync(dir, { recursive: true, force: true });
|
|
85
85
|
}
|
|
86
86
|
});
|
|
87
|
+
|
|
88
|
+
it("should add a chart entry under charts/ and hint recharts", () => {
|
|
89
|
+
const dir = mkdtempSync(join(tmpdir(), "zentauri-cli-chart-"));
|
|
90
|
+
try {
|
|
91
|
+
runCli(dir, ["init"]);
|
|
92
|
+
const out = runCli(dir, ["add", "charts/line"]);
|
|
93
|
+
expect(
|
|
94
|
+
existsSync(join(dir, "src/components/ui/charts/line/index.ts")),
|
|
95
|
+
).toBe(true);
|
|
96
|
+
// chart-line alias resolves to charts/line as well
|
|
97
|
+
expect(out).toContain("recharts");
|
|
98
|
+
} finally {
|
|
99
|
+
rmSync(dir, { recursive: true, force: true });
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("should add multiple components in one run", () => {
|
|
104
|
+
const dir = mkdtempSync(join(tmpdir(), "zentauri-cli-multi-"));
|
|
105
|
+
try {
|
|
106
|
+
runCli(dir, ["init"]);
|
|
107
|
+
const out = runCli(dir, ["add", "buttons", "card", "badge"]);
|
|
108
|
+
expect(existsSync(join(dir, "src/components/ui/buttons/button.tsx"))).toBe(
|
|
109
|
+
true,
|
|
110
|
+
);
|
|
111
|
+
expect(existsSync(join(dir, "src/components/ui/card/card.tsx"))).toBe(
|
|
112
|
+
true,
|
|
113
|
+
);
|
|
114
|
+
expect(existsSync(join(dir, "src/components/ui/badge/badge.tsx"))).toBe(
|
|
115
|
+
true,
|
|
116
|
+
);
|
|
117
|
+
expect(out).toContain("Adding buttons…");
|
|
118
|
+
expect(out).toContain("Adding badge…");
|
|
119
|
+
} finally {
|
|
120
|
+
rmSync(dir, { recursive: true, force: true });
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("should print react-icons peer hint for components that use icons", () => {
|
|
125
|
+
const dir = mkdtempSync(join(tmpdir(), "zentauri-cli-peer-"));
|
|
126
|
+
try {
|
|
127
|
+
runCli(dir, ["init"]);
|
|
128
|
+
const out = runCli(dir, ["add", "rating"]);
|
|
129
|
+
expect(out).toContain("Optional peer dependencies");
|
|
130
|
+
expect(out).toContain("react-icons");
|
|
131
|
+
} finally {
|
|
132
|
+
rmSync(dir, { recursive: true, force: true });
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it("should print Tailwind v4 source guidance after adding", () => {
|
|
137
|
+
const dir = mkdtempSync(join(tmpdir(), "zentauri-cli-tw-"));
|
|
138
|
+
try {
|
|
139
|
+
runCli(dir, ["init"]);
|
|
140
|
+
const out = runCli(dir, ["add", "buttons"]);
|
|
141
|
+
expect(out).toContain("Tailwind v4");
|
|
142
|
+
expect(out).toContain("@source");
|
|
143
|
+
} finally {
|
|
144
|
+
rmSync(dir, { recursive: true, force: true });
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("should not error when re-adding a component (existing files)", () => {
|
|
149
|
+
const dir = mkdtempSync(join(tmpdir(), "zentauri-cli-reAdd-"));
|
|
150
|
+
try {
|
|
151
|
+
runCli(dir, ["init"]);
|
|
152
|
+
runCli(dir, ["add", "buttons"]);
|
|
153
|
+
// Second add over existing files must succeed and keep the design-system.
|
|
154
|
+
expect(() => runCli(dir, ["add", "buttons"])).not.toThrow();
|
|
155
|
+
expect(
|
|
156
|
+
existsSync(join(dir, "src/components/design-system/button.ts")),
|
|
157
|
+
).toBe(true);
|
|
158
|
+
} finally {
|
|
159
|
+
rmSync(dir, { recursive: true, force: true });
|
|
160
|
+
}
|
|
161
|
+
});
|
|
87
162
|
});
|
package/cli/index.mjs
CHANGED
|
@@ -599,6 +599,58 @@ async function ensureUtilsFile(config, configDir, packageRoot) {
|
|
|
599
599
|
console.log(`Created ${relative(configDir, dest)}`);
|
|
600
600
|
}
|
|
601
601
|
|
|
602
|
+
/**
|
|
603
|
+
* Human-readable note explaining why each optional peer dependency may be
|
|
604
|
+
* needed, so the install hint is self-explanatory.
|
|
605
|
+
*/
|
|
606
|
+
const PEER_HINT_REASONS = {
|
|
607
|
+
"framer-motion": "only if you use the animated variants",
|
|
608
|
+
"react-icons": "icons used by this component",
|
|
609
|
+
recharts: "required to render charts",
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* Prints optional peer-dependency install hints and Tailwind v4 scanning
|
|
614
|
+
* guidance after a successful `add`. Hints come from `registry.peerHints`
|
|
615
|
+
* (generated by scripts/generate-registry.mjs). Silent when nothing applies.
|
|
616
|
+
*
|
|
617
|
+
* @param {string[]} resolvedNames — canonical component/chart names that were added
|
|
618
|
+
* @param {object} registry — from `loadRegistry()`
|
|
619
|
+
* @param {object} config — validated `components.json` (for resolvedPaths.ui)
|
|
620
|
+
*/
|
|
621
|
+
function printAdoptionHints(resolvedNames, registry, config) {
|
|
622
|
+
const peerHints = registry.peerHints ?? {};
|
|
623
|
+
/** @type {Map<string, string[]>} peer -> component names that need it */
|
|
624
|
+
const needed = new Map();
|
|
625
|
+
for (const name of resolvedNames) {
|
|
626
|
+
for (const peer of peerHints[name] ?? []) {
|
|
627
|
+
if (!needed.has(peer)) {
|
|
628
|
+
needed.set(peer, []);
|
|
629
|
+
}
|
|
630
|
+
needed.get(peer).push(name);
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
if (needed.size > 0) {
|
|
635
|
+
console.log("\nOptional peer dependencies:");
|
|
636
|
+
for (const [peer, users] of needed) {
|
|
637
|
+
const reason = PEER_HINT_REASONS[peer] ?? "";
|
|
638
|
+
console.log(
|
|
639
|
+
` - ${peer}${reason ? ` (${reason})` : ""} — used by ${users.join(", ")}`,
|
|
640
|
+
);
|
|
641
|
+
}
|
|
642
|
+
console.log(` Install with: npm i ${[...needed.keys()].join(" ")}`);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
const uiPath = config?.resolvedPaths?.ui ?? "your components directory";
|
|
646
|
+
console.log(
|
|
647
|
+
`\nTailwind v4: vendored files live in ${uiPath}, so they are scanned automatically when inside your app's content sources.`,
|
|
648
|
+
);
|
|
649
|
+
console.log(
|
|
650
|
+
` If you placed them elsewhere, add: @source "${uiPath}"; (light + dark: classes are paired, so the whole tree must be scanned)`,
|
|
651
|
+
);
|
|
652
|
+
}
|
|
653
|
+
|
|
602
654
|
/**
|
|
603
655
|
* `zentauri-components init` — writes default `components.json` next to `--cwd`.
|
|
604
656
|
*
|
|
@@ -707,6 +759,7 @@ async function cmdAdd(names, cwd) {
|
|
|
707
759
|
}
|
|
708
760
|
|
|
709
761
|
console.log("Done.");
|
|
762
|
+
printAdoptionHints(resolvedNames, registry, config);
|
|
710
763
|
}
|
|
711
764
|
|
|
712
765
|
/**
|
package/cli/registry.json
CHANGED
|
@@ -85,6 +85,132 @@
|
|
|
85
85
|
"useToggle",
|
|
86
86
|
"useWindowSize"
|
|
87
87
|
],
|
|
88
|
+
"peerHints": {
|
|
89
|
+
"accordion": [
|
|
90
|
+
"framer-motion"
|
|
91
|
+
],
|
|
92
|
+
"alert": [
|
|
93
|
+
"react-icons",
|
|
94
|
+
"framer-motion"
|
|
95
|
+
],
|
|
96
|
+
"animated-number": [
|
|
97
|
+
"framer-motion"
|
|
98
|
+
],
|
|
99
|
+
"avatar": [
|
|
100
|
+
"framer-motion"
|
|
101
|
+
],
|
|
102
|
+
"badge": [
|
|
103
|
+
"react-icons",
|
|
104
|
+
"framer-motion"
|
|
105
|
+
],
|
|
106
|
+
"buttons": [
|
|
107
|
+
"framer-motion"
|
|
108
|
+
],
|
|
109
|
+
"card": [
|
|
110
|
+
"framer-motion"
|
|
111
|
+
],
|
|
112
|
+
"checkbox": [
|
|
113
|
+
"framer-motion"
|
|
114
|
+
],
|
|
115
|
+
"command": [
|
|
116
|
+
"framer-motion"
|
|
117
|
+
],
|
|
118
|
+
"context-menu": [
|
|
119
|
+
"react-icons"
|
|
120
|
+
],
|
|
121
|
+
"copy-button": [
|
|
122
|
+
"react-icons",
|
|
123
|
+
"framer-motion"
|
|
124
|
+
],
|
|
125
|
+
"divider": [
|
|
126
|
+
"framer-motion"
|
|
127
|
+
],
|
|
128
|
+
"drawer": [
|
|
129
|
+
"framer-motion"
|
|
130
|
+
],
|
|
131
|
+
"dropdown": [
|
|
132
|
+
"react-icons"
|
|
133
|
+
],
|
|
134
|
+
"empty-state": [
|
|
135
|
+
"framer-motion"
|
|
136
|
+
],
|
|
137
|
+
"inputs": [
|
|
138
|
+
"framer-motion"
|
|
139
|
+
],
|
|
140
|
+
"kbd": [
|
|
141
|
+
"framer-motion"
|
|
142
|
+
],
|
|
143
|
+
"modal": [
|
|
144
|
+
"framer-motion"
|
|
145
|
+
],
|
|
146
|
+
"popover": [
|
|
147
|
+
"framer-motion"
|
|
148
|
+
],
|
|
149
|
+
"progress": [
|
|
150
|
+
"framer-motion"
|
|
151
|
+
],
|
|
152
|
+
"radio-group": [
|
|
153
|
+
"framer-motion"
|
|
154
|
+
],
|
|
155
|
+
"rating": [
|
|
156
|
+
"react-icons"
|
|
157
|
+
],
|
|
158
|
+
"skeleton": [
|
|
159
|
+
"framer-motion"
|
|
160
|
+
],
|
|
161
|
+
"table": [
|
|
162
|
+
"framer-motion"
|
|
163
|
+
],
|
|
164
|
+
"tabs": [
|
|
165
|
+
"framer-motion"
|
|
166
|
+
],
|
|
167
|
+
"timeline": [
|
|
168
|
+
"framer-motion"
|
|
169
|
+
],
|
|
170
|
+
"toast": [
|
|
171
|
+
"framer-motion"
|
|
172
|
+
],
|
|
173
|
+
"toggle": [
|
|
174
|
+
"framer-motion"
|
|
175
|
+
],
|
|
176
|
+
"tooltip": [
|
|
177
|
+
"framer-motion"
|
|
178
|
+
],
|
|
179
|
+
"tree-view": [
|
|
180
|
+
"react-icons",
|
|
181
|
+
"framer-motion"
|
|
182
|
+
],
|
|
183
|
+
"spinner": [
|
|
184
|
+
"framer-motion"
|
|
185
|
+
],
|
|
186
|
+
"charts/area": [
|
|
187
|
+
"recharts"
|
|
188
|
+
],
|
|
189
|
+
"charts/bar": [
|
|
190
|
+
"recharts"
|
|
191
|
+
],
|
|
192
|
+
"charts/bubble": [
|
|
193
|
+
"recharts"
|
|
194
|
+
],
|
|
195
|
+
"charts/funnel": [
|
|
196
|
+
"recharts"
|
|
197
|
+
],
|
|
198
|
+
"charts/line": [
|
|
199
|
+
"recharts"
|
|
200
|
+
],
|
|
201
|
+
"charts/pie": [
|
|
202
|
+
"recharts"
|
|
203
|
+
],
|
|
204
|
+
"charts/radar": [
|
|
205
|
+
"recharts"
|
|
206
|
+
],
|
|
207
|
+
"charts/scatter": [
|
|
208
|
+
"recharts"
|
|
209
|
+
],
|
|
210
|
+
"charts/stacked-bar": [
|
|
211
|
+
"recharts"
|
|
212
|
+
]
|
|
213
|
+
},
|
|
88
214
|
"nameAliases": {
|
|
89
215
|
"button": "buttons",
|
|
90
216
|
"chart-area": "charts/area",
|
package/cli/rewrite-imports.mjs
CHANGED
|
@@ -13,7 +13,10 @@ export function rewriteImports(source, options) {
|
|
|
13
13
|
const re = /from\s+(["'])((?:\.\.\/)+)hooks\/([^'"]+)\1/g;
|
|
14
14
|
let m;
|
|
15
15
|
while ((m = re.exec(text)) !== null) {
|
|
16
|
-
|
|
16
|
+
// Imports may target a file inside the hook folder
|
|
17
|
+
// (e.g. hooks/useResizeObserver/useResizeObserver); the copyable unit is
|
|
18
|
+
// the folder, so keep only the first path segment.
|
|
19
|
+
usedHooks.add(m[3].split("/")[0]);
|
|
17
20
|
}
|
|
18
21
|
};
|
|
19
22
|
|
|
@@ -1,24 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var chunkMUP7DVQR_js = require('./chunk-MUP7DVQR.js');
|
|
3
4
|
var classVarianceAuthority = require('class-variance-authority');
|
|
4
5
|
|
|
5
|
-
// src/ui/buttons/variants.ts
|
|
6
|
-
|
|
7
|
-
// src/design-system/tokens.ts
|
|
8
|
-
var zuiInteractiveBase = ["transition-colors", "select-none"];
|
|
9
|
-
var zuiDisabledState = {
|
|
10
|
-
default: "disabled:pointer-events-none disabled:opacity-50"
|
|
11
|
-
};
|
|
12
|
-
|
|
13
6
|
// src/design-system/button.ts
|
|
14
7
|
var zuiButtonBase = [
|
|
15
8
|
"inline-flex items-center justify-center gap-2 whitespace-nowrap",
|
|
16
9
|
"rounded-[var(--zui-button-radius,0.75rem)]",
|
|
17
10
|
"text-sm font-medium",
|
|
18
11
|
"ring-offset-[var(--zui-button-ring-offset,#f8fafc)] dark:ring-offset-[var(--zui-button-ring-offset-dark,#020617)]",
|
|
19
|
-
...zuiInteractiveBase,
|
|
12
|
+
...chunkMUP7DVQR_js.zuiInteractiveBase,
|
|
20
13
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--zui-button-focus-ring,#475569)] dark:focus-visible:ring-[var(--zui-button-focus-ring-dark,#cbd5e1)] focus-visible:ring-offset-2",
|
|
21
|
-
zuiDisabledState.default
|
|
14
|
+
chunkMUP7DVQR_js.zuiDisabledState.default
|
|
22
15
|
];
|
|
23
16
|
var zuiButtonAppearances = {
|
|
24
17
|
default: "bg-[var(--zui-button-default-bg,#0f172a)] dark:bg-[var(--zui-button-default-bg-dark,#f8fafc)] text-[color:var(--zui-button-default-fg,#f8fafc)] dark:text-[color:var(--zui-button-default-fg-dark,#020617)] shadow-[var(--zui-button-default-shadow,0_1px_2px_#0f172a14)] dark:shadow-[var(--zui-button-default-shadow-dark,0_1px_2px_#0f172a1f)] hover:bg-[var(--zui-button-default-bg-hover,#000000)] dark:hover:bg-[var(--zui-button-default-bg-hover-dark,#ffffff)]",
|
|
@@ -80,5 +73,5 @@ var buttonVariants = classVarianceAuthority.cva(zuiButtonBase, {
|
|
|
80
73
|
});
|
|
81
74
|
|
|
82
75
|
exports.buttonVariants = buttonVariants;
|
|
83
|
-
//# sourceMappingURL=chunk-
|
|
84
|
-
//# sourceMappingURL=chunk-
|
|
76
|
+
//# sourceMappingURL=chunk-466QDL44.js.map
|
|
77
|
+
//# sourceMappingURL=chunk-466QDL44.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/design-system/button.ts","../src/ui/buttons/variants.ts"],"names":["zuiInteractiveBase","zuiDisabledState","cva"],"mappings":";;;;;;AAEO,IAAM,aAAA,GAAgB;AAAA,EAC3B,iEAAA;AAAA,EACA,4CAAA;AAAA,EACA,qBAAA;AAAA,EACA,mHAAA;AAAA,EACA,GAAGA,mCAAA;AAAA,EACH,2MAAA;AAAA,EACAC,iCAAA,CAAiB;AACnB,CAAA;AAEO,IAAM,oBAAA,GAAuB;AAAA,EAClC,OAAA,EACE,ycAAA;AAAA,EACF,SAAA,EACE,+UAAA;AAAA,EACF,WAAA,EACE,2VAAA;AAAA,EACF,OAAA,EACE,gdAAA;AAAA,EACF,KAAA,EACE,gPAAA;AAAA,EACF,IAAA,EAAM,2JAAA;AAAA,EACN,KAAA,EACE,idAAA;AAAA,EACF,OAAA,EACE,mUAAA;AAAA,EACF,MAAA,EACE,6TAAA;AAAA,EACF,MAAA,EACE,6TAAA;AAAA,EACF,IAAA,EAAM,iTAAA;AAAA,EACN,IAAA,EAAM,iTAAA;AAAA,EACN,GAAA,EAAK,2SAAA;AAAA,EACL,IAAA,EAAM,iTAAA;AAAA,EACN,MAAA,EACE,6TAAA;AAAA,EACF,MAAA,EACE,6TAAA;AAAA,EACF,IAAA,EAAM,iTAAA;AAAA,EACN,KAAA,EACE,uTAAA;AAAA,EACF,MAAA,EACE,6TAAA;AAAA,EACF,eAAA,EACE,knBAAA;AAAA,EACF,gBAAA,EACE,4nBAAA;AAAA,EACF,cAAA,EACE,wmBAAA;AAAA,EACF,iBAAA,EACE,soBAAA;AAAA,EACF,iBAAA,EACE,soBAAA;AAAA,EACF,eAAA,EACE,knBAAA;AAAA,EACF,iBAAA,EACE,soBAAA;AAAA,EACF,eAAA,EACE,knBAAA;AAAA,EACF,iBAAA,EACE;AACJ,CAAA;AAEO,IAAM,cAAA,GAAiB;AAAA,EAC5B,EAAA,EAAI,yBAAA;AAAA,EACJ,EAAA,EAAI,kBAAA;AAAA,EACJ,EAAA,EAAI,6BAAA;AAAA,EACJ,EAAA,EAAI,2BAAA;AAAA,EACJ,KAAA,EAAO,mCAAA;AAAA,EACP,KAAA,EAAO,qCAAA;AAAA,EACP,KAAA,EAAO,sCAAA;AAAA,EACP,KAAA,EAAO,sCAAA;AAAA,EACP,KAAA,EAAO,sCAAA;AAAA,EACP,KAAA,EAAO,sCAAA;AAAA,EACP,KAAA,EAAO,6BAAA;AAAA,EACP,KAAA,EAAO,sCAAA;AAAA,EACP,MAAA,EAAQ,sCAAA;AAAA,EACR,IAAA,EAAM;AACR,CAAA;;;ACxEO,IAAM,cAAA,GAAiBC,2BAAI,aAAA,EAAe;AAAA,EAC/C,QAAA,EAAU;AAAA,IACR,UAAA,EAAY,oBAAA;AAAA,IACZ,IAAA,EAAM;AAAA,GACR;AAAA,EACA,eAAA,EAAiB;AAAA,IACf,UAAA,EAAY,SAAA;AAAA,IACZ,IAAA,EAAM;AAAA;AAEV,CAAC","file":"chunk-466QDL44.js","sourcesContent":["import { zuiDisabledState, zuiInteractiveBase } from \"./tokens\";\n\nexport const zuiButtonBase = [\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap\",\n \"rounded-[var(--zui-button-radius,0.75rem)]\",\n \"text-sm font-medium\",\n \"ring-offset-[var(--zui-button-ring-offset,#f8fafc)] dark:ring-offset-[var(--zui-button-ring-offset-dark,#020617)]\",\n ...zuiInteractiveBase,\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--zui-button-focus-ring,#475569)] dark:focus-visible:ring-[var(--zui-button-focus-ring-dark,#cbd5e1)] focus-visible:ring-offset-2\",\n zuiDisabledState.default,\n] as const;\n\nexport const zuiButtonAppearances = {\n default:\n \"bg-[var(--zui-button-default-bg,#0f172a)] dark:bg-[var(--zui-button-default-bg-dark,#f8fafc)] text-[color:var(--zui-button-default-fg,#f8fafc)] dark:text-[color:var(--zui-button-default-fg-dark,#020617)] shadow-[var(--zui-button-default-shadow,0_1px_2px_#0f172a14)] dark:shadow-[var(--zui-button-default-shadow-dark,0_1px_2px_#0f172a1f)] hover:bg-[var(--zui-button-default-bg-hover,#000000)] dark:hover:bg-[var(--zui-button-default-bg-hover-dark,#ffffff)]\",\n secondary:\n \"bg-[var(--zui-button-secondary-bg,#e2e8f0)] dark:bg-[var(--zui-button-secondary-bg-dark,#1e293b)] text-[color:var(--zui-button-secondary-fg,#0f172a)] dark:text-[color:var(--zui-button-secondary-fg-dark,#f8fafc)] hover:bg-[var(--zui-button-secondary-bg-hover,#cbd5e1)] dark:hover:bg-[var(--zui-button-secondary-bg-hover-dark,#334155)]\",\n destructive:\n \"bg-[var(--zui-button-destructive-bg,#f43f5e)] dark:bg-[var(--zui-button-destructive-bg-dark,#be123c)] text-[color:var(--zui-button-destructive-fg,#ffffff)] dark:text-[color:var(--zui-button-destructive-fg-dark,#ffffff)] hover:bg-[var(--zui-button-destructive-bg-hover,#f43f5e)] dark:hover:bg-[var(--zui-button-destructive-bg-hover-dark,#9f1239)]\",\n outline:\n \"border border-[color:var(--zui-button-outline-border,#0000001a)] dark:border-[color:var(--zui-button-outline-border-dark,#ffffff1a)] bg-[var(--zui-button-outline-bg,#0000000d)] dark:bg-[var(--zui-button-outline-bg-dark,#ffffff0d)] text-[color:var(--zui-button-outline-fg,#0f172a)] dark:text-[color:var(--zui-button-outline-fg-dark,#f8fafc)] hover:bg-[var(--zui-button-outline-bg-hover,#0000001a)] dark:hover:bg-[var(--zui-button-outline-bg-hover-dark,#ffffff1a)]\",\n ghost:\n \"bg-transparent text-[color:var(--zui-button-ghost-fg,#334155)] dark:text-[color:var(--zui-button-ghost-fg-dark,#e2e8f0)] hover:bg-[var(--zui-button-ghost-bg-hover,#0000000d)] dark:hover:bg-[var(--zui-button-ghost-bg-hover-dark,#ffffff0d)]\",\n link: \"bg-transparent text-[color:var(--zui-button-link-fg,#0e7490)] dark:text-[color:var(--zui-button-link-fg-dark,#67e8f9)] underline-offset-4 hover:underline\",\n glass:\n \"border border-[color:var(--zui-button-glass-border,#00000026)] dark:border-[color:var(--zui-button-glass-border-dark,#ffffff26)] bg-[var(--zui-button-glass-bg,#0000001a)] dark:bg-[var(--zui-button-glass-bg-dark,#ffffff1a)] text-[color:var(--zui-button-glass-fg,#0f172a)] dark:text-[color:var(--zui-button-glass-fg-dark,#ffffff)] backdrop-blur-md hover:bg-[var(--zui-button-glass-bg-hover,#00000026)] dark:hover:bg-[var(--zui-button-glass-bg-hover-dark,#ffffff26)]\",\n emerald:\n \"bg-[var(--zui-button-emerald-bg,#10b981)] dark:bg-[var(--zui-button-emerald-bg-dark,#065f46)] text-[color:var(--zui-button-emerald-fg,#ffffff)] dark:text-[color:var(--zui-button-emerald-fg-dark,#ffffff)] hover:bg-[var(--zui-button-emerald-bg-hover,#10b981)] dark:hover:bg-[var(--zui-button-emerald-bg-hover-dark,#064e3b)]\",\n indigo:\n \"bg-[var(--zui-button-indigo-bg,#3730a3)] dark:bg-[var(--zui-button-indigo-bg-dark,#4f46e5)] text-[color:var(--zui-button-indigo-fg,#ffffff)] dark:text-[color:var(--zui-button-indigo-fg-dark,#ffffff)] hover:bg-[var(--zui-button-indigo-bg-hover,#3730a3)] dark:hover:bg-[var(--zui-button-indigo-bg-hover-dark,#4f46e5)]\",\n purple:\n \"bg-[var(--zui-button-purple-bg,#6b21a8)] dark:bg-[var(--zui-button-purple-bg-dark,#9333ea)] text-[color:var(--zui-button-purple-fg,#ffffff)] dark:text-[color:var(--zui-button-purple-fg-dark,#ffffff)] hover:bg-[var(--zui-button-purple-bg-hover,#6b21a8)] dark:hover:bg-[var(--zui-button-purple-bg-hover-dark,#9333ea)]\",\n pink: \"bg-[var(--zui-button-pink-bg,#9d174d)] dark:bg-[var(--zui-button-pink-bg-dark,#db2777)] text-[color:var(--zui-button-pink-fg,#ffffff)] dark:text-[color:var(--zui-button-pink-fg-dark,#ffffff)] hover:bg-[var(--zui-button-pink-bg-hover,#9d174d)] dark:hover:bg-[var(--zui-button-pink-bg-hover-dark,#db2777)]\",\n rose: \"bg-[var(--zui-button-rose-bg,#9f1239)] dark:bg-[var(--zui-button-rose-bg-dark,#e11d48)] text-[color:var(--zui-button-rose-fg,#ffffff)] dark:text-[color:var(--zui-button-rose-fg-dark,#ffffff)] hover:bg-[var(--zui-button-rose-bg-hover,#9f1239)] dark:hover:bg-[var(--zui-button-rose-bg-hover-dark,#e11d48)]\",\n sky: \"bg-[var(--zui-button-sky-bg,#0ea5e9)] dark:bg-[var(--zui-button-sky-bg-dark,#0369a1)] text-[color:var(--zui-button-sky-fg,#ffffff)] dark:text-[color:var(--zui-button-sky-fg-dark,#ffffff)] hover:bg-[var(--zui-button-sky-bg-hover,#0ea5e9)] dark:hover:bg-[var(--zui-button-sky-bg-hover-dark,#075985)]\",\n teal: \"bg-[var(--zui-button-teal-bg,#14b8a6)] dark:bg-[var(--zui-button-teal-bg-dark,#0f766e)] text-[color:var(--zui-button-teal-fg,#ffffff)] dark:text-[color:var(--zui-button-teal-fg-dark,#ffffff)] hover:bg-[var(--zui-button-teal-bg-hover,#14b8a6)] dark:hover:bg-[var(--zui-button-teal-bg-hover-dark,#115e59)]\",\n yellow:\n \"bg-[var(--zui-button-yellow-bg,#eab308)] dark:bg-[var(--zui-button-yellow-bg-dark,#854d0e)] text-[color:var(--zui-button-yellow-fg,#ffffff)] dark:text-[color:var(--zui-button-yellow-fg-dark,#ffffff)] hover:bg-[var(--zui-button-yellow-bg-hover,#eab308)] dark:hover:bg-[var(--zui-button-yellow-bg-hover-dark,#713f12)]\",\n orange:\n \"bg-[var(--zui-button-orange-bg,#f97316)] dark:bg-[var(--zui-button-orange-bg-dark,#9a3412)] text-[color:var(--zui-button-orange-fg,#ffffff)] dark:text-[color:var(--zui-button-orange-fg-dark,#ffffff)] hover:bg-[var(--zui-button-orange-bg-hover,#f97316)] dark:hover:bg-[var(--zui-button-orange-bg-hover-dark,#7c2d12)]\",\n gray: \"bg-[var(--zui-button-gray-bg,#6b7280)] dark:bg-[var(--zui-button-gray-bg-dark,#374151)] text-[color:var(--zui-button-gray-fg,#ffffff)] dark:text-[color:var(--zui-button-gray-fg-dark,#ffffff)] hover:bg-[var(--zui-button-gray-bg-hover,#6b7280)] dark:hover:bg-[var(--zui-button-gray-bg-hover-dark,#1f2937)]\",\n amber:\n \"bg-[var(--zui-button-amber-bg,#f59e0b)] dark:bg-[var(--zui-button-amber-bg-dark,#92400e)] text-[color:var(--zui-button-amber-fg,#ffffff)] dark:text-[color:var(--zui-button-amber-fg-dark,#ffffff)] hover:bg-[var(--zui-button-amber-bg-hover,#f59e0b)] dark:hover:bg-[var(--zui-button-amber-bg-hover-dark,#78350f)]\",\n violet:\n \"bg-[var(--zui-button-violet-bg,#5b21b6)] dark:bg-[var(--zui-button-violet-bg-dark,#7c3aed)] text-[color:var(--zui-button-violet-fg,#ffffff)] dark:text-[color:var(--zui-button-violet-fg-dark,#ffffff)] hover:bg-[var(--zui-button-violet-bg-hover,#5b21b6)] dark:hover:bg-[var(--zui-button-violet-bg-hover-dark,#7c3aed)]\",\n \"gradient-blue\":\n \"bg-linear-to-r from-[var(--zui-button-gradient-blue-from,#1e40af)] dark:from-[var(--zui-button-gradient-blue-from-dark,#2563eb)] to-[var(--zui-button-gradient-blue-to,#6b21a8)] dark:to-[var(--zui-button-gradient-blue-to-dark,#9333ea)] text-[color:var(--zui-button-gradient-blue-fg,#ffffff)] dark:text-[color:var(--zui-button-gradient-blue-fg-dark,#ffffff)] hover:from-[var(--zui-button-gradient-blue-from-hover,#1e40af)] dark:hover:from-[var(--zui-button-gradient-blue-from-hover-dark,#2563eb)] hover:to-[var(--zui-button-gradient-blue-to-hover,#6b21a8)] dark:hover:to-[var(--zui-button-gradient-blue-to-hover-dark,#9333ea)]\",\n \"gradient-green\":\n \"bg-linear-to-r from-[var(--zui-button-gradient-green-from,#166534)] dark:from-[var(--zui-button-gradient-green-from-dark,#16a34a)] to-[var(--zui-button-gradient-green-to,#3f6212)] dark:to-[var(--zui-button-gradient-green-to-dark,#65a30d)] text-[color:var(--zui-button-gradient-green-fg,#ffffff)] dark:text-[color:var(--zui-button-gradient-green-fg-dark,#ffffff)] hover:from-[var(--zui-button-gradient-green-from-hover,#166534)] dark:hover:from-[var(--zui-button-gradient-green-from-hover-dark,#16a34a)] hover:to-[var(--zui-button-gradient-green-to-hover,#3f6212)] dark:hover:to-[var(--zui-button-gradient-green-to-hover-dark,#65a30d)]\",\n \"gradient-red\":\n \"bg-linear-to-r from-[var(--zui-button-gradient-red-from,#991b1b)] dark:from-[var(--zui-button-gradient-red-from-dark,#dc2626)] to-[var(--zui-button-gradient-red-to,#9d174d)] dark:to-[var(--zui-button-gradient-red-to-dark,#db2777)] text-[color:var(--zui-button-gradient-red-fg,#ffffff)] dark:text-[color:var(--zui-button-gradient-red-fg-dark,#ffffff)] hover:from-[var(--zui-button-gradient-red-from-hover,#991b1b)] dark:hover:from-[var(--zui-button-gradient-red-from-hover-dark,#dc2626)] hover:to-[var(--zui-button-gradient-red-to-hover,#9d174d)] dark:hover:to-[var(--zui-button-gradient-red-to-hover-dark,#db2777)]\",\n \"gradient-yellow\":\n \"bg-linear-to-r from-[var(--zui-button-gradient-yellow-from,#854d0e)] dark:from-[var(--zui-button-gradient-yellow-from-dark,#ca8a04)] to-[var(--zui-button-gradient-yellow-to,#9a3412)] dark:to-[var(--zui-button-gradient-yellow-to-dark,#ea580c)] text-[color:var(--zui-button-gradient-yellow-fg,#ffffff)] dark:text-[color:var(--zui-button-gradient-yellow-fg-dark,#ffffff)] hover:from-[var(--zui-button-gradient-yellow-from-hover,#854d0e)] dark:hover:from-[var(--zui-button-gradient-yellow-from-hover-dark,#ca8a04)] hover:to-[var(--zui-button-gradient-yellow-to-hover,#9a3412)] dark:hover:to-[var(--zui-button-gradient-yellow-to-hover-dark,#ea580c)]\",\n \"gradient-purple\":\n \"bg-linear-to-r from-[var(--zui-button-gradient-purple-from,#6b21a8)] dark:from-[var(--zui-button-gradient-purple-from-dark,#9333ea)] to-[var(--zui-button-gradient-purple-to,#9d174d)] dark:to-[var(--zui-button-gradient-purple-to-dark,#db2777)] text-[color:var(--zui-button-gradient-purple-fg,#ffffff)] dark:text-[color:var(--zui-button-gradient-purple-fg-dark,#ffffff)] hover:from-[var(--zui-button-gradient-purple-from-hover,#6b21a8)] dark:hover:from-[var(--zui-button-gradient-purple-from-hover-dark,#9333ea)] hover:to-[var(--zui-button-gradient-purple-to-hover,#9d174d)] dark:hover:to-[var(--zui-button-gradient-purple-to-hover-dark,#db2777)]\",\n \"gradient-teal\":\n \"bg-linear-to-r from-[var(--zui-button-gradient-teal-from,#115e59)] dark:from-[var(--zui-button-gradient-teal-from-dark,#0d9488)] to-[var(--zui-button-gradient-teal-to,#155e75)] dark:to-[var(--zui-button-gradient-teal-to-dark,#0891b2)] text-[color:var(--zui-button-gradient-teal-fg,#ffffff)] dark:text-[color:var(--zui-button-gradient-teal-fg-dark,#ffffff)] hover:from-[var(--zui-button-gradient-teal-from-hover,#115e59)] dark:hover:from-[var(--zui-button-gradient-teal-from-hover-dark,#0d9488)] hover:to-[var(--zui-button-gradient-teal-to-hover,#155e75)] dark:hover:to-[var(--zui-button-gradient-teal-to-hover-dark,#0891b2)]\",\n \"gradient-indigo\":\n \"bg-linear-to-r from-[var(--zui-button-gradient-indigo-from,#3730a3)] dark:from-[var(--zui-button-gradient-indigo-from-dark,#4f46e5)] to-[var(--zui-button-gradient-indigo-to,#6b21a8)] dark:to-[var(--zui-button-gradient-indigo-to-dark,#9333ea)] text-[color:var(--zui-button-gradient-indigo-fg,#ffffff)] dark:text-[color:var(--zui-button-gradient-indigo-fg-dark,#ffffff)] hover:from-[var(--zui-button-gradient-indigo-from-hover,#3730a3)] dark:hover:from-[var(--zui-button-gradient-indigo-from-hover-dark,#4f46e5)] hover:to-[var(--zui-button-gradient-indigo-to-hover,#6b21a8)] dark:hover:to-[var(--zui-button-gradient-indigo-to-hover-dark,#9333ea)]\",\n \"gradient-pink\":\n \"bg-linear-to-r from-[var(--zui-button-gradient-pink-from,#9d174d)] dark:from-[var(--zui-button-gradient-pink-from-dark,#db2777)] to-[var(--zui-button-gradient-pink-to,#9f1239)] dark:to-[var(--zui-button-gradient-pink-to-dark,#e11d48)] text-[color:var(--zui-button-gradient-pink-fg,#ffffff)] dark:text-[color:var(--zui-button-gradient-pink-fg-dark,#ffffff)] hover:from-[var(--zui-button-gradient-pink-from-hover,#9d174d)] dark:hover:from-[var(--zui-button-gradient-pink-from-hover-dark,#db2777)] hover:to-[var(--zui-button-gradient-pink-to-hover,#9f1239)] dark:hover:to-[var(--zui-button-gradient-pink-to-hover-dark,#e11d48)]\",\n \"gradient-orange\":\n \"bg-linear-to-r from-[var(--zui-button-gradient-orange-from,#9a3412)] dark:from-[var(--zui-button-gradient-orange-from-dark,#ea580c)] to-[var(--zui-button-gradient-orange-to,#991b1b)] dark:to-[var(--zui-button-gradient-orange-to-dark,#dc2626)] text-[color:var(--zui-button-gradient-orange-fg,#ffffff)] dark:text-[color:var(--zui-button-gradient-orange-fg-dark,#ffffff)] hover:from-[var(--zui-button-gradient-orange-from-hover,#9a3412)] dark:hover:from-[var(--zui-button-gradient-orange-from-hover-dark,#ea580c)] hover:to-[var(--zui-button-gradient-orange-to-hover,#991b1b)] dark:hover:to-[var(--zui-button-gradient-orange-to-hover-dark,#dc2626)]\",\n} as const;\n\nexport const zuiButtonSizes = {\n sm: \"h-7 md:h-9 px-3 text-xs\",\n md: \"h-9 md:h-11 px-4\",\n lg: \"h-10 md:h-12 px-5 text-base\",\n xl: \"h-12 md:h-14 px-6 text-lg\",\n \"2xl\": \"h-14 md:h-16 px-6 md:px-8 text-xl\",\n \"3xl\": \"h-16 md:h-18 px-8 md:px-10 text-2xl\",\n \"4xl\": \"h-18 md:h-20 px-10 md:px-12 text-2xl\",\n \"5xl\": \"h-20 md:h-22 px-12 md:px-14 text-2xl\",\n \"6xl\": \"h-22 md:h-24 px-14 md:px-16 text-2xl\",\n \"7xl\": \"h-24 md:h-26 px-16 md:px-18 text-2xl\",\n \"8xl\": \"h-26 md:h-28 px-20 text-2xl\",\n \"9xl\": \"h-24 md:h-30 px-18 md:px-22 text-2xl\",\n \"10xl\": \"h-26 md:h-32 px-20 md:px-24 text-2xl\",\n icon: \"h-10 w-10\",\n} as const;\n","import { cva } from \"class-variance-authority\";\n\nimport {\n zuiButtonAppearances,\n zuiButtonBase,\n zuiButtonSizes,\n} from \"../../design-system\";\n\nexport const buttonVariants = cva(zuiButtonBase, {\n variants: {\n appearance: zuiButtonAppearances,\n size: zuiButtonSizes,\n },\n defaultVariants: {\n appearance: \"default\",\n size: \"md\",\n },\n});\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// src/design-system/tokens.ts
|
|
2
|
+
var zuiCssVariablePattern = "--zui-<component>-<slot?>-<variant?>-<property>-<state?>-dark?";
|
|
3
|
+
var zuiInteractiveBase = ["transition-colors", "select-none"];
|
|
4
|
+
var zuiDisabledState = {
|
|
5
|
+
default: "disabled:pointer-events-none disabled:opacity-50"
|
|
6
|
+
};
|
|
7
|
+
var zuiFocusRing = {
|
|
8
|
+
default: "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--zui-focus-ring,oklch(44.6%_0.043_257.281))] dark:focus-visible:ring-[var(--zui-focus-ring-dark,oklch(86.9%_0.022_252.894))] focus-visible:ring-offset-2"
|
|
9
|
+
};
|
|
10
|
+
var zuiRingOffset = {
|
|
11
|
+
default: "ring-offset-[var(--zui-ring-offset,oklch(98.4%_0.003_247.858))] dark:ring-offset-[var(--zui-ring-offset-dark,oklch(12.9%_0.042_264.695))]"
|
|
12
|
+
};
|
|
13
|
+
var zuiRadius = {
|
|
14
|
+
xl: "rounded-[var(--zui-radius-xl,0.75rem)]"
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export { zuiCssVariablePattern, zuiDisabledState, zuiFocusRing, zuiInteractiveBase, zuiRadius, zuiRingOffset };
|
|
18
|
+
//# sourceMappingURL=chunk-4ZP444GA.mjs.map
|
|
19
|
+
//# sourceMappingURL=chunk-4ZP444GA.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/design-system/tokens.ts"],"names":[],"mappings":";AAAO,IAAM,qBAAA,GACX;AAEK,IAAM,kBAAA,GAAqB,CAAC,mBAAA,EAAqB,aAAa;AAE9D,IAAM,gBAAA,GAAmB;AAAA,EAC9B,OAAA,EAAS;AACX;AAEO,IAAM,YAAA,GAAe;AAAA,EAC1B,OAAA,EACE;AACJ;AAEO,IAAM,aAAA,GAAgB;AAAA,EAC3B,OAAA,EACE;AACJ;AAEO,IAAM,SAAA,GAAY;AAAA,EACvB,EAAA,EAAI;AACN","file":"chunk-4ZP444GA.mjs","sourcesContent":["export const zuiCssVariablePattern =\n \"--zui-<component>-<slot?>-<variant?>-<property>-<state?>-dark?\" as const;\n\nexport const zuiInteractiveBase = [\"transition-colors\", \"select-none\"] as const;\n\nexport const zuiDisabledState = {\n default: \"disabled:pointer-events-none disabled:opacity-50\",\n} as const;\n\nexport const zuiFocusRing = {\n default:\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--zui-focus-ring,oklch(44.6%_0.043_257.281))] dark:focus-visible:ring-[var(--zui-focus-ring-dark,oklch(86.9%_0.022_252.894))] focus-visible:ring-offset-2\",\n} as const;\n\nexport const zuiRingOffset = {\n default:\n \"ring-offset-[var(--zui-ring-offset,oklch(98.4%_0.003_247.858))] dark:ring-offset-[var(--zui-ring-offset-dark,oklch(12.9%_0.042_264.695))]\",\n} as const;\n\nexport const zuiRadius = {\n xl: \"rounded-[var(--zui-radius-xl,0.75rem)]\",\n} as const;\n"]}
|
|
@@ -1,13 +1,6 @@
|
|
|
1
|
+
import { zuiInteractiveBase, zuiDisabledState } from './chunk-4ZP444GA.mjs';
|
|
1
2
|
import { cva } from 'class-variance-authority';
|
|
2
3
|
|
|
3
|
-
// src/ui/buttons/variants.ts
|
|
4
|
-
|
|
5
|
-
// src/design-system/tokens.ts
|
|
6
|
-
var zuiInteractiveBase = ["transition-colors", "select-none"];
|
|
7
|
-
var zuiDisabledState = {
|
|
8
|
-
default: "disabled:pointer-events-none disabled:opacity-50"
|
|
9
|
-
};
|
|
10
|
-
|
|
11
4
|
// src/design-system/button.ts
|
|
12
5
|
var zuiButtonBase = [
|
|
13
6
|
"inline-flex items-center justify-center gap-2 whitespace-nowrap",
|
|
@@ -78,5 +71,5 @@ var buttonVariants = cva(zuiButtonBase, {
|
|
|
78
71
|
});
|
|
79
72
|
|
|
80
73
|
export { buttonVariants };
|
|
81
|
-
//# sourceMappingURL=chunk-
|
|
82
|
-
//# sourceMappingURL=chunk-
|
|
74
|
+
//# sourceMappingURL=chunk-CIEZFHCO.mjs.map
|
|
75
|
+
//# sourceMappingURL=chunk-CIEZFHCO.mjs.map
|