@aiready/components 0.13.11 → 0.13.13
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/dist/charts/ForceDirectedGraph.js +19 -22
- package/dist/charts/ForceDirectedGraph.js.map +1 -1
- package/dist/hooks/useForceSimulation.d.ts +1 -0
- package/dist/hooks/useForceSimulation.js +20 -19
- package/dist/hooks/useForceSimulation.js.map +1 -1
- package/dist/index.d.ts +20 -20
- package/dist/index.js +187 -279
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/charts/ForceDirectedGraph.tsx +30 -22
- package/src/components/icons/IconBase.tsx +31 -0
- package/src/components/icons/index.tsx +99 -164
- package/src/hooks/simulation-helpers.ts +31 -0
- package/src/hooks/simulation-types.ts +158 -0
- package/src/hooks/useForceSimulation.ts +20 -175
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiready/components",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.13",
|
|
4
4
|
"description": "Unified shared components library (UI, charts, hooks, utilities) for AIReady",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"framer-motion": "^12.35.0",
|
|
129
129
|
"lucide-react": "^0.577.0",
|
|
130
130
|
"tailwind-merge": "^3.0.0",
|
|
131
|
-
"@aiready/core": "0.23.
|
|
131
|
+
"@aiready/core": "0.23.14"
|
|
132
132
|
},
|
|
133
133
|
"devDependencies": {
|
|
134
134
|
"@testing-library/jest-dom": "^6.6.5",
|
|
@@ -106,6 +106,28 @@ export interface ForceDirectedGraphProps {
|
|
|
106
106
|
onLayoutChange?: (layout: LayoutType) => void;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
/**
|
|
110
|
+
* Helper functions for graph node manipulation.
|
|
111
|
+
* Extracted to reduce semantic duplicate patterns.
|
|
112
|
+
*/
|
|
113
|
+
|
|
114
|
+
/** Pins a node to its current position (sets fx/fy to current x/y) */
|
|
115
|
+
function pinNode(node: GraphNode): void {
|
|
116
|
+
node.fx = node.x;
|
|
117
|
+
node.fy = node.y;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Unpins a node (sets fx/fy to null) */
|
|
121
|
+
function unpinNode(node: GraphNode): void {
|
|
122
|
+
node.fx = null;
|
|
123
|
+
node.fy = null;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Unpins all nodes - helper for bulk unpin operations */
|
|
127
|
+
function unpinAllNodes(nodes: GraphNode[]): void {
|
|
128
|
+
nodes.forEach(unpinNode);
|
|
129
|
+
}
|
|
130
|
+
|
|
109
131
|
/**
|
|
110
132
|
* An interactive Force-Directed Graph component using D3.js for physics and React for rendering.
|
|
111
133
|
*
|
|
@@ -218,26 +240,19 @@ export const ForceDirectedGraph = forwardRef<
|
|
|
218
240
|
pinAll: () => {
|
|
219
241
|
const newPinned = new Set<string>();
|
|
220
242
|
nodes.forEach((node) => {
|
|
221
|
-
node
|
|
222
|
-
node.fy = node.y;
|
|
243
|
+
pinNode(node);
|
|
223
244
|
newPinned.add(node.id);
|
|
224
245
|
});
|
|
225
246
|
setPinnedNodes(newPinned);
|
|
226
247
|
restart();
|
|
227
248
|
},
|
|
228
249
|
unpinAll: () => {
|
|
229
|
-
nodes
|
|
230
|
-
node.fx = null;
|
|
231
|
-
node.fy = null;
|
|
232
|
-
});
|
|
250
|
+
unpinAllNodes(nodes);
|
|
233
251
|
setPinnedNodes(new Set());
|
|
234
252
|
restart();
|
|
235
253
|
},
|
|
236
254
|
resetLayout: () => {
|
|
237
|
-
nodes
|
|
238
|
-
node.fx = null;
|
|
239
|
-
node.fy = null;
|
|
240
|
-
});
|
|
255
|
+
unpinAllNodes(nodes);
|
|
241
256
|
setPinnedNodes(new Set());
|
|
242
257
|
restart();
|
|
243
258
|
},
|
|
@@ -352,8 +367,7 @@ export const ForceDirectedGraph = forwardRef<
|
|
|
352
367
|
event.stopPropagation();
|
|
353
368
|
dragActiveRef.current = true;
|
|
354
369
|
dragNodeRef.current = node;
|
|
355
|
-
node
|
|
356
|
-
node.fy = node.y;
|
|
370
|
+
pinNode(node);
|
|
357
371
|
setPinnedNodes((prev) => new Set([...prev, node.id]));
|
|
358
372
|
stop();
|
|
359
373
|
},
|
|
@@ -378,8 +392,7 @@ export const ForceDirectedGraph = forwardRef<
|
|
|
378
392
|
if (!event.active) restart();
|
|
379
393
|
dragActiveRef.current = true;
|
|
380
394
|
dragNodeRef.current = node;
|
|
381
|
-
node
|
|
382
|
-
node.fy = node.y;
|
|
395
|
+
pinNode(node);
|
|
383
396
|
setPinnedNodes((prev) => new Set([...prev, node.id]));
|
|
384
397
|
})
|
|
385
398
|
.on('drag', (event: any) => {
|
|
@@ -416,12 +429,10 @@ export const ForceDirectedGraph = forwardRef<
|
|
|
416
429
|
event.stopPropagation();
|
|
417
430
|
if (!enableDrag) return;
|
|
418
431
|
if (node.fx === null || node.fx === undefined) {
|
|
419
|
-
node
|
|
420
|
-
node.fy = node.y;
|
|
432
|
+
pinNode(node);
|
|
421
433
|
setPinnedNodes((prev) => new Set([...prev, node.id]));
|
|
422
434
|
} else {
|
|
423
|
-
node
|
|
424
|
-
node.fy = null;
|
|
435
|
+
unpinNode(node);
|
|
425
436
|
setPinnedNodes((prev) => {
|
|
426
437
|
const next = new Set(prev);
|
|
427
438
|
next.delete(node.id);
|
|
@@ -440,10 +451,7 @@ export const ForceDirectedGraph = forwardRef<
|
|
|
440
451
|
height={height}
|
|
441
452
|
className={cn('bg-white dark:bg-gray-900', className)}
|
|
442
453
|
onDoubleClick={() => {
|
|
443
|
-
nodes
|
|
444
|
-
n.fx = null;
|
|
445
|
-
n.fy = null;
|
|
446
|
-
});
|
|
454
|
+
unpinAllNodes(nodes);
|
|
447
455
|
setPinnedNodes(new Set());
|
|
448
456
|
restart();
|
|
449
457
|
}}
|
|
@@ -10,6 +10,37 @@ export interface IconBaseProps extends React.SVGProps<SVGSVGElement> {
|
|
|
10
10
|
viewBox?: string;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Common stroke props for line-based icons.
|
|
15
|
+
* Reduces duplication across icon components.
|
|
16
|
+
*/
|
|
17
|
+
export const STROKE_ICON_PROPS = {
|
|
18
|
+
strokeWidth: 2,
|
|
19
|
+
strokeLinecap: 'round' as const,
|
|
20
|
+
strokeLinejoin: 'round' as const,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Creates an icon component with common stroke props pre-applied.
|
|
25
|
+
* Reduces semantic duplicate patterns in icon definitions.
|
|
26
|
+
*
|
|
27
|
+
* @param _name - Name of the icon (reserved for debugging/future use)
|
|
28
|
+
* @param children - SVG child elements (paths, circles, etc.)
|
|
29
|
+
* @param additionalProps - Additional props to pass to IconBase
|
|
30
|
+
* @returns Icon component with standard stroke styling
|
|
31
|
+
*/
|
|
32
|
+
export function createStrokeIcon(
|
|
33
|
+
_name: string,
|
|
34
|
+
children: React.ReactNode,
|
|
35
|
+
additionalProps?: Partial<IconBaseProps>
|
|
36
|
+
): React.ReactElement {
|
|
37
|
+
return (
|
|
38
|
+
<IconBase {...STROKE_ICON_PROPS} {...additionalProps}>
|
|
39
|
+
{children}
|
|
40
|
+
</IconBase>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
13
44
|
/**
|
|
14
45
|
* A shared base component for all icons to reduce code duplication
|
|
15
46
|
* and improve AI signal clarity.
|
|
@@ -1,60 +1,49 @@
|
|
|
1
|
-
import { IconBase, IconBaseProps } from './IconBase';
|
|
1
|
+
import { IconBase, IconBaseProps, createStrokeIcon } from './IconBase';
|
|
2
2
|
|
|
3
|
+
// Icons using common stroke props - uses factory to reduce duplication
|
|
3
4
|
export function AlertCircleIcon(props: IconBaseProps) {
|
|
4
|
-
return (
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
strokeLinecap="round"
|
|
8
|
-
strokeLinejoin="round"
|
|
9
|
-
{...props}
|
|
10
|
-
>
|
|
5
|
+
return createStrokeIcon(
|
|
6
|
+
'AlertCircle',
|
|
7
|
+
<>
|
|
11
8
|
<circle cx="12" cy="12" r="10" />
|
|
12
9
|
<line x1="12" y1="8" x2="12" y2="12" />
|
|
13
10
|
<line x1="12" y1="16" x2="12.01" y2="16" />
|
|
14
|
-
|
|
11
|
+
</>,
|
|
12
|
+
props
|
|
15
13
|
);
|
|
16
14
|
}
|
|
17
15
|
|
|
18
16
|
export function AlertTriangleIcon(props: IconBaseProps) {
|
|
19
|
-
return (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
strokeLinecap="round"
|
|
23
|
-
strokeLinejoin="round"
|
|
24
|
-
{...props}
|
|
25
|
-
>
|
|
17
|
+
return createStrokeIcon(
|
|
18
|
+
'AlertTriangle',
|
|
19
|
+
<>
|
|
26
20
|
<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" />
|
|
27
21
|
<line x1="12" y1="9" x2="12" y2="13" />
|
|
28
22
|
<line x1="12" y1="17" x2="12.01" y2="17" />
|
|
29
|
-
|
|
23
|
+
</>,
|
|
24
|
+
props
|
|
30
25
|
);
|
|
31
26
|
}
|
|
32
27
|
|
|
33
28
|
export function ArrowRightIcon(props: IconBaseProps) {
|
|
34
|
-
return (
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
strokeLinecap="round"
|
|
38
|
-
strokeLinejoin="round"
|
|
39
|
-
{...props}
|
|
40
|
-
>
|
|
29
|
+
return createStrokeIcon(
|
|
30
|
+
'ArrowRight',
|
|
31
|
+
<>
|
|
41
32
|
<line x1="5" y1="12" x2="19" y2="12" />
|
|
42
33
|
<polyline points="12 5 19 12 12 19" />
|
|
43
|
-
|
|
34
|
+
</>,
|
|
35
|
+
props
|
|
44
36
|
);
|
|
45
37
|
}
|
|
46
38
|
|
|
47
39
|
export function BrainIcon(props: IconBaseProps) {
|
|
48
|
-
return (
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
strokeLinecap="round"
|
|
52
|
-
strokeLinejoin="round"
|
|
53
|
-
{...props}
|
|
54
|
-
>
|
|
40
|
+
return createStrokeIcon(
|
|
41
|
+
'Brain',
|
|
42
|
+
<>
|
|
55
43
|
<path d="M9.5 2A2.5 2.5 0 0 1 12 4.5v15a2.5 2.5 0 0 1-4.96.44 2.5 2.5 0 0 1-2.74-3.41A2.5 2.5 0 0 1 2 14c0-1.5 1-2 1-2s-1-.5-1-2a2.5 2.5 0 0 1 2.3-2.48A2.5 2.5 0 0 1 7 5.5a2.5 2.5 0 0 1 2.5-3.5z" />
|
|
56
44
|
<path d="M14.5 2A2.5 2.5 0 0 0 12 4.5v15a2.5 2.5 0 0 0 4.96.44 2.5 2.5 0 0 0 2.74-3.41A2.5 2.5 0 0 0 22 14c0-1.5-1-2-1-2s1-.5 1-2a2.5 2.5 0 0 0-2.3-2.48A2.5 2.5 0 0 0 17 5.5a2.5 2.5 0 0 0-2.5-3.5z" />
|
|
57
|
-
|
|
45
|
+
</>,
|
|
46
|
+
props
|
|
58
47
|
);
|
|
59
48
|
}
|
|
60
49
|
|
|
@@ -70,88 +59,68 @@ export function ChartIcon(props: IconBaseProps) {
|
|
|
70
59
|
}
|
|
71
60
|
|
|
72
61
|
export function ClockIcon(props: IconBaseProps) {
|
|
73
|
-
return (
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
strokeLinecap="round"
|
|
77
|
-
strokeLinejoin="round"
|
|
78
|
-
{...props}
|
|
79
|
-
>
|
|
62
|
+
return createStrokeIcon(
|
|
63
|
+
'Clock',
|
|
64
|
+
<>
|
|
80
65
|
<circle cx="12" cy="12" r="10" />
|
|
81
66
|
<polyline points="12 6 12 12 16 14" />
|
|
82
|
-
|
|
67
|
+
</>,
|
|
68
|
+
props
|
|
83
69
|
);
|
|
84
70
|
}
|
|
85
71
|
|
|
86
72
|
export function FileIcon(props: IconBaseProps) {
|
|
87
|
-
return (
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
strokeLinecap="round"
|
|
91
|
-
strokeLinejoin="round"
|
|
92
|
-
{...props}
|
|
93
|
-
>
|
|
73
|
+
return createStrokeIcon(
|
|
74
|
+
'File',
|
|
75
|
+
<>
|
|
94
76
|
<path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z" />
|
|
95
77
|
<polyline points="14 2 14 8 20 8" />
|
|
96
|
-
|
|
78
|
+
</>,
|
|
79
|
+
props
|
|
97
80
|
);
|
|
98
81
|
}
|
|
99
82
|
|
|
100
83
|
export function HammerIcon(props: IconBaseProps) {
|
|
101
|
-
return (
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
strokeLinecap="round"
|
|
105
|
-
strokeLinejoin="round"
|
|
106
|
-
{...props}
|
|
107
|
-
>
|
|
84
|
+
return createStrokeIcon(
|
|
85
|
+
'Hammer',
|
|
86
|
+
<>
|
|
108
87
|
<path d="M18.42 13.59L7.46 2.63a1 1 0 0 0-1.42 0l-4.7 4.7a1 1 0 0 0 0 1.42L11 18.23l1.07-1.07-1.41-1.41 1.42-1.42 1.41 1.41 1.41-1.41-1.41-1.41 1.42-1.42 1.41 1.41 2-2z" />
|
|
109
88
|
<path d="M13 18l6 6" />
|
|
110
|
-
|
|
89
|
+
</>,
|
|
90
|
+
props
|
|
111
91
|
);
|
|
112
92
|
}
|
|
113
93
|
|
|
114
94
|
export function InfoIcon(props: IconBaseProps) {
|
|
115
|
-
return (
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
strokeLinecap="round"
|
|
119
|
-
strokeLinejoin="round"
|
|
120
|
-
{...props}
|
|
121
|
-
>
|
|
95
|
+
return createStrokeIcon(
|
|
96
|
+
'Info',
|
|
97
|
+
<>
|
|
122
98
|
<circle cx="12" cy="12" r="10" />
|
|
123
99
|
<line x1="12" y1="16" x2="12" y2="12" />
|
|
124
100
|
<line x1="12" y1="8" x2="12.01" y2="8" />
|
|
125
|
-
|
|
101
|
+
</>,
|
|
102
|
+
props
|
|
126
103
|
);
|
|
127
104
|
}
|
|
128
105
|
|
|
129
106
|
export function PlayIcon(props: IconBaseProps) {
|
|
130
|
-
return (
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
strokeLinejoin="round"
|
|
135
|
-
{...props}
|
|
136
|
-
>
|
|
137
|
-
<polygon points="5 3 19 12 5 21 5 3" />
|
|
138
|
-
</IconBase>
|
|
107
|
+
return createStrokeIcon(
|
|
108
|
+
'Play',
|
|
109
|
+
<polygon points="5 3 19 12 5 21 5 3" />,
|
|
110
|
+
props
|
|
139
111
|
);
|
|
140
112
|
}
|
|
141
113
|
|
|
142
114
|
export function RefreshCwIcon(props: IconBaseProps) {
|
|
143
|
-
return (
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
strokeLinecap="round"
|
|
147
|
-
strokeLinejoin="round"
|
|
148
|
-
{...props}
|
|
149
|
-
>
|
|
115
|
+
return createStrokeIcon(
|
|
116
|
+
'RefreshCw',
|
|
117
|
+
<>
|
|
150
118
|
<path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8" />
|
|
151
119
|
<path d="M21 3v5h-5" />
|
|
152
120
|
<path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16" />
|
|
153
121
|
<path d="M3 21v-5h5" />
|
|
154
|
-
|
|
122
|
+
</>,
|
|
123
|
+
props
|
|
155
124
|
);
|
|
156
125
|
}
|
|
157
126
|
|
|
@@ -185,58 +154,44 @@ export function RocketIcon(props: IconBaseProps) {
|
|
|
185
154
|
}
|
|
186
155
|
|
|
187
156
|
export function SaveIcon(props: IconBaseProps) {
|
|
188
|
-
return (
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
strokeLinecap="round"
|
|
192
|
-
strokeLinejoin="round"
|
|
193
|
-
{...props}
|
|
194
|
-
>
|
|
157
|
+
return createStrokeIcon(
|
|
158
|
+
'Save',
|
|
159
|
+
<>
|
|
195
160
|
<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" />
|
|
196
161
|
<polyline points="17 21 17 13 7 13 7 21" />
|
|
197
162
|
<polyline points="7 3 7 8 15 8" />
|
|
198
|
-
|
|
163
|
+
</>,
|
|
164
|
+
props
|
|
199
165
|
);
|
|
200
166
|
}
|
|
201
167
|
|
|
202
168
|
export function SettingsIcon(props: IconBaseProps) {
|
|
203
|
-
return (
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
strokeLinecap="round"
|
|
207
|
-
strokeLinejoin="round"
|
|
208
|
-
{...props}
|
|
209
|
-
>
|
|
169
|
+
return createStrokeIcon(
|
|
170
|
+
'Settings',
|
|
171
|
+
<>
|
|
210
172
|
<path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.38a2 2 0 0 0-.73-2.73l-.15-.1a2 2 0 0 1-1-1.72v-.51a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z" />
|
|
211
173
|
<circle cx="12" cy="12" r="3" />
|
|
212
|
-
|
|
174
|
+
</>,
|
|
175
|
+
props
|
|
213
176
|
);
|
|
214
177
|
}
|
|
215
178
|
|
|
216
179
|
export function ShieldCheckIcon(props: IconBaseProps) {
|
|
217
|
-
return (
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
strokeLinecap="round"
|
|
221
|
-
strokeLinejoin="round"
|
|
222
|
-
{...props}
|
|
223
|
-
>
|
|
180
|
+
return createStrokeIcon(
|
|
181
|
+
'ShieldCheck',
|
|
182
|
+
<>
|
|
224
183
|
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
|
|
225
184
|
<path d="M9 12l2 2 4-4" />
|
|
226
|
-
|
|
185
|
+
</>,
|
|
186
|
+
props
|
|
227
187
|
);
|
|
228
188
|
}
|
|
229
189
|
|
|
230
190
|
export function ShieldIcon(props: IconBaseProps) {
|
|
231
|
-
return (
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
strokeLinejoin="round"
|
|
236
|
-
{...props}
|
|
237
|
-
>
|
|
238
|
-
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
|
|
239
|
-
</IconBase>
|
|
191
|
+
return createStrokeIcon(
|
|
192
|
+
'Shield',
|
|
193
|
+
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />,
|
|
194
|
+
props
|
|
240
195
|
);
|
|
241
196
|
}
|
|
242
197
|
|
|
@@ -255,87 +210,67 @@ export function TargetIcon(props: IconBaseProps) {
|
|
|
255
210
|
}
|
|
256
211
|
|
|
257
212
|
export function TerminalIcon(props: IconBaseProps) {
|
|
258
|
-
return (
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
strokeLinecap="round"
|
|
262
|
-
strokeLinejoin="round"
|
|
263
|
-
{...props}
|
|
264
|
-
>
|
|
213
|
+
return createStrokeIcon(
|
|
214
|
+
'Terminal',
|
|
215
|
+
<>
|
|
265
216
|
<polyline points="4 17 10 11 4 5" />
|
|
266
217
|
<line x1="12" y1="19" x2="20" y2="19" />
|
|
267
|
-
|
|
218
|
+
</>,
|
|
219
|
+
props
|
|
268
220
|
);
|
|
269
221
|
}
|
|
270
222
|
|
|
271
223
|
export function TrashIcon(props: IconBaseProps) {
|
|
272
|
-
return (
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
strokeLinecap="round"
|
|
276
|
-
strokeLinejoin="round"
|
|
277
|
-
{...props}
|
|
278
|
-
>
|
|
224
|
+
return createStrokeIcon(
|
|
225
|
+
'Trash',
|
|
226
|
+
<>
|
|
279
227
|
<polyline points="3 6 5 6 21 6" />
|
|
280
228
|
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
|
|
281
|
-
|
|
229
|
+
</>,
|
|
230
|
+
props
|
|
282
231
|
);
|
|
283
232
|
}
|
|
284
233
|
|
|
285
234
|
export function TrendingUpIcon(props: IconBaseProps) {
|
|
286
|
-
return (
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
strokeLinecap="round"
|
|
290
|
-
strokeLinejoin="round"
|
|
291
|
-
{...props}
|
|
292
|
-
>
|
|
235
|
+
return createStrokeIcon(
|
|
236
|
+
'TrendingUp',
|
|
237
|
+
<>
|
|
293
238
|
<polyline points="23 6 13.5 15.5 8.5 10.5 1 18" />
|
|
294
239
|
<polyline points="17 6 23 6 23 12" />
|
|
295
|
-
|
|
240
|
+
</>,
|
|
241
|
+
props
|
|
296
242
|
);
|
|
297
243
|
}
|
|
298
244
|
|
|
299
245
|
export function UploadIcon(props: IconBaseProps) {
|
|
300
|
-
return (
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
strokeLinecap="round"
|
|
304
|
-
strokeLinejoin="round"
|
|
305
|
-
{...props}
|
|
306
|
-
>
|
|
246
|
+
return createStrokeIcon(
|
|
247
|
+
'Upload',
|
|
248
|
+
<>
|
|
307
249
|
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v4" />
|
|
308
250
|
<polyline points="17 8 12 3 7 8" />
|
|
309
251
|
<line x1="12" y1="3" x2="12" y2="15" />
|
|
310
|
-
|
|
252
|
+
</>,
|
|
253
|
+
props
|
|
311
254
|
);
|
|
312
255
|
}
|
|
313
256
|
|
|
314
257
|
export function WalletIcon(props: IconBaseProps) {
|
|
315
|
-
return (
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
strokeLinecap="round"
|
|
319
|
-
strokeLinejoin="round"
|
|
320
|
-
{...props}
|
|
321
|
-
>
|
|
258
|
+
return createStrokeIcon(
|
|
259
|
+
'Wallet',
|
|
260
|
+
<>
|
|
322
261
|
<path d="M21 12V7a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-1" />
|
|
323
262
|
<path d="M16 12h5" />
|
|
324
263
|
<circle cx="16" cy="12" r="1" />
|
|
325
|
-
|
|
264
|
+
</>,
|
|
265
|
+
props
|
|
326
266
|
);
|
|
327
267
|
}
|
|
328
268
|
|
|
329
269
|
export function ZapIcon(props: IconBaseProps) {
|
|
330
|
-
return (
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
strokeLinejoin="round"
|
|
335
|
-
{...props}
|
|
336
|
-
>
|
|
337
|
-
<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" />
|
|
338
|
-
</IconBase>
|
|
270
|
+
return createStrokeIcon(
|
|
271
|
+
'Zap',
|
|
272
|
+
<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" />,
|
|
273
|
+
props
|
|
339
274
|
);
|
|
340
275
|
}
|
|
341
276
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { SimulationNode } from './simulation-types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Stabilizes nodes by zeroing velocities and rounding positions.
|
|
5
|
+
* Extracted to reduce duplicate patterns in useForceSimulation.
|
|
6
|
+
*/
|
|
7
|
+
export function stabilizeNodes(nodes: SimulationNode[]): void {
|
|
8
|
+
nodes.forEach((n) => {
|
|
9
|
+
(n as any).vx = 0;
|
|
10
|
+
(n as any).vy = 0;
|
|
11
|
+
if (typeof n.x === 'number') n.x = Number(n.x.toFixed(3));
|
|
12
|
+
if (typeof n.y === 'number') n.y = Number(n.y.toFixed(3));
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Seeds nodes with random positions within bounds.
|
|
18
|
+
* Used as fallback when initial positioning fails.
|
|
19
|
+
*/
|
|
20
|
+
export function seedRandomPositions(
|
|
21
|
+
nodes: SimulationNode[],
|
|
22
|
+
width: number,
|
|
23
|
+
height: number
|
|
24
|
+
): void {
|
|
25
|
+
nodes.forEach((n) => {
|
|
26
|
+
n.x = Math.random() * width;
|
|
27
|
+
n.y = Math.random() * height;
|
|
28
|
+
(n as any).vx = (Math.random() - 0.5) * 10;
|
|
29
|
+
(n as any).vy = (Math.random() - 0.5) * 10;
|
|
30
|
+
});
|
|
31
|
+
}
|