@povio/ui 5.0.0-rc.14 → 5.0.0-rc.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/{AppCanvasPage-vta1j5YQ.js → AppCanvasPage-BnyCHO3I.js} +139 -456
  2. package/dist/{AppCanvasPage-BZ2mrKY4.d.ts → AppCanvasPage-U9SxNwjS.d.ts} +1 -1
  3. package/dist/{BottomSheet-BXLE3161.js → BottomSheet-AqYVSMK9.js} +1 -75
  4. package/dist/BottomSheetHeader-Be6Elvs2.js +79 -0
  5. package/dist/{Calendar-DRHruqr_.js → Calendar-1p3VjSED.js} +3 -3
  6. package/dist/{CanvasComponentsFrame-D6Mh_G3q.js → CanvasComponentsFrame-Dp0oDDoH.js} +6 -6
  7. package/dist/{UIConfigurator-CjAW1SJY.js → CanvasInspector-DdP3mHUY.js} +1314 -474
  8. package/dist/{ComponentGallery-CzKU899_.js → ComponentGallery-C_rXFvUY.js} +250 -1797
  9. package/dist/{DatePicker-xDEqzNJv.js → DatePicker-CAzuZRmd.js} +6 -6
  10. package/dist/{DatePickerInput-B0fEeCOf.js → DatePickerInput-BeQOVCk0.js} +4 -3
  11. package/dist/{DateRangePicker-DxuVhRaf.js → DateRangePicker-X3mBhfmL.js} +5 -5
  12. package/dist/{DateTimePicker-4N1Pka07.js → DateTimePicker-EtmGtoRe.js} +6 -6
  13. package/dist/{InputItem-Cv19Hwnx.js → InputItem-yC5oMyN-.js} +7 -7
  14. package/dist/{Inputs-D1aE_J9f.js → Inputs-Bd2nRNqk.js} +1 -1
  15. package/dist/{NumberRangeInput-Bzfe-RlV.js → NumberRangeInput-TkPXiWV3.js} +2 -2
  16. package/dist/{RichTextEditor-Bd7F5D8f.js → RichTextEditor-DiaPcBUM.js} +110 -32
  17. package/dist/{Select-CgIhoWgk.js → Select-tNlFSbAC.js} +5 -5
  18. package/dist/{Table-piX1SWvN.js → Table-CgG02oHQ.js} +1 -1
  19. package/dist/{TextArea-uPffb457.js → TextArea-DuvFUjts.js} +1 -1
  20. package/dist/{TimePicker-DN-i98z5.js → TimePicker-CBkiE-Yq.js} +5 -4
  21. package/dist/{TooltipWrapper-CDHFaUKZ.js → TooltipWrapper-CSXs5-E3.js} +2 -2
  22. package/dist/components/autocomplete.js +3 -3
  23. package/dist/components/bottom-sheet.js +1 -1
  24. package/dist/components/date-picker.js +1 -1
  25. package/dist/components/date-range-picker.js +1 -1
  26. package/dist/components/date-time-picker.js +1 -1
  27. package/dist/components/input.js +3 -3
  28. package/dist/components/number-field.js +3 -3
  29. package/dist/components/number-range-input.js +1 -1
  30. package/dist/components/query-autocomplete.js +1 -1
  31. package/dist/components/query-select.js +2 -2
  32. package/dist/components/select.js +1 -1
  33. package/dist/components/text-area.js +1 -1
  34. package/dist/components/time-picker.js +1 -1
  35. package/dist/config/app-canvas-tanstack.d.ts +1 -1
  36. package/dist/config/app-canvas-tanstack.js +1 -1
  37. package/dist/config/app-canvas.d.ts +1 -1
  38. package/dist/config/app-canvas.js +1 -1
  39. package/dist/config/ui-configurator.d.ts +21 -2
  40. package/dist/config/ui-configurator.js +121 -3
  41. package/dist/{datePickerValue.utils-QWR2q5Vv.js → datePickerValue.utils-BDB6KM8q.js} +1 -1
  42. package/dist/demos-DIwj5vc0.js +2011 -0
  43. package/dist/index.js +7 -7
  44. package/dist/{logger-CqZjM-sn.js → logger-CW24po62.js} +10 -1
  45. package/dist/rhf/date-picker.js +1 -1
  46. package/dist/rhf/date-range-picker.js +1 -1
  47. package/dist/rhf/date-time-picker.js +1 -1
  48. package/dist/rhf/number-range-input.js +1 -1
  49. package/dist/rhf/rich-text-editor.js +1 -1
  50. package/dist/rhf/select.js +1 -1
  51. package/dist/rhf/text-area.js +1 -1
  52. package/dist/rhf/time-picker.js +1 -1
  53. package/dist/rhf.js +7 -7
  54. package/dist/rich-text-editor.js +1 -1
  55. package/dist/{staticDateTimeSegments-BWea3HAt.js → staticDateTimeSegments-Bs1_N5MR.js} +1 -1
  56. package/dist/{staticSelect.utils-BfTCi26B.js → staticSelect.utils-BgdYv2vP.js} +5 -4
  57. package/dist/styles/app-canvas.css +30 -24
  58. package/dist/styles/configurator.css +342 -34
  59. package/dist/tanstack/date-picker.js +1 -1
  60. package/dist/tanstack/date-range-picker.js +1 -1
  61. package/dist/tanstack/date-time-picker.js +1 -1
  62. package/dist/tanstack/form.js +1 -1
  63. package/dist/tanstack/inputs.js +1 -1
  64. package/dist/tanstack/number-range-input.js +1 -1
  65. package/dist/tanstack/rich-text-editor.js +1 -1
  66. package/dist/tanstack/select.js +1 -1
  67. package/dist/tanstack/table.js +2 -2
  68. package/dist/tanstack/text-area.js +1 -1
  69. package/dist/tanstack/time-picker.js +1 -1
  70. package/dist/tanstack.js +15 -15
  71. package/dist/token-classes-BqLWiy6O.js +245 -0
  72. package/dist/{useFieldAccessibility-B-bjtrNw.js → useFieldAccessibility-DnCdz938.js} +2 -1
  73. package/dist/{useFormAutosave-pmh35PXp.js → useFormAutosave-CxqZAJAB.js} +1 -1
  74. package/dist/{useStaticInputHandoff-B7DEm75m.js → useStaticInputHandoff-DKsxpVck.js} +2 -1
  75. package/dist/{useTableColumnConfig-CNJ_ZvIN.js → useTableColumnConfig-BnbKElno.js} +1 -1
  76. package/dist/utils/logger.js +1 -1
  77. package/package.json +1 -1
  78. package/dist/groups-oQmSeqXn.js +0 -18
  79. package/dist/underline-66hmELxa.js +0 -81
@@ -1,5 +1,5 @@
1
1
  import { t as createLucideIcon } from "./createLucideIcon-LcezOE4z.js";
2
- import { _ as Moon, a as inspectElement, c as HighlightOverlay, d as useUIConfiguration, f as Trash, g as Pencil, h as Pin, l as InspectorDetails, m as Plus, p as Sun, r as useRepositoryStorage, s as getBoxHighlights, t as UIConfigurationModal } from "./UIConfigurator-CjAW1SJY.js";
2
+ import { a as UIConfigurationModal, d as Trash, f as Sun, h as Moon, i as useCanvasInspector, m as Pencil, n as CanvasInspectorPanel, p as Plus, r as CanvasLayerHighlight, s as useRepositoryStorage, t as CanvasInspectionOverlay, u as useUIConfiguration } from "./CanvasInspector-DdP3mHUY.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";
@@ -7,10 +7,9 @@ import { t as Upload } from "./upload-CXU83BJ4.js";
7
7
  import { t as X } from "./x-B6vfz8Ps.js";
8
8
  import { c as $542a13ca2fa5b484$export$5b6b19405a83ff9d, n as $f2ff30fde7b014be$export$3ddf2d174ce01153 } from "./Dialog-CKLkS00H.js";
9
9
  import { t as $2ec61d1d4f780267$export$a8a3e93435678ff9 } from "./Heading-nI1_VOaE.js";
10
- import { t as Select } from "./Select-CgIhoWgk.js";
10
+ import { t as Select } from "./Select-tNlFSbAC.js";
11
11
  import { t as ThemeContext } from "./theme.context-B3wQDJ-i.js";
12
12
  import { c as isEditableToken } from "./theme-model-DtTsIxou.js";
13
- import { t as componentArtboards } from "./groups-oQmSeqXn.js";
14
13
  import { Suspense, lazy, memo, useCallback, useEffect, useLayoutEffect, useMemo, useReducer, useRef, useState } from "react";
15
14
  import { c } from "react/compiler-runtime";
16
15
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -1186,415 +1185,58 @@ function PageLayers({ frame, title, selected, onSelect, onHover }) {
1186
1185
  ]
1187
1186
  });
1188
1187
  }
1189
- //#endregion
1190
- //#region src/app-canvas/CanvasInspector.tsx
1191
- /** Inspect the live iframe DOM using its own, unscaled viewport coordinates. */
1192
- function useCanvasInspector(enabled, generation, isKnown) {
1193
- const [selection, setSelection] = useState(null);
1194
- const [measurement, setMeasurement] = useState(null);
1195
- const [pinned, setPinned] = useState(false);
1196
- const [highlightKey, setHighlightKey] = useState(null);
1197
- const hoverFrame = useRef(null);
1198
- const pending = useRef(null);
1199
- const clear = useCallback(() => {
1200
- if (hoverFrame.current !== null) cancelAnimationFrame(hoverFrame.current);
1201
- hoverFrame.current = null;
1202
- pending.current = null;
1203
- setSelection(null);
1204
- setMeasurement(null);
1205
- setPinned(false);
1206
- setHighlightKey(null);
1207
- }, []);
1208
- useEffect(() => {
1209
- if (!enabled) clear();
1210
- }, [enabled, clear]);
1211
- useEffect(() => {
1212
- clear();
1213
- }, [generation, clear]);
1214
- useEffect(() => () => {
1215
- if (hoverFrame.current !== null) cancelAnimationFrame(hoverFrame.current);
1216
- }, []);
1217
- const pick = useCallback((pageId, frame, clientX, clientY, pin) => {
1218
- if (!enabled || pinned && !pin) return;
1219
- const bounds = frame.getBoundingClientRect();
1220
- if (!bounds.width || !bounds.height) return;
1221
- try {
1222
- const doc = frame.contentDocument;
1223
- if (!doc) return;
1224
- const x = (clientX - bounds.left) * frame.clientWidth / bounds.width;
1225
- const y = (clientY - bounds.top) * frame.clientHeight / bounds.height;
1226
- const hit = doc.elementFromPoint(x, y);
1227
- const element = hit?.closest("button,input,textarea,select,a,label,[role],h1,h2,h3,h4,h5,h6,p") ?? hit;
1228
- if (!element || element === doc.documentElement || element === doc.body || element.namespaceURI !== "http://www.w3.org/1999/xhtml") return;
1229
- const target = element;
1230
- setSelection((current) => current?.element === target ? current : {
1231
- pageId,
1232
- element: target
1233
- });
1234
- setHighlightKey(null);
1235
- if (pin) setPinned((current_0) => !(current_0 && selection?.element === target));
1236
- } catch {
1237
- clear();
1238
- }
1239
- }, [
1240
- enabled,
1241
- pinned,
1242
- selection,
1243
- clear
1244
- ]);
1245
- const hover = useCallback((pageId_0, frame_0, x_0, y_0) => {
1246
- if (!enabled || pinned) return;
1247
- pending.current = () => pick(pageId_0, frame_0, x_0, y_0, false);
1248
- if (hoverFrame.current !== null) return;
1249
- hoverFrame.current = requestAnimationFrame(() => {
1250
- hoverFrame.current = null;
1251
- pending.current?.();
1252
- pending.current = null;
1188
+ const gap = 64;
1189
+ const header = 48;
1190
+ const titleSpace = 72;
1191
+ const sectionGap = 192;
1192
+ /**
1193
+ * Lays component artboards out by section: a title, then rows of up to four columns. Saved positions win, so
1194
+ * artboards a person dragged stay where they put them.
1195
+ */
1196
+ function layoutComponentArtboards(pages, heights, positions = {}) {
1197
+ const rowWidth = 1872;
1198
+ const nodes = [];
1199
+ const sections = [];
1200
+ const order = [...new Set(pages.map((page) => page.section))];
1201
+ let y = 0;
1202
+ for (const section of order) {
1203
+ sections.push({
1204
+ title: section,
1205
+ x: 0,
1206
+ y: y + titleSpace - 12
1253
1207
  });
1254
- }, [
1255
- enabled,
1256
- pinned,
1257
- pick
1258
- ]);
1259
- const select = useCallback((pageId_1, frame_1, x_1, y_1) => {
1260
- if (hoverFrame.current !== null) cancelAnimationFrame(hoverFrame.current);
1261
- hoverFrame.current = null;
1262
- pending.current = null;
1263
- pick(pageId_1, frame_1, x_1, y_1, true);
1264
- }, [pick]);
1265
- useEffect(() => {
1266
- if (!enabled || !selection) return;
1267
- const { element: element_0 } = selection;
1268
- const doc_0 = element_0.ownerDocument;
1269
- const owner = doc_0.defaultView;
1270
- if (!owner) return;
1271
- let scheduled = null;
1272
- const measure = () => {
1273
- scheduled = null;
1274
- if (!element_0.isConnected) {
1275
- clear();
1276
- return;
1277
- }
1278
- const rect = element_0.getBoundingClientRect();
1279
- const snapshot = inspectElement(element_0, isKnown);
1280
- const details = highlightKey ? getBoxHighlights(element_0, highlightKey) : null;
1281
- const spacing = highlightKey ? [] : [
1282
- "padding.top",
1283
- "padding.right",
1284
- "padding.bottom",
1285
- "padding.left",
1286
- "margin.top",
1287
- "margin.right",
1288
- "margin.bottom",
1289
- "margin.left",
1290
- "gap.row",
1291
- "gap.column"
1292
- ].flatMap((key) => {
1293
- const [kind, side] = key.split(".");
1294
- const raw = kind === "padding" ? snapshot.box.padding[side] : kind === "margin" ? snapshot.box.margin[side] : snapshot.box.gap[side];
1295
- if (!(Math.abs(Number.parseFloat(raw)) > 0)) return [];
1296
- const details_0 = getBoxHighlights(element_0, key);
1297
- const regions = details_0.regions.filter((region) => region.width > 0 && region.height > 0);
1298
- return regions.length ? [{
1299
- key,
1300
- label: details_0.label,
1301
- regions
1302
- }] : [];
1303
- });
1304
- if (!highlightKey) {
1305
- const seen = new Set(spacing.flatMap((item) => item.regions.map((region_0) => `${item.key}:${region_0.left}:${region_0.top}:${region_0.width}:${region_0.height}`)));
1306
- for (const child of Array.from(element_0.children).slice(0, 80)) {
1307
- if (child.namespaceURI !== "http://www.w3.org/1999/xhtml" || !child.getClientRects().length) continue;
1308
- const style = owner.getComputedStyle(child);
1309
- if (style.display === "none" || style.visibility === "hidden" || /^(absolute|fixed)$/.test(style.position)) continue;
1310
- for (const side_0 of [
1311
- "top",
1312
- "right",
1313
- "bottom",
1314
- "left"
1315
- ]) {
1316
- if (!(Math.abs(Number.parseFloat(style.getPropertyValue(`margin-${side_0}`))) > 0)) continue;
1317
- const key_0 = `margin.${side_0}`;
1318
- const details_1 = getBoxHighlights(child, key_0);
1319
- const regions_0 = details_1.regions.filter((region_1) => {
1320
- const id = `${key_0}:${region_1.left}:${region_1.top}:${region_1.width}:${region_1.height}`;
1321
- if (seen.has(id)) return false;
1322
- seen.add(id);
1323
- return region_1.width > 0 && region_1.height > 0;
1324
- });
1325
- if (regions_0.length) spacing.push({
1326
- key: key_0,
1327
- label: details_1.label,
1328
- regions: regions_0
1329
- });
1330
- }
1331
- }
1208
+ y += titleSpace;
1209
+ let x = 0;
1210
+ let rowHeight = 0;
1211
+ for (const page of pages.filter((item) => item.section === section)) {
1212
+ const width = page.wide ? 904 : 420;
1213
+ if (x > 0 && x + width > rowWidth) {
1214
+ y += rowHeight + gap;
1215
+ x = 0;
1216
+ rowHeight = 0;
1332
1217
  }
1333
- const next = {
1334
- snapshot,
1335
- spacing,
1336
- outline: {
1337
- left: rect.left,
1338
- top: rect.top,
1339
- width: rect.width,
1340
- height: rect.height
1341
- },
1342
- highlight: details && highlightKey ? {
1343
- key: highlightKey,
1344
- ...details
1345
- } : null
1218
+ const measured = heights[page.id];
1219
+ const height = Number.isFinite(measured) && measured > 0 ? measured : 240;
1220
+ const saved = positions[page.id];
1221
+ const position = saved && Number.isFinite(saved.x) && Number.isFinite(saved.y) ? saved : {
1222
+ x,
1223
+ y
1346
1224
  };
1347
- setMeasurement((current_1) => JSON.stringify(current_1) === JSON.stringify(next) ? current_1 : next);
1348
- };
1349
- const schedule = () => {
1350
- if (scheduled === null) scheduled = requestAnimationFrame(measure);
1351
- };
1352
- const mutations = new MutationObserver(schedule);
1353
- mutations.observe(doc_0.documentElement, {
1354
- subtree: true,
1355
- childList: true,
1356
- attributes: true,
1357
- characterData: true
1358
- });
1359
- const resize = new ResizeObserver(schedule);
1360
- resize.observe(element_0);
1361
- owner.addEventListener("scroll", schedule, true);
1362
- measure();
1363
- return () => {
1364
- mutations.disconnect();
1365
- resize.disconnect();
1366
- owner.removeEventListener("scroll", schedule, true);
1367
- if (scheduled !== null) cancelAnimationFrame(scheduled);
1368
- };
1369
- }, [
1370
- enabled,
1371
- selection,
1372
- highlightKey,
1373
- clear,
1374
- isKnown
1375
- ]);
1376
- return {
1377
- selection,
1378
- selectElement: (pageId_2, element_1) => {
1379
- setSelection({
1380
- pageId: pageId_2,
1381
- element: element_1
1225
+ nodes.push({
1226
+ ...page,
1227
+ ...position,
1228
+ width,
1229
+ height
1382
1230
  });
1383
- setPinned(true);
1384
- setHighlightKey(null);
1385
- },
1386
- measurement,
1387
- pinned,
1388
- hover,
1389
- select,
1390
- clear,
1391
- highlight: setHighlightKey,
1392
- togglePin: () => setPinned((value) => !value)
1393
- };
1394
- }
1395
- function CanvasInspectorPanel(t0) {
1396
- const $ = c(22);
1397
- const { inspector, onClose, onSelectToken } = t0;
1398
- let t1;
1399
- if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
1400
- t1 = /* @__PURE__ */ jsx("strong", { children: "Inspector view" });
1401
- $[0] = t1;
1402
- } else t1 = $[0];
1403
- const t2 = !inspector.selection;
1404
- let t3;
1405
- if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
1406
- t3 = /* @__PURE__ */ jsx(Pin, { size: 14 });
1407
- $[1] = t3;
1408
- } else t3 = $[1];
1409
- let t4;
1410
- if ($[2] !== inspector.pinned || $[3] !== inspector.togglePin || $[4] !== t2) {
1411
- t4 = /* @__PURE__ */ jsx("button", {
1412
- "aria-label": "Pin inspected element",
1413
- "aria-pressed": inspector.pinned,
1414
- disabled: t2,
1415
- onClick: inspector.togglePin,
1416
- children: t3
1417
- });
1418
- $[2] = inspector.pinned;
1419
- $[3] = inspector.togglePin;
1420
- $[4] = t2;
1421
- $[5] = t4;
1422
- } else t4 = $[5];
1423
- let t5;
1424
- if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
1425
- t5 = /* @__PURE__ */ jsx(X, { size: 15 });
1426
- $[6] = t5;
1427
- } else t5 = $[6];
1428
- let t6;
1429
- if ($[7] !== onClose) {
1430
- t6 = /* @__PURE__ */ jsx("button", {
1431
- "aria-label": "Close inspector view",
1432
- onClick: onClose,
1433
- children: t5
1434
- });
1435
- $[7] = onClose;
1436
- $[8] = t6;
1437
- } else t6 = $[8];
1438
- let t7;
1439
- if ($[9] !== t4 || $[10] !== t6) {
1440
- t7 = /* @__PURE__ */ jsxs("header", { children: [
1441
- t1,
1442
- t4,
1443
- t6
1444
- ] });
1445
- $[9] = t4;
1446
- $[10] = t6;
1447
- $[11] = t7;
1448
- } else t7 = $[11];
1449
- const t8 = inspector.pinned ? "Selection pinned · click it again to unpin" : "Hover a component · click to pin";
1450
- let t9;
1451
- if ($[12] !== t8) {
1452
- t9 = /* @__PURE__ */ jsx("p", {
1453
- className: "povio-canvas-inspect-hint",
1454
- children: t8
1455
- });
1456
- $[12] = t8;
1457
- $[13] = t9;
1458
- } else t9 = $[13];
1459
- let t10;
1460
- if ($[14] !== inspector.highlight || $[15] !== inspector.measurement || $[16] !== onSelectToken) {
1461
- t10 = inspector.measurement ? /* @__PURE__ */ jsx(InspectorDetails, {
1462
- snapshot: inspector.measurement.snapshot,
1463
- onSelect: onSelectToken,
1464
- onHighlight: inspector.highlight
1465
- }) : /* @__PURE__ */ jsx("p", {
1466
- className: "povio-canvas-inspect-hint",
1467
- children: "Inspect a live page to see its padding, margins, borders, radii and gaps."
1468
- });
1469
- $[14] = inspector.highlight;
1470
- $[15] = inspector.measurement;
1471
- $[16] = onSelectToken;
1472
- $[17] = t10;
1473
- } else t10 = $[17];
1474
- let t11;
1475
- if ($[18] !== t10 || $[19] !== t7 || $[20] !== t9) {
1476
- t11 = /* @__PURE__ */ jsxs("aside", {
1477
- className: "studio-inspector-panel povio-canvas-inspector",
1478
- "aria-label": "Inspector view",
1479
- children: [
1480
- t7,
1481
- t9,
1482
- t10
1483
- ]
1484
- });
1485
- $[18] = t10;
1486
- $[19] = t7;
1487
- $[20] = t9;
1488
- $[21] = t11;
1489
- } else t11 = $[21];
1490
- return t11;
1491
- }
1492
- function CanvasInspectionOverlay(t0) {
1493
- const $ = c(9);
1494
- const { measurement, width } = t0;
1495
- let t1;
1496
- if ($[0] !== measurement.outline) {
1497
- t1 = /* @__PURE__ */ jsx("div", {
1498
- className: "studio-hover-outline",
1499
- style: measurement.outline
1500
- });
1501
- $[0] = measurement.outline;
1502
- $[1] = t1;
1503
- } else t1 = $[1];
1504
- let t2;
1505
- if ($[2] !== measurement.highlight || $[3] !== measurement.spacing || $[4] !== width) {
1506
- t2 = measurement.highlight ? /* @__PURE__ */ jsx(HighlightOverlay, {
1507
- highlight: measurement.highlight,
1508
- width
1509
- }) : measurement.spacing.map((highlight) => /* @__PURE__ */ jsxs("div", {
1510
- className: "povio-canvas-auto-spacing",
1511
- children: [/* @__PURE__ */ jsx(HighlightOverlay, {
1512
- highlight,
1513
- width
1514
- }), highlight.regions.map((region) => /* @__PURE__ */ jsx("span", {
1515
- className: "povio-canvas-spacing-value",
1516
- style: {
1517
- left: region.left + region.width / 2,
1518
- top: region.top + region.height / 2
1519
- },
1520
- children: highlight.label.split(": ")[1]
1521
- }, `${region.left}:${region.top}:${region.width}:${region.height}`))]
1522
- }, `${highlight.key}:${highlight.label}:${highlight.regions[0]?.left}:${highlight.regions[0]?.top}`));
1523
- $[2] = measurement.highlight;
1524
- $[3] = measurement.spacing;
1525
- $[4] = width;
1526
- $[5] = t2;
1527
- } else t2 = $[5];
1528
- let t3;
1529
- if ($[6] !== t1 || $[7] !== t2) {
1530
- t3 = /* @__PURE__ */ jsxs("div", {
1531
- className: "povio-canvas-inspection-overlay",
1532
- "aria-hidden": "true",
1533
- children: [t1, t2]
1534
- });
1535
- $[6] = t1;
1536
- $[7] = t2;
1537
- $[8] = t3;
1538
- } else t3 = $[8];
1539
- return t3;
1540
- }
1541
- /** Temporary layer hover never replaces the pinned inspector selection. */
1542
- function CanvasLayerHighlight(t0) {
1543
- const $ = c(5);
1544
- const { element } = t0;
1545
- const [bounds, setBounds] = useState(null);
1546
- let t1;
1547
- let t2;
1548
- if ($[0] !== element) {
1549
- t1 = () => {
1550
- const owner = element.ownerDocument.defaultView;
1551
- const measure = () => {
1552
- if (!element.isConnected) {
1553
- setBounds(null);
1554
- return;
1555
- }
1556
- const rect = element.getBoundingClientRect();
1557
- setBounds({
1558
- left: rect.left,
1559
- top: rect.top,
1560
- width: rect.width,
1561
- height: rect.height
1562
- });
1563
- };
1564
- measure();
1565
- const observer = new ResizeObserver(measure);
1566
- observer.observe(element);
1567
- owner?.addEventListener("scroll", measure, true);
1568
- owner?.addEventListener("resize", measure);
1569
- return () => {
1570
- observer.disconnect();
1571
- owner?.removeEventListener("scroll", measure, true);
1572
- owner?.removeEventListener("resize", measure);
1573
- };
1574
- };
1575
- t2 = [element];
1576
- $[0] = element;
1577
- $[1] = t1;
1578
- $[2] = t2;
1579
- } else {
1580
- t1 = $[1];
1581
- t2 = $[2];
1231
+ x += width + gap;
1232
+ rowHeight = Math.max(rowHeight, header + height);
1233
+ }
1234
+ y += rowHeight + sectionGap;
1582
1235
  }
1583
- useLayoutEffect(t1, t2);
1584
- let t3;
1585
- if ($[3] !== bounds) {
1586
- t3 = bounds ? /* @__PURE__ */ jsx("div", {
1587
- className: "povio-canvas-inspection-overlay povio-canvas-layer-highlight",
1588
- "aria-hidden": "true",
1589
- children: /* @__PURE__ */ jsx("div", {
1590
- className: "studio-hover-outline",
1591
- style: bounds
1592
- })
1593
- }) : null;
1594
- $[3] = bounds;
1595
- $[4] = t3;
1596
- } else t3 = $[4];
1597
- return t3;
1236
+ return {
1237
+ nodes,
1238
+ sections
1239
+ };
1598
1240
  }
1599
1241
  //#endregion
1600
1242
  //#region src/app-canvas/route-model.ts
@@ -1861,6 +1503,23 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
1861
1503
  const [dark, setDark] = useState(false);
1862
1504
  /** The canvas shows either the app's pages or the component gallery's sections, as artboards either way. */
1863
1505
  const [content, setContent] = useState("pages");
1506
+ /** Gallery components (names and sections only); the demos themselves render inside their frames. */
1507
+ const [componentList, setComponentList] = useState([]);
1508
+ useEffect(() => {
1509
+ if (!componentsHref) return;
1510
+ let cancelled = false;
1511
+ import("./demos-DIwj5vc0.js").then((n) => n.n).then(({ demos }) => {
1512
+ if (!cancelled) setComponentList(demos.map(({ id, title, group, wide }) => ({
1513
+ id,
1514
+ title,
1515
+ section: group,
1516
+ wide
1517
+ })));
1518
+ });
1519
+ return () => {
1520
+ cancelled = true;
1521
+ };
1522
+ }, [componentsHref]);
1864
1523
  const [mobilePanel, setMobilePanel] = useState(null);
1865
1524
  const [query, setQuery] = useState("");
1866
1525
  const [notice, setNotice] = useState("");
@@ -1910,15 +1569,20 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
1910
1569
  workspace.enabledPages,
1911
1570
  storage.ready
1912
1571
  ]);
1913
- const componentCatalog = useMemo(() => componentsHref ? componentArtboards.map((group) => ({
1914
- id: `components:${group.toLowerCase()}`,
1915
- title: group,
1916
- path: group,
1917
- href: componentsHref(group),
1572
+ const componentCatalog = useMemo(() => componentsHref ? componentList.map((component) => ({
1573
+ id: `component:${component.id}`,
1574
+ title: component.title,
1575
+ path: component.section,
1576
+ section: component.section,
1577
+ wide: component.wide,
1578
+ href: componentsHref(component.id),
1918
1579
  missingParams: [],
1919
1580
  kind: "page"
1920
- })) : [], [componentsHref]);
1921
- const catalog = content === "components" && componentCatalog.length ? componentCatalog : pageCatalog;
1581
+ })) : [], [componentsHref, componentList]);
1582
+ const showingComponents = content === "components" && componentCatalog.length > 0;
1583
+ const catalog = showingComponents ? componentCatalog : pageCatalog;
1584
+ /** Components are measured from a short frame; pages start at the breakpoint's viewport height. */
1585
+ const frameViewportHeight = showingComponents ? 240 : bp.height;
1922
1586
  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}`])), [
1923
1587
  catalog,
1924
1588
  documentGeneration,
@@ -1934,12 +1598,21 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
1934
1598
  keys: startupKeys,
1935
1599
  complete: startup.complete
1936
1600
  };
1937
- const heights = useMemo(() => Object.fromEntries(catalog.map((page_2) => [page_2.id, runtime[`${bp.id}:${page_2.id}:${page_2.href ?? ""}`]?.height ?? bp.height])), [
1601
+ const heights = useMemo(() => Object.fromEntries(catalog.map((page_2) => [page_2.id, runtime[`${bp.id}:${page_2.id}:${page_2.href ?? ""}`]?.height ?? frameViewportHeight])), [
1938
1602
  catalog,
1939
1603
  runtime,
1940
- bp
1604
+ bp,
1605
+ frameViewportHeight
1941
1606
  ]);
1942
- const nodes = useMemo(() => layoutCanvasPages(catalog, bp.width, heights, workspace.positions[bp.id] ?? {}), [
1607
+ const { nodes, sections } = useMemo(() => {
1608
+ const positions = workspace.positions[bp.id] ?? {};
1609
+ return showingComponents ? layoutComponentArtboards(componentCatalog, heights, positions) : {
1610
+ nodes: layoutCanvasPages(catalog, bp.width, heights, positions),
1611
+ sections: []
1612
+ };
1613
+ }, [
1614
+ showingComponents,
1615
+ componentCatalog,
1943
1616
  catalog,
1944
1617
  bp,
1945
1618
  heights,
@@ -1965,25 +1638,28 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
1965
1638
  const valid = new Set(catalog.map((page_3) => `${bp.id}:${page_3.id}:${page_3.href ?? ""}`));
1966
1639
  setRuntime((current) => Object.keys(current).some((key_0) => !valid.has(key_0)) ? Object.fromEntries(Object.entries(current).filter(([key]) => valid.has(key))) : current);
1967
1640
  }, [catalog, bp.id]);
1641
+ const frameInteract = interact || showingComponents && !inspectMode;
1968
1642
  const latest = useRef({
1969
1643
  configuration: configuration.active,
1970
1644
  dark,
1971
- interact,
1645
+ interact: frameInteract,
1972
1646
  bp,
1973
1647
  catalog,
1974
- frameUrl
1648
+ frameUrl,
1649
+ viewportHeight: frameViewportHeight
1975
1650
  });
1976
1651
  latest.current = {
1977
1652
  configuration: configuration.active,
1978
1653
  dark,
1979
- interact,
1654
+ interact: frameInteract,
1980
1655
  bp,
1981
1656
  catalog,
1982
- frameUrl
1657
+ frameUrl,
1658
+ viewportHeight: frameViewportHeight
1983
1659
  };
1984
- const register = useCallback((id, frame) => {
1985
- if (frame) frames.current.set(id, frame);
1986
- else frames.current.delete(id);
1660
+ const register = useCallback((id_0, frame) => {
1661
+ if (frame) frames.current.set(id_0, frame);
1662
+ else frames.current.delete(id_0);
1987
1663
  }, []);
1988
1664
  const paint = useCallback(() => {
1989
1665
  if (world.current) {
@@ -2005,16 +1681,16 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
2005
1681
  paint();
2006
1682
  });
2007
1683
  }, [paint]);
2008
- const send = useCallback((id_0, type = "configuration") => {
2009
- const frame_0 = frames.current.get(id_0);
1684
+ const send = useCallback((id_1, type = "configuration") => {
1685
+ const frame_0 = frames.current.get(id_1);
2010
1686
  if (!frame_0?.contentWindow) return;
2011
1687
  const current_0 = latest.current;
2012
1688
  try {
2013
1689
  frame_0.contentWindow.postMessage({
2014
1690
  protocol: canvasProtocol,
2015
- id: id_0,
1691
+ id: id_1,
2016
1692
  token,
2017
- viewportHeight: current_0.bp.height,
1693
+ viewportHeight: current_0.viewportHeight,
2018
1694
  type,
2019
1695
  configuration: current_0.configuration,
2020
1696
  revision: revision.current,
@@ -2025,10 +1701,10 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
2025
1701
  setNotice("This configuration could not be sent to the page. Check for non-serializable values.");
2026
1702
  }
2027
1703
  }, [token]);
2028
- const focusPage = useCallback((id_1) => {
2029
- const node_0 = nodeMap.get(id_1), view = viewport.current;
1704
+ const focusPage = useCallback((id_2) => {
1705
+ const node_0 = nodeMap.get(id_2), view = viewport.current;
2030
1706
  if (!node_0 || !view) return;
2031
- setSelected(id_1);
1707
+ setSelected(id_2);
2032
1708
  setShowLayers(true);
2033
1709
  camera.current.zoom = Math.min(1, Math.max(.005, (view.clientWidth - 80) / node_0.width));
2034
1710
  camera.current.x = 40 - node_0.x * camera.current.zoom;
@@ -2112,7 +1788,7 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
2112
1788
  useEffect(() => {
2113
1789
  const frame_2 = requestAnimationFrame(() => {
2114
1790
  revision.current++;
2115
- for (const id_2 of frames.current.keys()) send(id_2);
1791
+ for (const id_3 of frames.current.keys()) send(id_3);
2116
1792
  });
2117
1793
  return () => cancelAnimationFrame(frame_2);
2118
1794
  }, [
@@ -2121,8 +1797,8 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
2121
1797
  send
2122
1798
  ]);
2123
1799
  useEffect(() => {
2124
- for (const id_3 of frames.current.keys()) send(id_3, "mode");
2125
- }, [interact, send]);
1800
+ for (const id_4 of frames.current.keys()) send(id_4, "mode");
1801
+ }, [frameInteract, send]);
2126
1802
  useEffect(() => {
2127
1803
  paint();
2128
1804
  const element = viewport.current;
@@ -2269,11 +1945,11 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
2269
1945
  }
2270
1946
  if (event_3.currentTarget.hasPointerCapture(event_3.pointerId)) event_3.currentTarget.releasePointerCapture(event_3.pointerId);
2271
1947
  };
2272
- const onLoad = useCallback((id_4, frame_3) => {
2273
- if (frames.current.get(id_4) !== frame_3) return;
2274
- startupRef.current.complete(startupRef.current.keys.get(id_4));
2275
- send(id_4);
2276
- send(id_4, "mode");
1948
+ const onLoad = useCallback((id_5, frame_3) => {
1949
+ if (frames.current.get(id_5) !== frame_3) return;
1950
+ startupRef.current.complete(startupRef.current.keys.get(id_5));
1951
+ send(id_5);
1952
+ send(id_5, "mode");
2277
1953
  }, [send]);
2278
1954
  useEffect(() => {
2279
1955
  const timer = setTimeout(() => setRuntime((current_5) => {
@@ -2456,7 +2132,7 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
2456
2132
  "/",
2457
2133
  nodes.length,
2458
2134
  " ",
2459
- content === "components" ? "sections" : "pages",
2135
+ content === "components" ? "components" : "pages",
2460
2136
  " ready"
2461
2137
  ]
2462
2138
  })
@@ -2500,14 +2176,21 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
2500
2176
  children: /* @__PURE__ */ jsx(PanelLeft, { size: 18 })
2501
2177
  })
2502
2178
  }),
2503
- /* @__PURE__ */ jsx("div", {
2179
+ /* @__PURE__ */ jsxs("div", {
2504
2180
  ref: world,
2505
2181
  className: "povio-canvas-world",
2506
2182
  style: {
2507
2183
  width: width_0,
2508
2184
  height: height_0
2509
2185
  },
2510
- children: nodes.map((node_5, index) => {
2186
+ children: [sections.map((section) => /* @__PURE__ */ jsx("h2", {
2187
+ className: "povio-canvas-section-title",
2188
+ style: {
2189
+ left: section.x,
2190
+ top: section.y
2191
+ },
2192
+ children: section.title
2193
+ }, section.title)), nodes.map((node_5, index) => {
2511
2194
  const state = runtime[`${bp.id}:${node_5.id}:${node_5.href ?? ""}`] ?? {};
2512
2195
  let source = "";
2513
2196
  let originError = false;
@@ -2558,7 +2241,7 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
2558
2241
  children: [
2559
2242
  /* @__PURE__ */ jsx("strong", { children: node_5.title }),
2560
2243
  /* @__PURE__ */ jsxs("span", { children: [
2561
- bp.width,
2244
+ node_5.width,
2562
2245
  " × ",
2563
2246
  Math.round(node_5.height).toLocaleString()
2564
2247
  ] }),
@@ -2627,20 +2310,20 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
2627
2310
  }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
2628
2311
  /* @__PURE__ */ jsx(PageFrame, {
2629
2312
  id: node_5.id,
2630
- interact,
2313
+ interact: frameInteract,
2631
2314
  inspect: inspectMode,
2632
2315
  src: source,
2633
- width: bp.width,
2316
+ width: node_5.width,
2634
2317
  height: node_5.height,
2635
2318
  name: `${canvasProtocol}:${JSON.stringify({
2636
2319
  id: node_5.id,
2637
2320
  token,
2638
- viewportHeight: bp.height
2321
+ viewportHeight: frameViewportHeight
2639
2322
  })}`,
2640
2323
  onLoad,
2641
2324
  register
2642
2325
  }, `${documentGeneration}:${bp.id}:${source}:${reload[node_5.id] ?? 0}`),
2643
- !interact && /* @__PURE__ */ jsx("button", {
2326
+ !frameInteract && /* @__PURE__ */ jsx("button", {
2644
2327
  type: "button",
2645
2328
  className: "povio-canvas-frame-cover",
2646
2329
  tabIndex: 0,
@@ -2680,7 +2363,7 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
2680
2363
  })
2681
2364
  ]
2682
2365
  }, node_5.id);
2683
- })
2366
+ })]
2684
2367
  }),
2685
2368
  !nodes.length && /* @__PURE__ */ jsx("div", {
2686
2369
  className: "povio-canvas-empty",
@@ -2779,12 +2462,12 @@ function AppCanvas({ router, examples = emptyExamples, exclude = emptyExclude, e
2779
2462
  id: item_4.id,
2780
2463
  label: `${item_4.label} · ${item_4.width}px`
2781
2464
  })),
2782
- onChange: (id_5) => {
2783
- if (id_5 === null || id_5 === bp.id) return;
2465
+ onChange: (id_6) => {
2466
+ if (id_6 === null || id_6 === bp.id) return;
2784
2467
  setRuntime({});
2785
2468
  setManifest((m_2) => ({
2786
2469
  ...m_2,
2787
- breakpoint: String(id_5)
2470
+ breakpoint: String(id_6)
2788
2471
  }));
2789
2472
  }
2790
2473
  })
@@ -3147,7 +2830,7 @@ function AppCanvasFrameBridge({ href }) {
3147
2830
  const APP_CANVAS_PATH = "/_canvas";
3148
2831
  /** Must match `componentsFrameParam`; kept inline so the canvas page does not load the gallery eagerly. */
3149
2832
  const componentsParam = "povio-components";
3150
- const CanvasComponentsFrame = lazy(() => import("./CanvasComponentsFrame-D6Mh_G3q.js"));
2833
+ const CanvasComponentsFrame = lazy(() => import("./CanvasComponentsFrame-Dp0oDDoH.js"));
3151
2834
  /** Ready-made route page. Mount beneath the app's UIConfigurationProvider. */
3152
2835
  function AppCanvasPage(t0) {
3153
2836
  const $ = c(24);
@@ -3205,10 +2888,10 @@ function AppCanvasPage(t0) {
3205
2888
  if (isAppCanvasFrame()) {
3206
2889
  let t7;
3207
2890
  if ($[14] === Symbol.for("react.memo_cache_sentinel")) {
3208
- const group = new URLSearchParams(window.location.search).get(componentsParam);
3209
- t7 = group ? /* @__PURE__ */ jsx(Suspense, {
2891
+ const component = new URLSearchParams(window.location.search).get(componentsParam);
2892
+ t7 = component ? /* @__PURE__ */ jsx(Suspense, {
3210
2893
  fallback: null,
3211
- children: /* @__PURE__ */ jsx(CanvasComponentsFrame, { group })
2894
+ children: /* @__PURE__ */ jsx(CanvasComponentsFrame, { id: component })
3212
2895
  }) : null;
3213
2896
  $[14] = t7;
3214
2897
  } else t7 = $[14];
@@ -3216,7 +2899,7 @@ function AppCanvasPage(t0) {
3216
2899
  }
3217
2900
  let t7;
3218
2901
  if ($[15] !== canvasPath) {
3219
- t7 = (group_0) => `${canvasPath}?${componentsParam}=${encodeURIComponent(group_0)}`;
2902
+ t7 = (component_0) => `${canvasPath}?${componentsParam}=${encodeURIComponent(component_0)}`;
3220
2903
  $[15] = canvasPath;
3221
2904
  $[16] = t7;
3222
2905
  } else t7 = $[16];