dishui 0.0.46 → 0.0.48

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 (115) hide show
  1. package/dist/chart.js +35 -33
  2. package/dist/components/Chart/index.d.ts +1 -1
  3. package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js +1 -2
  4. package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js.map +1 -1
  5. package/dist/components/pro/CodeEditor/themes.js +0 -25
  6. package/dist/components/pro/CodeEditor/themes.js.map +1 -1
  7. package/dist/components/pro/CodeEditor/types.d.ts +1 -1
  8. package/dist/components/pro/DataTable/pivotExtension.d.ts +6 -0
  9. package/dist/components/pro/DataTable/pivotExtension.js +31 -30
  10. package/dist/components/pro/DataTable/pivotExtension.js.map +1 -1
  11. package/dist/components/pro/Flow/Flow.js +500 -459
  12. package/dist/components/pro/Flow/Flow.js.map +1 -1
  13. package/dist/components/pro/Flow/FlowCanvas.js +526 -524
  14. package/dist/components/pro/Flow/FlowCanvas.js.map +1 -1
  15. package/dist/components/pro/Flow/canvas/GridRenderer.d.ts +3 -0
  16. package/dist/components/pro/Flow/canvas/GridRenderer.js +28 -23
  17. package/dist/components/pro/Flow/canvas/GridRenderer.js.map +1 -1
  18. package/dist/components/pro/Flow/canvas/MiniMapRenderer.js +18 -17
  19. package/dist/components/pro/Flow/canvas/MiniMapRenderer.js.map +1 -1
  20. package/dist/components/pro/Flow/canvas/PixiApp.d.ts +24 -0
  21. package/dist/components/pro/Flow/canvas/PixiApp.js +60 -15
  22. package/dist/components/pro/Flow/canvas/PixiApp.js.map +1 -1
  23. package/dist/components/pro/Flow/constants.js +7 -7
  24. package/dist/components/pro/Flow/constants.js.map +1 -1
  25. package/dist/components/pro/Flow/context/FlowAIContext.d.ts +15 -0
  26. package/dist/components/pro/Flow/context/FlowAIContext.js +32 -0
  27. package/dist/components/pro/Flow/context/FlowAIContext.js.map +1 -0
  28. package/dist/components/pro/Flow/context/FlowUIContext.d.ts +4 -1
  29. package/dist/components/pro/Flow/context/FlowUIContext.js +58 -55
  30. package/dist/components/pro/Flow/context/FlowUIContext.js.map +1 -1
  31. package/dist/components/pro/Flow/edges/EdgeRenderer.js +22 -21
  32. package/dist/components/pro/Flow/edges/EdgeRenderer.js.map +1 -1
  33. package/dist/components/pro/Flow/hooks/useFlowImportExport.d.ts +6 -0
  34. package/dist/components/pro/Flow/hooks/useFlowImportExport.js +146 -89
  35. package/dist/components/pro/Flow/hooks/useFlowImportExport.js.map +1 -1
  36. package/dist/components/pro/Flow/hooks/useLayoutActions.d.ts +2 -0
  37. package/dist/components/pro/Flow/hooks/useLayoutActions.js +94 -65
  38. package/dist/components/pro/Flow/hooks/useLayoutActions.js.map +1 -1
  39. package/dist/components/pro/Flow/hooks/usePdfExport.d.ts +10 -0
  40. package/dist/components/pro/Flow/hooks/usePdfExport.js +60 -0
  41. package/dist/components/pro/Flow/hooks/usePdfExport.js.map +1 -0
  42. package/dist/components/pro/Flow/hooks/usePixiApp.d.ts +6 -1
  43. package/dist/components/pro/Flow/hooks/usePixiApp.js +49 -30
  44. package/dist/components/pro/Flow/hooks/usePixiApp.js.map +1 -1
  45. package/dist/components/pro/Flow/index.d.ts +5 -2
  46. package/dist/components/pro/Flow/lines/FreehandTool.js +21 -20
  47. package/dist/components/pro/Flow/lines/FreehandTool.js.map +1 -1
  48. package/dist/components/pro/Flow/lines/GeometricLineTool.js +22 -18
  49. package/dist/components/pro/Flow/lines/GeometricLineTool.js.map +1 -1
  50. package/dist/components/pro/Flow/lines/LineRenderer.js +19 -18
  51. package/dist/components/pro/Flow/lines/LineRenderer.js.map +1 -1
  52. package/dist/components/pro/Flow/nodes/DataNodeView.d.ts +7 -0
  53. package/dist/components/pro/Flow/nodes/DataNodeView.js +217 -0
  54. package/dist/components/pro/Flow/nodes/DataNodeView.js.map +1 -0
  55. package/dist/components/pro/Flow/nodes/MediaContent.js +149 -120
  56. package/dist/components/pro/Flow/nodes/MediaContent.js.map +1 -1
  57. package/dist/components/pro/Flow/nodes/MediaOverlay.js +22 -17
  58. package/dist/components/pro/Flow/nodes/MediaOverlay.js.map +1 -1
  59. package/dist/components/pro/Flow/nodes/NodeRenderer.js +77 -76
  60. package/dist/components/pro/Flow/nodes/NodeRenderer.js.map +1 -1
  61. package/dist/components/pro/Flow/nodes/aiClient.d.ts +22 -0
  62. package/dist/components/pro/Flow/nodes/aiClient.js +107 -54
  63. package/dist/components/pro/Flow/nodes/aiClient.js.map +1 -1
  64. package/dist/components/pro/Flow/nodes/dataUtils.d.ts +52 -0
  65. package/dist/components/pro/Flow/nodes/dataUtils.js +270 -0
  66. package/dist/components/pro/Flow/nodes/dataUtils.js.map +1 -0
  67. package/dist/components/pro/Flow/nodes/svgIcons.js +59 -27
  68. package/dist/components/pro/Flow/nodes/svgIcons.js.map +1 -1
  69. package/dist/components/pro/Flow/panels/AIPanel.d.ts +2 -0
  70. package/dist/components/pro/Flow/panels/AIPanel.js +498 -0
  71. package/dist/components/pro/Flow/panels/AIPanel.js.map +1 -0
  72. package/dist/components/pro/Flow/panels/DataInspectorSection.d.ts +11 -0
  73. package/dist/components/pro/Flow/panels/DataInspectorSection.js +436 -0
  74. package/dist/components/pro/Flow/panels/DataInspectorSection.js.map +1 -0
  75. package/dist/components/pro/Flow/panels/ExpandableTextarea.d.ts +16 -0
  76. package/dist/components/pro/Flow/panels/ExpandableTextarea.js +65 -0
  77. package/dist/components/pro/Flow/panels/ExpandableTextarea.js.map +1 -0
  78. package/dist/components/pro/Flow/panels/FlowPanelGroup.js +51 -39
  79. package/dist/components/pro/Flow/panels/FlowPanelGroup.js.map +1 -1
  80. package/dist/components/pro/Flow/panels/FlowToolbar.d.ts +5 -1
  81. package/dist/components/pro/Flow/panels/FlowToolbar.js +310 -233
  82. package/dist/components/pro/Flow/panels/FlowToolbar.js.map +1 -1
  83. package/dist/components/pro/Flow/panels/InspectorPanel.js +358 -363
  84. package/dist/components/pro/Flow/panels/InspectorPanel.js.map +1 -1
  85. package/dist/components/pro/Flow/panels/OutlinePanel.js +63 -62
  86. package/dist/components/pro/Flow/panels/OutlinePanel.js.map +1 -1
  87. package/dist/components/pro/Flow/panels/ProjectTitle.d.ts +8 -0
  88. package/dist/components/pro/Flow/panels/ProjectTitle.js +49 -0
  89. package/dist/components/pro/Flow/panels/ProjectTitle.js.map +1 -0
  90. package/dist/components/pro/Flow/panels/ShapePalette.js +128 -115
  91. package/dist/components/pro/Flow/panels/ShapePalette.js.map +1 -1
  92. package/dist/components/pro/Flow/panels/toolbarIcons.d.ts +13 -0
  93. package/dist/components/pro/Flow/panels/toolbarIcons.js +241 -87
  94. package/dist/components/pro/Flow/panels/toolbarIcons.js.map +1 -1
  95. package/dist/components/pro/Flow/types.d.ts +77 -1
  96. package/dist/components/pro/Flow/types.js.map +1 -1
  97. package/dist/components/pro/Flow/utils/pdfExport.d.ts +20 -0
  98. package/dist/components/pro/Flow/utils/pdfExport.js +95 -0
  99. package/dist/components/pro/Flow/utils/pdfExport.js.map +1 -0
  100. package/dist/components/pro/Flow/utils/themeColor.d.ts +86 -0
  101. package/dist/components/pro/Flow/utils/themeColor.js +190 -0
  102. package/dist/components/pro/Flow/utils/themeColor.js.map +1 -0
  103. package/dist/contexts/AppContext.d.ts +1 -1
  104. package/dist/contexts/AppContext.js +28 -29
  105. package/dist/contexts/AppContext.js.map +1 -1
  106. package/dist/dishui.css +1 -1
  107. package/dist/favicon.svg +10 -0
  108. package/dist/flow.js +59 -51
  109. package/dist/index-nostyled.d.ts +1 -1
  110. package/dist/index.d.ts +1 -1
  111. package/dist/styles/themeStyles.js +6 -11
  112. package/dist/styles/themeStyles.js.map +1 -1
  113. package/dist/utils/themes.js +3 -23
  114. package/dist/utils/themes.js.map +1 -1
  115. package/package.json +17 -18
@@ -0,0 +1,10 @@
1
+ import type { PixiApp } from '../canvas/PixiApp';
2
+ /**
3
+ * Exports the document's animation anchors as a single PDF. Each page is cropped
4
+ * exactly to an anchor's world rectangle (not the whole viewport), so the PDF
5
+ * contains only the framed slide content. Pages follow the global anchor order,
6
+ * navigating across sub-canvases as needed.
7
+ *
8
+ * Returns a callback; it no-ops (returns false) when there are no anchors.
9
+ */
10
+ export declare function usePdfExport(pixiRef: React.RefObject<PixiApp | null>): () => Promise<boolean>;
@@ -0,0 +1,60 @@
1
+ import { useFlowContext as b } from "../context/FlowContext.js";
2
+ import { useFlowUI as k } from "../context/FlowUIContext.js";
3
+ import { anchorFocusRect as F, canvasStackTo as R, getDocumentSlides as A } from "../nodes/animAnchors.js";
4
+ import { downloadDataURL as L, safeFileBaseName as x } from "./useFlowImportExport.js";
5
+ import { buildPdfFromJpegs as C, pngDataUrlToJpeg as P } from "../utils/pdfExport.js";
6
+ import { useCallback as S } from "react";
7
+ function m(s) {
8
+ return new Promise((t) => {
9
+ let e = s;
10
+ const o = () => {
11
+ --e <= 0 ? t() : requestAnimationFrame(o);
12
+ };
13
+ requestAnimationFrame(o);
14
+ });
15
+ }
16
+ function q(s) {
17
+ const { doc: t, setDoc: e } = b(), { showAnchors: o, setShowAnchors: n } = k();
18
+ return S(async () => {
19
+ const i = A(t);
20
+ if (i.length === 0) return !1;
21
+ const a = s.current;
22
+ if (!a || a.destroyed) return !1;
23
+ const d = t.stack.slice(), p = o;
24
+ n(!1), await m(2);
25
+ const g = 2, c = [];
26
+ try {
27
+ for (const r of i) {
28
+ const f = R(t, r.canvasId);
29
+ f && (e((U) => ({
30
+ ...U,
31
+ stack: f
32
+ })), await m(3));
33
+ const w = F(r.node), u = await a.exportRegionPNG(w, {
34
+ scale: g,
35
+ backgroundColor: 16777215
36
+ });
37
+ u && c.push(await P(u.dataUrl));
38
+ }
39
+ } finally {
40
+ n(p), e((r) => ({
41
+ ...r,
42
+ stack: d
43
+ }));
44
+ }
45
+ if (c.length === 0) return !1;
46
+ const h = C(c), l = URL.createObjectURL(h);
47
+ return L(l, `${x(t.title)}.pdf`), URL.revokeObjectURL(l), !0;
48
+ }, [
49
+ t,
50
+ e,
51
+ o,
52
+ n,
53
+ s
54
+ ]);
55
+ }
56
+ export {
57
+ q as usePdfExport
58
+ };
59
+
60
+ //# sourceMappingURL=usePdfExport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePdfExport.js","names":[],"sources":["../../../../../src/components/pro/Flow/hooks/usePdfExport.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useFlowContext } from '../context/FlowContext';\nimport { useFlowUI } from '../context/FlowUIContext';\nimport { getDocumentSlides, anchorFocusRect, canvasStackTo } from '../nodes/animAnchors';\nimport { buildPdfFromJpegs, pngDataUrlToJpeg } from '../utils/pdfExport';\nimport { downloadDataURL, safeFileBaseName } from './useFlowImportExport';\nimport type { PixiApp } from '../canvas/PixiApp';\n\n/** Await the next N animation frames (lets Pixi settle after a state change). */\nfunction nextFrames(n: number): Promise<void> {\n return new Promise((resolve) => {\n let left = n;\n const step = () => {\n if (--left <= 0) resolve();\n else requestAnimationFrame(step);\n };\n requestAnimationFrame(step);\n });\n}\n\n/**\n * Exports the document's animation anchors as a single PDF. Each page is cropped\n * exactly to an anchor's world rectangle (not the whole viewport), so the PDF\n * contains only the framed slide content. Pages follow the global anchor order,\n * navigating across sub-canvases as needed.\n *\n * Returns a callback; it no-ops (returns false) when there are no anchors.\n */\nexport function usePdfExport(pixiRef: React.RefObject<PixiApp | null>) {\n const { doc, setDoc } = useFlowContext();\n const { showAnchors, setShowAnchors } = useFlowUI();\n\n return useCallback(async (): Promise<boolean> => {\n const slides = getDocumentSlides(doc);\n if (slides.length === 0) return false;\n\n const pixi = pixiRef.current;\n if (!pixi || pixi.destroyed) return false;\n\n // Snapshot state we temporarily change, so we can restore it afterward.\n const originalStack = doc.stack.slice();\n const anchorsWereVisible = showAnchors;\n\n // Hide anchor frames so they don't appear in the exported pages. The region\n // capture drives the world transform directly and restores it each time, so\n // the interactive viewport is untouched.\n setShowAnchors(false);\n await nextFrames(2);\n\n // Render slides at a crisp scale so text/shapes stay sharp in the PDF.\n const CAPTURE_SCALE = 2;\n const pages: Awaited<ReturnType<typeof pngDataUrlToJpeg>>[] = [];\n try {\n for (const slide of slides) {\n // Switch to the slide's canvas if it lives on a nested sub-canvas.\n const stack = canvasStackTo(doc, slide.canvasId);\n if (stack) {\n setDoc((prev) => ({ ...prev, stack }));\n // Canvas swap needs a couple frames to re-render the new node set.\n await nextFrames(3);\n }\n\n const r = anchorFocusRect(slide.node);\n const shot = await pixi.exportRegionPNG(r, {\n scale: CAPTURE_SCALE,\n backgroundColor: 0xffffff,\n });\n if (shot) pages.push(await pngDataUrlToJpeg(shot.dataUrl));\n }\n } finally {\n // Restore prior editor state regardless of success/failure.\n setShowAnchors(anchorsWereVisible);\n setDoc((prev) => ({ ...prev, stack: originalStack }));\n }\n\n if (pages.length === 0) return false;\n const blob = buildPdfFromJpegs(pages);\n const url = URL.createObjectURL(blob);\n downloadDataURL(url, `${safeFileBaseName(doc.title)}.pdf`);\n URL.revokeObjectURL(url);\n return true;\n }, [doc, setDoc, showAnchors, setShowAnchors, pixiRef]);\n}\n"],"mappings":";;;;;;AASA,SAAS,EAAW,GAA0B;AAC5C,SAAO,IAAI,QAAA,CAAS,MAAY;AAC9B,QAAI,IAAO;AACX,UAAM,IAAA,MAAa;AACjB,MAAI,EAAE,KAAQ,IAAG,EAAQ,IACpB,sBAAsB,CAAI;AAAA,IACjC;AACA,0BAAsB,CAAI;AAAA,EAC5B,CAAC;AACH;AAUA,SAAgB,EAAa,GAA0C;AACrE,QAAM,EAAE,KAAA,GAAK,QAAA,EAAA,IAAW,EAAe,GACjC,EAAE,aAAA,GAAa,gBAAA,EAAA,IAAmB,EAAU;AAElD,SAAO,EAAY,YAA8B;AAC/C,UAAM,IAAS,EAAkB,CAAG;AACpC,QAAI,EAAO,WAAW,EAAG,QAAO;AAEhC,UAAM,IAAO,EAAQ;AACrB,QAAI,CAAC,KAAQ,EAAK,UAAW,QAAO;AAGpC,UAAM,IAAgB,EAAI,MAAM,MAAM,GAChC,IAAqB;AAK3B,IAAA,EAAe,EAAK,GACpB,MAAM,EAAW,CAAC;AAGlB,UAAM,IAAgB,GAChB,IAAwD,CAAC;AAC/D,QAAI;AACF,iBAAW,KAAS,GAAQ;AAE1B,cAAM,IAAQ,EAAc,GAAK,EAAM,QAAQ;AAC/C,QAAI,MACF,EAAA,CAAQ,OAAU;AAAA,UAAE,GAAG;AAAA,UAAM,OAAA;AAAA,QAAM,EAAE,GAErC,MAAM,EAAW,CAAC;AAGpB,cAAM,IAAI,EAAgB,EAAM,IAAI,GAC9B,IAAO,MAAM,EAAK,gBAAgB,GAAG;AAAA,UACzC,OAAO;AAAA,UACP,iBAAiB;AAAA,QACnB,CAAC;AACD,QAAI,KAAM,EAAM,KAAK,MAAM,EAAiB,EAAK,OAAO,CAAC;AAAA,MAC3D;AAAA,IACF,UAAA;AAEE,MAAA,EAAe,CAAkB,GACjC,EAAA,CAAQ,OAAU;AAAA,QAAE,GAAG;AAAA,QAAM,OAAO;AAAA,MAAc,EAAE;AAAA,IACtD;AAEA,QAAI,EAAM,WAAW,EAAG,QAAO;AAC/B,UAAM,IAAO,EAAkB,CAAK,GAC9B,IAAM,IAAI,gBAAgB,CAAI;AACpC,WAAA,EAAgB,GAAK,GAAG,EAAiB,EAAI,KAAK,CAAA,MAAO,GACzD,IAAI,gBAAgB,CAAG,GAChB;AAAA,EACT,GAAG;AAAA,IAAC;AAAA,IAAK;AAAA,IAAQ;AAAA,IAAa;AAAA,IAAgB;AAAA,EAAO,CAAC;AACxD"}
@@ -1,9 +1,14 @@
1
1
  import { PixiApp } from '../canvas/PixiApp';
2
+ import { type FlowThemeColors } from '../utils/themeColor';
2
3
  /**
3
4
  * Manages PixiJS Application lifecycle: creates on mount, destroys on unmount,
4
5
  * handles container resize.
6
+ *
7
+ * The canvas backdrop follows the active DishUI theme (`--color-base-200`). We
8
+ * resolve the theme color from the container's inherited CSS scope at init and
9
+ * again whenever the ancestor `data-theme` attribute changes.
5
10
  */
6
- export declare function usePixiApp(containerRef: React.RefObject<HTMLDivElement | null>): {
11
+ export declare function usePixiApp(containerRef: React.RefObject<HTMLDivElement | null>, onThemeColors?: (colors: FlowThemeColors) => void): {
7
12
  pixiRef: import("react").RefObject<PixiApp | null>;
8
13
  canvasRef: import("react").RefObject<HTMLCanvasElement | null>;
9
14
  readyRef: import("react").RefObject<boolean>;
@@ -1,41 +1,60 @@
1
- import { PixiApp as y } from "../canvas/PixiApp.js";
2
- import { useEffect as m, useRef as c } from "react";
3
- function w(o) {
4
- const r = c(null), s = c(null), i = c(!1);
5
- return m(() => {
6
- const n = o.current;
7
- if (!n) return;
8
- let l = !1;
9
- const e = document.createElement("canvas");
10
- e.style.display = "block", e.style.width = "100%", e.style.height = "100%", n.appendChild(e), s.current = e;
11
- const t = new y();
12
- r.current = t;
13
- const u = n.getBoundingClientRect();
14
- t.init({
15
- canvas: e,
16
- width: u.width,
17
- height: u.height
1
+ import { PixiApp as k } from "../canvas/PixiApp.js";
2
+ import { refreshThemePalette as y, resolveFlowThemeColors as w } from "../utils/themeColor.js";
3
+ import { useEffect as x, useRef as o } from "react";
4
+ function O(l, a) {
5
+ const s = o(null), d = o(null), c = o(!1), i = o(a);
6
+ return i.current = a, x(() => {
7
+ const e = l.current;
8
+ if (!e) return;
9
+ let h = !1;
10
+ const t = document.createElement("canvas");
11
+ t.style.display = "block", t.style.width = "100%", t.style.height = "100%", e.appendChild(t), d.current = t;
12
+ const r = new k();
13
+ s.current = r;
14
+ const f = e.getBoundingClientRect();
15
+ y(e);
16
+ const m = w(e);
17
+ r.init({
18
+ canvas: t,
19
+ width: f.width,
20
+ height: f.height,
21
+ backgroundColor: m.background
18
22
  }).then(() => {
19
- l || (i.current = !0);
23
+ h || (c.current = !0, i.current?.(m));
20
24
  });
21
- const d = new ResizeObserver((h) => {
22
- if (!t.destroyed)
23
- for (const p of h) {
24
- const { width: f, height: a } = p.contentRect;
25
- f > 0 && a > 0 && t.resize(f, a);
25
+ const p = new ResizeObserver((n) => {
26
+ if (!r.destroyed)
27
+ for (const R of n) {
28
+ const { width: v, height: g } = R.contentRect;
29
+ v > 0 && g > 0 && r.resize(v, g);
26
30
  }
27
31
  });
28
- return d.observe(n), () => {
29
- l = !0, d.disconnect(), t.destroy(), r.current = null, i.current = !1, e.parentNode && e.parentNode.removeChild(e);
32
+ p.observe(e);
33
+ const C = () => {
34
+ if (r.destroyed) return;
35
+ y(e);
36
+ const n = w(e);
37
+ r.setBackgroundColor(n.background), i.current?.(n);
38
+ }, u = new MutationObserver(C);
39
+ u.observe(document.documentElement, {
40
+ attributes: !0,
41
+ attributeFilter: ["data-theme", "class"]
42
+ });
43
+ const b = e.closest("[data-theme]");
44
+ return b && u.observe(b, {
45
+ attributes: !0,
46
+ attributeFilter: ["data-theme", "class"]
47
+ }), () => {
48
+ h = !0, p.disconnect(), u.disconnect(), r.destroy(), s.current = null, c.current = !1, t.parentNode && t.parentNode.removeChild(t);
30
49
  };
31
- }, [o]), {
32
- pixiRef: r,
33
- canvasRef: s,
34
- readyRef: i
50
+ }, [l]), {
51
+ pixiRef: s,
52
+ canvasRef: d,
53
+ readyRef: c
35
54
  };
36
55
  }
37
56
  export {
38
- w as usePixiApp
57
+ O as usePixiApp
39
58
  };
40
59
 
41
60
  //# sourceMappingURL=usePixiApp.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"usePixiApp.js","names":[],"sources":["../../../../../src/components/pro/Flow/hooks/usePixiApp.ts"],"sourcesContent":["import { useRef, useEffect, useCallback } from 'react';\nimport { PixiApp } from '../canvas/PixiApp';\n\n/**\n * Manages PixiJS Application lifecycle: creates on mount, destroys on unmount,\n * handles container resize.\n */\nexport function usePixiApp(containerRef: React.RefObject<HTMLDivElement | null>) {\n const pixiRef = useRef<PixiApp | null>(null);\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const readyRef = useRef(false);\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n let cancelled = false;\n\n const canvas = document.createElement('canvas');\n canvas.style.display = 'block';\n canvas.style.width = '100%';\n canvas.style.height = '100%';\n container.appendChild(canvas);\n canvasRef.current = canvas;\n\n const pixi = new PixiApp();\n pixiRef.current = pixi;\n\n const rect = container.getBoundingClientRect();\n pixi.init({\n canvas,\n width: rect.width,\n height: rect.height,\n }).then(() => {\n if (!cancelled) readyRef.current = true;\n });\n\n const ro = new ResizeObserver((entries) => {\n if (pixi.destroyed) return;\n for (const entry of entries) {\n const { width, height } = entry.contentRect;\n if (width > 0 && height > 0) {\n pixi.resize(width, height);\n }\n }\n });\n ro.observe(container);\n\n return () => {\n cancelled = true;\n ro.disconnect();\n pixi.destroy();\n pixiRef.current = null;\n readyRef.current = false;\n if (canvas.parentNode) canvas.parentNode.removeChild(canvas);\n };\n }, [containerRef]);\n\n return { pixiRef, canvasRef, readyRef };\n}\n"],"mappings":";;AAOA,SAAgB,EAAW,GAAsD;AAC/E,QAAM,IAAU,EAAuB,IAAI,GACrC,IAAY,EAAiC,IAAI,GACjD,IAAW,EAAO,EAAK;AAE7B,SAAA,EAAA,MAAgB;AACd,UAAM,IAAY,EAAa;AAC/B,QAAI,CAAC,EAAW;AAEhB,QAAI,IAAY;AAEhB,UAAM,IAAS,SAAS,cAAc,QAAQ;AAC9C,IAAA,EAAO,MAAM,UAAU,SACvB,EAAO,MAAM,QAAQ,QACrB,EAAO,MAAM,SAAS,QACtB,EAAU,YAAY,CAAM,GAC5B,EAAU,UAAU;AAEpB,UAAM,IAAO,IAAI,EAAQ;AACzB,IAAA,EAAQ,UAAU;AAElB,UAAM,IAAO,EAAU,sBAAsB;AAC7C,IAAA,EAAK,KAAK;AAAA,MACR,QAAA;AAAA,MACA,OAAO,EAAK;AAAA,MACZ,QAAQ,EAAK;AAAA,IACf,CAAC,EAAE,KAAA,MAAW;AACZ,MAAK,MAAW,EAAS,UAAU;AAAA,IACrC,CAAC;AAED,UAAM,IAAK,IAAI,eAAA,CAAgB,MAAY;AACzC,UAAI,CAAA,EAAK;AACT,mBAAW,KAAS,GAAS;AAC3B,gBAAM,EAAE,OAAA,GAAO,QAAA,EAAA,IAAW,EAAM;AAChC,UAAI,IAAQ,KAAK,IAAS,KACxB,EAAK,OAAO,GAAO,CAAM;AAAA,QAE7B;AAAA,IACF,CAAC;AACD,WAAA,EAAG,QAAQ,CAAS,GAEpB,MAAa;AACX,MAAA,IAAY,IACZ,EAAG,WAAW,GACd,EAAK,QAAQ,GACb,EAAQ,UAAU,MAClB,EAAS,UAAU,IACf,EAAO,cAAY,EAAO,WAAW,YAAY,CAAM;AAAA,IAC7D;AAAA,EACF,GAAG,CAAC,CAAY,CAAC,GAEV;AAAA,IAAE,SAAA;AAAA,IAAS,WAAA;AAAA,IAAW,UAAA;AAAA,EAAS;AACxC"}
1
+ {"version":3,"file":"usePixiApp.js","names":[],"sources":["../../../../../src/components/pro/Flow/hooks/usePixiApp.ts"],"sourcesContent":["import { useRef, useEffect, useCallback } from 'react';\nimport { PixiApp } from '../canvas/PixiApp';\nimport { resolveFlowThemeColors, refreshThemePalette, type FlowThemeColors } from '../utils/themeColor';\n\n/**\n * Manages PixiJS Application lifecycle: creates on mount, destroys on unmount,\n * handles container resize.\n *\n * The canvas backdrop follows the active DishUI theme (`--color-base-200`). We\n * resolve the theme color from the container's inherited CSS scope at init and\n * again whenever the ancestor `data-theme` attribute changes.\n */\nexport function usePixiApp(\n containerRef: React.RefObject<HTMLDivElement | null>,\n onThemeColors?: (colors: FlowThemeColors) => void,\n) {\n const pixiRef = useRef<PixiApp | null>(null);\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const readyRef = useRef(false);\n const onThemeColorsRef = useRef(onThemeColors);\n onThemeColorsRef.current = onThemeColors;\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n let cancelled = false;\n\n const canvas = document.createElement('canvas');\n canvas.style.display = 'block';\n canvas.style.width = '100%';\n canvas.style.height = '100%';\n container.appendChild(canvas);\n canvasRef.current = canvas;\n\n const pixi = new PixiApp();\n pixiRef.current = pixi;\n\n const rect = container.getBoundingClientRect();\n refreshThemePalette(container);\n const themeColors = resolveFlowThemeColors(container);\n pixi.init({\n canvas,\n width: rect.width,\n height: rect.height,\n backgroundColor: themeColors.background,\n }).then(() => {\n if (!cancelled) {\n readyRef.current = true;\n onThemeColorsRef.current?.(themeColors);\n }\n });\n\n const ro = new ResizeObserver((entries) => {\n if (pixi.destroyed) return;\n for (const entry of entries) {\n const { width, height } = entry.contentRect;\n if (width > 0 && height > 0) {\n pixi.resize(width, height);\n }\n }\n });\n ro.observe(container);\n\n // React to DishUI theme switches (the theme is applied via a `data-theme`\n // attribute on an ancestor element). Re-resolve the themed colors and push\n // them to the canvas + subscriber.\n const applyTheme = () => {\n if (pixi.destroyed) return;\n refreshThemePalette(container);\n const colors = resolveFlowThemeColors(container);\n pixi.setBackgroundColor(colors.background);\n onThemeColorsRef.current?.(colors);\n };\n const themeObserver = new MutationObserver(applyTheme);\n themeObserver.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['data-theme', 'class'],\n });\n // Also watch the closest themed ancestor, if any.\n const themedAncestor = container.closest('[data-theme]');\n if (themedAncestor) {\n themeObserver.observe(themedAncestor, {\n attributes: true,\n attributeFilter: ['data-theme', 'class'],\n });\n }\n\n return () => {\n cancelled = true;\n ro.disconnect();\n themeObserver.disconnect();\n pixi.destroy();\n pixiRef.current = null;\n readyRef.current = false;\n if (canvas.parentNode) canvas.parentNode.removeChild(canvas);\n };\n }, [containerRef]);\n\n return { pixiRef, canvasRef, readyRef };\n}\n"],"mappings":";;;AAYA,SAAgB,EACd,GACA,GACA;AACA,QAAM,IAAU,EAAuB,IAAI,GACrC,IAAY,EAAiC,IAAI,GACjD,IAAW,EAAO,EAAK,GACvB,IAAmB,EAAO,CAAa;AAC7C,SAAA,EAAiB,UAAU,GAE3B,EAAA,MAAgB;AACd,UAAM,IAAY,EAAa;AAC/B,QAAI,CAAC,EAAW;AAEhB,QAAI,IAAY;AAEhB,UAAM,IAAS,SAAS,cAAc,QAAQ;AAC9C,IAAA,EAAO,MAAM,UAAU,SACvB,EAAO,MAAM,QAAQ,QACrB,EAAO,MAAM,SAAS,QACtB,EAAU,YAAY,CAAM,GAC5B,EAAU,UAAU;AAEpB,UAAM,IAAO,IAAI,EAAQ;AACzB,IAAA,EAAQ,UAAU;AAElB,UAAM,IAAO,EAAU,sBAAsB;AAC7C,IAAA,EAAoB,CAAS;AAC7B,UAAM,IAAc,EAAuB,CAAS;AACpD,IAAA,EAAK,KAAK;AAAA,MACR,QAAA;AAAA,MACA,OAAO,EAAK;AAAA,MACZ,QAAQ,EAAK;AAAA,MACb,iBAAiB,EAAY;AAAA,IAC/B,CAAC,EAAE,KAAA,MAAW;AACZ,MAAK,MACH,EAAS,UAAU,IACnB,EAAiB,UAAU,CAAW;AAAA,IAE1C,CAAC;AAED,UAAM,IAAK,IAAI,eAAA,CAAgB,MAAY;AACzC,UAAI,CAAA,EAAK;AACT,mBAAW,KAAS,GAAS;AAC3B,gBAAM,EAAE,OAAA,GAAO,QAAA,EAAA,IAAW,EAAM;AAChC,UAAI,IAAQ,KAAK,IAAS,KACxB,EAAK,OAAO,GAAO,CAAM;AAAA,QAE7B;AAAA,IACF,CAAC;AACD,IAAA,EAAG,QAAQ,CAAS;AAKpB,UAAM,IAAA,MAAmB;AACvB,UAAI,EAAK,UAAW;AACpB,MAAA,EAAoB,CAAS;AAC7B,YAAM,IAAS,EAAuB,CAAS;AAC/C,MAAA,EAAK,mBAAmB,EAAO,UAAU,GACzC,EAAiB,UAAU,CAAM;AAAA,IACnC,GACM,IAAgB,IAAI,iBAAiB,CAAU;AACrD,IAAA,EAAc,QAAQ,SAAS,iBAAiB;AAAA,MAC9C,YAAY;AAAA,MACZ,iBAAiB,CAAC,cAAc,OAAO;AAAA,IACzC,CAAC;AAED,UAAM,IAAiB,EAAU,QAAQ,cAAc;AACvD,WAAI,KACF,EAAc,QAAQ,GAAgB;AAAA,MACpC,YAAY;AAAA,MACZ,iBAAiB,CAAC,cAAc,OAAO;AAAA,IACzC,CAAC,GAGH,MAAa;AACX,MAAA,IAAY,IACZ,EAAG,WAAW,GACd,EAAc,WAAW,GACzB,EAAK,QAAQ,GACb,EAAQ,UAAU,MAClB,EAAS,UAAU,IACf,EAAO,cAAY,EAAO,WAAW,YAAY,CAAM;AAAA,IAC7D;AAAA,EACF,GAAG,CAAC,CAAY,CAAC,GAEV;AAAA,IAAE,SAAA;AAAA,IAAS,WAAA;AAAA,IAAW,UAAA;AAAA,EAAS;AACxC"}
@@ -9,13 +9,16 @@ export { useSelection } from './hooks/useSelection';
9
9
  export { useClipboard } from './hooks/useClipboard';
10
10
  export { useLayoutActions } from './hooks/useLayoutActions';
11
11
  export { useFlowImportExport, exportCanvasToPNG, downloadDataURL } from './hooks/useFlowImportExport';
12
- export { default as FlowToolbar } from './panels/FlowToolbar';
12
+ export { default as FlowToolbar, FlowZoomControls } from './panels/FlowToolbar';
13
13
  export { default as ShapePalette } from './panels/ShapePalette';
14
14
  export { default as InspectorPanel } from './panels/InspectorPanel';
15
15
  export { default as OutlinePanel } from './panels/OutlinePanel';
16
+ export { AIPanelContent } from './panels/AIPanel';
17
+ export { useFlowAI, FlowAIProvider } from './context/FlowAIContext';
16
18
  export { default as ContextMenu } from './panels/ContextMenu';
17
19
  export { default as Breadcrumb } from './panels/Breadcrumb';
18
- export type { FlowProps, FlowDocument, FlowCanvasData, FlowNode, FlowNodeData, FlowEdge, FlowEdgeData, FlowLine, FlowLineType, FlowShapeType, FlowEdgeTypeName, FlowEdgeMarkerKind, FlowEdgeLineStyle, FlowEdgeDashDensity, FlowBezierControl, FlowBorderStyle, FlowToolMode, ViewportState, SelectionState, FlowNodeAttribute, GradientDirection, FlowGroupLabelPlacement, FlowGroupLabelAlign, FlowIconLabelPlacement, FlowMediaKind, FlowModelFormat, } from './types';
20
+ export { default as ProjectTitle } from './panels/ProjectTitle';
21
+ export type { FlowProps, FlowDocument, FlowCanvasData, FlowNode, FlowNodeData, FlowEdge, FlowEdgeData, FlowLine, FlowLineType, FlowShapeType, FlowEdgeTypeName, FlowEdgeMarkerKind, FlowEdgeLineStyle, FlowEdgeDashDensity, FlowBezierControl, FlowBorderStyle, FlowToolMode, ViewportState, SelectionState, FlowNodeAttribute, GradientDirection, FlowGroupLabelPlacement, FlowGroupLabelAlign, FlowIconLabelPlacement, FlowMediaKind, FlowModelFormat, FlowDataConfig, FlowDataColumn, FlowDataColumnType, FlowDataView, FlowDataChartType, FlowDataChartConfig, FlowDataPivotConfig, FlowDataPivotPanelPlacement, FlowDataAggFn, } from './types';
19
22
  export { FLOW_NODE_TYPES } from './types';
20
23
  export { SVG_ICON_CATEGORIES, getSvgIcon, getSvgIconsByCategory, getAllSvgIcons, buildSvgMarkup, } from './nodes/svgIcons';
21
24
  export type { SvgIconDef, SvgIconCategory } from './nodes/svgIcons';
@@ -1,15 +1,16 @@
1
- import { generateId as s } from "../nodes/nodeUtils.js";
2
- import { simplifyPath as o, smoothCatmullRom as r } from "./lineSmoothing.js";
3
- import { Graphics as h } from "pixi.js";
4
- var w = class {
1
+ import { resolveThemeColor as s } from "../utils/themeColor.js";
2
+ import { generateId as o } from "../nodes/nodeUtils.js";
3
+ import { simplifyPath as r, smoothCatmullRom as h } from "./lineSmoothing.js";
4
+ import { Graphics as a } from "pixi.js";
5
+ var v = class {
5
6
  stage;
6
7
  preview;
7
8
  callbacks;
8
9
  rawPoints = [];
9
10
  drawing = !1;
10
11
  _active = !1;
11
- constructor(i, t, e) {
12
- this.stage = i, this.callbacks = e, this.preview = new h(), this.preview.label = "freehand-preview", this.preview.visible = !1, t.addChild(this.preview);
12
+ constructor(t, i, e) {
13
+ this.stage = t, this.callbacks = e, this.preview = new a(), this.preview.label = "freehand-preview", this.preview.visible = !1, i.addChild(this.preview);
13
14
  }
14
15
  get active() {
15
16
  return this._active;
@@ -20,19 +21,19 @@ var w = class {
20
21
  deactivate() {
21
22
  this._active = !1, this.drawing = !1, this.rawPoints = [], this.preview.destroyed || (this.preview.clear(), this.preview.visible = !1), this.stage.off("pointerdown", this._onDown, this), this.stage.off("globalpointermove", this._onMove, this), this.stage.off("pointerup", this._onUp, this), this.stage.off("pointerupoutside", this._onUp, this);
22
23
  }
23
- _onDown = (i) => {
24
- if (i.button !== 0) return;
25
- const t = this.callbacks.screenToWorld(i.global.x, i.global.y);
26
- this.drawing = !0, this.rawPoints = [t], this.preview.visible = !0, this.preview.clear();
24
+ _onDown = (t) => {
25
+ if (t.button !== 0) return;
26
+ const i = this.callbacks.screenToWorld(t.global.x, t.global.y);
27
+ this.drawing = !0, this.rawPoints = [i], this.preview.visible = !0, this.preview.clear();
27
28
  };
28
- _onMove = (i) => {
29
+ _onMove = (t) => {
29
30
  if (!this.drawing) return;
30
- const t = this.callbacks.screenToWorld(i.global.x, i.global.y);
31
- if (this.rawPoints.push(t), this.preview.clear(), !(this.rawPoints.length < 2)) {
31
+ const i = this.callbacks.screenToWorld(t.global.x, t.global.y);
32
+ if (this.rawPoints.push(i), this.preview.clear(), !(this.rawPoints.length < 2)) {
32
33
  this.preview.moveTo(this.rawPoints[0].x, this.rawPoints[0].y);
33
34
  for (let e = 1; e < this.rawPoints.length; e++) this.preview.lineTo(this.rawPoints[e].x, this.rawPoints[e].y);
34
35
  this.preview.stroke({
35
- color: 3621201,
36
+ color: s("theme:base-content", "#374151"),
36
37
  width: 2,
37
38
  alpha: 0.6
38
39
  });
@@ -44,22 +45,22 @@ var w = class {
44
45
  this.rawPoints = [];
45
46
  return;
46
47
  }
47
- const i = r(o(this.rawPoints, 2), 4), t = {
48
- id: s("line"),
48
+ const t = h(r(this.rawPoints, 2), 4), i = {
49
+ id: o("line"),
49
50
  type: "freehand",
50
- points: i,
51
- strokeColor: "#374151",
51
+ points: t,
52
+ strokeColor: "theme:base-content",
52
53
  strokeWidth: 2,
53
54
  lineStyle: "solid"
54
55
  };
55
- this.callbacks.onLineComplete(t), this.rawPoints = [];
56
+ this.callbacks.onLineComplete(i), this.rawPoints = [];
56
57
  };
57
58
  destroy() {
58
59
  this.deactivate(), this.preview.destroyed || this.preview.destroy();
59
60
  }
60
61
  };
61
62
  export {
62
- w as FreehandTool
63
+ v as FreehandTool
63
64
  };
64
65
 
65
66
  //# sourceMappingURL=FreehandTool.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FreehandTool.js","names":[],"sources":["../../../../../src/components/pro/Flow/lines/FreehandTool.ts"],"sourcesContent":["import { Graphics, Container, FederatedPointerEvent } from 'pixi.js';\nimport { simplifyPath, smoothCatmullRom, type Point } from './lineSmoothing';\nimport type { FlowLine } from '../types';\nimport { generateId } from '../nodes/nodeUtils';\n\nexport interface FreehandToolCallbacks {\n /** Called when a freehand line is finished */\n onLineComplete: (line: FlowLine) => void;\n /** Convert screen coords to world coords */\n screenToWorld: (sx: number, sy: number) => { x: number; y: number };\n}\n\n/**\n * Captures pointer trail for freehand drawing, smooths and stores as FlowLine.\n */\nexport class FreehandTool {\n private stage: Container;\n private preview: Graphics;\n private callbacks: FreehandToolCallbacks;\n private rawPoints: Point[] = [];\n private drawing = false;\n private _active = false;\n\n constructor(stage: Container, world: Container, callbacks: FreehandToolCallbacks) {\n this.stage = stage;\n this.callbacks = callbacks;\n this.preview = new Graphics();\n this.preview.label = 'freehand-preview';\n this.preview.visible = false;\n world.addChild(this.preview);\n }\n\n get active(): boolean { return this._active; }\n\n activate(): void {\n this._active = true;\n this.stage.on('pointerdown', this._onDown, this);\n this.stage.on('globalpointermove', this._onMove, this);\n this.stage.on('pointerup', this._onUp, this);\n this.stage.on('pointerupoutside', this._onUp, this);\n }\n\n deactivate(): void {\n this._active = false;\n this.drawing = false;\n this.rawPoints = [];\n if (!this.preview.destroyed) {\n this.preview.clear();\n this.preview.visible = false;\n }\n this.stage.off('pointerdown', this._onDown, this);\n this.stage.off('globalpointermove', this._onMove, this);\n this.stage.off('pointerup', this._onUp, this);\n this.stage.off('pointerupoutside', this._onUp, this);\n }\n\n private _onDown = (e: FederatedPointerEvent): void => {\n if (e.button !== 0) return;\n const world = this.callbacks.screenToWorld(e.global.x, e.global.y);\n this.drawing = true;\n this.rawPoints = [world];\n this.preview.visible = true;\n this.preview.clear();\n };\n\n private _onMove = (e: FederatedPointerEvent): void => {\n if (!this.drawing) return;\n const world = this.callbacks.screenToWorld(e.global.x, e.global.y);\n this.rawPoints.push(world);\n\n // Draw preview\n this.preview.clear();\n if (this.rawPoints.length < 2) return;\n this.preview.moveTo(this.rawPoints[0].x, this.rawPoints[0].y);\n for (let i = 1; i < this.rawPoints.length; i++) {\n this.preview.lineTo(this.rawPoints[i].x, this.rawPoints[i].y);\n }\n this.preview.stroke({ color: 0x374151, width: 2, alpha: 0.6 });\n };\n\n private _onUp = (): void => {\n if (!this.drawing) return;\n this.drawing = false;\n this.preview.clear();\n this.preview.visible = false;\n\n if (this.rawPoints.length < 3) {\n this.rawPoints = [];\n return;\n }\n\n const simplified = simplifyPath(this.rawPoints, 2);\n const smoothed = smoothCatmullRom(simplified, 4);\n\n const line: FlowLine = {\n id: generateId('line'),\n type: 'freehand',\n points: smoothed,\n strokeColor: '#374151',\n strokeWidth: 2,\n lineStyle: 'solid',\n };\n\n this.callbacks.onLineComplete(line);\n this.rawPoints = [];\n };\n\n destroy(): void {\n this.deactivate();\n if (!this.preview.destroyed) this.preview.destroy();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"FreehandTool.js","names":[],"sources":["../../../../../src/components/pro/Flow/lines/FreehandTool.ts"],"sourcesContent":["import { Graphics, Container, FederatedPointerEvent } from 'pixi.js';\nimport { simplifyPath, smoothCatmullRom, type Point } from './lineSmoothing';\nimport type { FlowLine } from '../types';\nimport { generateId } from '../nodes/nodeUtils';\nimport { resolveThemeColor } from '../utils/themeColor';\n\nexport interface FreehandToolCallbacks {\n /** Called when a freehand line is finished */\n onLineComplete: (line: FlowLine) => void;\n /** Convert screen coords to world coords */\n screenToWorld: (sx: number, sy: number) => { x: number; y: number };\n}\n\n/**\n * Captures pointer trail for freehand drawing, smooths and stores as FlowLine.\n */\nexport class FreehandTool {\n private stage: Container;\n private preview: Graphics;\n private callbacks: FreehandToolCallbacks;\n private rawPoints: Point[] = [];\n private drawing = false;\n private _active = false;\n\n constructor(stage: Container, world: Container, callbacks: FreehandToolCallbacks) {\n this.stage = stage;\n this.callbacks = callbacks;\n this.preview = new Graphics();\n this.preview.label = 'freehand-preview';\n this.preview.visible = false;\n world.addChild(this.preview);\n }\n\n get active(): boolean { return this._active; }\n\n activate(): void {\n this._active = true;\n this.stage.on('pointerdown', this._onDown, this);\n this.stage.on('globalpointermove', this._onMove, this);\n this.stage.on('pointerup', this._onUp, this);\n this.stage.on('pointerupoutside', this._onUp, this);\n }\n\n deactivate(): void {\n this._active = false;\n this.drawing = false;\n this.rawPoints = [];\n if (!this.preview.destroyed) {\n this.preview.clear();\n this.preview.visible = false;\n }\n this.stage.off('pointerdown', this._onDown, this);\n this.stage.off('globalpointermove', this._onMove, this);\n this.stage.off('pointerup', this._onUp, this);\n this.stage.off('pointerupoutside', this._onUp, this);\n }\n\n private _onDown = (e: FederatedPointerEvent): void => {\n if (e.button !== 0) return;\n const world = this.callbacks.screenToWorld(e.global.x, e.global.y);\n this.drawing = true;\n this.rawPoints = [world];\n this.preview.visible = true;\n this.preview.clear();\n };\n\n private _onMove = (e: FederatedPointerEvent): void => {\n if (!this.drawing) return;\n const world = this.callbacks.screenToWorld(e.global.x, e.global.y);\n this.rawPoints.push(world);\n\n // Draw preview\n this.preview.clear();\n if (this.rawPoints.length < 2) return;\n this.preview.moveTo(this.rawPoints[0].x, this.rawPoints[0].y);\n for (let i = 1; i < this.rawPoints.length; i++) {\n this.preview.lineTo(this.rawPoints[i].x, this.rawPoints[i].y);\n }\n this.preview.stroke({ color: resolveThemeColor('theme:base-content', '#374151'), width: 2, alpha: 0.6 });\n };\n\n private _onUp = (): void => {\n if (!this.drawing) return;\n this.drawing = false;\n this.preview.clear();\n this.preview.visible = false;\n\n if (this.rawPoints.length < 3) {\n this.rawPoints = [];\n return;\n }\n\n const simplified = simplifyPath(this.rawPoints, 2);\n const smoothed = smoothCatmullRom(simplified, 4);\n\n const line: FlowLine = {\n id: generateId('line'),\n type: 'freehand',\n points: smoothed,\n strokeColor: 'theme:base-content',\n strokeWidth: 2,\n lineStyle: 'solid',\n };\n\n this.callbacks.onLineComplete(line);\n this.rawPoints = [];\n };\n\n destroy(): void {\n this.deactivate();\n if (!this.preview.destroyed) this.preview.destroy();\n }\n}\n"],"mappings":"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"}
@@ -1,6 +1,10 @@
1
- import { generateId as o } from "../nodes/nodeUtils.js";
1
+ import { resolveThemeColor as o } from "../utils/themeColor.js";
2
+ import { generateId as n } from "../nodes/nodeUtils.js";
2
3
  import { Graphics as h } from "pixi.js";
3
- var r = class {
4
+ function r() {
5
+ return o("theme:base-content", "#374151");
6
+ }
7
+ var p = class {
4
8
  stage;
5
9
  preview;
6
10
  callbacks;
@@ -16,8 +20,8 @@ var r = class {
16
20
  x: 0,
17
21
  y: 0
18
22
  };
19
- constructor(i, t, e) {
20
- this.stage = i, this.callbacks = e, this.preview = new h(), this.preview.label = "geo-line-preview", this.preview.visible = !1, t.addChild(this.preview), this._handleKeyDown = this._handleKeyDown.bind(this);
23
+ constructor(i, e, t) {
24
+ this.stage = i, this.callbacks = t, this.preview = new h(), this.preview.label = "geo-line-preview", this.preview.visible = !1, e.addChild(this.preview), this._handleKeyDown = this._handleKeyDown.bind(this);
21
25
  }
22
26
  get active() {
23
27
  return this._active;
@@ -39,43 +43,43 @@ var r = class {
39
43
  }
40
44
  _onClick = (i) => {
41
45
  if (i.button !== 0) return;
42
- const t = this.callbacks.screenToWorld(i.global.x, i.global.y), e = Date.now(), s = e - this._lastClickTime < 350 && Math.hypot(t.x - this._lastClickPos.x, t.y - this._lastClickPos.y) < 10;
43
- if (this._lastClickTime = e, this._lastClickPos = t, s && this._mode === "polyline" && this.points.length >= 2) {
46
+ const e = this.callbacks.screenToWorld(i.global.x, i.global.y), t = Date.now(), s = t - this._lastClickTime < 350 && Math.hypot(e.x - this._lastClickPos.x, e.y - this._lastClickPos.y) < 10;
47
+ if (this._lastClickTime = t, this._lastClickPos = e, s && this._mode === "polyline" && this.points.length >= 2) {
44
48
  this._finishLine();
45
49
  return;
46
50
  }
47
- this.points.push(t), (this._mode === "straight" || this._mode === "arrow") && this.points.length >= 2 && this._finishLine();
51
+ this.points.push(e), (this._mode === "straight" || this._mode === "arrow") && this.points.length >= 2 && this._finishLine();
48
52
  };
49
53
  _onMove = (i) => {
50
- const t = this.callbacks.screenToWorld(i.global.x, i.global.y);
51
- if (this._currentPos = t, this.points.length !== 0) {
54
+ const e = this.callbacks.screenToWorld(i.global.x, i.global.y);
55
+ if (this._currentPos = e, this.points.length !== 0) {
52
56
  this.preview.visible = !0, this.preview.clear(), this.preview.moveTo(this.points[0].x, this.points[0].y);
53
- for (let e = 1; e < this.points.length; e++) this.preview.lineTo(this.points[e].x, this.points[e].y);
54
- this.preview.lineTo(t.x, t.y), this.preview.stroke({
55
- color: 3621201,
57
+ for (let t = 1; t < this.points.length; t++) this.preview.lineTo(this.points[t].x, this.points[t].y);
58
+ this.preview.lineTo(e.x, e.y), this.preview.stroke({
59
+ color: r(),
56
60
  width: 2,
57
61
  alpha: 0.5
58
62
  });
59
63
  }
60
64
  };
61
65
  _finishLine() {
62
- const i = this._mode === "arrow" ? "arrowclosed" : "none", t = this._mode === "arrow" ? "arrow" : this._mode, e = {
63
- id: o("line"),
64
- type: t,
66
+ const i = this._mode === "arrow" ? "arrowclosed" : "none", e = this._mode === "arrow" ? "arrow" : this._mode, t = {
67
+ id: n("line"),
68
+ type: e,
65
69
  points: [...this.points],
66
- strokeColor: "#374151",
70
+ strokeColor: "theme:base-content",
67
71
  strokeWidth: 2,
68
72
  lineStyle: "solid",
69
73
  markerEnd: i
70
74
  };
71
- this.callbacks.onLineComplete(e), this.points = [], this.preview.clear(), this.preview.visible = !1;
75
+ this.callbacks.onLineComplete(t), this.points = [], this.preview.clear(), this.preview.visible = !1;
72
76
  }
73
77
  destroy() {
74
78
  this.deactivate(), this.preview.destroyed || this.preview.destroy();
75
79
  }
76
80
  };
77
81
  export {
78
- r as GeometricLineTool
82
+ p as GeometricLineTool
79
83
  };
80
84
 
81
85
  //# sourceMappingURL=GeometricLineTool.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"GeometricLineTool.js","names":[],"sources":["../../../../../src/components/pro/Flow/lines/GeometricLineTool.ts"],"sourcesContent":["import { Graphics, Container, FederatedPointerEvent } from 'pixi.js';\nimport type { FlowLine, FlowLineType, FlowEdgeMarkerKind } from '../types';\nimport { generateId } from '../nodes/nodeUtils';\n\nexport interface GeometricLineToolCallbacks {\n onLineComplete: (line: FlowLine) => void;\n screenToWorld: (sx: number, sy: number) => { x: number; y: number };\n}\n\ntype GeoMode = 'straight' | 'polyline' | 'arrow';\n\n/**\n * Click-to-place geometric lines: straight, polyline, and arrow.\n * - straight/arrow: click start, click end\n * - polyline: click each point, double-click to finish\n */\nexport class GeometricLineTool {\n private stage: Container;\n private preview: Graphics;\n private callbacks: GeometricLineToolCallbacks;\n private points: Array<{ x: number; y: number }> = [];\n private _active = false;\n private _mode: GeoMode = 'straight';\n private _currentPos = { x: 0, y: 0 };\n private _lastClickTime = 0;\n private _lastClickPos = { x: 0, y: 0 };\n\n constructor(stage: Container, world: Container, callbacks: GeometricLineToolCallbacks) {\n this.stage = stage;\n this.callbacks = callbacks;\n this.preview = new Graphics();\n this.preview.label = 'geo-line-preview';\n this.preview.visible = false;\n world.addChild(this.preview);\n this._handleKeyDown = this._handleKeyDown.bind(this);\n }\n\n get active(): boolean { return this._active; }\n get mode(): GeoMode { return this._mode; }\n set mode(m: GeoMode) { this._mode = m; }\n\n activate(mode: GeoMode = 'straight'): void {\n this._active = true;\n this._mode = mode;\n this.points = [];\n this._lastClickTime = 0;\n this.stage.on('pointerdown', this._onClick, this);\n this.stage.on('globalpointermove', this._onMove, this);\n window.addEventListener('keydown', this._handleKeyDown);\n }\n\n deactivate(): void {\n this._active = false;\n this.points = [];\n if (!this.preview.destroyed) {\n this.preview.clear();\n this.preview.visible = false;\n }\n this.stage.off('pointerdown', this._onClick, this);\n this.stage.off('globalpointermove', this._onMove, this);\n window.removeEventListener('keydown', this._handleKeyDown);\n }\n\n private _handleKeyDown(e: KeyboardEvent): void {\n if (e.key === 'Enter' || e.key === 'Return') {\n if (this._mode === 'polyline' && this.points.length >= 2) {\n this._finishLine();\n }\n }\n }\n\n private _onClick = (e: FederatedPointerEvent): void => {\n if (e.button !== 0) return;\n const world = this.callbacks.screenToWorld(e.global.x, e.global.y);\n\n const now = Date.now();\n const isDbl = now - this._lastClickTime < 350\n && Math.hypot(world.x - this._lastClickPos.x, world.y - this._lastClickPos.y) < 10;\n this._lastClickTime = now;\n this._lastClickPos = world;\n\n if (isDbl && this._mode === 'polyline' && this.points.length >= 2) {\n this._finishLine();\n return;\n }\n\n this.points.push(world);\n if ((this._mode === 'straight' || this._mode === 'arrow') && this.points.length >= 2) {\n this._finishLine();\n }\n };\n\n private _onMove = (e: FederatedPointerEvent): void => {\n const world = this.callbacks.screenToWorld(e.global.x, e.global.y);\n this._currentPos = world;\n\n if (this.points.length === 0) return;\n this.preview.visible = true;\n this.preview.clear();\n\n this.preview.moveTo(this.points[0].x, this.points[0].y);\n for (let i = 1; i < this.points.length; i++) {\n this.preview.lineTo(this.points[i].x, this.points[i].y);\n }\n this.preview.lineTo(world.x, world.y);\n this.preview.stroke({ color: 0x374151, width: 2, alpha: 0.5 });\n };\n\n private _finishLine(): void {\n const markerEnd: FlowEdgeMarkerKind = this._mode === 'arrow' ? 'arrowclosed' : 'none';\n const lineType: FlowLineType = this._mode === 'arrow' ? 'arrow' : this._mode;\n\n const line: FlowLine = {\n id: generateId('line'),\n type: lineType,\n points: [...this.points],\n strokeColor: '#374151',\n strokeWidth: 2,\n lineStyle: 'solid',\n markerEnd,\n };\n\n this.callbacks.onLineComplete(line);\n this.points = [];\n this.preview.clear();\n this.preview.visible = false;\n }\n\n destroy(): void {\n this.deactivate();\n if (!this.preview.destroyed) this.preview.destroy();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"GeometricLineTool.js","names":[],"sources":["../../../../../src/components/pro/Flow/lines/GeometricLineTool.ts"],"sourcesContent":["import { Graphics, Container, FederatedPointerEvent } from 'pixi.js';\nimport type { FlowLine, FlowLineType, FlowEdgeMarkerKind } from '../types';\nimport { generateId } from '../nodes/nodeUtils';\nimport { resolveThemeColor } from '../utils/themeColor';\n\nfunction previewStrokeColor(): string {\n return resolveThemeColor('theme:base-content', '#374151');\n}\n\nexport interface GeometricLineToolCallbacks {\n onLineComplete: (line: FlowLine) => void;\n screenToWorld: (sx: number, sy: number) => { x: number; y: number };\n}\n\ntype GeoMode = 'straight' | 'polyline' | 'arrow';\n\n/**\n * Click-to-place geometric lines: straight, polyline, and arrow.\n * - straight/arrow: click start, click end\n * - polyline: click each point, double-click to finish\n */\nexport class GeometricLineTool {\n private stage: Container;\n private preview: Graphics;\n private callbacks: GeometricLineToolCallbacks;\n private points: Array<{ x: number; y: number }> = [];\n private _active = false;\n private _mode: GeoMode = 'straight';\n private _currentPos = { x: 0, y: 0 };\n private _lastClickTime = 0;\n private _lastClickPos = { x: 0, y: 0 };\n\n constructor(stage: Container, world: Container, callbacks: GeometricLineToolCallbacks) {\n this.stage = stage;\n this.callbacks = callbacks;\n this.preview = new Graphics();\n this.preview.label = 'geo-line-preview';\n this.preview.visible = false;\n world.addChild(this.preview);\n this._handleKeyDown = this._handleKeyDown.bind(this);\n }\n\n get active(): boolean { return this._active; }\n get mode(): GeoMode { return this._mode; }\n set mode(m: GeoMode) { this._mode = m; }\n\n activate(mode: GeoMode = 'straight'): void {\n this._active = true;\n this._mode = mode;\n this.points = [];\n this._lastClickTime = 0;\n this.stage.on('pointerdown', this._onClick, this);\n this.stage.on('globalpointermove', this._onMove, this);\n window.addEventListener('keydown', this._handleKeyDown);\n }\n\n deactivate(): void {\n this._active = false;\n this.points = [];\n if (!this.preview.destroyed) {\n this.preview.clear();\n this.preview.visible = false;\n }\n this.stage.off('pointerdown', this._onClick, this);\n this.stage.off('globalpointermove', this._onMove, this);\n window.removeEventListener('keydown', this._handleKeyDown);\n }\n\n private _handleKeyDown(e: KeyboardEvent): void {\n if (e.key === 'Enter' || e.key === 'Return') {\n if (this._mode === 'polyline' && this.points.length >= 2) {\n this._finishLine();\n }\n }\n }\n\n private _onClick = (e: FederatedPointerEvent): void => {\n if (e.button !== 0) return;\n const world = this.callbacks.screenToWorld(e.global.x, e.global.y);\n\n const now = Date.now();\n const isDbl = now - this._lastClickTime < 350\n && Math.hypot(world.x - this._lastClickPos.x, world.y - this._lastClickPos.y) < 10;\n this._lastClickTime = now;\n this._lastClickPos = world;\n\n if (isDbl && this._mode === 'polyline' && this.points.length >= 2) {\n this._finishLine();\n return;\n }\n\n this.points.push(world);\n if ((this._mode === 'straight' || this._mode === 'arrow') && this.points.length >= 2) {\n this._finishLine();\n }\n };\n\n private _onMove = (e: FederatedPointerEvent): void => {\n const world = this.callbacks.screenToWorld(e.global.x, e.global.y);\n this._currentPos = world;\n\n if (this.points.length === 0) return;\n this.preview.visible = true;\n this.preview.clear();\n\n this.preview.moveTo(this.points[0].x, this.points[0].y);\n for (let i = 1; i < this.points.length; i++) {\n this.preview.lineTo(this.points[i].x, this.points[i].y);\n }\n this.preview.lineTo(world.x, world.y);\n this.preview.stroke({ color: previewStrokeColor(), width: 2, alpha: 0.5 });\n };\n\n private _finishLine(): void {\n const markerEnd: FlowEdgeMarkerKind = this._mode === 'arrow' ? 'arrowclosed' : 'none';\n const lineType: FlowLineType = this._mode === 'arrow' ? 'arrow' : this._mode;\n\n const line: FlowLine = {\n id: generateId('line'),\n type: lineType,\n points: [...this.points],\n strokeColor: 'theme:base-content',\n strokeWidth: 2,\n lineStyle: 'solid',\n markerEnd,\n };\n\n this.callbacks.onLineComplete(line);\n this.points = [];\n this.preview.clear();\n this.preview.visible = false;\n }\n\n destroy(): void {\n this.deactivate();\n if (!this.preview.destroyed) this.preview.destroy();\n }\n}\n"],"mappings":"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"}
@@ -1,14 +1,15 @@
1
+ import { resolveThemeColor as x } from "../utils/themeColor.js";
1
2
  import { angleBetween as h, drawMarker as f } from "../edges/edgeMarkers.js";
2
- import { drawDashedPolyline as x } from "../utils/dashedLine.js";
3
+ import { drawDashedPolyline as g } from "../utils/dashedLine.js";
3
4
  import { Container as y, Graphics as m } from "pixi.js";
4
- function g(n, e = 2) {
5
+ function u(n, e = 2) {
5
6
  if (!(!n || n === "solid")) {
6
7
  if (n === "dynamic") return [e * 4, e * 3];
7
8
  if (n === "dotted") return [e, e * 2];
8
9
  if (n === "dashed") return [e * 3, e * 2];
9
10
  }
10
11
  }
11
- var v = class {
12
+ var L = class {
12
13
  world;
13
14
  lineLayer;
14
15
  lines = /* @__PURE__ */ new Map();
@@ -23,36 +24,36 @@ var v = class {
23
24
  }), this.world.addChildAt(this.lineLayer, Math.min(1, this.world.children.length));
24
25
  }
25
26
  sync(n, e) {
26
- const a = /* @__PURE__ */ new Set();
27
+ const s = /* @__PURE__ */ new Set();
27
28
  for (const r of n) {
28
- a.add(r.id);
29
+ s.add(r.id);
29
30
  let o = this.lines.get(r.id);
30
31
  o || (o = this._create(r), this.lines.set(r.id, o)), this._update(o, r, e.has(r.id));
31
32
  }
32
- for (const [r, o] of this.lines) a.has(r) || (this.lineLayer.removeChild(o.container), o.container.destroy({ children: !0 }), this.lines.delete(r));
33
+ for (const [r, o] of this.lines) s.has(r) || (this.lineLayer.removeChild(o.container), o.container.destroy({ children: !0 }), this.lines.delete(r));
33
34
  }
34
35
  _create(n) {
35
- const e = new y({ label: `line-${n.id}` }), a = new m();
36
- a.label = "line-hitarea", a.eventMode = "static", a.cursor = "pointer", a.alpha = 1e-3, e.addChild(a);
36
+ const e = new y({ label: `line-${n.id}` }), s = new m();
37
+ s.label = "line-hitarea", s.eventMode = "static", s.cursor = "pointer", s.alpha = 1e-3, e.addChild(s);
37
38
  const r = new m();
38
39
  return r.label = "line-gfx", e.addChild(r), this.lineLayer.addChild(e), {
39
40
  container: e,
40
41
  gfx: r,
41
- hitArea: a,
42
+ hitArea: s,
42
43
  lineId: n.id
43
44
  };
44
45
  }
45
- _update(n, e, a) {
46
+ _update(n, e, s) {
46
47
  n.container.zIndex = e.zIndex ?? 0;
47
48
  const { gfx: r, hitArea: o } = n, t = e.points;
48
49
  if (t.length < 2) return;
49
- const s = a ? "#3b82f6" : e.strokeColor, d = e.strokeWidth;
50
+ const a = s ? "#3b82f6" : x(e.strokeColor, "#374151"), d = e.strokeWidth;
50
51
  r.clear();
51
- const l = g(e.lineStyle, d);
52
+ const l = u(e.lineStyle, d);
52
53
  if (l) {
53
54
  const i = e.lineStyle === "dynamic" ? this._dynamicOffset : 0;
54
- x(r, e.closed ? [...t, t[0]] : t, l, i), r.stroke({
55
- color: s,
55
+ g(r, e.closed ? [...t, t[0]] : t, l, i), r.stroke({
56
+ color: a,
56
57
  width: d,
57
58
  cap: "round"
58
59
  });
@@ -60,17 +61,17 @@ var v = class {
60
61
  r.moveTo(t[0].x, t[0].y);
61
62
  for (let i = 1; i < t.length; i++) r.lineTo(t[i].x, t[i].y);
62
63
  e.closed && r.closePath(), r.stroke({
63
- color: s,
64
+ color: a,
64
65
  width: d
65
66
  });
66
67
  }
67
68
  if (e.markerStart && e.markerStart !== "none" && t.length >= 2) {
68
69
  const i = h(t[1].x, t[1].y, t[0].x, t[0].y);
69
- f(r, e.markerStart, t[0].x, t[0].y, i, s);
70
+ f(r, e.markerStart, t[0].x, t[0].y, i, a);
70
71
  }
71
72
  if (e.markerEnd && e.markerEnd !== "none" && t.length >= 2) {
72
73
  const i = t[t.length - 1], c = t[t.length - 2], p = h(c.x, c.y, i.x, i.y);
73
- f(r, e.markerEnd, i.x, i.y, p, s);
74
+ f(r, e.markerEnd, i.x, i.y, p, a);
74
75
  }
75
76
  o.clear(), o.moveTo(t[0].x, t[0].y);
76
77
  for (let i = 1; i < t.length; i++) o.lineTo(t[i].x, t[i].y);
@@ -85,7 +86,7 @@ var v = class {
85
86
  }
86
87
  };
87
88
  export {
88
- v as LineRenderer
89
+ L as LineRenderer
89
90
  };
90
91
 
91
92
  //# sourceMappingURL=LineRenderer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"LineRenderer.js","names":[],"sources":["../../../../../src/components/pro/Flow/lines/LineRenderer.ts"],"sourcesContent":["import { Container, Graphics } from 'pixi.js';\nimport type { FlowLine } from '../types';\nimport { drawMarker, angleBetween } from '../edges/edgeMarkers';\nimport { drawDashedPolyline } from '../utils/dashedLine';\n\nfunction getLineDash(style?: string, width = 2): number[] | undefined {\n if (!style || style === 'solid') return undefined;\n if (style === 'dynamic') return [width * 4, width * 3];\n if (style === 'dotted') return [width, width * 2];\n if (style === 'dashed') return [width * 3, width * 2];\n return undefined;\n}\n\ninterface LineDisplay {\n container: Container;\n gfx: Graphics;\n hitArea: Graphics;\n lineId: string;\n}\n\n/**\n * Renders independent FlowLine[] objects on the canvas.\n */\nexport class LineRenderer {\n private world: Container;\n private lineLayer: Container;\n private lines = new Map<string, LineDisplay>();\n private _dynamicOffset = 0;\n\n /** Call once per frame to advance the dynamic dash animation. */\n advanceAnimation(deltaMs: number): void {\n this._dynamicOffset = (this._dynamicOffset + deltaMs * 0.06) % 1000;\n }\n\n constructor(world: Container) {\n this.world = world;\n this.lineLayer = new Container({ label: 'lines', sortableChildren: true });\n // Lines on top of edges but below nodes\n this.world.addChildAt(this.lineLayer, Math.min(1, this.world.children.length));\n }\n\n sync(flowLines: FlowLine[], selectedIds: Set<string>): void {\n const seen = new Set<string>();\n\n for (const line of flowLines) {\n seen.add(line.id);\n let display = this.lines.get(line.id);\n if (!display) {\n display = this._create(line);\n this.lines.set(line.id, display);\n }\n this._update(display, line, selectedIds.has(line.id));\n }\n\n for (const [id, display] of this.lines) {\n if (!seen.has(id)) {\n this.lineLayer.removeChild(display.container);\n display.container.destroy({ children: true });\n this.lines.delete(id);\n }\n }\n }\n\n private _create(line: FlowLine): LineDisplay {\n const container = new Container({ label: `line-${line.id}` });\n\n const hitArea = new Graphics();\n hitArea.label = 'line-hitarea';\n hitArea.eventMode = 'static';\n hitArea.cursor = 'pointer';\n hitArea.alpha = 0.001;\n container.addChild(hitArea);\n\n const gfx = new Graphics();\n gfx.label = 'line-gfx';\n container.addChild(gfx);\n\n this.lineLayer.addChild(container);\n return { container, gfx, hitArea, lineId: line.id };\n }\n\n private _update(display: LineDisplay, line: FlowLine, selected: boolean): void {\n display.container.zIndex = line.zIndex ?? 0;\n const { gfx, hitArea } = display;\n const pts = line.points;\n if (pts.length < 2) return;\n\n const color = selected ? '#3b82f6' : line.strokeColor;\n const width = line.strokeWidth;\n\n gfx.clear();\n const dash = getLineDash(line.lineStyle, width);\n if (dash) {\n const offset = line.lineStyle === 'dynamic' ? this._dynamicOffset : 0;\n const drawPts = line.closed ? [...pts, pts[0]] : pts;\n drawDashedPolyline(gfx, drawPts, dash, offset);\n gfx.stroke({ color, width, cap: 'round' as const });\n } else {\n gfx.moveTo(pts[0].x, pts[0].y);\n for (let i = 1; i < pts.length; i++) {\n gfx.lineTo(pts[i].x, pts[i].y);\n }\n if (line.closed) gfx.closePath();\n gfx.stroke({ color, width });\n }\n\n // Markers\n if (line.markerStart && line.markerStart !== 'none' && pts.length >= 2) {\n const angle = angleBetween(pts[1].x, pts[1].y, pts[0].x, pts[0].y);\n drawMarker(gfx, line.markerStart, pts[0].x, pts[0].y, angle, color);\n }\n if (line.markerEnd && line.markerEnd !== 'none' && pts.length >= 2) {\n const last = pts[pts.length - 1];\n const prev = pts[pts.length - 2];\n const angle = angleBetween(prev.x, prev.y, last.x, last.y);\n drawMarker(gfx, line.markerEnd, last.x, last.y, angle, color);\n }\n\n // Hit area\n hitArea.clear();\n hitArea.moveTo(pts[0].x, pts[0].y);\n for (let i = 1; i < pts.length; i++) {\n hitArea.lineTo(pts[i].x, pts[i].y);\n }\n hitArea.stroke({ color: '#000000', width: Math.max(width + 10, 14) });\n hitArea.alpha = 0.001;\n }\n\n destroy(): void {\n for (const [, display] of this.lines) {\n display.container.destroy({ children: true });\n }\n this.lines.clear();\n this.lineLayer.destroy({ children: true });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"LineRenderer.js","names":[],"sources":["../../../../../src/components/pro/Flow/lines/LineRenderer.ts"],"sourcesContent":["import { Container, Graphics } from 'pixi.js';\nimport type { FlowLine } from '../types';\nimport { drawMarker, angleBetween } from '../edges/edgeMarkers';\nimport { drawDashedPolyline } from '../utils/dashedLine';\nimport { resolveThemeColor } from '../utils/themeColor';\n\nfunction getLineDash(style?: string, width = 2): number[] | undefined {\n if (!style || style === 'solid') return undefined;\n if (style === 'dynamic') return [width * 4, width * 3];\n if (style === 'dotted') return [width, width * 2];\n if (style === 'dashed') return [width * 3, width * 2];\n return undefined;\n}\n\ninterface LineDisplay {\n container: Container;\n gfx: Graphics;\n hitArea: Graphics;\n lineId: string;\n}\n\n/**\n * Renders independent FlowLine[] objects on the canvas.\n */\nexport class LineRenderer {\n private world: Container;\n private lineLayer: Container;\n private lines = new Map<string, LineDisplay>();\n private _dynamicOffset = 0;\n\n /** Call once per frame to advance the dynamic dash animation. */\n advanceAnimation(deltaMs: number): void {\n this._dynamicOffset = (this._dynamicOffset + deltaMs * 0.06) % 1000;\n }\n\n constructor(world: Container) {\n this.world = world;\n this.lineLayer = new Container({ label: 'lines', sortableChildren: true });\n // Lines on top of edges but below nodes\n this.world.addChildAt(this.lineLayer, Math.min(1, this.world.children.length));\n }\n\n sync(flowLines: FlowLine[], selectedIds: Set<string>): void {\n const seen = new Set<string>();\n\n for (const line of flowLines) {\n seen.add(line.id);\n let display = this.lines.get(line.id);\n if (!display) {\n display = this._create(line);\n this.lines.set(line.id, display);\n }\n this._update(display, line, selectedIds.has(line.id));\n }\n\n for (const [id, display] of this.lines) {\n if (!seen.has(id)) {\n this.lineLayer.removeChild(display.container);\n display.container.destroy({ children: true });\n this.lines.delete(id);\n }\n }\n }\n\n private _create(line: FlowLine): LineDisplay {\n const container = new Container({ label: `line-${line.id}` });\n\n const hitArea = new Graphics();\n hitArea.label = 'line-hitarea';\n hitArea.eventMode = 'static';\n hitArea.cursor = 'pointer';\n hitArea.alpha = 0.001;\n container.addChild(hitArea);\n\n const gfx = new Graphics();\n gfx.label = 'line-gfx';\n container.addChild(gfx);\n\n this.lineLayer.addChild(container);\n return { container, gfx, hitArea, lineId: line.id };\n }\n\n private _update(display: LineDisplay, line: FlowLine, selected: boolean): void {\n display.container.zIndex = line.zIndex ?? 0;\n const { gfx, hitArea } = display;\n const pts = line.points;\n if (pts.length < 2) return;\n\n const color = selected ? '#3b82f6' : resolveThemeColor(line.strokeColor, '#374151');\n const width = line.strokeWidth;\n\n gfx.clear();\n const dash = getLineDash(line.lineStyle, width);\n if (dash) {\n const offset = line.lineStyle === 'dynamic' ? this._dynamicOffset : 0;\n const drawPts = line.closed ? [...pts, pts[0]] : pts;\n drawDashedPolyline(gfx, drawPts, dash, offset);\n gfx.stroke({ color, width, cap: 'round' as const });\n } else {\n gfx.moveTo(pts[0].x, pts[0].y);\n for (let i = 1; i < pts.length; i++) {\n gfx.lineTo(pts[i].x, pts[i].y);\n }\n if (line.closed) gfx.closePath();\n gfx.stroke({ color, width });\n }\n\n // Markers\n if (line.markerStart && line.markerStart !== 'none' && pts.length >= 2) {\n const angle = angleBetween(pts[1].x, pts[1].y, pts[0].x, pts[0].y);\n drawMarker(gfx, line.markerStart, pts[0].x, pts[0].y, angle, color);\n }\n if (line.markerEnd && line.markerEnd !== 'none' && pts.length >= 2) {\n const last = pts[pts.length - 1];\n const prev = pts[pts.length - 2];\n const angle = angleBetween(prev.x, prev.y, last.x, last.y);\n drawMarker(gfx, line.markerEnd, last.x, last.y, angle, color);\n }\n\n // Hit area\n hitArea.clear();\n hitArea.moveTo(pts[0].x, pts[0].y);\n for (let i = 1; i < pts.length; i++) {\n hitArea.lineTo(pts[i].x, pts[i].y);\n }\n hitArea.stroke({ color: '#000000', width: Math.max(width + 10, 14) });\n hitArea.alpha = 0.001;\n }\n\n destroy(): void {\n for (const [, display] of this.lines) {\n display.container.destroy({ children: true });\n }\n this.lines.clear();\n this.lineLayer.destroy({ children: true });\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import type { FlowDataConfig } from '../types';
3
+ /** Dispatches to the table or chart surface based on the node's view. */
4
+ export declare function DataNodeView({ config }: {
5
+ config: FlowDataConfig;
6
+ }): React.JSX.Element;
7
+ export default DataNodeView;