@pihanga2/shadcn 0.2.1 → 0.2.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.
Files changed (124) hide show
  1. package/AGENT.building-cards.md +208 -3
  2. package/AGENT.md +58 -3
  3. package/AGENT.using-cards.md +142 -4
  4. package/README.md +4 -12
  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.component.js +13 -13
  12. package/cards/button/button.types.d.ts +1 -0
  13. package/cards/button/button.types.js.map +1 -1
  14. package/cards/{chartGraph/chartGraph.component.d.ts → chart/chart.component.d.ts} +1 -1
  15. package/cards/chart/chart.types.d.ts +223 -0
  16. package/cards/chart/index.d.ts +1 -0
  17. package/cards/checkbox/checkbox.component.js +1 -0
  18. package/cards/checkbox/checkbox.component.js.map +1 -1
  19. package/cards/checkbox/checkbox.types.d.ts +4 -0
  20. package/cards/checkbox/checkbox.types.js +2 -2
  21. package/cards/checkbox/checkbox.types.js.map +1 -1
  22. package/cards/checkbox/index.js +5 -5
  23. package/cards/conditional/conditional.component.js +5 -5
  24. package/cards/conditional/conditional.types.d.ts +20 -5
  25. package/cards/conditional/conditional.types.js.map +1 -1
  26. package/cards/core-index.d.ts +3 -0
  27. package/cards/dataTable/dataTable.component.js +8 -8
  28. package/cards/dataTable/dataTable.types.js.map +1 -1
  29. package/cards/dataTable/dataTableRowDetail.component.js +1 -0
  30. package/cards/dataTable/dataTableRowDetail.component.js.map +1 -1
  31. package/cards/dialog/dialog.component.js +7 -7
  32. package/cards/dropDownMenu/drop-down.component.js +7 -7
  33. package/cards/field/field.component.js +4 -4
  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.component.js +1 -1
  42. package/cards/flexGrid/flexGrid.types.js.map +1 -1
  43. package/cards/form/form.component.js +6 -6
  44. package/cards/form/form.types.d.ts +4 -0
  45. package/cards/form/form.types.js +2 -2
  46. package/cards/form/form.types.js.map +1 -1
  47. package/cards/form/index.js +5 -5
  48. package/cards/framework/framework.component.js +4 -4
  49. package/cards/graphin/graphin.types.d.ts +37 -4
  50. package/cards/input/index.js +5 -5
  51. package/cards/input/input.component.js +1 -0
  52. package/cards/input/input.component.js.map +1 -1
  53. package/cards/input/input.types.d.ts +10 -2
  54. package/cards/input/input.types.js +2 -2
  55. package/cards/input/input.types.js.map +1 -1
  56. package/cards/list/list.component.js +32 -32
  57. package/cards/list/list.types.js +1 -0
  58. package/cards/list/list.types.js.map +1 -1
  59. package/cards/loadingOverlay/loadingOverlay.component.js +1 -1
  60. package/cards/loadingSkeleton/loading-skeleton.component.js +1 -1
  61. package/cards/pageWithNavbar/pageWithNavbar.component.d.ts +5 -7
  62. package/cards/pageWithNavbar/pageWithNavbar.component.js +43 -43
  63. package/cards/pageWithNavbar/pageWithNavbar.component.js.map +1 -1
  64. package/cards/pasteTarget/pasteTarget.component.js.map +1 -1
  65. package/cards/select/index.js +5 -5
  66. package/cards/select/select.component.js +1 -0
  67. package/cards/select/select.component.js.map +1 -1
  68. package/cards/select/select.types.d.ts +12 -0
  69. package/cards/select/select.types.js +2 -2
  70. package/cards/select/select.types.js.map +1 -1
  71. package/cards/slider/index.js +13 -0
  72. package/cards/slider/index.js.map +1 -0
  73. package/cards/slider/slider.component.js +64 -0
  74. package/cards/slider/slider.component.js.map +1 -0
  75. package/cards/slider/slider.types.d.ts +12 -4
  76. package/cards/slider/slider.types.js +7 -0
  77. package/cards/slider/slider.types.js.map +1 -0
  78. package/cards/sliderValue/index.js +12 -0
  79. package/cards/sliderValue/index.js.map +1 -0
  80. package/cards/sliderValue/sliderValue.component.js +33 -0
  81. package/cards/sliderValue/sliderValue.component.js.map +1 -0
  82. package/cards/sliderValue/sliderValue.types.js +7 -0
  83. package/cards/sliderValue/sliderValue.types.js.map +1 -0
  84. package/cards/stack/stack.component.js +5 -5
  85. package/cards/stack/stack.component.js.map +1 -1
  86. package/cards/stack/stack.types.js.map +1 -1
  87. package/cards/stepper/stepper.component.js +7 -7
  88. package/cards/switch/index.js +5 -5
  89. package/cards/switch/switch.component.js +1 -0
  90. package/cards/switch/switch.component.js.map +1 -1
  91. package/cards/switch/switch.types.d.ts +4 -0
  92. package/cards/switch/switch.types.js +2 -2
  93. package/cards/switch/switch.types.js.map +1 -1
  94. package/cards/tabs/tabs.component.js +6 -6
  95. package/cards/textField/index.js +5 -5
  96. package/cards/textField/textField.component.js +1 -0
  97. package/cards/textField/textField.component.js.map +1 -1
  98. package/cards/textField/textField.types.d.ts +4 -0
  99. package/cards/textField/textField.types.js +2 -2
  100. package/cards/textField/textField.types.js.map +1 -1
  101. package/cards/toast/index.js +7 -7
  102. package/cards/toast/toast.component.js +12 -12
  103. package/cards/toast/toast.component.js.map +1 -1
  104. package/cards/toast/toast.types.d.ts +4 -0
  105. package/cards/toast/toast.types.js +2 -2
  106. package/cards/toast/toast.types.js.map +1 -1
  107. package/cards/toggleGroup/index.js +5 -5
  108. package/cards/toggleGroup/toggleGroup.component.js +1 -0
  109. package/cards/toggleGroup/toggleGroup.component.js.map +1 -1
  110. package/cards/toggleGroup/toggleGroup.types.d.ts +4 -0
  111. package/cards/toggleGroup/toggleGroup.types.js +2 -2
  112. package/cards/toggleGroup/toggleGroup.types.js.map +1 -1
  113. package/cards/typography/typography.component.js +4 -4
  114. package/cards/typography/typography.types.js +1 -0
  115. package/cards/typography/typography.types.js.map +1 -1
  116. package/components/ui/slider.js +36 -0
  117. package/components/ui/slider.js.map +1 -0
  118. package/components/ui/toggle-group.js +1 -0
  119. package/components/ui/toggle-group.js.map +1 -1
  120. package/package.json +19 -8
  121. package/pihanga-shadcn.css +1 -1
  122. package/cards/chartGraph/chartGraph.types.d.ts +0 -102
  123. package/cards/chartGraph/index.d.ts +0 -1
  124. package/cards/core-index.js +0 -61
@@ -1,13 +1,217 @@
1
1
  # AGENT.building-cards.md — creating new pihanga-shadcn cards
2
2
 
3
- > **Scope:** adding a new card *type* to `src/cards/` in this repository.
3
+ > **Scope:** building new cards either by composing existing cards into a
4
+ > **meta card** (recommended, TypeScript-only) or by adding a brand-new
5
+ > React-based primitive card to `src/cards/`.
4
6
  > Read [`AGENT.md`](./AGENT.md) first for orientation and universal rules.
5
7
  > If you only need to *use* existing cards in an app, switch to
6
8
  > [`AGENT.using-cards.md`](./AGENT.using-cards.md).
7
9
 
8
10
  ---
9
11
 
10
- ## ⚠️ Hard constraints before you write a single line
12
+ ## Meta cards composing new widgets from existing cards
13
+
14
+ > **This is the recommended approach for building any complex or reusable UI
15
+ > widget.** A meta card is assembled entirely from existing cards using a
16
+ > plain TypeScript mapper function — no JSX, no React imports, no DOM
17
+ > knowledge required. Read this section before considering a primitive card.
18
+
19
+ ### Why meta cards?
20
+
21
+ | Concern | Meta card | New primitive card (React component) |
22
+ |---|---|---|
23
+ | Code volume | ~50 lines TypeScript | ~200 lines JSX + hooks |
24
+ | Maintenance | Inherits upstream card fixes automatically | Must track shadcn/Radix updates manually |
25
+ | Reusability | Portable across any Pihanga app unchanged | Tightly coupled to one project |
26
+ | Testability | Pure function — mock props, assert card tree | Requires DOM + Redux environment |
27
+ | Extendibility | Swap any inner card without touching consumers | Requires internal refactoring |
28
+ | Learning curve | Pihanga config patterns only | JSX, React hooks, Pihanga internals |
29
+
30
+ **Rule of thumb:** if you can describe the widget as *"a layout card containing
31
+ some input and display cards"*, build it as a meta card. Only drop to a
32
+ primitive React component when the widget genuinely needs a DOM API, a
33
+ third-party React hook, or a non-card rendering strategy.
34
+
35
+ ### How meta cards work
36
+
37
+ A meta card has three ingredients:
38
+
39
+ 1. **Card declaration + actions** — same as any card; use
40
+ `createCardDeclaration`, `registerActions`, `createOnAction`.
41
+ 2. **Mapper function** — a plain function `(name, props, registerCard) =>
42
+ PiCardDef` that assembles child cards and returns the root card definition.
43
+ 3. **Registration** — `registerMetaCard({type, mapper, events})`.
44
+
45
+ The Pihanga runtime calls the mapper whenever the meta card needs to be
46
+ rendered or re-evaluated. Child cards can use `resolve(props.foo)` inside
47
+ their own prop functions to lazily read a value that may itself be a state
48
+ selector.
49
+
50
+ ### Full worked example — `Counter` meta card
51
+
52
+ The complete, annotated source lives at
53
+ [`example/src/counter.card.ts`](./example/src/counter.card.ts).
54
+ Abbreviated for reference:
55
+
56
+ ```ts
57
+ import {
58
+ createCardDeclaration, createOnAction, registerActions, registerMetaCard,
59
+ } from "@pihanga2/core";
60
+ import type {PiCardDef, PiMapProps, PiRegisterMetaCard, ReduxState, RegisterCardF} from "@pihanga2/core";
61
+ import {Stack, Button, Typography} from "@pihanga2/shadcn";
62
+
63
+ // ── 1. Card identity ─────────────────────────────────────────────────────────
64
+ const COUNTER_CARD = "meta/counter"; // convention: "meta/<name>" for app-level
65
+
66
+ // ── 2. Public factory (consumers call Counter({value: ...})) ────────────────
67
+ export const Counter = createCardDeclaration<CounterProps, CounterEvents>(COUNTER_CARD);
68
+
69
+ // ── 3. Actions + typed event helper ─────────────────────────────────────────
70
+ export const COUNTER_ACTION = registerActions(COUNTER_CARD, ["changed"]);
71
+ export const onCounterChanged = createOnAction<CounterChangeEvent>(COUNTER_ACTION.CHANGED);
72
+
73
+ // ── 4. Types ─────────────────────────────────────────────────────────────────
74
+ type CounterProps = { value: number };
75
+ type CounterChangeEvent = { value: number };
76
+ type CounterEvents = { onChange: CounterChangeEvent };
77
+ type CounterMapperProps = CounterProps & CounterEvents;
78
+
79
+ // ── 5. Mapper — assembles child cards ────────────────────────────────────────
80
+ function CounterMapper(
81
+ _: string,
82
+ props: PiMapProps<CounterMapperProps, ReduxState, object>,
83
+ registerCard: RegisterCardF,
84
+ ): PiCardDef {
85
+ // Register a child card under a stable name (optional but shown for reference)
86
+ const plusButton = registerCard("plus", Button({
87
+ label: "+",
88
+ opts: {size: "lg"},
89
+ // Re-map raw click → COUNTER_ACTION.CHANGED { value + 1 }
90
+ onClickedMapper: (_, {resolve}) => ({
91
+ type: COUNTER_ACTION.CHANGED,
92
+ value: resolve(props.value) + 1, // resolve() unwraps lazy state selectors
93
+ }),
94
+ }));
95
+
96
+ return Stack({
97
+ direction: "row", alignItems: "center", spacing: 4,
98
+ className: "p-16 justify-center",
99
+ content: [
100
+ Button({
101
+ label: "−",
102
+ opts: {size: "lg"},
103
+ onClickedMapper: (_, {resolve}) => ({
104
+ type: COUNTER_ACTION.CHANGED,
105
+ value: resolve(props.value) - 1,
106
+ }),
107
+ }),
108
+ Typography({
109
+ text: (_, {resolve}) => `Count: ${resolve(props.value)}`, // reactive text
110
+ level: "h2",
111
+ className: "min-w-[120px] text-center",
112
+ }),
113
+ plusButton,
114
+ ],
115
+ });
116
+ }
117
+
118
+ // ── 6. Register ───────────────────────────────────────────────────────────────
119
+ registerMetaCard({
120
+ type: COUNTER_CARD,
121
+ mapper: CounterMapper,
122
+ events: COUNTER_ACTION,
123
+ } satisfies PiRegisterMetaCard);
124
+ ```
125
+
126
+ **Usage at the app level** (`example/src/app.pihanga.ts`):
127
+
128
+ ```ts
129
+ import {Counter} from "./counter.card";
130
+ import type {AppState} from "./app.state";
131
+
132
+ registerCard("page", Counter<AppState>({
133
+ value: (s) => s.count, // state selector — auto-reactive
134
+ }));
135
+ ```
136
+
137
+ **Handling the emitted event** (`example/src/app.reducer.ts`):
138
+
139
+ ```ts
140
+ import {onCounterChanged} from "./counter.card";
141
+
142
+ register((r) => {
143
+ onCounterChanged<AppState>(r, (state, {value}) => {
144
+ state.count = value; // raw button clicks never surface here — encapsulated
145
+ });
146
+ });
147
+ ```
148
+
149
+ ### Key API reference for meta cards
150
+
151
+ | Symbol | Source | Purpose |
152
+ |---|---|---|
153
+ | `registerMetaCard(opts)` | `@pihanga2/core` | Registers a mapper as a named card type |
154
+ | `PiRegisterMetaCard` | `@pihanga2/core` | Type for the `opts` object (use `satisfies`) |
155
+ | `MetaCardMapperF` | `@pihanga2/core` | Type of the mapper function |
156
+ | `RegisterCardF` | `@pihanga2/core` | Type of the `registerCard` arg inside the mapper |
157
+ | `PiMapProps<Props, State, Ctx>` | `@pihanga2/core` | Prop type inside the mapper (each prop may be a state selector) |
158
+ | `resolve(prop)` | `StateMapperContext` | Unwraps a lazy prop value inside a child card's prop function |
159
+ | `onClickedMapper` / `on*Mapper` | any card | Event mapper suffix — re-maps a child card's action to a different action type |
160
+
161
+ ### Patterns to know
162
+
163
+ **Lazy prop propagation with `resolve`**
164
+
165
+ When a meta card receives `value: (s) => s.count` (a state selector), child
166
+ cards can't use that selector directly — it has to be unwrapped at the time the
167
+ child's own prop function runs:
168
+
169
+ ```ts
170
+ // ❌ Doesn't work — selector is passed as-is; child sees a function, not a number
171
+ Typography({ text: props.value })
172
+
173
+ // ✅ Correct — resolve() unwraps the selector inside the child's prop function
174
+ Typography({ text: (_, {resolve}) => `Count: ${resolve(props.value)}` })
175
+ ```
176
+
177
+ **Event remapping with `onXxxMapper`**
178
+
179
+ Every card that emits an event supports an `on<EventName>Mapper` prop. The
180
+ mapper intercepts the raw event and returns a different action (or `null` to
181
+ suppress):
182
+
183
+ ```ts
184
+ Button({
185
+ label: "Save",
186
+ // Re-map generic click → domain-specific action
187
+ onClickedMapper: (_ev, _ctx) => ({ type: MY_ACTION.SAVED }),
188
+ })
189
+ ```
190
+
191
+ **Registering a stable child card name**
192
+
193
+ Pass the result of `registerCard(name, def)` as a child in the `content` array.
194
+ This is optional but gives the child a stable registry identity:
195
+
196
+ ```ts
197
+ const saveBtn = registerCard("save-btn", Button({label: "Save", …}));
198
+ return Stack({ content: [saveBtn] });
199
+ ```
200
+
201
+ **Accessing metacard context from a deeply nested child**
202
+
203
+ Use `metaCtxtProps` in a child card's state mapper when you need the context
204
+ props that were passed to the meta card's top-level card:
205
+
206
+ ```ts
207
+ // Inside a child card declaration within the mapper:
208
+ properties: (s, { metaCtxtProps }) => metaCtxtProps.elementData.properties,
209
+ ```
210
+
211
+ ---
212
+
213
+ ## ⚠️ Hard constraints before you write a single line (primitive cards)
214
+
11
215
 
12
216
  1. **`src/components/` is read-only.** It is managed exclusively by the shadcn
13
217
  CLI (`npx shadcn@latest add <name>`). Never create or edit files there.
@@ -383,7 +587,8 @@ Rules:
383
587
 
384
588
  | Need | Card to study |
385
589
  |---|---|
386
- | Minimal card structure | `src/cards/emptyCard.tsx` |
590
+ | **Meta card (composition)** | **`example/src/counter.card.ts`** — fully annotated: Stack + Button × 2 + Typography, event remapping, `resolve()`, stable child names |
591
+ | Minimal primitive card structure | `src/cards/emptyCard.tsx` |
387
592
  | Button with variants, icons, tooltip | `src/cards/button/` |
388
593
  | Dropdown / context menu | `src/cards/dropDownMenu/` |
389
594
  | Form input pattern | `src/cards/textField/`, `src/cards/checkbox/` |
package/AGENT.md CHANGED
@@ -32,7 +32,8 @@ https://github.com/ivcap-works/pihanga-shadcn
32
32
  |---|---|
33
33
  | **Getting started** — brand-new project, shadcn/ui + pihanga setup, file layout | [`AGENTS.getting-started.md`](./AGENTS.getting-started.md) |
34
34
  | **Using** existing cards — install, wire, compose, navigate | [`AGENT.using-cards.md`](./AGENT.using-cards.md) |
35
- | **Building** new cardscreate a new card type for this repo | [`AGENT.building-cards.md`](./AGENT.building-cards.md) |
35
+ | **Building complex UI**assembling a reusable widget from existing cards | [`AGENT.building-cards.md`](./AGENT.building-cards.md) — § *Meta cards* |
36
+ | **Building** a new primitive card from scratch — new React component for this repo | [`AGENT.building-cards.md`](./AGENT.building-cards.md) |
36
37
 
37
38
  If you are **starting from scratch**, read `AGENTS.getting-started.md` first — it
38
39
  covers Vite setup, shadcn/ui init, pihanga-core installation, and the initial file
@@ -41,8 +42,55 @@ layout. Then continue with `AGENT.using-cards.md` for wiring and composing card
41
42
  If you are adding cards to an **existing project**, go straight to
42
43
  `AGENT.using-cards.md`.
43
44
 
44
- Switch to `AGENT.building-cards.md` only when you need to add a new card *type*
45
- to `src/cards/` itself.
45
+ ### Need a complex, reusable UI widget? Use a meta card.
46
+
47
+ Before writing a new React component, ask: *can I build this by composing
48
+ existing cards?* If yes — and that is almost always the answer — use a
49
+ **meta card** instead.
50
+
51
+ A meta card is a TypeScript-only module (no JSX, no React imports) that
52
+ assembles other cards inside a mapper function and registers itself with
53
+ `registerMetaCard`. The result looks and feels exactly like a primitive card to
54
+ consumers: a typed factory function, typed event helpers, and full `memo()`/state
55
+ reactivity.
56
+
57
+ ```ts
58
+ // example/src/counter.card.ts (abbreviated)
59
+ import {registerMetaCard, createCardDeclaration, registerActions} from "@pihanga2/core";
60
+ import {Stack, Button, Typography} from "@pihanga2/shadcn";
61
+
62
+ const COUNTER_CARD = "meta/counter";
63
+ export const Counter = createCardDeclaration<CounterProps, CounterEvents>(COUNTER_CARD);
64
+ export const COUNTER_ACTION = registerActions(COUNTER_CARD, ["changed"]);
65
+
66
+ registerMetaCard({
67
+ type: COUNTER_CARD,
68
+ mapper(_name, props, registerCard) {
69
+ return Stack({ content: [
70
+ Button({ label: "−", onClickedMapper: (_, {resolve}) => ({type: COUNTER_ACTION.CHANGED, value: resolve(props.value) - 1}) }),
71
+ Typography({ text: (_, {resolve}) => `Count: ${resolve(props.value)}` }),
72
+ Button({ label: "+", onClickedMapper: (_, {resolve}) => ({type: COUNTER_ACTION.CHANGED, value: resolve(props.value) + 1}) }),
73
+ ]});
74
+ },
75
+ events: COUNTER_ACTION,
76
+ });
77
+ ```
78
+
79
+ **Why meta cards over new React components?**
80
+
81
+ | Concern | Meta card | New React component |
82
+ |---|---|---|
83
+ | Code complexity | Low — pure TypeScript config | High — JSX, hooks, event wiring |
84
+ | Maintenance | Inherits upstream fixes automatically | Must be kept in sync manually |
85
+ | Reusability | Drops into any Pihanga app | Tightly coupled to one project |
86
+ | Testability | Plain function, mockable | Requires DOM + Redux setup |
87
+ | Extendibility | Swap out any inner card without touching consumers | Requires internal refactoring |
88
+
89
+ See the full meta card guide in [`AGENT.building-cards.md`](./AGENT.building-cards.md#meta-cards--composing-new-widgets-from-existing-cards)
90
+ and the complete working example at [`example/src/counter.card.ts`](./example/src/counter.card.ts).
91
+
92
+ Switch to `AGENT.building-cards.md` — § *Building a primitive card from scratch* — only
93
+ when no combination of existing cards can achieve the required UI.
46
94
 
47
95
  ---
48
96
 
@@ -55,3 +103,10 @@ to `src/cards/` itself.
55
103
  must ensure only one of them calls it.
56
104
  - **`children` is a reserved React prop** — never use it in a card's `…Props`
57
105
  type; use `content`, `contentCard`, or `items` instead.
106
+ - **npm channel: add `lucide-react` to `optimizeDeps.include`** — excluding
107
+ `@pihanga2/shadcn` from Vite's pre-bundler (required to prevent duplicate
108
+ registries) also causes `lucide-react` to be served as raw ESM, triggering
109
+ ~1 000 individual icon file requests in the dev browser. Adblockers block
110
+ `fingerprint.js` as a tracking script. Always include `"lucide-react"` in
111
+ `optimizeDeps.include` (see `AGENTS.getting-started.md` Step 5). Production
112
+ builds are unaffected — Rollup tree-shakes unused icons normally.
@@ -30,9 +30,16 @@
30
30
  > shadcn/ui and Radix UI updates, it won't appear in the playground
31
31
  > automatically, and it won't benefit from upstream bug fixes.
32
32
  >
33
- > **If no suitable card exists:**
34
- > - Confirm the need is genuine and not already covered by composing existing
35
- > 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:**
36
43
  > - Unless the card would expose confidential business logic, please
37
44
  > **open an issue** at
38
45
  > `https://github.com/ivcap-works/pihanga-shadcn/issues` describing what you
@@ -424,6 +431,137 @@ registerCard("myApp/save", Button({
424
431
 
425
432
  ---
426
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
+
427
565
  ## Version pinning
428
566
 
429
567
  Use a git tag in the URL to pin to a specific release:
@@ -992,7 +1130,7 @@ project that was bootstrapped without the reference `index.css`:
992
1130
  Both fixes are now included in the reference `src/index.css` template in
993
1131
  *Prerequisites step 3*.
994
1132
 
995
- ### 2026-06 agent evaluation — ViteJS app from scratch (BuhlOS-2)
1133
+ ### 2026-06 agent evaluation — ViteJS app from scratch
996
1134
 
997
1135
  An agent built a new ViteJS + React + TypeScript app from scratch using
998
1136
  `yarn create vite` and then manually copied pihanga-shadcn cards. The
package/README.md CHANGED
@@ -52,17 +52,6 @@ module.exports = {
52
52
 
53
53
  ## Usage
54
54
 
55
- ### Register all core cards at once
56
-
57
- ```ts
58
- import "@pihanga2/shadcn";
59
- ```
60
-
61
- This imports `core-index.js`, which calls `registerCardComponent()` for every
62
- core card in the Pihanga runtime.
63
-
64
- ### Register individual cards (tree-shakeable)
65
-
66
55
  Import only the cards your app uses — unused cards are eliminated by your bundler:
67
56
 
68
57
  ```ts
@@ -73,7 +62,7 @@ import "@pihanga2/shadcn/cards/dataTable";
73
62
 
74
63
  ---
75
64
 
76
- ## Included cards (30)
65
+ ## Included cards (33)
77
66
 
78
67
  - `badge`
79
68
  - `box`
@@ -84,6 +73,7 @@ import "@pihanga2/shadcn/cards/dataTable";
84
73
  - `dialog`
85
74
  - `dropDownMenu`
86
75
  - `field`
76
+ - `fileDrop`
87
77
  - `flexGrid`
88
78
  - `form`
89
79
  - `framework`
@@ -97,6 +87,8 @@ import "@pihanga2/shadcn/cards/dataTable";
97
87
  - `pageWithNavbar`
98
88
  - `pasteTarget`
99
89
  - `select`
90
+ - `slider`
91
+ - `sliderValue`
100
92
  - `stack`
101
93
  - `stepper`
102
94
  - `switch`
@@ -1,6 +1,7 @@
1
1
  import { Badge as e } from "../../components/ui/badge.js";
2
2
  import { cn as t } from "../../lib/utils.js";
3
3
  import "react";
4
+ import "@pihanga2/core";
4
5
  import { jsx as n } from "react/jsx-runtime";
5
6
  //#region src/cards/badge/badge.component.tsx
6
7
  var r = (r) => {
@@ -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"}
@@ -1,9 +1,9 @@
1
- import { Card as e } from "@pihanga2/core";
2
1
  import "react";
2
+ import { Card as e } from "@pihanga2/core";
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 = { ...o?.shad };
6
+ let { content: i, className: a, style: o, cardName: s } = r, c = { ...o };
7
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, {
@@ -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 const sy: Record<string, string | number> = {\n ...(style as {shad?: Record<string, string | number>} | undefined)?.shad,\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,GAAgE,KACtE;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
+ {"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"}
@@ -1,16 +1,16 @@
1
- import { Button as e, LinkButton as t } from "../../components/ui/button.js";
2
- import { Tooltip as n, TooltipContent as r, TooltipTrigger as i } from "../../components/ui/tooltip.js";
3
- import { getIcon as a } from "../icons.js";
1
+ import { getIcon as e } from "../icons.js";
2
+ import { Button as t, LinkButton as n } from "../../components/ui/button.js";
3
+ import { Tooltip as r, TooltipContent as i, TooltipTrigger as a } from "../../components/ui/tooltip.js";
4
4
  import { useDropdownOpen as o } from "../dropDownMenu/dropdown-context.js";
5
- import { Card as s } from "@pihanga2/core";
6
5
  import "react";
6
+ import { Card as s } from "@pihanga2/core";
7
7
  import { Fragment as c, jsx as l, jsxs as u } from "react/jsx-runtime";
8
8
  //#region src/cards/button/button.component.tsx
9
- function d(e) {
10
- return e ? a(e) : null;
9
+ function d(t) {
10
+ return t ? e(t) : null;
11
11
  }
12
- var f = (a) => {
13
- let { opts: f, ariaLabel: p, label: m, iconLabel: h, contentCard: g, href: _, target: v, tooltip: y, tooltipCard: b, tooltipMode: x, tooltipPlacement: S, className: C, id: w, onClicked: T, cardName: E, _cls: D, active: O, focused: k, disabled: A, loading: j, isPending: M } = a, N = o(), P = d(f?.beforeIcon), F = d(f?.afterIcon), I = /* @__PURE__ */ u(c, { children: [
12
+ var f = (e) => {
13
+ let { opts: f, ariaLabel: p, label: m, iconLabel: h, contentCard: g, href: _, target: v, tooltip: y, tooltipCard: b, tooltipMode: x, tooltipPlacement: S, className: C, id: w, onClicked: T, cardName: E, _cls: D, active: O, focused: k, disabled: A, loading: j, isPending: M } = e, N = o(), P = d(f?.beforeIcon), F = d(f?.afterIcon), I = /* @__PURE__ */ u(c, { children: [
14
14
  P,
15
15
  h ? d(h) : g ? /* @__PURE__ */ l(s, {
16
16
  cardName: g,
@@ -31,7 +31,7 @@ var f = (a) => {
31
31
  className: `${D("root")} ${C || ""}`.trim()
32
32
  }, R = () => {
33
33
  T({ id: w });
34
- }, z = () => _ ? /* @__PURE__ */ l(t, {
34
+ }, z = () => _ ? /* @__PURE__ */ l(n, {
35
35
  ...L,
36
36
  href: _,
37
37
  target: v,
@@ -39,7 +39,7 @@ var f = (a) => {
39
39
  label: p ?? m,
40
40
  onClick: R,
41
41
  children: I
42
- }) : /* @__PURE__ */ l(e, {
42
+ }) : /* @__PURE__ */ l(t, {
43
43
  ...L,
44
44
  "data-pihanga": E,
45
45
  label: p ?? m,
@@ -54,12 +54,12 @@ var f = (a) => {
54
54
  "data-pihanga": `${E}-tooltip`,
55
55
  children: y
56
56
  });
57
- return /* @__PURE__ */ u(n, {
57
+ return /* @__PURE__ */ u(r, {
58
58
  open: B,
59
- children: [/* @__PURE__ */ l(i, {
59
+ children: [/* @__PURE__ */ l(a, {
60
60
  asChild: !0,
61
61
  children: z()
62
- }), /* @__PURE__ */ l(r, {
62
+ }), /* @__PURE__ */ l(i, {
63
63
  side: S,
64
64
  children: V
65
65
  })]