@pihanga2/shadcn 0.2.0 → 0.2.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.
Files changed (130) hide show
  1. package/AGENT.building-cards.md +208 -3
  2. package/AGENT.md +66 -4
  3. package/AGENT.using-cards.md +197 -250
  4. package/README.md +4 -1
  5. package/cards/badge/badge.component.js +1 -0
  6. package/cards/badge/badge.component.js.map +1 -1
  7. package/cards/box/box.component.js +2 -2
  8. package/cards/box/box.component.js.map +1 -1
  9. package/cards/box/box.types.d.ts +0 -8
  10. package/cards/box/box.types.js.map +1 -1
  11. package/cards/button/button.types.d.ts +4 -0
  12. package/cards/button/button.types.js +2 -2
  13. package/cards/button/button.types.js.map +1 -1
  14. package/cards/button/index.js +5 -5
  15. package/cards/chart/chart.component.d.ts +4 -0
  16. package/cards/chart/chart.types.d.ts +223 -0
  17. package/cards/chart/index.d.ts +1 -0
  18. package/cards/checkbox/checkbox.component.js +1 -0
  19. package/cards/checkbox/checkbox.component.js.map +1 -1
  20. package/cards/checkbox/checkbox.types.d.ts +4 -0
  21. package/cards/checkbox/checkbox.types.js +2 -2
  22. package/cards/checkbox/checkbox.types.js.map +1 -1
  23. package/cards/checkbox/index.js +5 -5
  24. package/cards/conditional/conditional.component.d.ts +14 -3
  25. package/cards/conditional/conditional.component.js +17 -9
  26. package/cards/conditional/conditional.component.js.map +1 -1
  27. package/cards/conditional/conditional.types.d.ts +115 -8
  28. package/cards/conditional/conditional.types.js.map +1 -1
  29. package/cards/core-index.d.ts +3 -0
  30. package/cards/core-index.js +38 -31
  31. package/cards/dataTable/dataTable.types.js.map +1 -1
  32. package/cards/dataTable/dataTableRowDetail.component.js +1 -0
  33. package/cards/dataTable/dataTableRowDetail.component.js.map +1 -1
  34. package/cards/field/field.types.js.map +1 -1
  35. package/cards/fileDrop/fileDrop.component.js +90 -0
  36. package/cards/fileDrop/fileDrop.component.js.map +1 -0
  37. package/cards/fileDrop/fileDrop.types.js +11 -0
  38. package/cards/fileDrop/fileDrop.types.js.map +1 -0
  39. package/cards/fileDrop/index.js +13 -0
  40. package/cards/fileDrop/index.js.map +1 -0
  41. package/cards/flexGrid/flexGrid.types.js.map +1 -1
  42. package/cards/form/form.types.d.ts +4 -0
  43. package/cards/form/form.types.js +2 -2
  44. package/cards/form/form.types.js.map +1 -1
  45. package/cards/form/index.js +5 -5
  46. package/cards/graphin/contextMenu.component.d.ts +28 -0
  47. package/cards/graphin/eventDispatcher.component.d.ts +8 -0
  48. package/cards/graphin/graphin.component.d.ts +2 -2
  49. package/cards/graphin/graphin.playground-cards.d.ts +1 -0
  50. package/cards/graphin/graphin.types.d.ts +477 -4
  51. package/cards/graphin/graphinOpHandler.component.d.ts +8 -0
  52. package/cards/graphin/index.d.ts +1 -0
  53. package/cards/graphin/tooltip.component.d.ts +13 -1
  54. package/cards/input/index.js +5 -5
  55. package/cards/input/input.component.js +1 -0
  56. package/cards/input/input.component.js.map +1 -1
  57. package/cards/input/input.types.d.ts +10 -2
  58. package/cards/input/input.types.js +2 -2
  59. package/cards/input/input.types.js.map +1 -1
  60. package/cards/list/list.types.js +1 -0
  61. package/cards/list/list.types.js.map +1 -1
  62. package/cards/pageWithNavbar/pageWithNavbar.component.d.ts +5 -7
  63. package/cards/pageWithNavbar/pageWithNavbar.component.js +1 -1
  64. package/cards/pageWithNavbar/pageWithNavbar.component.js.map +1 -1
  65. package/cards/pasteTarget/pasteTarget.component.js.map +1 -1
  66. package/cards/select/index.js +5 -5
  67. package/cards/select/select.component.js +1 -0
  68. package/cards/select/select.component.js.map +1 -1
  69. package/cards/select/select.types.d.ts +12 -0
  70. package/cards/select/select.types.js +2 -2
  71. package/cards/select/select.types.js.map +1 -1
  72. package/cards/slider/index.d.ts +1 -0
  73. package/cards/slider/index.js +13 -0
  74. package/cards/slider/index.js.map +1 -0
  75. package/cards/slider/slider.component.d.ts +4 -0
  76. package/cards/slider/slider.component.js +64 -0
  77. package/cards/slider/slider.component.js.map +1 -0
  78. package/cards/slider/slider.types.d.ts +110 -0
  79. package/cards/slider/slider.types.js +7 -0
  80. package/cards/slider/slider.types.js.map +1 -0
  81. package/cards/sliderValue/index.d.ts +1 -0
  82. package/cards/sliderValue/index.js +12 -0
  83. package/cards/sliderValue/index.js.map +1 -0
  84. package/cards/sliderValue/sliderValue.component.d.ts +15 -0
  85. package/cards/sliderValue/sliderValue.component.js +33 -0
  86. package/cards/sliderValue/sliderValue.component.js.map +1 -0
  87. package/cards/sliderValue/sliderValue.types.d.ts +21 -0
  88. package/cards/sliderValue/sliderValue.types.js +7 -0
  89. package/cards/sliderValue/sliderValue.types.js.map +1 -0
  90. package/cards/stack/stack.component.js +1 -1
  91. package/cards/stack/stack.component.js.map +1 -1
  92. package/cards/stack/stack.types.js.map +1 -1
  93. package/cards/switch/index.js +5 -5
  94. package/cards/switch/switch.component.js +1 -0
  95. package/cards/switch/switch.component.js.map +1 -1
  96. package/cards/switch/switch.types.d.ts +4 -0
  97. package/cards/switch/switch.types.js +2 -2
  98. package/cards/switch/switch.types.js.map +1 -1
  99. package/cards/tabs/tabs.component.js +51 -25
  100. package/cards/tabs/tabs.component.js.map +1 -1
  101. package/cards/tabs/tabs.types.d.ts +10 -0
  102. package/cards/tabs/tabs.types.js.map +1 -1
  103. package/cards/textField/index.js +5 -5
  104. package/cards/textField/textField.component.js +1 -0
  105. package/cards/textField/textField.component.js.map +1 -1
  106. package/cards/textField/textField.types.d.ts +4 -0
  107. package/cards/textField/textField.types.js +2 -2
  108. package/cards/textField/textField.types.js.map +1 -1
  109. package/cards/toast/index.js +7 -7
  110. package/cards/toast/toast.component.js.map +1 -1
  111. package/cards/toast/toast.types.d.ts +4 -0
  112. package/cards/toast/toast.types.js +2 -2
  113. package/cards/toast/toast.types.js.map +1 -1
  114. package/cards/toggleGroup/index.js +5 -5
  115. package/cards/toggleGroup/toggleGroup.component.js +1 -0
  116. package/cards/toggleGroup/toggleGroup.component.js.map +1 -1
  117. package/cards/toggleGroup/toggleGroup.types.d.ts +4 -0
  118. package/cards/toggleGroup/toggleGroup.types.js +2 -2
  119. package/cards/toggleGroup/toggleGroup.types.js.map +1 -1
  120. package/cards/typography/typography.types.js +1 -0
  121. package/cards/typography/typography.types.js.map +1 -1
  122. package/components/hooks/use-breakpoint.d.ts +49 -0
  123. package/components/hooks/use-breakpoint.js +73 -0
  124. package/components/hooks/use-breakpoint.js.map +1 -0
  125. package/components/ui/slider.js +36 -0
  126. package/components/ui/slider.js.map +1 -0
  127. package/components/ui/toggle-group.js +1 -0
  128. package/components/ui/toggle-group.js.map +1 -1
  129. package/package.json +19 -2
  130. package/pihanga-shadcn.css +1 -1
@@ -4,6 +4,10 @@
4
4
  > Read [`AGENT.md`](./AGENT.md) first for orientation and universal rules.
5
5
  > If you need to *create* a new card type, switch to
6
6
  > [`AGENT.building-cards.md`](./AGENT.building-cards.md).
7
+ >
8
+ > **Starting from scratch?** Follow [`AGENTS.getting-started.md`](./AGENTS.getting-started.md)
9
+ > first to scaffold your Vite project, run `shadcn init`, install `@pihanga2/core`,
10
+ > and wire up the initial file layout. Return here once the scaffold is in place.
7
11
 
8
12
  > 💬 **Encountered a bug, a missing card, or an agent-unfriendly doc section?**
9
13
  > Please open an issue at **https://github.com/ivcap-works/pihanga-shadcn/issues**
@@ -26,9 +30,16 @@
26
30
  > shadcn/ui and Radix UI updates, it won't appear in the playground
27
31
  > automatically, and it won't benefit from upstream bug fixes.
28
32
  >
29
- > **If no suitable card exists:**
30
- > - Confirm the need is genuine and not already covered by composing existing
31
- > cards (`Conditional`, `FlexGrid`, `Stack`, `Box`).
33
+ > **⭐ If no single card covers your need but existing cards could be combined:**
34
+ > Build a **meta card** a TypeScript-only mapper that assembles existing cards
35
+ > into a reusable, self-contained widget. Meta cards require no JSX, no React
36
+ > imports, and no DOM knowledge. They are easier to maintain, extend, and test
37
+ > than a bespoke React component. See
38
+ > [Meta cards — building complex UIs by composition](#meta-cards--building-complex-uis-by-composition)
39
+ > below, or the full guide in
40
+ > [`AGENT.building-cards.md`](./AGENT.building-cards.md#meta-cards--composing-new-widgets-from-existing-cards).
41
+ >
42
+ > **If no suitable card or card combination exists:**
32
43
  > - Unless the card would expose confidential business logic, please
33
44
  > **open an issue** at
34
45
  > `https://github.com/ivcap-works/pihanga-shadcn/issues` describing what you
@@ -41,12 +52,10 @@
41
52
  ## Table of Contents
42
53
 
43
54
  - [Distribution channels — choose one](#distribution-channels--choose-one)
44
- - [Channel 1 — shadcn registry prerequisites](#channel-1--shadcn-registry-prerequisites)
55
+ - [Channel 1 — shadcn registry (one-time project setup)](#channel-1--shadcn-registry-one-time-project-setup)
45
56
  - [Channel 2 — npm package `@pihanga2/shadcn`](#channel-2--npm-package-pihanga2shadcn)
46
57
  - [Migrating a card from npm to a local copy](#migrating-a-card-from-npm-to-a-local-customised-copy)
47
58
  - [Vite configuration (both channels)](#vite-configuration-both-channels)
48
- - [Required Vite aliases](#required-vite-aliases)
49
- - [Required `src/components/lib/utils.ts`](#required-srccomponentslibutils-ts)
50
59
  - [`@pihanga2/cards` — deprecated, do not use](#pihanga2cards--deprecated-do-not-use)
51
60
  - [Type-only import gotcha](#type-only-import-gotcha--picardref-store-etc)
52
61
  - [Transitive card dependencies](#transitive-card-dependencies)
@@ -69,7 +78,7 @@
69
78
 
70
79
  | | Registry | npm package |
71
80
  |---|---|---|
72
- | **Install** | `npx shadcn@latest add <url>` | `npm install @pihanga2/shadcn` |
81
+ | **Install** | `npx shadcn@latest add <url>` (or `yarn dlx shadcn@latest add <url>`) | `npm install @pihanga2/shadcn` |
73
82
  | **Cards available** | All 34 | 30 core (no graphin / jsonViewer / markdownViewer / resizable) |
74
83
  | **Requires `shadcn init`** | Yes | No |
75
84
  | **Files land in your project** | Yes — editable source | No — compiled bundle |
@@ -81,192 +90,23 @@ a clean `npm install` workflow is preferred.
81
90
 
82
91
  ---
83
92
 
84
- ## Channel 1 — shadcn registry prerequisites
85
-
86
- ### 1 — Initialise shadcn (creates `components.json` and `@/` alias)
87
-
88
- ```sh
89
- npx shadcn@latest init
90
- ```
91
-
92
- When prompted, choose:
93
- - **Style**: New York
94
- - **Base colour**: Neutral
95
- - **CSS variables**: Yes
93
+ ## Channel 1 — shadcn registry (one-time project setup)
96
94
 
97
- This command creates `components.json`, patches `tsconfig.json` with the `@/`
98
- path alias, and installs Tailwind CSS if not already present.
95
+ > **New project?** The full one-time setup (Vite scaffold, shadcn init, Tailwind
96
+ > theme, Vite aliases, pihanga-core install) is documented step-by-step in
97
+ > **[`AGENTS.getting-started.md`](./AGENTS.getting-started.md)**. Follow that
98
+ > guide first, then return here to install and wire individual cards.
99
99
 
100
- ### 2 Ensure `@/cards` alias is configured
101
-
102
- Pihanga cards are copied to `src/cards/` and import each other via the
103
- `@/cards/` alias. After `shadcn init`, add this alias to `tsconfig.json`:
104
-
105
- ```jsonc
106
- // tsconfig.json → compilerOptions.paths
107
- {
108
- "compilerOptions": {
109
- "paths": {
110
- "@/*": ["./src/*"]
111
- }
112
- }
113
- }
114
- ```
115
-
116
- The `@/*` → `./src/*` mapping (which `shadcn init` creates) already covers
117
- `@/cards/` → `src/cards/`, so **no extra alias is needed** as long as cards
118
- are placed at `src/cards/`.
119
-
120
- If cards end up elsewhere, add an explicit alias:
121
- ```jsonc
122
- "@/cards/*": ["./src/cards/*"]
123
- ```
100
+ Key things the setup guide covers:
124
101
 
125
- ### 3Configure `src/index.css` (Tailwind v4 + shadcn theme)
126
-
127
- > **⚠️ This is a Tailwind CSS project.** `index.html` must NOT contain any
128
- > `<link rel="stylesheet">` tags for external CSS frameworks (Bootstrap, Bulma,
129
- > etc.) or manual font CDN links, and no `<style>` blocks. Tailwind generates
130
- > all styles at build time from utility classes in your source files. Adding
131
- > foreign stylesheets will conflict with Tailwind's generated output and break
132
- > the shadcn colour variables.
133
-
134
- Tailwind v4 no longer auto-discovers shadcn's semantic CSS variables. Without
135
- an explicit `@theme inline` block, classes like `bg-card`, `bg-background`, and
136
- `border-border` have no associated colour and render as **transparent** — causing
137
- dialog panels, popovers, and cards to appear invisible.
138
-
139
- In addition, Radix UI overlays (Dialog, Sheet, etc.) apply `overflow: hidden` to
140
- `<body>` when open, which removes the scrollbar and widens the content area by
141
- ~15 px, causing **visible text reflow** behind the dialog backdrop.
142
-
143
- The complete reference `src/index.css` is maintained in the pihanga-shadcn
144
- repository. **Copy it directly** from:
145
- ```
146
- https://raw.githubusercontent.com/ivcap-works/pihanga-shadcn/main/src/index.css
147
- ```
148
- or from `src/index.css` in a local clone. The full content is reproduced below
149
- for reference / offline use:
150
-
151
- The required `src/index.css`:
152
-
153
- ```css
154
- @import "tailwindcss";
155
-
156
- /*
157
- * Tailwind v4 — map shadcn semantic CSS variables to Tailwind colour utilities.
158
- * Without this @theme block, classes like bg-card / bg-background / border-border
159
- * have no associated colour and render as transparent. This means dialog panels,
160
- * cards, popovers, etc. will appear invisible or incorrectly coloured.
161
- */
162
- @theme inline {
163
- /*
164
- * Brand button tokens — override these in your app to retheme variant="brand".
165
- * Defaults to the primary colour family. See the pi/button section below.
166
- */
167
- --color-btn-brand: var(--primary);
168
- --color-btn-brand-foreground: var(--primary-foreground);
169
- --radius-btn-brand: var(--radius-md);
170
-
171
- --color-background: var(--background);
172
- --color-foreground: var(--foreground);
173
- --color-card: var(--card);
174
- --color-card-foreground: var(--card-foreground);
175
- --color-popover: var(--popover);
176
- --color-popover-foreground: var(--popover-foreground);
177
- --color-primary: var(--primary);
178
- --color-primary-foreground: var(--primary-foreground);
179
- --color-secondary: var(--secondary);
180
- --color-secondary-foreground: var(--secondary-foreground);
181
- --color-muted: var(--muted);
182
- --color-muted-foreground: var(--muted-foreground);
183
- --color-accent: var(--accent);
184
- --color-accent-foreground: var(--accent-foreground);
185
- --color-destructive: var(--destructive);
186
- --color-border: var(--border);
187
- --color-input: var(--input);
188
- --color-ring: var(--ring);
189
- --radius-sm: calc(var(--radius) - 4px);
190
- --radius-md: calc(var(--radius) - 2px);
191
- --radius-lg: var(--radius);
192
- --radius-xl: calc(var(--radius) + 4px);
193
- }
194
-
195
- /* ── Light theme (shadcn neutral / new-york) ─────────────────────────────── */
196
- :root {
197
- --background: oklch(1 0 0);
198
- --foreground: oklch(0.145 0 0);
199
- --card: oklch(1 0 0);
200
- --card-foreground: oklch(0.145 0 0);
201
- --popover: oklch(1 0 0);
202
- --popover-foreground: oklch(0.145 0 0);
203
- --primary: oklch(0.205 0 0);
204
- --primary-foreground: oklch(0.985 0 0);
205
- --secondary: oklch(0.97 0 0);
206
- --secondary-foreground: oklch(0.205 0 0);
207
- --muted: oklch(0.97 0 0);
208
- --muted-foreground: oklch(0.556 0 0);
209
- --accent: oklch(0.97 0 0);
210
- --accent-foreground: oklch(0.205 0 0);
211
- --destructive: oklch(0.577 0.245 27.325);
212
- --border: oklch(0.922 0 0);
213
- --input: oklch(0.922 0 0);
214
- --ring: oklch(0.708 0 0);
215
- --radius: 0.625rem;
216
- }
217
-
218
- /* ── Dark theme ──────────────────────────────────────────────────────────── */
219
- .dark {
220
- --background: oklch(0.145 0 0);
221
- --foreground: oklch(0.985 0 0);
222
- --card: oklch(0.205 0 0);
223
- --card-foreground: oklch(0.985 0 0);
224
- --popover: oklch(0.205 0 0);
225
- --popover-foreground: oklch(0.985 0 0);
226
- --primary: oklch(0.922 0 0);
227
- --primary-foreground: oklch(0.205 0 0);
228
- --secondary: oklch(0.269 0 0);
229
- --secondary-foreground: oklch(0.985 0 0);
230
- --muted: oklch(0.269 0 0);
231
- --muted-foreground: oklch(0.708 0 0);
232
- --accent: oklch(0.269 0 0);
233
- --accent-foreground: oklch(0.985 0 0);
234
- --destructive: oklch(0.704 0.191 22.216);
235
- --border: oklch(1 0 0 / 10%);
236
- --input: oklch(1 0 0 / 15%);
237
- --ring: oklch(0.556 0 0);
238
- }
239
-
240
- @layer base {
241
- * {
242
- @apply border-border outline-ring/50;
243
- }
244
-
245
- body {
246
- @apply bg-background text-foreground;
247
- /*
248
- * Prevent layout reflow when a dialog (or any Radix overlay) applies
249
- * `overflow: hidden` to <body> to disable background scrolling.
250
- * Without this, removing the scrollbar widens the content area by ~15 px
251
- * and causes visible text reflow behind the dialog backdrop.
252
- */
253
- scrollbar-gutter: stable;
254
- }
255
- }
256
- ```
257
-
258
- > **Why `@theme inline`?** Tailwind v4 separates design tokens from utility
259
- > generation. shadcn stores its colours as CSS custom properties (`--card`,
260
- > `--background`, …) but Tailwind v4 will not generate colour utilities from
261
- > raw CSS variables unless they are declared inside an `@theme` block. Without
262
- > it the generated CSS contains no colour definitions for those utility classes.
263
-
264
- > **Why `scrollbar-gutter: stable`?** When a Radix dialog opens, the library
265
- > `@radix-ui/react-remove-scroll` sets `overflow: hidden` on `<body>` to
266
- > prevent background scrolling. This hides the scrollbar and adds ~15 px of
267
- > width back to the page — causing text to reflow. `scrollbar-gutter: stable`
268
- > reserves a permanent gutter for the scrollbar so its appearance/disappearance
269
- > never changes the usable width.
102
+ - **⚠️ npx + npm 11 + Node 24 incompatibility** use `nvm use 22` or `yarn dlx`
103
+ as a drop-in (see getting-started § *npx compatibility*)
104
+ - `npx shadcn@latest init` / `yarn dlx shadcn@latest init` creates
105
+ `components.json`, patches `tsconfig.json` with `@/*` alias, installs Tailwind
106
+ - `src/index.css` requires a full `@theme inline` block; without it `bg-card`,
107
+ `bg-background` etc. render transparent and dialogs appear invisible
108
+ - `src/components/lib/utils.ts` must create the `cn()` helper at this path
109
+ - `vite.config.ts` aliases `@/lib`, `@/registry`, `@/components`, `@/cards`, `@`
270
110
 
271
111
  ---
272
112
 
@@ -364,62 +204,10 @@ import-order dependency.
364
204
 
365
205
  ## Vite configuration (both channels)
366
206
 
367
- When building a **Vite + React + TypeScript** app from scratch (i.e. without
368
- using `shadcn init` or copying the playground project), the following setup is
369
- required regardless of whether you use the registry or the npm channel.
370
-
371
- ### Required Vite aliases
372
-
373
- pihanga-shadcn cards reference each other and shadcn UI primitives via these
374
- path aliases. Without the `@/registry` alias in particular, `button.component.tsx`
375
- (and other cards) will fail at Vite dev time with a cryptic
376
- `"Failed to resolve import '@/registry/ui/button'"` error.
377
-
378
- ```ts
379
- // vite.config.ts — required for both channels
380
- import path from "path";
381
- import tailwindcss from "@tailwindcss/vite";
382
- import react from "@vitejs/plugin-react";
383
- import {defineConfig} from "vite";
384
-
385
- export default defineConfig({
386
- plugins: [react(), tailwindcss()],
387
- resolve: {
388
- alias: [
389
- // @/lib → src/lib (shared utilities used by cards)
390
- {find: "@/lib", replacement: path.resolve(__dirname, "./src/lib")},
391
- // @/registry → src/components (shadcn UI primitives — cards import via
392
- // "@/registry/ui/button" etc.; this alias bridges them to the local copies)
393
- {find: "@/registry", replacement: path.resolve(__dirname, "./src/components")},
394
- // @/components → src/components (needed for cross-component imports)
395
- {find: "@/components", replacement: path.resolve(__dirname, "./src/components")},
396
- // @/cards → src/cards (explicit card-to-card imports)
397
- {find: "@/cards", replacement: path.resolve(__dirname, "./src/cards")},
398
- // @ → src (catch-all for everything else)
399
- {find: "@", replacement: path.resolve(__dirname, "./src")},
400
- ],
401
- },
402
- });
403
- ```
404
-
405
- ### Required `src/components/lib/utils.ts`
406
-
407
- All shadcn UI components (`button.tsx`, `tooltip.tsx`, `sheet.tsx`, `badge.tsx`,
408
- etc.) import the `cn()` helper from `@/components/lib/utils` — **not** from
409
- `@/lib/utils`. Create this file:
410
-
411
- ```ts
412
- // src/components/lib/utils.ts
413
- import {clsx, type ClassValue} from "clsx";
414
- import {twMerge} from "tailwind-merge";
415
-
416
- export function cn(...inputs: ClassValue[]): string {
417
- return twMerge(clsx(inputs));
418
- }
419
- ```
420
-
421
- Note that `@/lib/utils.ts` can also exist for app-level utilities; they are two
422
- separate files at two separate paths.
207
+ > **Vite project setup** (aliases, `src/components/lib/utils.ts`, `src/index.css`)
208
+ > is documented in full in **[`AGENTS.getting-started.md`](./AGENTS.getting-started.md)
209
+ > Step 5 & Step 2**. The sub-sections below cover **runtime-only gotchas** that
210
+ > apply regardless of when the project was scaffolded.
423
211
 
424
212
  ### `@pihanga2/cards` — deprecated, do not use
425
213
 
@@ -502,15 +290,28 @@ After the one-time setup (Channel 1 prerequisites above), add any card with a
502
290
  single command. `@pihanga2/core` and all card-specific npm packages are
503
291
  installed automatically.
504
292
 
293
+ > ⚠️ **npm 11 + Node 24:** `npx` fails on this combination — use Node 22 via
294
+ > `nvm use 22`, or use `yarn dlx` instead (see the
295
+ > [compatibility note above](#channel-1--shadcn-registry-prerequisites)).
296
+
505
297
  ```sh
506
- # Add a single card
298
+ # npm / npx (Node 22 recommended)
507
299
  npx shadcn@latest add https://ivcap-works.github.io/pihanga-shadcn/r/button.json
508
300
 
509
- # Add multiple cards at once
301
+ # yarn (works on all supported Node versions)
302
+ yarn dlx shadcn@latest add https://ivcap-works.github.io/pihanga-shadcn/r/button.json
303
+
304
+ # Add multiple cards at once (npx)
510
305
  npx shadcn@latest add \
511
306
  https://ivcap-works.github.io/pihanga-shadcn/r/button.json \
512
307
  https://ivcap-works.github.io/pihanga-shadcn/r/form.json \
513
- https://ivcap-works.github.io/pihanga-shadcn/r/dataTa.jsonle
308
+ https://ivcap-works.github.io/pihanga-shadcn/r/dataTable.json
309
+
310
+ # Add multiple cards at once (yarn dlx)
311
+ yarn dlx shadcn@latest add \
312
+ https://ivcap-works.github.io/pihanga-shadcn/r/button.json \
313
+ https://ivcap-works.github.io/pihanga-shadcn/r/form.json \
314
+ https://ivcap-works.github.io/pihanga-shadcn/r/dataTable.json
514
315
  ```
515
316
 
516
317
  ### npm channel
@@ -570,6 +371,8 @@ Full registry index: `https://ivcap-works.github.io/pihanga-shadcn/r/registry.js
570
371
  **Registry channel:**
571
372
  - `npx shadcn@latest add <url>` automatically installs `@pihanga2/core` and all
572
373
  card-specific npm packages — no separate `npm install` needed.
374
+ - **`npx` fails on npm 11 + Node 24** — use `nvm use 22` or replace every
375
+ `npx shadcn@latest` with `yarn dlx shadcn@latest` (identical output).
573
376
  - Cards land at `src/cards/<card-name>/` in the consumer's project.
574
377
  - The `framework` card is the Pihanga app root — add it first for new apps.
575
378
  - `graphin` has heavy AntV dependencies (~5 MB) — only add if graph
@@ -628,6 +431,137 @@ registerCard("myApp/save", Button({
628
431
 
629
432
  ---
630
433
 
434
+ ## Meta cards — building complex UIs by composition
435
+
436
+ > **⭐ This is the recommended approach whenever you need a reusable UI widget
437
+ > that combines several existing cards.** Prefer a meta card over writing a new
438
+ > React component; meta cards are easier to maintain, extend, test, and port.
439
+
440
+ A **meta card** is a TypeScript-only module that assembles existing primitive
441
+ cards (or other meta cards) inside a mapper function. No JSX, no React hooks,
442
+ no DOM knowledge is required.
443
+
444
+ ### Decision guide
445
+
446
+ ```
447
+ Do I need a complex, multi-widget UI?
448
+
449
+ ├─► Can I build it from existing cards? ──► YES ──► Write a META CARD ⭐
450
+ │ (registerMetaCard)
451
+ └─► NO — needs a DOM API / third-party React hook
452
+ └─► Only then: write a PRIMITIVE CARD
453
+ (registerCardComponent + React component)
454
+ ```
455
+
456
+ ### Minimal meta card skeleton
457
+
458
+ ```ts
459
+ // src/myWidget.card.ts
460
+ import {
461
+ createCardDeclaration, createOnAction, registerActions, registerMetaCard,
462
+ } from "@pihanga2/core";
463
+ import type {PiCardDef, PiMapProps, PiRegisterMetaCard, ReduxState, RegisterCardF} from "@pihanga2/core";
464
+ import {Stack, Button, Typography} from "@pihanga2/shadcn"; // use whatever cards you need
465
+
466
+ // ── 1. Identity (use "meta/<name>" convention for app-local meta cards) ─────
467
+ const MY_WIDGET_CARD = "meta/my-widget";
468
+
469
+ // ── 2. Public factory ────────────────────────────────────────────────────────
470
+ export const MyWidget = createCardDeclaration<MyWidgetProps, MyWidgetEvents>(MY_WIDGET_CARD);
471
+
472
+ // ── 3. Actions ───────────────────────────────────────────────────────────────
473
+ export const MY_WIDGET_ACTION = registerActions(MY_WIDGET_CARD, ["submitted"]);
474
+ export const onMyWidgetSubmitted = createOnAction<MyWidgetSubmitEvent>(MY_WIDGET_ACTION.SUBMITTED);
475
+
476
+ // ── 4. Types ─────────────────────────────────────────────────────────────────
477
+ type MyWidgetProps = { label: string; value: string };
478
+ type MyWidgetSubmitEvent = { value: string };
479
+ type MyWidgetEvents = { onSubmit: MyWidgetSubmitEvent };
480
+ type MapperProps = MyWidgetProps & MyWidgetEvents;
481
+
482
+ // ── 5. Mapper ────────────────────────────────────────────────────────────────
483
+ function MyWidgetMapper(
484
+ _: string,
485
+ props: PiMapProps<MapperProps, ReduxState, object>,
486
+ _registerCard: RegisterCardF,
487
+ ): PiCardDef {
488
+ return Stack({
489
+ direction: "row",
490
+ content: [
491
+ Typography({ text: (_, {resolve}) => resolve(props.label) }),
492
+ Button({
493
+ label: "Submit",
494
+ onClickedMapper: (_, {resolve}) => ({
495
+ type: MY_WIDGET_ACTION.SUBMITTED,
496
+ value: resolve(props.value),
497
+ }),
498
+ }),
499
+ ],
500
+ });
501
+ }
502
+
503
+ // ── 6. Register ───────────────────────────────────────────────────────────────
504
+ registerMetaCard({
505
+ type: MY_WIDGET_CARD,
506
+ mapper: MyWidgetMapper,
507
+ events: MY_WIDGET_ACTION,
508
+ } satisfies PiRegisterMetaCard);
509
+ ```
510
+
511
+ **Using the meta card in your app:**
512
+
513
+ ```ts
514
+ // src/app.pihanga.ts
515
+ import {MyWidget, onMyWidgetSubmitted} from "./myWidget.card";
516
+ import type {AppState} from "./app.state";
517
+
518
+ register((r) => {
519
+ onMyWidgetSubmitted<AppState>(r, (state, {value}) => {
520
+ state.submittedValue = value;
521
+ });
522
+ });
523
+
524
+ registerCard("app/myWidget", MyWidget<AppState>({
525
+ label: "Enter name",
526
+ value: (s) => s.currentValue, // reactive — updates when state changes
527
+ }));
528
+ ```
529
+
530
+ ### Key patterns
531
+
532
+ **`resolve(props.foo)` — unwrap lazy state selectors in child props**
533
+
534
+ A meta card prop may be a plain value *or* a state selector `(s) => s.foo`.
535
+ Inside child card prop functions, always use `resolve()` to unwrap it:
536
+
537
+ ```ts
538
+ // ✅ Correct
539
+ Typography({ text: (_, {resolve}) => `Hello ${resolve(props.name)}` })
540
+
541
+ // ❌ Wrong — child sees a function reference, not the resolved string
542
+ Typography({ text: props.name })
543
+ ```
544
+
545
+ **`onXxxMapper` — remap child events into domain actions**
546
+
547
+ Every event-emitting card supports an `on<Event>Mapper` prop that intercepts
548
+ the raw event and emits a different action (or `null` to suppress):
549
+
550
+ ```ts
551
+ Button({
552
+ label: "Delete",
553
+ onClickedMapper: (_, {resolve}) => ({
554
+ type: MY_WIDGET_ACTION.SUBMITTED,
555
+ value: resolve(props.value),
556
+ }),
557
+ })
558
+ ```
559
+
560
+ **Full reference:** See [`AGENT.building-cards.md`](./AGENT.building-cards.md#meta-cards--composing-new-widgets-from-existing-cards)
561
+ and the complete annotated example at [`example/src/counter.card.ts`](./example/src/counter.card.ts).
562
+
563
+ ---
564
+
631
565
  ## Version pinning
632
566
 
633
567
  Use a git tag in the URL to pin to a specific release:
@@ -1196,7 +1130,7 @@ project that was bootstrapped without the reference `index.css`:
1196
1130
  Both fixes are now included in the reference `src/index.css` template in
1197
1131
  *Prerequisites step 3*.
1198
1132
 
1199
- ### 2026-06 agent evaluation — ViteJS app from scratch (BuhlOS-2)
1133
+ ### 2026-06 agent evaluation — ViteJS app from scratch
1200
1134
 
1201
1135
  An agent built a new ViteJS + React + TypeScript app from scratch using
1202
1136
  `yarn create vite` and then manually copied pihanga-shadcn cards. The
@@ -1240,3 +1174,16 @@ local modifications to the registry code for features that already existed.
1240
1174
  | `shad/list` icon decorators silently rendered nothing when icon names were unregistered | The `shad/list` card calls `getIcon(name)` which requires icons to be pre-registered via `registerIcon()` in `src/cards/icons.ts`; this contract is not visible in the type declarations | Added *`shad/list` — icon decorators require registered icons* to *Card API quick reference* |
1241
1175
  | `flexGrid.component.tsx` failed to compile under `verbatimModuleSyntax` / `noImplicitAny` strict TypeScript | Registry source mixed value and type imports; had implicit `any` in `.map()` callback; `Object.entries` lacked an explicit cast; `_style` lacked widened type for `gridTemplateAreas` | Fixed directly in `flexGrid.component.tsx`: split `import type`, added explicit `row: string[]` annotation, added `as [string, PiCardRef][]` cast, widened `_style` type |
1242
1176
  | `stack.component.tsx` contained commented-out Joy UI dead code | Leftover from a previous MUI Joy UI implementation; the current Tailwind implementation is complete and the comment block serves no purpose | Removed the dead code block |
1177
+
1178
+ ### 2026-06 user feedback — `npx shadcn@latest add` fails on npm 11 + Node 24
1179
+
1180
+ Users reported that every `npx shadcn@latest` command failed with
1181
+ `npm error could not determine executable to run` when running Node 24 (which
1182
+ bundles npm 11). The docs only showed `npx` examples with no mention of a
1183
+ yarn alternative or Node version constraint.
1184
+
1185
+ | Reported gap | Fix applied |
1186
+ |---|---|
1187
+ | No `yarn dlx` alternative documented | Added `yarn dlx shadcn@latest` as the yarn-compatible alternative in the distribution channels table, Channel 1 init step, and "Adding individual cards" commands |
1188
+ | No warning about npm 11 + Node 24 incompatibility | Added a prominent compatibility callout at the top of *Channel 1 — shadcn registry prerequisites*, with the `nvm use 22` workaround and the `yarn dlx` alternative |
1189
+ | "Notes for AI agents" section did not mention the `npx` breakage | Added a bullet noting that `npx` fails on npm 11 + Node 24 and that `yarn dlx shadcn@latest` is a drop-in replacement |
package/README.md CHANGED
@@ -73,7 +73,7 @@ import "@pihanga2/shadcn/cards/dataTable";
73
73
 
74
74
  ---
75
75
 
76
- ## Included cards (30)
76
+ ## Included cards (33)
77
77
 
78
78
  - `badge`
79
79
  - `box`
@@ -84,6 +84,7 @@ import "@pihanga2/shadcn/cards/dataTable";
84
84
  - `dialog`
85
85
  - `dropDownMenu`
86
86
  - `field`
87
+ - `fileDrop`
87
88
  - `flexGrid`
88
89
  - `form`
89
90
  - `framework`
@@ -97,6 +98,8 @@ import "@pihanga2/shadcn/cards/dataTable";
97
98
  - `pageWithNavbar`
98
99
  - `pasteTarget`
99
100
  - `select`
101
+ - `slider`
102
+ - `sliderValue`
100
103
  - `stack`
101
104
  - `stepper`
102
105
  - `switch`
@@ -1,5 +1,6 @@
1
1
  import { Badge as e } from "../../components/ui/badge.js";
2
2
  import { cn as t } from "../../lib/utils.js";
3
+ import "@pihanga2/core";
3
4
  import "react";
4
5
  import { jsx as n } from "react/jsx-runtime";
5
6
  //#region src/cards/badge/badge.component.tsx
@@ -1 +1 @@
1
- {"version":3,"file":"badge.component.js","names":[],"sources":["../../../src/cards/badge/badge.component.tsx"],"sourcesContent":["import * as React from \"react\";\nimport {type PiCardProps} from \"@pihanga2/core\";\nimport {Badge} from \"@/components/ui/badge\";\nimport {cn} from \"@/lib/utils\";\nimport type {BadgeCardProps} from \"./badge.types\";\n\n/**\n * `shad/badge` card component.\n *\n * Renders a shadcn `<Badge>` element with a `label` and an optional `variant`.\n * The variant vocabulary is intentionally identical to the `BadgeColumn.variants`\n * map used by the `shad/data-table` card, so both can be driven from the same\n * source-of-truth value:\n *\n * \"default\" | \"secondary\" | \"destructive\" | \"outline\"\n */\nexport const BadgeComponent = (\n props: PiCardProps<BadgeCardProps>,\n): React.ReactNode => {\n const {label, variant = \"secondary\", className, cardName} = props;\n\n return (\n <Badge\n variant={variant}\n className={cn(className)}\n data-pihanga={cardName}\n >\n {label}\n </Badge>\n );\n};\n"],"mappings":";;;;;AAgBA,IAAa,KACX,MACoB;CACpB,IAAM,EAAC,UAAO,aAAU,aAAa,cAAW,gBAAY;CAE5D,OACE,kBAAC,GAAD;EACW;EACT,WAAW,EAAG,CAAS;EACvB,gBAAc;YAEb;CACI,CAAA;AAEX"}
1
+ {"version":3,"file":"badge.component.js","names":[],"sources":["../../../src/cards/badge/badge.component.tsx"],"sourcesContent":["import * as React from \"react\";\nimport {type PiCardProps} from \"@pihanga2/core\";\nimport {Badge} from \"@/components/ui/badge\";\nimport {cn} from \"@/lib/utils\";\nimport type {BadgeCardProps} from \"./badge.types\";\n\n/**\n * `shad/badge` card component.\n *\n * Renders a shadcn `<Badge>` element with a `label` and an optional `variant`.\n * The variant vocabulary is intentionally identical to the `BadgeColumn.variants`\n * map used by the `shad/data-table` card, so both can be driven from the same\n * source-of-truth value:\n *\n * \"default\" | \"secondary\" | \"destructive\" | \"outline\"\n */\nexport const BadgeComponent = (\n props: PiCardProps<BadgeCardProps>,\n): React.ReactNode => {\n const {label, variant = \"secondary\", className, cardName} = props;\n\n return (\n <Badge\n variant={variant}\n className={cn(className)}\n data-pihanga={cardName}\n >\n {label}\n </Badge>\n );\n};\n"],"mappings":";;;;;;AAgBA,IAAa,KACX,MACoB;CACpB,IAAM,EAAC,UAAO,aAAU,aAAa,cAAW,gBAAY;CAE5D,OACE,kBAAC,GAAD;EACW;EACT,WAAW,EAAG,CAAS;EACvB,gBAAc;YAEb;CACI,CAAA;AAEX"}
@@ -3,8 +3,8 @@ import "react";
3
3
  import { jsx as t, jsxs as n } from "react/jsx-runtime";
4
4
  //#region src/cards/box/box.component.tsx
5
5
  var r = (r) => {
6
- let { content: i, className: a, style: o, cardName: s } = r, c = {};
7
- r.height && (c.height = `${r.height}px`), r.width && (c.height = `${r.width}px`), r.marginTop && (c["margin-top"] = `${r.marginTop}px`), r.marginBottom && (c["margin-bottom"] = `${r.marginBottom}px`), r.marginLeft && (c["margin-ledt"] = `${r.marginLeft}px`), r.marginRight && (c["margin-right"] = `${r.marginRight}px`), r.paddingTop && (c["padding-top"] = `${r.paddingTop}px`), r.paddingBottom && (c["padding-bottom"] = `${r.paddingBottom}px`), r.paddingLeft && (c["padding-ledt"] = `${r.paddingLeft}px`), r.paddingRight && (c["padding-right"] = `${r.paddingRight}px`), c = { ...o?.shad };
6
+ let { content: i, className: a, style: o, cardName: s } = r, c = { ...o };
7
+ r.height && (c.height = `${r.height}px`), r.width && (c.width = `${r.width}px`), r.marginTop && (c.marginTop = `${r.marginTop}px`), r.marginBottom && (c.marginBottom = `${r.marginBottom}px`), r.marginLeft && (c.marginLeft = `${r.marginLeft}px`), r.marginRight && (c.marginRight = `${r.marginRight}px`), r.paddingTop && (c.paddingTop = `${r.paddingTop}px`), r.paddingBottom && (c.paddingBottom = `${r.paddingBottom}px`), r.paddingLeft && (c.paddingLeft = `${r.paddingLeft}px`), r.paddingRight && (c.paddingRight = `${r.paddingRight}px`);
8
8
  function l() {
9
9
  return i ? i.map((n, r) => /* @__PURE__ */ t(e, {
10
10
  cardName: n,
@@ -1 +1 @@
1
- {"version":3,"file":"box.component.js","names":[],"sources":["../../../src/cards/box/box.component.tsx"],"sourcesContent":["import * as React from \"react\";\n\nimport {Card, type PiCardProps} from \"@pihanga2/core\";\nimport type {BoxProps} from \"./box.types\";\n\nexport const BoxComponent = (props: PiCardProps<BoxProps>): React.ReactNode => {\n const {content, className, style, cardName} = props;\n\n let sy: Record<string, string | number> = {};\n if (props.height) sy.height = `${props.height}px`;\n if (props.width) sy.height = `${props.width}px`;\n\n if (props.marginTop) sy[\"margin-top\"] = `${props.marginTop}px`;\n if (props.marginBottom) sy[\"margin-bottom\"] = `${props.marginBottom}px`;\n if (props.marginLeft) sy[\"margin-ledt\"] = `${props.marginLeft}px`;\n if (props.marginRight) sy[\"margin-right\"] = `${props.marginRight}px`;\n\n if (props.paddingTop) sy[\"padding-top\"] = `${props.paddingTop}px`;\n if (props.paddingBottom) sy[\"padding-bottom\"] = `${props.paddingBottom}px`;\n if (props.paddingLeft) sy[\"padding-ledt\"] = `${props.paddingLeft}px`;\n if (props.paddingRight) sy[\"padding-right\"] = `${props.paddingRight}px`;\n\n sy = {\n ...(style as {shad?: Record<string, string | number>} | undefined)?.shad,\n };\n\n function renderContent() {\n if (!content) return null;\n return content.map((cn, i) => (\n <Card cardName={cn} parentCard={cardName} key={i} />\n ));\n }\n\n return (\n <div className={className} style={sy} data-pihanga={cardName}>\n {renderContent()}\n {props.children}\n </div>\n );\n};\n"],"mappings":";;;;AAKA,IAAa,KAAgB,MAAkD;CAC7E,IAAM,EAAC,YAAS,cAAW,UAAO,gBAAY,GAE1C,IAAsC,CAAC;CAc3C,AAbI,EAAM,WAAQ,EAAG,SAAS,GAAG,EAAM,OAAO,MAC1C,EAAM,UAAO,EAAG,SAAS,GAAG,EAAM,MAAM,MAExC,EAAM,cAAW,EAAG,gBAAgB,GAAG,EAAM,UAAU,MACvD,EAAM,iBAAc,EAAG,mBAAmB,GAAG,EAAM,aAAa,MAChE,EAAM,eAAY,EAAG,iBAAiB,GAAG,EAAM,WAAW,MAC1D,EAAM,gBAAa,EAAG,kBAAkB,GAAG,EAAM,YAAY,MAE7D,EAAM,eAAY,EAAG,iBAAiB,GAAG,EAAM,WAAW,MAC1D,EAAM,kBAAe,EAAG,oBAAoB,GAAG,EAAM,cAAc,MACnE,EAAM,gBAAa,EAAG,kBAAkB,GAAG,EAAM,YAAY,MAC7D,EAAM,iBAAc,EAAG,mBAAmB,GAAG,EAAM,aAAa,MAEpE,IAAK,EACH,GAAI,GAAgE,KACtE;CAEA,SAAS,IAAgB;EAEvB,OADK,IACE,EAAQ,KAAK,GAAI,MACtB,kBAAC,GAAD;GAAM,UAAU;GAAI,YAAY;EAAmB,GAAJ,CAAI,CACpD,IAHoB;CAIvB;CAEA,OACE,kBAAC,OAAD;EAAgB;EAAW,OAAO;EAAI,gBAAc;YAApD,CACG,EAAc,GACd,EAAM,QACJ;;AAET"}
1
+ {"version":3,"file":"box.component.js","names":[],"sources":["../../../src/cards/box/box.component.tsx"],"sourcesContent":["import * as React from \"react\";\n\nimport {Card, type PiCardProps} from \"@pihanga2/core\";\nimport type {BoxProps} from \"./box.types\";\n\nexport const BoxComponent = (props: PiCardProps<BoxProps>): React.ReactNode => {\n const {content, className, style, cardName} = props;\n\n const sy: Record<string, string | number> = {\n ...(style as Record<string, string | number> | undefined),\n };\n if (props.height) sy.height = `${props.height}px`;\n if (props.width) sy.width = `${props.width}px`;\n\n if (props.marginTop) sy.marginTop = `${props.marginTop}px`;\n if (props.marginBottom) sy.marginBottom = `${props.marginBottom}px`;\n if (props.marginLeft) sy.marginLeft = `${props.marginLeft}px`;\n if (props.marginRight) sy.marginRight = `${props.marginRight}px`;\n\n if (props.paddingTop) sy.paddingTop = `${props.paddingTop}px`;\n if (props.paddingBottom) sy.paddingBottom = `${props.paddingBottom}px`;\n if (props.paddingLeft) sy.paddingLeft = `${props.paddingLeft}px`;\n if (props.paddingRight) sy.paddingRight = `${props.paddingRight}px`;\n\n function renderContent() {\n if (!content) return null;\n return content.map((cn, i) => (\n <Card cardName={cn} parentCard={cardName} key={i} />\n ));\n }\n\n return (\n <div className={className} style={sy} data-pihanga={cardName}>\n {renderContent()}\n {props.children}\n </div>\n );\n};\n"],"mappings":";;;;AAKA,IAAa,KAAgB,MAAkD;CAC7E,IAAM,EAAC,YAAS,cAAW,UAAO,gBAAY,GAExC,IAAsC,EAC1C,GAAI,EACN;CAYA,AAXI,EAAM,WAAQ,EAAG,SAAS,GAAG,EAAM,OAAO,MAC1C,EAAM,UAAO,EAAG,QAAQ,GAAG,EAAM,MAAM,MAEvC,EAAM,cAAW,EAAG,YAAY,GAAG,EAAM,UAAU,MACnD,EAAM,iBAAc,EAAG,eAAe,GAAG,EAAM,aAAa,MAC5D,EAAM,eAAY,EAAG,aAAa,GAAG,EAAM,WAAW,MACtD,EAAM,gBAAa,EAAG,cAAc,GAAG,EAAM,YAAY,MAEzD,EAAM,eAAY,EAAG,aAAa,GAAG,EAAM,WAAW,MACtD,EAAM,kBAAe,EAAG,gBAAgB,GAAG,EAAM,cAAc,MAC/D,EAAM,gBAAa,EAAG,cAAc,GAAG,EAAM,YAAY,MACzD,EAAM,iBAAc,EAAG,eAAe,GAAG,EAAM,aAAa;CAEhE,SAAS,IAAgB;EAEvB,OADK,IACE,EAAQ,KAAK,GAAI,MACtB,kBAAC,GAAD;GAAM,UAAU;GAAI,YAAY;EAAmB,GAAJ,CAAI,CACpD,IAHoB;CAIvB;CAEA,OACE,kBAAC,OAAD;EAAgB;EAAW,OAAO;EAAI,gBAAc;YAApD,CACG,EAAc,GACd,EAAM,QACJ;;AAET"}
@@ -1,5 +1,4 @@
1
1
  import { PiCardRef } from '@pihanga2/core';
2
- import { AlignItemsT } from '../types';
3
2
  export declare const BOX_CARD = "shad/box";
4
3
  /**
5
4
  * Responsive display grid breakpoints.
@@ -37,13 +36,6 @@ export type BoxProps<S = object> = {
37
36
  paddingBottom?: number;
38
37
  paddingLeft?: number;
39
38
  paddingRight?: number;
40
- alignItems?: AlignItemsT;
41
- /** Tailwind gap spacing units */
42
- gap?: number;
43
- /** Uniform padding in pixels */
44
- padding?: number;
45
- /** Responsive display grid breakpoints */
46
- display?: DisplayGridT;
47
39
  /** Card style object (use the `shad` key for Tailwind-compatible overrides) */
48
40
  style?: S;
49
41
  /** Additional Tailwind utility classes */
@@ -1 +1 @@
1
- {"version":3,"file":"box.types.js","names":[],"sources":["../../../src/cards/box/box.types.ts"],"sourcesContent":["import {type PiCardRef, createCardDeclaration} from \"@pihanga2/core\";\nimport { AlignItemsT } from \"../types\";\n\nexport const BOX_CARD = \"shad/box\";\n\n/**\n * Responsive display grid breakpoints.\n *\n * Each key maps to a CSS display value applied at that viewport width:\n * - `xs`: < 640 px (default / mobile-first)\n * - `sm`: ≥ 640 px\n * - `md`: ≥ 768 px\n * - `lg`: ≥ 1024 px\n * - `xl`: ≥ 1280 px\n * - `xxl`: ≥ 1536 px\n */\nexport type DisplayGridT = {\n xs?: string;\n sm?: string;\n md?: string;\n lg?: string;\n xl?: string;\n xxl?: string;\n};\n\nexport type BoxProps<S = object> = {\n /** Child card refs rendered inside the box */\n content?: PiCardRef[];\n\n /** Override the root element type */\n component?: React.ElementType;\n\n /** Fixed height in pixels */\n height?: number;\n /** Fixed width in pixels */\n width?: number;\n\n marginTop?: number;\n marginBottom?: number;\n marginLeft?: number;\n marginRight?: number;\n\n paddingTop?: number;\n paddingBottom?: number;\n paddingLeft?: number;\n paddingRight?: number;\n\n alignItems?: AlignItemsT;\n /** Tailwind gap spacing units */\n gap?: number;\n /** Uniform padding in pixels */\n padding?: number;\n /** Responsive display grid breakpoints */\n display?: DisplayGridT;\n\n /** Card style object (use the `shad` key for Tailwind-compatible overrides) */\n style?: S;\n /** Additional Tailwind utility classes */\n className?: string;\n};\n\n/**\n * Factory function for declaring a `shad/box` card instance.\n *\n * ```ts\n * import {registerCard} from \"@pihanga2/core\";\n * import {Box} from \"@/cards/box\";\n *\n * registerCard(\"myApp/spacer\", Box({height: 24}));\n *\n * registerCard(\"myApp/contentRegion\", Box({\n * content: [\"myApp/card1\", \"myApp/card2\"],\n * paddingTop: 16,\n * className: \"rounded-lg border bg-card\",\n * }));\n * ```\n */\nexport const Box = createCardDeclaration<BoxProps>(BOX_CARD);\n"],"mappings":";;AAGA,IAAa,IAAW,YA0EX,IAAM,EAAgC,CAAQ"}
1
+ {"version":3,"file":"box.types.js","names":[],"sources":["../../../src/cards/box/box.types.ts"],"sourcesContent":["import {type PiCardRef, createCardDeclaration} from \"@pihanga2/core\";\n\nexport const BOX_CARD = \"shad/box\";\n\n/**\n * Responsive display grid breakpoints.\n *\n * Each key maps to a CSS display value applied at that viewport width:\n * - `xs`: < 640 px (default / mobile-first)\n * - `sm`: ≥ 640 px\n * - `md`: ≥ 768 px\n * - `lg`: ≥ 1024 px\n * - `xl`: ≥ 1280 px\n * - `xxl`: ≥ 1536 px\n */\nexport type DisplayGridT = {\n xs?: string;\n sm?: string;\n md?: string;\n lg?: string;\n xl?: string;\n xxl?: string;\n};\n\nexport type BoxProps<S = object> = {\n /** Child card refs rendered inside the box */\n content?: PiCardRef[];\n\n /** Override the root element type */\n component?: React.ElementType;\n\n /** Fixed height in pixels */\n height?: number;\n /** Fixed width in pixels */\n width?: number;\n\n marginTop?: number;\n marginBottom?: number;\n marginLeft?: number;\n marginRight?: number;\n\n paddingTop?: number;\n paddingBottom?: number;\n paddingLeft?: number;\n paddingRight?: number;\n\n /** Card style object (use the `shad` key for Tailwind-compatible overrides) */\n style?: S;\n /** Additional Tailwind utility classes */\n className?: string;\n};\n\n/**\n * Factory function for declaring a `shad/box` card instance.\n *\n * ```ts\n * import {registerCard} from \"@pihanga2/core\";\n * import {Box} from \"@/cards/box\";\n *\n * registerCard(\"myApp/spacer\", Box({height: 24}));\n *\n * registerCard(\"myApp/contentRegion\", Box({\n * content: [\"myApp/card1\", \"myApp/card2\"],\n * paddingTop: 16,\n * className: \"rounded-lg border bg-card\",\n * }));\n * ```\n */\nexport const Box = createCardDeclaration<BoxProps>(BOX_CARD);\n"],"mappings":";;AAEA,IAAa,IAAW,YAkEX,IAAM,EAAgC,CAAQ"}
@@ -4,6 +4,10 @@ export declare const Button: <S extends import('@pihanga2/core').ReduxState>(p:
4
4
  export declare const PI_BUTTON_ACTION: {
5
5
  CLICKED: string;
6
6
  };
7
+ export declare const onButtonClicked: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
8
+ cardID: string;
9
+ } & PiButtonClickedEvent>) => void;
10
+ /** @deprecated Use `onButtonClicked` instead. */
7
11
  export declare const onPiButtonClicked: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
8
12
  cardID: string;
9
13
  } & PiButtonClickedEvent>) => void;
@@ -1,7 +1,7 @@
1
1
  import { createCardDeclaration as e, createOnAction as t, registerActions as n } from "@pihanga2/core";
2
2
  //#region src/cards/button/button.types.ts
3
- var r = "pi/button", i = e(r), a = n(r, ["clicked"]), o = t(a.CLICKED);
3
+ var r = "pi/button", i = e(r), a = n(r, ["clicked"]), o = t(a.CLICKED), s = o;
4
4
  //#endregion
5
- export { i as Button, a as PI_BUTTON_ACTION, r as PI_BUTTON_CARD, o as onPiButtonClicked };
5
+ export { i as Button, a as PI_BUTTON_ACTION, r as PI_BUTTON_CARD, o as onButtonClicked, s as onPiButtonClicked };
6
6
 
7
7
  //# sourceMappingURL=button.types.js.map