@particle-academy/react-fancy 2.9.0 → 3.0.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@particle-academy/react-fancy",
3
- "version": "2.9.0",
3
+ "version": "3.0.0",
4
4
  "description": "React UI component library — React port of the fancy-flux Blade component library",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,273 +0,0 @@
1
- // src/components/Diagram/diagram.serializers.ts
2
- function serializeToERD(schema) {
3
- const lines = [];
4
- for (const entity of schema.entities) {
5
- lines.push(`[${entity.name}]`);
6
- if (entity.fields) {
7
- for (const field of entity.fields) {
8
- const parts = [` ${field.name}`];
9
- if (field.type) parts.push(field.type);
10
- if (field.primary) parts.push("PK");
11
- if (field.foreign) parts.push("FK");
12
- if (field.nullable) parts.push("?");
13
- lines.push(parts.join(" "));
14
- }
15
- }
16
- lines.push("");
17
- }
18
- for (const rel of schema.relations) {
19
- const fromEntity = schema.entities.find((e) => e.id === rel.from);
20
- const toEntity = schema.entities.find((e) => e.id === rel.to);
21
- if (!fromEntity || !toEntity) continue;
22
- const marker = getERDMarker(rel.type);
23
- const parts = [fromEntity.name, marker, toEntity.name];
24
- if (rel.label) parts.push(`: ${rel.label}`);
25
- lines.push(parts.join(" "));
26
- }
27
- return lines.join("\n").trim();
28
- }
29
- function getERDMarker(type) {
30
- switch (type) {
31
- case "one-to-one":
32
- return "1--1";
33
- case "one-to-many":
34
- return "1--*";
35
- case "many-to-many":
36
- return "*--*";
37
- }
38
- }
39
- function serializeToUML(schema) {
40
- const lines = ["@startuml"];
41
- for (const entity of schema.entities) {
42
- lines.push(`class ${entity.name} {`);
43
- if (entity.fields) {
44
- for (const field of entity.fields) {
45
- const typeStr = field.type ?? "any";
46
- const nullable = field.nullable ? "?" : "";
47
- const stereotype = field.primary ? " <<PK>>" : field.foreign ? " <<FK>>" : "";
48
- lines.push(` ${field.name} : ${typeStr}${nullable}${stereotype}`);
49
- }
50
- }
51
- lines.push("}");
52
- lines.push("");
53
- }
54
- for (const rel of schema.relations) {
55
- const fromEntity = schema.entities.find((e) => e.id === rel.from);
56
- const toEntity = schema.entities.find((e) => e.id === rel.to);
57
- if (!fromEntity || !toEntity) continue;
58
- const arrow = getUMLArrow(rel.type);
59
- const label = rel.label ? ` : ${rel.label}` : "";
60
- lines.push(`${fromEntity.name} ${arrow} ${toEntity.name}${label}`);
61
- }
62
- lines.push("@enduml");
63
- return lines.join("\n");
64
- }
65
- function getUMLArrow(type) {
66
- switch (type) {
67
- case "one-to-one":
68
- return '"1" -- "1"';
69
- case "one-to-many":
70
- return '"1" -- "*"';
71
- case "many-to-many":
72
- return '"*" -- "*"';
73
- }
74
- }
75
- function serializeToDFD(schema) {
76
- const lines = [];
77
- for (const entity of schema.entities) {
78
- lines.push(`entity ${entity.name}`);
79
- }
80
- lines.push("");
81
- for (const rel of schema.relations) {
82
- const fromEntity = schema.entities.find((e) => e.id === rel.from);
83
- const toEntity = schema.entities.find((e) => e.id === rel.to);
84
- if (!fromEntity || !toEntity) continue;
85
- const label = rel.label ? ` "${rel.label}"` : "";
86
- lines.push(`${fromEntity.name} -> ${toEntity.name}${label}`);
87
- }
88
- return lines.join("\n").trim();
89
- }
90
- function deserializeSchema(input, format) {
91
- switch (format) {
92
- case "erd":
93
- return deserializeERD(input);
94
- case "uml":
95
- return deserializeUML(input);
96
- case "dfd":
97
- return deserializeDFD(input);
98
- }
99
- }
100
- function deserializeERD(input) {
101
- const entities = [];
102
- const relations = [];
103
- const lines = input.split("\n");
104
- let currentEntity = null;
105
- for (const rawLine of lines) {
106
- const line = rawLine.trim();
107
- const entityMatch = line.match(/^\[(.+)\]$/);
108
- if (entityMatch) {
109
- currentEntity = {
110
- id: entityMatch[1].toLowerCase().replace(/\s+/g, "_"),
111
- name: entityMatch[1],
112
- fields: []
113
- };
114
- entities.push(currentEntity);
115
- continue;
116
- }
117
- if (currentEntity && rawLine.startsWith(" ") && line.length > 0) {
118
- const parts = line.split(/\s+/);
119
- const field = { name: parts[0] };
120
- if (parts.length > 1 && !["PK", "FK", "?"].includes(parts[1])) {
121
- field.type = parts[1];
122
- }
123
- if (parts.includes("PK")) field.primary = true;
124
- if (parts.includes("FK")) field.foreign = true;
125
- if (parts.includes("?")) field.nullable = true;
126
- currentEntity.fields.push(field);
127
- continue;
128
- }
129
- const relMatch = line.match(
130
- /^(\S+)\s+(1--1|1--\*|\*--\*)\s+(\S+)(?:\s*:\s*(.+))?$/
131
- );
132
- if (relMatch) {
133
- currentEntity = null;
134
- const fromName = relMatch[1];
135
- const marker = relMatch[2];
136
- const toName = relMatch[3];
137
- const label = relMatch[4];
138
- const fromEntity = entities.find((e) => e.name === fromName);
139
- const toEntity = entities.find((e) => e.name === toName);
140
- if (fromEntity && toEntity) {
141
- relations.push({
142
- id: `${fromEntity.id ?? fromEntity.name}_${toEntity.id ?? toEntity.name}`,
143
- from: fromEntity.id ?? fromEntity.name,
144
- to: toEntity.id ?? toEntity.name,
145
- type: parseERDMarker(marker),
146
- label
147
- });
148
- }
149
- continue;
150
- }
151
- if (line === "") {
152
- currentEntity = null;
153
- }
154
- }
155
- return { entities, relations };
156
- }
157
- function parseERDMarker(marker) {
158
- switch (marker) {
159
- case "1--1":
160
- return "one-to-one";
161
- case "1--*":
162
- return "one-to-many";
163
- case "*--*":
164
- return "many-to-many";
165
- default:
166
- return "one-to-many";
167
- }
168
- }
169
- function deserializeUML(input) {
170
- const entities = [];
171
- const relations = [];
172
- const lines = input.split("\n");
173
- let currentEntity = null;
174
- for (const rawLine of lines) {
175
- const line = rawLine.trim();
176
- if (line === "@startuml" || line === "@enduml" || line === "") continue;
177
- const classMatch = line.match(/^class\s+(\S+)\s*\{$/);
178
- if (classMatch) {
179
- currentEntity = {
180
- id: classMatch[1].toLowerCase().replace(/\s+/g, "_"),
181
- name: classMatch[1],
182
- fields: []
183
- };
184
- entities.push(currentEntity);
185
- continue;
186
- }
187
- if (line === "}") {
188
- currentEntity = null;
189
- continue;
190
- }
191
- if (currentEntity) {
192
- const fieldMatch = line.match(
193
- /^(\S+)\s*:\s*(\S+?)(\?)?(?:\s*<<(PK|FK)>>)?$/
194
- );
195
- if (fieldMatch) {
196
- const field = {
197
- name: fieldMatch[1],
198
- type: fieldMatch[2]
199
- };
200
- if (fieldMatch[3]) field.nullable = true;
201
- if (fieldMatch[4] === "PK") field.primary = true;
202
- if (fieldMatch[4] === "FK") field.foreign = true;
203
- currentEntity.fields.push(field);
204
- }
205
- continue;
206
- }
207
- const relMatch = line.match(
208
- /^(\S+)\s+"([1*])"\s+--\s+"([1*])"\s+(\S+)(?:\s*:\s*(.+))?$/
209
- );
210
- if (relMatch) {
211
- const fromName = relMatch[1];
212
- const fromCard = relMatch[2];
213
- const toCard = relMatch[3];
214
- const toName = relMatch[4];
215
- const label = relMatch[5];
216
- const fromEntity = entities.find((e) => e.name === fromName);
217
- const toEntity = entities.find((e) => e.name === toName);
218
- if (fromEntity && toEntity) {
219
- const type = fromCard === "1" && toCard === "1" ? "one-to-one" : fromCard === "1" && toCard === "*" ? "one-to-many" : "many-to-many";
220
- relations.push({
221
- id: `${fromEntity.id ?? fromEntity.name}_${toEntity.id ?? toEntity.name}`,
222
- from: fromEntity.id ?? fromEntity.name,
223
- to: toEntity.id ?? toEntity.name,
224
- type,
225
- label
226
- });
227
- }
228
- }
229
- }
230
- return { entities, relations };
231
- }
232
- function deserializeDFD(input) {
233
- const entities = [];
234
- const relations = [];
235
- const lines = input.split("\n");
236
- for (const rawLine of lines) {
237
- const line = rawLine.trim();
238
- if (line === "") continue;
239
- const entityMatch = line.match(/^entity\s+(\S+)$/);
240
- if (entityMatch) {
241
- entities.push({
242
- id: entityMatch[1].toLowerCase().replace(/\s+/g, "_"),
243
- name: entityMatch[1],
244
- fields: []
245
- });
246
- continue;
247
- }
248
- const flowMatch = line.match(
249
- /^(\S+)\s+->\s+(\S+)(?:\s+"(.+)")?$/
250
- );
251
- if (flowMatch) {
252
- const fromName = flowMatch[1];
253
- const toName = flowMatch[2];
254
- const label = flowMatch[3];
255
- const fromEntity = entities.find((e) => e.name === fromName);
256
- const toEntity = entities.find((e) => e.name === toName);
257
- if (fromEntity && toEntity) {
258
- relations.push({
259
- id: `${fromEntity.id ?? fromEntity.name}_${toEntity.id ?? toEntity.name}`,
260
- from: fromEntity.id ?? fromEntity.name,
261
- to: toEntity.id ?? toEntity.name,
262
- type: "one-to-many",
263
- label
264
- });
265
- }
266
- }
267
- }
268
- return { entities, relations };
269
- }
270
-
271
- export { deserializeSchema, serializeToDFD, serializeToERD, serializeToUML };
272
- //# sourceMappingURL=diagram.serializers-6RPUO46U.js.map
273
- //# sourceMappingURL=diagram.serializers-6RPUO46U.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/Diagram/diagram.serializers.ts"],"names":[],"mappings":"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","file":"diagram.serializers-6RPUO46U.js","sourcesContent":["import type {\n DiagramSchema,\n DiagramEntityData,\n DiagramRelationData,\n DiagramFieldData,\n ExportFormat,\n RelationType,\n} from \"./Diagram.types\";\n\n/**\n * Serialize a diagram schema to PlantUML-style ERD text.\n *\n * Example output:\n * ```\n * [Users]\n * id int PK\n * email varchar\n *\n * [Posts]\n * id int PK\n * user_id int FK\n *\n * Users 1--* Posts\n * ```\n */\nexport function serializeToERD(schema: DiagramSchema): string {\n const lines: string[] = [];\n\n for (const entity of schema.entities) {\n lines.push(`[${entity.name}]`);\n if (entity.fields) {\n for (const field of entity.fields) {\n const parts = [` ${field.name}`];\n if (field.type) parts.push(field.type);\n if (field.primary) parts.push(\"PK\");\n if (field.foreign) parts.push(\"FK\");\n if (field.nullable) parts.push(\"?\");\n lines.push(parts.join(\" \"));\n }\n }\n lines.push(\"\");\n }\n\n for (const rel of schema.relations) {\n const fromEntity = schema.entities.find((e) => e.id === rel.from);\n const toEntity = schema.entities.find((e) => e.id === rel.to);\n if (!fromEntity || !toEntity) continue;\n\n const marker = getERDMarker(rel.type);\n const parts = [fromEntity.name, marker, toEntity.name];\n if (rel.label) parts.push(`: ${rel.label}`);\n lines.push(parts.join(\" \"));\n }\n\n return lines.join(\"\\n\").trim();\n}\n\nfunction getERDMarker(type: RelationType): string {\n switch (type) {\n case \"one-to-one\":\n return \"1--1\";\n case \"one-to-many\":\n return \"1--*\";\n case \"many-to-many\":\n return \"*--*\";\n }\n}\n\n/**\n * Serialize a diagram schema to PlantUML class diagram text.\n */\nexport function serializeToUML(schema: DiagramSchema): string {\n const lines: string[] = [\"@startuml\"];\n\n for (const entity of schema.entities) {\n lines.push(`class ${entity.name} {`);\n if (entity.fields) {\n for (const field of entity.fields) {\n const typeStr = field.type ?? \"any\";\n const nullable = field.nullable ? \"?\" : \"\";\n const stereotype = field.primary\n ? \" <<PK>>\"\n : field.foreign\n ? \" <<FK>>\"\n : \"\";\n lines.push(` ${field.name} : ${typeStr}${nullable}${stereotype}`);\n }\n }\n lines.push(\"}\");\n lines.push(\"\");\n }\n\n for (const rel of schema.relations) {\n const fromEntity = schema.entities.find((e) => e.id === rel.from);\n const toEntity = schema.entities.find((e) => e.id === rel.to);\n if (!fromEntity || !toEntity) continue;\n\n const arrow = getUMLArrow(rel.type);\n const label = rel.label ? ` : ${rel.label}` : \"\";\n lines.push(`${fromEntity.name} ${arrow} ${toEntity.name}${label}`);\n }\n\n lines.push(\"@enduml\");\n return lines.join(\"\\n\");\n}\n\nfunction getUMLArrow(type: RelationType): string {\n switch (type) {\n case \"one-to-one\":\n return '\"1\" -- \"1\"';\n case \"one-to-many\":\n return '\"1\" -- \"*\"';\n case \"many-to-many\":\n return '\"*\" -- \"*\"';\n }\n}\n\n/**\n * Serialize a diagram schema to a simple DFD text format.\n */\nexport function serializeToDFD(schema: DiagramSchema): string {\n const lines: string[] = [];\n\n for (const entity of schema.entities) {\n lines.push(`entity ${entity.name}`);\n }\n\n lines.push(\"\");\n\n for (const rel of schema.relations) {\n const fromEntity = schema.entities.find((e) => e.id === rel.from);\n const toEntity = schema.entities.find((e) => e.id === rel.to);\n if (!fromEntity || !toEntity) continue;\n\n const label = rel.label ? ` \"${rel.label}\"` : \"\";\n lines.push(`${fromEntity.name} -> ${toEntity.name}${label}`);\n }\n\n return lines.join(\"\\n\").trim();\n}\n\n/**\n * Parse a serialized schema string back into a DiagramSchema.\n */\nexport function deserializeSchema(\n input: string,\n format: ExportFormat,\n): DiagramSchema {\n switch (format) {\n case \"erd\":\n return deserializeERD(input);\n case \"uml\":\n return deserializeUML(input);\n case \"dfd\":\n return deserializeDFD(input);\n }\n}\n\nfunction deserializeERD(input: string): DiagramSchema {\n const entities: DiagramEntityData[] = [];\n const relations: DiagramRelationData[] = [];\n const lines = input.split(\"\\n\");\n\n let currentEntity: DiagramEntityData | null = null;\n\n for (const rawLine of lines) {\n const line = rawLine.trim();\n\n // Entity header: [EntityName]\n const entityMatch = line.match(/^\\[(.+)\\]$/);\n if (entityMatch) {\n currentEntity = {\n id: entityMatch[1].toLowerCase().replace(/\\s+/g, \"_\"),\n name: entityMatch[1],\n fields: [],\n };\n entities.push(currentEntity);\n continue;\n }\n\n // Field line (indented): name type PK FK ?\n if (currentEntity && rawLine.startsWith(\" \") && line.length > 0) {\n const parts = line.split(/\\s+/);\n const field: DiagramFieldData = { name: parts[0] };\n if (parts.length > 1 && ![\"PK\", \"FK\", \"?\"].includes(parts[1])) {\n field.type = parts[1];\n }\n if (parts.includes(\"PK\")) field.primary = true;\n if (parts.includes(\"FK\")) field.foreign = true;\n if (parts.includes(\"?\")) field.nullable = true;\n currentEntity.fields!.push(field);\n continue;\n }\n\n // Relation: EntityA 1--* EntityB : label\n const relMatch = line.match(\n /^(\\S+)\\s+(1--1|1--\\*|\\*--\\*)\\s+(\\S+)(?:\\s*:\\s*(.+))?$/,\n );\n if (relMatch) {\n currentEntity = null;\n const fromName = relMatch[1];\n const marker = relMatch[2];\n const toName = relMatch[3];\n const label = relMatch[4];\n\n const fromEntity = entities.find((e) => e.name === fromName);\n const toEntity = entities.find((e) => e.name === toName);\n if (fromEntity && toEntity) {\n relations.push({\n id: `${fromEntity.id ?? fromEntity.name}_${toEntity.id ?? toEntity.name}`,\n from: fromEntity.id ?? fromEntity.name,\n to: toEntity.id ?? toEntity.name,\n type: parseERDMarker(marker),\n label,\n });\n }\n continue;\n }\n\n // Empty line resets current entity context\n if (line === \"\") {\n currentEntity = null;\n }\n }\n\n return { entities, relations };\n}\n\nfunction parseERDMarker(marker: string): RelationType {\n switch (marker) {\n case \"1--1\":\n return \"one-to-one\";\n case \"1--*\":\n return \"one-to-many\";\n case \"*--*\":\n return \"many-to-many\";\n default:\n return \"one-to-many\";\n }\n}\n\nfunction deserializeUML(input: string): DiagramSchema {\n const entities: DiagramEntityData[] = [];\n const relations: DiagramRelationData[] = [];\n const lines = input.split(\"\\n\");\n\n let currentEntity: DiagramEntityData | null = null;\n\n for (const rawLine of lines) {\n const line = rawLine.trim();\n\n if (line === \"@startuml\" || line === \"@enduml\" || line === \"\") continue;\n\n // Class header: class EntityName {\n const classMatch = line.match(/^class\\s+(\\S+)\\s*\\{$/);\n if (classMatch) {\n currentEntity = {\n id: classMatch[1].toLowerCase().replace(/\\s+/g, \"_\"),\n name: classMatch[1],\n fields: [],\n };\n entities.push(currentEntity);\n continue;\n }\n\n // Closing brace\n if (line === \"}\") {\n currentEntity = null;\n continue;\n }\n\n // Field: name : type<<stereotype>>\n if (currentEntity) {\n const fieldMatch = line.match(\n /^(\\S+)\\s*:\\s*(\\S+?)(\\?)?(?:\\s*<<(PK|FK)>>)?$/,\n );\n if (fieldMatch) {\n const field: DiagramFieldData = {\n name: fieldMatch[1],\n type: fieldMatch[2],\n };\n if (fieldMatch[3]) field.nullable = true;\n if (fieldMatch[4] === \"PK\") field.primary = true;\n if (fieldMatch[4] === \"FK\") field.foreign = true;\n currentEntity.fields!.push(field);\n }\n continue;\n }\n\n // Relation: EntityA \"1\" -- \"*\" EntityB : label\n const relMatch = line.match(\n /^(\\S+)\\s+\"([1*])\"\\s+--\\s+\"([1*])\"\\s+(\\S+)(?:\\s*:\\s*(.+))?$/,\n );\n if (relMatch) {\n const fromName = relMatch[1];\n const fromCard = relMatch[2];\n const toCard = relMatch[3];\n const toName = relMatch[4];\n const label = relMatch[5];\n\n const fromEntity = entities.find((e) => e.name === fromName);\n const toEntity = entities.find((e) => e.name === toName);\n if (fromEntity && toEntity) {\n const type: RelationType =\n fromCard === \"1\" && toCard === \"1\"\n ? \"one-to-one\"\n : fromCard === \"1\" && toCard === \"*\"\n ? \"one-to-many\"\n : \"many-to-many\";\n relations.push({\n id: `${fromEntity.id ?? fromEntity.name}_${toEntity.id ?? toEntity.name}`,\n from: fromEntity.id ?? fromEntity.name,\n to: toEntity.id ?? toEntity.name,\n type,\n label,\n });\n }\n }\n }\n\n return { entities, relations };\n}\n\nfunction deserializeDFD(input: string): DiagramSchema {\n const entities: DiagramEntityData[] = [];\n const relations: DiagramRelationData[] = [];\n const lines = input.split(\"\\n\");\n\n for (const rawLine of lines) {\n const line = rawLine.trim();\n if (line === \"\") continue;\n\n // Entity: entity EntityName\n const entityMatch = line.match(/^entity\\s+(\\S+)$/);\n if (entityMatch) {\n entities.push({\n id: entityMatch[1].toLowerCase().replace(/\\s+/g, \"_\"),\n name: entityMatch[1],\n fields: [],\n });\n continue;\n }\n\n // Flow: EntityA -> EntityB \"label\"\n const flowMatch = line.match(\n /^(\\S+)\\s+->\\s+(\\S+)(?:\\s+\"(.+)\")?$/,\n );\n if (flowMatch) {\n const fromName = flowMatch[1];\n const toName = flowMatch[2];\n const label = flowMatch[3];\n\n const fromEntity = entities.find((e) => e.name === fromName);\n const toEntity = entities.find((e) => e.name === toName);\n if (fromEntity && toEntity) {\n relations.push({\n id: `${fromEntity.id ?? fromEntity.name}_${toEntity.id ?? toEntity.name}`,\n from: fromEntity.id ?? fromEntity.name,\n to: toEntity.id ?? toEntity.name,\n type: \"one-to-many\",\n label,\n });\n }\n }\n }\n\n return { entities, relations };\n}\n"]}
package/docs/Canvas.md DELETED
@@ -1,105 +0,0 @@
1
- # Canvas
2
-
3
- An infinite pannable and zoomable canvas for positioning nodes with edges between them. Includes minimap and zoom controls.
4
-
5
- ## Import
6
-
7
- ```tsx
8
- import { Canvas } from "@particle-academy/react-fancy";
9
- ```
10
-
11
- ## Basic Usage
12
-
13
- ```tsx
14
- <Canvas className="h-96 w-full" showGrid>
15
- <Canvas.Node id="a" x={50} y={50} draggable>
16
- <div className="rounded border bg-white p-4">Node A</div>
17
- </Canvas.Node>
18
- <Canvas.Node id="b" x={300} y={150} draggable>
19
- <div className="rounded border bg-white p-4">Node B</div>
20
- </Canvas.Node>
21
- <Canvas.Edge from="a" to="b" curve="bezier" markerEnd="canvas-arrow" />
22
- <Canvas.Controls />
23
- <Canvas.Minimap />
24
- </Canvas>
25
- ```
26
-
27
- ## Props
28
-
29
- ### Canvas (root)
30
-
31
- | Prop | Type | Default | Description |
32
- |------|------|---------|-------------|
33
- | viewport | `ViewportState` | - | Controlled viewport `{ panX, panY, zoom }` |
34
- | defaultViewport | `ViewportState` | `{ panX: 0, panY: 0, zoom: 1 }` | Default viewport (uncontrolled) |
35
- | onViewportChange | `(viewport: ViewportState) => void` | - | Callback when viewport changes |
36
- | minZoom | `number` | `0.1` | Minimum zoom level |
37
- | maxZoom | `number` | `3` | Maximum zoom level |
38
- | pannable | `boolean` | `true` | Enable panning (click+drag on background) |
39
- | zoomable | `boolean` | `true` | Enable zoom (Ctrl+scroll) |
40
- | gridSize | `number` | `20` | Grid cell size in canvas-space pixels |
41
- | showGrid | `boolean` | `false` | Display the canvas grid background |
42
- | gridStyle | `'dots' \| 'lines' \| 'none'` | `'dots'` | Grid pattern when shown. `'none'` hides the grid even when `showGrid` is true |
43
- | gridColor | `string` | `'rgb(161 161 170 / 0.3)'` | Any CSS color for grid dots/lines |
44
- | snapToGrid | `boolean` | `false` | Snap dragged nodes to the grid |
45
- | fitOnMount | `boolean` | `false` | Auto-fit all nodes into view on mount |
46
- | className | `string` | - | Additional CSS classes |
47
- | style | `CSSProperties` | - | Inline styles |
48
-
49
- ### Canvas.Node
50
-
51
- | Prop | Type | Default | Description |
52
- |------|------|---------|-------------|
53
- | id | `string` | - | Unique node identifier (required) |
54
- | x | `number` | - | X position in canvas coordinates (required) |
55
- | y | `number` | - | Y position in canvas coordinates (required) |
56
- | draggable | `boolean` | - | Allow drag-to-move |
57
- | onPositionChange | `(x: number, y: number) => void` | - | Callback when dragged to a new position |
58
- | className | `string` | - | Additional CSS classes |
59
- | style | `CSSProperties` | - | Inline styles |
60
-
61
- ### Canvas.Edge
62
-
63
- | Prop | Type | Default | Description |
64
- |------|------|---------|-------------|
65
- | from | `string` | - | Source node id (required) |
66
- | to | `string` | - | Target node id (required) |
67
- | fromAnchor | `EdgeAnchor` | - | Anchor point on source: `"top"`, `"bottom"`, `"left"`, `"right"`, `"center"`, `"auto"` |
68
- | toAnchor | `EdgeAnchor` | - | Anchor point on target |
69
- | curve | `"bezier" \| "step" \| "straight"` | - | Path interpolation |
70
- | color | `string` | - | Stroke color |
71
- | strokeWidth | `number` | - | Stroke width |
72
- | dashed | `boolean` | - | Dashed line |
73
- | animated | `boolean` | - | Animated dash pattern |
74
- | label | `ReactNode` | - | Label at the midpoint |
75
- | markerStart | `string` | - | SVG marker id for start (e.g. `"canvas-arrow"`, `"canvas-circle"`, `"canvas-diamond"`) |
76
- | markerEnd | `string` | - | SVG marker id for end |
77
- | className | `string` | - | Additional CSS classes |
78
-
79
- ### Canvas.Controls
80
-
81
- | Prop | Type | Default | Description |
82
- |------|------|---------|-------------|
83
- | showZoomIn | `boolean` | - | Show zoom-in button |
84
- | showZoomOut | `boolean` | - | Show zoom-out button |
85
- | showReset | `boolean` | - | Show reset-viewport button |
86
- | showFitAll | `boolean` | - | Show fit-all button |
87
- | className | `string` | - | Additional CSS classes |
88
-
89
- ### Canvas.Minimap
90
-
91
- | Prop | Type | Default | Description |
92
- |------|------|---------|-------------|
93
- | width | `number` | - | Minimap width in px |
94
- | height | `number` | - | Minimap height in px |
95
- | className | `string` | - | Additional CSS classes |
96
-
97
- ### ViewportState
98
-
99
- ```ts
100
- { panX: number; panY: number; zoom: number }
101
- ```
102
-
103
- ## Built-in SVG Markers
104
-
105
- The Canvas includes predefined SVG markers for edge endpoints: `"canvas-arrow"`, `"canvas-circle"`, `"canvas-diamond"`, `"canvas-one"`, `"canvas-crow-foot"`.
package/docs/Diagram.md DELETED
@@ -1,119 +0,0 @@
1
- # Diagram
2
-
3
- A high-level ERD/flowchart diagram built on top of Canvas. Accepts a schema of entities and relations, auto-layouts positions, and supports drag-to-move, export, and import.
4
-
5
- ## Import
6
-
7
- ```tsx
8
- import { Diagram } from "@particle-academy/react-fancy";
9
- ```
10
-
11
- ## Basic Usage (Schema-driven)
12
-
13
- ```tsx
14
- const schema = {
15
- entities: [
16
- {
17
- name: "users",
18
- fields: [
19
- { name: "id", type: "bigint", primary: true },
20
- { name: "name", type: "varchar" },
21
- { name: "email", type: "varchar" },
22
- ],
23
- },
24
- {
25
- name: "posts",
26
- fields: [
27
- { name: "id", type: "bigint", primary: true },
28
- { name: "user_id", type: "bigint", foreign: true },
29
- { name: "title", type: "varchar" },
30
- { name: "body", type: "text", nullable: true },
31
- ],
32
- },
33
- ],
34
- relations: [
35
- { from: "users", to: "posts", type: "one-to-many" },
36
- ],
37
- };
38
-
39
- <Diagram schema={schema} className="h-[600px]" downloadable minimap />
40
- ```
41
-
42
- ## Props
43
-
44
- ### Diagram (root)
45
-
46
- | Prop | Type | Default | Description |
47
- |------|------|---------|-------------|
48
- | schema | `DiagramSchema` | - | Declarative schema of entities and relations |
49
- | type | `"erd" \| "flowchart" \| "general"` | `"general"` | Diagram type (affects relation rendering) |
50
- | viewport | `ViewportState` | - | Controlled viewport |
51
- | defaultViewport | `ViewportState` | - | Default viewport (auto-computed from schema if omitted) |
52
- | onViewportChange | `(viewport: ViewportState) => void` | - | Viewport change callback |
53
- | downloadable | `boolean` | `false` | Enable download toolbar action |
54
- | importable | `boolean` | `false` | Enable import toolbar action |
55
- | exportFormats | `ExportFormat[]` | `["erd"]` | Export format options: `"erd"`, `"uml"`, `"dfd"` |
56
- | onImport | `(schema: DiagramSchema) => void` | - | Callback when a schema is imported |
57
- | minimap | `boolean` | `false` | Show minimap overlay |
58
- | className | `string` | - | Additional CSS classes |
59
-
60
- ### Diagram.Entity
61
-
62
- | Prop | Type | Default | Description |
63
- |------|------|---------|-------------|
64
- | id | `string` | - | Unique identifier (defaults to `name`) |
65
- | name | `string` | - | Entity name (required) |
66
- | x | `number` | - | X position |
67
- | y | `number` | - | Y position |
68
- | color | `string` | - | Header color |
69
- | draggable | `boolean` | - | Allow drag-to-move |
70
- | onPositionChange | `(x: number, y: number) => void` | - | Drag callback |
71
- | children | `ReactNode` | - | Field children |
72
- | className | `string` | - | Additional CSS classes |
73
-
74
- ### Diagram.Field
75
-
76
- | Prop | Type | Default | Description |
77
- |------|------|---------|-------------|
78
- | name | `string` | - | Field name (required) |
79
- | type | `string` | - | Data type label |
80
- | primary | `boolean` | - | Primary key indicator |
81
- | foreign | `boolean` | - | Foreign key indicator |
82
- | nullable | `boolean` | - | Nullable indicator |
83
- | className | `string` | - | Additional CSS classes |
84
-
85
- ### Diagram.Relation
86
-
87
- | Prop | Type | Default | Description |
88
- |------|------|---------|-------------|
89
- | from | `string` | - | Source entity id (required) |
90
- | to | `string` | - | Target entity id (required) |
91
- | fromField | `string` | - | Source field name |
92
- | toField | `string` | - | Target field name |
93
- | type | `RelationType` | - | `"one-to-one"`, `"one-to-many"`, or `"many-to-many"` (required) |
94
- | label | `string` | - | Edge label |
95
- | className | `string` | - | Additional CSS classes |
96
-
97
- ### Diagram.Toolbar
98
-
99
- | Prop | Type | Default | Description |
100
- |------|------|---------|-------------|
101
- | className | `string` | - | Additional CSS classes |
102
-
103
- ## Declarative Children
104
-
105
- You can also compose entities and relations as JSX children instead of (or alongside) the schema prop:
106
-
107
- ```tsx
108
- <Diagram type="erd" className="h-[500px]">
109
- <Diagram.Entity name="categories" x={0} y={0} draggable>
110
- <Diagram.Field name="id" type="int" primary />
111
- <Diagram.Field name="name" type="varchar" />
112
- </Diagram.Entity>
113
- <Diagram.Entity name="products" x={300} y={0} draggable>
114
- <Diagram.Field name="id" type="int" primary />
115
- <Diagram.Field name="category_id" type="int" foreign />
116
- </Diagram.Entity>
117
- <Diagram.Relation from="categories" to="products" type="one-to-many" />
118
- </Diagram>
119
- ```