@pihanga2/shadcn 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/AGENT.building-cards.md +208 -3
  2. package/AGENT.md +66 -4
  3. package/AGENT.using-cards.md +197 -250
  4. package/README.md +4 -1
  5. package/cards/badge/badge.component.js +1 -0
  6. package/cards/badge/badge.component.js.map +1 -1
  7. package/cards/box/box.component.js +2 -2
  8. package/cards/box/box.component.js.map +1 -1
  9. package/cards/box/box.types.d.ts +0 -8
  10. package/cards/box/box.types.js.map +1 -1
  11. package/cards/button/button.types.d.ts +4 -0
  12. package/cards/button/button.types.js +2 -2
  13. package/cards/button/button.types.js.map +1 -1
  14. package/cards/button/index.js +5 -5
  15. package/cards/chart/chart.component.d.ts +4 -0
  16. package/cards/chart/chart.types.d.ts +223 -0
  17. package/cards/chart/index.d.ts +1 -0
  18. package/cards/checkbox/checkbox.component.js +1 -0
  19. package/cards/checkbox/checkbox.component.js.map +1 -1
  20. package/cards/checkbox/checkbox.types.d.ts +4 -0
  21. package/cards/checkbox/checkbox.types.js +2 -2
  22. package/cards/checkbox/checkbox.types.js.map +1 -1
  23. package/cards/checkbox/index.js +5 -5
  24. package/cards/conditional/conditional.component.d.ts +14 -3
  25. package/cards/conditional/conditional.component.js +17 -9
  26. package/cards/conditional/conditional.component.js.map +1 -1
  27. package/cards/conditional/conditional.types.d.ts +115 -8
  28. package/cards/conditional/conditional.types.js.map +1 -1
  29. package/cards/core-index.d.ts +3 -0
  30. package/cards/core-index.js +38 -31
  31. package/cards/dataTable/dataTable.types.js.map +1 -1
  32. package/cards/dataTable/dataTableRowDetail.component.js +1 -0
  33. package/cards/dataTable/dataTableRowDetail.component.js.map +1 -1
  34. package/cards/field/field.types.js.map +1 -1
  35. package/cards/fileDrop/fileDrop.component.js +90 -0
  36. package/cards/fileDrop/fileDrop.component.js.map +1 -0
  37. package/cards/fileDrop/fileDrop.types.js +11 -0
  38. package/cards/fileDrop/fileDrop.types.js.map +1 -0
  39. package/cards/fileDrop/index.js +13 -0
  40. package/cards/fileDrop/index.js.map +1 -0
  41. package/cards/flexGrid/flexGrid.types.js.map +1 -1
  42. package/cards/form/form.types.d.ts +4 -0
  43. package/cards/form/form.types.js +2 -2
  44. package/cards/form/form.types.js.map +1 -1
  45. package/cards/form/index.js +5 -5
  46. package/cards/graphin/contextMenu.component.d.ts +28 -0
  47. package/cards/graphin/eventDispatcher.component.d.ts +8 -0
  48. package/cards/graphin/graphin.component.d.ts +2 -2
  49. package/cards/graphin/graphin.playground-cards.d.ts +1 -0
  50. package/cards/graphin/graphin.types.d.ts +477 -4
  51. package/cards/graphin/graphinOpHandler.component.d.ts +8 -0
  52. package/cards/graphin/index.d.ts +1 -0
  53. package/cards/graphin/tooltip.component.d.ts +13 -1
  54. package/cards/input/index.js +5 -5
  55. package/cards/input/input.component.js +1 -0
  56. package/cards/input/input.component.js.map +1 -1
  57. package/cards/input/input.types.d.ts +10 -2
  58. package/cards/input/input.types.js +2 -2
  59. package/cards/input/input.types.js.map +1 -1
  60. package/cards/list/list.types.js +1 -0
  61. package/cards/list/list.types.js.map +1 -1
  62. package/cards/pageWithNavbar/pageWithNavbar.component.d.ts +5 -7
  63. package/cards/pageWithNavbar/pageWithNavbar.component.js +1 -1
  64. package/cards/pageWithNavbar/pageWithNavbar.component.js.map +1 -1
  65. package/cards/pasteTarget/pasteTarget.component.js.map +1 -1
  66. package/cards/select/index.js +5 -5
  67. package/cards/select/select.component.js +1 -0
  68. package/cards/select/select.component.js.map +1 -1
  69. package/cards/select/select.types.d.ts +12 -0
  70. package/cards/select/select.types.js +2 -2
  71. package/cards/select/select.types.js.map +1 -1
  72. package/cards/slider/index.d.ts +1 -0
  73. package/cards/slider/index.js +13 -0
  74. package/cards/slider/index.js.map +1 -0
  75. package/cards/slider/slider.component.d.ts +4 -0
  76. package/cards/slider/slider.component.js +64 -0
  77. package/cards/slider/slider.component.js.map +1 -0
  78. package/cards/slider/slider.types.d.ts +110 -0
  79. package/cards/slider/slider.types.js +7 -0
  80. package/cards/slider/slider.types.js.map +1 -0
  81. package/cards/sliderValue/index.d.ts +1 -0
  82. package/cards/sliderValue/index.js +12 -0
  83. package/cards/sliderValue/index.js.map +1 -0
  84. package/cards/sliderValue/sliderValue.component.d.ts +15 -0
  85. package/cards/sliderValue/sliderValue.component.js +33 -0
  86. package/cards/sliderValue/sliderValue.component.js.map +1 -0
  87. package/cards/sliderValue/sliderValue.types.d.ts +21 -0
  88. package/cards/sliderValue/sliderValue.types.js +7 -0
  89. package/cards/sliderValue/sliderValue.types.js.map +1 -0
  90. package/cards/stack/stack.component.js +1 -1
  91. package/cards/stack/stack.component.js.map +1 -1
  92. package/cards/stack/stack.types.js.map +1 -1
  93. package/cards/switch/index.js +5 -5
  94. package/cards/switch/switch.component.js +1 -0
  95. package/cards/switch/switch.component.js.map +1 -1
  96. package/cards/switch/switch.types.d.ts +4 -0
  97. package/cards/switch/switch.types.js +2 -2
  98. package/cards/switch/switch.types.js.map +1 -1
  99. package/cards/tabs/tabs.component.js +51 -25
  100. package/cards/tabs/tabs.component.js.map +1 -1
  101. package/cards/tabs/tabs.types.d.ts +10 -0
  102. package/cards/tabs/tabs.types.js.map +1 -1
  103. package/cards/textField/index.js +5 -5
  104. package/cards/textField/textField.component.js +1 -0
  105. package/cards/textField/textField.component.js.map +1 -1
  106. package/cards/textField/textField.types.d.ts +4 -0
  107. package/cards/textField/textField.types.js +2 -2
  108. package/cards/textField/textField.types.js.map +1 -1
  109. package/cards/toast/index.js +7 -7
  110. package/cards/toast/toast.component.js.map +1 -1
  111. package/cards/toast/toast.types.d.ts +4 -0
  112. package/cards/toast/toast.types.js +2 -2
  113. package/cards/toast/toast.types.js.map +1 -1
  114. package/cards/toggleGroup/index.js +5 -5
  115. package/cards/toggleGroup/toggleGroup.component.js +1 -0
  116. package/cards/toggleGroup/toggleGroup.component.js.map +1 -1
  117. package/cards/toggleGroup/toggleGroup.types.d.ts +4 -0
  118. package/cards/toggleGroup/toggleGroup.types.js +2 -2
  119. package/cards/toggleGroup/toggleGroup.types.js.map +1 -1
  120. package/cards/typography/typography.types.js +1 -0
  121. package/cards/typography/typography.types.js.map +1 -1
  122. package/components/hooks/use-breakpoint.d.ts +49 -0
  123. package/components/hooks/use-breakpoint.js +73 -0
  124. package/components/hooks/use-breakpoint.js.map +1 -0
  125. package/components/ui/slider.js +36 -0
  126. package/components/ui/slider.js.map +1 -0
  127. package/components/ui/toggle-group.js +1 -0
  128. package/components/ui/toggle-group.js.map +1 -1
  129. package/package.json +19 -2
  130. package/pihanga-shadcn.css +1 -1
@@ -1,11 +1,213 @@
1
- import { PiCardDef } from '@pihanga2/core';
1
+ import { default as React } from 'react';
2
+ import { DispatchF, ReduxAction } from '@pihanga2/core';
2
3
  import { GraphData, GraphOptions } from '@antv/g6';
3
4
  export declare const GRAPHIN_CARD = "graphin";
4
- export declare const Graphin: <S extends import('@pihanga2/core').ReduxState>(p: import('@pihanga2/core').PiMapProps<GraphinProps, S, {}>) => PiCardDef;
5
+ export declare const Graphin: <S extends import('@pihanga2/core').ReduxState>(p: import('@pihanga2/core').PiMapProps<GraphinProps, S, GraphinEvents>) => import('@pihanga2/core').PiCardDef;
6
+ export declare const GRAPHIN_ACTION: {
7
+ NODE_HOVERED: string;
8
+ NODE_HOVER_END: string;
9
+ NODE_CLICKED: string;
10
+ NODE_DBL_CLICKED: string;
11
+ TOOLTIP_OPEN: string;
12
+ TOOLTIP_CLOSE: string;
13
+ CONTEXT_MENU_OPEN: string;
14
+ CONTEXT_MENU_CLOSE: string;
15
+ };
16
+ export declare const onGraphinNodeHovered: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, ReduxAction & {
17
+ cardID: string;
18
+ } & GraphinNodeEventContext<Record<string, unknown>>>) => void;
19
+ export declare const onGraphinNodeHoverEnd: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, ReduxAction & {
20
+ cardID: string;
21
+ } & GraphinNodeEventContext<Record<string, unknown>>>) => void;
22
+ export declare const onGraphinNodeClicked: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, ReduxAction & {
23
+ cardID: string;
24
+ } & GraphinNodeEventContext<Record<string, unknown>>>) => void;
25
+ export declare const onGraphinNodeDblClicked: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, ReduxAction & {
26
+ cardID: string;
27
+ } & GraphinNodeEventContext<Record<string, unknown>>>) => void;
28
+ export declare const onGraphinTooltipOpen: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, ReduxAction & {
29
+ cardID: string;
30
+ } & GraphinNodeEventContext<Record<string, unknown>>>) => void;
31
+ export declare const onGraphinTooltipClose: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, ReduxAction & {
32
+ cardID: string;
33
+ } & GraphinNodeEventContext<Record<string, unknown>>>) => void;
34
+ export declare const onGraphinContextMenuOpen: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, ReduxAction & {
35
+ cardID: string;
36
+ } & GraphinNodeEventContext<Record<string, unknown>>>) => void;
37
+ export declare const onGraphinContextMenuClose: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, ReduxAction & {
38
+ cardID: string;
39
+ } & GraphinNodeEventContext<Record<string, unknown>>>) => void;
40
+ /**
41
+ * Payload carried by all node interaction events.
42
+ * Also forwarded as props to tooltip / context-menu `PiCard` content cards
43
+ * so they can render node-specific information.
44
+ */
45
+ export type GraphinNodeEventContext<T = Record<string, unknown>> = {
46
+ /** The G6 node id */
47
+ nodeId: string;
48
+ /** The node's `data` bag as stored in `GraphData` */
49
+ nodeData?: T;
50
+ /** Canvas x-coordinate of the pointer when the event fired */
51
+ x: number;
52
+ /** Canvas y-coordinate of the pointer when the event fired */
53
+ y: number;
54
+ };
55
+ /**
56
+ * Convenience union of every built-in G6 layout-type string.
57
+ *
58
+ * | Value | Description |
59
+ * |---|---|
60
+ * | `"force-atlas2"` | Force Atlas 2 – general-purpose force (default) |
61
+ * | `"force"` / `"gforce"` | Classic force-directed |
62
+ * | `"d3-force"` | D3 force simulation |
63
+ * | `"fruchterman"` | Fruchterman-Reingold force |
64
+ * | `"dagre"` | Hierarchical / DAG (Dagre) |
65
+ * | `"antv-dagre"` | AntV variant of Dagre |
66
+ * | `"circular"` | Nodes arranged in a circle |
67
+ * | `"concentric"` | Concentric rings ordered by degree |
68
+ * | `"radial"` | Radial tree from a focal node |
69
+ * | `"grid"` | Uniform grid |
70
+ * | `"mds"` | Multi-dimensional scaling |
71
+ * | `"random"` | Random positions |
72
+ * | `"snake"` | Snake / serpentine path |
73
+ * | `"fishbone"` | Fishbone / Ishikawa diagram |
74
+ */
75
+ export type GraphinLayoutType = "force-atlas2" | "force" | "gforce" | "d3-force" | "d3-force3d" | "fruchterman" | "fruchterman-gpu" | "dagre" | "antv-dagre" | "circular" | "concentric" | "radial" | "grid" | "mds" | "random" | "snake" | "fishbone";
5
76
  export type GraphinProps = {
6
77
  data: GraphData;
7
78
  options?: Partial<Omit<GraphOptions, "data">>;
79
+ /**
80
+ * Shorthand for `options.layout.type`. When provided it overrides whatever
81
+ * layout type is set inside `options.layout`, while still preserving any
82
+ * other layout parameters (e.g. `rankdir`, `preventOverlap`, …) you set
83
+ * via `options`.
84
+ *
85
+ * Pass the full options as `options.layout` when you also need to tweak
86
+ * layout-specific parameters.
87
+ *
88
+ * @default "force-atlas2"
89
+ */
90
+ layout?: GraphinLayoutType;
91
+ /**
92
+ * When `true` the default `zoom-canvas` behavior is removed, preventing
93
+ * the user from zooming in/out with the scroll wheel.
94
+ *
95
+ * Useful when the graph is embedded inside a scrollable page and you do
96
+ * not want accidental scroll events to zoom the canvas instead of
97
+ * scrolling the page.
98
+ *
99
+ * You can still customise or re-enable zoom by passing a `zoom-canvas`
100
+ * entry in `options.behaviors`.
101
+ *
102
+ * @default false
103
+ */
104
+ suppressZoom?: boolean;
105
+ /**
106
+ * When `true` the default `drag-canvas` behavior is removed, preventing
107
+ * the user from **panning** (moving the entire canvas) by click-dragging
108
+ * on the background.
109
+ *
110
+ * Useful when you want to lock the viewport (e.g. an embedded static
111
+ * overview) or when touch-scroll conflicts with canvas pan on mobile.
112
+ *
113
+ * You can still customise or re-enable panning by passing a `drag-canvas`
114
+ * entry in `options.behaviors`.
115
+ *
116
+ * @default false
117
+ */
118
+ suppressPan?: boolean;
119
+ /**
120
+ * When `true` the default `drag-element` behavior is removed, preventing
121
+ * the user from **dragging individual nodes** to rearrange them after the
122
+ * initial layout has been applied.
123
+ *
124
+ * By default nodes are freely repositionable. Set this to `true` to
125
+ * produce a read-only graph where the computed layout is preserved exactly.
126
+ *
127
+ * You can still customise or re-enable node dragging by passing a
128
+ * `drag-element` entry in `options.behaviors`.
129
+ *
130
+ * @default false
131
+ */
132
+ suppressDrag?: boolean;
133
+ /**
134
+ * Initial zoom level of the canvas viewport.
135
+ *
136
+ * **Range:** `0.02` – `16` (G6's default `zoomRange`)
137
+ * - `1` = 100 % (actual size)
138
+ * - `< 1` zooms out — e.g. `0.5` shows everything at 50 %
139
+ * - `> 1` zooms in — e.g. `2` shows everything at 200 %
140
+ *
141
+ * Setting this prop automatically disables G6's default `autoFit: 'view'`
142
+ * behaviour (which would otherwise fit the graph to the container and
143
+ * override the requested zoom level).
144
+ *
145
+ * The user can still change the zoom interactively via scroll unless
146
+ * `suppressZoom` is also set.
147
+ *
148
+ * @example 0.5 // 50 % — useful for large graphs; shows the full picture
149
+ * @example 1 // 100 % — natural size
150
+ * @example 2 // 200 % — start zoomed in on a small graph
151
+ */
152
+ zoomLevel?: number;
153
+ /**
154
+ * When `true` every edge is rendered with an arrowhead at its **target**
155
+ * end, making the graph visually directed.
156
+ *
157
+ * You can override arrow style granularly via
158
+ * `options.edge.style.endArrow` / `options.edge.style.startArrow`.
159
+ *
160
+ * @default false
161
+ */
162
+ directed?: boolean;
163
+ /**
164
+ * Hover tooltip — shown while the pointer is over a node or edge.
165
+ * The specified `PiCardDef` is rendered inside a floating panel with
166
+ * `pointerEvents: none`. The card receives `GraphinNodeEventContext`
167
+ * as extra props.
168
+ */
8
169
  tooltip?: GraphinTooltip;
170
+ /**
171
+ * Context panel — opens when the user clicks a node and stays visible
172
+ * until they click outside it or press the built-in ✕ close button.
173
+ * The panel is interactive (`pointerEvents: auto`) and passes an
174
+ * `onClose` callback as well as `GraphinNodeEventContext` to the card.
175
+ */
176
+ contextMenu?: GraphinContextMenu;
177
+ /**
178
+ * Serialisable map from **style name** → visual spec used to style nodes
179
+ * without JavaScript functions in props (required for Redux serialisation).
180
+ *
181
+ * Nodes and edges reference a style by setting a string field in their
182
+ * `data` object. The field name defaults to `"style"` and can be
183
+ * overridden with `nodeStyleKey`.
184
+ *
185
+ * The component builds the G6 style functions internally from this map, so
186
+ * the layout engine never re-runs when styles change — use the
187
+ * `dispatchGraphinUpdateNodeStyleMap` OP to update styles at runtime.
188
+ *
189
+ * @example
190
+ * ```ts
191
+ * nodeStyles: {
192
+ * gateway: { type: "star", fill: "#e67e22", size: 48, labelFill: "#fff" },
193
+ * service: { type: "circle", fill: "#2980b9", size: 32, labelFill: "#fff" },
194
+ * db: { type: "rect", fill: "#8e44ad", size: 22, labelFill: "#fff" },
195
+ * }
196
+ * // node data:
197
+ * { id: "gw", data: { displayName: "Gateway", style: "gateway" } }
198
+ * ```
199
+ */
200
+ nodeStyles?: GraphinNodeStyleMap;
201
+ /**
202
+ * The field name inside `node.data` that holds the style name to look up
203
+ * in `nodeStyles`.
204
+ *
205
+ * Useful when your data already has a different key (e.g. `"role"`,
206
+ * `"type"`, `"category"`).
207
+ *
208
+ * @default "style"
209
+ */
210
+ nodeStyleKey?: string;
9
211
  style?: {
10
212
  root?: React.CSSProperties;
11
213
  item?: React.CSSProperties;
@@ -13,6 +215,277 @@ export type GraphinProps = {
13
215
  className?: string;
14
216
  };
15
217
  export type GraphinTooltip = {
16
- node?: PiCardDef;
17
- edge?: PiCardDef;
218
+ /** Registered card name whose component is rendered inside the floating panel. */
219
+ node?: string;
220
+ edge?: string;
221
+ /**
222
+ * Pixel gap between the pointer position and the top-left corner of the
223
+ * tooltip panel. Pass a single number for equal x/y offset, or
224
+ * `[xOffset, yOffset]` to control each axis independently.
225
+ *
226
+ * @default 4
227
+ */
228
+ offset?: number | [number, number];
229
+ /**
230
+ * Extra CSS class name(s) applied to the tooltip wrapper `<div>`.
231
+ * Use this to override the default background / border / shadow via
232
+ * Tailwind utilities or your own CSS classes.
233
+ *
234
+ * @example "rounded-xl shadow-lg border-primary"
235
+ */
236
+ className?: string;
237
+ /**
238
+ * Inline style overrides for the tooltip wrapper `<div>`.
239
+ * Merged on top of the built-in positioning / pointer-events styles so
240
+ * you can safely override individual properties (e.g. `padding`, `zIndex`).
241
+ */
242
+ style?: React.CSSProperties;
243
+ };
244
+ export type GraphinContextMenu = {
245
+ /** Registered card name whose component is rendered inside the click panel. */
246
+ node?: string;
247
+ edge?: string;
248
+ /**
249
+ * Pixel gap between the click point and the top-left corner of the context
250
+ * panel. Pass a single number for equal x/y offset, or
251
+ * `[xOffset, yOffset]` to control each axis independently.
252
+ *
253
+ * @default 4
254
+ */
255
+ offset?: number | [number, number];
256
+ /**
257
+ * Extra CSS class name(s) applied to the context-menu wrapper `<div>`.
258
+ * Use this to override the default background / border / shadow via
259
+ * Tailwind utilities or your own CSS classes.
260
+ *
261
+ * @example "rounded-xl shadow-lg border-primary"
262
+ */
263
+ className?: string;
264
+ /**
265
+ * Inline style overrides for the context-menu wrapper `<div>`.
266
+ * Merged on top of the built-in positioning / pointer-events styles so
267
+ * you can safely override individual properties (e.g. `padding`, `zIndex`).
268
+ */
269
+ style?: React.CSSProperties;
270
+ };
271
+ /**
272
+ * Node shape types supported by G6 v5.
273
+ */
274
+ export type GraphinNodeShape = "circle" | "rect" | "diamond" | "star" | "triangle" | "hexagon" | "ellipse";
275
+ /**
276
+ * Serialisable visual specification for a named node style.
277
+ *
278
+ * All fields are optional — unset fields fall back to the card's base style.
279
+ */
280
+ export type GraphinNodeStyleDef = {
281
+ /** Node shape. @default "circle" */
282
+ type?: GraphinNodeShape;
283
+ /** Fill colour (CSS colour string). */
284
+ fill?: string;
285
+ /** Border colour. */
286
+ stroke?: string;
287
+ /** Border thickness in pixels. Alias: `strokeWidth` (takes precedence). */
288
+ lineWidth?: number;
289
+ /** Border thickness in pixels. Takes precedence over `lineWidth`. */
290
+ strokeWidth?: number;
291
+ /**
292
+ * Node size in pixels.
293
+ * Pass a number for a square/circle; pass `[width, height]` for a rectangle.
294
+ */
295
+ size?: number | [number, number];
296
+ /** Fill opacity 0–1. */
297
+ opacity?: number;
298
+ /** Label text colour. */
299
+ labelFill?: string;
300
+ /** Label font size in pixels. */
301
+ labelFontSize?: number;
302
+ };
303
+ /**
304
+ * Map from **style name** → visual spec.
305
+ *
306
+ * Nodes reference a style by setting a string field in their `data` object
307
+ * (default field name: `"style"`). The component looks up that name here
308
+ * and builds the G6 style functions internally — so no JavaScript functions
309
+ * ever appear in props (safe for Redux serialisation).
310
+ *
311
+ * @example
312
+ * ```ts
313
+ * nodeStyles: {
314
+ * gateway: { type: "star", fill: "#e67e22", size: 48 },
315
+ * service: { type: "circle", fill: "#2980b9", size: 32 },
316
+ * db: { type: "rect", fill: "#8e44ad", size: 22 },
317
+ * failed: { fill: "#e74c3c", stroke: "#c0392b", lineWidth: 3 },
318
+ * }
319
+ * ```
320
+ */
321
+ export type GraphinNodeStyleMap = Record<string, GraphinNodeStyleDef>;
322
+ /**
323
+ * OP actions let external code drive G6 imperatively (highlight nodes,
324
+ * zoom to a node, etc.) without touching `data` or `options` — so the
325
+ * layout engine NEVER re-runs.
326
+ *
327
+ * Dispatch with the `dispatchGraphin*` helpers exported from this module.
328
+ */
329
+ export declare const GRAPHIN_OP_ACTION: {
330
+ SET_NODE_STYLES: string;
331
+ CLEAR_NODE_STYLES: string;
332
+ ZOOM_TO_NODE: string;
333
+ UPDATE_NODE_STYLE_MAP: string;
334
+ };
335
+ /**
336
+ * Payload for `GRAPHIN_OP_ACTION.SET_NODE_STYLES`.
337
+ *
338
+ * Sets the style-name field (determined by `nodeStyleKey`, default `"style"`)
339
+ * on each specified node, then calls `graph.draw()` so the new style name is
340
+ * looked up in `nodeStyles` and applied visually — **zero layout re-runs**.
341
+ *
342
+ * @example
343
+ * ```ts
344
+ * // Mark two nodes as failed; they will immediately render with the "failed"
345
+ * // visual spec from the nodeStyles map.
346
+ * dispatchGraphinSetNodeStyles(dispatch, {
347
+ * cardName: "myGraph",
348
+ * nodeStyles: { "db-u": "failed", "users": "degraded" },
349
+ * });
350
+ * ```
351
+ */
352
+ export type GraphinSetNodeStylesAction = {
353
+ cardName: string;
354
+ /**
355
+ * Map of `nodeId` → style name or ordered list of style names to merge
356
+ * (each must be a key in the card's `nodeStyles` map).
357
+ * When an array is given, styles are merged left-to-right with later entries
358
+ * overriding duplicate properties from earlier ones.
359
+ * @example { n1: "failed", n2: ["base", "degraded"], n3: "ok" }
360
+ */
361
+ nodeStyles: Record<string, string | string[]>;
362
+ };
363
+ /**
364
+ * Payload for `GRAPHIN_OP_ACTION.CLEAR_NODE_STYLES`.
365
+ *
366
+ * Removes the style-name field from the specified nodes (or all nodes when
367
+ * `nodeIds` is omitted), reverting them to the default `nodeStyles` fallback
368
+ * appearance. Calls `graph.draw()` — **zero layout re-runs**.
369
+ *
370
+ * @example
371
+ * ```ts
372
+ * // Restore all nodes to their default style
373
+ * dispatchGraphinClearNodeStyles(dispatch, { cardName: "myGraph" });
374
+ * ```
375
+ */
376
+ export type GraphinClearNodeStylesAction = {
377
+ cardName: string;
378
+ /** Nodes to clear — omit to clear ALL nodes in the graph. */
379
+ nodeIds?: string[];
380
+ };
381
+ /**
382
+ * Payload for `GRAPHIN_OP_ACTION.ZOOM_TO_NODE`.
383
+ *
384
+ * Pans (and optionally zooms) the viewport so the target node is centred.
385
+ */
386
+ export type GraphinZoomToNodeAction = {
387
+ cardName: string;
388
+ nodeId: string;
389
+ /** Desired zoom level after centering. Omit to keep the current zoom. */
390
+ zoomLevel?: number;
391
+ /** Animation duration in milliseconds. @default 400 */
392
+ duration?: number;
393
+ };
394
+ /**
395
+ * Set the style name on individual nodes — zero layout re-runs.
396
+ *
397
+ * The style name is written to the `nodeStyleKey` field in each node's data
398
+ * bag, then `graph.draw()` is called so the `nodeStyles` map is re-evaluated
399
+ * and the new colour / shape / size appears immediately.
400
+ *
401
+ * @example
402
+ * ```ts
403
+ * dispatchGraphinSetNodeStyles(dispatch, {
404
+ * cardName: "myGraph",
405
+ * nodeStyles: { "db-u": "failed", "users": "degraded" },
406
+ * });
407
+ * ```
408
+ */
409
+ export declare const dispatchGraphinSetNodeStyles: (dispatch: DispatchF, payload: GraphinSetNodeStylesAction) => string;
410
+ /**
411
+ * Clear the style name from nodes (all nodes when `nodeIds` is omitted).
412
+ * Nodes revert to the default fallback appearance defined in the component.
413
+ *
414
+ * @example
415
+ * ```ts
416
+ * dispatchGraphinClearNodeStyles(dispatch, { cardName: "myGraph" });
417
+ * ```
418
+ */
419
+ export declare const dispatchGraphinClearNodeStyles: (dispatch: DispatchF, payload: GraphinClearNodeStylesAction) => string;
420
+ /**
421
+ * Pan (and optionally zoom) the viewport to centre a node.
422
+ *
423
+ * @example
424
+ * ```ts
425
+ * dispatchGraphinZoomToNode(dispatch, {
426
+ * cardName: "myGraph",
427
+ * nodeId: "n3",
428
+ * zoomLevel: 1.5,
429
+ * duration: 600,
430
+ * });
431
+ * ```
432
+ */
433
+ export declare const dispatchGraphinZoomToNode: (dispatch: DispatchF, payload: GraphinZoomToNodeAction) => string;
434
+ /**
435
+ * Payload for `GRAPHIN_OP_ACTION.UPDATE_NODE_STYLE_MAP`.
436
+ *
437
+ * Merges (or replaces) style definitions in the card's live style map and
438
+ * triggers a G6 re-draw — **without** re-running the layout engine.
439
+ *
440
+ * Use this to animate node colours, highlight failures, show traffic
441
+ * intensity, etc. at runtime.
442
+ */
443
+ export type GraphinUpdateNodeStyleMapAction = {
444
+ cardName: string;
445
+ /**
446
+ * Style definitions to merge into the current map.
447
+ * @example { failed: { fill: "#e74c3c", stroke: "#c0392b" } }
448
+ */
449
+ styles: GraphinNodeStyleMap;
450
+ /**
451
+ * When `true`, replaces the entire map instead of merging.
452
+ * @default false
453
+ */
454
+ replace?: boolean;
455
+ };
456
+ /**
457
+ * Merge new style definitions into the card's live node style map and
458
+ * trigger a re-draw — zero layout re-runs.
459
+ *
460
+ * The style map is kept in a React ref inside the component so updates are
461
+ * applied immediately without going through Redux state.
462
+ *
463
+ * @example
464
+ * ```ts
465
+ * // Mark "users" node style as failed (red) without touching node data
466
+ * dispatchGraphinUpdateNodeStyleMap(dispatch, {
467
+ * cardName: "myGraph",
468
+ * styles: { service: { fill: "#e74c3c", stroke: "#c0392b" } },
469
+ * });
470
+ * ```
471
+ */
472
+ export declare const dispatchGraphinUpdateNodeStyleMap: (dispatch: DispatchF, payload: GraphinUpdateNodeStyleMapAction) => string;
473
+ export type { ReduxAction };
474
+ export type GraphinEvents = {
475
+ /** Fired when the pointer enters a node */
476
+ onNodeHovered: GraphinNodeEventContext;
477
+ /** Fired when the pointer leaves a node */
478
+ onNodeHoverEnd: GraphinNodeEventContext;
479
+ /** Fired on a single click on a node */
480
+ onNodeClicked: GraphinNodeEventContext;
481
+ /** Fired on a double-click on a node */
482
+ onNodeDblClicked: GraphinNodeEventContext;
483
+ /** Fired when the hover tooltip becomes visible */
484
+ onTooltipOpen: GraphinNodeEventContext;
485
+ /** Fired when the hover tooltip is dismissed */
486
+ onTooltipClose: GraphinNodeEventContext;
487
+ /** Fired when the context-menu panel opens */
488
+ onContextMenuOpen: GraphinNodeEventContext;
489
+ /** Fired when the context-menu panel closes */
490
+ onContextMenuClose: GraphinNodeEventContext;
18
491
  };
@@ -0,0 +1,8 @@
1
+ import { GraphinNodeStyleMap } from './graphin.types';
2
+ export type GraphinOpHandlerProps = {
3
+ cardName: string;
4
+ nodeStylesRef: React.MutableRefObject<GraphinNodeStyleMap>;
5
+ /** Ref to the current nodeStyleKey (defaults to "style"). */
6
+ nodeStyleKeyRef: React.MutableRefObject<string>;
7
+ };
8
+ export declare function GraphinOpHandler({ cardName, nodeStylesRef, nodeStyleKeyRef, }: GraphinOpHandlerProps): null;
@@ -1,2 +1,3 @@
1
1
  export * from './graphin.types';
2
2
  export type { TooltipContext } from './tooltip.component';
3
+ export type { ContextMenuContext } from './contextMenu.component';
@@ -1,10 +1,22 @@
1
- import { GraphinTooltip } from './graphin.types';
1
+ import { GraphinNodeEventContext, GraphinTooltip } from './graphin.types';
2
+ /**
3
+ * Context forwarded to the tooltip content card as props.
4
+ *
5
+ * ```ts
6
+ * type MyTooltipProps = TooltipContext & { ... }
7
+ * ```
8
+ */
2
9
  export type TooltipContext<T = Record<string, unknown>> = {
10
+ /** `true` when the hovered element is an edge, `false` for a node */
3
11
  isEdge?: boolean;
12
+ /** The G6 element id */
4
13
  elementID?: string;
14
+ /** The element's raw `data` bag */
5
15
  elementData?: T;
6
16
  };
7
17
  export declare function TooltipComponent(props: {
8
18
  contentCards: GraphinTooltip;
9
19
  parentCard: string;
20
+ onOpen?: (ctx: GraphinNodeEventContext) => void;
21
+ onClose?: (ctx: GraphinNodeEventContext) => void;
10
22
  }): React.ReactNode;
@@ -1,13 +1,13 @@
1
1
  import { InputComponent as e } from "./input.component.js";
2
- import { PI_INPUT_ACTION as t, PI_INPUT_CARD as n, PiInput as r, onPiInputChanged as i, onPiInputCommitted as a } from "./input.types.js";
3
- import { actionTypesToEvents as o, registerCardComponent as s } from "@pihanga2/core";
2
+ import { PI_INPUT_ACTION as t, PI_INPUT_CARD as n, PiInput as r, onInputChanged as i, onInputCommitted as a, onPiInputChanged as o, onPiInputCommitted as s } from "./input.types.js";
3
+ import { actionTypesToEvents as c, registerCardComponent as l } from "@pihanga2/core";
4
4
  //#region src/cards/input/index.ts
5
- s({
5
+ l({
6
6
  name: n,
7
7
  component: e,
8
- events: o(t)
8
+ events: c(t)
9
9
  });
10
10
  //#endregion
11
- export { t as PI_INPUT_ACTION, n as PI_INPUT_CARD, r as PiInput, i as onPiInputChanged, a as onPiInputCommitted };
11
+ export { t as PI_INPUT_ACTION, n as PI_INPUT_CARD, r as PiInput, i as onInputChanged, a as onInputCommitted, o as onPiInputChanged, s as onPiInputCommitted };
12
12
 
13
13
  //# sourceMappingURL=index.js.map
@@ -1,6 +1,7 @@
1
1
  import { useFormContext as e } from "../form/form.context.js";
2
2
  import { Label as t } from "../../components/ui/label.js";
3
3
  import { Input as n } from "../../components/ui/input.js";
4
+ import "@pihanga2/core";
4
5
  import r from "react";
5
6
  import { jsx as i, jsxs as a } from "react/jsx-runtime";
6
7
  //#region src/cards/input/input.component.tsx
@@ -1 +1 @@
1
- {"version":3,"file":"input.component.js","names":[],"sources":["../../../src/cards/input/input.component.tsx"],"sourcesContent":["import React from \"react\";\nimport {type PiCardProps} from \"@pihanga2/core\";\nimport {Input} from \"@/components/ui/input\";\nimport {Label} from \"@/components/ui/label\";\nimport {useFormContext} from \"@/cards/form/form.context\";\nimport type {PiInputEvents, PiInputProps} from \"./input.types\";\n\nexport const InputComponent = (\n props: PiCardProps<PiInputProps, PiInputEvents>,\n): React.ReactNode => {\n const {\n name,\n value: propValue = \"\",\n type = \"text\",\n placeholder,\n disabled,\n label,\n description,\n className,\n cardName,\n onChanged,\n onCommitted,\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 // Local display state — lets the user type freely without triggering Redux\n // on every keystroke. Only `onCommitted` (blur / Enter) writes back to\n // Redux, so callers that use `onCommitted` instead of `onChanged` avoid\n // per-keystroke panel rebuilds.\n const [localValue, setLocalValue] = React.useState<string>(\n type === \"file\" ? \"\" : propValue,\n );\n\n // Sync local value when the prop changes from outside (e.g. when a different\n // card is selected in the playground, resetting the controls panel).\n React.useEffect(() => {\n if (!useFormData && type !== \"file\") {\n setLocalValue(propValue);\n }\n }, [propValue, useFormData, type]);\n\n // Derive the effective value for the controlled <Input>:\n // - inside a form → read from form.formData[name]\n // - standalone → use localValue (updated on every keystroke locally)\n // - file inputs → uncontrolled (no value binding)\n const inputValue =\n type === \"file\"\n ? undefined\n : useFormData\n ? ((form.formData[name!] as string | undefined) ?? \"\")\n : localValue;\n\n function handleChange(e: React.ChangeEvent<HTMLInputElement>) {\n const newValue =\n type === \"file\" ? (e.target.files?.[0]?.name ?? \"\") : e.target.value;\n if (useFormData) {\n form.handleChange(name!, newValue);\n } else {\n setLocalValue(newValue);\n onChanged({name, value: newValue});\n }\n }\n\n // Fire onCommitted when the user leaves the field or presses Enter.\n function handleBlur() {\n if (!useFormData && type !== \"file\") {\n onCommitted({name, value: localValue});\n }\n }\n\n function handleKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {\n if (e.key === \"Enter\" && !useFormData && type !== \"file\") {\n onCommitted({name, value: localValue});\n }\n }\n\n // Use the id injected by pi/field (for label↔control linking); fall back\n // to a locally-generated id when used standalone.\n const selfId = `${cardName}-${name ?? \"input\"}`;\n const fieldId = injectedId ?? selfId;\n\n return (\n <div data-pihanga={cardName} className=\"grid w-full gap-1.5\">\n {label && <Label htmlFor={fieldId}>{label}</Label>}\n <Input\n id={fieldId}\n type={type}\n value={inputValue}\n onChange={handleChange}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n disabled={disabled}\n className={className}\n aria-invalid={invalid || undefined}\n aria-describedby={description ? `${fieldId}-desc` : undefined}\n />\n {description && (\n <p id={`${fieldId}-desc`} className=\"text-sm text-muted-foreground\">\n {description}\n </p>\n )}\n </div>\n );\n};\n"],"mappings":";;;;;;AAOA,IAAa,KACX,MACoB;CACpB,IAAM,EACJ,SACA,OAAO,IAAY,IACnB,UAAO,QACP,gBACA,aACA,UACA,gBACA,cACA,aACA,cACA,mBACE,GAKE,IAAc,EAAwB,IACtC,IAAU,EAAS,EAA8B,SAGjD,IAAO,EAAe,GACtB,IAAc,EAAK,YAAY,EAAQ,GAMvC,CAAC,GAAY,KAAiB,EAAM,SACxC,MAAS,SAAS,KAAK,CACzB;CAIA,EAAM,gBAAgB;EACpB,AAAI,CAAC,KAAe,MAAS,UAC3B,EAAc,CAAS;CAE3B,GAAG;EAAC;EAAW;EAAa;CAAI,CAAC;CAMjC,IAAM,IACJ,MAAS,SACL,KAAA,IACA,IACI,EAAK,SAAS,MAAiC,KACjD;CAER,SAAS,EAAa,GAAwC;EAC5D,IAAM,IACJ,MAAS,SAAU,EAAE,OAAO,QAAQ,IAAI,QAAQ,KAAM,EAAE,OAAO;EACjE,AAAI,IACF,EAAK,aAAa,GAAO,CAAQ,KAEjC,EAAc,CAAQ,GACtB,EAAU;GAAC;GAAM,OAAO;EAAQ,CAAC;CAErC;CAGA,SAAS,IAAa;EACpB,AAAI,CAAC,KAAe,MAAS,UAC3B,EAAY;GAAC;GAAM,OAAO;EAAU,CAAC;CAEzC;CAEA,SAAS,EAAc,GAA0C;EAC/D,AAAI,EAAE,QAAQ,WAAW,CAAC,KAAe,MAAS,UAChD,EAAY;GAAC;GAAM,OAAO;EAAU,CAAC;CAEzC;CAIA,IAAM,IAAS,GAAG,EAAS,GAAG,KAAQ,WAChC,IAAU,KAAc;CAE9B,OACE,kBAAC,OAAD;EAAK,gBAAc;EAAU,WAAU;YAAvC;GACG,KAAS,kBAAC,GAAD;IAAO,SAAS;cAAU;GAAa,CAAA;GACjD,kBAAC,GAAD;IACE,IAAI;IACE;IACN,OAAO;IACP,UAAU;IACV,QAAQ;IACR,WAAW;IACE;IACH;IACC;IACX,gBAAc,KAAW,KAAA;IACzB,oBAAkB,IAAc,GAAG,EAAQ,SAAS,KAAA;GACrD,CAAA;GACA,KACC,kBAAC,KAAD;IAAG,IAAI,GAAG,EAAQ;IAAQ,WAAU;cACjC;GACA,CAAA;EAEF;;AAET"}
1
+ {"version":3,"file":"input.component.js","names":[],"sources":["../../../src/cards/input/input.component.tsx"],"sourcesContent":["import React from \"react\";\nimport {type PiCardProps} from \"@pihanga2/core\";\nimport {Input} from \"@/components/ui/input\";\nimport {Label} from \"@/components/ui/label\";\nimport {useFormContext} from \"@/cards/form/form.context\";\nimport type {PiInputEvents, PiInputProps} from \"./input.types\";\n\nexport const InputComponent = (\n props: PiCardProps<PiInputProps, PiInputEvents>,\n): React.ReactNode => {\n const {\n name,\n value: propValue = \"\",\n type = \"text\",\n placeholder,\n disabled,\n label,\n description,\n className,\n cardName,\n onChanged,\n onCommitted,\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 // Local display state — lets the user type freely without triggering Redux\n // on every keystroke. Only `onCommitted` (blur / Enter) writes back to\n // Redux, so callers that use `onCommitted` instead of `onChanged` avoid\n // per-keystroke panel rebuilds.\n const [localValue, setLocalValue] = React.useState<string>(\n type === \"file\" ? \"\" : propValue,\n );\n\n // Sync local value when the prop changes from outside (e.g. when a different\n // card is selected in the playground, resetting the controls panel).\n React.useEffect(() => {\n if (!useFormData && type !== \"file\") {\n setLocalValue(propValue);\n }\n }, [propValue, useFormData, type]);\n\n // Derive the effective value for the controlled <Input>:\n // - inside a form → read from form.formData[name]\n // - standalone → use localValue (updated on every keystroke locally)\n // - file inputs → uncontrolled (no value binding)\n const inputValue =\n type === \"file\"\n ? undefined\n : useFormData\n ? ((form.formData[name!] as string | undefined) ?? \"\")\n : localValue;\n\n function handleChange(e: React.ChangeEvent<HTMLInputElement>) {\n const newValue =\n type === \"file\" ? (e.target.files?.[0]?.name ?? \"\") : e.target.value;\n if (useFormData) {\n form.handleChange(name!, newValue);\n } else {\n setLocalValue(newValue);\n onChanged({name, value: newValue});\n }\n }\n\n // Fire onCommitted when the user leaves the field or presses Enter.\n function handleBlur() {\n if (!useFormData && type !== \"file\") {\n onCommitted({name, value: localValue});\n }\n }\n\n function handleKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {\n if (e.key === \"Enter\" && !useFormData && type !== \"file\") {\n onCommitted({name, value: localValue});\n }\n }\n\n // Use the id injected by pi/field (for label↔control linking); fall back\n // to a locally-generated id when used standalone.\n const selfId = `${cardName}-${name ?? \"input\"}`;\n const fieldId = injectedId ?? selfId;\n\n return (\n <div data-pihanga={cardName} className=\"grid w-full gap-1.5\">\n {label && <Label htmlFor={fieldId}>{label}</Label>}\n <Input\n id={fieldId}\n type={type}\n value={inputValue}\n onChange={handleChange}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n disabled={disabled}\n className={className}\n aria-invalid={invalid || undefined}\n aria-describedby={description ? `${fieldId}-desc` : undefined}\n />\n {description && (\n <p id={`${fieldId}-desc`} className=\"text-sm text-muted-foreground\">\n {description}\n </p>\n )}\n </div>\n );\n};\n"],"mappings":";;;;;;;AAOA,IAAa,KACX,MACoB;CACpB,IAAM,EACJ,SACA,OAAO,IAAY,IACnB,UAAO,QACP,gBACA,aACA,UACA,gBACA,cACA,aACA,cACA,mBACE,GAKE,IAAc,EAAwB,IACtC,IAAU,EAAS,EAA8B,SAGjD,IAAO,EAAe,GACtB,IAAc,EAAK,YAAY,EAAQ,GAMvC,CAAC,GAAY,KAAiB,EAAM,SACxC,MAAS,SAAS,KAAK,CACzB;CAIA,EAAM,gBAAgB;EACpB,AAAI,CAAC,KAAe,MAAS,UAC3B,EAAc,CAAS;CAE3B,GAAG;EAAC;EAAW;EAAa;CAAI,CAAC;CAMjC,IAAM,IACJ,MAAS,SACL,KAAA,IACA,IACI,EAAK,SAAS,MAAiC,KACjD;CAER,SAAS,EAAa,GAAwC;EAC5D,IAAM,IACJ,MAAS,SAAU,EAAE,OAAO,QAAQ,IAAI,QAAQ,KAAM,EAAE,OAAO;EACjE,AAAI,IACF,EAAK,aAAa,GAAO,CAAQ,KAEjC,EAAc,CAAQ,GACtB,EAAU;GAAC;GAAM,OAAO;EAAQ,CAAC;CAErC;CAGA,SAAS,IAAa;EACpB,AAAI,CAAC,KAAe,MAAS,UAC3B,EAAY;GAAC;GAAM,OAAO;EAAU,CAAC;CAEzC;CAEA,SAAS,EAAc,GAA0C;EAC/D,AAAI,EAAE,QAAQ,WAAW,CAAC,KAAe,MAAS,UAChD,EAAY;GAAC;GAAM,OAAO;EAAU,CAAC;CAEzC;CAIA,IAAM,IAAS,GAAG,EAAS,GAAG,KAAQ,WAChC,IAAU,KAAc;CAE9B,OACE,kBAAC,OAAD;EAAK,gBAAc;EAAU,WAAU;YAAvC;GACG,KAAS,kBAAC,GAAD;IAAO,SAAS;cAAU;GAAa,CAAA;GACjD,kBAAC,GAAD;IACE,IAAI;IACE;IACN,OAAO;IACP,UAAU;IACV,QAAQ;IACR,WAAW;IACE;IACH;IACC;IACX,gBAAc,KAAW,KAAA;IACzB,oBAAkB,IAAc,GAAG,EAAQ,SAAS,KAAA;GACrD,CAAA;GACA,KACC,kBAAC,KAAD;IAAG,IAAI,GAAG,EAAQ;IAAQ,WAAU;cACjC;GACA,CAAA;EAEF;;AAET"}
@@ -4,15 +4,23 @@ export declare const PI_INPUT_ACTION: {
4
4
  CHANGED: string;
5
5
  COMMITTED: string;
6
6
  };
7
+ export declare const onInputChanged: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
8
+ cardID: string;
9
+ } & PiInputChangedEvent>) => void;
10
+ /** @deprecated Use `onInputChanged` instead. */
7
11
  export declare const onPiInputChanged: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
8
12
  cardID: string;
9
13
  } & PiInputChangedEvent>) => void;
10
14
  /**
11
15
  * Subscribe to "committed" events — fired when the user finishes editing
12
- * (blur or Enter key). Unlike `onChanged` (which fires on every keystroke),
13
- * `onCommitted` only fires once per editing session, making it the preferred
16
+ * (blur or Enter key). Unlike `onInputChanged` (which fires on every keystroke),
17
+ * `onInputCommitted` only fires once per editing session, making it the preferred
14
18
  * handler for controlled inputs that trigger expensive downstream work.
15
19
  */
20
+ export declare const onInputCommitted: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
21
+ cardID: string;
22
+ } & PiInputCommittedEvent>) => void;
23
+ /** @deprecated Use `onInputCommitted` instead. */
16
24
  export declare const onPiInputCommitted: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
17
25
  cardID: string;
18
26
  } & PiInputCommittedEvent>) => 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/input/input.types.ts
3
- var r = "pi/input", i = e(r), a = n(r, ["changed", "committed"]), o = t(a.CHANGED), s = t(a.COMMITTED);
3
+ var r = "pi/input", i = e(r), a = n(r, ["changed", "committed"]), o = t(a.CHANGED), s = o, c = t(a.COMMITTED), l = c;
4
4
  //#endregion
5
- export { a as PI_INPUT_ACTION, r as PI_INPUT_CARD, i as PiInput, o as onPiInputChanged, s as onPiInputCommitted };
5
+ export { a as PI_INPUT_ACTION, r as PI_INPUT_CARD, i as PiInput, o as onInputChanged, c as onInputCommitted, s as onPiInputChanged, l as onPiInputCommitted };
6
6
 
7
7
  //# sourceMappingURL=input.types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"input.types.js","names":[],"sources":["../../../src/cards/input/input.types.ts"],"sourcesContent":["import {\n createCardDeclaration,\n createOnAction,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const PI_INPUT_CARD = \"pi/input\";\n\nexport const PiInput = createCardDeclaration<PiInputProps, PiInputEvents>(\n PI_INPUT_CARD,\n);\n\nexport const PI_INPUT_ACTION = registerActions(PI_INPUT_CARD, [\n \"changed\",\n \"committed\",\n]);\n\nexport const onPiInputChanged = createOnAction<PiInputChangedEvent>(\n PI_INPUT_ACTION.CHANGED,\n);\n\n/**\n * Subscribe to \"committed\" events — fired when the user finishes editing\n * (blur or Enter key). Unlike `onChanged` (which fires on every keystroke),\n * `onCommitted` only fires once per editing session, making it the preferred\n * handler for controlled inputs that trigger expensive downstream work.\n */\nexport const onPiInputCommitted = createOnAction<PiInputCommittedEvent>(\n PI_INPUT_ACTION.COMMITTED,\n);\n\n// ---------------------------------------------------------------------------\n// Props & Events\n// ---------------------------------------------------------------------------\n\nexport type PiInputProps = {\n /**\n * Field name used to bind to FormContext when inside a pi/form card.\n * When provided the component reads its value from form state and writes\n * back via form.handleChange.\n */\n name?: string;\n\n /**\n * Controlled value used in standalone mode (outside a Form).\n * Ignored when `name` is set and the component is inside a pi/form.\n */\n value?: string;\n\n /**\n * HTML input type.\n * Common values: \"text\" | \"email\" | \"password\" | \"number\" | \"search\" |\n * \"url\" | \"tel\" | \"date\" | \"file\".\n * Defaults to \"text\".\n */\n type?: string;\n\n /** Placeholder text shown when the input is empty. */\n placeholder?: string;\n\n /** When true, the input is disabled and non-interactive. */\n disabled?: boolean;\n\n /**\n * Optional label text rendered in a `<label>` element above the input.\n * The label is automatically associated with the input via `htmlFor`.\n */\n label?: string;\n\n /**\n * Optional helper / description text rendered below the input.\n * Use this for hints, formatting guidance, or validation feedback.\n */\n description?: string;\n\n /** Extra Tailwind / CSS classes forwarded to the underlying <input> element. */\n className?: string;\n};\n\nexport type PiInputChangedEvent = {\n /** Field name, mirrors the `name` prop if provided. */\n name?: string;\n /** New value after the change. */\n value: string;\n};\n\n/**\n * Payload for the `onCommitted` event (blur / Enter key).\n * Same shape as `PiInputChangedEvent`.\n */\nexport type PiInputCommittedEvent = {\n /** Field name, mirrors the `name` prop if provided. */\n name?: string;\n /** Final committed value. */\n value: string;\n};\n\nexport type PiInputEvents = {\n /** Fires on every keystroke. */\n onChanged: PiInputChangedEvent;\n /**\n * Fires once when the user finishes editing (blur or Enter key).\n * Use this instead of `onChanged` when each change triggers expensive\n * downstream work (e.g. rebuilding a panel).\n */\n onCommitted: PiInputCommittedEvent;\n};\n"],"mappings":";;AAMA,IAAa,IAAgB,YAEhB,IAAU,EACrB,CACF,GAEa,IAAkB,EAAgB,GAAe,CAC5D,WACA,WACF,CAAC,GAEY,IAAmB,EAC9B,EAAgB,OAClB,GAQa,IAAqB,EAChC,EAAgB,SAClB"}
1
+ {"version":3,"file":"input.types.js","names":[],"sources":["../../../src/cards/input/input.types.ts"],"sourcesContent":["import {\n createCardDeclaration,\n createOnAction,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const PI_INPUT_CARD = \"pi/input\";\n\nexport const PiInput = createCardDeclaration<PiInputProps, PiInputEvents>(\n PI_INPUT_CARD,\n);\n\nexport const PI_INPUT_ACTION = registerActions(PI_INPUT_CARD, [\n \"changed\",\n \"committed\",\n]);\n\nexport const onInputChanged = createOnAction<PiInputChangedEvent>(\n PI_INPUT_ACTION.CHANGED,\n);\n\n/** @deprecated Use `onInputChanged` instead. */\nexport const onPiInputChanged = onInputChanged;\n\n/**\n * Subscribe to \"committed\" events — fired when the user finishes editing\n * (blur or Enter key). Unlike `onInputChanged` (which fires on every keystroke),\n * `onInputCommitted` only fires once per editing session, making it the preferred\n * handler for controlled inputs that trigger expensive downstream work.\n */\nexport const onInputCommitted = createOnAction<PiInputCommittedEvent>(\n PI_INPUT_ACTION.COMMITTED,\n);\n\n/** @deprecated Use `onInputCommitted` instead. */\nexport const onPiInputCommitted = onInputCommitted;\n\n// ---------------------------------------------------------------------------\n// Props & Events\n// ---------------------------------------------------------------------------\n\nexport type PiInputProps = {\n /**\n * Field name used to bind to FormContext when inside a pi/form card.\n * When provided the component reads its value from form state and writes\n * back via form.handleChange.\n */\n name?: string;\n\n /**\n * Controlled value used in standalone mode (outside a Form).\n * Ignored when `name` is set and the component is inside a pi/form.\n */\n value?: string;\n\n /**\n * HTML input type.\n * Common values: \"text\" | \"email\" | \"password\" | \"number\" | \"search\" |\n * \"url\" | \"tel\" | \"date\" | \"file\".\n * Defaults to \"text\".\n */\n type?: string;\n\n /** Placeholder text shown when the input is empty. */\n placeholder?: string;\n\n /** When true, the input is disabled and non-interactive. */\n disabled?: boolean;\n\n /**\n * Optional label text rendered in a `<label>` element above the input.\n * The label is automatically associated with the input via `htmlFor`.\n */\n label?: string;\n\n /**\n * Optional helper / description text rendered below the input.\n * Use this for hints, formatting guidance, or validation feedback.\n */\n description?: string;\n\n /** Extra Tailwind / CSS classes forwarded to the underlying <input> element. */\n className?: string;\n};\n\nexport type PiInputChangedEvent = {\n /** Field name, mirrors the `name` prop if provided. */\n name?: string;\n /** New value after the change. */\n value: string;\n};\n\n/**\n * Payload for the `onCommitted` event (blur / Enter key).\n * Same shape as `PiInputChangedEvent`.\n */\nexport type PiInputCommittedEvent = {\n /** Field name, mirrors the `name` prop if provided. */\n name?: string;\n /** Final committed value. */\n value: string;\n};\n\nexport type PiInputEvents = {\n /** Fires on every keystroke. */\n onChanged: PiInputChangedEvent;\n /**\n * Fires once when the user finishes editing (blur or Enter key).\n * Use this instead of `onChanged` when each change triggers expensive\n * downstream work (e.g. rebuilding a panel).\n */\n onCommitted: PiInputCommittedEvent;\n};\n"],"mappings":";;AAMA,IAAa,IAAgB,YAEhB,IAAU,EACrB,CACF,GAEa,IAAkB,EAAgB,GAAe,CAC5D,WACA,WACF,CAAC,GAEY,IAAiB,EAC5B,EAAgB,OAClB,GAGa,IAAmB,GAQnB,IAAmB,EAC9B,EAAgB,SAClB,GAGa,IAAqB"}
@@ -1,4 +1,5 @@
1
1
  import { createCardDeclaration as e, createOnAction as t, registerActions as n } from "@pihanga2/core";
2
+ import "react";
2
3
  //#region src/cards/list/list.types.ts
3
4
  var r = "shad/list", i = e(r), a = n(r, ["item_clicked"]), o = t(a.ITEM_CLICKED);
4
5
  //#endregion