@pihanga2/shadcn 0.1.0 → 0.2.1

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 (99) hide show
  1. package/AGENT.building-cards.md +413 -0
  2. package/AGENT.md +57 -0
  3. package/AGENT.using-cards.md +1051 -0
  4. package/cards/box/box.component.js +2 -2
  5. package/cards/box/box.component.js.map +1 -1
  6. package/cards/box/box.types.d.ts +1 -4
  7. package/cards/box/box.types.js.map +1 -1
  8. package/cards/button/button.types.d.ts +3 -0
  9. package/cards/button/button.types.js +2 -2
  10. package/cards/button/button.types.js.map +1 -1
  11. package/cards/button/index.js +5 -5
  12. package/cards/chartGraph/chartGraph.component.d.ts +4 -0
  13. package/cards/chartGraph/chartGraph.types.d.ts +102 -0
  14. package/cards/chartGraph/index.d.ts +1 -0
  15. package/cards/conditional/conditional.component.d.ts +14 -3
  16. package/cards/conditional/conditional.component.js +17 -9
  17. package/cards/conditional/conditional.component.js.map +1 -1
  18. package/cards/conditional/conditional.types.d.ts +100 -8
  19. package/cards/conditional/conditional.types.js.map +1 -1
  20. package/cards/core-index.js +31 -31
  21. package/cards/fileDrop/fileDrop.component.d.ts +5 -0
  22. package/cards/fileDrop/fileDrop.types.d.ts +43 -0
  23. package/cards/fileDrop/index.d.ts +2 -0
  24. package/cards/graphin/contextMenu.component.d.ts +28 -0
  25. package/cards/graphin/eventDispatcher.component.d.ts +8 -0
  26. package/cards/graphin/graphin.component.d.ts +2 -2
  27. package/cards/graphin/graphin.playground-cards.d.ts +1 -0
  28. package/cards/graphin/graphin.types.d.ts +444 -4
  29. package/cards/graphin/graphinOpHandler.component.d.ts +8 -0
  30. package/cards/graphin/index.d.ts +1 -0
  31. package/cards/graphin/tooltip.component.d.ts +13 -1
  32. package/cards/icons.js +7 -3
  33. package/cards/icons.js.map +1 -1
  34. package/cards/index.d.ts +1 -0
  35. package/cards/slider/index.d.ts +1 -0
  36. package/cards/slider/slider.component.d.ts +4 -0
  37. package/cards/slider/slider.types.d.ts +102 -0
  38. package/cards/sliderValue/index.d.ts +1 -0
  39. package/cards/sliderValue/sliderValue.component.d.ts +15 -0
  40. package/cards/sliderValue/sliderValue.types.d.ts +21 -0
  41. package/cards/stack/stack.types.d.ts +19 -22
  42. package/cards/stack/stack.types.js +1 -1
  43. package/cards/stack/stack.types.js.map +1 -1
  44. package/cards/tabs/index.js +4 -4
  45. package/cards/tabs/tabs.component.js +51 -25
  46. package/cards/tabs/tabs.component.js.map +1 -1
  47. package/cards/tabs/tabs.types.d.ts +12 -0
  48. package/cards/tabs/tabs.types.js +2 -2
  49. package/cards/tabs/tabs.types.js.map +1 -1
  50. package/cards/types.d.ts +4 -0
  51. package/cards/types.js.map +1 -1
  52. package/components/hooks/use-breakpoint.d.ts +49 -0
  53. package/components/hooks/use-breakpoint.js +73 -0
  54. package/components/hooks/use-breakpoint.js.map +1 -0
  55. package/package.json +9 -1
  56. package/pihanga-shadcn.css +1 -1
  57. package/mountain-snow.svg +0 -4
  58. package/r/badge.json +0 -35
  59. package/r/box.json +0 -26
  60. package/r/button.json +0 -39
  61. package/r/checkbox.json +0 -31
  62. package/r/conditional.json +0 -30
  63. package/r/dataTable.json +0 -43
  64. package/r/dialog.json +0 -36
  65. package/r/dropDownMenu.json +0 -47
  66. package/r/field.json +0 -35
  67. package/r/flexGrid.json +0 -32
  68. package/r/form.json +0 -37
  69. package/r/framework.json +0 -28
  70. package/r/graphin.json +0 -42
  71. package/r/input.json +0 -35
  72. package/r/jsonViewer.json +0 -40
  73. package/r/list.json +0 -39
  74. package/r/loadingOverlay.json +0 -39
  75. package/r/loadingSkeleton.json +0 -30
  76. package/r/markdownViewer.json +0 -51
  77. package/r/menu.json +0 -34
  78. package/r/modeToggle.json +0 -36
  79. package/r/navbarSearch.json +0 -31
  80. package/r/pageWithNavbar.json +0 -46
  81. package/r/pasteTarget.json +0 -41
  82. package/r/pihanga-base.json +0 -11
  83. package/r/pihanga-cards-icons.json +0 -16
  84. package/r/pihanga-cards-types.json +0 -16
  85. package/r/pihanga-hook-use-is-touch-device.json +0 -15
  86. package/r/pihanga-lib-utils.json +0 -18
  87. package/r/pihanga-theme-provider.json +0 -25
  88. package/r/pihanga-ui-extras.json +0 -68
  89. package/r/registry.json +0 -171
  90. package/r/resizable.json +0 -35
  91. package/r/select.json +0 -35
  92. package/r/stack.json +0 -27
  93. package/r/stepper.json +0 -39
  94. package/r/switch.json +0 -36
  95. package/r/tabs.json +0 -33
  96. package/r/textField.json +0 -32
  97. package/r/toast.json +0 -32
  98. package/r/toggleGroup.json +0 -35
  99. package/r/typography.json +0 -31
@@ -0,0 +1,43 @@
1
+ export declare const FILE_DROP_CARD = "shad/file-drop";
2
+ export declare const FileDrop: <S extends import('@pihanga2/core').ReduxState>(p: import('@pihanga2/core').PiMapProps<FileDropProps<Record<string, unknown>>, S, FileDropEvents>) => import('@pihanga2/core').PiCardDef;
3
+ export declare const FILE_DROP_ACTION: {
4
+ ERROR: string;
5
+ FILE_DROPPED: string;
6
+ };
7
+ export declare const onFileDropped: <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
+ } & FileDroppedEvent>) => void;
10
+ export declare const onFileDropError: <S extends import('@pihanga2/core').ReduxState>(register: import('@pihanga2/core').PiRegister, f: import('@pihanga2/core').ReduceF<S, import('@pihanga2/core').ReduxAction & {
11
+ cardID: string;
12
+ } & FileDropErrorEvent>) => void;
13
+ export type FileDropProps<S = Record<string, unknown>> = {
14
+ /** Accepted file extensions, e.g. ["JPG", "PNG", "PDF"]. Defaults to ["JPG", "PNG", "GIF"]. */
15
+ fileTypes?: string[];
16
+ /** Heading shown inside the drop zone. */
17
+ title?: string;
18
+ /** Secondary text shown inside the drop zone. */
19
+ description?: string;
20
+ /** When true, shows a progress bar instead of the drop zone. */
21
+ showProgress?: boolean;
22
+ /** Inline styles applied to the drop zone wrapper. */
23
+ dropStyle?: Record<string, unknown>;
24
+ /** Inline styles applied to the progress bar container. */
25
+ progressStyle?: Record<string, unknown>;
26
+ /** Current upload progress (0–100). Only used when `showProgress` is true. */
27
+ progress?: number;
28
+ style?: S;
29
+ className?: string;
30
+ };
31
+ export declare const DEF_FILE_DROP_FILE_TYPES: string[];
32
+ export type FileDroppedEvent = {
33
+ name: string;
34
+ size: number;
35
+ type: string;
36
+ };
37
+ export type FileDropErrorEvent = {
38
+ error: string;
39
+ };
40
+ export type FileDropEvents = {
41
+ onFileDropped: FileDroppedEvent;
42
+ onError: FileDropErrorEvent;
43
+ };
@@ -0,0 +1,2 @@
1
+ export * from './fileDrop.types';
2
+ export { get_last_dropped } from './fileDrop.component';
@@ -0,0 +1,28 @@
1
+ import { default as React } from 'react';
2
+ import { GraphinContextMenu, GraphinNodeEventContext } from './graphin.types';
3
+ /**
4
+ * Context forwarded to the content card as props.
5
+ * Consumers can import this type to type their card props:
6
+ *
7
+ * ```ts
8
+ * type MyMenuProps = ContextMenuContext & { ... }
9
+ * ```
10
+ */
11
+ export type ContextMenuContext<T = Record<string, unknown>> = {
12
+ /** Whether this panel was triggered from an edge (vs node) */
13
+ isEdge?: boolean;
14
+ /** The G6 element id */
15
+ elementID?: string;
16
+ /** The element's raw `data` bag */
17
+ elementData?: T;
18
+ /**
19
+ * Call this to close the context menu panel from within the content card.
20
+ */
21
+ onClose?: () => void;
22
+ };
23
+ export declare function ContextMenuComponent(props: {
24
+ contentCards: GraphinContextMenu;
25
+ parentCard: string;
26
+ onOpen?: (ctx: GraphinNodeEventContext) => void;
27
+ onClose?: (ctx: GraphinNodeEventContext) => void;
28
+ }): React.ReactNode;
@@ -0,0 +1,8 @@
1
+ import { GraphinNodeEventContext } from './graphin.types';
2
+ export type GraphinEventDispatcherProps = {
3
+ onNodeHovered?: (ctx: GraphinNodeEventContext) => void;
4
+ onNodeHoverEnd?: (ctx: GraphinNodeEventContext) => void;
5
+ onNodeClicked?: (ctx: GraphinNodeEventContext) => void;
6
+ onNodeDblClicked?: (ctx: GraphinNodeEventContext) => void;
7
+ };
8
+ export declare function GraphinEventDispatcher(props: GraphinEventDispatcherProps): null;
@@ -1,4 +1,4 @@
1
1
  import { default as React } from 'react';
2
2
  import { PiCardProps } from '@pihanga2/core';
3
- import { GraphinProps } from './graphin.types';
4
- export declare const GraphinComponent: (props: PiCardProps<GraphinProps>) => React.ReactNode;
3
+ import { GraphinEvents, GraphinProps } from './graphin.types';
4
+ export declare const GraphinComponent: (props: PiCardProps<GraphinProps, GraphinEvents>) => React.ReactNode;
@@ -0,0 +1 @@
1
+ export {};
@@ -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,244 @@ 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
+ export type GraphinContextMenu = {
231
+ /** Registered card name whose component is rendered inside the click panel. */
232
+ node?: string;
233
+ edge?: string;
234
+ /**
235
+ * Pixel gap between the click point and the top-left corner of the context
236
+ * panel. Pass a single number for equal x/y offset, or
237
+ * `[xOffset, yOffset]` to control each axis independently.
238
+ *
239
+ * @default 4
240
+ */
241
+ offset?: number | [number, number];
242
+ };
243
+ /**
244
+ * Node shape types supported by G6 v5.
245
+ */
246
+ export type GraphinNodeShape = "circle" | "rect" | "diamond" | "star" | "triangle" | "hexagon" | "ellipse";
247
+ /**
248
+ * Serialisable visual specification for a named node style.
249
+ *
250
+ * All fields are optional — unset fields fall back to the card's base style.
251
+ */
252
+ export type GraphinNodeStyleDef = {
253
+ /** Node shape. @default "circle" */
254
+ type?: GraphinNodeShape;
255
+ /** Fill colour (CSS colour string). */
256
+ fill?: string;
257
+ /** Border colour. */
258
+ stroke?: string;
259
+ /** Border thickness in pixels. */
260
+ lineWidth?: number;
261
+ /**
262
+ * Node size in pixels.
263
+ * Pass a number for a square/circle; pass `[width, height]` for a rectangle.
264
+ */
265
+ size?: number | [number, number];
266
+ /** Fill opacity 0–1. */
267
+ opacity?: number;
268
+ /** Label text colour. */
269
+ labelFill?: string;
270
+ /** Label font size in pixels. */
271
+ labelFontSize?: number;
272
+ };
273
+ /**
274
+ * Map from **style name** → visual spec.
275
+ *
276
+ * Nodes reference a style by setting a string field in their `data` object
277
+ * (default field name: `"style"`). The component looks up that name here
278
+ * and builds the G6 style functions internally — so no JavaScript functions
279
+ * ever appear in props (safe for Redux serialisation).
280
+ *
281
+ * @example
282
+ * ```ts
283
+ * nodeStyles: {
284
+ * gateway: { type: "star", fill: "#e67e22", size: 48 },
285
+ * service: { type: "circle", fill: "#2980b9", size: 32 },
286
+ * db: { type: "rect", fill: "#8e44ad", size: 22 },
287
+ * failed: { fill: "#e74c3c", stroke: "#c0392b", lineWidth: 3 },
288
+ * }
289
+ * ```
290
+ */
291
+ export type GraphinNodeStyleMap = Record<string, GraphinNodeStyleDef>;
292
+ /**
293
+ * OP actions let external code drive G6 imperatively (highlight nodes,
294
+ * zoom to a node, etc.) without touching `data` or `options` — so the
295
+ * layout engine NEVER re-runs.
296
+ *
297
+ * Dispatch with the `dispatchGraphin*` helpers exported from this module.
298
+ */
299
+ export declare const GRAPHIN_OP_ACTION: {
300
+ SET_NODE_STYLES: string;
301
+ CLEAR_NODE_STYLES: string;
302
+ ZOOM_TO_NODE: string;
303
+ UPDATE_NODE_STYLE_MAP: string;
304
+ };
305
+ /**
306
+ * Payload for `GRAPHIN_OP_ACTION.SET_NODE_STYLES`.
307
+ *
308
+ * Sets the style-name field (determined by `nodeStyleKey`, default `"style"`)
309
+ * on each specified node, then calls `graph.draw()` so the new style name is
310
+ * looked up in `nodeStyles` and applied visually — **zero layout re-runs**.
311
+ *
312
+ * @example
313
+ * ```ts
314
+ * // Mark two nodes as failed; they will immediately render with the "failed"
315
+ * // visual spec from the nodeStyles map.
316
+ * dispatchGraphinSetNodeStyles(dispatch, {
317
+ * cardName: "myGraph",
318
+ * nodeStyles: { "db-u": "failed", "users": "degraded" },
319
+ * });
320
+ * ```
321
+ */
322
+ export type GraphinSetNodeStylesAction = {
323
+ cardName: string;
324
+ /**
325
+ * Map of `nodeId` → style name (must be a key in the card's `nodeStyles` map).
326
+ * @example { n1: "failed", n2: "degraded", n3: "ok" }
327
+ */
328
+ nodeStyles: Record<string, string>;
329
+ };
330
+ /**
331
+ * Payload for `GRAPHIN_OP_ACTION.CLEAR_NODE_STYLES`.
332
+ *
333
+ * Removes the style-name field from the specified nodes (or all nodes when
334
+ * `nodeIds` is omitted), reverting them to the default `nodeStyles` fallback
335
+ * appearance. Calls `graph.draw()` — **zero layout re-runs**.
336
+ *
337
+ * @example
338
+ * ```ts
339
+ * // Restore all nodes to their default style
340
+ * dispatchGraphinClearNodeStyles(dispatch, { cardName: "myGraph" });
341
+ * ```
342
+ */
343
+ export type GraphinClearNodeStylesAction = {
344
+ cardName: string;
345
+ /** Nodes to clear — omit to clear ALL nodes in the graph. */
346
+ nodeIds?: string[];
347
+ };
348
+ /**
349
+ * Payload for `GRAPHIN_OP_ACTION.ZOOM_TO_NODE`.
350
+ *
351
+ * Pans (and optionally zooms) the viewport so the target node is centred.
352
+ */
353
+ export type GraphinZoomToNodeAction = {
354
+ cardName: string;
355
+ nodeId: string;
356
+ /** Desired zoom level after centering. Omit to keep the current zoom. */
357
+ zoomLevel?: number;
358
+ /** Animation duration in milliseconds. @default 400 */
359
+ duration?: number;
360
+ };
361
+ /**
362
+ * Set the style name on individual nodes — zero layout re-runs.
363
+ *
364
+ * The style name is written to the `nodeStyleKey` field in each node's data
365
+ * bag, then `graph.draw()` is called so the `nodeStyles` map is re-evaluated
366
+ * and the new colour / shape / size appears immediately.
367
+ *
368
+ * @example
369
+ * ```ts
370
+ * dispatchGraphinSetNodeStyles(dispatch, {
371
+ * cardName: "myGraph",
372
+ * nodeStyles: { "db-u": "failed", "users": "degraded" },
373
+ * });
374
+ * ```
375
+ */
376
+ export declare const dispatchGraphinSetNodeStyles: (dispatch: DispatchF, payload: GraphinSetNodeStylesAction) => string;
377
+ /**
378
+ * Clear the style name from nodes (all nodes when `nodeIds` is omitted).
379
+ * Nodes revert to the default fallback appearance defined in the component.
380
+ *
381
+ * @example
382
+ * ```ts
383
+ * dispatchGraphinClearNodeStyles(dispatch, { cardName: "myGraph" });
384
+ * ```
385
+ */
386
+ export declare const dispatchGraphinClearNodeStyles: (dispatch: DispatchF, payload: GraphinClearNodeStylesAction) => string;
387
+ /**
388
+ * Pan (and optionally zoom) the viewport to centre a node.
389
+ *
390
+ * @example
391
+ * ```ts
392
+ * dispatchGraphinZoomToNode(dispatch, {
393
+ * cardName: "myGraph",
394
+ * nodeId: "n3",
395
+ * zoomLevel: 1.5,
396
+ * duration: 600,
397
+ * });
398
+ * ```
399
+ */
400
+ export declare const dispatchGraphinZoomToNode: (dispatch: DispatchF, payload: GraphinZoomToNodeAction) => string;
401
+ /**
402
+ * Payload for `GRAPHIN_OP_ACTION.UPDATE_NODE_STYLE_MAP`.
403
+ *
404
+ * Merges (or replaces) style definitions in the card's live style map and
405
+ * triggers a G6 re-draw — **without** re-running the layout engine.
406
+ *
407
+ * Use this to animate node colours, highlight failures, show traffic
408
+ * intensity, etc. at runtime.
409
+ */
410
+ export type GraphinUpdateNodeStyleMapAction = {
411
+ cardName: string;
412
+ /**
413
+ * Style definitions to merge into the current map.
414
+ * @example { failed: { fill: "#e74c3c", stroke: "#c0392b" } }
415
+ */
416
+ styles: GraphinNodeStyleMap;
417
+ /**
418
+ * When `true`, replaces the entire map instead of merging.
419
+ * @default false
420
+ */
421
+ replace?: boolean;
422
+ };
423
+ /**
424
+ * Merge new style definitions into the card's live node style map and
425
+ * trigger a re-draw — zero layout re-runs.
426
+ *
427
+ * The style map is kept in a React ref inside the component so updates are
428
+ * applied immediately without going through Redux state.
429
+ *
430
+ * @example
431
+ * ```ts
432
+ * // Mark "users" node style as failed (red) without touching node data
433
+ * dispatchGraphinUpdateNodeStyleMap(dispatch, {
434
+ * cardName: "myGraph",
435
+ * styles: { service: { fill: "#e74c3c", stroke: "#c0392b" } },
436
+ * });
437
+ * ```
438
+ */
439
+ export declare const dispatchGraphinUpdateNodeStyleMap: (dispatch: DispatchF, payload: GraphinUpdateNodeStyleMapAction) => string;
440
+ export type { ReduxAction };
441
+ export type GraphinEvents = {
442
+ /** Fired when the pointer enters a node */
443
+ onNodeHovered: GraphinNodeEventContext;
444
+ /** Fired when the pointer leaves a node */
445
+ onNodeHoverEnd: GraphinNodeEventContext;
446
+ /** Fired on a single click on a node */
447
+ onNodeClicked: GraphinNodeEventContext;
448
+ /** Fired on a double-click on a node */
449
+ onNodeDblClicked: GraphinNodeEventContext;
450
+ /** Fired when the hover tooltip becomes visible */
451
+ onTooltipOpen: GraphinNodeEventContext;
452
+ /** Fired when the hover tooltip is dismissed */
453
+ onTooltipClose: GraphinNodeEventContext;
454
+ /** Fired when the context-menu panel opens */
455
+ onContextMenuOpen: GraphinNodeEventContext;
456
+ /** Fired when the context-menu panel closes */
457
+ onContextMenuClose: GraphinNodeEventContext;
18
458
  };
@@ -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;
package/cards/icons.js CHANGED
@@ -2,14 +2,18 @@ import e from "react";
2
2
  //#region src/cards/icons.ts
3
3
  window._PihangaIcons = window._PihangaIcons || { name2icon: {} };
4
4
  var t = window._PihangaIcons.name2icon;
5
- function n(e) {
5
+ function n(e, n) {
6
+ if (t[e] !== void 0) throw Error(`icon '${e}' already registered`);
7
+ return t[e] = n, e;
8
+ }
9
+ function r(e) {
6
10
  return t[e];
7
11
  }
8
- function r(n, r) {
12
+ function i(n, r) {
9
13
  let i = t[n];
10
14
  return i ? e.createElement(i, r) : null;
11
15
  }
12
16
  //#endregion
13
- export { r as getIcon, n as getIconElement };
17
+ export { i as getIcon, r as getIconElement, n as registerIcon };
14
18
 
15
19
  //# sourceMappingURL=icons.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"icons.js","names":[],"sources":["../../src/cards/icons.ts"],"sourcesContent":["import React from \"react\";\n\ntype G = {\n name2icon: {[name: string]: React.ElementType};\n};\n\ndeclare global {\n interface Window {\n _PihangaIcons: G;\n }\n}\n\nwindow._PihangaIcons = window._PihangaIcons || {\n name2icon: {},\n};\n\nconst name2icon = window._PihangaIcons.name2icon;\n\n\n\nexport function registerIcon(name: string, el: React.ElementType): string {\n if (name2icon[name] !== undefined) {\n throw new Error(`icon '${name}' already registered`);\n }\n name2icon[name] = el;\n return name;\n}\n\nexport function getIconElement(name: string): React.ElementType | undefined {\n return name2icon[name];\n}\n\n// can't figure out what the proper return type is, SVvgIconT does\n// NOT work with <IconButton>\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function getIcon(name: string, props?: any): React.ReactNode {\n const icon = name2icon[name];\n if (!icon) return null;\n const el = React.createElement(icon, props);\n return el;\n}\n"],"mappings":";;AAYA,OAAO,gBAAgB,OAAO,iBAAiB,EAC7C,WAAW,CAAC,EACd;AAEA,IAAM,IAAY,OAAO,cAAc;AAYvC,SAAgB,EAAe,GAA6C;CAC1E,OAAO,EAAU;AACnB;AAKA,SAAgB,EAAQ,GAAc,GAA8B;CAClE,IAAM,IAAO,EAAU;CAGvB,OAFK,IACM,EAAM,cAAc,GAAM,CAC9B,IAFW;AAGpB"}
1
+ {"version":3,"file":"icons.js","names":[],"sources":["../../src/cards/icons.ts"],"sourcesContent":["import React from \"react\";\n\ntype G = {\n name2icon: {[name: string]: React.ElementType};\n};\n\ndeclare global {\n interface Window {\n _PihangaIcons: G;\n }\n}\n\nwindow._PihangaIcons = window._PihangaIcons || {\n name2icon: {},\n};\n\nconst name2icon = window._PihangaIcons.name2icon;\n\n\n\nexport function registerIcon(name: string, el: React.ElementType): string {\n if (name2icon[name] !== undefined) {\n throw new Error(`icon '${name}' already registered`);\n }\n name2icon[name] = el;\n return name;\n}\n\nexport function getIconElement(name: string): React.ElementType | undefined {\n return name2icon[name];\n}\n\n// can't figure out what the proper return type is, SVvgIconT does\n// NOT work with <IconButton>\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function getIcon(name: string, props?: any): React.ReactNode {\n const icon = name2icon[name];\n if (!icon) return null;\n const el = React.createElement(icon, props);\n return el;\n}\n"],"mappings":";;AAYA,OAAO,gBAAgB,OAAO,iBAAiB,EAC7C,WAAW,CAAC,EACd;AAEA,IAAM,IAAY,OAAO,cAAc;AAIvC,SAAgB,EAAa,GAAc,GAA+B;CACxE,IAAI,EAAU,OAAU,KAAA,GACtB,MAAU,MAAM,SAAS,EAAK,qBAAqB;CAGrD,OADA,EAAU,KAAQ,GACX;AACT;AAEA,SAAgB,EAAe,GAA6C;CAC1E,OAAO,EAAU;AACnB;AAKA,SAAgB,EAAQ,GAAc,GAA8B;CAClE,IAAM,IAAO,EAAU;CAGvB,OAFK,IACM,EAAM,cAAc,GAAM,CAC9B,IAFW;AAGpB"}
@@ -0,0 +1 @@
1
+ export * from './types';
@@ -0,0 +1 @@
1
+ export * from './slider.types';
@@ -0,0 +1,4 @@
1
+ import { default as React } from 'react';
2
+ import { PiCardProps } from '@pihanga2/core';
3
+ import { PiSliderEvents, PiSliderProps } from './slider.types';
4
+ export declare const SliderComponent: (props: PiCardProps<PiSliderProps, PiSliderEvents>) => React.ReactNode;