@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,11 +1,213 @@
|
|
|
1
|
-
import {
|
|
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,
|
|
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
|
-
|
|
17
|
-
|
|
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;
|
package/cards/graphin/index.d.ts
CHANGED
|
@@ -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;
|
package/cards/input/index.js
CHANGED
|
@@ -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,
|
|
3
|
-
import { actionTypesToEvents as
|
|
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
|
-
|
|
5
|
+
l({
|
|
6
6
|
name: n,
|
|
7
7
|
component: e,
|
|
8
|
-
events:
|
|
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
|
|
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":"
|
|
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 `
|
|
13
|
-
* `
|
|
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
|
|
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
|
|
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"}
|
package/cards/list/list.types.js
CHANGED