@pihanga2/shadcn 0.2.1 → 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 (108) 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 -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 +1 -1
  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 +1 -0
  12. package/cards/button/button.types.js.map +1 -1
  13. package/cards/{chartGraph/chartGraph.component.d.ts → chart/chart.component.d.ts} +1 -1
  14. package/cards/chart/chart.types.d.ts +223 -0
  15. package/cards/chart/index.d.ts +1 -0
  16. package/cards/checkbox/checkbox.component.js +1 -0
  17. package/cards/checkbox/checkbox.component.js.map +1 -1
  18. package/cards/checkbox/checkbox.types.d.ts +4 -0
  19. package/cards/checkbox/checkbox.types.js +2 -2
  20. package/cards/checkbox/checkbox.types.js.map +1 -1
  21. package/cards/checkbox/index.js +5 -5
  22. package/cards/conditional/conditional.types.d.ts +20 -5
  23. package/cards/conditional/conditional.types.js.map +1 -1
  24. package/cards/core-index.d.ts +3 -0
  25. package/cards/core-index.js +36 -29
  26. package/cards/dataTable/dataTable.types.js.map +1 -1
  27. package/cards/dataTable/dataTableRowDetail.component.js +1 -0
  28. package/cards/dataTable/dataTableRowDetail.component.js.map +1 -1
  29. package/cards/field/field.types.js.map +1 -1
  30. package/cards/fileDrop/fileDrop.component.js +90 -0
  31. package/cards/fileDrop/fileDrop.component.js.map +1 -0
  32. package/cards/fileDrop/fileDrop.types.js +11 -0
  33. package/cards/fileDrop/fileDrop.types.js.map +1 -0
  34. package/cards/fileDrop/index.js +13 -0
  35. package/cards/fileDrop/index.js.map +1 -0
  36. package/cards/flexGrid/flexGrid.types.js.map +1 -1
  37. package/cards/form/form.types.d.ts +4 -0
  38. package/cards/form/form.types.js +2 -2
  39. package/cards/form/form.types.js.map +1 -1
  40. package/cards/form/index.js +5 -5
  41. package/cards/graphin/graphin.types.d.ts +37 -4
  42. package/cards/input/index.js +5 -5
  43. package/cards/input/input.component.js +1 -0
  44. package/cards/input/input.component.js.map +1 -1
  45. package/cards/input/input.types.d.ts +10 -2
  46. package/cards/input/input.types.js +2 -2
  47. package/cards/input/input.types.js.map +1 -1
  48. package/cards/list/list.types.js +1 -0
  49. package/cards/list/list.types.js.map +1 -1
  50. package/cards/pageWithNavbar/pageWithNavbar.component.d.ts +5 -7
  51. package/cards/pageWithNavbar/pageWithNavbar.component.js +1 -1
  52. package/cards/pageWithNavbar/pageWithNavbar.component.js.map +1 -1
  53. package/cards/pasteTarget/pasteTarget.component.js.map +1 -1
  54. package/cards/select/index.js +5 -5
  55. package/cards/select/select.component.js +1 -0
  56. package/cards/select/select.component.js.map +1 -1
  57. package/cards/select/select.types.d.ts +12 -0
  58. package/cards/select/select.types.js +2 -2
  59. package/cards/select/select.types.js.map +1 -1
  60. package/cards/slider/index.js +13 -0
  61. package/cards/slider/index.js.map +1 -0
  62. package/cards/slider/slider.component.js +64 -0
  63. package/cards/slider/slider.component.js.map +1 -0
  64. package/cards/slider/slider.types.d.ts +12 -4
  65. package/cards/slider/slider.types.js +7 -0
  66. package/cards/slider/slider.types.js.map +1 -0
  67. package/cards/sliderValue/index.js +12 -0
  68. package/cards/sliderValue/index.js.map +1 -0
  69. package/cards/sliderValue/sliderValue.component.js +33 -0
  70. package/cards/sliderValue/sliderValue.component.js.map +1 -0
  71. package/cards/sliderValue/sliderValue.types.js +7 -0
  72. package/cards/sliderValue/sliderValue.types.js.map +1 -0
  73. package/cards/stack/stack.component.js +1 -1
  74. package/cards/stack/stack.component.js.map +1 -1
  75. package/cards/stack/stack.types.js.map +1 -1
  76. package/cards/switch/index.js +5 -5
  77. package/cards/switch/switch.component.js +1 -0
  78. package/cards/switch/switch.component.js.map +1 -1
  79. package/cards/switch/switch.types.d.ts +4 -0
  80. package/cards/switch/switch.types.js +2 -2
  81. package/cards/switch/switch.types.js.map +1 -1
  82. package/cards/textField/index.js +5 -5
  83. package/cards/textField/textField.component.js +1 -0
  84. package/cards/textField/textField.component.js.map +1 -1
  85. package/cards/textField/textField.types.d.ts +4 -0
  86. package/cards/textField/textField.types.js +2 -2
  87. package/cards/textField/textField.types.js.map +1 -1
  88. package/cards/toast/index.js +7 -7
  89. package/cards/toast/toast.component.js.map +1 -1
  90. package/cards/toast/toast.types.d.ts +4 -0
  91. package/cards/toast/toast.types.js +2 -2
  92. package/cards/toast/toast.types.js.map +1 -1
  93. package/cards/toggleGroup/index.js +5 -5
  94. package/cards/toggleGroup/toggleGroup.component.js +1 -0
  95. package/cards/toggleGroup/toggleGroup.component.js.map +1 -1
  96. package/cards/toggleGroup/toggleGroup.types.d.ts +4 -0
  97. package/cards/toggleGroup/toggleGroup.types.js +2 -2
  98. package/cards/toggleGroup/toggleGroup.types.js.map +1 -1
  99. package/cards/typography/typography.types.js +1 -0
  100. package/cards/typography/typography.types.js.map +1 -1
  101. package/components/ui/slider.js +36 -0
  102. package/components/ui/slider.js.map +1 -0
  103. package/components/ui/toggle-group.js +1 -0
  104. package/components/ui/toggle-group.js.map +1 -1
  105. package/package.json +19 -2
  106. package/pihanga-shadcn.css +1 -1
  107. package/cards/chartGraph/chartGraph.types.d.ts +0 -102
  108. package/cards/chartGraph/index.d.ts +0 -1
@@ -0,0 +1,223 @@
1
+ import { ChartConfig } from '../../components/ui/chart';
2
+ export declare const PI_CHART_GRAPH_CARD = "shad/chart-graph";
3
+ export declare const Chart: <S extends import('@pihanga2/core').ReduxState>(p: import('@pihanga2/core').PiMapProps<PiChartGraphProps, S, {}>) => import('@pihanga2/core').PiCardDef;
4
+ export type { ChartConfig };
5
+ export type PiChartSeries = {
6
+ /** Key in each data-point object whose value will be plotted on the y-axis. */
7
+ dataKey: string;
8
+ /** Human-readable label used in the tooltip and legend. Defaults to `dataKey`. */
9
+ label?: string;
10
+ /**
11
+ * CSS colour string for this series.
12
+ * Falls back to the shadcn chart CSS variables
13
+ * (`hsl(var(--chart-1))`, `hsl(var(--chart-2))`, …) in order.
14
+ */
15
+ color?: string;
16
+ /**
17
+ * Recharts curve interpolation type.
18
+ * Common values: `"natural"` (smooth, default), `"linear"`, `"step"`,
19
+ * `"stepBefore"`, `"stepAfter"`, `"monotone"`.
20
+ */
21
+ curveType?: "natural" | "linear" | "monotone" | "step" | "stepBefore" | "stepAfter";
22
+ /** Stroke width in pixels. Defaults to `2`. */
23
+ strokeWidth?: number;
24
+ /**
25
+ * SVG `stroke-dasharray` value for a dashed/dotted line.
26
+ * e.g. `"4 4"` → short dashes, `"8 4"` → long dashes, `undefined` → solid.
27
+ */
28
+ strokeDasharray?: string;
29
+ /**
30
+ * Show a dot at each data point.
31
+ * `false` (default) hides dots; `true` shows them with the recharts defaults;
32
+ * pass an object (e.g. `{ r: 4, fill: "white" }`) for full SVG circle control.
33
+ */
34
+ dot?: boolean | Record<string, unknown>;
35
+ /**
36
+ * CSS colour override for the filled area (`chartType: "area"` only).
37
+ * Defaults to the same value as `color` so the fill matches the stroke.
38
+ *
39
+ * @example `fillColor: "hsl(var(--chart-3))"` — fill with a different palette colour.
40
+ * @example `fillColor: "transparent"` — stroke-only appearance inside an AreaChart.
41
+ */
42
+ fillColor?: string;
43
+ /**
44
+ * Per-series fill opacity (`chartType: "area"` only).
45
+ * Overrides the chart-level `fillOpacity` prop for this series.
46
+ * Range 0–1.
47
+ */
48
+ fillOpacity?: number;
49
+ };
50
+ /**
51
+ * A single recharts `<ReferenceLine>` to overlay on the chart.
52
+ * Specify either `x` (vertical line) or `y` (horizontal line).
53
+ *
54
+ * @example
55
+ * ```ts
56
+ * // Horizontal threshold at y = 100
57
+ * { y: 100, label: "Limit", stroke: "red", strokeDasharray: "4 4" }
58
+ *
59
+ * // Vertical marker at a specific x value
60
+ * { x: "Mar", label: "Launch", stroke: "var(--chart-2)" }
61
+ * ```
62
+ */
63
+ export type PiChartReferenceLine = {
64
+ /**
65
+ * Value on the **x-axis** where a vertical reference line is drawn.
66
+ * Omit when drawing a horizontal line.
67
+ */
68
+ x?: string | number;
69
+ /**
70
+ * Value on the **y-axis** where a horizontal reference line is drawn.
71
+ * Omit when drawing a vertical line.
72
+ */
73
+ y?: number;
74
+ /**
75
+ * Label rendered beside the line. Pass a plain string for the recharts
76
+ * default positioning, or a `{ value, position, fill, fontSize }` object
77
+ * for full control (recharts `LabelProps`).
78
+ */
79
+ label?: string | {
80
+ value: string;
81
+ position?: string;
82
+ fill?: string;
83
+ fontSize?: number;
84
+ };
85
+ /** CSS colour for the line stroke. Defaults to `"var(--border)"`. */
86
+ stroke?: string;
87
+ /**
88
+ * SVG `stroke-dasharray` value for the line style.
89
+ * `"4 4"` → short dashes, `"8 4"` → long dashes, `undefined` → solid.
90
+ */
91
+ strokeDasharray?: string;
92
+ /** Line stroke width in pixels. Defaults to `1`. */
93
+ strokeWidth?: number;
94
+ };
95
+ export type PiChartGraphProps = {
96
+ /**
97
+ * Whether to render an **area** chart (filled) or a **line** chart (stroke only).
98
+ */
99
+ chartType: "area" | "line";
100
+ /**
101
+ * Array of data points. Each entry must contain:
102
+ * - a value for `xDataKey` (used for the x-axis labels), and
103
+ * - a numeric value for each `series[].dataKey`.
104
+ *
105
+ * @example
106
+ * ```ts
107
+ * [
108
+ * { month: "Jan", desktop: 186, mobile: 80 },
109
+ * { month: "Feb", desktop: 305, mobile: 200 },
110
+ * ]
111
+ * ```
112
+ */
113
+ data: Array<Record<string, unknown>>;
114
+ /**
115
+ * Series definitions. Each entry describes one plotted line or area.
116
+ * At least one series is required.
117
+ */
118
+ series: PiChartSeries[];
119
+ /** Key inside each data-point object used for the x-axis tick labels. */
120
+ xDataKey: string;
121
+ /**
122
+ * Optional card title rendered above the chart.
123
+ * When either `title` or `description` is set the chart is wrapped in a
124
+ * shadcn `<Card>` shell; otherwise it renders as a bare `<div>`.
125
+ */
126
+ title?: string;
127
+ /**
128
+ * Optional subtitle rendered below `title`.
129
+ * Has no effect when `title` is not set.
130
+ */
131
+ description?: string;
132
+ /**
133
+ * Minimum chart height in pixels.
134
+ * The chart expands if the responsive container requires more space.
135
+ * Defaults to `250`.
136
+ */
137
+ height?: number;
138
+ /** Show a legend beneath the chart. Defaults to `true`. */
139
+ showLegend?: boolean;
140
+ /** Show horizontal cartesian grid lines. Defaults to `true`. */
141
+ showGrid?: boolean;
142
+ /**
143
+ * Show the x-axis tick labels along the bottom of the chart.
144
+ * Defaults to `true`. Set to `false` to hide the x-axis entirely.
145
+ */
146
+ showXAxisLabel?: boolean;
147
+ /**
148
+ * Show the y-axis with numeric tick labels on the left edge of the chart.
149
+ * Defaults to `false` (y-axis hidden) to keep the chart compact.
150
+ * Alias: `showYAxisLabel`.
151
+ */
152
+ showYAxis?: boolean;
153
+ /**
154
+ * Alias for `showYAxis` — provided for naming consistency with `showXAxisLabel`.
155
+ * When either flag is `true` the y-axis is rendered.
156
+ */
157
+ showYAxisLabel?: boolean;
158
+ /**
159
+ * Minimum value for the y-axis domain. Defaults to `"auto"` (data-driven).
160
+ * Pass `0` to always start the y-axis at zero.
161
+ */
162
+ yAxisMin?: number;
163
+ /**
164
+ * Maximum value for the y-axis domain. Defaults to `"auto"` (data-driven).
165
+ */
166
+ yAxisMax?: number;
167
+ /**
168
+ * Minimum value for the x-axis domain. Only meaningful for numeric x-axes.
169
+ * Defaults to `"auto"` (data-driven).
170
+ */
171
+ xAxisMin?: number;
172
+ /**
173
+ * Maximum value for the x-axis domain. Only meaningful for numeric x-axes.
174
+ * Defaults to `"auto"` (data-driven).
175
+ */
176
+ xAxisMax?: number;
177
+ /**
178
+ * Unit string appended to every y-axis tick label (e.g. `"ms"`, `"%"`, `" km"`).
179
+ * Only visible when `showYAxis` is `true`.
180
+ *
181
+ * @example `yAxisUnit="%"` renders ticks as `"0%"`, `"50%"`, `"100%"`.
182
+ */
183
+ yAxisUnit?: string;
184
+ /**
185
+ * Unit string appended to every x-axis tick label.
186
+ * Useful when x-axis values are numeric (e.g. seconds, iterations).
187
+ * Has no effect when x-axis values are already formatted strings (e.g. month names).
188
+ *
189
+ * @example `xAxisUnit="s"` renders ticks as `"1s"`, `"2s"`, etc.
190
+ */
191
+ xAxisUnit?: string;
192
+ /**
193
+ * Stack all area series on top of each other (area chart only).
194
+ * When `false` (default) the filled areas overlap.
195
+ */
196
+ stacked?: boolean;
197
+ /**
198
+ * Opacity of the filled area (area chart only).
199
+ * Range 0–1. Defaults to `0.4`.
200
+ */
201
+ fillOpacity?: number;
202
+ /**
203
+ * Suppress the recharts entry animation so the chart renders immediately
204
+ * without the "draw-in" / "unfold" effect.
205
+ * Defaults to `false` (animation enabled).
206
+ */
207
+ suppressAnimation?: boolean;
208
+ /**
209
+ * One or more reference lines to overlay on the chart.
210
+ * Each entry maps directly to a recharts `<ReferenceLine>`.
211
+ *
212
+ * @example
213
+ * ```ts
214
+ * referenceLines: [
215
+ * { y: 100, label: "Threshold", stroke: "red", strokeDasharray: "4 4" },
216
+ * { x: "Mar", label: "Launch", stroke: "var(--chart-2)" },
217
+ * ]
218
+ * ```
219
+ */
220
+ referenceLines?: PiChartReferenceLine[];
221
+ /** Extra Tailwind / CSS classes forwarded to the outermost element. */
222
+ className?: string;
223
+ };
@@ -0,0 +1 @@
1
+ export * from './chart.types';
@@ -1,4 +1,5 @@
1
1
  import { useFormContext as e } from "../form/form.context.js";
2
+ import "@pihanga2/core";
2
3
  import "react";
3
4
  import { jsx as t, jsxs as n } from "react/jsx-runtime";
4
5
  //#region src/cards/checkbox/checkbox.component.tsx
@@ -1 +1 @@
1
- {"version":3,"file":"checkbox.component.js","names":[],"sources":["../../../src/cards/checkbox/checkbox.component.tsx"],"sourcesContent":["import React from \"react\";\nimport {type PiCardProps} from \"@pihanga2/core\";\nimport {useFormContext} from \"@/cards/form/form.context\";\nimport type {PiCheckboxEvents, PiCheckboxProps} from \"./checkbox.types\";\n\nexport const CheckboxComponent = (\n props: PiCardProps<PiCheckboxProps, PiCheckboxEvents>,\n): React.ReactNode => {\n const {\n name,\n checked: propChecked = false,\n disabled,\n label,\n cardName,\n onChanged,\n } = props;\n\n // `id` and `invalid` may be injected by a parent pi/field card via\n // Pihanga's extra-prop forwarding. They are not in the official type so\n // we read them through an escape hatch.\n const injectedId = (props as {id?: string}).id;\n const invalid = Boolean((props as {invalid?: boolean}).invalid);\n\n // Detect if we are inside a pi/form card via React context.\n const form = useFormContext();\n const useFormData = form.isInForm && Boolean(name);\n\n const checked = useFormData\n ? Boolean(form.formData[name!] ?? false)\n : propChecked;\n\n function handleChange(e: React.ChangeEvent<HTMLInputElement>) {\n const newChecked = e.target.checked;\n if (useFormData) {\n form.handleChange(name!, newChecked);\n } else {\n onChanged({name, checked: newChecked});\n }\n }\n\n // Use the id injected by pi/field; fall back to a local id when standalone.\n const selfId = `${cardName}-${name ?? \"checkbox\"}`;\n const fieldId = injectedId ?? selfId;\n\n return (\n <div data-pihanga={cardName} className=\"flex items-center gap-2\">\n <input\n id={fieldId}\n type=\"checkbox\"\n checked={checked}\n onChange={handleChange}\n disabled={disabled}\n aria-invalid={invalid || undefined}\n className=\"h-4 w-4 rounded border-input accent-primary disabled:cursor-not-allowed disabled:opacity-50\"\n />\n {label && (\n <label\n htmlFor={fieldId}\n className=\"text-sm leading-none cursor-pointer select-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\"\n >\n {label}\n </label>\n )}\n </div>\n );\n};\n"],"mappings":";;;;AAKA,IAAa,KACX,MACoB;CACpB,IAAM,EACJ,SACA,SAAS,IAAc,IACvB,aACA,UACA,aACA,iBACE,GAKE,IAAc,EAAwB,IACtC,IAAU,EAAS,EAA8B,SAGjD,IAAO,EAAe,GACtB,IAAc,EAAK,YAAY,EAAQ,GAEvC,IAAU,IACZ,GAAQ,EAAK,SAAS,MAAU,MAChC;CAEJ,SAAS,EAAa,GAAwC;EAC5D,IAAM,IAAa,EAAE,OAAO;EAC5B,AAAI,IACF,EAAK,aAAa,GAAO,CAAU,IAEnC,EAAU;GAAC;GAAM,SAAS;EAAU,CAAC;CAEzC;CAGA,IAAM,IAAS,GAAG,EAAS,GAAG,KAAQ,cAChC,IAAU,KAAc;CAE9B,OACE,kBAAC,OAAD;EAAK,gBAAc;EAAU,WAAU;YAAvC,CACE,kBAAC,SAAD;GACE,IAAI;GACJ,MAAK;GACI;GACT,UAAU;GACA;GACV,gBAAc,KAAW,KAAA;GACzB,WAAU;EACX,CAAA,GACA,KACC,kBAAC,SAAD;GACE,SAAS;GACT,WAAU;aAET;EACI,CAAA,CAEN;;AAET"}
1
+ {"version":3,"file":"checkbox.component.js","names":[],"sources":["../../../src/cards/checkbox/checkbox.component.tsx"],"sourcesContent":["import React from \"react\";\nimport {type PiCardProps} from \"@pihanga2/core\";\nimport {useFormContext} from \"@/cards/form/form.context\";\nimport type {PiCheckboxEvents, PiCheckboxProps} from \"./checkbox.types\";\n\nexport const CheckboxComponent = (\n props: PiCardProps<PiCheckboxProps, PiCheckboxEvents>,\n): React.ReactNode => {\n const {\n name,\n checked: propChecked = false,\n disabled,\n label,\n cardName,\n onChanged,\n } = props;\n\n // `id` and `invalid` may be injected by a parent pi/field card via\n // Pihanga's extra-prop forwarding. They are not in the official type so\n // we read them through an escape hatch.\n const injectedId = (props as {id?: string}).id;\n const invalid = Boolean((props as {invalid?: boolean}).invalid);\n\n // Detect if we are inside a pi/form card via React context.\n const form = useFormContext();\n const useFormData = form.isInForm && Boolean(name);\n\n const checked = useFormData\n ? Boolean(form.formData[name!] ?? false)\n : propChecked;\n\n function handleChange(e: React.ChangeEvent<HTMLInputElement>) {\n const newChecked = e.target.checked;\n if (useFormData) {\n form.handleChange(name!, newChecked);\n } else {\n onChanged({name, checked: newChecked});\n }\n }\n\n // Use the id injected by pi/field; fall back to a local id when standalone.\n const selfId = `${cardName}-${name ?? \"checkbox\"}`;\n const fieldId = injectedId ?? selfId;\n\n return (\n <div data-pihanga={cardName} className=\"flex items-center gap-2\">\n <input\n id={fieldId}\n type=\"checkbox\"\n checked={checked}\n onChange={handleChange}\n disabled={disabled}\n aria-invalid={invalid || undefined}\n className=\"h-4 w-4 rounded border-input accent-primary disabled:cursor-not-allowed disabled:opacity-50\"\n />\n {label && (\n <label\n htmlFor={fieldId}\n className=\"text-sm leading-none cursor-pointer select-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\"\n >\n {label}\n </label>\n )}\n </div>\n );\n};\n"],"mappings":";;;;;AAKA,IAAa,KACX,MACoB;CACpB,IAAM,EACJ,SACA,SAAS,IAAc,IACvB,aACA,UACA,aACA,iBACE,GAKE,IAAc,EAAwB,IACtC,IAAU,EAAS,EAA8B,SAGjD,IAAO,EAAe,GACtB,IAAc,EAAK,YAAY,EAAQ,GAEvC,IAAU,IACZ,GAAQ,EAAK,SAAS,MAAU,MAChC;CAEJ,SAAS,EAAa,GAAwC;EAC5D,IAAM,IAAa,EAAE,OAAO;EAC5B,AAAI,IACF,EAAK,aAAa,GAAO,CAAU,IAEnC,EAAU;GAAC;GAAM,SAAS;EAAU,CAAC;CAEzC;CAGA,IAAM,IAAS,GAAG,EAAS,GAAG,KAAQ,cAChC,IAAU,KAAc;CAE9B,OACE,kBAAC,OAAD;EAAK,gBAAc;EAAU,WAAU;YAAvC,CACE,kBAAC,SAAD;GACE,IAAI;GACJ,MAAK;GACI;GACT,UAAU;GACA;GACV,gBAAc,KAAW,KAAA;GACzB,WAAU;EACX,CAAA,GACA,KACC,kBAAC,SAAD;GACE,SAAS;GACT,WAAU;aAET;EACI,CAAA,CAEN;;AAET"}
@@ -3,6 +3,10 @@ export declare const Checkbox: <S extends import('@pihanga2/core').ReduxState>(p
3
3
  export declare const PI_CHECKBOX_ACTION: {
4
4
  CHANGED: string;
5
5
  };
6
+ export declare const onCheckboxChanged: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
7
+ cardID: string;
8
+ } & PiCheckboxChangedEvent>) => void;
9
+ /** @deprecated Use `onCheckboxChanged` instead. */
6
10
  export declare const onPiCheckboxChanged: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
7
11
  cardID: string;
8
12
  } & PiCheckboxChangedEvent>) => 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/checkbox/checkbox.types.ts
3
- var r = "pi/checkbox", i = e(r), a = n(r, ["changed"]), o = t(a.CHANGED);
3
+ var r = "pi/checkbox", i = e(r), a = n(r, ["changed"]), o = t(a.CHANGED), s = o;
4
4
  //#endregion
5
- export { i as Checkbox, a as PI_CHECKBOX_ACTION, r as PI_CHECKBOX_CARD, o as onPiCheckboxChanged };
5
+ export { i as Checkbox, a as PI_CHECKBOX_ACTION, r as PI_CHECKBOX_CARD, o as onCheckboxChanged, s as onPiCheckboxChanged };
6
6
 
7
7
  //# sourceMappingURL=checkbox.types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"checkbox.types.js","names":[],"sources":["../../../src/cards/checkbox/checkbox.types.ts"],"sourcesContent":["import {\n createCardDeclaration,\n createOnAction,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const PI_CHECKBOX_CARD = \"pi/checkbox\";\n\nexport const Checkbox = createCardDeclaration<\n PiCheckboxProps,\n PiCheckboxEvents\n>(PI_CHECKBOX_CARD);\n\nexport const PI_CHECKBOX_ACTION = registerActions(PI_CHECKBOX_CARD, [\n \"changed\",\n]);\n\nexport const onPiCheckboxChanged = createOnAction<PiCheckboxChangedEvent>(\n PI_CHECKBOX_ACTION.CHANGED,\n);\n\nexport type PiCheckboxProps = {\n /**\n * Field name used to bind to FormContext when inside a pi/form card.\n * When provided the component reads its checked state from form data and\n * writes back via form.handleChange.\n */\n name?: string;\n\n /**\n * Controlled checked state used in standalone mode (outside a Form).\n * Ignored when `name` is set and the component is inside a pi/form.\n */\n checked?: boolean;\n\n /** When true, the checkbox is disabled and non-interactive. */\n disabled?: boolean;\n\n /**\n * Optional label text rendered next to the checkbox.\n * The label is automatically associated with the input via `htmlFor`.\n */\n label?: string;\n};\n\nexport type PiCheckboxChangedEvent = {\n /** Field name, mirrors the `name` prop if provided. */\n name?: string;\n /** New checked state after the change. */\n checked: boolean;\n};\n\nexport type PiCheckboxEvents = {\n onChanged: PiCheckboxChangedEvent;\n};\n"],"mappings":";;AAMA,IAAa,IAAmB,eAEnB,IAAW,EAGtB,CAAgB,GAEL,IAAqB,EAAgB,GAAkB,CAClE,SACF,CAAC,GAEY,IAAsB,EACjC,EAAmB,OACrB"}
1
+ {"version":3,"file":"checkbox.types.js","names":[],"sources":["../../../src/cards/checkbox/checkbox.types.ts"],"sourcesContent":["import {\n createCardDeclaration,\n createOnAction,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const PI_CHECKBOX_CARD = \"pi/checkbox\";\n\nexport const Checkbox = createCardDeclaration<\n PiCheckboxProps,\n PiCheckboxEvents\n>(PI_CHECKBOX_CARD);\n\nexport const PI_CHECKBOX_ACTION = registerActions(PI_CHECKBOX_CARD, [\n \"changed\",\n]);\n\nexport const onCheckboxChanged = createOnAction<PiCheckboxChangedEvent>(\n PI_CHECKBOX_ACTION.CHANGED,\n);\n\n/** @deprecated Use `onCheckboxChanged` instead. */\nexport const onPiCheckboxChanged = onCheckboxChanged;\n\nexport type PiCheckboxProps = {\n /**\n * Field name used to bind to FormContext when inside a pi/form card.\n * When provided the component reads its checked state from form data and\n * writes back via form.handleChange.\n */\n name?: string;\n\n /**\n * Controlled checked state used in standalone mode (outside a Form).\n * Ignored when `name` is set and the component is inside a pi/form.\n */\n checked?: boolean;\n\n /** When true, the checkbox is disabled and non-interactive. */\n disabled?: boolean;\n\n /**\n * Optional label text rendered next to the checkbox.\n * The label is automatically associated with the input via `htmlFor`.\n */\n label?: string;\n};\n\nexport type PiCheckboxChangedEvent = {\n /** Field name, mirrors the `name` prop if provided. */\n name?: string;\n /** New checked state after the change. */\n checked: boolean;\n};\n\nexport type PiCheckboxEvents = {\n onChanged: PiCheckboxChangedEvent;\n};\n"],"mappings":";;AAMA,IAAa,IAAmB,eAEnB,IAAW,EAGtB,CAAgB,GAEL,IAAqB,EAAgB,GAAkB,CAClE,SACF,CAAC,GAEY,IAAoB,EAC/B,EAAmB,OACrB,GAGa,IAAsB"}
@@ -1,13 +1,13 @@
1
1
  import { CheckboxComponent as e } from "./checkbox.component.js";
2
- import { Checkbox as t, PI_CHECKBOX_ACTION as n, PI_CHECKBOX_CARD as r, onPiCheckboxChanged as i } from "./checkbox.types.js";
3
- import { actionTypesToEvents as a, registerCardComponent as o } from "@pihanga2/core";
2
+ import { Checkbox as t, PI_CHECKBOX_ACTION as n, PI_CHECKBOX_CARD as r, onCheckboxChanged as i, onPiCheckboxChanged as a } from "./checkbox.types.js";
3
+ import { actionTypesToEvents as o, registerCardComponent as s } from "@pihanga2/core";
4
4
  //#region src/cards/checkbox/index.ts
5
- o({
5
+ s({
6
6
  name: r,
7
7
  component: e,
8
- events: a(n)
8
+ events: o(n)
9
9
  });
10
10
  //#endregion
11
- export { t as Checkbox, n as PI_CHECKBOX_ACTION, r as PI_CHECKBOX_CARD, i as onPiCheckboxChanged };
11
+ export { t as Checkbox, n as PI_CHECKBOX_ACTION, r as PI_CHECKBOX_CARD, i as onCheckboxChanged, a as onPiCheckboxChanged };
12
12
 
13
13
  //# sourceMappingURL=index.js.map
@@ -2,15 +2,18 @@ import { PiCardRef } from '@pihanga2/core';
2
2
  export declare const CONDITIONAL_CARD = "shad/conditional";
3
3
  export declare const Conditional: <S extends import('@pihanga2/core').ReduxState>(p: import('@pihanga2/core').PiMapProps<ConditionalProps, S, {}>) => import('@pihanga2/core').PiCardDef;
4
4
  /**
5
- * Named Tailwind-compatible breakpoints or a custom pixel expression.
5
+ * Named Tailwind-compatible breakpoints.
6
6
  *
7
- * Named breakpoints (Tailwind CSS defaults)
8
- * ─────────────────────────────────────────
7
+ * `xs` → viewport < 640 px (mobile-first default)
9
8
  * `sm` → viewport ≥ 640 px
10
9
  * `md` → viewport ≥ 768 px
11
10
  * `lg` → viewport ≥ 1024 px
12
11
  * `xl` → viewport ≥ 1280 px
13
12
  * `2xl` → viewport ≥ 1536 px
13
+ */
14
+ export type BreakpointName = "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
15
+ /**
16
+ * A `BreakpointName` **or** a custom pixel expression.
14
17
  *
15
18
  * Pixel expressions
16
19
  * ─────────────────
@@ -20,7 +23,19 @@ export declare const Conditional: <S extends import('@pihanga2/core').ReduxState
20
23
  * `<=1024px` → viewport ≤ 1024 px
21
24
  * `<1024px` → viewport < 1024 px (max-width: 1023px)
22
25
  */
23
- export type BreakpointSelector = "sm" | "md" | "lg" | "xl" | "2xl" | (string & Record<never, never>);
26
+ export type BreakpointSelector = BreakpointName | (string & Record<never, never>);
27
+ /**
28
+ * A partial map from each named breakpoint to a value of type `T`.
29
+ *
30
+ * Useful for props that need per-breakpoint configuration — e.g. the CSS
31
+ * `display` value to apply at each viewport width.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * const display: BreakpointMap = { xs: "none", md: "flex" };
36
+ * ```
37
+ */
38
+ export type BreakpointMap<T = string> = Partial<Record<BreakpointName, T>>;
24
39
  /**
25
40
  * Props for the `shad/conditional` card.
26
41
  *
@@ -91,7 +106,7 @@ export type ConditionalProps = {
91
106
  * to `window.matchMedia` and reactively shows/hides the content card
92
107
  * whenever the viewport crosses the breakpoint.
93
108
  *
94
- * Supported values: `sm` | `md` | `lg` | `xl` | `2xl` (Tailwind),
109
+ * Supported values: `xs` | `sm` | `md` | `lg` | `xl` | `2xl` (Tailwind),
95
110
  * or pixel expressions such as `>400px`, `>=640px`, `<768px`, `<=1024px`,
96
111
  * `400px`.
97
112
  *
@@ -1 +1 @@
1
- {"version":3,"file":"conditional.types.js","names":[],"sources":["../../../src/cards/conditional/conditional.types.ts"],"sourcesContent":["import {createCardDeclaration} from \"@pihanga2/core\";\nimport type {PiCardRef} from \"@pihanga2/core\";\n\n// ── Card id ───────────────────────────────────────────────────────────────────\n\nexport const CONDITIONAL_CARD = \"shad/conditional\";\n\n// ── Card declaration factory ──────────────────────────────────────────────────\n\nexport const Conditional =\n createCardDeclaration<ConditionalProps>(CONDITIONAL_CARD);\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\n/**\n * Named Tailwind-compatible breakpoints or a custom pixel expression.\n *\n * Named breakpoints (Tailwind CSS defaults)\n * ─────────────────────────────────────────\n * `sm` → viewport ≥ 640 px\n * `md` → viewport ≥ 768 px\n * `lg` → viewport ≥ 1024 px\n * `xl` → viewport ≥ 1280 px\n * `2xl` → viewport ≥ 1536 px\n *\n * Pixel expressions\n * ─────────────────\n * `400px` → viewport ≥ 400 px (bare value = min-width)\n * `>=640px` → viewport ≥ 640 px\n * `>640px` → viewport > 640 px (min-width: 641px)\n * `<=1024px` → viewport ≤ 1024 px\n * `<1024px` → viewport < 1024 px (max-width: 1023px)\n */\nexport type BreakpointSelector =\n | \"sm\"\n | \"md\"\n | \"lg\"\n | \"xl\"\n | \"2xl\"\n | (string & Record<never, never>); // allows arbitrary strings with IDE hints\n\n// ── Props ─────────────────────────────────────────────────────────────────────\n\n/**\n * Props for the `shad/conditional` card.\n *\n * The card renders `content` only when the combined visibility condition is\n * `true`; it renders nothing otherwise. This is a transparent pass-through —\n * no extra DOM wrapper is added.\n *\n * ## Modes\n *\n * ### 1 · Manual boolean (existing behaviour)\n *\n * Drive `show` from a `memo()` selector so the card reactively mounts/unmounts\n * as state changes:\n *\n * ```ts\n * import {memo, registerCard} from \"@pihanga2/core\";\n * import {Conditional} from \"@/cards/conditional\";\n *\n * registerCard(\"myApp/hint\", Conditional({\n * show: memo((s: AppState) => s.items.length === 0 && !s.isLoading),\n * content: \"myApp/emptyStateHint\",\n * }));\n * ```\n *\n * ### 2 · Breakpoint-based auto-selection (new)\n *\n * Set `showOn` to a breakpoint name or pixel expression. The component\n * subscribes to `window.matchMedia` and automatically mounts/unmounts the\n * content card as the viewport crosses the breakpoint — no state, no memo:\n *\n * ```ts\n * // Show only on tablet-sized screens and up\n * registerCard(\"myApp/sidebar\", Conditional({\n * showOn: \"md\",\n * content: \"myApp/desktopSidebar\",\n * }));\n *\n * // Show only on narrow viewports (mobile drawer)\n * registerCard(\"myApp/mobileNav\", Conditional({\n * showOn: \"<768px\",\n * content: \"myApp/drawer\",\n * }));\n * ```\n *\n * ### 3 · Combined\n *\n * Both conditions are ANDed — content renders only when the breakpoint matches\n * **and** `show` is `true`:\n *\n * ```ts\n * registerCard(\"myApp/adminSidebar\", Conditional({\n * show: memo((s: AppState) => s.isAdmin),\n * showOn: \"lg\",\n * content: \"myApp/adminPanel\",\n * }));\n * ```\n */\nexport type ConditionalProps = {\n /**\n * Manual boolean gate. When omitted it defaults to `true` so that a\n * `showOn`-only card does not need to set it explicitly.\n *\n * Drive with `memo()` for reactive mount/unmount behaviour.\n */\n show?: boolean;\n\n /**\n * Viewport-width breakpoint selector. When set, the component subscribes\n * to `window.matchMedia` and reactively shows/hides the content card\n * whenever the viewport crosses the breakpoint.\n *\n * Supported values: `sm` | `md` | `lg` | `xl` | `2xl` (Tailwind),\n * or pixel expressions such as `>400px`, `>=640px`, `<768px`, `<=1024px`,\n * `400px`.\n *\n * When both `show` and `showOn` are provided the content is rendered only\n * when **both** conditions are satisfied.\n *\n * By default the breakpoint is evaluated against the **viewport** width via\n * `window.matchMedia`. Set `containerQuery: true` to evaluate it against\n * the width of the **enclosing container** instead (uses `ResizeObserver`).\n */\n showOn?: BreakpointSelector;\n\n /**\n * When `true`, the `showOn` breakpoint is measured against the width of the\n * component's **enclosing container** rather than the viewport.\n *\n * Internally the component renders a transparent `<div style=\"width:100%\">`\n * wrapper and observes it with `ResizeObserver`. This means a single extra\n * DOM node is added when `containerQuery` is `true`.\n *\n * Has no effect when `showOn` is not set.\n *\n * @default false\n */\n containerQuery?: boolean;\n\n /** The card to render when the visibility condition is met. */\n content: PiCardRef;\n};\n"],"mappings":";;AAKA,IAAa,IAAmB,oBAInB,IACX,EAAwC,CAAgB"}
1
+ {"version":3,"file":"conditional.types.js","names":[],"sources":["../../../src/cards/conditional/conditional.types.ts"],"sourcesContent":["import {createCardDeclaration} from \"@pihanga2/core\";\nimport type {PiCardRef} from \"@pihanga2/core\";\n\n// ── Card id ───────────────────────────────────────────────────────────────────\n\nexport const CONDITIONAL_CARD = \"shad/conditional\";\n\n// ── Card declaration factory ──────────────────────────────────────────────────\n\nexport const Conditional =\n createCardDeclaration<ConditionalProps>(CONDITIONAL_CARD);\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\n/**\n * Named Tailwind-compatible breakpoints.\n *\n * `xs` → viewport < 640 px (mobile-first default)\n * `sm` → viewport ≥ 640 px\n * `md` → viewport ≥ 768 px\n * `lg` → viewport ≥ 1024 px\n * `xl` → viewport ≥ 1280 px\n * `2xl` → viewport ≥ 1536 px\n */\nexport type BreakpointName = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\";\n\n/**\n * A `BreakpointName` **or** a custom pixel expression.\n *\n * Pixel expressions\n * ─────────────────\n * `400px` → viewport ≥ 400 px (bare value = min-width)\n * `>=640px` → viewport ≥ 640 px\n * `>640px` → viewport > 640 px (min-width: 641px)\n * `<=1024px` → viewport ≤ 1024 px\n * `<1024px` → viewport < 1024 px (max-width: 1023px)\n */\nexport type BreakpointSelector =\n | BreakpointName\n | (string & Record<never, never>); // allows arbitrary strings with IDE hints\n\n/**\n * A partial map from each named breakpoint to a value of type `T`.\n *\n * Useful for props that need per-breakpoint configuration — e.g. the CSS\n * `display` value to apply at each viewport width.\n *\n * @example\n * ```ts\n * const display: BreakpointMap = { xs: \"none\", md: \"flex\" };\n * ```\n */\nexport type BreakpointMap<T = string> = Partial<Record<BreakpointName, T>>;\n\n// ── Props ─────────────────────────────────────────────────────────────────────\n\n/**\n * Props for the `shad/conditional` card.\n *\n * The card renders `content` only when the combined visibility condition is\n * `true`; it renders nothing otherwise. This is a transparent pass-through —\n * no extra DOM wrapper is added.\n *\n * ## Modes\n *\n * ### 1 · Manual boolean (existing behaviour)\n *\n * Drive `show` from a `memo()` selector so the card reactively mounts/unmounts\n * as state changes:\n *\n * ```ts\n * import {memo, registerCard} from \"@pihanga2/core\";\n * import {Conditional} from \"@/cards/conditional\";\n *\n * registerCard(\"myApp/hint\", Conditional({\n * show: memo((s: AppState) => s.items.length === 0 && !s.isLoading),\n * content: \"myApp/emptyStateHint\",\n * }));\n * ```\n *\n * ### 2 · Breakpoint-based auto-selection (new)\n *\n * Set `showOn` to a breakpoint name or pixel expression. The component\n * subscribes to `window.matchMedia` and automatically mounts/unmounts the\n * content card as the viewport crosses the breakpoint — no state, no memo:\n *\n * ```ts\n * // Show only on tablet-sized screens and up\n * registerCard(\"myApp/sidebar\", Conditional({\n * showOn: \"md\",\n * content: \"myApp/desktopSidebar\",\n * }));\n *\n * // Show only on narrow viewports (mobile drawer)\n * registerCard(\"myApp/mobileNav\", Conditional({\n * showOn: \"<768px\",\n * content: \"myApp/drawer\",\n * }));\n * ```\n *\n * ### 3 · Combined\n *\n * Both conditions are ANDed — content renders only when the breakpoint matches\n * **and** `show` is `true`:\n *\n * ```ts\n * registerCard(\"myApp/adminSidebar\", Conditional({\n * show: memo((s: AppState) => s.isAdmin),\n * showOn: \"lg\",\n * content: \"myApp/adminPanel\",\n * }));\n * ```\n */\nexport type ConditionalProps = {\n /**\n * Manual boolean gate. When omitted it defaults to `true` so that a\n * `showOn`-only card does not need to set it explicitly.\n *\n * Drive with `memo()` for reactive mount/unmount behaviour.\n */\n show?: boolean;\n\n /**\n * Viewport-width breakpoint selector. When set, the component subscribes\n * to `window.matchMedia` and reactively shows/hides the content card\n * whenever the viewport crosses the breakpoint.\n *\n * Supported values: `xs` | `sm` | `md` | `lg` | `xl` | `2xl` (Tailwind),\n * or pixel expressions such as `>400px`, `>=640px`, `<768px`, `<=1024px`,\n * `400px`.\n *\n * When both `show` and `showOn` are provided the content is rendered only\n * when **both** conditions are satisfied.\n *\n * By default the breakpoint is evaluated against the **viewport** width via\n * `window.matchMedia`. Set `containerQuery: true` to evaluate it against\n * the width of the **enclosing container** instead (uses `ResizeObserver`).\n */\n showOn?: BreakpointSelector;\n\n /**\n * When `true`, the `showOn` breakpoint is measured against the width of the\n * component's **enclosing container** rather than the viewport.\n *\n * Internally the component renders a transparent `<div style=\"width:100%\">`\n * wrapper and observes it with `ResizeObserver`. This means a single extra\n * DOM node is added when `containerQuery` is `true`.\n *\n * Has no effect when `showOn` is not set.\n *\n * @default false\n */\n containerQuery?: boolean;\n\n /** The card to render when the visibility condition is met. */\n content: PiCardRef;\n};\n"],"mappings":";;AAKA,IAAa,IAAmB,oBAInB,IACX,EAAwC,CAAgB"}
@@ -7,6 +7,7 @@ export * from './dataTable/index.js';
7
7
  export * from './dialog/index.js';
8
8
  export * from './dropDownMenu/index.js';
9
9
  export * from './field/index.js';
10
+ export * from './fileDrop/index.js';
10
11
  export * from './flexGrid/index.js';
11
12
  export * from './form/index.js';
12
13
  export * from './framework/index.js';
@@ -20,6 +21,8 @@ export * from './navbarSearch/index.js';
20
21
  export * from './pageWithNavbar/index.js';
21
22
  export * from './pasteTarget/index.js';
22
23
  export * from './select/index.js';
24
+ export * from './slider/index.js';
25
+ export * from './sliderValue/index.js';
23
26
  export * from './stack/index.js';
24
27
  export * from './stepper/index.js';
25
28
  export * from './switch/index.js';
@@ -5,57 +5,64 @@ import "./box/index.js";
5
5
  import { Button as i, PI_BUTTON_ACTION as a, PI_BUTTON_CARD as o, onButtonClicked as s, onPiButtonClicked as c } from "./button/button.types.js";
6
6
  import "./button/index.js";
7
7
  import { FormContext as l, useFormContext as u } from "./form/form.context.js";
8
- import { Checkbox as d, PI_CHECKBOX_ACTION as f, PI_CHECKBOX_CARD as p, onPiCheckboxChanged as m } from "./checkbox/checkbox.types.js";
8
+ import { Checkbox as d, PI_CHECKBOX_ACTION as f, PI_CHECKBOX_CARD as p, onCheckboxChanged as m, onPiCheckboxChanged as h } from "./checkbox/checkbox.types.js";
9
9
  import "./checkbox/index.js";
10
- import { CONDITIONAL_CARD as h, Conditional as g } from "./conditional/conditional.types.js";
10
+ import { CONDITIONAL_CARD as g, Conditional as _ } from "./conditional/conditional.types.js";
11
11
  import "./conditional/index.js";
12
- import { DATA_TABLE_ACTION as _, DATA_TABLE_CARD as v, DATA_TABLE_ROW_DETAIL_CARD as y, DataTable as b, DataTableRowDetail as x, onDataTableHideDetail as S, onDataTablePageChanged as C, onDataTableRowClicked as w, onDataTableShowDetail as T, onDataTableSortChanged as E } from "./dataTable/dataTable.types.js";
12
+ import { DATA_TABLE_ACTION as v, DATA_TABLE_CARD as y, DATA_TABLE_ROW_DETAIL_CARD as b, DataTable as x, DataTableRowDetail as S, onDataTableHideDetail as C, onDataTablePageChanged as w, onDataTableRowClicked as T, onDataTableShowDetail as E, onDataTableSortChanged as D } from "./dataTable/dataTable.types.js";
13
13
  import "./dataTable/index.js";
14
- import { Dialog as D, PI_DIALOG_ACTION as O, PI_DIALOG_CARD as k, onDialogClosed as A, onDialogOpenChanged as j, onDialogOpened as M } from "./dialog/dialog.types.js";
14
+ import { Dialog as O, PI_DIALOG_ACTION as k, PI_DIALOG_CARD as A, onDialogClosed as j, onDialogOpenChanged as M, onDialogOpened as N } from "./dialog/dialog.types.js";
15
15
  import "./dialog/index.js";
16
- import { DROP_DOWN_MENU_ACTION as N, DROP_DOWN_MENU_CARD as P, DropDownMenu as F, onDropDownMenuClicked as I } from "./dropDownMenu/drop-down.types.js";
16
+ import { DROP_DOWN_MENU_ACTION as P, DROP_DOWN_MENU_CARD as F, DropDownMenu as I, onDropDownMenuClicked as L } from "./dropDownMenu/drop-down.types.js";
17
17
  import "./dropDownMenu/index.js";
18
- import { Field as L, PI_FIELD_CARD as R } from "./field/field.types.js";
18
+ import { Field as R, PI_FIELD_CARD as z } from "./field/field.types.js";
19
19
  import "./field/index.js";
20
- import { FLEX_GRID_CARD as z, FlexGrid as B } from "./flexGrid/flexGrid.types.js";
20
+ import { DEF_FILE_DROP_FILE_TYPES as B, FILE_DROP_ACTION as V, FILE_DROP_CARD as H, FileDrop as U, onFileDropError as W, onFileDropped as G } from "./fileDrop/fileDrop.types.js";
21
+ import { get_last_dropped as K } from "./fileDrop/fileDrop.component.js";
22
+ import "./fileDrop/index.js";
23
+ import { FLEX_GRID_CARD as q, FlexGrid as J } from "./flexGrid/flexGrid.types.js";
21
24
  import "./flexGrid/index.js";
22
- import { Form as V, PI_FORM_ACTION as H, PI_FORM_CARD as U, onPiFormSubmitted as W } from "./form/form.types.js";
25
+ import { Form as Y, PI_FORM_ACTION as X, PI_FORM_CARD as Z, onFormSubmitted as Q, onPiFormSubmitted as $ } from "./form/form.types.js";
23
26
  import "./form/index.js";
24
- import { SdFramework as G } from "./framework/index.js";
25
- import { PI_INPUT_ACTION as K, PI_INPUT_CARD as q, PiInput as J, onPiInputChanged as Y, onPiInputCommitted as X } from "./input/input.types.js";
27
+ import { SdFramework as ee } from "./framework/index.js";
28
+ import { PI_INPUT_ACTION as te, PI_INPUT_CARD as ne, PiInput as re, onInputChanged as ie, onInputCommitted as ae, onPiInputChanged as oe, onPiInputCommitted as se } from "./input/input.types.js";
26
29
  import "./input/index.js";
27
- import { LIST_ACTION as Z, LIST_CARD as Q, List as $, onListItemClicked as ee } from "./list/list.types.js";
30
+ import { LIST_ACTION as ce, LIST_CARD as le, List as ue, onListItemClicked as de } from "./list/list.types.js";
28
31
  import "./list/index.js";
29
- import { LOADING_OVERLAY_CARD as te, LoadingOverlay as ne } from "./loadingOverlay/loadingOverlay.types.js";
32
+ import { LOADING_OVERLAY_CARD as fe, LoadingOverlay as pe } from "./loadingOverlay/loadingOverlay.types.js";
30
33
  import "./loadingOverlay/index.js";
31
- import { LOADING_SKELETON_CARD as re, LoadingSkeleton as ie } from "./loadingSkeleton/loading-skeleton.types.js";
34
+ import { LOADING_SKELETON_CARD as me, LoadingSkeleton as he } from "./loadingSkeleton/loading-skeleton.types.js";
32
35
  import "./loadingSkeleton/index.js";
33
- import { MENU_ACTION as ae, MENU_CARD as oe, Menu as se, onMenuClicked as ce } from "./menu/menu.types.js";
36
+ import { MENU_ACTION as ge, MENU_CARD as _e, Menu as ve, onMenuClicked as ye } from "./menu/menu.types.js";
34
37
  import "./menu/index.js";
35
- import { MODE_TOGGLE_ACTION as le, MODE_TOGGLE_CARD as ue, ModeToggle as de, onModeToggleChanged as fe } from "./modeToggle/mode-toggle.types.js";
38
+ import { MODE_TOGGLE_ACTION as be, MODE_TOGGLE_CARD as xe, ModeToggle as Se, onModeToggleChanged as Ce } from "./modeToggle/mode-toggle.types.js";
36
39
  import "./modeToggle/index.js";
37
- import { NAVBAR_SEARCH_ACTION as pe, NAVBAR_SEARCH_CARD as me, NavbarSearch as he, onNavbarSearchFocus as ge, onNavbarSearchItems as _e, onNavbarSearchSubmit as ve } from "./navbarSearch/navbarSearch.type.js";
40
+ import { NAVBAR_SEARCH_ACTION as we, NAVBAR_SEARCH_CARD as Te, NavbarSearch as Ee, onNavbarSearchFocus as De, onNavbarSearchItems as Oe, onNavbarSearchSubmit as ke } from "./navbarSearch/navbarSearch.type.js";
38
41
  import "./navbarSearch/index.js";
39
- import { PAGE_WITH_NAVBAR_ACTION as ye, PAGE_WITH_NAVBAR_CARD as be, PageWithNavbar as xe, onPageWithNavbarNavigateTo as Se } from "./pageWithNavbar/pageWithNavbar.type.js";
40
- import { SdPageWithNavbar as Ce } from "./pageWithNavbar/index.js";
41
- import { DEF_ERROR_COLOR as we, DEF_EVENT_DURATION_SECONDS as Te, DEF_HEIGHT as Ee, DEF_OVERLAY_OPACITY as De, DEF_PASTE_FIRST_REMINDER as Oe, DEF_PASTE_TARGET_FILE_TYPES as ke, DEF_SUCCESS_COLOR as Ae, PASTE_TARGET_ACTION as je, PASTE_TARGET_CARD as Me, PasteTarget as Ne, onContentPasted as Pe, onPasteError as Fe } from "./pasteTarget/pasteTarget.types.js";
42
+ import { PAGE_WITH_NAVBAR_ACTION as Ae, PAGE_WITH_NAVBAR_CARD as je, PageWithNavbar as Me, onPageWithNavbarNavigateTo as Ne } from "./pageWithNavbar/pageWithNavbar.type.js";
43
+ import { SdPageWithNavbar as Pe } from "./pageWithNavbar/index.js";
44
+ import { DEF_ERROR_COLOR as Fe, DEF_EVENT_DURATION_SECONDS as Ie, DEF_HEIGHT as Le, DEF_OVERLAY_OPACITY as Re, DEF_PASTE_FIRST_REMINDER as ze, DEF_PASTE_TARGET_FILE_TYPES as Be, DEF_SUCCESS_COLOR as Ve, PASTE_TARGET_ACTION as He, PASTE_TARGET_CARD as Ue, PasteTarget as We, onContentPasted as Ge, onPasteError as Ke } from "./pasteTarget/pasteTarget.types.js";
42
45
  import "./pasteTarget/index.js";
43
- import { PI_SELECT_ACTION as Ie, PI_SELECT_CARD as Le, Select as Re, onPiSelectChanged as ze, onPiSelectClosed as Be, onPiSelectOpened as Ve } from "./select/select.types.js";
46
+ import { PI_SELECT_ACTION as qe, PI_SELECT_CARD as Je, Select as Ye, onPiSelectChanged as Xe, onPiSelectClosed as Ze, onPiSelectOpened as Qe, onSelectChanged as $e, onSelectClosed as et, onSelectOpened as tt } from "./select/select.types.js";
44
47
  import "./select/index.js";
45
- import { STACK_CARD as He, Stack as Ue } from "./stack/stack.types.js";
48
+ import { PI_SLIDER_ACTION as nt, PI_SLIDER_CARD as rt, Slider as it, onPiSliderChanged as at, onPiSliderCommitted as ot, onSliderChanged as st, onSliderCommitted as ct } from "./slider/slider.types.js";
49
+ import "./slider/index.js";
50
+ import { PI_SLIDER_VALUE_CARD as lt, SliderValue as ut } from "./sliderValue/sliderValue.types.js";
51
+ import "./sliderValue/index.js";
52
+ import { STACK_CARD as dt, Stack as ft } from "./stack/stack.types.js";
46
53
  import "./stack/index.js";
47
- import { STEPPER_ACTION as We, STEPPER_CARD as Ge, Stepper as Ke, onStepperStepClicked as qe } from "./stepper/stepper.types.js";
54
+ import { STEPPER_ACTION as pt, STEPPER_CARD as mt, Stepper as ht, onStepperStepClicked as gt } from "./stepper/stepper.types.js";
48
55
  import "./stepper/index.js";
49
- import { PI_SWITCH_ACTION as Je, PI_SWITCH_CARD as Ye, Switch as Xe, onPiSwitchChanged as Ze } from "./switch/switch.types.js";
56
+ import { PI_SWITCH_ACTION as _t, PI_SWITCH_CARD as vt, Switch as yt, onPiSwitchChanged as bt, onSwitchChanged as xt } from "./switch/switch.types.js";
50
57
  import "./switch/index.js";
51
- import { SdTabs as Qe, TABS_ACTION as $e, TABS_CARD as et, Tabs as tt, onTabsTabChanged as nt } from "./tabs/tabs.types.js";
58
+ import { SdTabs as St, TABS_ACTION as Ct, TABS_CARD as wt, Tabs as Tt, onTabsTabChanged as Et } from "./tabs/tabs.types.js";
52
59
  import "./tabs/index.js";
53
- import { PI_TEXT_FIELD_ACTION as rt, PI_TEXT_FIELD_CARD as it, TextField as at, onPiTextFieldChanged as ot } from "./textField/textField.types.js";
60
+ import { PI_TEXT_FIELD_ACTION as Dt, PI_TEXT_FIELD_CARD as Ot, TextField as kt, onPiTextFieldChanged as At, onTextFieldChanged as jt } from "./textField/textField.types.js";
54
61
  import "./textField/index.js";
55
- import { PI_TOAST_ACTION as st, PI_TOAST_CARD as ct, TOAST_OP_ACTION as lt, Toast as ut, dispatchShowToast as dt, onPiToastClosed as ft, onShowToast as pt } from "./toast/toast.types.js";
62
+ import { PI_TOAST_ACTION as Mt, PI_TOAST_CARD as Nt, TOAST_OP_ACTION as Pt, Toast as Ft, dispatchShowToast as It, onPiToastClosed as Lt, onShowToast as Rt, onToastClosed as zt } from "./toast/toast.types.js";
56
63
  import "./toast/index.js";
57
- import { PI_TOGGLE_GROUP_ACTION as mt, PI_TOGGLE_GROUP_CARD as ht, ToggleGroup as gt, onPiToggleGroupChanged as _t } from "./toggleGroup/toggleGroup.types.js";
64
+ import { PI_TOGGLE_GROUP_ACTION as Bt, PI_TOGGLE_GROUP_CARD as Vt, ToggleGroup as Ht, onPiToggleGroupChanged as Ut, onToggleGroupChanged as Wt } from "./toggleGroup/toggleGroup.types.js";
58
65
  import "./toggleGroup/index.js";
59
- import { TYPOGRAPHY_CARD as vt, Typography as yt } from "./typography/typography.types.js";
66
+ import { TYPOGRAPHY_CARD as Gt, Typography as Kt } from "./typography/typography.types.js";
60
67
  import "./typography/index.js";
61
- export { e as BADGE_CARD, n as BOX_CARD, r as Box, i as Button, h as CONDITIONAL_CARD, d as Checkbox, g as Conditional, _ as DATA_TABLE_ACTION, v as DATA_TABLE_CARD, y as DATA_TABLE_ROW_DETAIL_CARD, we as DEF_ERROR_COLOR, Te as DEF_EVENT_DURATION_SECONDS, Ee as DEF_HEIGHT, De as DEF_OVERLAY_OPACITY, Oe as DEF_PASTE_FIRST_REMINDER, ke as DEF_PASTE_TARGET_FILE_TYPES, Ae as DEF_SUCCESS_COLOR, N as DROP_DOWN_MENU_ACTION, P as DROP_DOWN_MENU_CARD, b as DataTable, x as DataTableRowDetail, D as Dialog, F as DropDownMenu, z as FLEX_GRID_CARD, L as Field, B as FlexGrid, V as Form, l as FormContext, Z as LIST_ACTION, Q as LIST_CARD, te as LOADING_OVERLAY_CARD, re as LOADING_SKELETON_CARD, $ as List, ne as LoadingOverlay, ie as LoadingSkeleton, ae as MENU_ACTION, oe as MENU_CARD, le as MODE_TOGGLE_ACTION, ue as MODE_TOGGLE_CARD, se as Menu, de as ModeToggle, pe as NAVBAR_SEARCH_ACTION, me as NAVBAR_SEARCH_CARD, he as NavbarSearch, ye as PAGE_WITH_NAVBAR_ACTION, be as PAGE_WITH_NAVBAR_CARD, je as PASTE_TARGET_ACTION, Me as PASTE_TARGET_CARD, a as PI_BUTTON_ACTION, o as PI_BUTTON_CARD, f as PI_CHECKBOX_ACTION, p as PI_CHECKBOX_CARD, O as PI_DIALOG_ACTION, k as PI_DIALOG_CARD, R as PI_FIELD_CARD, H as PI_FORM_ACTION, U as PI_FORM_CARD, K as PI_INPUT_ACTION, q as PI_INPUT_CARD, Ie as PI_SELECT_ACTION, Le as PI_SELECT_CARD, Je as PI_SWITCH_ACTION, Ye as PI_SWITCH_CARD, rt as PI_TEXT_FIELD_ACTION, it as PI_TEXT_FIELD_CARD, st as PI_TOAST_ACTION, ct as PI_TOAST_CARD, mt as PI_TOGGLE_GROUP_ACTION, ht as PI_TOGGLE_GROUP_CARD, xe as PageWithNavbar, Ne as PasteTarget, J as PiInput, He as STACK_CARD, We as STEPPER_ACTION, Ge as STEPPER_CARD, G as SdFramework, Ce as SdPageWithNavbar, Qe as SdTabs, Re as Select, t as ShadBadge, Ue as Stack, Ke as Stepper, Xe as Switch, $e as TABS_ACTION, et as TABS_CARD, lt as TOAST_OP_ACTION, vt as TYPOGRAPHY_CARD, tt as Tabs, at as TextField, ut as Toast, gt as ToggleGroup, yt as Typography, dt as dispatchShowToast, s as onButtonClicked, Pe as onContentPasted, S as onDataTableHideDetail, C as onDataTablePageChanged, w as onDataTableRowClicked, T as onDataTableShowDetail, E as onDataTableSortChanged, A as onDialogClosed, j as onDialogOpenChanged, M as onDialogOpened, I as onDropDownMenuClicked, ee as onListItemClicked, ce as onMenuClicked, fe as onModeToggleChanged, ge as onNavbarSearchFocus, _e as onNavbarSearchItems, ve as onNavbarSearchSubmit, Se as onPageWithNavbarNavigateTo, Fe as onPasteError, c as onPiButtonClicked, m as onPiCheckboxChanged, W as onPiFormSubmitted, Y as onPiInputChanged, X as onPiInputCommitted, ze as onPiSelectChanged, Be as onPiSelectClosed, Ve as onPiSelectOpened, Ze as onPiSwitchChanged, ot as onPiTextFieldChanged, ft as onPiToastClosed, _t as onPiToggleGroupChanged, pt as onShowToast, qe as onStepperStepClicked, nt as onTabsTabChanged, u as useFormContext };
68
+ export { e as BADGE_CARD, n as BOX_CARD, r as Box, i as Button, g as CONDITIONAL_CARD, d as Checkbox, _ as Conditional, v as DATA_TABLE_ACTION, y as DATA_TABLE_CARD, b as DATA_TABLE_ROW_DETAIL_CARD, Fe as DEF_ERROR_COLOR, Ie as DEF_EVENT_DURATION_SECONDS, B as DEF_FILE_DROP_FILE_TYPES, Le as DEF_HEIGHT, Re as DEF_OVERLAY_OPACITY, ze as DEF_PASTE_FIRST_REMINDER, Be as DEF_PASTE_TARGET_FILE_TYPES, Ve as DEF_SUCCESS_COLOR, P as DROP_DOWN_MENU_ACTION, F as DROP_DOWN_MENU_CARD, x as DataTable, S as DataTableRowDetail, O as Dialog, I as DropDownMenu, V as FILE_DROP_ACTION, H as FILE_DROP_CARD, q as FLEX_GRID_CARD, R as Field, U as FileDrop, J as FlexGrid, Y as Form, l as FormContext, ce as LIST_ACTION, le as LIST_CARD, fe as LOADING_OVERLAY_CARD, me as LOADING_SKELETON_CARD, ue as List, pe as LoadingOverlay, he as LoadingSkeleton, ge as MENU_ACTION, _e as MENU_CARD, be as MODE_TOGGLE_ACTION, xe as MODE_TOGGLE_CARD, ve as Menu, Se as ModeToggle, we as NAVBAR_SEARCH_ACTION, Te as NAVBAR_SEARCH_CARD, Ee as NavbarSearch, Ae as PAGE_WITH_NAVBAR_ACTION, je as PAGE_WITH_NAVBAR_CARD, He as PASTE_TARGET_ACTION, Ue as PASTE_TARGET_CARD, a as PI_BUTTON_ACTION, o as PI_BUTTON_CARD, f as PI_CHECKBOX_ACTION, p as PI_CHECKBOX_CARD, k as PI_DIALOG_ACTION, A as PI_DIALOG_CARD, z as PI_FIELD_CARD, X as PI_FORM_ACTION, Z as PI_FORM_CARD, te as PI_INPUT_ACTION, ne as PI_INPUT_CARD, qe as PI_SELECT_ACTION, Je as PI_SELECT_CARD, nt as PI_SLIDER_ACTION, rt as PI_SLIDER_CARD, lt as PI_SLIDER_VALUE_CARD, _t as PI_SWITCH_ACTION, vt as PI_SWITCH_CARD, Dt as PI_TEXT_FIELD_ACTION, Ot as PI_TEXT_FIELD_CARD, Mt as PI_TOAST_ACTION, Nt as PI_TOAST_CARD, Bt as PI_TOGGLE_GROUP_ACTION, Vt as PI_TOGGLE_GROUP_CARD, Me as PageWithNavbar, We as PasteTarget, re as PiInput, dt as STACK_CARD, pt as STEPPER_ACTION, mt as STEPPER_CARD, ee as SdFramework, Pe as SdPageWithNavbar, St as SdTabs, Ye as Select, t as ShadBadge, it as Slider, ut as SliderValue, ft as Stack, ht as Stepper, yt as Switch, Ct as TABS_ACTION, wt as TABS_CARD, Pt as TOAST_OP_ACTION, Gt as TYPOGRAPHY_CARD, Tt as Tabs, kt as TextField, Ft as Toast, Ht as ToggleGroup, Kt as Typography, It as dispatchShowToast, K as get_last_dropped, s as onButtonClicked, m as onCheckboxChanged, Ge as onContentPasted, C as onDataTableHideDetail, w as onDataTablePageChanged, T as onDataTableRowClicked, E as onDataTableShowDetail, D as onDataTableSortChanged, j as onDialogClosed, M as onDialogOpenChanged, N as onDialogOpened, L as onDropDownMenuClicked, W as onFileDropError, G as onFileDropped, Q as onFormSubmitted, ie as onInputChanged, ae as onInputCommitted, de as onListItemClicked, ye as onMenuClicked, Ce as onModeToggleChanged, De as onNavbarSearchFocus, Oe as onNavbarSearchItems, ke as onNavbarSearchSubmit, Ne as onPageWithNavbarNavigateTo, Ke as onPasteError, c as onPiButtonClicked, h as onPiCheckboxChanged, $ as onPiFormSubmitted, oe as onPiInputChanged, se as onPiInputCommitted, Xe as onPiSelectChanged, Ze as onPiSelectClosed, Qe as onPiSelectOpened, at as onPiSliderChanged, ot as onPiSliderCommitted, bt as onPiSwitchChanged, At as onPiTextFieldChanged, Lt as onPiToastClosed, Ut as onPiToggleGroupChanged, $e as onSelectChanged, et as onSelectClosed, tt as onSelectOpened, Rt as onShowToast, st as onSliderChanged, ct as onSliderCommitted, gt as onStepperStepClicked, xt as onSwitchChanged, Et as onTabsTabChanged, jt as onTextFieldChanged, zt as onToastClosed, Wt as onToggleGroupChanged, u as useFormContext };
@@ -1 +1 @@
1
- {"version":3,"file":"dataTable.types.js","names":[],"sources":["../../../src/cards/dataTable/dataTable.types.ts"],"sourcesContent":["import {\n PiCardRef,\n createCardDeclaration,\n createOnAction,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const DATA_TABLE_CARD = \"shad/data-table\";\n\nexport const DataTable = createCardDeclaration<DataTableProps, DataTableEvents>(\n DATA_TABLE_CARD,\n);\n\nexport const DATA_TABLE_ACTION = registerActions(DATA_TABLE_CARD, [\n \"row_clicked\",\n \"sort_changed\",\n \"show_detail\",\n \"hide_detail\",\n \"page_changed\",\n]);\n\nexport const onDataTableRowClicked = createOnAction<DataTableRowClickedEvent>(\n DATA_TABLE_ACTION.ROW_CLICKED,\n);\nexport const onDataTableSortChanged = createOnAction<DataTableSortChangedEvent>(\n DATA_TABLE_ACTION.SORT_CHANGED,\n);\nexport const onDataTableShowDetail = createOnAction<DataTableDetailEvent>(\n DATA_TABLE_ACTION.SHOW_DETAIL,\n);\nexport const onDataTableHideDetail = createOnAction<DataTableDetailEvent>(\n DATA_TABLE_ACTION.HIDE_DETAIL,\n);\nexport const onDataTablePageChanged = createOnAction<DataTablePageChangedEvent>(\n DATA_TABLE_ACTION.PAGE_CHANGED,\n);\n\n// ---------------------------------------------------------------------------\n// Column type definitions\n// ---------------------------------------------------------------------------\n\n/** Shared base for all column definitions */\nexport type DataTableColumnBase = {\n /** Key into the row's `data` object used to retrieve the cell value */\n key: string;\n /**\n * Column header label.\n * Defaults to the `key` with camelCase expanded to \"Title Case\".\n */\n title?: string;\n /** Column width as a CSS value (e.g. \"120px\", \"10%\", \"1fr\") */\n width?: string | number;\n /** Horizontal alignment of cell content. Defaults to \"left\". */\n align?: \"left\" | \"center\" | \"right\";\n /** Whether the column header is clickable for sorting */\n sortable?: boolean;\n /** Extra CSS class applied to the `<th>` header cell */\n headerClassName?: string;\n /** Extra CSS class applied to every `<td>` data cell in this column */\n cellClassName?: string;\n};\n\n/** Plain text column — cell value rendered as a string */\nexport type TextColumn = DataTableColumnBase & {\n type?: \"text\";\n};\n\n/** Numeric column with optional custom formatter */\nexport type NumberColumn = DataTableColumnBase & {\n type: \"number\";\n /** Custom number formatter; defaults to `String(value)` */\n format?: (n: number) => string;\n};\n\n/** Badge/chip column — cell value is rendered inside a `<Badge>` */\nexport type BadgeColumn = DataTableColumnBase & {\n type: \"badge\";\n /**\n * Map from cell value (as a string) to a shadcn Badge variant.\n * Falls back to \"secondary\" for unrecognised values.\n */\n variants?: Record<\n string,\n \"default\" | \"secondary\" | \"destructive\" | \"outline\"\n >;\n};\n\n/** Date column with optional custom formatter */\nexport type DateColumn = DataTableColumnBase & {\n type: \"date\";\n /** Custom date formatter; defaults to `toLocaleDateString()` */\n format?: (d: Date | string) => string;\n};\n\n/** Boolean column — renders a check-mark or cross icon */\nexport type BooleanColumn = DataTableColumnBase & {\n type: \"boolean\";\n};\n\n/**\n * Card column — cell value must be a `PiCardRef` (string).\n * The referenced card is rendered inline via Pihanga's `<Card />`.\n * This enables full reuse of any registered Pihanga card as cell content.\n */\nexport type CardColumn = DataTableColumnBase & {\n type: \"card\";\n};\n\nexport type DataTableColumn =\n | TextColumn\n | NumberColumn\n | BadgeColumn\n | DateColumn\n | BooleanColumn\n | CardColumn;\n\n// ---------------------------------------------------------------------------\n// Row\n// ---------------------------------------------------------------------------\n\nexport type DataTableRow<T = Record<string, unknown>> = {\n /** Unique row identifier used as the React key and in events */\n id: string | number;\n /**\n * Row payload — values are keyed by the column's `key` field.\n * For \"card\" columns the value should be a `PiCardRef` string.\n */\n data: T;\n /**\n * When set, the row shows an expand/collapse toggle button.\n * The referenced card is rendered full-width below the row on expand.\n * Use `onShowDetail` / `onHideDetail` events to track expanded state in\n * your redux store and update `detailCard` per row as needed.\n */\n detailCard?: PiCardRef;\n};\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n\nexport type DataTableProps<T = Record<string, unknown>> = {\n /** Column definitions — order determines display order */\n columns: DataTableColumn[];\n /** Row data */\n rows: DataTableRow<T>[];\n /** Optional visible `<caption>` rendered below the table */\n caption?: string;\n\n // --- Sorting ---\n /**\n * Key of the currently sorted column.\n * When provided the sort state is controlled; otherwise managed internally.\n */\n sortKey?: string;\n /**\n * Sort direction.\n * When provided together with `sortKey` the sort state is controlled.\n */\n sortAscending?: boolean;\n\n // --- Pagination ---\n /** Maximum number of rows per page. Omit to disable pagination. */\n pageSize?: number;\n /** Current page index (0-based). Treated as controlled when provided. */\n currentPage?: number;\n /**\n * Total row count, used for server-side pagination display.\n * Leave unset for client-side pagination derived from `rows.length`.\n */\n totalRows?: number;\n\n // --- Display ---\n /** Keep the header visible while the body scrolls */\n stickyHeader?: boolean;\n /** Alternate row background colour (zebra striping) */\n striped?: boolean;\n /** Highlight rows on hover (default: true) */\n hoverable?: boolean;\n /** Use compact row padding */\n compact?: boolean;\n\n // --- Empty state ---\n /** Card rendered when `rows` is empty */\n emptyCard?: PiCardRef;\n /** Fallback text when `rows` is empty and `emptyCard` is not set */\n emptyText?: string;\n\n className?: string;\n};\n\n// ---------------------------------------------------------------------------\n// Events\n// ---------------------------------------------------------------------------\n\nexport type DataTableRowClickedEvent = {\n rowId: string | number;\n row: DataTableRow;\n};\n\nexport type DataTableSortChangedEvent = {\n /** The column key that was clicked */\n key: string;\n /** `true` = ascending, `false` = descending */\n ascending: boolean;\n};\n\nexport type DataTableDetailEvent = {\n rowId: string | number;\n row: DataTableRow;\n};\n\nexport type DataTablePageChangedEvent = {\n /** New page index (0-based) */\n page: number;\n pageSize: number;\n};\n\nexport type DataTableEvents = {\n onRowClicked: DataTableRowClickedEvent;\n onSortChanged: DataTableSortChangedEvent;\n onShowDetail: DataTableDetailEvent;\n onHideDetail: DataTableDetailEvent;\n onPageChanged: DataTablePageChangedEvent;\n};\n\n// ---------------------------------------------------------------------------\n// DataTableRowDetail — generic single-template detail panel\n// ---------------------------------------------------------------------------\n\n/** Configuration for a single field shown in the detail panel. */\nexport type DataTableRowDetailField = {\n /** Key to look up in `row.data` */\n key: string;\n /** Optional human-readable label prefix (e.g. \"Director\") */\n label?: string;\n /** Render style: \"title\" → h4 bold, \"muted\" → muted foreground, \"text\" (default) → plain */\n type?: \"title\" | \"text\" | \"muted\";\n /** Additional Tailwind class names forwarded to the element */\n className?: string;\n};\n\nexport type DataTableRowDetailProps = {\n /**\n * The row to display. Set this via a state mapper so a single template\n * card works for all rows:\n * ```ts\n * DataTableRowDetail({\n * row: (_, ctx) => ctx.ctxtProps?.row,\n * fields: [{ key: \"title\", type: \"title\" }, ...],\n * })\n * ```\n */\n row?: DataTableRow<Record<string, unknown>>;\n /**\n * Fields to render in order.\n * When omitted, every key in `row.data` is rendered as a plain key:value pair.\n */\n fields?: DataTableRowDetailField[];\n};\n\nexport const DATA_TABLE_ROW_DETAIL_CARD = \"shad/data-table-row-detail\";\nexport const DataTableRowDetail =\n createCardDeclaration<DataTableRowDetailProps>(DATA_TABLE_ROW_DETAIL_CARD);\n"],"mappings":";;AAOA,IAAa,IAAkB,mBAElB,IAAY,EACvB,CACF,GAEa,IAAoB,EAAgB,GAAiB;CAChE;CACA;CACA;CACA;CACA;AACF,CAAC,GAEY,IAAwB,EACnC,EAAkB,WACpB,GACa,IAAyB,EACpC,EAAkB,YACpB,GACa,IAAwB,EACnC,EAAkB,WACpB,GACa,IAAwB,EACnC,EAAkB,WACpB,GACa,IAAyB,EACpC,EAAkB,YACpB,GAkOa,IAA6B,8BAC7B,IACX,EAA+C,CAA0B"}
1
+ {"version":3,"file":"dataTable.types.js","names":[],"sources":["../../../src/cards/dataTable/dataTable.types.ts"],"sourcesContent":["import {\n type PiCardRef,\n createCardDeclaration,\n createOnAction,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const DATA_TABLE_CARD = \"shad/data-table\";\n\nexport const DataTable = createCardDeclaration<DataTableProps, DataTableEvents>(\n DATA_TABLE_CARD,\n);\n\nexport const DATA_TABLE_ACTION = registerActions(DATA_TABLE_CARD, [\n \"row_clicked\",\n \"sort_changed\",\n \"show_detail\",\n \"hide_detail\",\n \"page_changed\",\n]);\n\nexport const onDataTableRowClicked = createOnAction<DataTableRowClickedEvent>(\n DATA_TABLE_ACTION.ROW_CLICKED,\n);\nexport const onDataTableSortChanged = createOnAction<DataTableSortChangedEvent>(\n DATA_TABLE_ACTION.SORT_CHANGED,\n);\nexport const onDataTableShowDetail = createOnAction<DataTableDetailEvent>(\n DATA_TABLE_ACTION.SHOW_DETAIL,\n);\nexport const onDataTableHideDetail = createOnAction<DataTableDetailEvent>(\n DATA_TABLE_ACTION.HIDE_DETAIL,\n);\nexport const onDataTablePageChanged = createOnAction<DataTablePageChangedEvent>(\n DATA_TABLE_ACTION.PAGE_CHANGED,\n);\n\n// ---------------------------------------------------------------------------\n// Column type definitions\n// ---------------------------------------------------------------------------\n\n/** Shared base for all column definitions */\nexport type DataTableColumnBase = {\n /** Key into the row's `data` object used to retrieve the cell value */\n key: string;\n /**\n * Column header label.\n * Defaults to the `key` with camelCase expanded to \"Title Case\".\n */\n title?: string;\n /** Column width as a CSS value (e.g. \"120px\", \"10%\", \"1fr\") */\n width?: string | number;\n /** Horizontal alignment of cell content. Defaults to \"left\". */\n align?: \"left\" | \"center\" | \"right\";\n /** Whether the column header is clickable for sorting */\n sortable?: boolean;\n /** Extra CSS class applied to the `<th>` header cell */\n headerClassName?: string;\n /** Extra CSS class applied to every `<td>` data cell in this column */\n cellClassName?: string;\n};\n\n/** Plain text column — cell value rendered as a string */\nexport type TextColumn = DataTableColumnBase & {\n type?: \"text\";\n};\n\n/** Numeric column with optional custom formatter */\nexport type NumberColumn = DataTableColumnBase & {\n type: \"number\";\n /** Custom number formatter; defaults to `String(value)` */\n format?: (n: number) => string;\n};\n\n/** Badge/chip column — cell value is rendered inside a `<Badge>` */\nexport type BadgeColumn = DataTableColumnBase & {\n type: \"badge\";\n /**\n * Map from cell value (as a string) to a shadcn Badge variant.\n * Falls back to \"secondary\" for unrecognised values.\n */\n variants?: Record<\n string,\n \"default\" | \"secondary\" | \"destructive\" | \"outline\"\n >;\n};\n\n/** Date column with optional custom formatter */\nexport type DateColumn = DataTableColumnBase & {\n type: \"date\";\n /** Custom date formatter; defaults to `toLocaleDateString()` */\n format?: (d: Date | string) => string;\n};\n\n/** Boolean column — renders a check-mark or cross icon */\nexport type BooleanColumn = DataTableColumnBase & {\n type: \"boolean\";\n};\n\n/**\n * Card column — cell value must be a `PiCardRef` (string).\n * The referenced card is rendered inline via Pihanga's `<Card />`.\n * This enables full reuse of any registered Pihanga card as cell content.\n */\nexport type CardColumn = DataTableColumnBase & {\n type: \"card\";\n};\n\nexport type DataTableColumn =\n | TextColumn\n | NumberColumn\n | BadgeColumn\n | DateColumn\n | BooleanColumn\n | CardColumn;\n\n// ---------------------------------------------------------------------------\n// Row\n// ---------------------------------------------------------------------------\n\nexport type DataTableRow<T = Record<string, unknown>> = {\n /** Unique row identifier used as the React key and in events */\n id: string | number;\n /**\n * Row payload — values are keyed by the column's `key` field.\n * For \"card\" columns the value should be a `PiCardRef` string.\n */\n data: T;\n /**\n * When set, the row shows an expand/collapse toggle button.\n * The referenced card is rendered full-width below the row on expand.\n * Use `onShowDetail` / `onHideDetail` events to track expanded state in\n * your redux store and update `detailCard` per row as needed.\n */\n detailCard?: PiCardRef;\n};\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n\nexport type DataTableProps<T = Record<string, unknown>> = {\n /** Column definitions — order determines display order */\n columns: DataTableColumn[];\n /** Row data */\n rows: DataTableRow<T>[];\n /** Optional visible `<caption>` rendered below the table */\n caption?: string;\n\n // --- Sorting ---\n /**\n * Key of the currently sorted column.\n * When provided the sort state is controlled; otherwise managed internally.\n */\n sortKey?: string;\n /**\n * Sort direction.\n * When provided together with `sortKey` the sort state is controlled.\n */\n sortAscending?: boolean;\n\n // --- Pagination ---\n /** Maximum number of rows per page. Omit to disable pagination. */\n pageSize?: number;\n /** Current page index (0-based). Treated as controlled when provided. */\n currentPage?: number;\n /**\n * Total row count, used for server-side pagination display.\n * Leave unset for client-side pagination derived from `rows.length`.\n */\n totalRows?: number;\n\n // --- Display ---\n /** Keep the header visible while the body scrolls */\n stickyHeader?: boolean;\n /** Alternate row background colour (zebra striping) */\n striped?: boolean;\n /** Highlight rows on hover (default: true) */\n hoverable?: boolean;\n /** Use compact row padding */\n compact?: boolean;\n\n // --- Empty state ---\n /** Card rendered when `rows` is empty */\n emptyCard?: PiCardRef;\n /** Fallback text when `rows` is empty and `emptyCard` is not set */\n emptyText?: string;\n\n className?: string;\n};\n\n// ---------------------------------------------------------------------------\n// Events\n// ---------------------------------------------------------------------------\n\nexport type DataTableRowClickedEvent = {\n rowId: string | number;\n row: DataTableRow;\n};\n\nexport type DataTableSortChangedEvent = {\n /** The column key that was clicked */\n key: string;\n /** `true` = ascending, `false` = descending */\n ascending: boolean;\n};\n\nexport type DataTableDetailEvent = {\n rowId: string | number;\n row: DataTableRow;\n};\n\nexport type DataTablePageChangedEvent = {\n /** New page index (0-based) */\n page: number;\n pageSize: number;\n};\n\nexport type DataTableEvents = {\n onRowClicked: DataTableRowClickedEvent;\n onSortChanged: DataTableSortChangedEvent;\n onShowDetail: DataTableDetailEvent;\n onHideDetail: DataTableDetailEvent;\n onPageChanged: DataTablePageChangedEvent;\n};\n\n// ---------------------------------------------------------------------------\n// DataTableRowDetail — generic single-template detail panel\n// ---------------------------------------------------------------------------\n\n/** Configuration for a single field shown in the detail panel. */\nexport type DataTableRowDetailField = {\n /** Key to look up in `row.data` */\n key: string;\n /** Optional human-readable label prefix (e.g. \"Director\") */\n label?: string;\n /** Render style: \"title\" → h4 bold, \"muted\" → muted foreground, \"text\" (default) → plain */\n type?: \"title\" | \"text\" | \"muted\";\n /** Additional Tailwind class names forwarded to the element */\n className?: string;\n};\n\nexport type DataTableRowDetailProps = {\n /**\n * The row to display. Set this via a state mapper so a single template\n * card works for all rows:\n * ```ts\n * DataTableRowDetail({\n * row: (_, ctx) => ctx.ctxtProps?.row,\n * fields: [{ key: \"title\", type: \"title\" }, ...],\n * })\n * ```\n */\n row?: DataTableRow<Record<string, unknown>>;\n /**\n * Fields to render in order.\n * When omitted, every key in `row.data` is rendered as a plain key:value pair.\n */\n fields?: DataTableRowDetailField[];\n};\n\nexport const DATA_TABLE_ROW_DETAIL_CARD = \"shad/data-table-row-detail\";\nexport const DataTableRowDetail =\n createCardDeclaration<DataTableRowDetailProps>(DATA_TABLE_ROW_DETAIL_CARD);\n"],"mappings":";;AAOA,IAAa,IAAkB,mBAElB,IAAY,EACvB,CACF,GAEa,IAAoB,EAAgB,GAAiB;CAChE;CACA;CACA;CACA;CACA;AACF,CAAC,GAEY,IAAwB,EACnC,EAAkB,WACpB,GACa,IAAyB,EACpC,EAAkB,YACpB,GACa,IAAwB,EACnC,EAAkB,WACpB,GACa,IAAwB,EACnC,EAAkB,WACpB,GACa,IAAyB,EACpC,EAAkB,YACpB,GAkOa,IAA6B,8BAC7B,IACX,EAA+C,CAA0B"}
@@ -1,4 +1,5 @@
1
1
  import { cn as e } from "../../lib/utils.js";
2
+ import "@pihanga2/core";
2
3
  import "react";
3
4
  import { Fragment as t, jsx as n, jsxs as r } from "react/jsx-runtime";
4
5
  //#region src/cards/dataTable/dataTableRowDetail.component.tsx
@@ -1 +1 @@
1
- {"version":3,"file":"dataTableRowDetail.component.js","names":[],"sources":["../../../src/cards/dataTable/dataTableRowDetail.component.tsx"],"sourcesContent":["import React from \"react\";\nimport {type PiCardProps} from \"@pihanga2/core\";\nimport {cn} from \"@/lib/utils\";\nimport type {\n DataTableRowDetailField,\n DataTableRowDetailProps,\n} from \"./dataTable.types\";\n\n/**\n * DataTableRowDetail — generic detail-panel card for use with DataTable.\n *\n * Register it ONCE as a template, then reference it in every row via\n * `detailCard`. The DataTable passes the row via `cardKey` + `row` context\n * props so a state mapper on the `row` field delivers the correct data:\n *\n * ```ts\n * registerCard(\n * \"app/myTable/rowDetail\",\n * DataTableRowDetail({\n * // State mapper — ctx.ctxtProps.row is injected by the DataTable\n * row: (_, ctx) => ctx.ctxtProps?.row,\n * fields: [\n * { key: \"title\", type: \"title\" },\n * { key: \"director\", label: \"Director\" },\n * { key: \"plot\", type: \"muted\" },\n * ],\n * }),\n * );\n * ```\n */\nexport const DataTableRowDetailComponent = (\n props: PiCardProps<DataTableRowDetailProps>,\n): React.ReactNode => {\n const {row, fields, cardName} = props;\n\n if (!row?.data) {\n return null;\n }\n\n const data = row.data as Record<string, unknown>;\n\n /** If no `fields` config, auto-render all keys as plain text */\n if (!fields || fields.length === 0) {\n return (\n <div className=\"flex flex-col gap-1 text-sm\" data-pihanga={cardName}>\n {Object.entries(data).map(([key, value]) => (\n <div key={key}>\n <span className=\"font-medium text-muted-foreground\">{key}: </span>\n <span>{String(value ?? \"\")}</span>\n </div>\n ))}\n </div>\n );\n }\n\n return (\n <div className=\"flex flex-col gap-1\" data-pihanga={cardName}>\n {fields.map((field: DataTableRowDetailField) => {\n const value = data[field.key];\n const display = value == null ? \"\" : String(value);\n\n switch (field.type) {\n case \"title\":\n return (\n <h4 key={field.key} className=\"text-base font-semibold\">\n {display}\n </h4>\n );\n\n case \"muted\":\n return (\n <p key={field.key} className=\"text-sm text-muted-foreground\">\n {field.label ? (\n <>\n <span className=\"font-medium\">{field.label}: </span>\n {display}\n </>\n ) : (\n display\n )}\n </p>\n );\n\n default:\n // \"text\" or any unknown type\n return (\n <p key={field.key} className={cn(\"text-sm\", field.className)}>\n {field.label ? (\n <>\n <span className=\"font-medium\">{field.label}: </span>\n {display}\n </>\n ) : (\n display\n )}\n </p>\n );\n }\n })}\n </div>\n );\n};\n"],"mappings":";;;;AA8BA,IAAa,KACX,MACoB;CACpB,IAAM,EAAC,QAAK,WAAQ,gBAAY;CAEhC,IAAI,CAAC,GAAK,MACR,OAAO;CAGT,IAAM,IAAO,EAAI;CAgBjB,OAbI,CAAC,KAAU,EAAO,WAAW,IAE7B,kBAAC,OAAD;EAAK,WAAU;EAA8B,gBAAc;YACxD,OAAO,QAAQ,CAAI,EAAE,KAAK,CAAC,GAAK,OAC/B,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,QAAD;GAAM,WAAU;aAAhB,CAAqD,GAAI,IAAQ;MACjE,kBAAC,QAAD,EAAA,UAAO,OAAO,KAAS,EAAE,EAAQ,CAAA,CAC9B,EAAA,GAHK,CAGL,CACN;CACE,CAAA,IAKP,kBAAC,OAAD;EAAK,WAAU;EAAsB,gBAAc;YAChD,EAAO,KAAK,MAAmC;GAC9C,IAAM,IAAQ,EAAK,EAAM,MACnB,IAAU,KAAS,OAAO,KAAK,OAAO,CAAK;GAEjD,QAAQ,EAAM,MAAd;IACE,KAAK,SACH,OACE,kBAAC,MAAD;KAAoB,WAAU;eAC3B;IACC,GAFK,EAAM,GAEX;IAGR,KAAK,SACH,OACE,kBAAC,KAAD;KAAmB,WAAU;eAC1B,EAAM,QACL,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,QAAD;MAAM,WAAU;gBAAhB,CAA+B,EAAM,OAAM,IAAQ;SAClD,CACD,EAAA,CAAA,IAEF;IAED,GATK,EAAM,GASX;IAGP,SAEE,OACE,kBAAC,KAAD;KAAmB,WAAW,EAAG,WAAW,EAAM,SAAS;eACxD,EAAM,QACL,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,QAAD;MAAM,WAAU;gBAAhB,CAA+B,EAAM,OAAM,IAAQ;SAClD,CACD,EAAA,CAAA,IAEF;IAED,GATK,EAAM,GASX;GAET;EACF,CAAC;CACE,CAAA;AAET"}
1
+ {"version":3,"file":"dataTableRowDetail.component.js","names":[],"sources":["../../../src/cards/dataTable/dataTableRowDetail.component.tsx"],"sourcesContent":["import React from \"react\";\nimport {type PiCardProps} from \"@pihanga2/core\";\nimport {cn} from \"@/lib/utils\";\nimport type {\n DataTableRowDetailField,\n DataTableRowDetailProps,\n} from \"./dataTable.types\";\n\n/**\n * DataTableRowDetail — generic detail-panel card for use with DataTable.\n *\n * Register it ONCE as a template, then reference it in every row via\n * `detailCard`. The DataTable passes the row via `cardKey` + `row` context\n * props so a state mapper on the `row` field delivers the correct data:\n *\n * ```ts\n * registerCard(\n * \"app/myTable/rowDetail\",\n * DataTableRowDetail({\n * // State mapper — ctx.ctxtProps.row is injected by the DataTable\n * row: (_, ctx) => ctx.ctxtProps?.row,\n * fields: [\n * { key: \"title\", type: \"title\" },\n * { key: \"director\", label: \"Director\" },\n * { key: \"plot\", type: \"muted\" },\n * ],\n * }),\n * );\n * ```\n */\nexport const DataTableRowDetailComponent = (\n props: PiCardProps<DataTableRowDetailProps>,\n): React.ReactNode => {\n const {row, fields, cardName} = props;\n\n if (!row?.data) {\n return null;\n }\n\n const data = row.data as Record<string, unknown>;\n\n /** If no `fields` config, auto-render all keys as plain text */\n if (!fields || fields.length === 0) {\n return (\n <div className=\"flex flex-col gap-1 text-sm\" data-pihanga={cardName}>\n {Object.entries(data).map(([key, value]) => (\n <div key={key}>\n <span className=\"font-medium text-muted-foreground\">{key}: </span>\n <span>{String(value ?? \"\")}</span>\n </div>\n ))}\n </div>\n );\n }\n\n return (\n <div className=\"flex flex-col gap-1\" data-pihanga={cardName}>\n {fields.map((field: DataTableRowDetailField) => {\n const value = data[field.key];\n const display = value == null ? \"\" : String(value);\n\n switch (field.type) {\n case \"title\":\n return (\n <h4 key={field.key} className=\"text-base font-semibold\">\n {display}\n </h4>\n );\n\n case \"muted\":\n return (\n <p key={field.key} className=\"text-sm text-muted-foreground\">\n {field.label ? (\n <>\n <span className=\"font-medium\">{field.label}: </span>\n {display}\n </>\n ) : (\n display\n )}\n </p>\n );\n\n default:\n // \"text\" or any unknown type\n return (\n <p key={field.key} className={cn(\"text-sm\", field.className)}>\n {field.label ? (\n <>\n <span className=\"font-medium\">{field.label}: </span>\n {display}\n </>\n ) : (\n display\n )}\n </p>\n );\n }\n })}\n </div>\n );\n};\n"],"mappings":";;;;;AA8BA,IAAa,KACX,MACoB;CACpB,IAAM,EAAC,QAAK,WAAQ,gBAAY;CAEhC,IAAI,CAAC,GAAK,MACR,OAAO;CAGT,IAAM,IAAO,EAAI;CAgBjB,OAbI,CAAC,KAAU,EAAO,WAAW,IAE7B,kBAAC,OAAD;EAAK,WAAU;EAA8B,gBAAc;YACxD,OAAO,QAAQ,CAAI,EAAE,KAAK,CAAC,GAAK,OAC/B,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,QAAD;GAAM,WAAU;aAAhB,CAAqD,GAAI,IAAQ;MACjE,kBAAC,QAAD,EAAA,UAAO,OAAO,KAAS,EAAE,EAAQ,CAAA,CAC9B,EAAA,GAHK,CAGL,CACN;CACE,CAAA,IAKP,kBAAC,OAAD;EAAK,WAAU;EAAsB,gBAAc;YAChD,EAAO,KAAK,MAAmC;GAC9C,IAAM,IAAQ,EAAK,EAAM,MACnB,IAAU,KAAS,OAAO,KAAK,OAAO,CAAK;GAEjD,QAAQ,EAAM,MAAd;IACE,KAAK,SACH,OACE,kBAAC,MAAD;KAAoB,WAAU;eAC3B;IACC,GAFK,EAAM,GAEX;IAGR,KAAK,SACH,OACE,kBAAC,KAAD;KAAmB,WAAU;eAC1B,EAAM,QACL,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,QAAD;MAAM,WAAU;gBAAhB,CAA+B,EAAM,OAAM,IAAQ;SAClD,CACD,EAAA,CAAA,IAEF;IAED,GATK,EAAM,GASX;IAGP,SAEE,OACE,kBAAC,KAAD;KAAmB,WAAW,EAAG,WAAW,EAAM,SAAS;eACxD,EAAM,QACL,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,QAAD;MAAM,WAAU;gBAAhB,CAA+B,EAAM,OAAM,IAAQ;SAClD,CACD,EAAA,CAAA,IAEF;IAED,GATK,EAAM,GASX;GAET;EACF,CAAC;CACE,CAAA;AAET"}