@pihanga2/shadcn 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENT.building-cards.md +208 -3
- package/AGENT.md +66 -4
- package/AGENT.using-cards.md +197 -250
- package/README.md +4 -1
- package/cards/badge/badge.component.js +1 -0
- package/cards/badge/badge.component.js.map +1 -1
- package/cards/box/box.component.js +2 -2
- package/cards/box/box.component.js.map +1 -1
- package/cards/box/box.types.d.ts +0 -8
- package/cards/box/box.types.js.map +1 -1
- package/cards/button/button.types.d.ts +4 -0
- package/cards/button/button.types.js +2 -2
- package/cards/button/button.types.js.map +1 -1
- package/cards/button/index.js +5 -5
- package/cards/chart/chart.component.d.ts +4 -0
- package/cards/chart/chart.types.d.ts +223 -0
- package/cards/chart/index.d.ts +1 -0
- package/cards/checkbox/checkbox.component.js +1 -0
- package/cards/checkbox/checkbox.component.js.map +1 -1
- package/cards/checkbox/checkbox.types.d.ts +4 -0
- package/cards/checkbox/checkbox.types.js +2 -2
- package/cards/checkbox/checkbox.types.js.map +1 -1
- package/cards/checkbox/index.js +5 -5
- package/cards/conditional/conditional.component.d.ts +14 -3
- package/cards/conditional/conditional.component.js +17 -9
- package/cards/conditional/conditional.component.js.map +1 -1
- package/cards/conditional/conditional.types.d.ts +115 -8
- package/cards/conditional/conditional.types.js.map +1 -1
- package/cards/core-index.d.ts +3 -0
- package/cards/core-index.js +38 -31
- package/cards/dataTable/dataTable.types.js.map +1 -1
- package/cards/dataTable/dataTableRowDetail.component.js +1 -0
- package/cards/dataTable/dataTableRowDetail.component.js.map +1 -1
- package/cards/field/field.types.js.map +1 -1
- package/cards/fileDrop/fileDrop.component.js +90 -0
- package/cards/fileDrop/fileDrop.component.js.map +1 -0
- package/cards/fileDrop/fileDrop.types.js +11 -0
- package/cards/fileDrop/fileDrop.types.js.map +1 -0
- package/cards/fileDrop/index.js +13 -0
- package/cards/fileDrop/index.js.map +1 -0
- package/cards/flexGrid/flexGrid.types.js.map +1 -1
- package/cards/form/form.types.d.ts +4 -0
- package/cards/form/form.types.js +2 -2
- package/cards/form/form.types.js.map +1 -1
- package/cards/form/index.js +5 -5
- package/cards/graphin/contextMenu.component.d.ts +28 -0
- package/cards/graphin/eventDispatcher.component.d.ts +8 -0
- package/cards/graphin/graphin.component.d.ts +2 -2
- package/cards/graphin/graphin.playground-cards.d.ts +1 -0
- package/cards/graphin/graphin.types.d.ts +477 -4
- package/cards/graphin/graphinOpHandler.component.d.ts +8 -0
- package/cards/graphin/index.d.ts +1 -0
- package/cards/graphin/tooltip.component.d.ts +13 -1
- package/cards/input/index.js +5 -5
- package/cards/input/input.component.js +1 -0
- package/cards/input/input.component.js.map +1 -1
- package/cards/input/input.types.d.ts +10 -2
- package/cards/input/input.types.js +2 -2
- package/cards/input/input.types.js.map +1 -1
- package/cards/list/list.types.js +1 -0
- package/cards/list/list.types.js.map +1 -1
- package/cards/pageWithNavbar/pageWithNavbar.component.d.ts +5 -7
- package/cards/pageWithNavbar/pageWithNavbar.component.js +1 -1
- package/cards/pageWithNavbar/pageWithNavbar.component.js.map +1 -1
- package/cards/pasteTarget/pasteTarget.component.js.map +1 -1
- package/cards/select/index.js +5 -5
- package/cards/select/select.component.js +1 -0
- package/cards/select/select.component.js.map +1 -1
- package/cards/select/select.types.d.ts +12 -0
- package/cards/select/select.types.js +2 -2
- package/cards/select/select.types.js.map +1 -1
- package/cards/slider/index.d.ts +1 -0
- package/cards/slider/index.js +13 -0
- package/cards/slider/index.js.map +1 -0
- package/cards/slider/slider.component.d.ts +4 -0
- package/cards/slider/slider.component.js +64 -0
- package/cards/slider/slider.component.js.map +1 -0
- package/cards/slider/slider.types.d.ts +110 -0
- package/cards/slider/slider.types.js +7 -0
- package/cards/slider/slider.types.js.map +1 -0
- package/cards/sliderValue/index.d.ts +1 -0
- package/cards/sliderValue/index.js +12 -0
- package/cards/sliderValue/index.js.map +1 -0
- package/cards/sliderValue/sliderValue.component.d.ts +15 -0
- package/cards/sliderValue/sliderValue.component.js +33 -0
- package/cards/sliderValue/sliderValue.component.js.map +1 -0
- package/cards/sliderValue/sliderValue.types.d.ts +21 -0
- package/cards/sliderValue/sliderValue.types.js +7 -0
- package/cards/sliderValue/sliderValue.types.js.map +1 -0
- package/cards/stack/stack.component.js +1 -1
- package/cards/stack/stack.component.js.map +1 -1
- package/cards/stack/stack.types.js.map +1 -1
- package/cards/switch/index.js +5 -5
- package/cards/switch/switch.component.js +1 -0
- package/cards/switch/switch.component.js.map +1 -1
- package/cards/switch/switch.types.d.ts +4 -0
- package/cards/switch/switch.types.js +2 -2
- package/cards/switch/switch.types.js.map +1 -1
- package/cards/tabs/tabs.component.js +51 -25
- package/cards/tabs/tabs.component.js.map +1 -1
- package/cards/tabs/tabs.types.d.ts +10 -0
- package/cards/tabs/tabs.types.js.map +1 -1
- package/cards/textField/index.js +5 -5
- package/cards/textField/textField.component.js +1 -0
- package/cards/textField/textField.component.js.map +1 -1
- package/cards/textField/textField.types.d.ts +4 -0
- package/cards/textField/textField.types.js +2 -2
- package/cards/textField/textField.types.js.map +1 -1
- package/cards/toast/index.js +7 -7
- package/cards/toast/toast.component.js.map +1 -1
- package/cards/toast/toast.types.d.ts +4 -0
- package/cards/toast/toast.types.js +2 -2
- package/cards/toast/toast.types.js.map +1 -1
- package/cards/toggleGroup/index.js +5 -5
- package/cards/toggleGroup/toggleGroup.component.js +1 -0
- package/cards/toggleGroup/toggleGroup.component.js.map +1 -1
- package/cards/toggleGroup/toggleGroup.types.d.ts +4 -0
- package/cards/toggleGroup/toggleGroup.types.js +2 -2
- package/cards/toggleGroup/toggleGroup.types.js.map +1 -1
- package/cards/typography/typography.types.js +1 -0
- package/cards/typography/typography.types.js.map +1 -1
- package/components/hooks/use-breakpoint.d.ts +49 -0
- package/components/hooks/use-breakpoint.js +73 -0
- package/components/hooks/use-breakpoint.js.map +1 -0
- package/components/ui/slider.js +36 -0
- package/components/ui/slider.js.map +1 -0
- package/components/ui/toggle-group.js +1 -0
- package/components/ui/toggle-group.js.map +1 -1
- package/package.json +19 -2
- package/pihanga-shadcn.css +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button.types.js","names":[],"sources":["../../../src/cards/button/button.types.ts"],"sourcesContent":["import {\n createCardDeclaration,\n createOnAction,\n PiCardRef,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const PI_BUTTON_CARD = \"pi/button\";\n\nexport const Button = createCardDeclaration<PiButtonProps, PiButtonEvents>(\n PI_BUTTON_CARD,\n);\n\nexport const PI_BUTTON_ACTION = registerActions(PI_BUTTON_CARD, [\"clicked\"]);\n\nexport const
|
|
1
|
+
{"version":3,"file":"button.types.js","names":[],"sources":["../../../src/cards/button/button.types.ts"],"sourcesContent":["import {\n createCardDeclaration,\n createOnAction,\n type PiCardRef,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const PI_BUTTON_CARD = \"pi/button\";\n\nexport const Button = createCardDeclaration<PiButtonProps, PiButtonEvents>(\n PI_BUTTON_CARD,\n);\n\nexport const PI_BUTTON_ACTION = registerActions(PI_BUTTON_CARD, [\"clicked\"]);\n\nexport const onButtonClicked = createOnAction<PiButtonClickedEvent>(\n PI_BUTTON_ACTION.CLICKED,\n);\n\n/** @deprecated Use `onButtonClicked` instead. */\nexport const onPiButtonClicked = onButtonClicked;\n\n/**\n * Declarative \"opts\" subset based on `src/registry/ui/button.tsx`.\n *\n * Notes:\n * - Any icon is referenced by name and resolved via `src/pihanga/icons.ts`.\n * - `children` are provided via `label` (simple) or `content` (card ref).\n */\nexport type PiButtonOpts = {\n /**\n * Visual style variant of the button.\n * Determines the button's appearance (colors, borders, etc.).\n */\n variant?:\n | \"default\"\n | \"destructive\"\n | \"outline\"\n | \"secondary\"\n | \"ghost\"\n | \"ghost2\"\n | \"ghost3\"\n | \"ghostActive\"\n | \"brand\"\n | \"nav\"\n | \"navAction\"\n | \"menuAction\"\n | \"blockAction\"\n | \"blockActionSecondary\"\n | \"primaryOutline\"\n | \"radio\"\n | \"none\";\n\n /**\n * Size of the button.\n * Controls padding, font size, and overall dimensions.\n */\n size?:\n | \"default\"\n | \"xs\"\n | \"sm\"\n | \"md\"\n | \"lg\"\n | \"icon\"\n | \"iconSm\"\n | \"navAction\"\n | \"menuAction\"\n | \"blockAction\"\n | \"none\";\n\n /** Truncate button content with ellipsis if it overflows. */\n truncate?: boolean;\n\n /** If true, button is rendered as a menu trigger button. */\n isMenu?: boolean;\n\n /** Custom CSS class to apply to the loading spinner/indicator. */\n loadingClassName?: string;\n\n /** Icon to display before the button content. Set 'size' to 'icon' if ONLY show icon */\n beforeIcon?: string;\n\n /** Icon to display after the button content */\n afterIcon?: string;\n};\n\nexport type PiButtonProps = {\n id?: string; // optional 'id' to be added to events\n\n /**\n * Optional explicit aria-label.\n *\n * Useful for icon-only / letter-only buttons where the visible content\n * shouldn't be used as the accessible name.\n */\n ariaLabel?: string;\n\n /**\n * Declarative options; maps closely to `@/registry/ui/button`.\n */\n opts?: PiButtonOpts;\n\n /** Simple label; used as children and aria-label fallback. */\n label?: string;\n\n /**\n * Icon name to use as the main button content (instead of text label).\n * Resolved via `src/pihanga/icons.ts`.\n * Takes precedence over `label` and `contentCard`.\n */\n iconLabel?: string;\n\n /**\n * If set, renders this card as the content instead of `label`.\n * (Useful for rich content.)\n */\n contentCard?: PiCardRef;\n\n /** When provided, button will render as an anchor. */\n href?: string;\n target?: string;\n\n tooltip?: string;\n\n /**\n * If set, renders this card as the tooltip content instead of `tooltip`.\n * (Useful for rich tooltip content.)\n */\n tooltipCard?: PiCardRef;\n\n /**\n * Controls tooltip visibility mode.\n * - 'auto' (default): Normal hover behavior\n * - 'open': Force tooltip to be visible\n * - 'closed': Force tooltip to be hidden\n */\n tooltipMode?: \"auto\" | \"open\" | \"closed\";\n\n /**\n * Controls tooltip placement/position.\n * - 'top': Tooltip appears above the button (default)\n * - 'right': Tooltip appears to the right of the button\n * - 'bottom': Tooltip appears below the button\n * - 'left': Tooltip appears to the left of the button\n */\n tooltipPlacement?: \"top\" | \"right\" | \"bottom\" | \"left\";\n\n /** Indicates whether the button is in an active/selected state. */\n active?: boolean;\n\n /** Indicates whether the button has focus state styling applied. */\n focused?: boolean;\n\n /** If true, disables the button and prevents interaction. */\n disabled?: boolean;\n\n /** If true, shows loading state and typically disables interaction. */\n loading?: boolean;\n\n /** If true, indicates an async operation is pending (similar to loading but distinct). */\n isPending?: boolean;\n\n className?: string;\n};\n\nexport type PiButtonClickedEvent = {\n id?: string;\n};\n\nexport type PiButtonEvents = {\n onClicked: PiButtonClickedEvent;\n};\n"],"mappings":";;AAOA,IAAa,IAAiB,aAEjB,IAAS,EACpB,CACF,GAEa,IAAmB,EAAgB,GAAgB,CAAC,SAAS,CAAC,GAE9D,IAAkB,EAC7B,EAAiB,OACnB,GAGa,IAAoB"}
|
package/cards/button/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { ButtonComponent as e } from "./button.component.js";
|
|
2
|
-
import { Button as t, PI_BUTTON_ACTION as n, PI_BUTTON_CARD as r,
|
|
3
|
-
import { actionTypesToEvents as
|
|
2
|
+
import { Button as t, PI_BUTTON_ACTION as n, PI_BUTTON_CARD as r, onButtonClicked as i, onPiButtonClicked as a } from "./button.types.js";
|
|
3
|
+
import { actionTypesToEvents as o, registerCardComponent as s } from "@pihanga2/core";
|
|
4
4
|
//#region src/cards/button/index.ts
|
|
5
|
-
|
|
5
|
+
s({
|
|
6
6
|
name: r,
|
|
7
7
|
component: e,
|
|
8
|
-
events:
|
|
8
|
+
events: o(n)
|
|
9
9
|
});
|
|
10
10
|
//#endregion
|
|
11
|
-
export { t as Button, n as PI_BUTTON_ACTION, r as PI_BUTTON_CARD, i as onPiButtonClicked };
|
|
11
|
+
export { t as Button, n as PI_BUTTON_ACTION, r as PI_BUTTON_CARD, i as onButtonClicked, a as onPiButtonClicked };
|
|
12
12
|
|
|
13
13
|
//# sourceMappingURL=index.js.map
|
|
@@ -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 +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":"
|
|
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
|
|
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"}
|
package/cards/checkbox/index.js
CHANGED
|
@@ -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,
|
|
3
|
-
import { actionTypesToEvents as
|
|
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
|
-
|
|
5
|
+
s({
|
|
6
6
|
name: r,
|
|
7
7
|
component: e,
|
|
8
|
-
events:
|
|
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
|
|
@@ -4,8 +4,19 @@ import * as React from "react";
|
|
|
4
4
|
/**
|
|
5
5
|
* ConditionalComponent
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
* returns `null` otherwise.
|
|
9
|
-
*
|
|
7
|
+
* Renders the `content` card when the combined visibility condition is `true`,
|
|
8
|
+
* returns `null` otherwise.
|
|
9
|
+
*
|
|
10
|
+
* Visibility rules (all must be satisfied):
|
|
11
|
+
* 1. `show` — manual boolean gate (defaults to `true` when omitted)
|
|
12
|
+
* 2. `showOn` — breakpoint selector (always `true` when omitted)
|
|
13
|
+
* • `containerQuery: false` (default) → evaluated against the **viewport**
|
|
14
|
+
* via `window.matchMedia`
|
|
15
|
+
* • `containerQuery: true` → evaluated against the width of the
|
|
16
|
+
* **enclosing container** via `ResizeObserver`; a thin `<div>` wrapper
|
|
17
|
+
* is rendered so the container width can be measured
|
|
18
|
+
*
|
|
19
|
+
* Both hooks are always called unconditionally (React rules); whichever is not
|
|
20
|
+
* "active" receives `undefined` and returns `true` immediately.
|
|
10
21
|
*/
|
|
11
22
|
export declare const ConditionalComponent: (props: PiCardProps<ConditionalProps>) => React.ReactNode;
|
|
@@ -1,15 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import "
|
|
3
|
-
import
|
|
1
|
+
import { useBreakpoint as e, useContainerBreakpoint as t } from "../../components/hooks/use-breakpoint.js";
|
|
2
|
+
import { Card as n } from "@pihanga2/core";
|
|
3
|
+
import * as r from "react";
|
|
4
|
+
import { jsx as i } from "react/jsx-runtime";
|
|
4
5
|
//#region src/cards/conditional/conditional.component.tsx
|
|
5
|
-
var
|
|
6
|
-
let { cardName:
|
|
7
|
-
return
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
var a = (a) => {
|
|
7
|
+
let { cardName: o, show: s = !0, showOn: c, containerQuery: l = !1, content: u } = a, d = r.useRef(null), f = e(l ? void 0 : c), p = t(l ? c : void 0, d), m = s && (l ? p : f);
|
|
8
|
+
return l ? /* @__PURE__ */ i("div", {
|
|
9
|
+
ref: d,
|
|
10
|
+
style: { width: "100%" },
|
|
11
|
+
children: m && /* @__PURE__ */ i(n, {
|
|
12
|
+
cardName: u,
|
|
13
|
+
parentCard: o
|
|
14
|
+
})
|
|
15
|
+
}) : m ? /* @__PURE__ */ i(n, {
|
|
16
|
+
cardName: u,
|
|
17
|
+
parentCard: o
|
|
10
18
|
}) : null;
|
|
11
19
|
};
|
|
12
20
|
//#endregion
|
|
13
|
-
export {
|
|
21
|
+
export { a as ConditionalComponent };
|
|
14
22
|
|
|
15
23
|
//# sourceMappingURL=conditional.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conditional.component.js","names":[],"sources":["../../../src/cards/conditional/conditional.component.tsx"],"sourcesContent":["import * as React from \"react\";\nimport {Card, type PiCardProps} from \"@pihanga2/core\";\nimport type {ConditionalProps} from \"./conditional.types\";\n\n/**\n * ConditionalComponent\n *\n *
|
|
1
|
+
{"version":3,"file":"conditional.component.js","names":[],"sources":["../../../src/cards/conditional/conditional.component.tsx"],"sourcesContent":["import * as React from \"react\";\nimport {Card, type PiCardProps} from \"@pihanga2/core\";\nimport {\n useBreakpoint,\n useContainerBreakpoint,\n} from \"@/components/hooks/use-breakpoint\";\nimport type {ConditionalProps} from \"./conditional.types\";\n\n/**\n * ConditionalComponent\n *\n * Renders the `content` card when the combined visibility condition is `true`,\n * returns `null` otherwise.\n *\n * Visibility rules (all must be satisfied):\n * 1. `show` — manual boolean gate (defaults to `true` when omitted)\n * 2. `showOn` — breakpoint selector (always `true` when omitted)\n * • `containerQuery: false` (default) → evaluated against the **viewport**\n * via `window.matchMedia`\n * • `containerQuery: true` → evaluated against the width of the\n * **enclosing container** via `ResizeObserver`; a thin `<div>` wrapper\n * is rendered so the container width can be measured\n *\n * Both hooks are always called unconditionally (React rules); whichever is not\n * \"active\" receives `undefined` and returns `true` immediately.\n */\nexport const ConditionalComponent = (\n props: PiCardProps<ConditionalProps>,\n): React.ReactNode => {\n const {\n cardName,\n show = true,\n showOn,\n containerQuery = false,\n content,\n } = props;\n\n // Ref for container-query mode — attached to the wrapper div.\n // Always created (hooks must not be conditional).\n const wrapperRef = React.useRef<HTMLDivElement>(null);\n\n // Viewport breakpoint: active when containerQuery is false.\n const viewportMatch = useBreakpoint(containerQuery ? undefined : showOn);\n\n // Container breakpoint: active when containerQuery is true.\n const containerMatch = useContainerBreakpoint(\n containerQuery ? showOn : undefined,\n wrapperRef,\n );\n\n const breakpointMatch = containerQuery ? containerMatch : viewportMatch;\n const visible = show && breakpointMatch;\n\n // ── Container-query mode ─────────────────────────────────────────────────\n // Render a full-width wrapper so ResizeObserver has something to measure.\n // The wrapper is always in the DOM (measuring must be continuous), but the\n // content card inside it is mounted/unmounted based on `visible`.\n if (containerQuery) {\n return (\n <div ref={wrapperRef} style={{width: \"100%\"}}>\n {visible && <Card cardName={content} parentCard={cardName} />}\n </div>\n );\n }\n\n // ── Viewport / manual mode ───────────────────────────────────────────────\n // Transparent pass-through — no extra DOM node.\n if (!visible) return null;\n return <Card cardName={content} parentCard={cardName} />;\n};\n"],"mappings":";;;;;AA0BA,IAAa,KACX,MACoB;CACpB,IAAM,EACJ,aACA,UAAO,IACP,WACA,oBAAiB,IACjB,eACE,GAIE,IAAa,EAAM,OAAuB,IAAI,GAG9C,IAAgB,EAAc,IAAiB,KAAA,IAAY,CAAM,GAGjE,IAAiB,EACrB,IAAiB,IAAS,KAAA,GAC1B,CACF,GAGM,IAAU,MADQ,IAAiB,IAAiB;CAkB1D,OAXI,IAEA,kBAAC,OAAD;EAAK,KAAK;EAAY,OAAO,EAAC,OAAO,OAAM;YACxC,KAAW,kBAAC,GAAD;GAAM,UAAU;GAAS,YAAY;EAAW,CAAA;CACzD,CAAA,IAMJ,IACE,kBAAC,GAAD;EAAM,UAAU;EAAS,YAAY;CAAW,CAAA,IADlC;AAEvB"}
|
|
@@ -1,14 +1,54 @@
|
|
|
1
1
|
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
|
+
/**
|
|
5
|
+
* Named Tailwind-compatible breakpoints.
|
|
6
|
+
*
|
|
7
|
+
* `xs` → viewport < 640 px (mobile-first default)
|
|
8
|
+
* `sm` → viewport ≥ 640 px
|
|
9
|
+
* `md` → viewport ≥ 768 px
|
|
10
|
+
* `lg` → viewport ≥ 1024 px
|
|
11
|
+
* `xl` → viewport ≥ 1280 px
|
|
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.
|
|
17
|
+
*
|
|
18
|
+
* Pixel expressions
|
|
19
|
+
* ─────────────────
|
|
20
|
+
* `400px` → viewport ≥ 400 px (bare value = min-width)
|
|
21
|
+
* `>=640px` → viewport ≥ 640 px
|
|
22
|
+
* `>640px` → viewport > 640 px (min-width: 641px)
|
|
23
|
+
* `<=1024px` → viewport ≤ 1024 px
|
|
24
|
+
* `<1024px` → viewport < 1024 px (max-width: 1023px)
|
|
25
|
+
*/
|
|
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>>;
|
|
4
39
|
/**
|
|
5
40
|
* Props for the `shad/conditional` card.
|
|
6
41
|
*
|
|
7
|
-
*
|
|
8
|
-
* This is a transparent pass-through —
|
|
42
|
+
* The card renders `content` only when the combined visibility condition is
|
|
43
|
+
* `true`; it renders nothing otherwise. This is a transparent pass-through —
|
|
44
|
+
* no extra DOM wrapper is added.
|
|
45
|
+
*
|
|
46
|
+
* ## Modes
|
|
47
|
+
*
|
|
48
|
+
* ### 1 · Manual boolean (existing behaviour)
|
|
9
49
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
50
|
+
* Drive `show` from a `memo()` selector so the card reactively mounts/unmounts
|
|
51
|
+
* as state changes:
|
|
12
52
|
*
|
|
13
53
|
* ```ts
|
|
14
54
|
* import {memo, registerCard} from "@pihanga2/core";
|
|
@@ -19,11 +59,78 @@ export declare const Conditional: <S extends import('@pihanga2/core').ReduxState
|
|
|
19
59
|
* content: "myApp/emptyStateHint",
|
|
20
60
|
* }));
|
|
21
61
|
* ```
|
|
62
|
+
*
|
|
63
|
+
* ### 2 · Breakpoint-based auto-selection (new)
|
|
64
|
+
*
|
|
65
|
+
* Set `showOn` to a breakpoint name or pixel expression. The component
|
|
66
|
+
* subscribes to `window.matchMedia` and automatically mounts/unmounts the
|
|
67
|
+
* content card as the viewport crosses the breakpoint — no state, no memo:
|
|
68
|
+
*
|
|
69
|
+
* ```ts
|
|
70
|
+
* // Show only on tablet-sized screens and up
|
|
71
|
+
* registerCard("myApp/sidebar", Conditional({
|
|
72
|
+
* showOn: "md",
|
|
73
|
+
* content: "myApp/desktopSidebar",
|
|
74
|
+
* }));
|
|
75
|
+
*
|
|
76
|
+
* // Show only on narrow viewports (mobile drawer)
|
|
77
|
+
* registerCard("myApp/mobileNav", Conditional({
|
|
78
|
+
* showOn: "<768px",
|
|
79
|
+
* content: "myApp/drawer",
|
|
80
|
+
* }));
|
|
81
|
+
* ```
|
|
82
|
+
*
|
|
83
|
+
* ### 3 · Combined
|
|
84
|
+
*
|
|
85
|
+
* Both conditions are ANDed — content renders only when the breakpoint matches
|
|
86
|
+
* **and** `show` is `true`:
|
|
87
|
+
*
|
|
88
|
+
* ```ts
|
|
89
|
+
* registerCard("myApp/adminSidebar", Conditional({
|
|
90
|
+
* show: memo((s: AppState) => s.isAdmin),
|
|
91
|
+
* showOn: "lg",
|
|
92
|
+
* content: "myApp/adminPanel",
|
|
93
|
+
* }));
|
|
94
|
+
* ```
|
|
22
95
|
*/
|
|
23
96
|
export type ConditionalProps = {
|
|
24
|
-
/**
|
|
25
|
-
*
|
|
26
|
-
|
|
27
|
-
|
|
97
|
+
/**
|
|
98
|
+
* Manual boolean gate. When omitted it defaults to `true` so that a
|
|
99
|
+
* `showOn`-only card does not need to set it explicitly.
|
|
100
|
+
*
|
|
101
|
+
* Drive with `memo()` for reactive mount/unmount behaviour.
|
|
102
|
+
*/
|
|
103
|
+
show?: boolean;
|
|
104
|
+
/**
|
|
105
|
+
* Viewport-width breakpoint selector. When set, the component subscribes
|
|
106
|
+
* to `window.matchMedia` and reactively shows/hides the content card
|
|
107
|
+
* whenever the viewport crosses the breakpoint.
|
|
108
|
+
*
|
|
109
|
+
* Supported values: `xs` | `sm` | `md` | `lg` | `xl` | `2xl` (Tailwind),
|
|
110
|
+
* or pixel expressions such as `>400px`, `>=640px`, `<768px`, `<=1024px`,
|
|
111
|
+
* `400px`.
|
|
112
|
+
*
|
|
113
|
+
* When both `show` and `showOn` are provided the content is rendered only
|
|
114
|
+
* when **both** conditions are satisfied.
|
|
115
|
+
*
|
|
116
|
+
* By default the breakpoint is evaluated against the **viewport** width via
|
|
117
|
+
* `window.matchMedia`. Set `containerQuery: true` to evaluate it against
|
|
118
|
+
* the width of the **enclosing container** instead (uses `ResizeObserver`).
|
|
119
|
+
*/
|
|
120
|
+
showOn?: BreakpointSelector;
|
|
121
|
+
/**
|
|
122
|
+
* When `true`, the `showOn` breakpoint is measured against the width of the
|
|
123
|
+
* component's **enclosing container** rather than the viewport.
|
|
124
|
+
*
|
|
125
|
+
* Internally the component renders a transparent `<div style="width:100%">`
|
|
126
|
+
* wrapper and observes it with `ResizeObserver`. This means a single extra
|
|
127
|
+
* DOM node is added when `containerQuery` is `true`.
|
|
128
|
+
*
|
|
129
|
+
* Has no effect when `showOn` is not set.
|
|
130
|
+
*
|
|
131
|
+
* @default false
|
|
132
|
+
*/
|
|
133
|
+
containerQuery?: boolean;
|
|
134
|
+
/** The card to render when the visibility condition is met. */
|
|
28
135
|
content: PiCardRef;
|
|
29
136
|
};
|
|
@@ -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// ── Props ─────────────────────────────────────────────────────────────────────\n\n/**\n * Props for the `shad/conditional` card.\n *\n *
|
|
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"}
|
package/cards/core-index.d.ts
CHANGED
|
@@ -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';
|