dishui 0.0.47 → 0.0.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js +1 -2
- package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js.map +1 -1
- package/dist/components/pro/CodeEditor/themes.js +0 -25
- package/dist/components/pro/CodeEditor/themes.js.map +1 -1
- package/dist/components/pro/CodeEditor/types.d.ts +1 -1
- package/dist/components/pro/Flow/Flow.js +500 -483
- package/dist/components/pro/Flow/Flow.js.map +1 -1
- package/dist/components/pro/Flow/FlowCanvas.js +526 -524
- package/dist/components/pro/Flow/FlowCanvas.js.map +1 -1
- package/dist/components/pro/Flow/canvas/GridRenderer.d.ts +3 -0
- package/dist/components/pro/Flow/canvas/GridRenderer.js +28 -23
- package/dist/components/pro/Flow/canvas/GridRenderer.js.map +1 -1
- package/dist/components/pro/Flow/canvas/MiniMapRenderer.js +18 -17
- package/dist/components/pro/Flow/canvas/MiniMapRenderer.js.map +1 -1
- package/dist/components/pro/Flow/canvas/PixiApp.d.ts +2 -0
- package/dist/components/pro/Flow/canvas/PixiApp.js +14 -11
- package/dist/components/pro/Flow/canvas/PixiApp.js.map +1 -1
- package/dist/components/pro/Flow/constants.js +7 -7
- package/dist/components/pro/Flow/constants.js.map +1 -1
- package/dist/components/pro/Flow/context/FlowAIContext.d.ts +15 -0
- package/dist/components/pro/Flow/context/FlowAIContext.js +32 -0
- package/dist/components/pro/Flow/context/FlowAIContext.js.map +1 -0
- package/dist/components/pro/Flow/context/FlowUIContext.d.ts +4 -1
- package/dist/components/pro/Flow/context/FlowUIContext.js +58 -55
- package/dist/components/pro/Flow/context/FlowUIContext.js.map +1 -1
- package/dist/components/pro/Flow/edges/EdgeRenderer.js +22 -21
- package/dist/components/pro/Flow/edges/EdgeRenderer.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useFlowImportExport.js +32 -32
- package/dist/components/pro/Flow/hooks/useFlowImportExport.js.map +1 -1
- package/dist/components/pro/Flow/hooks/usePixiApp.d.ts +6 -1
- package/dist/components/pro/Flow/hooks/usePixiApp.js +49 -30
- package/dist/components/pro/Flow/hooks/usePixiApp.js.map +1 -1
- package/dist/components/pro/Flow/index.d.ts +2 -0
- package/dist/components/pro/Flow/lines/FreehandTool.js +21 -20
- package/dist/components/pro/Flow/lines/FreehandTool.js.map +1 -1
- package/dist/components/pro/Flow/lines/GeometricLineTool.js +22 -18
- package/dist/components/pro/Flow/lines/GeometricLineTool.js.map +1 -1
- package/dist/components/pro/Flow/lines/LineRenderer.js +19 -18
- package/dist/components/pro/Flow/lines/LineRenderer.js.map +1 -1
- package/dist/components/pro/Flow/nodes/MediaContent.js +143 -124
- package/dist/components/pro/Flow/nodes/MediaContent.js.map +1 -1
- package/dist/components/pro/Flow/nodes/MediaOverlay.js +22 -17
- package/dist/components/pro/Flow/nodes/MediaOverlay.js.map +1 -1
- package/dist/components/pro/Flow/nodes/NodeRenderer.js +77 -76
- package/dist/components/pro/Flow/nodes/NodeRenderer.js.map +1 -1
- package/dist/components/pro/Flow/nodes/aiClient.d.ts +22 -0
- package/dist/components/pro/Flow/nodes/aiClient.js +107 -54
- package/dist/components/pro/Flow/nodes/aiClient.js.map +1 -1
- package/dist/components/pro/Flow/nodes/svgIcons.js +6 -6
- package/dist/components/pro/Flow/nodes/svgIcons.js.map +1 -1
- package/dist/components/pro/Flow/panels/AIPanel.d.ts +2 -0
- package/dist/components/pro/Flow/panels/AIPanel.js +498 -0
- package/dist/components/pro/Flow/panels/AIPanel.js.map +1 -0
- package/dist/components/pro/Flow/panels/FlowPanelGroup.js +51 -39
- package/dist/components/pro/Flow/panels/FlowPanelGroup.js.map +1 -1
- package/dist/components/pro/Flow/panels/FlowToolbar.js +91 -85
- package/dist/components/pro/Flow/panels/FlowToolbar.js.map +1 -1
- package/dist/components/pro/Flow/panels/InspectorPanel.js +372 -332
- package/dist/components/pro/Flow/panels/InspectorPanel.js.map +1 -1
- package/dist/components/pro/Flow/panels/OutlinePanel.js +28 -27
- package/dist/components/pro/Flow/panels/OutlinePanel.js.map +1 -1
- package/dist/components/pro/Flow/panels/ShapePalette.js +107 -104
- package/dist/components/pro/Flow/panels/ShapePalette.js.map +1 -1
- package/dist/components/pro/Flow/panels/toolbarIcons.d.ts +1 -0
- package/dist/components/pro/Flow/panels/toolbarIcons.js +25 -20
- package/dist/components/pro/Flow/panels/toolbarIcons.js.map +1 -1
- package/dist/components/pro/Flow/types.d.ts +13 -0
- package/dist/components/pro/Flow/types.js.map +1 -1
- package/dist/components/pro/Flow/utils/themeColor.d.ts +87 -0
- package/dist/components/pro/Flow/utils/themeColor.js +212 -0
- package/dist/components/pro/Flow/utils/themeColor.js.map +1 -0
- package/dist/contexts/AppContext.d.ts +1 -1
- package/dist/contexts/AppContext.js +28 -29
- package/dist/contexts/AppContext.js.map +1 -1
- package/dist/dishui.css +1 -1
- package/dist/favicon.svg +10 -0
- package/dist/flow.js +56 -51
- package/dist/styles/themeStyles.js +6 -11
- package/dist/styles/themeStyles.js.map +1 -1
- package/dist/utils/themes.js +3 -23
- package/dist/utils/themes.js.map +1 -1
- package/package.json +17 -18
|
@@ -7,10 +7,13 @@ export declare class GridRenderer {
|
|
|
7
7
|
private gfx;
|
|
8
8
|
private _gridSize;
|
|
9
9
|
private _visible;
|
|
10
|
+
private _dotColor;
|
|
10
11
|
private _last;
|
|
11
12
|
constructor(parent: Container, gridSize?: number, visible?: boolean);
|
|
12
13
|
set visible(v: boolean);
|
|
13
14
|
set gridSize(s: number);
|
|
15
|
+
/** Grid dot color, derived from the active theme's foreground. */
|
|
16
|
+
set dotColor(c: number);
|
|
14
17
|
update(viewport: ViewportState, screenW: number, screenH: number): void;
|
|
15
18
|
destroy(): void;
|
|
16
19
|
}
|
|
@@ -3,9 +3,10 @@ var b = class {
|
|
|
3
3
|
gfx;
|
|
4
4
|
_gridSize;
|
|
5
5
|
_visible;
|
|
6
|
+
_dotColor = 13751771;
|
|
6
7
|
_last = null;
|
|
7
|
-
constructor(t,
|
|
8
|
-
this._gridSize =
|
|
8
|
+
constructor(t, s = 20, l = !0) {
|
|
9
|
+
this._gridSize = s, this._visible = l, this.gfx = new v(), this.gfx.label = "grid", t.addChildAt(this.gfx, 0);
|
|
9
10
|
}
|
|
10
11
|
set visible(t) {
|
|
11
12
|
this._visible = t, this.gfx.visible = t;
|
|
@@ -13,34 +14,38 @@ var b = class {
|
|
|
13
14
|
set gridSize(t) {
|
|
14
15
|
this._gridSize = Math.max(5, t);
|
|
15
16
|
}
|
|
16
|
-
|
|
17
|
+
set dotColor(t) {
|
|
18
|
+
this._dotColor = t;
|
|
19
|
+
}
|
|
20
|
+
update(t, s, l) {
|
|
17
21
|
if (!this._visible) return;
|
|
18
|
-
const { x:
|
|
19
|
-
if (
|
|
22
|
+
const { x: e, y: d, zoom: r } = t, i = this._last;
|
|
23
|
+
if (i && i.ox === e && i.oy === d && i.zoom === r && i.w === s && i.h === l && i.grid === this._gridSize && i.vis === this._visible && i.color === this._dotColor) return;
|
|
20
24
|
this._last = {
|
|
21
|
-
ox:
|
|
22
|
-
oy:
|
|
25
|
+
ox: e,
|
|
26
|
+
oy: d,
|
|
23
27
|
zoom: r,
|
|
24
|
-
w:
|
|
25
|
-
h:
|
|
28
|
+
w: s,
|
|
29
|
+
h: l,
|
|
26
30
|
grid: this._gridSize,
|
|
27
|
-
vis: this._visible
|
|
31
|
+
vis: this._visible,
|
|
32
|
+
color: this._dotColor
|
|
28
33
|
};
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
let
|
|
33
|
-
if (
|
|
34
|
-
let
|
|
35
|
-
for (;
|
|
36
|
-
if (
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
color:
|
|
34
|
+
const h = this.gfx;
|
|
35
|
+
h.clear();
|
|
36
|
+
const c = 12;
|
|
37
|
+
let o = this._gridSize * r;
|
|
38
|
+
if (o <= 0) return;
|
|
39
|
+
let a = 1;
|
|
40
|
+
for (; o * a < c; ) a *= 2;
|
|
41
|
+
if (o *= a, (Math.ceil(s / o) + 1) * (Math.ceil(l / o) + 1) > 6e3) return;
|
|
42
|
+
const f = Math.max(0.8, Math.min(1.6, r * 0.8)), x = this._dotColor, n = Math.min(0.6, Math.max(0.2, r * 0.4)), m = e % o, u = d % o;
|
|
43
|
+
h.setFillStyle({
|
|
44
|
+
color: x,
|
|
40
45
|
alpha: n
|
|
41
46
|
});
|
|
42
|
-
for (let
|
|
43
|
-
|
|
47
|
+
for (let _ = m; _ < s; _ += o) for (let g = u; g < l; g += o) h.circle(_, g, f);
|
|
48
|
+
h.fill();
|
|
44
49
|
}
|
|
45
50
|
destroy() {
|
|
46
51
|
this.gfx.destroy();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GridRenderer.js","names":[],"sources":["../../../../../src/components/pro/Flow/canvas/GridRenderer.ts"],"sourcesContent":["import { Graphics, Container } from 'pixi.js';\nimport type { ViewportState } from '../types';\n\n/**\n * Renders a dot grid on the canvas that adjusts to viewport pan/zoom.\n */\nexport class GridRenderer {\n private gfx: Graphics;\n private _gridSize: number;\n private _visible: boolean;\n // Cache of the last render inputs so we can skip redrawing when nothing\n // changed. Redrawing thousands of dots every frame (60fps) is the main\n // source of low-zoom jitter/stutter.\n private _last: { ox: number; oy: number; zoom: number; w: number; h: number; grid: number; vis: boolean } | null = null;\n\n constructor(parent: Container, gridSize = 20, visible = true) {\n this._gridSize = gridSize;\n this._visible = visible;\n this.gfx = new Graphics();\n this.gfx.label = 'grid';\n parent.addChildAt(this.gfx, 0);\n }\n\n set visible(v: boolean) {\n this._visible = v;\n this.gfx.visible = v;\n }\n\n set gridSize(s: number) {\n this._gridSize = Math.max(5, s);\n }\n\n update(viewport: ViewportState, screenW: number, screenH: number): void {\n if (!this._visible) return;\n\n const { x: ox, y: oy, zoom } = viewport;\n\n // Skip the redraw entirely if nothing that affects the grid changed.\n const last = this._last;\n if (\n last &&\n last.ox === ox && last.oy === oy && last.zoom === zoom &&\n last.w === screenW && last.h === screenH &&\n last.grid === this._gridSize && last.vis === this._visible\n ) {\n return;\n }\n this._last = { ox, oy, zoom, w: screenW, h: screenH, grid: this._gridSize, vis: this._visible };\n\n const g = this.gfx;\n g.clear();\n\n // Adaptive spacing: multiply the base grid step by a power of two until the\n // on-screen spacing is comfortably large. Without this, low zoom levels\n // (e.g. 25%–45%) produce tens of thousands of dots per frame.\n const MIN_SCREEN_STEP = 12;\n let step = this._gridSize * zoom;\n if (step <= 0) return;\n let mul = 1;\n while (step * mul < MIN_SCREEN_STEP) {\n mul *= 2;\n }\n step *= mul;\n\n // Hard cap on total dot count as a final safety net.\n const MAX_DOTS = 6000;\n const cols = Math.ceil(screenW / step) + 1;\n const rows = Math.ceil(screenH / step) + 1;\n if (cols * rows > MAX_DOTS) return;\n\n const dotRadius = Math.max(0.8, Math.min(1.6, zoom * 0.8));\n const dotColor =
|
|
1
|
+
{"version":3,"file":"GridRenderer.js","names":[],"sources":["../../../../../src/components/pro/Flow/canvas/GridRenderer.ts"],"sourcesContent":["import { Graphics, Container } from 'pixi.js';\nimport type { ViewportState } from '../types';\n\n/**\n * Renders a dot grid on the canvas that adjusts to viewport pan/zoom.\n */\nexport class GridRenderer {\n private gfx: Graphics;\n private _gridSize: number;\n private _visible: boolean;\n private _dotColor = 0xd1d5db;\n // Cache of the last render inputs so we can skip redrawing when nothing\n // changed. Redrawing thousands of dots every frame (60fps) is the main\n // source of low-zoom jitter/stutter.\n private _last: { ox: number; oy: number; zoom: number; w: number; h: number; grid: number; vis: boolean; color: number } | null = null;\n\n constructor(parent: Container, gridSize = 20, visible = true) {\n this._gridSize = gridSize;\n this._visible = visible;\n this.gfx = new Graphics();\n this.gfx.label = 'grid';\n parent.addChildAt(this.gfx, 0);\n }\n\n set visible(v: boolean) {\n this._visible = v;\n this.gfx.visible = v;\n }\n\n set gridSize(s: number) {\n this._gridSize = Math.max(5, s);\n }\n\n /** Grid dot color, derived from the active theme's foreground. */\n set dotColor(c: number) {\n this._dotColor = c;\n }\n\n update(viewport: ViewportState, screenW: number, screenH: number): void {\n if (!this._visible) return;\n\n const { x: ox, y: oy, zoom } = viewport;\n\n // Skip the redraw entirely if nothing that affects the grid changed.\n const last = this._last;\n if (\n last &&\n last.ox === ox && last.oy === oy && last.zoom === zoom &&\n last.w === screenW && last.h === screenH &&\n last.grid === this._gridSize && last.vis === this._visible &&\n last.color === this._dotColor\n ) {\n return;\n }\n this._last = { ox, oy, zoom, w: screenW, h: screenH, grid: this._gridSize, vis: this._visible, color: this._dotColor };\n\n const g = this.gfx;\n g.clear();\n\n // Adaptive spacing: multiply the base grid step by a power of two until the\n // on-screen spacing is comfortably large. Without this, low zoom levels\n // (e.g. 25%–45%) produce tens of thousands of dots per frame.\n const MIN_SCREEN_STEP = 12;\n let step = this._gridSize * zoom;\n if (step <= 0) return;\n let mul = 1;\n while (step * mul < MIN_SCREEN_STEP) {\n mul *= 2;\n }\n step *= mul;\n\n // Hard cap on total dot count as a final safety net.\n const MAX_DOTS = 6000;\n const cols = Math.ceil(screenW / step) + 1;\n const rows = Math.ceil(screenH / step) + 1;\n if (cols * rows > MAX_DOTS) return;\n\n const dotRadius = Math.max(0.8, Math.min(1.6, zoom * 0.8));\n const dotColor = this._dotColor;\n const dotAlpha = Math.min(0.6, Math.max(0.2, zoom * 0.4));\n\n const startX = ox % step;\n const startY = oy % step;\n\n g.setFillStyle({ color: dotColor, alpha: dotAlpha });\n for (let x = startX; x < screenW; x += step) {\n for (let y = startY; y < screenH; y += step) {\n g.circle(x, y, dotRadius);\n }\n }\n g.fill();\n }\n\n destroy(): void {\n this.gfx.destroy();\n }\n}\n"],"mappings":";AAMA,IAAa,IAAb,MAA0B;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAoB;AAAA,EAIpB,QAAkI;AAAA,EAElI,YAAY,GAAmB,IAAW,IAAI,IAAU,IAAM;AAC5D,SAAK,YAAY,GACjB,KAAK,WAAW,GAChB,KAAK,MAAM,IAAI,EAAS,GACxB,KAAK,IAAI,QAAQ,QACjB,EAAO,WAAW,KAAK,KAAK,CAAC;AAAA,EAC/B;AAAA,EAEA,IAAI,QAAQ,GAAY;AACtB,SAAK,WAAW,GAChB,KAAK,IAAI,UAAU;AAAA,EACrB;AAAA,EAEA,IAAI,SAAS,GAAW;AACtB,SAAK,YAAY,KAAK,IAAI,GAAG,CAAC;AAAA,EAChC;AAAA,EAGA,IAAI,SAAS,GAAW;AACtB,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,OAAO,GAAyB,GAAiB,GAAuB;AACtE,QAAI,CAAC,KAAK,SAAU;AAEpB,UAAM,EAAE,GAAG,GAAI,GAAG,GAAI,MAAA,EAAA,IAAS,GAGzB,IAAO,KAAK;AAClB,QACE,KACA,EAAK,OAAO,KAAM,EAAK,OAAO,KAAM,EAAK,SAAS,KAClD,EAAK,MAAM,KAAW,EAAK,MAAM,KACjC,EAAK,SAAS,KAAK,aAAa,EAAK,QAAQ,KAAK,YAClD,EAAK,UAAU,KAAK,UAEpB;AAEF,SAAK,QAAQ;AAAA,MAAE,IAAA;AAAA,MAAI,IAAA;AAAA,MAAI,MAAA;AAAA,MAAM,GAAG;AAAA,MAAS,GAAG;AAAA,MAAS,MAAM,KAAK;AAAA,MAAW,KAAK,KAAK;AAAA,MAAU,OAAO,KAAK;AAAA,IAAU;AAErH,UAAM,IAAI,KAAK;AACf,IAAA,EAAE,MAAM;AAKR,UAAM,IAAkB;AACxB,QAAI,IAAO,KAAK,YAAY;AAC5B,QAAI,KAAQ,EAAG;AACf,QAAI,IAAM;AACV,WAAO,IAAO,IAAM,IAClB,CAAA,KAAO;AAQT,QANA,KAAQ,IAIK,KAAK,KAAK,IAAU,CAAI,IAAI,MAC5B,KAAK,KAAK,IAAU,CAAI,IAAI,KACvB,IAAU;AAE5B,UAAM,IAAY,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,IAAO,GAAG,CAAC,GACnD,IAAW,KAAK,WAChB,IAAW,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,IAAO,GAAG,CAAC,GAElD,IAAS,IAAK,GACd,IAAS,IAAK;AAEpB,IAAA,EAAE,aAAa;AAAA,MAAE,OAAO;AAAA,MAAU,OAAO;AAAA,IAAS,CAAC;AACnD,aAAS,IAAI,GAAQ,IAAI,GAAS,KAAK,EACrC,UAAS,IAAI,GAAQ,IAAI,GAAS,KAAK,EACrC,CAAA,EAAE,OAAO,GAAG,GAAG,CAAS;AAG5B,IAAA,EAAE,KAAK;AAAA,EACT;AAAA,EAEA,UAAgB;AACd,SAAK,IAAI,QAAQ;AAAA,EACnB;AACF"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { resolveThemeColor as X } from "../utils/themeColor.js";
|
|
2
|
+
var S = class {
|
|
2
3
|
canvas;
|
|
3
4
|
ctx;
|
|
4
5
|
_visible = !0;
|
|
@@ -9,11 +10,11 @@ var Y = class {
|
|
|
9
10
|
set visible(i) {
|
|
10
11
|
this._visible = i, this.canvas.style.display = i ? "block" : "none";
|
|
11
12
|
}
|
|
12
|
-
minimapToWorld(i,
|
|
13
|
+
minimapToWorld(i, c) {
|
|
13
14
|
const n = this._transform;
|
|
14
15
|
return n ? {
|
|
15
16
|
x: (i - n.ox) / n.scale + n.wMinX,
|
|
16
|
-
y: (
|
|
17
|
+
y: (c - n.oy) / n.scale + n.wMinY
|
|
17
18
|
} : null;
|
|
18
19
|
}
|
|
19
20
|
get size() {
|
|
@@ -22,39 +23,39 @@ var Y = class {
|
|
|
22
23
|
height: this.canvas.height
|
|
23
24
|
};
|
|
24
25
|
}
|
|
25
|
-
update(i,
|
|
26
|
+
update(i, c, n, Y) {
|
|
26
27
|
if (!this._visible || i.length === 0) {
|
|
27
28
|
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
28
29
|
return;
|
|
29
30
|
}
|
|
30
|
-
const
|
|
31
|
-
this.ctx.clearRect(0, 0,
|
|
32
|
-
const m = -
|
|
33
|
-
let a = 1 / 0,
|
|
31
|
+
const r = this.canvas.width, x = this.canvas.height;
|
|
32
|
+
this.ctx.clearRect(0, 0, r, x);
|
|
33
|
+
const m = -c.x / c.zoom, f = -c.y / c.zoom, d = n / c.zoom, v = Y / c.zoom;
|
|
34
|
+
let a = 1 / 0, o = 1 / 0, h = -1 / 0, e = -1 / 0;
|
|
34
35
|
for (const t of i)
|
|
35
|
-
a = Math.min(a, t.position.x),
|
|
36
|
+
a = Math.min(a, t.position.x), o = Math.min(o, t.position.y), h = Math.max(h, t.position.x + t.width), e = Math.max(e, t.position.y + t.height);
|
|
36
37
|
const l = 50;
|
|
37
|
-
a -= l,
|
|
38
|
-
const
|
|
38
|
+
a -= l, o -= l, h += l, e += l, a = Math.min(a, m), o = Math.min(o, f), h = Math.max(h, m + d), e = Math.max(e, f + v);
|
|
39
|
+
const w = h - a, p = e - o, s = Math.min(r / w, x / p), M = (r - w * s) / 2, y = (x - p * s) / 2;
|
|
39
40
|
this._transform = {
|
|
40
41
|
scale: s,
|
|
41
42
|
ox: M,
|
|
42
43
|
oy: y,
|
|
43
44
|
wMinX: a,
|
|
44
|
-
wMinY:
|
|
45
|
+
wMinY: o
|
|
45
46
|
};
|
|
46
47
|
for (const t of i) {
|
|
47
|
-
const R = M + (t.position.x - a) * s, _ = y + (t.position.y -
|
|
48
|
-
this.ctx.fillStyle = t.data.fill === "transparent" ? "#e5e7eb" : t.data.fill, this.ctx.fillRect(R, _, Math.max(z, 2), Math.max(W, 2)), this.ctx.strokeStyle = t.data.stroke === "transparent" ? "#9ca3af" : t.data.stroke, this.ctx.lineWidth = 0.5, this.ctx.strokeRect(R, _, Math.max(z, 2), Math.max(W, 2));
|
|
48
|
+
const R = M + (t.position.x - a) * s, _ = y + (t.position.y - o) * s, z = t.width * s, W = t.height * s;
|
|
49
|
+
this.ctx.fillStyle = t.data.fill === "transparent" ? "#e5e7eb" : X(t.data.fill, "#e5e7eb"), this.ctx.fillRect(R, _, Math.max(z, 2), Math.max(W, 2)), this.ctx.strokeStyle = t.data.stroke === "transparent" ? "#9ca3af" : X(t.data.stroke, "#9ca3af"), this.ctx.lineWidth = 0.5, this.ctx.strokeRect(R, _, Math.max(z, 2), Math.max(W, 2));
|
|
49
50
|
}
|
|
50
|
-
const g = M + (m - a) * s,
|
|
51
|
-
this.ctx.fillStyle = "rgba(59, 130, 246, 0.12)", this.ctx.fillRect(g,
|
|
51
|
+
const g = M + (m - a) * s, b = y + (f - o) * s, u = d * s, k = v * s;
|
|
52
|
+
this.ctx.fillStyle = "rgba(59, 130, 246, 0.12)", this.ctx.fillRect(g, b, u, k), this.ctx.strokeStyle = "#3b82f6", this.ctx.lineWidth = 1.5, this.ctx.strokeRect(g, b, u, k);
|
|
52
53
|
}
|
|
53
54
|
destroy() {
|
|
54
55
|
}
|
|
55
56
|
};
|
|
56
57
|
export {
|
|
57
|
-
|
|
58
|
+
S as MiniMapRenderer
|
|
58
59
|
};
|
|
59
60
|
|
|
60
61
|
//# sourceMappingURL=MiniMapRenderer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MiniMapRenderer.js","names":[],"sources":["../../../../../src/components/pro/Flow/canvas/MiniMapRenderer.ts"],"sourcesContent":["import { Graphics, Container, Application } from 'pixi.js';\nimport type { FlowNode, FlowEdge, ViewportState } from '../types';\n\n/**\n * Renders a small minimap in a separate canvas element.\n * Shows node positions as colored rectangles and a viewport rectangle.\n */\nexport class MiniMapRenderer {\n private canvas: HTMLCanvasElement;\n private ctx: CanvasRenderingContext2D;\n private _visible = true;\n\n // Last-computed world→minimap transform, used to invert minimap clicks\n // back into world coordinates for click-to-navigate.\n private _transform: { scale: number; ox: number; oy: number; wMinX: number; wMinY: number } | null = null;\n\n constructor(canvas: HTMLCanvasElement) {\n this.canvas = canvas;\n this.ctx = canvas.getContext('2d')!;\n }\n\n set visible(v: boolean) {\n this._visible = v;\n this.canvas.style.display = v ? 'block' : 'none';\n }\n\n /**\n * Convert a point in minimap *canvas pixel* space (0..canvas.width /\n * 0..canvas.height) into world coordinates. Returns null if the minimap has\n * not been rendered yet (no transform available).\n */\n minimapToWorld(px: number, py: number): { x: number; y: number } | null {\n const t = this._transform;\n if (!t) return null;\n return {\n x: (px - t.ox) / t.scale + t.wMinX,\n y: (py - t.oy) / t.scale + t.wMinY,\n };\n }\n\n /** Canvas backing size, so callers can map CSS pixels → canvas pixels. */\n get size(): { width: number; height: number } {\n return { width: this.canvas.width, height: this.canvas.height };\n }\n\n update(\n nodes: FlowNode[],\n viewport: ViewportState,\n screenW: number,\n screenH: number,\n ): void {\n if (!this._visible || nodes.length === 0) {\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n return;\n }\n\n const cw = this.canvas.width;\n const ch = this.canvas.height;\n this.ctx.clearRect(0, 0, cw, ch);\n\n // Current viewport rect in world coords.\n const viewX = -viewport.x / viewport.zoom;\n const viewY = -viewport.y / viewport.zoom;\n const viewW = screenW / viewport.zoom;\n const viewH = screenH / viewport.zoom;\n\n // Compute world bounds of the content.\n let wMinX = Infinity, wMinY = Infinity, wMaxX = -Infinity, wMaxY = -Infinity;\n for (const n of nodes) {\n wMinX = Math.min(wMinX, n.position.x);\n wMinY = Math.min(wMinY, n.position.y);\n wMaxX = Math.max(wMaxX, n.position.x + n.width);\n wMaxY = Math.max(wMaxY, n.position.y + n.height);\n }\n\n const padding = 50;\n wMinX -= padding;\n wMinY -= padding;\n wMaxX += padding;\n wMaxY += padding;\n\n // Include the viewport rect in the fitted bounds so the blue box always\n // stays visible and proportional (instead of overflowing when zoomed out).\n wMinX = Math.min(wMinX, viewX);\n wMinY = Math.min(wMinY, viewY);\n wMaxX = Math.max(wMaxX, viewX + viewW);\n wMaxY = Math.max(wMaxY, viewY + viewH);\n\n const ww = wMaxX - wMinX;\n const wh = wMaxY - wMinY;\n const scale = Math.min(cw / ww, ch / wh);\n const ox = (cw - ww * scale) / 2;\n const oy = (ch - wh * scale) / 2;\n\n // Remember the transform so minimap clicks can be inverted to world space.\n this._transform = { scale, ox, oy, wMinX, wMinY };\n\n // Draw nodes\n for (const n of nodes) {\n const x = ox + (n.position.x - wMinX) * scale;\n const y = oy + (n.position.y - wMinY) * scale;\n const w = n.width * scale;\n const h = n.height * scale;\n\n this.ctx.fillStyle = n.data.fill === 'transparent' ? '#e5e7eb' : n.data.fill;\n this.ctx.fillRect(x, y, Math.max(w, 2), Math.max(h, 2));\n this.ctx.strokeStyle = n.data.stroke === 'transparent' ? '#9ca3af' : n.data.stroke;\n this.ctx.lineWidth = 0.5;\n this.ctx.strokeRect(x, y, Math.max(w, 2), Math.max(h, 2));\n }\n\n // Draw viewport rectangle\n const vpX = ox + (viewX - wMinX) * scale;\n const vpY = oy + (viewY - wMinY) * scale;\n const vpW = viewW * scale;\n const vpH = viewH * scale;\n\n this.ctx.fillStyle = 'rgba(59, 130, 246, 0.12)';\n this.ctx.fillRect(vpX, vpY, vpW, vpH);\n this.ctx.strokeStyle = '#3b82f6';\n this.ctx.lineWidth = 1.5;\n this.ctx.strokeRect(vpX, vpY, vpW, vpH);\n }\n\n destroy(): void {\n // Canvas element lifecycle managed by React\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"MiniMapRenderer.js","names":[],"sources":["../../../../../src/components/pro/Flow/canvas/MiniMapRenderer.ts"],"sourcesContent":["import { Graphics, Container, Application } from 'pixi.js';\nimport type { FlowNode, FlowEdge, ViewportState } from '../types';\nimport { resolveThemeColor } from '../utils/themeColor';\n\n/**\n * Renders a small minimap in a separate canvas element.\n * Shows node positions as colored rectangles and a viewport rectangle.\n */\nexport class MiniMapRenderer {\n private canvas: HTMLCanvasElement;\n private ctx: CanvasRenderingContext2D;\n private _visible = true;\n\n // Last-computed world→minimap transform, used to invert minimap clicks\n // back into world coordinates for click-to-navigate.\n private _transform: { scale: number; ox: number; oy: number; wMinX: number; wMinY: number } | null = null;\n\n constructor(canvas: HTMLCanvasElement) {\n this.canvas = canvas;\n this.ctx = canvas.getContext('2d')!;\n }\n\n set visible(v: boolean) {\n this._visible = v;\n this.canvas.style.display = v ? 'block' : 'none';\n }\n\n /**\n * Convert a point in minimap *canvas pixel* space (0..canvas.width /\n * 0..canvas.height) into world coordinates. Returns null if the minimap has\n * not been rendered yet (no transform available).\n */\n minimapToWorld(px: number, py: number): { x: number; y: number } | null {\n const t = this._transform;\n if (!t) return null;\n return {\n x: (px - t.ox) / t.scale + t.wMinX,\n y: (py - t.oy) / t.scale + t.wMinY,\n };\n }\n\n /** Canvas backing size, so callers can map CSS pixels → canvas pixels. */\n get size(): { width: number; height: number } {\n return { width: this.canvas.width, height: this.canvas.height };\n }\n\n update(\n nodes: FlowNode[],\n viewport: ViewportState,\n screenW: number,\n screenH: number,\n ): void {\n if (!this._visible || nodes.length === 0) {\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n return;\n }\n\n const cw = this.canvas.width;\n const ch = this.canvas.height;\n this.ctx.clearRect(0, 0, cw, ch);\n\n // Current viewport rect in world coords.\n const viewX = -viewport.x / viewport.zoom;\n const viewY = -viewport.y / viewport.zoom;\n const viewW = screenW / viewport.zoom;\n const viewH = screenH / viewport.zoom;\n\n // Compute world bounds of the content.\n let wMinX = Infinity, wMinY = Infinity, wMaxX = -Infinity, wMaxY = -Infinity;\n for (const n of nodes) {\n wMinX = Math.min(wMinX, n.position.x);\n wMinY = Math.min(wMinY, n.position.y);\n wMaxX = Math.max(wMaxX, n.position.x + n.width);\n wMaxY = Math.max(wMaxY, n.position.y + n.height);\n }\n\n const padding = 50;\n wMinX -= padding;\n wMinY -= padding;\n wMaxX += padding;\n wMaxY += padding;\n\n // Include the viewport rect in the fitted bounds so the blue box always\n // stays visible and proportional (instead of overflowing when zoomed out).\n wMinX = Math.min(wMinX, viewX);\n wMinY = Math.min(wMinY, viewY);\n wMaxX = Math.max(wMaxX, viewX + viewW);\n wMaxY = Math.max(wMaxY, viewY + viewH);\n\n const ww = wMaxX - wMinX;\n const wh = wMaxY - wMinY;\n const scale = Math.min(cw / ww, ch / wh);\n const ox = (cw - ww * scale) / 2;\n const oy = (ch - wh * scale) / 2;\n\n // Remember the transform so minimap clicks can be inverted to world space.\n this._transform = { scale, ox, oy, wMinX, wMinY };\n\n // Draw nodes\n for (const n of nodes) {\n const x = ox + (n.position.x - wMinX) * scale;\n const y = oy + (n.position.y - wMinY) * scale;\n const w = n.width * scale;\n const h = n.height * scale;\n\n this.ctx.fillStyle = n.data.fill === 'transparent' ? '#e5e7eb' : resolveThemeColor(n.data.fill, '#e5e7eb');\n this.ctx.fillRect(x, y, Math.max(w, 2), Math.max(h, 2));\n this.ctx.strokeStyle = n.data.stroke === 'transparent' ? '#9ca3af' : resolveThemeColor(n.data.stroke, '#9ca3af');\n this.ctx.lineWidth = 0.5;\n this.ctx.strokeRect(x, y, Math.max(w, 2), Math.max(h, 2));\n }\n\n // Draw viewport rectangle\n const vpX = ox + (viewX - wMinX) * scale;\n const vpY = oy + (viewY - wMinY) * scale;\n const vpW = viewW * scale;\n const vpH = viewH * scale;\n\n this.ctx.fillStyle = 'rgba(59, 130, 246, 0.12)';\n this.ctx.fillRect(vpX, vpY, vpW, vpH);\n this.ctx.strokeStyle = '#3b82f6';\n this.ctx.lineWidth = 1.5;\n this.ctx.strokeRect(vpX, vpY, vpW, vpH);\n }\n\n destroy(): void {\n // Canvas element lifecycle managed by React\n }\n}\n"],"mappings":"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"}
|
|
@@ -20,6 +20,8 @@ export declare class PixiApp {
|
|
|
20
20
|
constructor();
|
|
21
21
|
init(options: PixiAppOptions): Promise<void>;
|
|
22
22
|
resize(width: number, height: number): void;
|
|
23
|
+
/** Update the canvas backdrop color (e.g. when the DishUI theme changes). */
|
|
24
|
+
setBackgroundColor(color: number): void;
|
|
23
25
|
/**
|
|
24
26
|
* Export the current scene to a PNG data URL.
|
|
25
27
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Application as u, Container as p } from "pixi.js";
|
|
2
|
-
var
|
|
2
|
+
var g = class {
|
|
3
3
|
app;
|
|
4
4
|
world;
|
|
5
5
|
_destroyed = !1;
|
|
@@ -21,6 +21,9 @@ var w = class {
|
|
|
21
21
|
resize(t, r) {
|
|
22
22
|
this._destroyed || !this._initialized || (this.app.renderer.resize(t, r), this.app.stage.hitArea = this.app.screen);
|
|
23
23
|
}
|
|
24
|
+
setBackgroundColor(t) {
|
|
25
|
+
this._destroyed || !this._initialized || (this.app.renderer.background.color = t);
|
|
26
|
+
}
|
|
24
27
|
async exportPNG(t) {
|
|
25
28
|
if (this._destroyed || !this._initialized) return null;
|
|
26
29
|
const r = this.app.renderer;
|
|
@@ -62,23 +65,23 @@ var w = class {
|
|
|
62
65
|
return this.world.position.set(e.x, e.y), this.world.scale.set(e.sx, e.sy), this.app.render(), null;
|
|
63
66
|
}
|
|
64
67
|
this.world.position.set(e.x, e.y), this.world.scale.set(e.sx, e.sy), this.app.render();
|
|
65
|
-
const o = i.width,
|
|
66
|
-
if (!o || !
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
const h =
|
|
68
|
+
const o = i.width, d = i.height;
|
|
69
|
+
if (!o || !d) return null;
|
|
70
|
+
const l = document.createElement("canvas");
|
|
71
|
+
l.width = o, l.height = d;
|
|
72
|
+
const h = l.getContext("2d");
|
|
70
73
|
if (!h) {
|
|
71
74
|
const c = typeof i.toDataURL == "function" ? i.toDataURL("image/png") : null;
|
|
72
75
|
return c ? {
|
|
73
76
|
dataUrl: c,
|
|
74
77
|
width: o,
|
|
75
|
-
height:
|
|
78
|
+
height: d
|
|
76
79
|
} : null;
|
|
77
80
|
}
|
|
78
|
-
return h.fillStyle = r?.backgroundColor !== void 0 ? `#${r.backgroundColor.toString(16).padStart(6, "0")}` : "#ffffff", h.fillRect(0, 0, o,
|
|
79
|
-
dataUrl:
|
|
81
|
+
return h.fillStyle = r?.backgroundColor !== void 0 ? `#${r.backgroundColor.toString(16).padStart(6, "0")}` : "#ffffff", h.fillRect(0, 0, o, d), h.drawImage(i, 0, 0), {
|
|
82
|
+
dataUrl: l.toDataURL("image/png"),
|
|
80
83
|
width: o,
|
|
81
|
-
height:
|
|
84
|
+
height: d
|
|
82
85
|
};
|
|
83
86
|
}
|
|
84
87
|
destroy() {
|
|
@@ -96,7 +99,7 @@ var w = class {
|
|
|
96
99
|
}
|
|
97
100
|
};
|
|
98
101
|
export {
|
|
99
|
-
|
|
102
|
+
g as PixiApp
|
|
100
103
|
};
|
|
101
104
|
|
|
102
105
|
//# sourceMappingURL=PixiApp.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PixiApp.js","names":[],"sources":["../../../../../src/components/pro/Flow/canvas/PixiApp.ts"],"sourcesContent":["import { Application, Container } from 'pixi.js';\n\nexport interface PixiAppOptions {\n canvas: HTMLCanvasElement;\n backgroundColor?: number;\n antialias?: boolean;\n resolution?: number;\n autoDensity?: boolean;\n width?: number;\n height?: number;\n}\n\n/**\n * Wraps PixiJS Application lifecycle: init, resize, destroy.\n * The world container holds all flow content and is transformed for pan/zoom.\n */\nexport class PixiApp {\n app: Application;\n world: Container;\n private _destroyed = false;\n private _initialized = false;\n\n constructor() {\n this.app = new Application();\n this.world = new Container({ label: 'world' });\n }\n\n async init(options: PixiAppOptions): Promise<void> {\n if (this._destroyed) return;\n await this.app.init({\n canvas: options.canvas,\n background: options.backgroundColor ?? 0xf8f9fa,\n antialias: options.antialias ?? true,\n resolution: options.resolution ?? (window.devicePixelRatio || 1),\n autoDensity: options.autoDensity ?? true,\n width: options.width,\n height: options.height,\n });\n if (this._destroyed) return;\n this._initialized = true;\n this.app.stage.addChild(this.world);\n this.app.stage.eventMode = 'static';\n this.app.stage.hitArea = this.app.screen;\n }\n\n resize(width: number, height: number): void {\n if (this._destroyed || !this._initialized) return;\n this.app.renderer.resize(width, height);\n this.app.stage.hitArea = this.app.screen;\n }\n\n /**\n * Export the current scene to a PNG data URL.\n *\n * Reading the WebGL canvas directly with `canvas.toDataURL()` returns a black\n * image because PixiJS does not preserve the drawing buffer between frames.\n * The renderer's `extract` plugin re-renders the target into an offscreen\n * canvas, which is the reliable way to snapshot the scene.\n */\n async exportPNG(backgroundColor?: number): Promise<string | null> {\n if (this._destroyed || !this._initialized) return null;\n const renderer = this.app.renderer as unknown as {\n extract?: {\n canvas: (target: unknown) => HTMLCanvasElement | OffscreenCanvas;\n };\n };\n if (!renderer || !renderer.extract) return null;\n\n // Force a fresh render so the extract reflects the latest state.\n this.app.render();\n\n let out: HTMLCanvasElement | OffscreenCanvas;\n try {\n out = renderer.extract.canvas(this.app.stage);\n } catch {\n return null;\n }\n\n const w = (out as HTMLCanvasElement).width;\n const h = (out as HTMLCanvasElement).height;\n if (!w || !h) return null;\n\n // Composite onto an opaque background so transparent areas aren't black.\n const composite = document.createElement('canvas');\n composite.width = w;\n composite.height = h;\n const ctx = composite.getContext('2d');\n if (!ctx) {\n return typeof (out as HTMLCanvasElement).toDataURL === 'function'\n ? (out as HTMLCanvasElement).toDataURL('image/png')\n : null;\n }\n ctx.fillStyle = backgroundColor !== undefined\n ? `#${backgroundColor.toString(16).padStart(6, '0')}`\n : '#ffffff';\n ctx.fillRect(0, 0, w, h);\n ctx.drawImage(out as CanvasImageSource, 0, 0);\n return composite.toDataURL('image/png');\n }\n\n /**\n * Export a specific world-space rectangle to a PNG data URL, cropped exactly\n * to that rectangle (used for per-anchor slide capture).\n *\n * Uses the extract system's `frame` option to render precisely the given\n * region of the `world` container in world coordinates, independent of the\n * current pan/zoom. This guarantees the output is exactly the anchor's\n * framed content — no screen-space cropping or transform juggling.\n */\n async exportRegionPNG(\n rect: { x: number; y: number; w: number; h: number },\n options?: { scale?: number; backgroundColor?: number },\n ): Promise<{ dataUrl: string; width: number; height: number } | null> {\n if (this._destroyed || !this._initialized) return null;\n const { Rectangle } = await import('pixi.js');\n const renderer = this.app.renderer as unknown as {\n extract?: {\n canvas: (options: unknown) => HTMLCanvasElement | OffscreenCanvas;\n };\n };\n if (!renderer || !renderer.extract) return null;\n\n const scale = Math.max(0.1, options?.scale ?? 2);\n\n // Temporarily reset the world transform to identity so the `frame` (given in\n // world coordinates) maps 1:1 to the anchor content, independent of the\n // current pan/zoom. Restored immediately after extraction.\n const prev = {\n x: this.world.position.x,\n y: this.world.position.y,\n sx: this.world.scale.x,\n sy: this.world.scale.y,\n };\n this.world.position.set(0, 0);\n this.world.scale.set(1, 1);\n\n let out: HTMLCanvasElement | OffscreenCanvas;\n try {\n // Fresh render so the extract reflects the latest scene state.\n this.app.render();\n out = renderer.extract.canvas({\n target: this.world,\n // Frame is in the target's LOCAL (world) coordinates.\n frame: new Rectangle(rect.x, rect.y, rect.w, rect.h),\n resolution: scale,\n antialias: true,\n });\n } catch {\n this.world.position.set(prev.x, prev.y);\n this.world.scale.set(prev.sx, prev.sy);\n this.app.render();\n return null;\n }\n\n // Restore the interactive viewport transform immediately.\n this.world.position.set(prev.x, prev.y);\n this.world.scale.set(prev.sx, prev.sy);\n this.app.render();\n\n const w = (out as HTMLCanvasElement).width;\n const h = (out as HTMLCanvasElement).height;\n if (!w || !h) return null;\n\n // Composite onto an opaque background so transparent areas aren't black.\n const composite = document.createElement('canvas');\n composite.width = w;\n composite.height = h;\n const ctx = composite.getContext('2d');\n if (!ctx) {\n const url = typeof (out as HTMLCanvasElement).toDataURL === 'function'\n ? (out as HTMLCanvasElement).toDataURL('image/png')\n : null;\n return url ? { dataUrl: url, width: w, height: h } : null;\n }\n ctx.fillStyle = options?.backgroundColor !== undefined\n ? `#${options.backgroundColor.toString(16).padStart(6, '0')}`\n : '#ffffff';\n ctx.fillRect(0, 0, w, h);\n ctx.drawImage(out as CanvasImageSource, 0, 0);\n return { dataUrl: composite.toDataURL('image/png'), width: w, height: h };\n }\n\n destroy(): void {\n if (this._destroyed) return;\n this._destroyed = true;\n if (!this._initialized) return;\n try {\n this.app.destroy(true, { children: true, texture: true });\n } catch {\n // PixiJS may throw if internal state is partially torn down\n }\n }\n\n get destroyed(): boolean {\n return this._destroyed;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PixiApp.js","names":[],"sources":["../../../../../src/components/pro/Flow/canvas/PixiApp.ts"],"sourcesContent":["import { Application, Container } from 'pixi.js';\n\nexport interface PixiAppOptions {\n canvas: HTMLCanvasElement;\n backgroundColor?: number;\n antialias?: boolean;\n resolution?: number;\n autoDensity?: boolean;\n width?: number;\n height?: number;\n}\n\n/**\n * Wraps PixiJS Application lifecycle: init, resize, destroy.\n * The world container holds all flow content and is transformed for pan/zoom.\n */\nexport class PixiApp {\n app: Application;\n world: Container;\n private _destroyed = false;\n private _initialized = false;\n\n constructor() {\n this.app = new Application();\n this.world = new Container({ label: 'world' });\n }\n\n async init(options: PixiAppOptions): Promise<void> {\n if (this._destroyed) return;\n await this.app.init({\n canvas: options.canvas,\n background: options.backgroundColor ?? 0xf8f9fa,\n antialias: options.antialias ?? true,\n resolution: options.resolution ?? (window.devicePixelRatio || 1),\n autoDensity: options.autoDensity ?? true,\n width: options.width,\n height: options.height,\n });\n if (this._destroyed) return;\n this._initialized = true;\n this.app.stage.addChild(this.world);\n this.app.stage.eventMode = 'static';\n this.app.stage.hitArea = this.app.screen;\n }\n\n resize(width: number, height: number): void {\n if (this._destroyed || !this._initialized) return;\n this.app.renderer.resize(width, height);\n this.app.stage.hitArea = this.app.screen;\n }\n\n /** Update the canvas backdrop color (e.g. when the DishUI theme changes). */\n setBackgroundColor(color: number): void {\n if (this._destroyed || !this._initialized) return;\n this.app.renderer.background.color = color;\n }\n\n /**\n * Export the current scene to a PNG data URL.\n *\n * Reading the WebGL canvas directly with `canvas.toDataURL()` returns a black\n * image because PixiJS does not preserve the drawing buffer between frames.\n * The renderer's `extract` plugin re-renders the target into an offscreen\n * canvas, which is the reliable way to snapshot the scene.\n */\n async exportPNG(backgroundColor?: number): Promise<string | null> {\n if (this._destroyed || !this._initialized) return null;\n const renderer = this.app.renderer as unknown as {\n extract?: {\n canvas: (target: unknown) => HTMLCanvasElement | OffscreenCanvas;\n };\n };\n if (!renderer || !renderer.extract) return null;\n\n // Force a fresh render so the extract reflects the latest state.\n this.app.render();\n\n let out: HTMLCanvasElement | OffscreenCanvas;\n try {\n out = renderer.extract.canvas(this.app.stage);\n } catch {\n return null;\n }\n\n const w = (out as HTMLCanvasElement).width;\n const h = (out as HTMLCanvasElement).height;\n if (!w || !h) return null;\n\n // Composite onto an opaque background so transparent areas aren't black.\n const composite = document.createElement('canvas');\n composite.width = w;\n composite.height = h;\n const ctx = composite.getContext('2d');\n if (!ctx) {\n return typeof (out as HTMLCanvasElement).toDataURL === 'function'\n ? (out as HTMLCanvasElement).toDataURL('image/png')\n : null;\n }\n ctx.fillStyle = backgroundColor !== undefined\n ? `#${backgroundColor.toString(16).padStart(6, '0')}`\n : '#ffffff';\n ctx.fillRect(0, 0, w, h);\n ctx.drawImage(out as CanvasImageSource, 0, 0);\n return composite.toDataURL('image/png');\n }\n\n /**\n * Export a specific world-space rectangle to a PNG data URL, cropped exactly\n * to that rectangle (used for per-anchor slide capture).\n *\n * Uses the extract system's `frame` option to render precisely the given\n * region of the `world` container in world coordinates, independent of the\n * current pan/zoom. This guarantees the output is exactly the anchor's\n * framed content — no screen-space cropping or transform juggling.\n */\n async exportRegionPNG(\n rect: { x: number; y: number; w: number; h: number },\n options?: { scale?: number; backgroundColor?: number },\n ): Promise<{ dataUrl: string; width: number; height: number } | null> {\n if (this._destroyed || !this._initialized) return null;\n const { Rectangle } = await import('pixi.js');\n const renderer = this.app.renderer as unknown as {\n extract?: {\n canvas: (options: unknown) => HTMLCanvasElement | OffscreenCanvas;\n };\n };\n if (!renderer || !renderer.extract) return null;\n\n const scale = Math.max(0.1, options?.scale ?? 2);\n\n // Temporarily reset the world transform to identity so the `frame` (given in\n // world coordinates) maps 1:1 to the anchor content, independent of the\n // current pan/zoom. Restored immediately after extraction.\n const prev = {\n x: this.world.position.x,\n y: this.world.position.y,\n sx: this.world.scale.x,\n sy: this.world.scale.y,\n };\n this.world.position.set(0, 0);\n this.world.scale.set(1, 1);\n\n let out: HTMLCanvasElement | OffscreenCanvas;\n try {\n // Fresh render so the extract reflects the latest scene state.\n this.app.render();\n out = renderer.extract.canvas({\n target: this.world,\n // Frame is in the target's LOCAL (world) coordinates.\n frame: new Rectangle(rect.x, rect.y, rect.w, rect.h),\n resolution: scale,\n antialias: true,\n });\n } catch {\n this.world.position.set(prev.x, prev.y);\n this.world.scale.set(prev.sx, prev.sy);\n this.app.render();\n return null;\n }\n\n // Restore the interactive viewport transform immediately.\n this.world.position.set(prev.x, prev.y);\n this.world.scale.set(prev.sx, prev.sy);\n this.app.render();\n\n const w = (out as HTMLCanvasElement).width;\n const h = (out as HTMLCanvasElement).height;\n if (!w || !h) return null;\n\n // Composite onto an opaque background so transparent areas aren't black.\n const composite = document.createElement('canvas');\n composite.width = w;\n composite.height = h;\n const ctx = composite.getContext('2d');\n if (!ctx) {\n const url = typeof (out as HTMLCanvasElement).toDataURL === 'function'\n ? (out as HTMLCanvasElement).toDataURL('image/png')\n : null;\n return url ? { dataUrl: url, width: w, height: h } : null;\n }\n ctx.fillStyle = options?.backgroundColor !== undefined\n ? `#${options.backgroundColor.toString(16).padStart(6, '0')}`\n : '#ffffff';\n ctx.fillRect(0, 0, w, h);\n ctx.drawImage(out as CanvasImageSource, 0, 0);\n return { dataUrl: composite.toDataURL('image/png'), width: w, height: h };\n }\n\n destroy(): void {\n if (this._destroyed) return;\n this._destroyed = true;\n if (!this._initialized) return;\n try {\n this.app.destroy(true, { children: true, texture: true });\n } catch {\n // PixiJS may throw if internal state is partially torn down\n }\n }\n\n get destroyed(): boolean {\n return this._destroyed;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
var t = "root", e = {
|
|
2
2
|
label: "Text",
|
|
3
|
-
fill: "
|
|
4
|
-
stroke: "
|
|
3
|
+
fill: "theme:base-100",
|
|
4
|
+
stroke: "theme:base-content",
|
|
5
5
|
strokeWidth: 2,
|
|
6
|
-
color: "
|
|
6
|
+
color: "theme:base-content",
|
|
7
7
|
fontSize: 14,
|
|
8
8
|
attributes: []
|
|
9
9
|
}, a = {
|
|
@@ -11,11 +11,11 @@ var t = "root", e = {
|
|
|
11
11
|
fill: "transparent",
|
|
12
12
|
stroke: "transparent",
|
|
13
13
|
strokeWidth: 0,
|
|
14
|
-
color: "
|
|
14
|
+
color: "theme:base-content",
|
|
15
15
|
fontSize: 14,
|
|
16
16
|
attributes: []
|
|
17
17
|
}, l = {
|
|
18
|
-
strokeColor: "
|
|
18
|
+
strokeColor: "theme:base-content",
|
|
19
19
|
strokeWidth: 2,
|
|
20
20
|
lineStyle: "solid",
|
|
21
21
|
markerEnd: "arrowclosed"
|
|
@@ -239,7 +239,7 @@ var t = "root", e = {
|
|
|
239
239
|
label: "Top-Right → Bottom-Left"
|
|
240
240
|
}
|
|
241
241
|
], n = 0.1;
|
|
242
|
-
function
|
|
242
|
+
function b() {
|
|
243
243
|
return {
|
|
244
244
|
canvases: { [t]: {
|
|
245
245
|
nodes: [],
|
|
@@ -262,7 +262,7 @@ export {
|
|
|
262
262
|
o as PALETTE_ITEMS,
|
|
263
263
|
t as ROOT_CANVAS_ID,
|
|
264
264
|
a as TEXT_NODE_DATA,
|
|
265
|
-
|
|
265
|
+
b as createEmptyDocument
|
|
266
266
|
};
|
|
267
267
|
|
|
268
268
|
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","names":[],"sources":["../../../../src/components/pro/Flow/constants.ts"],"sourcesContent":["import type {\n FlowNodeData,\n FlowShapeType,\n FlowEdgeTypeName,\n FlowEdgeMarkerKind,\n FlowEdgeLineStyle,\n FlowEdgeDashDensity,\n FlowBorderStyle,\n GradientDirection,\n FlowDocument,\n FlowEdgeData,\n} from './types';\n\nexport const ROOT_CANVAS_ID = 'root';\n\nexport const DEFAULT_NODE_DATA: FlowNodeData = {\n label: 'Text',\n fill: '
|
|
1
|
+
{"version":3,"file":"constants.js","names":[],"sources":["../../../../src/components/pro/Flow/constants.ts"],"sourcesContent":["import type {\n FlowNodeData,\n FlowShapeType,\n FlowEdgeTypeName,\n FlowEdgeMarkerKind,\n FlowEdgeLineStyle,\n FlowEdgeDashDensity,\n FlowBorderStyle,\n GradientDirection,\n FlowDocument,\n FlowEdgeData,\n} from './types';\n\nexport const ROOT_CANVAS_ID = 'root';\n\nexport const DEFAULT_NODE_DATA: FlowNodeData = {\n label: 'Text',\n fill: 'theme:base-100',\n stroke: 'theme:base-content',\n strokeWidth: 2,\n color: 'theme:base-content',\n fontSize: 14,\n attributes: [],\n};\n\nexport const TEXT_NODE_DATA: FlowNodeData = {\n label: 'Label',\n fill: 'transparent',\n stroke: 'transparent',\n strokeWidth: 0,\n color: 'theme:base-content',\n fontSize: 14,\n attributes: [],\n};\n\nexport const DEFAULT_EDGE_DATA: FlowEdgeData = {\n strokeColor: 'theme:base-content',\n strokeWidth: 2,\n lineStyle: 'solid',\n markerEnd: 'arrowclosed',\n};\n\nexport const PALETTE_ITEMS: Array<{\n type: FlowShapeType;\n width: number;\n height: number;\n data: FlowNodeData;\n}> = [\n { type: 'shapeRect', width: 140, height: 72, data: { ...DEFAULT_NODE_DATA, label: 'Rectangle' } },\n { type: 'shapeRoundRect', width: 140, height: 72, data: { ...DEFAULT_NODE_DATA, label: 'Rounded' } },\n { type: 'shapeEllipse', width: 120, height: 120, data: { ...DEFAULT_NODE_DATA, label: 'Ellipse' } },\n { type: 'shapeDiamond', width: 120, height: 120, data: { ...DEFAULT_NODE_DATA, label: 'Diamond' } },\n { type: 'shapeDocument', width: 120, height: 80, data: { ...DEFAULT_NODE_DATA, label: 'Document' } },\n { type: 'shapeParallelogram', width: 140, height: 72, data: { ...DEFAULT_NODE_DATA, label: 'Parallelogram' } },\n { type: 'shapeTriangle', width: 120, height: 100, data: { ...DEFAULT_NODE_DATA, label: 'Triangle' } },\n { type: 'shapeTrapezoid', width: 140, height: 72, data: { ...DEFAULT_NODE_DATA, label: 'Trapezoid' } },\n { type: 'shapePentagon', width: 100, height: 100, data: { ...DEFAULT_NODE_DATA, label: 'Pentagon' } },\n { type: 'shapeHexagon', width: 120, height: 100, data: { ...DEFAULT_NODE_DATA, label: 'Hexagon' } },\n { type: 'shapeStar', width: 100, height: 100, data: { ...DEFAULT_NODE_DATA, label: 'Star' } },\n { type: 'shapeHexagram', width: 100, height: 100, data: { ...DEFAULT_NODE_DATA, label: 'Hexagram' } },\n { type: 'shapeRightTriangle', width: 120, height: 100, data: { ...DEFAULT_NODE_DATA, label: 'Right Triangle' } },\n { type: 'shapeCorner', width: 100, height: 100, data: { ...DEFAULT_NODE_DATA, label: 'Corner' } },\n { type: 'textLabel', width: 120, height: 40, data: { ...TEXT_NODE_DATA, label: 'Label' } },\n { type: 'animAnchor', width: 320, height: 240, data: { ...DEFAULT_NODE_DATA, label: 'Anchor', fill: 'transparent', stroke: '#8b5cf6', strokeWidth: 1.5, borderStyle: 'dashed' } },\n { type: 'geometryGroup', width: 200, height: 160, data: { ...DEFAULT_NODE_DATA, label: 'Geo Group', fill: '#fefce8', stroke: '#9ca3af', strokeWidth: 1.5, borderStyle: 'dashed', isGroup: true } },\n];\n\nexport const EDGE_TYPE_OPTIONS: FlowEdgeTypeName[] = [\n 'smoothstep',\n 'step',\n 'straight',\n 'simplebezier',\n];\n\nexport const EDGE_MARKER_OPTIONS: FlowEdgeMarkerKind[] = [\n 'none',\n 'arrow',\n 'arrowclosed',\n];\n\nexport const EDGE_LINE_STYLE_OPTIONS: FlowEdgeLineStyle[] = [\n 'solid',\n 'dashed',\n 'dotted',\n 'dynamic',\n];\n\nexport const BORDER_STYLE_OPTIONS: FlowBorderStyle[] = [\n 'solid',\n 'dashed',\n 'dotted',\n 'dynamic',\n];\n\nexport const DASH_DENSITY_OPTIONS: FlowEdgeDashDensity[] = [\n 'sparse',\n 'medium',\n 'dense',\n];\n\nexport const GRADIENT_DIRECTION_OPTIONS: Array<{\n value: GradientDirection;\n label: string;\n}> = [\n { value: 'to-r', label: 'Left → Right' },\n { value: 'to-l', label: 'Right → Left' },\n { value: 'to-b', label: 'Top → Bottom' },\n { value: 'to-t', label: 'Bottom → Top' },\n { value: 'to-br', label: 'Top-Left → Bottom-Right' },\n { value: 'to-tl', label: 'Bottom-Right → Top-Left' },\n { value: 'to-tr', label: 'Bottom-Left → Top-Right' },\n { value: 'to-bl', label: 'Top-Right → Bottom-Left' },\n];\n\nexport const MIN_ZOOM = 0.1;\nexport const MAX_ZOOM = 4;\nexport const DEFAULT_GRID_SIZE = 20;\nexport const ZOOM_SENSITIVITY = 0.001;\nexport const SNAP_THRESHOLD = 5;\nexport const HANDLE_SIZE = 8;\n\nexport function createEmptyDocument(): FlowDocument {\n return {\n canvases: { [ROOT_CANVAS_ID]: { nodes: [], edges: [], lines: [] } },\n stack: [ROOT_CANVAS_ID],\n };\n}\n"],"mappings":"AAaA,IAAa,IAAiB,QAEjB,IAAkC;AAAA,EAC7C,OAAO;AAAA,EACP,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY,CAAC;AACf,GAEa,IAA+B;AAAA,EAC1C,OAAO;AAAA,EACP,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY,CAAC;AACf,GAEa,IAAkC;AAAA,EAC7C,aAAa;AAAA,EACb,aAAa;AAAA,EACb,WAAW;AAAA,EACX,WAAW;AACb,GAEa,IAKR;AAAA,EACH;AAAA,IAAE,MAAM;AAAA,IAAa,OAAO;AAAA,IAAK,QAAQ;AAAA,IAAI,MAAM;AAAA,MAAE,GAAG;AAAA,MAAmB,OAAO;AAAA,IAAY;AAAA,EAAE;AAAA,EAChG;AAAA,IAAE,MAAM;AAAA,IAAkB,OAAO;AAAA,IAAK,QAAQ;AAAA,IAAI,MAAM;AAAA,MAAE,GAAG;AAAA,MAAmB,OAAO;AAAA,IAAU;AAAA,EAAE;AAAA,EACnG;AAAA,IAAE,MAAM;AAAA,IAAgB,OAAO;AAAA,IAAK,QAAQ;AAAA,IAAK,MAAM;AAAA,MAAE,GAAG;AAAA,MAAmB,OAAO;AAAA,IAAU;AAAA,EAAE;AAAA,EAClG;AAAA,IAAE,MAAM;AAAA,IAAgB,OAAO;AAAA,IAAK,QAAQ;AAAA,IAAK,MAAM;AAAA,MAAE,GAAG;AAAA,MAAmB,OAAO;AAAA,IAAU;AAAA,EAAE;AAAA,EAClG;AAAA,IAAE,MAAM;AAAA,IAAiB,OAAO;AAAA,IAAK,QAAQ;AAAA,IAAI,MAAM;AAAA,MAAE,GAAG;AAAA,MAAmB,OAAO;AAAA,IAAW;AAAA,EAAE;AAAA,EACnG;AAAA,IAAE,MAAM;AAAA,IAAsB,OAAO;AAAA,IAAK,QAAQ;AAAA,IAAI,MAAM;AAAA,MAAE,GAAG;AAAA,MAAmB,OAAO;AAAA,IAAgB;AAAA,EAAE;AAAA,EAC7G;AAAA,IAAE,MAAM;AAAA,IAAiB,OAAO;AAAA,IAAK,QAAQ;AAAA,IAAK,MAAM;AAAA,MAAE,GAAG;AAAA,MAAmB,OAAO;AAAA,IAAW;AAAA,EAAE;AAAA,EACpG;AAAA,IAAE,MAAM;AAAA,IAAkB,OAAO;AAAA,IAAK,QAAQ;AAAA,IAAI,MAAM;AAAA,MAAE,GAAG;AAAA,MAAmB,OAAO;AAAA,IAAY;AAAA,EAAE;AAAA,EACrG;AAAA,IAAE,MAAM;AAAA,IAAiB,OAAO;AAAA,IAAK,QAAQ;AAAA,IAAK,MAAM;AAAA,MAAE,GAAG;AAAA,MAAmB,OAAO;AAAA,IAAW;AAAA,EAAE;AAAA,EACpG;AAAA,IAAE,MAAM;AAAA,IAAgB,OAAO;AAAA,IAAK,QAAQ;AAAA,IAAK,MAAM;AAAA,MAAE,GAAG;AAAA,MAAmB,OAAO;AAAA,IAAU;AAAA,EAAE;AAAA,EAClG;AAAA,IAAE,MAAM;AAAA,IAAa,OAAO;AAAA,IAAK,QAAQ;AAAA,IAAK,MAAM;AAAA,MAAE,GAAG;AAAA,MAAmB,OAAO;AAAA,IAAO;AAAA,EAAE;AAAA,EAC5F;AAAA,IAAE,MAAM;AAAA,IAAiB,OAAO;AAAA,IAAK,QAAQ;AAAA,IAAK,MAAM;AAAA,MAAE,GAAG;AAAA,MAAmB,OAAO;AAAA,IAAW;AAAA,EAAE;AAAA,EACpG;AAAA,IAAE,MAAM;AAAA,IAAsB,OAAO;AAAA,IAAK,QAAQ;AAAA,IAAK,MAAM;AAAA,MAAE,GAAG;AAAA,MAAmB,OAAO;AAAA,IAAiB;AAAA,EAAE;AAAA,EAC/G;AAAA,IAAE,MAAM;AAAA,IAAe,OAAO;AAAA,IAAK,QAAQ;AAAA,IAAK,MAAM;AAAA,MAAE,GAAG;AAAA,MAAmB,OAAO;AAAA,IAAS;AAAA,EAAE;AAAA,EAChG;AAAA,IAAE,MAAM;AAAA,IAAa,OAAO;AAAA,IAAK,QAAQ;AAAA,IAAI,MAAM;AAAA,MAAE,GAAG;AAAA,MAAgB,OAAO;AAAA,IAAQ;AAAA,EAAE;AAAA,EACzF;AAAA,IAAE,MAAM;AAAA,IAAc,OAAO;AAAA,IAAK,QAAQ;AAAA,IAAK,MAAM;AAAA,MAAE,GAAG;AAAA,MAAmB,OAAO;AAAA,MAAU,MAAM;AAAA,MAAe,QAAQ;AAAA,MAAW,aAAa;AAAA,MAAK,aAAa;AAAA,IAAS;AAAA,EAAE;AAAA,EAChL;AAAA,IAAE,MAAM;AAAA,IAAiB,OAAO;AAAA,IAAK,QAAQ;AAAA,IAAK,MAAM;AAAA,MAAE,GAAG;AAAA,MAAmB,OAAO;AAAA,MAAa,MAAM;AAAA,MAAW,QAAQ;AAAA,MAAW,aAAa;AAAA,MAAK,aAAa;AAAA,MAAU,SAAS;AAAA,IAAK;AAAA,EAAE;AACnM,GAEa,IAAwC;AAAA,EACnD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAEa,IAA4C;AAAA,EACvD;AAAA,EACA;AAAA,EACA;AACF,GAEa,IAA+C;AAAA,EAC1D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAEa,IAA0C;AAAA,EACrD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAEa,IAA8C;AAAA,EACzD;AAAA,EACA;AAAA,EACA;AACF,GAEa,IAGR;AAAA,EACH;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAe;AAAA,EACvC;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAe;AAAA,EACvC;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAe;AAAA,EACvC;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAe;AAAA,EACvC;AAAA,IAAE,OAAO;AAAA,IAAS,OAAO;AAAA,EAA0B;AAAA,EACnD;AAAA,IAAE,OAAO;AAAA,IAAS,OAAO;AAAA,EAA0B;AAAA,EACnD;AAAA,IAAE,OAAO;AAAA,IAAS,OAAO;AAAA,EAA0B;AAAA,EACnD;AAAA,IAAE,OAAO;AAAA,IAAS,OAAO;AAAA,EAA0B;AACrD,GAEa,IAAW;AAOxB,SAAgB,IAAoC;AAClD,SAAO;AAAA,IACL,UAAU,EAAA,CAAG,CAAA,GAAiB;AAAA,MAAE,OAAO,CAAC;AAAA,MAAG,OAAO,CAAC;AAAA,MAAG,OAAO,CAAC;AAAA,IAAE,EAAE;AAAA,IAClE,OAAO,CAAC,CAAc;AAAA,EACxB;AACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { FlowAIConfig } from '../types';
|
|
3
|
+
export interface FlowAIContextValue {
|
|
4
|
+
aiConfig: FlowAIConfig;
|
|
5
|
+
setAIConfig: (config: FlowAIConfig) => void;
|
|
6
|
+
/** Whether the model-config form is shown inside the AI panel. */
|
|
7
|
+
showAIConfig: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function useFlowAI(): FlowAIContextValue;
|
|
10
|
+
export interface FlowAIProviderProps {
|
|
11
|
+
initialConfig?: FlowAIConfig;
|
|
12
|
+
showAIConfig?: boolean;
|
|
13
|
+
children: React.ReactNode;
|
|
14
|
+
}
|
|
15
|
+
export declare function FlowAIProvider({ initialConfig, showAIConfig, children }: FlowAIProviderProps): React.JSX.Element;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { createContext as s, useContext as a, useMemo as l, useState as c } from "react";
|
|
2
|
+
import { jsx as w } from "react/jsx-runtime";
|
|
3
|
+
var m = {
|
|
4
|
+
gateway: "",
|
|
5
|
+
protocol: "openai",
|
|
6
|
+
model: ""
|
|
7
|
+
}, r = s(null);
|
|
8
|
+
function f() {
|
|
9
|
+
const o = a(r);
|
|
10
|
+
if (!o) throw new Error("useFlowAI must be used within FlowAIProvider");
|
|
11
|
+
return o;
|
|
12
|
+
}
|
|
13
|
+
function v({ initialConfig: o, showAIConfig: e = !0, children: n }) {
|
|
14
|
+
const [t, u] = c({
|
|
15
|
+
...m,
|
|
16
|
+
...o
|
|
17
|
+
}), i = l(() => ({
|
|
18
|
+
aiConfig: t,
|
|
19
|
+
setAIConfig: u,
|
|
20
|
+
showAIConfig: e
|
|
21
|
+
}), [t, e]);
|
|
22
|
+
return /* @__PURE__ */ w(r.Provider, {
|
|
23
|
+
value: i,
|
|
24
|
+
children: n
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
export {
|
|
28
|
+
v as FlowAIProvider,
|
|
29
|
+
f as useFlowAI
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
//# sourceMappingURL=FlowAIContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FlowAIContext.js","names":[],"sources":["../../../../../src/components/pro/Flow/context/FlowAIContext.tsx"],"sourcesContent":["import React, { createContext, useContext, useMemo, useState } from 'react';\nimport type { FlowAIConfig } from '../types';\n\nexport interface FlowAIContextValue {\n aiConfig: FlowAIConfig;\n setAIConfig: (config: FlowAIConfig) => void;\n /** Whether the model-config form is shown inside the AI panel. */\n showAIConfig: boolean;\n}\n\nconst DEFAULT_AI_CONFIG: FlowAIConfig = {\n gateway: '',\n protocol: 'openai',\n model: '',\n};\n\nconst FlowAIContext = createContext<FlowAIContextValue | null>(null);\n\nexport function useFlowAI(): FlowAIContextValue {\n const ctx = useContext(FlowAIContext);\n if (!ctx) throw new Error('useFlowAI must be used within FlowAIProvider');\n return ctx;\n}\n\nexport interface FlowAIProviderProps {\n initialConfig?: FlowAIConfig;\n showAIConfig?: boolean;\n children: React.ReactNode;\n}\n\nexport function FlowAIProvider({ initialConfig, showAIConfig = true, children }: FlowAIProviderProps) {\n const [aiConfig, setAIConfig] = useState<FlowAIConfig>({ ...DEFAULT_AI_CONFIG, ...initialConfig });\n const value = useMemo<FlowAIContextValue>(\n () => ({ aiConfig, setAIConfig, showAIConfig }),\n [aiConfig, showAIConfig],\n );\n return <FlowAIContext.Provider value={value}>{children}</FlowAIContext.Provider>;\n}\n"],"mappings":";;AAUA,IAAM,IAAkC;AAAA,EACtC,SAAS;AAAA,EACT,UAAU;AAAA,EACV,OAAO;AACT,GAEM,IAAgB,EAAyC,IAAI;AAEnE,SAAgB,IAAgC;AAC9C,QAAM,IAAM,EAAW,CAAa;AACpC,MAAI,CAAC,EAAK,OAAM,IAAI,MAAM,8CAA8C;AACxE,SAAO;AACT;AAQA,SAAgB,EAAe,EAAE,eAAA,GAAe,cAAA,IAAe,IAAM,UAAA,EAAA,GAAiC;AACpG,QAAM,CAAC,GAAU,CAAA,IAAe,EAAuB;AAAA,IAAE,GAAG;AAAA,IAAmB,GAAG;AAAA,EAAc,CAAC,GAC3F,IAAQ,EAAA,OACL;AAAA,IAAE,UAAA;AAAA,IAAU,aAAA;AAAA,IAAa,cAAA;AAAA,EAAa,IAC7C,CAAC,GAAU,CAAY,CACzB;AACA,SAAO,gBAAA,EAAC,EAAc,UAAf;AAAA,IAA+B,OAAA;AAAA,IAAQ,UAAA;AAAA,EAAiC,CAAA;AACjF"}
|
|
@@ -45,6 +45,8 @@ export interface FlowUIContextValue {
|
|
|
45
45
|
setShowOutline: (v: boolean) => void;
|
|
46
46
|
showJson: boolean;
|
|
47
47
|
setShowJson: (v: boolean) => void;
|
|
48
|
+
showAI: boolean;
|
|
49
|
+
setShowAI: (v: boolean) => void;
|
|
48
50
|
showMiniMap: boolean;
|
|
49
51
|
setShowMiniMap: (v: boolean) => void;
|
|
50
52
|
showGrid: boolean;
|
|
@@ -82,6 +84,7 @@ export interface FlowUIProviderProps {
|
|
|
82
84
|
showMiniMap?: boolean;
|
|
83
85
|
showGrid?: boolean;
|
|
84
86
|
gridSize?: number;
|
|
87
|
+
showAI?: boolean;
|
|
85
88
|
children: React.ReactNode;
|
|
86
89
|
}
|
|
87
|
-
export declare function FlowUIProvider({ showMiniMap: initMiniMap, showGrid: initGrid, gridSize: initGridSize, children }: FlowUIProviderProps): React.JSX.Element;
|
|
90
|
+
export declare function FlowUIProvider({ showMiniMap: initMiniMap, showGrid: initGrid, gridSize: initGridSize, showAI: initShowAI, children }: FlowUIProviderProps): React.JSX.Element;
|