@povio/ui 5.0.0-rc.11 → 5.0.0-rc.12
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/README.md +6 -0
- package/dist/{AppCanvasPage-BTmt8poT.d.ts → AppCanvasPage-BZ2mrKY4.d.ts} +3 -1
- package/dist/{AppCanvasPage-BsQrZ8q7.js → AppCanvasPage-DCjiFfQW.js} +1363 -343
- package/dist/{CanvasComponentsFrame-C0Sf9RcC.js → CanvasComponentsFrame-CZXY0Dxi.js} +1 -1
- package/dist/{ComponentGallery-DDSqnm9f.js → ComponentGallery-D4U5hXZL.js} +1 -1
- package/dist/{UIConfigurator-C_2kgJtm.js → UIConfigurator-CBU0G6rb.js} +171 -145
- package/dist/config/app-canvas-tanstack.d.ts +1 -1
- package/dist/config/app-canvas-tanstack.js +1 -1
- package/dist/config/app-canvas.d.ts +2 -2
- package/dist/config/app-canvas.js +1 -1
- package/dist/config/ui-configurator-vite.d.ts +2 -0
- package/dist/config/ui-configurator-vite.js +293 -4
- package/dist/config/ui-configurator.d.ts +1 -1
- package/dist/config/ui-configurator.js +1 -1
- package/dist/{configuration.context-qdjDwQJj.d.ts → configuration.context-iuZu-ie0.d.ts} +2 -0
- package/dist/styles/app-canvas.css +425 -14
- package/package.json +1 -1
|
@@ -1,44 +1,19 @@
|
|
|
1
1
|
import { t as createLucideIcon } from "./createLucideIcon-LcezOE4z.js";
|
|
2
|
-
import { a as
|
|
2
|
+
import { a as inspectElement, c as HighlightOverlay, d as emptyConfiguration, f as useUIConfiguration, g as Moon, h as Pin, i as saveThemeCss, l as InspectorDetails, m as Plus, p as Sun, r as getThemeWriter, s as getBoxHighlights, t as UIConfigurationModal } from "./UIConfigurator-CBU0G6rb.js";
|
|
3
3
|
import { t as ChevronDown } from "./chevron-down-B4Pr8bD3.js";
|
|
4
4
|
import { t as ChevronRight } from "./chevron-right-3nKJR5Bb.js";
|
|
5
5
|
import { i as Search } from "./selectDesktop.cva-CHAMxhfO.js";
|
|
6
6
|
import { t as Upload } from "./upload-CXU83BJ4.js";
|
|
7
7
|
import { t as X } from "./x-B6vfz8Ps.js";
|
|
8
|
-
import { c as
|
|
8
|
+
import { c as $542a13ca2fa5b484$export$5b6b19405a83ff9d, n as $f2ff30fde7b014be$export$3ddf2d174ce01153 } from "./Dialog-CKLkS00H.js";
|
|
9
|
+
import { t as $2ec61d1d4f780267$export$a8a3e93435678ff9 } from "./Heading-nI1_VOaE.js";
|
|
10
|
+
import { t as Select } from "./Select-CgIhoWgk.js";
|
|
11
|
+
import { t as ThemeContext } from "./theme.context-B3wQDJ-i.js";
|
|
12
|
+
import { c as isEditableToken, i as exportCss, v as parseThemeCss } from "./theme-model-DtTsIxou.js";
|
|
9
13
|
import { t as componentArtboards } from "./groups-oQmSeqXn.js";
|
|
10
|
-
import { Suspense, lazy, memo, useCallback, useEffect, useMemo, useReducer, useRef, useState } from "react";
|
|
14
|
+
import { Suspense, lazy, memo, useCallback, useEffect, useLayoutEffect, useMemo, useReducer, useRef, useState } from "react";
|
|
11
15
|
import { c } from "react/compiler-runtime";
|
|
12
16
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
13
|
-
//#region ../../node_modules/.bun/lucide-react@1.43.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/code-xml.mjs
|
|
14
|
-
/**
|
|
15
|
-
* @license lucide-react v1.43.0 - ISC
|
|
16
|
-
*
|
|
17
|
-
* This source code is licensed under the ISC license.
|
|
18
|
-
* See the LICENSE file in the root directory of this source tree.
|
|
19
|
-
*/
|
|
20
|
-
const __iconData$9 = {
|
|
21
|
-
name: "code-xml",
|
|
22
|
-
size: 24,
|
|
23
|
-
node: [
|
|
24
|
-
["path", {
|
|
25
|
-
d: "m18 16 4-4-4-4",
|
|
26
|
-
key: "1inbqp"
|
|
27
|
-
}],
|
|
28
|
-
["path", {
|
|
29
|
-
d: "m6 8-4 4 4 4",
|
|
30
|
-
key: "15zrgr"
|
|
31
|
-
}],
|
|
32
|
-
["path", {
|
|
33
|
-
d: "m14.5 4-5 16",
|
|
34
|
-
key: "e7oirm"
|
|
35
|
-
}]
|
|
36
|
-
],
|
|
37
|
-
aliases: ["code-2"]
|
|
38
|
-
};
|
|
39
|
-
__iconData$9.node;
|
|
40
|
-
const CodeXml = createLucideIcon(__iconData$9);
|
|
41
|
-
//#endregion
|
|
42
17
|
//#region ../../node_modules/.bun/lucide-react@1.43.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/download.mjs
|
|
43
18
|
/**
|
|
44
19
|
* @license lucide-react v1.43.0 - ISC
|
|
@@ -46,7 +21,7 @@ const CodeXml = createLucideIcon(__iconData$9);
|
|
|
46
21
|
* This source code is licensed under the ISC license.
|
|
47
22
|
* See the LICENSE file in the root directory of this source tree.
|
|
48
23
|
*/
|
|
49
|
-
const __iconData$
|
|
24
|
+
const __iconData$10 = {
|
|
50
25
|
name: "download",
|
|
51
26
|
size: 24,
|
|
52
27
|
node: [
|
|
@@ -64,8 +39,8 @@ const __iconData$8 = {
|
|
|
64
39
|
}]
|
|
65
40
|
]
|
|
66
41
|
};
|
|
67
|
-
__iconData$
|
|
68
|
-
const Download = createLucideIcon(__iconData$
|
|
42
|
+
__iconData$10.node;
|
|
43
|
+
const Download = createLucideIcon(__iconData$10);
|
|
69
44
|
//#endregion
|
|
70
45
|
//#region ../../node_modules/.bun/lucide-react@1.43.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/frame.mjs
|
|
71
46
|
/**
|
|
@@ -74,7 +49,7 @@ const Download = createLucideIcon(__iconData$8);
|
|
|
74
49
|
* This source code is licensed under the ISC license.
|
|
75
50
|
* See the LICENSE file in the root directory of this source tree.
|
|
76
51
|
*/
|
|
77
|
-
const __iconData$
|
|
52
|
+
const __iconData$9 = {
|
|
78
53
|
name: "frame",
|
|
79
54
|
size: 24,
|
|
80
55
|
node: [
|
|
@@ -108,8 +83,8 @@ const __iconData$7 = {
|
|
|
108
83
|
}]
|
|
109
84
|
]
|
|
110
85
|
};
|
|
111
|
-
__iconData$
|
|
112
|
-
const Frame = createLucideIcon(__iconData$
|
|
86
|
+
__iconData$9.node;
|
|
87
|
+
const Frame = createLucideIcon(__iconData$9);
|
|
113
88
|
//#endregion
|
|
114
89
|
//#region ../../node_modules/.bun/lucide-react@1.43.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/hand.mjs
|
|
115
90
|
/**
|
|
@@ -118,7 +93,7 @@ const Frame = createLucideIcon(__iconData$7);
|
|
|
118
93
|
* This source code is licensed under the ISC license.
|
|
119
94
|
* See the LICENSE file in the root directory of this source tree.
|
|
120
95
|
*/
|
|
121
|
-
const __iconData$
|
|
96
|
+
const __iconData$8 = {
|
|
122
97
|
name: "hand",
|
|
123
98
|
size: 24,
|
|
124
99
|
node: [
|
|
@@ -140,8 +115,8 @@ const __iconData$6 = {
|
|
|
140
115
|
}]
|
|
141
116
|
]
|
|
142
117
|
};
|
|
143
|
-
__iconData$
|
|
144
|
-
const Hand = createLucideIcon(__iconData$
|
|
118
|
+
__iconData$8.node;
|
|
119
|
+
const Hand = createLucideIcon(__iconData$8);
|
|
145
120
|
//#endregion
|
|
146
121
|
//#region ../../node_modules/.bun/lucide-react@1.43.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/monitor.mjs
|
|
147
122
|
/**
|
|
@@ -150,7 +125,7 @@ const Hand = createLucideIcon(__iconData$6);
|
|
|
150
125
|
* This source code is licensed under the ISC license.
|
|
151
126
|
* See the LICENSE file in the root directory of this source tree.
|
|
152
127
|
*/
|
|
153
|
-
const __iconData$
|
|
128
|
+
const __iconData$7 = {
|
|
154
129
|
name: "monitor",
|
|
155
130
|
size: 24,
|
|
156
131
|
node: [
|
|
@@ -178,8 +153,8 @@ const __iconData$5 = {
|
|
|
178
153
|
}]
|
|
179
154
|
]
|
|
180
155
|
};
|
|
181
|
-
__iconData$
|
|
182
|
-
const Monitor = createLucideIcon(__iconData$
|
|
156
|
+
__iconData$7.node;
|
|
157
|
+
const Monitor = createLucideIcon(__iconData$7);
|
|
183
158
|
//#endregion
|
|
184
159
|
//#region ../../node_modules/.bun/lucide-react@1.43.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/mouse-pointer-2.mjs
|
|
185
160
|
/**
|
|
@@ -188,7 +163,7 @@ const Monitor = createLucideIcon(__iconData$5);
|
|
|
188
163
|
* This source code is licensed under the ISC license.
|
|
189
164
|
* See the LICENSE file in the root directory of this source tree.
|
|
190
165
|
*/
|
|
191
|
-
const __iconData$
|
|
166
|
+
const __iconData$6 = {
|
|
192
167
|
name: "mouse-pointer-2",
|
|
193
168
|
size: 24,
|
|
194
169
|
node: [["path", {
|
|
@@ -196,8 +171,8 @@ const __iconData$4 = {
|
|
|
196
171
|
key: "edeuup"
|
|
197
172
|
}]]
|
|
198
173
|
};
|
|
199
|
-
__iconData$
|
|
200
|
-
const MousePointer2 = createLucideIcon(__iconData$
|
|
174
|
+
__iconData$6.node;
|
|
175
|
+
const MousePointer2 = createLucideIcon(__iconData$6);
|
|
201
176
|
//#endregion
|
|
202
177
|
//#region ../../node_modules/.bun/lucide-react@1.43.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/panel-left.mjs
|
|
203
178
|
/**
|
|
@@ -206,7 +181,7 @@ const MousePointer2 = createLucideIcon(__iconData$4);
|
|
|
206
181
|
* This source code is licensed under the ISC license.
|
|
207
182
|
* See the LICENSE file in the root directory of this source tree.
|
|
208
183
|
*/
|
|
209
|
-
const __iconData$
|
|
184
|
+
const __iconData$5 = {
|
|
210
185
|
name: "panel-left",
|
|
211
186
|
size: 24,
|
|
212
187
|
node: [["rect", {
|
|
@@ -222,8 +197,8 @@ const __iconData$3 = {
|
|
|
222
197
|
}]],
|
|
223
198
|
aliases: ["sidebar"]
|
|
224
199
|
};
|
|
225
|
-
__iconData$
|
|
226
|
-
const PanelLeft = createLucideIcon(__iconData$
|
|
200
|
+
__iconData$5.node;
|
|
201
|
+
const PanelLeft = createLucideIcon(__iconData$5);
|
|
227
202
|
//#endregion
|
|
228
203
|
//#region ../../node_modules/.bun/lucide-react@1.43.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/panels-top-left.mjs
|
|
229
204
|
/**
|
|
@@ -232,7 +207,7 @@ const PanelLeft = createLucideIcon(__iconData$3);
|
|
|
232
207
|
* This source code is licensed under the ISC license.
|
|
233
208
|
* See the LICENSE file in the root directory of this source tree.
|
|
234
209
|
*/
|
|
235
|
-
const __iconData$
|
|
210
|
+
const __iconData$4 = {
|
|
236
211
|
name: "panels-top-left",
|
|
237
212
|
size: 24,
|
|
238
213
|
node: [
|
|
@@ -255,8 +230,29 @@ const __iconData$2 = {
|
|
|
255
230
|
],
|
|
256
231
|
aliases: ["layout"]
|
|
257
232
|
};
|
|
258
|
-
__iconData$
|
|
259
|
-
const PanelsTopLeft = createLucideIcon(__iconData$
|
|
233
|
+
__iconData$4.node;
|
|
234
|
+
const PanelsTopLeft = createLucideIcon(__iconData$4);
|
|
235
|
+
//#endregion
|
|
236
|
+
//#region ../../node_modules/.bun/lucide-react@1.43.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/pencil.mjs
|
|
237
|
+
/**
|
|
238
|
+
* @license lucide-react v1.43.0 - ISC
|
|
239
|
+
*
|
|
240
|
+
* This source code is licensed under the ISC license.
|
|
241
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
242
|
+
*/
|
|
243
|
+
const __iconData$3 = {
|
|
244
|
+
name: "pencil",
|
|
245
|
+
size: 24,
|
|
246
|
+
node: [["path", {
|
|
247
|
+
d: "M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",
|
|
248
|
+
key: "1a8usu"
|
|
249
|
+
}], ["path", {
|
|
250
|
+
d: "m15 5 4 4",
|
|
251
|
+
key: "1mk7zo"
|
|
252
|
+
}]]
|
|
253
|
+
};
|
|
254
|
+
__iconData$3.node;
|
|
255
|
+
const Pencil = createLucideIcon(__iconData$3);
|
|
260
256
|
//#endregion
|
|
261
257
|
//#region ../../node_modules/.bun/lucide-react@1.43.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/scan-line.mjs
|
|
262
258
|
/**
|
|
@@ -265,7 +261,7 @@ const PanelsTopLeft = createLucideIcon(__iconData$2);
|
|
|
265
261
|
* This source code is licensed under the ISC license.
|
|
266
262
|
* See the LICENSE file in the root directory of this source tree.
|
|
267
263
|
*/
|
|
268
|
-
const __iconData$
|
|
264
|
+
const __iconData$2 = {
|
|
269
265
|
name: "scan-line",
|
|
270
266
|
size: 24,
|
|
271
267
|
node: [
|
|
@@ -291,8 +287,8 @@ const __iconData$1 = {
|
|
|
291
287
|
}]
|
|
292
288
|
]
|
|
293
289
|
};
|
|
294
|
-
__iconData$
|
|
295
|
-
const ScanLine = createLucideIcon(__iconData$
|
|
290
|
+
__iconData$2.node;
|
|
291
|
+
const ScanLine = createLucideIcon(__iconData$2);
|
|
296
292
|
//#endregion
|
|
297
293
|
//#region ../../node_modules/.bun/lucide-react@1.43.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/settings-2.mjs
|
|
298
294
|
/**
|
|
@@ -301,7 +297,7 @@ const ScanLine = createLucideIcon(__iconData$1);
|
|
|
301
297
|
* This source code is licensed under the ISC license.
|
|
302
298
|
* See the LICENSE file in the root directory of this source tree.
|
|
303
299
|
*/
|
|
304
|
-
const __iconData = {
|
|
300
|
+
const __iconData$1 = {
|
|
305
301
|
name: "settings-2",
|
|
306
302
|
size: 24,
|
|
307
303
|
node: [
|
|
@@ -327,8 +323,937 @@ const __iconData = {
|
|
|
327
323
|
}]
|
|
328
324
|
]
|
|
329
325
|
};
|
|
326
|
+
__iconData$1.node;
|
|
327
|
+
const Settings2 = createLucideIcon(__iconData$1);
|
|
328
|
+
//#endregion
|
|
329
|
+
//#region ../../node_modules/.bun/lucide-react@1.43.0+83d5fd7b249dbeef/node_modules/lucide-react/dist/esm/icons/trash.mjs
|
|
330
|
+
/**
|
|
331
|
+
* @license lucide-react v1.43.0 - ISC
|
|
332
|
+
*
|
|
333
|
+
* This source code is licensed under the ISC license.
|
|
334
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
335
|
+
*/
|
|
336
|
+
const __iconData = {
|
|
337
|
+
name: "trash",
|
|
338
|
+
size: 24,
|
|
339
|
+
node: [
|
|
340
|
+
["path", {
|
|
341
|
+
d: "M10 11v6",
|
|
342
|
+
key: "nco0om"
|
|
343
|
+
}],
|
|
344
|
+
["path", {
|
|
345
|
+
d: "M14 11v6",
|
|
346
|
+
key: "outv1u"
|
|
347
|
+
}],
|
|
348
|
+
["path", {
|
|
349
|
+
d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",
|
|
350
|
+
key: "miytrc"
|
|
351
|
+
}],
|
|
352
|
+
["path", {
|
|
353
|
+
d: "M3 6h18",
|
|
354
|
+
key: "d0wm0j"
|
|
355
|
+
}],
|
|
356
|
+
["path", {
|
|
357
|
+
d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",
|
|
358
|
+
key: "e791ji"
|
|
359
|
+
}]
|
|
360
|
+
],
|
|
361
|
+
aliases: ["trash-2"]
|
|
362
|
+
};
|
|
330
363
|
__iconData.node;
|
|
331
|
-
const
|
|
364
|
+
const Trash = createLucideIcon(__iconData);
|
|
365
|
+
//#endregion
|
|
366
|
+
//#region src/app-canvas/useWorkspaceConfiguration.ts
|
|
367
|
+
function useWorkspaceConfiguration(workspace, ready, generation, setManifest) {
|
|
368
|
+
const $ = c(15);
|
|
369
|
+
const { currentConfiguration, replaceConfiguration, defaults } = useUIConfiguration();
|
|
370
|
+
const loaded = useRef(null);
|
|
371
|
+
const t0 = workspace.id;
|
|
372
|
+
let t1;
|
|
373
|
+
if ($[0] !== defaults) {
|
|
374
|
+
t1 = JSON.stringify(defaults);
|
|
375
|
+
$[0] = defaults;
|
|
376
|
+
$[1] = t1;
|
|
377
|
+
} else t1 = $[1];
|
|
378
|
+
const key = `${generation}:${t0}:${t1}`;
|
|
379
|
+
let t2;
|
|
380
|
+
if ($[2] !== workspace.configuration) {
|
|
381
|
+
t2 = JSON.stringify(workspace.configuration);
|
|
382
|
+
$[2] = workspace.configuration;
|
|
383
|
+
$[3] = t2;
|
|
384
|
+
} else t2 = $[3];
|
|
385
|
+
const saved = t2;
|
|
386
|
+
let t3;
|
|
387
|
+
let t4;
|
|
388
|
+
if ($[4] !== currentConfiguration || $[5] !== defaults || $[6] !== key || $[7] !== ready || $[8] !== replaceConfiguration || $[9] !== saved || $[10] !== setManifest || $[11] !== workspace.configuration || $[12] !== workspace.id) {
|
|
389
|
+
t3 = () => {
|
|
390
|
+
if (!ready) return;
|
|
391
|
+
if (!loaded.current || loaded.current.key !== key || loaded.current.saved !== saved) {
|
|
392
|
+
const value = workspace.configuration ?? (loaded.current ? emptyConfiguration() : currentConfiguration);
|
|
393
|
+
const switchingWorkspace = !!loaded.current && loaded.current.workspaceId !== workspace.id;
|
|
394
|
+
loaded.current = {
|
|
395
|
+
key,
|
|
396
|
+
workspaceId: workspace.id,
|
|
397
|
+
saved
|
|
398
|
+
};
|
|
399
|
+
replaceConfiguration({
|
|
400
|
+
...value,
|
|
401
|
+
theme: {
|
|
402
|
+
light: Object.fromEntries(Object.entries(value.theme.light).filter((t5) => {
|
|
403
|
+
const [name, value_0] = t5;
|
|
404
|
+
return value_0 !== defaults.light[name];
|
|
405
|
+
})),
|
|
406
|
+
dark: Object.fromEntries(Object.entries(value.theme.dark).filter((t6) => {
|
|
407
|
+
const [name_0, value_1] = t6;
|
|
408
|
+
return value_1 !== defaults.dark[name_0];
|
|
409
|
+
})),
|
|
410
|
+
theme: Object.fromEntries(Object.entries(value.theme.theme).filter((t7) => {
|
|
411
|
+
const [name_1, value_2] = t7;
|
|
412
|
+
return value_2 !== defaults.theme[name_1];
|
|
413
|
+
}))
|
|
414
|
+
}
|
|
415
|
+
}, switchingWorkspace);
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
const snapshot = {
|
|
419
|
+
...currentConfiguration,
|
|
420
|
+
theme: {
|
|
421
|
+
light: {
|
|
422
|
+
...defaults.light,
|
|
423
|
+
...currentConfiguration.theme.light
|
|
424
|
+
},
|
|
425
|
+
dark: {
|
|
426
|
+
...defaults.dark,
|
|
427
|
+
...currentConfiguration.theme.dark
|
|
428
|
+
},
|
|
429
|
+
theme: {
|
|
430
|
+
...defaults.theme,
|
|
431
|
+
...currentConfiguration.theme.theme
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
const serialized = JSON.stringify(snapshot);
|
|
436
|
+
if (serialized === saved) return;
|
|
437
|
+
loaded.current.saved = serialized;
|
|
438
|
+
setManifest((current) => ({
|
|
439
|
+
...current,
|
|
440
|
+
workspaces: current.workspaces.map((item) => item.id === workspace.id ? {
|
|
441
|
+
...item,
|
|
442
|
+
configuration: structuredClone(snapshot)
|
|
443
|
+
} : item)
|
|
444
|
+
}));
|
|
445
|
+
};
|
|
446
|
+
t4 = [
|
|
447
|
+
defaults,
|
|
448
|
+
key,
|
|
449
|
+
saved,
|
|
450
|
+
workspace.id,
|
|
451
|
+
workspace.configuration,
|
|
452
|
+
ready,
|
|
453
|
+
currentConfiguration,
|
|
454
|
+
replaceConfiguration,
|
|
455
|
+
setManifest
|
|
456
|
+
];
|
|
457
|
+
$[4] = currentConfiguration;
|
|
458
|
+
$[5] = defaults;
|
|
459
|
+
$[6] = key;
|
|
460
|
+
$[7] = ready;
|
|
461
|
+
$[8] = replaceConfiguration;
|
|
462
|
+
$[9] = saved;
|
|
463
|
+
$[10] = setManifest;
|
|
464
|
+
$[11] = workspace.configuration;
|
|
465
|
+
$[12] = workspace.id;
|
|
466
|
+
$[13] = t3;
|
|
467
|
+
$[14] = t4;
|
|
468
|
+
} else {
|
|
469
|
+
t3 = $[13];
|
|
470
|
+
t4 = $[14];
|
|
471
|
+
}
|
|
472
|
+
useLayoutEffect(t3, t4);
|
|
473
|
+
}
|
|
474
|
+
//#endregion
|
|
475
|
+
//#region src/app-canvas/SaveCanvasTheme.tsx
|
|
476
|
+
/** Uses the same development-only writer as the configurator's CSS export. */
|
|
477
|
+
function SaveCanvasTheme() {
|
|
478
|
+
const { active, defaults } = useUIConfiguration();
|
|
479
|
+
const [writer, setWriter] = useState(null);
|
|
480
|
+
const [saving, setSaving] = useState(false);
|
|
481
|
+
const [message, setMessage] = useState("");
|
|
482
|
+
const [savedTheme, setSavedTheme] = useState(defaults);
|
|
483
|
+
useEffect(() => setWriter(getThemeWriter()), []);
|
|
484
|
+
useEffect(() => setSavedTheme(defaults), [defaults]);
|
|
485
|
+
const css = exportCss(active.theme, defaults);
|
|
486
|
+
const exported = parseThemeCss(css);
|
|
487
|
+
const currentTheme = {
|
|
488
|
+
light: {
|
|
489
|
+
...defaults.light,
|
|
490
|
+
...exported.light
|
|
491
|
+
},
|
|
492
|
+
dark: {
|
|
493
|
+
...defaults.dark,
|
|
494
|
+
...exported.dark
|
|
495
|
+
},
|
|
496
|
+
theme: {
|
|
497
|
+
...defaults.theme,
|
|
498
|
+
...exported.theme
|
|
499
|
+
}
|
|
500
|
+
};
|
|
501
|
+
const hasChanges = [
|
|
502
|
+
"light",
|
|
503
|
+
"dark",
|
|
504
|
+
"theme"
|
|
505
|
+
].some((mode) => {
|
|
506
|
+
return [.../* @__PURE__ */ new Set([...Object.keys(currentTheme[mode]), ...Object.keys(savedTheme[mode])])].some((key) => currentTheme[mode][key]?.trim() !== savedTheme[mode][key]?.trim());
|
|
507
|
+
});
|
|
508
|
+
useEffect(() => setMessage(""), [active.theme]);
|
|
509
|
+
if (!writer || !hasChanges && !saving) return null;
|
|
510
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
511
|
+
className: "povio-canvas-save-theme",
|
|
512
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
513
|
+
disabled: saving,
|
|
514
|
+
title: `Save current CSS settings to ${writer.file}`,
|
|
515
|
+
onClick: async () => {
|
|
516
|
+
setSaving(true);
|
|
517
|
+
setMessage("");
|
|
518
|
+
try {
|
|
519
|
+
await saveThemeCss(writer, css);
|
|
520
|
+
setSavedTheme(currentTheme);
|
|
521
|
+
setMessage(`Saved CSS to ${writer.file}.`);
|
|
522
|
+
} catch (error) {
|
|
523
|
+
setMessage(error instanceof Error ? error.message : "Could not save CSS settings.");
|
|
524
|
+
} finally {
|
|
525
|
+
setSaving(false);
|
|
526
|
+
}
|
|
527
|
+
},
|
|
528
|
+
children: saving ? "Saving theme…" : "Save theme to repo"
|
|
529
|
+
}), message && /* @__PURE__ */ jsx("p", {
|
|
530
|
+
role: "status",
|
|
531
|
+
children: message
|
|
532
|
+
})]
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
//#endregion
|
|
536
|
+
//#region src/app-canvas/manifest.ts
|
|
537
|
+
function createCanvasWorkspace(name, id) {
|
|
538
|
+
return {
|
|
539
|
+
id,
|
|
540
|
+
name: name.trim() || "Workspace",
|
|
541
|
+
enabledPages: null,
|
|
542
|
+
positions: {}
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
function createCanvasManifest() {
|
|
546
|
+
return {
|
|
547
|
+
version: 2,
|
|
548
|
+
workspaces: [createCanvasWorkspace("All pages", "default")],
|
|
549
|
+
activeWorkspaceId: "default",
|
|
550
|
+
examples: {},
|
|
551
|
+
breakpoint: "desktop"
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
function isRecord(value) {
|
|
555
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
556
|
+
}
|
|
557
|
+
function isJSON(value, ancestors = /* @__PURE__ */ new Set(), depth = 0) {
|
|
558
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return true;
|
|
559
|
+
if (typeof value === "number") return Number.isFinite(value);
|
|
560
|
+
if (typeof value !== "object" || depth > 30 || ancestors.has(value)) return false;
|
|
561
|
+
ancestors.add(value);
|
|
562
|
+
const valid = Object.values(value).every((child) => isJSON(child, ancestors, depth + 1));
|
|
563
|
+
ancestors.delete(value);
|
|
564
|
+
return valid;
|
|
565
|
+
}
|
|
566
|
+
function safeJSON(value, ancestors = /* @__PURE__ */ new Set(), depth = 0) {
|
|
567
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return true;
|
|
568
|
+
if (typeof value === "number") return Number.isFinite(value);
|
|
569
|
+
if (typeof value !== "object" || depth > 30 || ancestors.has(value)) return false;
|
|
570
|
+
if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) return false;
|
|
571
|
+
ancestors.add(value);
|
|
572
|
+
const valid = Object.entries(value).every(([key, child]) => ![
|
|
573
|
+
"__proto__",
|
|
574
|
+
"prototype",
|
|
575
|
+
"constructor"
|
|
576
|
+
].includes(key) && safeJSON(child, ancestors, depth + 1));
|
|
577
|
+
ancestors.delete(value);
|
|
578
|
+
return valid;
|
|
579
|
+
}
|
|
580
|
+
const stringMap = (value) => isRecord(value) && Object.values(value).every((item) => typeof item === "string");
|
|
581
|
+
const variantValue = (value) => value === null || typeof value === "string" || typeof value === "boolean";
|
|
582
|
+
function validCvaEdits(value) {
|
|
583
|
+
return isRecord(value) && Object.entries(value).every(([slot, definition]) => {
|
|
584
|
+
if (!/^[a-zA-Z][a-zA-Z0-9]*\.[a-zA-Z][a-zA-Z0-9]*$/.test(slot) || !isRecord(definition) || !Array.isArray(definition.base) || !definition.base.every((item) => typeof item === "string") || !isRecord(definition.config)) return false;
|
|
585
|
+
const config = definition.config;
|
|
586
|
+
return isRecord(config.variants) && Object.values(config.variants).every(stringMap) && isRecord(config.defaultVariants) && Object.values(config.defaultVariants).every(variantValue) && Array.isArray(config.compoundVariants) && config.compoundVariants.every((compound) => isRecord(compound) && Object.values(compound).every((item) => variantValue(item) || Array.isArray(item) && (item.every((part) => typeof part === "string") || item.every((part) => typeof part === "boolean"))));
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
/** Returns an independent JSON configuration, or undefined for invalid/unset overrides. */
|
|
590
|
+
function parseCanvasConfiguration(value) {
|
|
591
|
+
if (!isRecord(value) || !safeJSON(value) || !isRecord(value.theme) || ![
|
|
592
|
+
"light",
|
|
593
|
+
"dark",
|
|
594
|
+
"theme"
|
|
595
|
+
].every((key) => stringMap(value.theme && value.theme[key])) || !isRecord(value.config) || value.overrides !== void 0 && !validCvaEdits(value.overrides)) return void 0;
|
|
596
|
+
return JSON.parse(JSON.stringify(value));
|
|
597
|
+
}
|
|
598
|
+
function parsePositions(input) {
|
|
599
|
+
return Object.fromEntries(Object.entries(isRecord(input) ? input : {}).flatMap(([breakpoint, entries]) => {
|
|
600
|
+
if (!isRecord(entries)) return [];
|
|
601
|
+
return [[breakpoint, Object.fromEntries(Object.entries(entries).flatMap(([id, point]) => isRecord(point) && typeof point.x === "number" && Number.isFinite(point.x) && typeof point.y === "number" && Number.isFinite(point.y) ? [[id, {
|
|
602
|
+
x: point.x,
|
|
603
|
+
y: point.y
|
|
604
|
+
}]] : []))]];
|
|
605
|
+
}));
|
|
606
|
+
}
|
|
607
|
+
/** Sanitize either stored JSON text or an imported value, migrating v1 positions into the default workspace. */
|
|
608
|
+
function parseCanvasManifest(input) {
|
|
609
|
+
const fallback = createCanvasManifest();
|
|
610
|
+
let value = input;
|
|
611
|
+
if (typeof value === "string") try {
|
|
612
|
+
value = JSON.parse(value);
|
|
613
|
+
} catch {
|
|
614
|
+
return fallback;
|
|
615
|
+
}
|
|
616
|
+
if (!isRecord(value) || value.version !== 1 && value.version !== 2) return fallback;
|
|
617
|
+
const examples = Object.fromEntries(Object.entries(isRecord(value.examples) ? value.examples : {}).flatMap(([id, example]) => {
|
|
618
|
+
if (!isRecord(example)) return [];
|
|
619
|
+
const clean = {};
|
|
620
|
+
if (typeof example.title === "string") clean.title = example.title;
|
|
621
|
+
if (isRecord(example.params)) clean.params = Object.fromEntries(Object.entries(example.params).filter((entry) => typeof entry[1] === "string"));
|
|
622
|
+
if (isRecord(example.search)) clean.search = Object.fromEntries(Object.entries(example.search).filter(([, item]) => isJSON(item)));
|
|
623
|
+
return [[id, clean]];
|
|
624
|
+
}));
|
|
625
|
+
const workspaces = [];
|
|
626
|
+
const ids = /* @__PURE__ */ new Set();
|
|
627
|
+
if (value.version === 1) workspaces.push({
|
|
628
|
+
...createCanvasWorkspace("All pages", "default"),
|
|
629
|
+
positions: parsePositions(value.positions)
|
|
630
|
+
});
|
|
631
|
+
else if (Array.isArray(value.workspaces)) for (const entry of value.workspaces) {
|
|
632
|
+
if (!isRecord(entry) || typeof entry.id !== "string" || !entry.id.trim() || ids.has(entry.id)) continue;
|
|
633
|
+
ids.add(entry.id);
|
|
634
|
+
const configuration = parseCanvasConfiguration(entry.configuration);
|
|
635
|
+
workspaces.push({
|
|
636
|
+
id: entry.id,
|
|
637
|
+
name: typeof entry.name === "string" && entry.name.trim() ? entry.name.trim() : "Workspace",
|
|
638
|
+
enabledPages: Array.isArray(entry.enabledPages) ? [...new Set(entry.enabledPages.filter((id) => typeof id === "string" && id.length > 0))] : null,
|
|
639
|
+
positions: parsePositions(entry.positions),
|
|
640
|
+
...configuration ? { configuration } : {}
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
if (!workspaces.length) workspaces.push(createCanvasWorkspace("All pages", "default"));
|
|
644
|
+
return {
|
|
645
|
+
version: 2,
|
|
646
|
+
workspaces,
|
|
647
|
+
activeWorkspaceId: typeof value.activeWorkspaceId === "string" && workspaces.some((workspace) => workspace.id === value.activeWorkspaceId) ? value.activeWorkspaceId : workspaces[0].id,
|
|
648
|
+
examples,
|
|
649
|
+
breakpoint: typeof value.breakpoint === "string" && value.breakpoint.length > 0 ? value.breakpoint : fallback.breakpoint
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
//#endregion
|
|
653
|
+
//#region src/app-canvas/WorkspaceControls.tsx
|
|
654
|
+
function WorkspaceControls(t0) {
|
|
655
|
+
const $ = c(81);
|
|
656
|
+
const { manifest, setManifest, pages, disabled } = t0;
|
|
657
|
+
const createTrigger = useRef(null);
|
|
658
|
+
const pagesTrigger = useRef(null);
|
|
659
|
+
const editTrigger = useRef(null);
|
|
660
|
+
let t1;
|
|
661
|
+
if ($[0] !== manifest.activeWorkspaceId) {
|
|
662
|
+
t1 = (item) => item.id === manifest.activeWorkspaceId;
|
|
663
|
+
$[0] = manifest.activeWorkspaceId;
|
|
664
|
+
$[1] = t1;
|
|
665
|
+
} else t1 = $[1];
|
|
666
|
+
const workspace = manifest.workspaces.find(t1);
|
|
667
|
+
const [action, setAction] = useState(null);
|
|
668
|
+
const [name, setName] = useState("");
|
|
669
|
+
const [draftPages, setDraftPages] = useState(null);
|
|
670
|
+
const [query, setQuery] = useState("");
|
|
671
|
+
let t2;
|
|
672
|
+
if ($[2] !== setAction) {
|
|
673
|
+
t2 = () => {
|
|
674
|
+
setAction(null);
|
|
675
|
+
};
|
|
676
|
+
$[2] = setAction;
|
|
677
|
+
$[3] = t2;
|
|
678
|
+
} else t2 = $[3];
|
|
679
|
+
useEffect(t2, [workspace.id]);
|
|
680
|
+
let t3;
|
|
681
|
+
if ($[4] !== disabled || $[5] !== setAction) {
|
|
682
|
+
t3 = () => {
|
|
683
|
+
if (disabled) setAction(null);
|
|
684
|
+
};
|
|
685
|
+
$[4] = disabled;
|
|
686
|
+
$[5] = setAction;
|
|
687
|
+
$[6] = t3;
|
|
688
|
+
} else t3 = $[6];
|
|
689
|
+
let t4;
|
|
690
|
+
if ($[7] !== disabled) {
|
|
691
|
+
t4 = [disabled];
|
|
692
|
+
$[7] = disabled;
|
|
693
|
+
$[8] = t4;
|
|
694
|
+
} else t4 = $[8];
|
|
695
|
+
useEffect(t3, t4);
|
|
696
|
+
const open = (next) => {
|
|
697
|
+
setName(next === "create" ? "" : workspace.name);
|
|
698
|
+
setDraftPages(next === "create" ? [] : workspace.enabledPages);
|
|
699
|
+
setQuery("");
|
|
700
|
+
setAction(next);
|
|
701
|
+
};
|
|
702
|
+
let t5;
|
|
703
|
+
if ($[9] !== draftPages) {
|
|
704
|
+
t5 = (id) => draftPages === null || draftPages.includes(id);
|
|
705
|
+
$[9] = draftPages;
|
|
706
|
+
$[10] = t5;
|
|
707
|
+
} else t5 = $[10];
|
|
708
|
+
const enabled = t5;
|
|
709
|
+
const title = action === "create" ? "Create workspace" : action === "rename" ? "Edit workspace" : action === "delete" ? "Delete workspace?" : "Manage pages";
|
|
710
|
+
const save = () => {
|
|
711
|
+
if (disabled || !action) return;
|
|
712
|
+
if ((action === "create" || action === "rename") && !name.trim()) return;
|
|
713
|
+
const created = action === "create" ? {
|
|
714
|
+
...createCanvasWorkspace(name.trim(), crypto.randomUUID()),
|
|
715
|
+
enabledPages: draftPages
|
|
716
|
+
} : null;
|
|
717
|
+
setManifest((current) => {
|
|
718
|
+
if (created) return {
|
|
719
|
+
...current,
|
|
720
|
+
workspaces: [...current.workspaces, created],
|
|
721
|
+
activeWorkspaceId: created.id
|
|
722
|
+
};
|
|
723
|
+
if (action === "delete") {
|
|
724
|
+
if (current.workspaces.length < 2) return current;
|
|
725
|
+
const remaining = current.workspaces.filter((item_0) => item_0.id !== workspace.id);
|
|
726
|
+
return {
|
|
727
|
+
...current,
|
|
728
|
+
workspaces: remaining,
|
|
729
|
+
activeWorkspaceId: remaining[0].id
|
|
730
|
+
};
|
|
731
|
+
}
|
|
732
|
+
return {
|
|
733
|
+
...current,
|
|
734
|
+
workspaces: current.workspaces.map((item_1) => item_1.id === workspace.id ? {
|
|
735
|
+
...item_1,
|
|
736
|
+
...action === "rename" ? { name: name.trim() } : { enabledPages: draftPages }
|
|
737
|
+
} : item_1)
|
|
738
|
+
};
|
|
739
|
+
});
|
|
740
|
+
setAction(null);
|
|
741
|
+
};
|
|
742
|
+
let t6;
|
|
743
|
+
if ($[11] !== query) {
|
|
744
|
+
t6 = (page) => `${page.title} ${page.path}`.toLowerCase().includes(query.toLowerCase());
|
|
745
|
+
$[11] = query;
|
|
746
|
+
$[12] = t6;
|
|
747
|
+
} else t6 = $[12];
|
|
748
|
+
const visiblePages = pages.filter(t6);
|
|
749
|
+
const t7 = workspace.id;
|
|
750
|
+
let t8;
|
|
751
|
+
if ($[13] !== manifest.workspaces) {
|
|
752
|
+
t8 = manifest.workspaces.map(_temp);
|
|
753
|
+
$[13] = manifest.workspaces;
|
|
754
|
+
$[14] = t8;
|
|
755
|
+
} else t8 = $[14];
|
|
756
|
+
let t9;
|
|
757
|
+
if ($[15] !== setManifest) {
|
|
758
|
+
t9 = (id_0) => {
|
|
759
|
+
if (id_0 !== null) setManifest((current_0) => ({
|
|
760
|
+
...current_0,
|
|
761
|
+
activeWorkspaceId: String(id_0)
|
|
762
|
+
}));
|
|
763
|
+
};
|
|
764
|
+
$[15] = setManifest;
|
|
765
|
+
$[16] = t9;
|
|
766
|
+
} else t9 = $[16];
|
|
767
|
+
let t10;
|
|
768
|
+
if ($[17] !== open) {
|
|
769
|
+
t10 = () => open("create");
|
|
770
|
+
$[17] = open;
|
|
771
|
+
$[18] = t10;
|
|
772
|
+
} else t10 = $[18];
|
|
773
|
+
let t11;
|
|
774
|
+
if ($[19] === Symbol.for("react.memo_cache_sentinel")) {
|
|
775
|
+
t11 = /* @__PURE__ */ jsx(Plus, { size: 15 });
|
|
776
|
+
$[19] = t11;
|
|
777
|
+
} else t11 = $[19];
|
|
778
|
+
let t12;
|
|
779
|
+
if ($[20] !== t10) {
|
|
780
|
+
t12 = /* @__PURE__ */ jsx("button", {
|
|
781
|
+
ref: createTrigger,
|
|
782
|
+
"aria-label": "Add workspace",
|
|
783
|
+
title: "Add workspace",
|
|
784
|
+
onClick: t10,
|
|
785
|
+
children: t11
|
|
786
|
+
});
|
|
787
|
+
$[20] = t10;
|
|
788
|
+
$[21] = t12;
|
|
789
|
+
} else t12 = $[21];
|
|
790
|
+
let t13;
|
|
791
|
+
if ($[22] !== open) {
|
|
792
|
+
t13 = () => open("rename");
|
|
793
|
+
$[22] = open;
|
|
794
|
+
$[23] = t13;
|
|
795
|
+
} else t13 = $[23];
|
|
796
|
+
let t14;
|
|
797
|
+
if ($[24] === Symbol.for("react.memo_cache_sentinel")) {
|
|
798
|
+
t14 = /* @__PURE__ */ jsx(Pencil, { size: 14 });
|
|
799
|
+
$[24] = t14;
|
|
800
|
+
} else t14 = $[24];
|
|
801
|
+
let t15;
|
|
802
|
+
if ($[25] !== t13) {
|
|
803
|
+
t15 = /* @__PURE__ */ jsx("button", {
|
|
804
|
+
ref: editTrigger,
|
|
805
|
+
"aria-label": "Rename workspace",
|
|
806
|
+
title: "Edit workspace",
|
|
807
|
+
onClick: t13,
|
|
808
|
+
children: t14
|
|
809
|
+
});
|
|
810
|
+
$[25] = t13;
|
|
811
|
+
$[26] = t15;
|
|
812
|
+
} else t15 = $[26];
|
|
813
|
+
let t16;
|
|
814
|
+
if ($[27] !== open) {
|
|
815
|
+
t16 = () => open("pages");
|
|
816
|
+
$[27] = open;
|
|
817
|
+
$[28] = t16;
|
|
818
|
+
} else t16 = $[28];
|
|
819
|
+
const t17 = pages.filter((page_0) => workspace.enabledPages === null || workspace.enabledPages.includes(page_0.id));
|
|
820
|
+
let t18;
|
|
821
|
+
if ($[29] !== pages.length || $[30] !== t17) {
|
|
822
|
+
t18 = /* @__PURE__ */ jsxs("span", { children: [
|
|
823
|
+
t17.length,
|
|
824
|
+
"/",
|
|
825
|
+
pages.length
|
|
826
|
+
] });
|
|
827
|
+
$[29] = pages.length;
|
|
828
|
+
$[30] = t17;
|
|
829
|
+
$[31] = t18;
|
|
830
|
+
} else t18 = $[31];
|
|
831
|
+
let t19;
|
|
832
|
+
if ($[32] !== t16 || $[33] !== t18) {
|
|
833
|
+
t19 = /* @__PURE__ */ jsx("div", {
|
|
834
|
+
className: "povio-canvas-workspace-actions",
|
|
835
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
836
|
+
ref: pagesTrigger,
|
|
837
|
+
onClick: t16,
|
|
838
|
+
children: [
|
|
839
|
+
"Manage pages",
|
|
840
|
+
" ",
|
|
841
|
+
t18
|
|
842
|
+
]
|
|
843
|
+
})
|
|
844
|
+
});
|
|
845
|
+
$[32] = t16;
|
|
846
|
+
$[33] = t18;
|
|
847
|
+
$[34] = t19;
|
|
848
|
+
} else t19 = $[34];
|
|
849
|
+
const T0 = $542a13ca2fa5b484$export$5b6b19405a83ff9d;
|
|
850
|
+
const t20 = action === "create" ? createTrigger : action === "pages" ? pagesTrigger : editTrigger;
|
|
851
|
+
const t21 = "bottom start";
|
|
852
|
+
const t22 = 6;
|
|
853
|
+
const t23 = "povio-canvas-workspace-popover";
|
|
854
|
+
const t24 = action !== null;
|
|
855
|
+
let t25;
|
|
856
|
+
if ($[35] !== setAction) {
|
|
857
|
+
t25 = (isOpen) => {
|
|
858
|
+
if (!isOpen) setAction(null);
|
|
859
|
+
};
|
|
860
|
+
$[35] = setAction;
|
|
861
|
+
$[36] = t25;
|
|
862
|
+
} else t25 = $[36];
|
|
863
|
+
const T1 = $f2ff30fde7b014be$export$3ddf2d174ce01153;
|
|
864
|
+
const t26 = action === "delete" ? "alertdialog" : "dialog";
|
|
865
|
+
let t27;
|
|
866
|
+
if ($[37] !== save) {
|
|
867
|
+
t27 = (event) => {
|
|
868
|
+
event.preventDefault();
|
|
869
|
+
save();
|
|
870
|
+
};
|
|
871
|
+
$[37] = save;
|
|
872
|
+
$[38] = t27;
|
|
873
|
+
} else t27 = $[38];
|
|
874
|
+
let t28;
|
|
875
|
+
if ($[39] !== title) {
|
|
876
|
+
t28 = /* @__PURE__ */ jsx($2ec61d1d4f780267$export$a8a3e93435678ff9, {
|
|
877
|
+
slot: "title",
|
|
878
|
+
children: title
|
|
879
|
+
});
|
|
880
|
+
$[39] = title;
|
|
881
|
+
$[40] = t28;
|
|
882
|
+
} else t28 = $[40];
|
|
883
|
+
let t29;
|
|
884
|
+
if ($[41] !== setAction) {
|
|
885
|
+
t29 = () => setAction(null);
|
|
886
|
+
$[41] = setAction;
|
|
887
|
+
$[42] = t29;
|
|
888
|
+
} else t29 = $[42];
|
|
889
|
+
let t30;
|
|
890
|
+
if ($[43] === Symbol.for("react.memo_cache_sentinel")) {
|
|
891
|
+
t30 = /* @__PURE__ */ jsx(X, { size: 12 });
|
|
892
|
+
$[43] = t30;
|
|
893
|
+
} else t30 = $[43];
|
|
894
|
+
let t31;
|
|
895
|
+
if ($[44] !== t29) {
|
|
896
|
+
t31 = /* @__PURE__ */ jsx("button", {
|
|
897
|
+
type: "button",
|
|
898
|
+
"aria-label": "Close workspace dialog",
|
|
899
|
+
onClick: t29,
|
|
900
|
+
children: t30
|
|
901
|
+
});
|
|
902
|
+
$[44] = t29;
|
|
903
|
+
$[45] = t31;
|
|
904
|
+
} else t31 = $[45];
|
|
905
|
+
let t32;
|
|
906
|
+
if ($[46] !== t28 || $[47] !== t31) {
|
|
907
|
+
t32 = /* @__PURE__ */ jsxs("header", {
|
|
908
|
+
className: "povio-canvas-workspace-popover-heading",
|
|
909
|
+
children: [t28, t31]
|
|
910
|
+
});
|
|
911
|
+
$[46] = t28;
|
|
912
|
+
$[47] = t31;
|
|
913
|
+
$[48] = t32;
|
|
914
|
+
} else t32 = $[48];
|
|
915
|
+
const t33 = action === "delete" ? /* @__PURE__ */ jsxs("p", { children: [
|
|
916
|
+
"Delete “",
|
|
917
|
+
workspace.name,
|
|
918
|
+
"” and its saved layout and theme?"
|
|
919
|
+
] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [(action === "create" || action === "rename") && /* @__PURE__ */ jsxs("label", { children: ["Workspace name", /* @__PURE__ */ jsx("input", {
|
|
920
|
+
autoFocus: true,
|
|
921
|
+
value: name,
|
|
922
|
+
maxLength: 80,
|
|
923
|
+
placeholder: "Workspace name",
|
|
924
|
+
onChange: (event_0) => setName(event_0.target.value),
|
|
925
|
+
required: true
|
|
926
|
+
})] }), (action === "create" || action === "pages") && /* @__PURE__ */ jsxs("div", {
|
|
927
|
+
role: "group",
|
|
928
|
+
"aria-label": "Enabled pages",
|
|
929
|
+
className: "povio-canvas-popover-pages",
|
|
930
|
+
children: [
|
|
931
|
+
/* @__PURE__ */ jsxs("div", {
|
|
932
|
+
className: "povio-canvas-popover-page-tools",
|
|
933
|
+
children: [
|
|
934
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
935
|
+
pages.filter((page_1) => enabled(page_1.id)).length,
|
|
936
|
+
"/",
|
|
937
|
+
pages.length,
|
|
938
|
+
" pages"
|
|
939
|
+
] }),
|
|
940
|
+
/* @__PURE__ */ jsx("button", {
|
|
941
|
+
type: "button",
|
|
942
|
+
onClick: () => setDraftPages(null),
|
|
943
|
+
children: "Enable all"
|
|
944
|
+
}),
|
|
945
|
+
/* @__PURE__ */ jsx("button", {
|
|
946
|
+
type: "button",
|
|
947
|
+
onClick: () => setDraftPages([]),
|
|
948
|
+
children: "Disable all"
|
|
949
|
+
})
|
|
950
|
+
]
|
|
951
|
+
}),
|
|
952
|
+
/* @__PURE__ */ jsxs("label", {
|
|
953
|
+
className: "povio-canvas-popover-search",
|
|
954
|
+
children: [/* @__PURE__ */ jsx(Search, { size: 12 }), /* @__PURE__ */ jsx("input", {
|
|
955
|
+
"aria-label": "Find workspace pages",
|
|
956
|
+
placeholder: "Find pages…",
|
|
957
|
+
value: query,
|
|
958
|
+
onChange: (event_1) => setQuery(event_1.target.value)
|
|
959
|
+
})]
|
|
960
|
+
}),
|
|
961
|
+
/* @__PURE__ */ jsxs("div", {
|
|
962
|
+
className: "povio-canvas-popover-page-list",
|
|
963
|
+
children: [visiblePages.map((page_2) => /* @__PURE__ */ jsxs("label", { children: [/* @__PURE__ */ jsx("input", {
|
|
964
|
+
type: "checkbox",
|
|
965
|
+
checked: enabled(page_2.id),
|
|
966
|
+
onChange: (event_2) => {
|
|
967
|
+
const ids = draftPages ?? pages.map(_temp2);
|
|
968
|
+
setDraftPages(event_2.target.checked ? [.../* @__PURE__ */ new Set([...ids, page_2.id])] : ids.filter((id_1) => id_1 !== page_2.id));
|
|
969
|
+
}
|
|
970
|
+
}), /* @__PURE__ */ jsx("span", { children: page_2.title })] }, page_2.id)), !visiblePages.length && /* @__PURE__ */ jsx("p", { children: "No matching pages." })]
|
|
971
|
+
})
|
|
972
|
+
]
|
|
973
|
+
})] });
|
|
974
|
+
let t34;
|
|
975
|
+
if ($[49] !== action || $[50] !== manifest.workspaces.length || $[51] !== setAction) {
|
|
976
|
+
t34 = action === "rename" ? /* @__PURE__ */ jsxs("button", {
|
|
977
|
+
type: "button",
|
|
978
|
+
className: "povio-canvas-workspace-delete",
|
|
979
|
+
disabled: manifest.workspaces.length < 2,
|
|
980
|
+
onClick: () => setAction("delete"),
|
|
981
|
+
children: [/* @__PURE__ */ jsx(Trash, { size: 12 }), " Delete workspace"]
|
|
982
|
+
}) : /* @__PURE__ */ jsx("button", {
|
|
983
|
+
type: "button",
|
|
984
|
+
autoFocus: action === "delete",
|
|
985
|
+
onClick: () => action === "delete" ? setAction("rename") : setAction(null),
|
|
986
|
+
children: action === "delete" ? "Back" : "Cancel"
|
|
987
|
+
});
|
|
988
|
+
$[49] = action;
|
|
989
|
+
$[50] = manifest.workspaces.length;
|
|
990
|
+
$[51] = setAction;
|
|
991
|
+
$[52] = t34;
|
|
992
|
+
} else t34 = $[52];
|
|
993
|
+
const t35 = action === "delete" ? "is-danger" : "is-primary";
|
|
994
|
+
let t36;
|
|
995
|
+
if ($[53] !== action || $[54] !== disabled || $[55] !== name) {
|
|
996
|
+
t36 = disabled || (action === "create" || action === "rename") && !name.trim();
|
|
997
|
+
$[53] = action;
|
|
998
|
+
$[54] = disabled;
|
|
999
|
+
$[55] = name;
|
|
1000
|
+
$[56] = t36;
|
|
1001
|
+
} else t36 = $[56];
|
|
1002
|
+
const t37 = action === "create" ? "Create workspace" : action === "rename" ? "Save name" : action === "delete" ? "Delete" : "Save pages";
|
|
1003
|
+
let t38;
|
|
1004
|
+
if ($[57] !== t35 || $[58] !== t36 || $[59] !== t37) {
|
|
1005
|
+
t38 = /* @__PURE__ */ jsx("button", {
|
|
1006
|
+
type: "submit",
|
|
1007
|
+
className: t35,
|
|
1008
|
+
disabled: t36,
|
|
1009
|
+
children: t37
|
|
1010
|
+
});
|
|
1011
|
+
$[57] = t35;
|
|
1012
|
+
$[58] = t36;
|
|
1013
|
+
$[59] = t37;
|
|
1014
|
+
$[60] = t38;
|
|
1015
|
+
} else t38 = $[60];
|
|
1016
|
+
let t39;
|
|
1017
|
+
if ($[61] !== t34 || $[62] !== t38) {
|
|
1018
|
+
t39 = /* @__PURE__ */ jsxs("div", {
|
|
1019
|
+
className: "povio-canvas-workspace-popover-actions",
|
|
1020
|
+
children: [t34, t38]
|
|
1021
|
+
});
|
|
1022
|
+
$[61] = t34;
|
|
1023
|
+
$[62] = t38;
|
|
1024
|
+
$[63] = t39;
|
|
1025
|
+
} else t39 = $[63];
|
|
1026
|
+
let t40;
|
|
1027
|
+
if ($[64] !== t27 || $[65] !== t32 || $[66] !== t33 || $[67] !== t39) {
|
|
1028
|
+
t40 = /* @__PURE__ */ jsxs("form", {
|
|
1029
|
+
onSubmit: t27,
|
|
1030
|
+
children: [
|
|
1031
|
+
t32,
|
|
1032
|
+
t33,
|
|
1033
|
+
t39
|
|
1034
|
+
]
|
|
1035
|
+
});
|
|
1036
|
+
$[64] = t27;
|
|
1037
|
+
$[65] = t32;
|
|
1038
|
+
$[66] = t33;
|
|
1039
|
+
$[67] = t39;
|
|
1040
|
+
$[68] = t40;
|
|
1041
|
+
} else t40 = $[68];
|
|
1042
|
+
let t41;
|
|
1043
|
+
if ($[69] !== T1 || $[70] !== action || $[71] !== t26 || $[72] !== t40 || $[73] !== title) {
|
|
1044
|
+
t41 = /* @__PURE__ */ jsx(T1, {
|
|
1045
|
+
"aria-label": title,
|
|
1046
|
+
role: t26,
|
|
1047
|
+
children: t40
|
|
1048
|
+
}, action);
|
|
1049
|
+
$[69] = T1;
|
|
1050
|
+
$[70] = action;
|
|
1051
|
+
$[71] = t26;
|
|
1052
|
+
$[72] = t40;
|
|
1053
|
+
$[73] = title;
|
|
1054
|
+
$[74] = t41;
|
|
1055
|
+
} else t41 = $[74];
|
|
1056
|
+
let t42;
|
|
1057
|
+
if ($[75] !== T0 || $[76] !== t20 || $[77] !== t24 || $[78] !== t25 || $[79] !== t41) {
|
|
1058
|
+
t42 = /* @__PURE__ */ jsx(T0, {
|
|
1059
|
+
triggerRef: t20,
|
|
1060
|
+
placement: t21,
|
|
1061
|
+
offset: t22,
|
|
1062
|
+
className: t23,
|
|
1063
|
+
isOpen: t24,
|
|
1064
|
+
onOpenChange: t25,
|
|
1065
|
+
children: t41
|
|
1066
|
+
});
|
|
1067
|
+
$[75] = T0;
|
|
1068
|
+
$[76] = t20;
|
|
1069
|
+
$[77] = t24;
|
|
1070
|
+
$[78] = t25;
|
|
1071
|
+
$[79] = t41;
|
|
1072
|
+
$[80] = t42;
|
|
1073
|
+
} else t42 = $[80];
|
|
1074
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("fieldset", {
|
|
1075
|
+
className: "povio-canvas-workspaces",
|
|
1076
|
+
disabled,
|
|
1077
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
1078
|
+
className: "povio-canvas-workspace-picker",
|
|
1079
|
+
children: [
|
|
1080
|
+
/* @__PURE__ */ jsx("div", {
|
|
1081
|
+
className: "povio-canvas-workspace-select",
|
|
1082
|
+
children: /* @__PURE__ */ jsx(Select, {
|
|
1083
|
+
label: "Workspace",
|
|
1084
|
+
hideLabel: true,
|
|
1085
|
+
size: "small",
|
|
1086
|
+
variant: "outlined",
|
|
1087
|
+
as: "default",
|
|
1088
|
+
className: "povio-canvas-workspace-input",
|
|
1089
|
+
selectionMode: "single",
|
|
1090
|
+
isClearable: false,
|
|
1091
|
+
isDisabled: disabled,
|
|
1092
|
+
renderStaticInput: false,
|
|
1093
|
+
value: t7,
|
|
1094
|
+
items: t8,
|
|
1095
|
+
onChange: t9
|
|
1096
|
+
})
|
|
1097
|
+
}),
|
|
1098
|
+
t12,
|
|
1099
|
+
t15
|
|
1100
|
+
]
|
|
1101
|
+
}), t19]
|
|
1102
|
+
}), t42] });
|
|
1103
|
+
}
|
|
1104
|
+
function _temp2(item_3) {
|
|
1105
|
+
return item_3.id;
|
|
1106
|
+
}
|
|
1107
|
+
function _temp(item_2) {
|
|
1108
|
+
return {
|
|
1109
|
+
id: item_2.id,
|
|
1110
|
+
label: item_2.name
|
|
1111
|
+
};
|
|
1112
|
+
}
|
|
1113
|
+
const canvasStorageTokenHeader = "x-povio-canvas-token";
|
|
1114
|
+
//#endregion
|
|
1115
|
+
//#region src/app-canvas/useCanvasStorage.ts
|
|
1116
|
+
function connectionFromDocument() {
|
|
1117
|
+
if (typeof document === "undefined") return null;
|
|
1118
|
+
try {
|
|
1119
|
+
const value = JSON.parse(document.querySelector(`meta[name="povio-ui-canvas-storage"]`)?.content ?? "null");
|
|
1120
|
+
return value && typeof value.endpoint === "string" && value.endpoint.startsWith("/") && !value.endpoint.startsWith("//") && typeof value.token === "string" && typeof value.file === "string" ? value : null;
|
|
1121
|
+
} catch {
|
|
1122
|
+
return null;
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
function localManifest(key) {
|
|
1126
|
+
try {
|
|
1127
|
+
return parseCanvasManifest(localStorage.getItem(key));
|
|
1128
|
+
} catch {
|
|
1129
|
+
return createCanvasManifest();
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
/** Repo is authoritative when connected; local storage remains an offline draft cache. */
|
|
1133
|
+
function useCanvasStorage(key, enabled = true) {
|
|
1134
|
+
const [connection] = useState(() => enabled ? connectionFromDocument() : null);
|
|
1135
|
+
const [manifest, setManifest] = useState(() => localManifest(key));
|
|
1136
|
+
const [ready, setReady] = useState(!connection);
|
|
1137
|
+
const [status, setStatus] = useState(connection ? "Loading workspace…" : "Saved in this browser");
|
|
1138
|
+
const [error, setError] = useState("");
|
|
1139
|
+
const latest = useRef(manifest);
|
|
1140
|
+
latest.current = manifest;
|
|
1141
|
+
const revision = useRef(null);
|
|
1142
|
+
const saved = useRef("");
|
|
1143
|
+
const busy = useRef(false);
|
|
1144
|
+
const paused = useRef(false);
|
|
1145
|
+
const alive = useRef(true);
|
|
1146
|
+
const loadGeneration = useRef(0);
|
|
1147
|
+
useEffect(() => {
|
|
1148
|
+
alive.current = true;
|
|
1149
|
+
return () => {
|
|
1150
|
+
alive.current = false;
|
|
1151
|
+
};
|
|
1152
|
+
}, []);
|
|
1153
|
+
const load = useCallback(async () => {
|
|
1154
|
+
if (!connection) return;
|
|
1155
|
+
const generation = ++loadGeneration.current;
|
|
1156
|
+
setReady(false);
|
|
1157
|
+
setError("");
|
|
1158
|
+
setStatus("Loading workspace…");
|
|
1159
|
+
paused.current = false;
|
|
1160
|
+
try {
|
|
1161
|
+
const response = await fetch(connection.endpoint, {
|
|
1162
|
+
headers: { [canvasStorageTokenHeader]: connection.token },
|
|
1163
|
+
cache: "no-store"
|
|
1164
|
+
});
|
|
1165
|
+
const result = await response.json();
|
|
1166
|
+
if (!response.ok) throw new Error(result.error ?? "Could not read workspace configuration.");
|
|
1167
|
+
if (!alive.current || generation !== loadGeneration.current) return;
|
|
1168
|
+
revision.current = result.revision;
|
|
1169
|
+
if (result.manifest) {
|
|
1170
|
+
const next = parseCanvasManifest(result.manifest);
|
|
1171
|
+
saved.current = JSON.stringify(next);
|
|
1172
|
+
latest.current = next;
|
|
1173
|
+
setManifest(next);
|
|
1174
|
+
} else saved.current = "";
|
|
1175
|
+
setStatus(`Saved to ${connection.file}`);
|
|
1176
|
+
setReady(true);
|
|
1177
|
+
} catch (cause) {
|
|
1178
|
+
if (!alive.current || generation !== loadGeneration.current) return;
|
|
1179
|
+
paused.current = true;
|
|
1180
|
+
setError(cause instanceof Error ? cause.message : "Could not load repository settings.");
|
|
1181
|
+
setStatus("Repository unavailable");
|
|
1182
|
+
setReady(true);
|
|
1183
|
+
}
|
|
1184
|
+
}, [connection]);
|
|
1185
|
+
useEffect(() => {
|
|
1186
|
+
load();
|
|
1187
|
+
}, [load]);
|
|
1188
|
+
const save = useCallback(async () => {
|
|
1189
|
+
if (!connection || busy.current || paused.current || !ready) return;
|
|
1190
|
+
busy.current = true;
|
|
1191
|
+
try {
|
|
1192
|
+
while (alive.current && !paused.current) {
|
|
1193
|
+
const value = latest.current;
|
|
1194
|
+
const serialized = JSON.stringify(value);
|
|
1195
|
+
if (serialized === saved.current) break;
|
|
1196
|
+
setStatus("Saving to repository…");
|
|
1197
|
+
const response_0 = await fetch(connection.endpoint, {
|
|
1198
|
+
method: "POST",
|
|
1199
|
+
headers: {
|
|
1200
|
+
"Content-Type": "application/json",
|
|
1201
|
+
[canvasStorageTokenHeader]: connection.token
|
|
1202
|
+
},
|
|
1203
|
+
body: JSON.stringify({
|
|
1204
|
+
manifest: value,
|
|
1205
|
+
revision: revision.current
|
|
1206
|
+
})
|
|
1207
|
+
});
|
|
1208
|
+
const result_0 = await response_0.json();
|
|
1209
|
+
if (!response_0.ok) throw new Error(response_0.status === 409 ? "Workspace file changed elsewhere. Export your draft, then reload repository settings." : result_0.error ?? "Could not save workspace settings.");
|
|
1210
|
+
revision.current = result_0.revision;
|
|
1211
|
+
saved.current = serialized;
|
|
1212
|
+
}
|
|
1213
|
+
if (alive.current) {
|
|
1214
|
+
setError("");
|
|
1215
|
+
setStatus(`Saved to ${connection.file}`);
|
|
1216
|
+
}
|
|
1217
|
+
} catch (cause_0) {
|
|
1218
|
+
paused.current = true;
|
|
1219
|
+
if (alive.current) {
|
|
1220
|
+
setError(cause_0 instanceof Error ? cause_0.message : "Could not save workspace settings.");
|
|
1221
|
+
setStatus("Workspace not saved to repository");
|
|
1222
|
+
}
|
|
1223
|
+
} finally {
|
|
1224
|
+
busy.current = false;
|
|
1225
|
+
}
|
|
1226
|
+
}, [connection, ready]);
|
|
1227
|
+
useEffect(() => {
|
|
1228
|
+
if (!ready) return;
|
|
1229
|
+
try {
|
|
1230
|
+
localStorage.setItem(key, JSON.stringify(manifest));
|
|
1231
|
+
} catch {
|
|
1232
|
+
if (!connection) setStatus("Browser storage unavailable — export your layout");
|
|
1233
|
+
}
|
|
1234
|
+
if (!connection || paused.current || JSON.stringify(manifest) === saved.current) return;
|
|
1235
|
+
setStatus("Saving to repository…");
|
|
1236
|
+
const timer = setTimeout(() => {
|
|
1237
|
+
save();
|
|
1238
|
+
}, 350);
|
|
1239
|
+
return () => clearTimeout(timer);
|
|
1240
|
+
}, [
|
|
1241
|
+
manifest,
|
|
1242
|
+
key,
|
|
1243
|
+
connection,
|
|
1244
|
+
ready,
|
|
1245
|
+
save
|
|
1246
|
+
]);
|
|
1247
|
+
return {
|
|
1248
|
+
manifest,
|
|
1249
|
+
setManifest,
|
|
1250
|
+
ready,
|
|
1251
|
+
status,
|
|
1252
|
+
error,
|
|
1253
|
+
repositoryFile: connection?.file,
|
|
1254
|
+
reload: load
|
|
1255
|
+
};
|
|
1256
|
+
}
|
|
332
1257
|
//#endregion
|
|
333
1258
|
//#region src/app-canvas/useFrameStartup.ts
|
|
334
1259
|
/** Bound concurrent bootstraps, without unloading any admitted page. */
|
|
@@ -408,7 +1333,7 @@ function labelOf(element) {
|
|
|
408
1333
|
return (element.getAttribute("aria-label") || element.getAttribute("alt") || (!element.children.length ? element.textContent?.trim().replace(/\s+/g, " ") : ""))?.slice(0, 48) || (element.id ? `#${element.id}` : "");
|
|
409
1334
|
}
|
|
410
1335
|
/** Only expanded branches are read and rendered; large pages do not create a second full DOM tree. */
|
|
411
|
-
function PageLayers({ frame, title, selected, onSelect }) {
|
|
1336
|
+
function PageLayers({ frame, title, selected, onSelect, onHover }) {
|
|
412
1337
|
const [root, setRoot] = useState(null);
|
|
413
1338
|
const [, refresh] = useReducer((value) => value + 1, 0);
|
|
414
1339
|
const expanded = useRef(/* @__PURE__ */ new WeakSet());
|
|
@@ -490,7 +1415,13 @@ function PageLayers({ frame, title, selected, onSelect }) {
|
|
|
490
1415
|
"aria-expanded": children.length ? open_0 : void 0,
|
|
491
1416
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
492
1417
|
className: "povio-canvas-layer-row",
|
|
493
|
-
|
|
1418
|
+
onMouseEnter: () => onHover(element_1),
|
|
1419
|
+
onMouseLeave: () => onHover(null),
|
|
1420
|
+
onFocus: () => onHover(element_1),
|
|
1421
|
+
onBlur: (event) => {
|
|
1422
|
+
if (!event.currentTarget.contains(event.relatedTarget)) onHover(null);
|
|
1423
|
+
},
|
|
1424
|
+
style: { paddingLeft: 4 + depth * 10 },
|
|
494
1425
|
children: [children.length ? /* @__PURE__ */ jsx("button", {
|
|
495
1426
|
className: "povio-canvas-layer-toggle",
|
|
496
1427
|
"aria-label": `${open_0 ? "Collapse" : "Expand"} ${element_1.localName}${label ? ` ${label}` : ""}`,
|
|
@@ -500,13 +1431,13 @@ function PageLayers({ frame, title, selected, onSelect }) {
|
|
|
500
1431
|
className: "povio-canvas-layer-select",
|
|
501
1432
|
title: `${element_1.localName}${label ? ` · ${label}` : ""}`,
|
|
502
1433
|
onClick: () => onSelect(element_1),
|
|
503
|
-
onKeyDown: (
|
|
504
|
-
if (
|
|
505
|
-
|
|
1434
|
+
onKeyDown: (event_0) => {
|
|
1435
|
+
if (event_0.key === "ArrowRight" && children.length && !open_0) {
|
|
1436
|
+
event_0.preventDefault();
|
|
506
1437
|
toggle(element_1, false);
|
|
507
1438
|
}
|
|
508
|
-
if (
|
|
509
|
-
|
|
1439
|
+
if (event_0.key === "ArrowLeft" && open_0) {
|
|
1440
|
+
event_0.preventDefault();
|
|
510
1441
|
toggle(element_1, true);
|
|
511
1442
|
}
|
|
512
1443
|
},
|
|
@@ -523,11 +1454,6 @@ function PageLayers({ frame, title, selected, onSelect }) {
|
|
|
523
1454
|
className: "povio-canvas-layers",
|
|
524
1455
|
"aria-label": `Layers for ${title}`,
|
|
525
1456
|
children: [
|
|
526
|
-
/* @__PURE__ */ jsxs("header", { children: [
|
|
527
|
-
/* @__PURE__ */ jsx(CodeXml, { size: 14 }),
|
|
528
|
-
/* @__PURE__ */ jsx("strong", { children: "Layers" }),
|
|
529
|
-
/* @__PURE__ */ jsx("span", { children: title })
|
|
530
|
-
] }),
|
|
531
1457
|
/* @__PURE__ */ jsx("div", {
|
|
532
1458
|
role: "tree",
|
|
533
1459
|
"aria-label": "HTML layers",
|
|
@@ -894,6 +1820,64 @@ function CanvasInspectionOverlay(t0) {
|
|
|
894
1820
|
} else t3 = $[8];
|
|
895
1821
|
return t3;
|
|
896
1822
|
}
|
|
1823
|
+
/** Temporary layer hover never replaces the pinned inspector selection. */
|
|
1824
|
+
function CanvasLayerHighlight(t0) {
|
|
1825
|
+
const $ = c(5);
|
|
1826
|
+
const { element } = t0;
|
|
1827
|
+
const [bounds, setBounds] = useState(null);
|
|
1828
|
+
let t1;
|
|
1829
|
+
let t2;
|
|
1830
|
+
if ($[0] !== element) {
|
|
1831
|
+
t1 = () => {
|
|
1832
|
+
const owner = element.ownerDocument.defaultView;
|
|
1833
|
+
const measure = () => {
|
|
1834
|
+
if (!element.isConnected) {
|
|
1835
|
+
setBounds(null);
|
|
1836
|
+
return;
|
|
1837
|
+
}
|
|
1838
|
+
const rect = element.getBoundingClientRect();
|
|
1839
|
+
setBounds({
|
|
1840
|
+
left: rect.left,
|
|
1841
|
+
top: rect.top,
|
|
1842
|
+
width: rect.width,
|
|
1843
|
+
height: rect.height
|
|
1844
|
+
});
|
|
1845
|
+
};
|
|
1846
|
+
measure();
|
|
1847
|
+
const observer = new ResizeObserver(measure);
|
|
1848
|
+
observer.observe(element);
|
|
1849
|
+
owner?.addEventListener("scroll", measure, true);
|
|
1850
|
+
owner?.addEventListener("resize", measure);
|
|
1851
|
+
return () => {
|
|
1852
|
+
observer.disconnect();
|
|
1853
|
+
owner?.removeEventListener("scroll", measure, true);
|
|
1854
|
+
owner?.removeEventListener("resize", measure);
|
|
1855
|
+
};
|
|
1856
|
+
};
|
|
1857
|
+
t2 = [element];
|
|
1858
|
+
$[0] = element;
|
|
1859
|
+
$[1] = t1;
|
|
1860
|
+
$[2] = t2;
|
|
1861
|
+
} else {
|
|
1862
|
+
t1 = $[1];
|
|
1863
|
+
t2 = $[2];
|
|
1864
|
+
}
|
|
1865
|
+
useLayoutEffect(t1, t2);
|
|
1866
|
+
let t3;
|
|
1867
|
+
if ($[3] !== bounds) {
|
|
1868
|
+
t3 = bounds ? /* @__PURE__ */ jsx("div", {
|
|
1869
|
+
className: "povio-canvas-inspection-overlay povio-canvas-layer-highlight",
|
|
1870
|
+
"aria-hidden": "true",
|
|
1871
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
1872
|
+
className: "studio-hover-outline",
|
|
1873
|
+
style: bounds
|
|
1874
|
+
})
|
|
1875
|
+
}) : null;
|
|
1876
|
+
$[3] = bounds;
|
|
1877
|
+
$[4] = t3;
|
|
1878
|
+
} else t3 = $[4];
|
|
1879
|
+
return t3;
|
|
1880
|
+
}
|
|
897
1881
|
//#endregion
|
|
898
1882
|
//#region src/app-canvas/route-model.ts
|
|
899
1883
|
function joinPath(parent, path) {
|
|
@@ -1072,68 +2056,6 @@ function validConfiguration(value) {
|
|
|
1072
2056
|
}) && !!config.config && typeof config.config === "object";
|
|
1073
2057
|
}
|
|
1074
2058
|
//#endregion
|
|
1075
|
-
//#region src/app-canvas/manifest.ts
|
|
1076
|
-
function createCanvasManifest() {
|
|
1077
|
-
return {
|
|
1078
|
-
version: 1,
|
|
1079
|
-
positions: {},
|
|
1080
|
-
examples: {},
|
|
1081
|
-
manualEdges: [],
|
|
1082
|
-
hiddenEdges: [],
|
|
1083
|
-
breakpoint: "desktop"
|
|
1084
|
-
};
|
|
1085
|
-
}
|
|
1086
|
-
function isRecord(value) {
|
|
1087
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1088
|
-
}
|
|
1089
|
-
function isJSON(value, ancestors = /* @__PURE__ */ new Set(), depth = 0) {
|
|
1090
|
-
if (value === null || typeof value === "string" || typeof value === "boolean") return true;
|
|
1091
|
-
if (typeof value === "number") return Number.isFinite(value);
|
|
1092
|
-
if (typeof value !== "object" || depth > 30 || ancestors.has(value)) return false;
|
|
1093
|
-
ancestors.add(value);
|
|
1094
|
-
const valid = Object.values(value).every((child) => isJSON(child, ancestors, depth + 1));
|
|
1095
|
-
ancestors.delete(value);
|
|
1096
|
-
return valid;
|
|
1097
|
-
}
|
|
1098
|
-
/** Sanitize either stored JSON text or an imported value, retaining valid v1 entries. */
|
|
1099
|
-
function parseCanvasManifest(input) {
|
|
1100
|
-
const fallback = createCanvasManifest();
|
|
1101
|
-
let value = input;
|
|
1102
|
-
if (typeof value === "string") try {
|
|
1103
|
-
value = JSON.parse(value);
|
|
1104
|
-
} catch {
|
|
1105
|
-
return fallback;
|
|
1106
|
-
}
|
|
1107
|
-
if (!isRecord(value) || value.version !== 1) return fallback;
|
|
1108
|
-
const positions = Object.fromEntries(Object.entries(isRecord(value.positions) ? value.positions : {}).flatMap(([breakpoint, entries]) => {
|
|
1109
|
-
if (!isRecord(entries)) return [];
|
|
1110
|
-
return [[breakpoint, Object.fromEntries(Object.entries(entries).flatMap(([id, point]) => isRecord(point) && typeof point.x === "number" && Number.isFinite(point.x) && typeof point.y === "number" && Number.isFinite(point.y) ? [[id, {
|
|
1111
|
-
x: point.x,
|
|
1112
|
-
y: point.y
|
|
1113
|
-
}]] : []))]];
|
|
1114
|
-
}));
|
|
1115
|
-
const examples = Object.fromEntries(Object.entries(isRecord(value.examples) ? value.examples : {}).flatMap(([id, example]) => {
|
|
1116
|
-
if (!isRecord(example)) return [];
|
|
1117
|
-
const clean = {};
|
|
1118
|
-
if (typeof example.title === "string") clean.title = example.title;
|
|
1119
|
-
if (isRecord(example.params)) clean.params = Object.fromEntries(Object.entries(example.params).filter((entry) => typeof entry[1] === "string"));
|
|
1120
|
-
if (isRecord(example.search)) clean.search = Object.fromEntries(Object.entries(example.search).filter(([, item]) => isJSON(item)));
|
|
1121
|
-
return [[id, clean]];
|
|
1122
|
-
}));
|
|
1123
|
-
const manualEdges = (Array.isArray(value.manualEdges) ? value.manualEdges : []).flatMap((edge) => isRecord(edge) && typeof edge.from === "string" && edge.from.length > 0 && typeof edge.to === "string" && edge.to.length > 0 ? [{
|
|
1124
|
-
from: edge.from,
|
|
1125
|
-
to: edge.to
|
|
1126
|
-
}] : []);
|
|
1127
|
-
return {
|
|
1128
|
-
version: 1,
|
|
1129
|
-
positions,
|
|
1130
|
-
examples,
|
|
1131
|
-
manualEdges: [...new Map(manualEdges.map((edge) => [JSON.stringify(edge), edge])).values()],
|
|
1132
|
-
hiddenEdges: [...new Set((Array.isArray(value.hiddenEdges) ? value.hiddenEdges : []).filter((edge) => typeof edge === "string"))],
|
|
1133
|
-
breakpoint: typeof value.breakpoint === "string" && value.breakpoint.length > 0 ? value.breakpoint : fallback.breakpoint
|
|
1134
|
-
};
|
|
1135
|
-
}
|
|
1136
|
-
//#endregion
|
|
1137
2059
|
//#region src/app-canvas/AppCanvas.tsx
|
|
1138
2060
|
const defaultCanvasBreakpoints = [
|
|
1139
2061
|
{
|
|
@@ -1160,14 +2082,6 @@ const emptyExclude = [];
|
|
|
1160
2082
|
/** Zoom per wheel pixel, and the largest delta one wheel event may contribute. */
|
|
1161
2083
|
const ZOOM_SENSITIVITY = .006;
|
|
1162
2084
|
const ZOOM_DELTA_LIMIT = 40;
|
|
1163
|
-
function readManifest(key) {
|
|
1164
|
-
if (typeof window === "undefined") return createCanvasManifest();
|
|
1165
|
-
try {
|
|
1166
|
-
return parseCanvasManifest(localStorage.getItem(key));
|
|
1167
|
-
} catch {
|
|
1168
|
-
return createCanvasManifest();
|
|
1169
|
-
}
|
|
1170
|
-
}
|
|
1171
2085
|
const PageFrame = memo(function PageFrame(t0) {
|
|
1172
2086
|
const $ = c(16);
|
|
1173
2087
|
const { id, src, width, height, name, interact, inspect, onLoad, register } = t0;
|
|
@@ -1216,10 +2130,13 @@ const PageFrame = memo(function PageFrame(t0) {
|
|
|
1216
2130
|
return t6;
|
|
1217
2131
|
});
|
|
1218
2132
|
/** Live route artboards. The camera transforms only the canvas, never the iframe viewport width. */
|
|
1219
|
-
function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, excludePaths = emptyExclude, breakpoints = defaultCanvasBreakpoints, storageKey = "povio-app-canvas", frameUrl, componentsHref }) {
|
|
2133
|
+
function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, excludePaths = emptyExclude, breakpoints = defaultCanvasBreakpoints, storageKey = "povio-app-canvas", frameUrl, componentsHref, repositoryStorage = true }) {
|
|
1220
2134
|
const configuration = useUIConfiguration();
|
|
1221
|
-
const
|
|
2135
|
+
const storage = useCanvasStorage(storageKey, repositoryStorage);
|
|
2136
|
+
const { manifest, setManifest } = storage;
|
|
2137
|
+
const workspace = manifest.workspaces.find((item) => item.id === manifest.activeWorkspaceId);
|
|
1222
2138
|
const [runtime, setRuntime] = useState({});
|
|
2139
|
+
const [hoveredLayer, setHoveredLayer] = useState(null);
|
|
1223
2140
|
const [selected, setSelected] = useState(null);
|
|
1224
2141
|
const [interact, setInteract] = useState(false);
|
|
1225
2142
|
const [inspectMode, setInspectMode] = useState(false);
|
|
@@ -1230,7 +2147,16 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1230
2147
|
const [query, setQuery] = useState("");
|
|
1231
2148
|
const [notice, setNotice] = useState("");
|
|
1232
2149
|
const [documentGeneration, setDocumentGeneration] = useState(0);
|
|
2150
|
+
useWorkspaceConfiguration(workspace, storage.ready, documentGeneration, setManifest);
|
|
1233
2151
|
const [reload, setReload] = useState({});
|
|
2152
|
+
const [showLayers, setShowLayers] = useState(true);
|
|
2153
|
+
useEffect(() => setHoveredLayer(null), [
|
|
2154
|
+
selected,
|
|
2155
|
+
showLayers,
|
|
2156
|
+
manifest.activeWorkspaceId,
|
|
2157
|
+
manifest.breakpoint,
|
|
2158
|
+
documentGeneration
|
|
2159
|
+
]);
|
|
1234
2160
|
const zoomOutput = useRef(null);
|
|
1235
2161
|
const importInput = useRef(null);
|
|
1236
2162
|
const viewport = useRef(null), world = useRef(null);
|
|
@@ -1243,12 +2169,12 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1243
2169
|
}), pendingCamera = useRef(null);
|
|
1244
2170
|
const pointer = useRef(null);
|
|
1245
2171
|
const cameraRevision = useRef(0);
|
|
1246
|
-
const bp = breakpoints.find((
|
|
2172
|
+
const bp = breakpoints.find((item_0) => item_0.id === manifest.breakpoint) ?? breakpoints[breakpoints.length - 1] ?? defaultCanvasBreakpoints[2];
|
|
1247
2173
|
const isKnownToken = useCallback((name) => isEditableToken(name, configuration.defaults), [configuration.defaults]);
|
|
1248
2174
|
const { hostComponents } = configuration;
|
|
1249
2175
|
useEffect(() => hostComponents(), [hostComponents]);
|
|
1250
|
-
const inspector = useCanvasInspector(inspectMode, `${content}:${bp.id}:${documentGeneration}:${JSON.stringify(reload)}`, isKnownToken);
|
|
1251
|
-
const
|
|
2176
|
+
const inspector = useCanvasInspector(inspectMode, `${manifest.activeWorkspaceId}:${content}:${bp.id}:${documentGeneration}:${JSON.stringify(reload)}`, isKnownToken);
|
|
2177
|
+
const allPages = useMemo(() => discoverCanvasPages(router, {
|
|
1252
2178
|
examples: {
|
|
1253
2179
|
...examples,
|
|
1254
2180
|
...manifest.examples
|
|
@@ -1262,6 +2188,11 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1262
2188
|
exclude,
|
|
1263
2189
|
excludePaths
|
|
1264
2190
|
]);
|
|
2191
|
+
const pageCatalog = useMemo(() => storage.ready ? allPages.filter((page) => workspace.enabledPages === null || workspace.enabledPages.includes(page.id)) : [], [
|
|
2192
|
+
allPages,
|
|
2193
|
+
workspace.enabledPages,
|
|
2194
|
+
storage.ready
|
|
2195
|
+
]);
|
|
1265
2196
|
const componentCatalog = useMemo(() => componentsHref ? componentArtboards.map((group) => ({
|
|
1266
2197
|
id: `components:${group.toLowerCase()}`,
|
|
1267
2198
|
title: group,
|
|
@@ -1271,7 +2202,7 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1271
2202
|
kind: "page"
|
|
1272
2203
|
})) : [], [componentsHref]);
|
|
1273
2204
|
const catalog = content === "components" && componentCatalog.length ? componentCatalog : pageCatalog;
|
|
1274
|
-
const startupKeys = useMemo(() => new Map(catalog.filter((
|
|
2205
|
+
const startupKeys = useMemo(() => new Map(catalog.filter((page_0) => page_0.href).map((page_1) => [page_1.id, `${documentGeneration}:${bp.id}:${page_1.id}:${page_1.href}:${reload[page_1.id] ?? 0}`])), [
|
|
1275
2206
|
catalog,
|
|
1276
2207
|
documentGeneration,
|
|
1277
2208
|
bp.id,
|
|
@@ -1286,18 +2217,37 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1286
2217
|
keys: startupKeys,
|
|
1287
2218
|
complete: startup.complete
|
|
1288
2219
|
};
|
|
1289
|
-
const heights = useMemo(() => Object.fromEntries(catalog.map((
|
|
2220
|
+
const heights = useMemo(() => Object.fromEntries(catalog.map((page_2) => [page_2.id, runtime[`${bp.id}:${page_2.id}:${page_2.href ?? ""}`]?.height ?? bp.height])), [
|
|
1290
2221
|
catalog,
|
|
1291
2222
|
runtime,
|
|
1292
2223
|
bp
|
|
1293
2224
|
]);
|
|
1294
|
-
const nodes = useMemo(() => layoutCanvasPages(catalog, bp.width, heights,
|
|
2225
|
+
const nodes = useMemo(() => layoutCanvasPages(catalog, bp.width, heights, workspace.positions[bp.id] ?? {}), [
|
|
1295
2226
|
catalog,
|
|
1296
2227
|
bp,
|
|
1297
2228
|
heights,
|
|
1298
|
-
|
|
2229
|
+
workspace.positions
|
|
1299
2230
|
]);
|
|
1300
2231
|
const nodeMap = useMemo(() => new Map(nodes.map((node) => [node.id, node])), [nodes]);
|
|
2232
|
+
useLayoutEffect(() => {
|
|
2233
|
+
const gesture = pointer.current;
|
|
2234
|
+
if (gesture && viewport.current?.hasPointerCapture(gesture.id)) viewport.current.releasePointerCapture(gesture.id);
|
|
2235
|
+
pointer.current = null;
|
|
2236
|
+
setSelected(null);
|
|
2237
|
+
setQuery("");
|
|
2238
|
+
camera.current = {
|
|
2239
|
+
x: 40,
|
|
2240
|
+
y: 40,
|
|
2241
|
+
zoom: .25
|
|
2242
|
+
};
|
|
2243
|
+
}, [manifest.activeWorkspaceId]);
|
|
2244
|
+
useEffect(() => {
|
|
2245
|
+
if (selected && !nodeMap.has(selected)) setSelected(null);
|
|
2246
|
+
}, [selected, nodeMap]);
|
|
2247
|
+
useEffect(() => {
|
|
2248
|
+
const valid = new Set(catalog.map((page_3) => `${bp.id}:${page_3.id}:${page_3.href ?? ""}`));
|
|
2249
|
+
setRuntime((current) => Object.keys(current).some((key_0) => !valid.has(key_0)) ? Object.fromEntries(Object.entries(current).filter(([key]) => valid.has(key))) : current);
|
|
2250
|
+
}, [catalog, bp.id]);
|
|
1301
2251
|
const latest = useRef({
|
|
1302
2252
|
configuration: configuration.active,
|
|
1303
2253
|
dark,
|
|
@@ -1328,6 +2278,9 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1328
2278
|
const canvas = viewport.current?.closest(".povio-app-canvas");
|
|
1329
2279
|
if (canvas) canvas.setAttribute("data-camera-revision", String(++cameraRevision.current));
|
|
1330
2280
|
}, []);
|
|
2281
|
+
useLayoutEffect(() => {
|
|
2282
|
+
paint();
|
|
2283
|
+
}, [manifest.activeWorkspaceId, paint]);
|
|
1331
2284
|
const schedulePaint = useCallback(() => {
|
|
1332
2285
|
if (pendingCamera.current !== null) return;
|
|
1333
2286
|
pendingCamera.current = requestAnimationFrame(() => {
|
|
@@ -1338,18 +2291,18 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1338
2291
|
const send = useCallback((id_0, type = "configuration") => {
|
|
1339
2292
|
const frame_0 = frames.current.get(id_0);
|
|
1340
2293
|
if (!frame_0?.contentWindow) return;
|
|
1341
|
-
const
|
|
2294
|
+
const current_0 = latest.current;
|
|
1342
2295
|
try {
|
|
1343
2296
|
frame_0.contentWindow.postMessage({
|
|
1344
2297
|
protocol: canvasProtocol,
|
|
1345
2298
|
id: id_0,
|
|
1346
2299
|
token,
|
|
1347
|
-
viewportHeight:
|
|
2300
|
+
viewportHeight: current_0.bp.height,
|
|
1348
2301
|
type,
|
|
1349
|
-
configuration:
|
|
2302
|
+
configuration: current_0.configuration,
|
|
1350
2303
|
revision: revision.current,
|
|
1351
|
-
dark:
|
|
1352
|
-
interact:
|
|
2304
|
+
dark: current_0.dark,
|
|
2305
|
+
interact: current_0.interact
|
|
1353
2306
|
}, new URL(frame_0.src).origin);
|
|
1354
2307
|
} catch {
|
|
1355
2308
|
setNotice("This configuration could not be sent to the page. Check for non-serializable values.");
|
|
@@ -1359,7 +2312,8 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1359
2312
|
const node_0 = nodeMap.get(id_1), view = viewport.current;
|
|
1360
2313
|
if (!node_0 || !view) return;
|
|
1361
2314
|
setSelected(id_1);
|
|
1362
|
-
|
|
2315
|
+
setShowLayers(true);
|
|
2316
|
+
camera.current.zoom = Math.min(1, Math.max(.005, (view.clientWidth - 80) / node_0.width));
|
|
1363
2317
|
camera.current.x = 40 - node_0.x * camera.current.zoom;
|
|
1364
2318
|
camera.current.y = 40 - node_0.y * camera.current.zoom;
|
|
1365
2319
|
paint();
|
|
@@ -1374,18 +2328,18 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1374
2328
|
batch = 0;
|
|
1375
2329
|
const changes = Array.from(queue);
|
|
1376
2330
|
queue.clear();
|
|
1377
|
-
setRuntime((
|
|
1378
|
-
const next = { ...
|
|
2331
|
+
setRuntime((current_1) => {
|
|
2332
|
+
const next = { ...current_1 };
|
|
1379
2333
|
let changed = false;
|
|
1380
|
-
for (const [
|
|
1381
|
-
if (frames.current.get(
|
|
1382
|
-
next[
|
|
1383
|
-
...next[
|
|
1384
|
-
...
|
|
2334
|
+
for (const [key_1, item_1] of changes) {
|
|
2335
|
+
if (frames.current.get(item_1.id) !== item_1.frame || item_1.frame.contentWindow !== item_1.source) continue;
|
|
2336
|
+
next[key_1] = {
|
|
2337
|
+
...next[key_1],
|
|
2338
|
+
...item_1.change
|
|
1385
2339
|
};
|
|
1386
2340
|
changed = true;
|
|
1387
2341
|
}
|
|
1388
|
-
return changed ? next :
|
|
2342
|
+
return changed ? next : current_1;
|
|
1389
2343
|
});
|
|
1390
2344
|
};
|
|
1391
2345
|
const receive = (event) => {
|
|
@@ -1393,7 +2347,7 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1393
2347
|
if (packet?.protocol !== "povio-app-canvas-v1" || packet.token !== token || typeof packet.id !== "string") return;
|
|
1394
2348
|
const frame_1 = frames.current.get(packet.id);
|
|
1395
2349
|
if (!frame_1 || event.source !== frame_1.contentWindow || event.origin !== new URL(frame_1.src).origin) return;
|
|
1396
|
-
const
|
|
2350
|
+
const key_2 = `${latest.current.bp.id}:${packet.id}:${latest.current.catalog.find((page_4) => page_4.id === packet.id)?.href ?? ""}`;
|
|
1397
2351
|
let change = {};
|
|
1398
2352
|
if (packet.type === "ready") {
|
|
1399
2353
|
startupRef.current.complete(startupRef.current.keys.get(packet.id));
|
|
@@ -1415,9 +2369,9 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1415
2369
|
return;
|
|
1416
2370
|
}
|
|
1417
2371
|
if (!Object.keys(change).length) return;
|
|
1418
|
-
const pending = queue.get(
|
|
2372
|
+
const pending = queue.get(key_2);
|
|
1419
2373
|
const previous = pending?.frame === frame_1 && pending.source === event.source ? pending.change : {};
|
|
1420
|
-
queue.set(
|
|
2374
|
+
queue.set(key_2, {
|
|
1421
2375
|
id: packet.id,
|
|
1422
2376
|
frame: frame_1,
|
|
1423
2377
|
source: event.source,
|
|
@@ -1452,19 +2406,13 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1452
2406
|
useEffect(() => {
|
|
1453
2407
|
for (const id_3 of frames.current.keys()) send(id_3, "mode");
|
|
1454
2408
|
}, [interact, send]);
|
|
1455
|
-
useEffect(() => {
|
|
1456
|
-
try {
|
|
1457
|
-
localStorage.setItem(storageKey, JSON.stringify(manifest));
|
|
1458
|
-
} catch {
|
|
1459
|
-
setNotice("Browser storage is unavailable; use Export layout to save this canvas.");
|
|
1460
|
-
}
|
|
1461
|
-
}, [manifest, storageKey]);
|
|
1462
2409
|
useEffect(() => {
|
|
1463
2410
|
paint();
|
|
1464
2411
|
const element = viewport.current;
|
|
1465
2412
|
if (!element) return;
|
|
1466
2413
|
const wheel = (event_0) => {
|
|
1467
2414
|
event_0.preventDefault();
|
|
2415
|
+
if (pointer.current) return;
|
|
1468
2416
|
if (event_0.ctrlKey || event_0.metaKey) {
|
|
1469
2417
|
const box = element.getBoundingClientRect();
|
|
1470
2418
|
const x = event_0.clientX - box.left, y = event_0.clientY - box.top;
|
|
@@ -1534,58 +2482,74 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1534
2482
|
1.5,
|
|
1535
2483
|
2
|
|
1536
2484
|
];
|
|
1537
|
-
const
|
|
1538
|
-
const next_3 = direction === 1 ? stops.find((value_0) => value_0 >
|
|
2485
|
+
const current_2 = camera.current.zoom;
|
|
2486
|
+
const next_3 = direction === 1 ? stops.find((value_0) => value_0 > current_2 + 1e-4) : [...stops].reverse().find((value_1) => value_1 < current_2 - 1e-4);
|
|
1539
2487
|
if (next_3 !== void 0) zoomTo(next_3);
|
|
1540
2488
|
};
|
|
1541
2489
|
const startPan = (event_1) => {
|
|
1542
2490
|
if (inspectMode && event_1.target.closest(".povio-canvas-frame-cover")) return;
|
|
1543
2491
|
if (event_1.button !== 0 || event_1.target.closest("button:not(.povio-canvas-frame-cover),input,select,.povio-canvas-node-header")) return;
|
|
2492
|
+
event_1.preventDefault();
|
|
1544
2493
|
event_1.currentTarget.setPointerCapture(event_1.pointerId);
|
|
1545
2494
|
pointer.current = {
|
|
1546
2495
|
id: event_1.pointerId,
|
|
1547
2496
|
x: event_1.clientX,
|
|
1548
2497
|
y: event_1.clientY,
|
|
2498
|
+
lastX: event_1.clientX,
|
|
2499
|
+
lastY: event_1.clientY,
|
|
1549
2500
|
startX: camera.current.x,
|
|
1550
2501
|
startY: camera.current.y
|
|
1551
2502
|
};
|
|
1552
2503
|
};
|
|
1553
2504
|
const move = (event_2) => {
|
|
1554
|
-
const
|
|
1555
|
-
if (!
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
2505
|
+
const current_3 = pointer.current;
|
|
2506
|
+
if (!current_3 || current_3.id !== event_2.pointerId) return;
|
|
2507
|
+
if (event_2.buttons === 0) {
|
|
2508
|
+
end(event_2, true);
|
|
2509
|
+
return;
|
|
2510
|
+
}
|
|
2511
|
+
current_3.lastX = event_2.clientX;
|
|
2512
|
+
current_3.lastY = event_2.clientY;
|
|
2513
|
+
const dx = event_2.clientX - current_3.x, dy = event_2.clientY - current_3.y;
|
|
2514
|
+
if (current_3.node) {
|
|
2515
|
+
const element_0 = world.current?.querySelector(`[data-node-index="${nodes.findIndex((n_3) => n_3.id === current_3.node)}"]`);
|
|
1559
2516
|
if (element_0) {
|
|
1560
|
-
element_0.style.left = `${
|
|
1561
|
-
element_0.style.top = `${
|
|
2517
|
+
element_0.style.left = `${current_3.nodeX + dx / camera.current.zoom}px`;
|
|
2518
|
+
element_0.style.top = `${current_3.nodeY + dy / camera.current.zoom}px`;
|
|
1562
2519
|
}
|
|
1563
2520
|
} else {
|
|
1564
|
-
camera.current.x =
|
|
1565
|
-
camera.current.y =
|
|
2521
|
+
camera.current.x = current_3.startX + dx;
|
|
2522
|
+
camera.current.y = current_3.startY + dy;
|
|
1566
2523
|
schedulePaint();
|
|
1567
2524
|
}
|
|
1568
2525
|
};
|
|
1569
|
-
const end = (event_3) => {
|
|
1570
|
-
const
|
|
1571
|
-
if (!
|
|
1572
|
-
|
|
2526
|
+
const end = (event_3, useLastPosition = false) => {
|
|
2527
|
+
const current_4 = pointer.current;
|
|
2528
|
+
if (!current_4 || current_4.id !== event_3.pointerId) return;
|
|
2529
|
+
pointer.current = null;
|
|
2530
|
+
if (current_4.node) {
|
|
1573
2531
|
const position = {
|
|
1574
|
-
x:
|
|
1575
|
-
y:
|
|
2532
|
+
x: current_4.nodeX + ((useLastPosition ? current_4.lastX : event_3.clientX) - current_4.x) / camera.current.zoom,
|
|
2533
|
+
y: current_4.nodeY + ((useLastPosition ? current_4.lastY : event_3.clientY) - current_4.y) / camera.current.zoom
|
|
1576
2534
|
};
|
|
1577
2535
|
setManifest((m) => ({
|
|
1578
2536
|
...m,
|
|
1579
|
-
|
|
1580
|
-
...
|
|
1581
|
-
|
|
1582
|
-
...
|
|
1583
|
-
[
|
|
2537
|
+
workspaces: m.workspaces.map((item_2) => item_2.id === m.activeWorkspaceId ? {
|
|
2538
|
+
...item_2,
|
|
2539
|
+
positions: {
|
|
2540
|
+
...item_2.positions,
|
|
2541
|
+
[bp.id]: {
|
|
2542
|
+
...item_2.positions[bp.id],
|
|
2543
|
+
...Object.fromEntries(nodes.map((node_1) => [node_1.id, {
|
|
2544
|
+
x: node_1.x,
|
|
2545
|
+
y: node_1.y
|
|
2546
|
+
}])),
|
|
2547
|
+
[current_4.node]: position
|
|
2548
|
+
}
|
|
1584
2549
|
}
|
|
1585
|
-
}
|
|
2550
|
+
} : item_2)
|
|
1586
2551
|
}));
|
|
1587
2552
|
}
|
|
1588
|
-
pointer.current = null;
|
|
1589
2553
|
if (event_3.currentTarget.hasPointerCapture(event_3.pointerId)) event_3.currentTarget.releasePointerCapture(event_3.pointerId);
|
|
1590
2554
|
};
|
|
1591
2555
|
const onLoad = useCallback((id_4, frame_3) => {
|
|
@@ -1595,12 +2559,12 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1595
2559
|
send(id_4, "mode");
|
|
1596
2560
|
}, [send]);
|
|
1597
2561
|
useEffect(() => {
|
|
1598
|
-
const timer = setTimeout(() => setRuntime((
|
|
1599
|
-
const next_4 = { ...
|
|
1600
|
-
for (const
|
|
1601
|
-
const
|
|
1602
|
-
if (
|
|
1603
|
-
...next_4[
|
|
2562
|
+
const timer = setTimeout(() => setRuntime((current_5) => {
|
|
2563
|
+
const next_4 = { ...current_5 };
|
|
2564
|
+
for (const page_5 of latest.current.catalog) {
|
|
2565
|
+
const key_3 = `${latest.current.bp.id}:${page_5.id}:${page_5.href ?? ""}`;
|
|
2566
|
+
if (page_5.href && frames.current.has(page_5.id) && !next_4[key_3]?.ready) next_4[key_3] = {
|
|
2567
|
+
...next_4[key_3],
|
|
1604
2568
|
timedOut: true
|
|
1605
2569
|
};
|
|
1606
2570
|
}
|
|
@@ -1644,13 +2608,13 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1644
2608
|
if (!file) return;
|
|
1645
2609
|
try {
|
|
1646
2610
|
const raw = JSON.parse(await file.text());
|
|
1647
|
-
if (raw?.version !== 1) throw new Error("version");
|
|
2611
|
+
if (raw?.version !== 1 && raw?.version !== 2) throw new Error("version");
|
|
1648
2612
|
setManifest(parseCanvasManifest(raw));
|
|
1649
2613
|
setRuntime({});
|
|
1650
2614
|
setDocumentGeneration((value_2) => value_2 + 1);
|
|
1651
2615
|
setNotice("Layout imported.");
|
|
1652
2616
|
} catch {
|
|
1653
|
-
setNotice("Choose a valid
|
|
2617
|
+
setNotice("Choose a valid canvas workspace JSON file.");
|
|
1654
2618
|
}
|
|
1655
2619
|
}
|
|
1656
2620
|
}),
|
|
@@ -1661,6 +2625,12 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1661
2625
|
className: "povio-canvas-catalog",
|
|
1662
2626
|
"aria-label": "Page catalog",
|
|
1663
2627
|
children: [
|
|
2628
|
+
/* @__PURE__ */ jsx(WorkspaceControls, {
|
|
2629
|
+
manifest,
|
|
2630
|
+
setManifest,
|
|
2631
|
+
pages: allPages,
|
|
2632
|
+
disabled: !storage.ready
|
|
2633
|
+
}),
|
|
1664
2634
|
/* @__PURE__ */ jsxs("div", {
|
|
1665
2635
|
className: "povio-canvas-brand povio-canvas-content-switch",
|
|
1666
2636
|
role: "group",
|
|
@@ -1699,37 +2669,49 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1699
2669
|
})
|
|
1700
2670
|
]
|
|
1701
2671
|
}),
|
|
1702
|
-
/* @__PURE__ */
|
|
2672
|
+
/* @__PURE__ */ jsx("div", {
|
|
1703
2673
|
className: "povio-canvas-page-list",
|
|
1704
|
-
children:
|
|
1705
|
-
"
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
2674
|
+
children: nodes.filter((node_2) => `${node_2.title} ${node_2.path}`.toLowerCase().includes(query.toLowerCase())).map((node_3) => /* @__PURE__ */ jsxs("div", {
|
|
2675
|
+
className: "povio-canvas-page-entry",
|
|
2676
|
+
children: [/* @__PURE__ */ jsxs("button", {
|
|
2677
|
+
"aria-expanded": node_3.href ? selected === node_3.id && showLayers : void 0,
|
|
2678
|
+
"aria-pressed": selected === node_3.id,
|
|
2679
|
+
onClick: () => {
|
|
2680
|
+
if (selected === node_3.id && showLayers) setShowLayers(false);
|
|
2681
|
+
else focusPage(node_3.id);
|
|
2682
|
+
},
|
|
2683
|
+
children: [node_3.href ? selected === node_3.id && showLayers ? /* @__PURE__ */ jsx(ChevronDown, { size: 12 }) : /* @__PURE__ */ jsx(ChevronRight, { size: 12 }) : /* @__PURE__ */ jsx(Frame, { size: 15 }), /* @__PURE__ */ jsxs("span", {
|
|
2684
|
+
className: "povio-canvas-page-label",
|
|
2685
|
+
children: [/* @__PURE__ */ jsx("strong", { children: node_3.title }), node_3.kind === "unresolved" && /* @__PURE__ */ jsx("small", { children: "Needs parameters" })]
|
|
2686
|
+
})]
|
|
2687
|
+
}), showLayers && selected === node_3.id && node_3.href && /* @__PURE__ */ jsx("div", {
|
|
2688
|
+
className: "povio-canvas-inline-layers",
|
|
2689
|
+
children: /* @__PURE__ */ jsx(PageLayers, {
|
|
2690
|
+
frame: frames.current.get(selected) ?? null,
|
|
2691
|
+
title: nodeMap.get(selected).title,
|
|
2692
|
+
selected: inspector.selection?.pageId === selected ? inspector.selection.element : void 0,
|
|
2693
|
+
onHover: (element_1) => setHoveredLayer(element_1 ? {
|
|
2694
|
+
pageId: node_3.id,
|
|
2695
|
+
element: element_1
|
|
2696
|
+
} : null),
|
|
2697
|
+
onSelect: (element_2) => {
|
|
2698
|
+
setInteract(false);
|
|
2699
|
+
setInspectMode(true);
|
|
2700
|
+
inspector.selectElement(selected, element_2);
|
|
2701
|
+
setMobilePanel(null);
|
|
2702
|
+
requestAnimationFrame(() => {
|
|
2703
|
+
const node_4 = nodeMap.get(selected), view_1 = viewport.current;
|
|
2704
|
+
if (!node_4 || !view_1 || !element_2.isConnected) return;
|
|
2705
|
+
const rect = element_2.getBoundingClientRect();
|
|
2706
|
+
camera.current.zoom = Math.min(camera.current.zoom, Math.max(.005, (view_1.clientWidth - 80) / node_4.width));
|
|
2707
|
+
camera.current.x = 40 - node_4.x * camera.current.zoom;
|
|
2708
|
+
camera.current.y = view_1.clientHeight / 2 - (node_4.y + 48 + rect.top + rect.height / 2) * camera.current.zoom;
|
|
2709
|
+
paint();
|
|
2710
|
+
});
|
|
2711
|
+
}
|
|
2712
|
+
}, `${bp.id}:${documentGeneration}:${reload[selected] ?? 0}:${selected}:${nodeMap.get(selected)?.href}`)
|
|
1713
2713
|
})]
|
|
1714
|
-
},
|
|
1715
|
-
frame: frames.current.get(selected) ?? null,
|
|
1716
|
-
title: nodeMap.get(selected).title,
|
|
1717
|
-
selected: inspector.selection?.pageId === selected ? inspector.selection.element : void 0,
|
|
1718
|
-
onSelect: (element_1) => {
|
|
1719
|
-
setInteract(false);
|
|
1720
|
-
setInspectMode(true);
|
|
1721
|
-
inspector.selectElement(selected, element_1);
|
|
1722
|
-
setMobilePanel(null);
|
|
1723
|
-
requestAnimationFrame(() => {
|
|
1724
|
-
const node_3 = nodeMap.get(selected), view_1 = viewport.current;
|
|
1725
|
-
if (!node_3 || !view_1 || !element_1.isConnected) return;
|
|
1726
|
-
const rect = element_1.getBoundingClientRect();
|
|
1727
|
-
camera.current.x = view_1.clientWidth / 2 - (node_3.x + rect.left + rect.width / 2) * camera.current.zoom;
|
|
1728
|
-
camera.current.y = view_1.clientHeight / 2 - (node_3.y + 48 + rect.top + rect.height / 2) * camera.current.zoom;
|
|
1729
|
-
paint();
|
|
1730
|
-
});
|
|
1731
|
-
}
|
|
1732
|
-
}, `${bp.id}:${documentGeneration}:${reload[selected] ?? 0}:${selected}:${nodeMap.get(selected)?.href}`)]
|
|
2714
|
+
}, node_3.id))
|
|
1733
2715
|
}),
|
|
1734
2716
|
/* @__PURE__ */ jsxs("div", {
|
|
1735
2717
|
className: "povio-canvas-sidebar-actions",
|
|
@@ -1762,6 +2744,22 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1762
2744
|
]
|
|
1763
2745
|
})
|
|
1764
2746
|
]
|
|
2747
|
+
}),
|
|
2748
|
+
/* @__PURE__ */ jsxs("div", {
|
|
2749
|
+
className: "povio-canvas-storage-status",
|
|
2750
|
+
role: "status",
|
|
2751
|
+
children: [
|
|
2752
|
+
storage.status,
|
|
2753
|
+
/* @__PURE__ */ jsx(SaveCanvasTheme, {}),
|
|
2754
|
+
storage.error && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("p", { children: storage.error }), /* @__PURE__ */ jsx("button", {
|
|
2755
|
+
onClick: () => {
|
|
2756
|
+
setRuntime({});
|
|
2757
|
+
setDocumentGeneration((value_3) => value_3 + 1);
|
|
2758
|
+
storage.reload();
|
|
2759
|
+
},
|
|
2760
|
+
children: "Reload repository settings"
|
|
2761
|
+
})] })
|
|
2762
|
+
]
|
|
1765
2763
|
})
|
|
1766
2764
|
]
|
|
1767
2765
|
}),
|
|
@@ -1777,18 +2775,8 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1777
2775
|
onPointerDown: startPan,
|
|
1778
2776
|
onPointerMove: move,
|
|
1779
2777
|
onPointerUp: end,
|
|
1780
|
-
onPointerCancel: (event_7) =>
|
|
1781
|
-
|
|
1782
|
-
if (current_5?.node) {
|
|
1783
|
-
const element_2 = world.current?.querySelector(`[data-node-index="${nodes.findIndex((node_4) => node_4.id === current_5.node)}"]`);
|
|
1784
|
-
if (element_2) {
|
|
1785
|
-
element_2.style.left = `${current_5.nodeX}px`;
|
|
1786
|
-
element_2.style.top = `${current_5.nodeY}px`;
|
|
1787
|
-
}
|
|
1788
|
-
}
|
|
1789
|
-
pointer.current = null;
|
|
1790
|
-
if (event_7.currentTarget.hasPointerCapture(event_7.pointerId)) event_7.currentTarget.releasePointerCapture(event_7.pointerId);
|
|
1791
|
-
},
|
|
2778
|
+
onPointerCancel: (event_7) => end(event_7, true),
|
|
2779
|
+
onLostPointerCapture: (event_8) => end(event_8, true),
|
|
1792
2780
|
children: [
|
|
1793
2781
|
/* @__PURE__ */ jsx("div", {
|
|
1794
2782
|
className: "povio-canvas-mobile-tools",
|
|
@@ -1834,14 +2822,18 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1834
2822
|
children: [
|
|
1835
2823
|
/* @__PURE__ */ jsxs("header", {
|
|
1836
2824
|
className: "povio-canvas-node-header",
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
2825
|
+
onDragStart: (event_9) => event_9.preventDefault(),
|
|
2826
|
+
onPointerDown: (event_10) => {
|
|
2827
|
+
if (event_10.button !== 0 || event_10.target.closest("button")) return;
|
|
2828
|
+
event_10.preventDefault();
|
|
2829
|
+
event_10.stopPropagation();
|
|
2830
|
+
viewport.current?.setPointerCapture(event_10.pointerId);
|
|
1841
2831
|
pointer.current = {
|
|
1842
|
-
id:
|
|
1843
|
-
x:
|
|
1844
|
-
y:
|
|
2832
|
+
id: event_10.pointerId,
|
|
2833
|
+
x: event_10.clientX,
|
|
2834
|
+
y: event_10.clientY,
|
|
2835
|
+
lastX: event_10.clientX,
|
|
2836
|
+
lastY: event_10.clientY,
|
|
1845
2837
|
startX: 0,
|
|
1846
2838
|
startY: 0,
|
|
1847
2839
|
node: node_5.id,
|
|
@@ -1880,12 +2872,12 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1880
2872
|
}),
|
|
1881
2873
|
!node_5.href ? /* @__PURE__ */ jsxs("form", {
|
|
1882
2874
|
className: "povio-canvas-unresolved",
|
|
1883
|
-
onSubmit: (
|
|
1884
|
-
|
|
1885
|
-
const form = new FormData(
|
|
1886
|
-
const enteredParams = Object.fromEntries(node_5.missingParams.map((
|
|
1887
|
-
const
|
|
1888
|
-
return [
|
|
2875
|
+
onSubmit: (event_11) => {
|
|
2876
|
+
event_11.preventDefault();
|
|
2877
|
+
const form = new FormData(event_11.currentTarget);
|
|
2878
|
+
const enteredParams = Object.fromEntries(node_5.missingParams.map((key_4) => {
|
|
2879
|
+
const value_4 = form.get(key_4);
|
|
2880
|
+
return [key_4, typeof value_4 === "string" ? value_4 : ""];
|
|
1889
2881
|
}));
|
|
1890
2882
|
setManifest((m_0) => ({
|
|
1891
2883
|
...m_0,
|
|
@@ -1906,10 +2898,10 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1906
2898
|
children: [
|
|
1907
2899
|
/* @__PURE__ */ jsx("strong", { children: "Route needs parameters" }),
|
|
1908
2900
|
/* @__PURE__ */ jsx("code", { children: node_5.path }),
|
|
1909
|
-
node_5.missingParams.map((
|
|
1910
|
-
name:
|
|
2901
|
+
node_5.missingParams.map((key_5) => /* @__PURE__ */ jsxs("label", { children: [key_5, /* @__PURE__ */ jsx("input", {
|
|
2902
|
+
name: key_5,
|
|
1911
2903
|
required: true
|
|
1912
|
-
})] },
|
|
2904
|
+
})] }, key_5)),
|
|
1913
2905
|
/* @__PURE__ */ jsx("button", { children: "Render page" })
|
|
1914
2906
|
]
|
|
1915
2907
|
}) : originError ? /* @__PURE__ */ jsx("p", {
|
|
@@ -1940,25 +2932,26 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1940
2932
|
className: "povio-canvas-frame-cover",
|
|
1941
2933
|
tabIndex: 0,
|
|
1942
2934
|
"aria-label": `Select ${node_5.title}`,
|
|
1943
|
-
onKeyDown: (
|
|
1944
|
-
if (
|
|
1945
|
-
|
|
2935
|
+
onKeyDown: (event_12) => {
|
|
2936
|
+
if (event_12.key === "Enter" || event_12.key === " ") {
|
|
2937
|
+
event_12.preventDefault();
|
|
1946
2938
|
setSelected(node_5.id);
|
|
1947
2939
|
}
|
|
1948
2940
|
},
|
|
1949
|
-
onPointerMove: (
|
|
2941
|
+
onPointerMove: (event_13) => {
|
|
1950
2942
|
const frame_4 = frames.current.get(node_5.id);
|
|
1951
|
-
if (frame_4) inspector.hover(node_5.id, frame_4,
|
|
2943
|
+
if (frame_4) inspector.hover(node_5.id, frame_4, event_13.clientX, event_13.clientY);
|
|
1952
2944
|
},
|
|
1953
|
-
onPointerDown: (
|
|
2945
|
+
onPointerDown: (event_14) => {
|
|
1954
2946
|
setSelected(node_5.id);
|
|
1955
2947
|
if (inspectMode) {
|
|
1956
2948
|
const frame_5 = frames.current.get(node_5.id);
|
|
1957
|
-
if (frame_5) inspector.select(node_5.id, frame_5,
|
|
2949
|
+
if (frame_5) inspector.select(node_5.id, frame_5, event_14.clientX, event_14.clientY);
|
|
1958
2950
|
}
|
|
1959
2951
|
},
|
|
1960
2952
|
onClick: () => setSelected(node_5.id)
|
|
1961
2953
|
}),
|
|
2954
|
+
hoveredLayer?.pageId === node_5.id && /* @__PURE__ */ jsx(CanvasLayerHighlight, { element: hoveredLayer.element }),
|
|
1962
2955
|
inspectMode && inspector.selection?.pageId === node_5.id && inspector.measurement && /* @__PURE__ */ jsx(CanvasInspectionOverlay, {
|
|
1963
2956
|
measurement: inspector.measurement,
|
|
1964
2957
|
width: node_5.width
|
|
@@ -1976,6 +2969,10 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
1976
2969
|
}, node_5.id);
|
|
1977
2970
|
})
|
|
1978
2971
|
}),
|
|
2972
|
+
!nodes.length && /* @__PURE__ */ jsx("div", {
|
|
2973
|
+
className: "povio-canvas-empty",
|
|
2974
|
+
children: storage.ready ? "Enable pages in this workspace to start arranging your canvas." : "Loading workspace…"
|
|
2975
|
+
}),
|
|
1979
2976
|
/* @__PURE__ */ jsxs("div", {
|
|
1980
2977
|
className: "povio-canvas-tool-dock",
|
|
1981
2978
|
children: [
|
|
@@ -2021,10 +3018,13 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
2021
3018
|
"aria-label": "Auto layout",
|
|
2022
3019
|
onClick: () => setManifest((m_1) => ({
|
|
2023
3020
|
...m_1,
|
|
2024
|
-
|
|
2025
|
-
...
|
|
2026
|
-
|
|
2027
|
-
|
|
3021
|
+
workspaces: m_1.workspaces.map((item_3) => item_3.id === m_1.activeWorkspaceId ? {
|
|
3022
|
+
...item_3,
|
|
3023
|
+
positions: {
|
|
3024
|
+
...item_3.positions,
|
|
3025
|
+
[bp.id]: {}
|
|
3026
|
+
}
|
|
3027
|
+
} : item_3)
|
|
2028
3028
|
})),
|
|
2029
3029
|
children: [/* @__PURE__ */ jsx(PanelsTopLeft, { size: 17 }), /* @__PURE__ */ jsx("span", { children: "Auto layout" })]
|
|
2030
3030
|
})
|
|
@@ -2048,29 +3048,33 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
|
|
|
2048
3048
|
title: "Toggle page theme",
|
|
2049
3049
|
children: dark ? /* @__PURE__ */ jsx(Moon, { size: 16 }) : /* @__PURE__ */ jsx(Sun, { size: 16 })
|
|
2050
3050
|
}),
|
|
2051
|
-
/* @__PURE__ */
|
|
2052
|
-
className: "povio-canvas-breakpoint",
|
|
2053
|
-
children:
|
|
2054
|
-
|
|
3051
|
+
/* @__PURE__ */ jsx("div", {
|
|
3052
|
+
className: "povio-canvas-breakpoint povio-canvas-workspace-select",
|
|
3053
|
+
children: /* @__PURE__ */ jsx(Select, {
|
|
3054
|
+
label: "Canvas breakpoint",
|
|
3055
|
+
hideLabel: true,
|
|
3056
|
+
size: "small",
|
|
3057
|
+
variant: "outlined",
|
|
3058
|
+
as: "default",
|
|
3059
|
+
className: "povio-canvas-workspace-input",
|
|
3060
|
+
selectionMode: "single",
|
|
3061
|
+
isClearable: false,
|
|
3062
|
+
renderStaticInput: false,
|
|
3063
|
+
leadingContent: /* @__PURE__ */ jsx(Monitor, { size: 15 }),
|
|
2055
3064
|
value: bp.id,
|
|
2056
|
-
|
|
2057
|
-
|
|
3065
|
+
items: breakpoints.map((item_4) => ({
|
|
3066
|
+
id: item_4.id,
|
|
3067
|
+
label: `${item_4.label} · ${item_4.width}px`
|
|
3068
|
+
})),
|
|
3069
|
+
onChange: (id_5) => {
|
|
3070
|
+
if (id_5 === null || id_5 === bp.id) return;
|
|
2058
3071
|
setRuntime({});
|
|
2059
3072
|
setManifest((m_2) => ({
|
|
2060
3073
|
...m_2,
|
|
2061
|
-
breakpoint:
|
|
3074
|
+
breakpoint: String(id_5)
|
|
2062
3075
|
}));
|
|
2063
|
-
}
|
|
2064
|
-
|
|
2065
|
-
value: item_1.id,
|
|
2066
|
-
children: [
|
|
2067
|
-
item_1.label,
|
|
2068
|
-
" · ",
|
|
2069
|
-
item_1.width,
|
|
2070
|
-
"px"
|
|
2071
|
-
]
|
|
2072
|
-
}, item_1.id))
|
|
2073
|
-
})]
|
|
3076
|
+
}
|
|
3077
|
+
})
|
|
2074
3078
|
}),
|
|
2075
3079
|
/* @__PURE__ */ jsx("span", { className: "povio-canvas-dock-divider" }),
|
|
2076
3080
|
/* @__PURE__ */ jsx("button", {
|
|
@@ -2407,10 +3411,10 @@ function AppCanvasFrameBridge({ href }) {
|
|
|
2407
3411
|
const APP_CANVAS_PATH = "/_canvas";
|
|
2408
3412
|
/** Must match `componentsFrameParam`; kept inline so the canvas page does not load the gallery eagerly. */
|
|
2409
3413
|
const componentsParam = "povio-components";
|
|
2410
|
-
const CanvasComponentsFrame = lazy(() => import("./CanvasComponentsFrame-
|
|
3414
|
+
const CanvasComponentsFrame = lazy(() => import("./CanvasComponentsFrame-CZXY0Dxi.js"));
|
|
2411
3415
|
/** Ready-made route page. Mount beneath the app's UIConfigurationProvider. */
|
|
2412
3416
|
function AppCanvasPage(t0) {
|
|
2413
|
-
const $ = c(
|
|
3417
|
+
const $ = c(24);
|
|
2414
3418
|
let excludePaths;
|
|
2415
3419
|
let props;
|
|
2416
3420
|
let t1;
|
|
@@ -2426,72 +3430,88 @@ function AppCanvasPage(t0) {
|
|
|
2426
3430
|
t1 = $[3];
|
|
2427
3431
|
}
|
|
2428
3432
|
const canvasPath = t1 === void 0 ? APP_CANVAS_PATH : t1;
|
|
3433
|
+
const updateTheme = ThemeContext.useTheme()?.updateTheme;
|
|
2429
3434
|
let t2;
|
|
2430
|
-
if ($[4] !== excludePaths) {
|
|
2431
|
-
t2 = excludePaths ?? [];
|
|
2432
|
-
$[4] = excludePaths;
|
|
2433
|
-
$[5] = t2;
|
|
2434
|
-
} else t2 = $[5];
|
|
2435
3435
|
let t3;
|
|
2436
|
-
if ($[
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
3436
|
+
if ($[4] !== updateTheme) {
|
|
3437
|
+
t2 = () => {
|
|
3438
|
+
if (!isAppCanvasFrame()) updateTheme?.("light");
|
|
3439
|
+
};
|
|
3440
|
+
t3 = [updateTheme];
|
|
3441
|
+
$[4] = updateTheme;
|
|
3442
|
+
$[5] = t2;
|
|
3443
|
+
$[6] = t3;
|
|
3444
|
+
} else {
|
|
3445
|
+
t2 = $[5];
|
|
3446
|
+
t3 = $[6];
|
|
3447
|
+
}
|
|
3448
|
+
useEffect(t2, t3);
|
|
2442
3449
|
let t4;
|
|
2443
|
-
if ($[
|
|
2444
|
-
t4 = [
|
|
2445
|
-
$[
|
|
3450
|
+
if ($[7] !== excludePaths) {
|
|
3451
|
+
t4 = excludePaths ?? [];
|
|
3452
|
+
$[7] = excludePaths;
|
|
3453
|
+
$[8] = t4;
|
|
3454
|
+
} else t4 = $[8];
|
|
3455
|
+
let t5;
|
|
3456
|
+
if ($[9] !== canvasPath || $[10] !== t4) {
|
|
3457
|
+
t5 = /* @__PURE__ */ new Set([...t4, canvasPath]);
|
|
3458
|
+
$[9] = canvasPath;
|
|
2446
3459
|
$[10] = t4;
|
|
2447
|
-
|
|
2448
|
-
|
|
3460
|
+
$[11] = t5;
|
|
3461
|
+
} else t5 = $[11];
|
|
3462
|
+
let t6;
|
|
3463
|
+
if ($[12] !== t5) {
|
|
3464
|
+
t6 = [...t5];
|
|
3465
|
+
$[12] = t5;
|
|
3466
|
+
$[13] = t6;
|
|
3467
|
+
} else t6 = $[13];
|
|
3468
|
+
const exclusions = t6;
|
|
2449
3469
|
if (isAppCanvasFrame()) {
|
|
2450
|
-
let
|
|
2451
|
-
if ($[
|
|
3470
|
+
let t7;
|
|
3471
|
+
if ($[14] === Symbol.for("react.memo_cache_sentinel")) {
|
|
2452
3472
|
const group = new URLSearchParams(window.location.search).get(componentsParam);
|
|
2453
|
-
|
|
3473
|
+
t7 = group ? /* @__PURE__ */ jsx(Suspense, {
|
|
2454
3474
|
fallback: null,
|
|
2455
3475
|
children: /* @__PURE__ */ jsx(CanvasComponentsFrame, { group })
|
|
2456
3476
|
}) : null;
|
|
2457
|
-
$[
|
|
2458
|
-
} else
|
|
2459
|
-
return
|
|
3477
|
+
$[14] = t7;
|
|
3478
|
+
} else t7 = $[14];
|
|
3479
|
+
return t7;
|
|
2460
3480
|
}
|
|
2461
|
-
let
|
|
2462
|
-
if ($[
|
|
2463
|
-
|
|
2464
|
-
$[
|
|
2465
|
-
$[
|
|
2466
|
-
} else
|
|
2467
|
-
let
|
|
2468
|
-
if ($[
|
|
2469
|
-
|
|
3481
|
+
let t7;
|
|
3482
|
+
if ($[15] !== canvasPath) {
|
|
3483
|
+
t7 = (group_0) => `${canvasPath}?${componentsParam}=${encodeURIComponent(group_0)}`;
|
|
3484
|
+
$[15] = canvasPath;
|
|
3485
|
+
$[16] = t7;
|
|
3486
|
+
} else t7 = $[16];
|
|
3487
|
+
let t8;
|
|
3488
|
+
if ($[17] !== exclusions || $[18] !== props || $[19] !== t7) {
|
|
3489
|
+
t8 = /* @__PURE__ */ jsx(AppCanvas, {
|
|
2470
3490
|
...props,
|
|
2471
3491
|
excludePaths: exclusions,
|
|
2472
|
-
componentsHref:
|
|
3492
|
+
componentsHref: t7
|
|
2473
3493
|
});
|
|
2474
|
-
$[
|
|
2475
|
-
$[
|
|
2476
|
-
$[
|
|
2477
|
-
$[
|
|
2478
|
-
} else
|
|
2479
|
-
let
|
|
2480
|
-
if ($[
|
|
2481
|
-
|
|
2482
|
-
$[
|
|
2483
|
-
} else
|
|
2484
|
-
let
|
|
2485
|
-
if ($[
|
|
2486
|
-
|
|
3494
|
+
$[17] = exclusions;
|
|
3495
|
+
$[18] = props;
|
|
3496
|
+
$[19] = t7;
|
|
3497
|
+
$[20] = t8;
|
|
3498
|
+
} else t8 = $[20];
|
|
3499
|
+
let t9;
|
|
3500
|
+
if ($[21] === Symbol.for("react.memo_cache_sentinel")) {
|
|
3501
|
+
t9 = /* @__PURE__ */ jsx(UIConfigurationModal, {});
|
|
3502
|
+
$[21] = t9;
|
|
3503
|
+
} else t9 = $[21];
|
|
3504
|
+
let t10;
|
|
3505
|
+
if ($[22] !== t8) {
|
|
3506
|
+
t10 = /* @__PURE__ */ jsxs("div", {
|
|
2487
3507
|
className: "povio-app-canvas-page",
|
|
2488
3508
|
"aria-label": "App canvas page",
|
|
2489
|
-
children: [
|
|
3509
|
+
children: [t8, t9]
|
|
2490
3510
|
});
|
|
2491
|
-
$[
|
|
2492
|
-
$[
|
|
2493
|
-
} else
|
|
2494
|
-
return
|
|
3511
|
+
$[22] = t8;
|
|
3512
|
+
$[23] = t10;
|
|
3513
|
+
} else t10 = $[23];
|
|
3514
|
+
return t10;
|
|
2495
3515
|
}
|
|
2496
3516
|
//#endregion
|
|
2497
3517
|
export { defaultCanvasBreakpoints as a, layoutCanvasPages as c, AppCanvas as i, AppCanvasPage as n, isAppCanvasFrame as o, AppCanvasFrameBridge as r, discoverCanvasPages as s, APP_CANVAS_PATH as t };
|