camox 0.45.0 → 0.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/core/hooks/useArtifactHost.js +2 -2
  2. package/dist/features/canvas/CamoxCanvas.js +438 -771
  3. package/dist/features/canvas/CanvasPageFrame.js +1 -3
  4. package/dist/features/canvas/CanvasPreviewPageSlot.js +26 -6
  5. package/dist/features/canvas/canvasCamera.js +3 -3
  6. package/dist/features/canvas/canvasFrameDocument.js +4 -19
  7. package/dist/features/canvas/canvasItems.js +12 -102
  8. package/dist/features/canvas/canvasStore.js +3 -92
  9. package/dist/features/canvas/sidebar/CanvasNavigator.js +81 -183
  10. package/dist/features/canvas/sidebar/CanvasSidebar.js +22 -28
  11. package/dist/features/canvas/sidebar/CuratedPageInspector.js +2 -2
  12. package/dist/features/canvas/useCanvasCamera.js +0 -20
  13. package/dist/features/canvas/useCanvasFrame.js +5 -6
  14. package/dist/features/preview/CamoxPreview.js +3 -3
  15. package/dist/features/preview/components/{AddBlockDialog.js → AddBlockSheet.js} +35 -32
  16. package/dist/features/preview/components/BlockActionsPopover.js +6 -6
  17. package/dist/features/preview/components/BlockThumbnail.js +31 -33
  18. package/dist/features/preview/components/Overlays.js +1 -1
  19. package/dist/features/preview/components/PageTree.js +1 -1
  20. package/dist/features/preview/components/PreviewPanel.js +1 -1
  21. package/dist/features/preview/previewStore.js +9 -9
  22. package/dist/features/provider/CoreCamoxProvider.js +9 -6
  23. package/dist/features/routes/pageRuntime.js +8 -8
  24. package/dist/features/runtime/runtime.d.ts +2 -7
  25. package/dist/features/runtime/runtime.js +6 -19
  26. package/dist/features/studio/FollowAgentProvider.js +11 -22
  27. package/dist/features/studio/components/FaviconDialog.js +3 -3
  28. package/dist/features/studio/followAgent.js +5 -14
  29. package/dist/features/studio/routes.js +1 -23
  30. package/dist/lib/auth.js +36 -24
  31. package/dist/lib/studio-reads.js +0 -20
  32. package/dist/package.js +1 -1
  33. package/dist/studio.css +1 -1
  34. package/package.json +4 -4
  35. package/skills/camox-expand/SKILL.md +5 -4
  36. package/dist/features/canvas/CanvasBlockFrame.js +0 -353
  37. package/dist/features/canvas/CanvasBlockHeader.js +0 -55
  38. package/dist/features/canvas/CanvasShelfMarker.js +0 -255
  39. package/dist/features/canvas/sidebar/CatalogBlockInspector.js +0 -189
@@ -52,18 +52,19 @@ Stop suggesting when the next idea would be filler; there is no target count. Th
52
52
  Make only these kinds of change:
53
53
 
54
54
  - **New Block Definitions**, following [Block Definitions](../camox/references/block-definitions.md), [Localized code](../camox/SKILL.md#localized-code) (every visible text in fields, internal links through `useLocalizedHref` without a locale prefix), and Camoxify's rules on [styling](../camoxify/SKILL.md#use-the-existing-styling-stack), [genericity and default content](../camoxify/SKILL.md#keep-definitions-generic), [repeaters](../camoxify/SKILL.md#model-repetition-not-a-fixed-screenshot), [Settings](../camoxify/SKILL.md#use-settings-for-constrained-choices), and [formatted text](../camoxify/SKILL.md#keep-formatted-text-in-one-field).
55
- - **New Settings on existing Block Definitions**, with defaults that leave current rendering unchanged. Existing content schemas stay exactly as they are. Before editing the block, capture it in the Block Catalog at desktop and mobile, opened at `/camox/blocks/<id>` on the running dev server; step 6 compares against this capture.
55
+ - **New Settings on existing Block Definitions**, with defaults that leave current rendering unchanged. Existing content schemas stay exactly as they are. Before editing the block, capture it at desktop and mobile on a Page that places it, on the running dev server; step 6 compares against this capture.
56
56
  - **Description edits.** A new block's `description` says when to choose it over its siblings. Edit the siblings' descriptions so each one names what sets it apart, and the Agent can choose between them.
57
57
 
58
- New blocks live only in code and the Block Catalog. Leave Pages, layouts, and publishing alone, and create no temporary Pages. This rules out new Layout-only Blocks: the Block Catalog never shows them, and they only sync once a layout uses them. An existing Layout-only Block that gains a Setting has no Block Catalog page either, so capture and check it on a Page whose layout uses it.
58
+ New blocks live only in code, plus one review Page in the development draft: create it with the CLI (see [Managing Pages and Blocks](../camox/references/cli-content.md)) and place each new block on it with its default content. Leave every other Page, layouts, and publishing alone. This rules out new Layout-only Blocks: a Page can't hold them, and they only sync once a layout uses them. An existing Layout-only Block that gains a Setting is captured and checked on a Page whose layout uses it.
59
59
 
60
60
  ## 6. Verify
61
61
 
62
- Finish with a Block Catalog link to each new block, so the operator and the product marketing team can review them live. Delete any block the operator rejects, along with any description changes made only for it.
62
+ Finish with a link to the review Page, so the operator and the product marketing team can review the new blocks live. Delete any block the operator rejects, along with any description changes made only for it. Once the review is over, delete the review Page with `pages delete`, so publishing the development draft never ships it.
63
63
 
64
64
  The run is complete when:
65
65
 
66
66
  - every approved item is built, and every rejected one is deleted,
67
+ - the review Page is deleted once the operator has reviewed it,
67
68
  - the project's `check` script passes, and so does `vp lint --type-aware --type-check`, since `vp check` skips type errors unless the project's Vite config sets `lint.options.typeCheck`,
68
- - every new block renders correctly with its default content at desktop and mobile in the Block Catalog at `/camox/blocks/<id>`,
69
+ - every new block renders correctly with its default content at desktop and mobile on the review Page,
69
70
  - every existing block that gained a Setting renders the same as its capture with default Settings.
@@ -1,353 +0,0 @@
1
- import { NormalizedDataProvider } from "../../lib/normalized-data.js";
2
- import { reads, useRead } from "../../lib/studio-reads.js";
3
- import { BlockEditingRuntimeProvider } from "../../core/editing/BlockEditingRuntime.js";
4
- import { ArtifactStudioContext, ArtifactsRunContext } from "../../core/hooks/useArtifactHost.js";
5
- import { BlockErrorBoundary } from "../preview/components/BlockErrorBoundary.js";
6
- import { PreviewDocumentContext } from "../runtime/PreviewDocumentContext.js";
7
- import { canvasDocumentStyles, canvasPageHref } from "./canvasFrameDocument.js";
8
- import { useCanvasFrameMode } from "./canvasFrameMode.js";
9
- import { CanvasFrameProviders, preventLinkNavigation, useCanvasFrame } from "./useCanvasFrame.js";
10
- import { useCanvasNearness } from "./useCanvasNearness.js";
11
- import { c } from "react/compiler-runtime";
12
- import * as React from "react";
13
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
14
- import { createPortal } from "react-dom";
15
-
16
- //#region src/features/canvas/CanvasBlockFrame.tsx
17
- /** World-space height reserved for a frame until it mounts and measures its block. */
18
- const PLACEHOLDER_HEIGHT = 400;
19
- /** Block Catalog blocks render as on the website, but on the Canvas and never editable. */
20
- const CATALOG_ARTIFACT_STUDIO = {
21
- editing: false,
22
- canvas: true
23
- };
24
- /**
25
- * A live frame of the Block Catalog: one block with its default content, or a
26
- * Synced Block's shared content when the project has some, bare and
27
- * interactive, but with no editing. It mounts once it comes near the
28
- * Canvas viewport and stays mounted, so its state survives panning away,
29
- * though it only runs while selected and the camera is still.
30
- */
31
- function CanvasBlockFrame(props) {
32
- const $ = c(17);
33
- const ref = React.useRef(null);
34
- const { near, reached } = useCanvasNearness(ref);
35
- let t0;
36
- if ($[0] !== near || $[1] !== props.selected) {
37
- t0 = {
38
- near,
39
- selected: props.selected
40
- };
41
- $[0] = near;
42
- $[1] = props.selected;
43
- $[2] = t0;
44
- } else t0 = $[2];
45
- const mode = useCanvasFrameMode(t0);
46
- const previewDocument = React.useContext(PreviewDocumentContext);
47
- let t1;
48
- if ($[3] !== previewDocument || $[4] !== reached) {
49
- t1 = reached ? canvasDocumentStyles(previewDocument) : "";
50
- $[3] = previewDocument;
51
- $[4] = reached;
52
- $[5] = t1;
53
- } else t1 = $[5];
54
- const styles = t1;
55
- const t2 = near || props.selected ? void 0 : "hidden";
56
- let t3;
57
- if ($[6] !== t2) {
58
- t3 = { visibility: t2 };
59
- $[6] = t2;
60
- $[7] = t3;
61
- } else t3 = $[7];
62
- let t4;
63
- if ($[8] !== mode || $[9] !== previewDocument || $[10] !== props || $[11] !== reached || $[12] !== styles) {
64
- t4 = reached ? /* @__PURE__ */ jsx(BlockFrame, {
65
- ...props,
66
- previewDocument,
67
- mode
68
- }, styles) : /* @__PURE__ */ jsx("div", {
69
- "data-canvas-block-placeholder": true,
70
- style: { height: PLACEHOLDER_HEIGHT }
71
- });
72
- $[8] = mode;
73
- $[9] = previewDocument;
74
- $[10] = props;
75
- $[11] = reached;
76
- $[12] = styles;
77
- $[13] = t4;
78
- } else t4 = $[13];
79
- let t5;
80
- if ($[14] !== t3 || $[15] !== t4) {
81
- t5 = /* @__PURE__ */ jsx("div", {
82
- ref,
83
- style: t3,
84
- children: t4
85
- });
86
- $[14] = t3;
87
- $[15] = t4;
88
- $[16] = t5;
89
- } else t5 = $[16];
90
- return t5;
91
- }
92
- function BlockFrame(t0) {
93
- const $ = c(26);
94
- const { block, projectId, runtimeBasePath, width, viewportHeight, selected, onSelect, previewDocument, mode } = t0;
95
- const [initialPreviewDocument] = React.useState(previewDocument);
96
- let t1;
97
- if ($[0] !== runtimeBasePath) {
98
- t1 = () => canvasPageHref({
99
- runtimeBasePath,
100
- pathname: "/",
101
- href: window.location.href
102
- });
103
- $[0] = runtimeBasePath;
104
- $[1] = t1;
105
- } else t1 = $[1];
106
- const [href] = React.useState(t1);
107
- let t2;
108
- if ($[2] !== href || $[3] !== initialPreviewDocument || $[4] !== mode || $[5] !== viewportHeight || $[6] !== width) {
109
- t2 = {
110
- previewDocument: initialPreviewDocument,
111
- href,
112
- width,
113
- viewportHeight,
114
- fit: "content",
115
- subject: "block",
116
- mode
117
- };
118
- $[2] = href;
119
- $[3] = initialPreviewDocument;
120
- $[4] = mode;
121
- $[5] = viewportHeight;
122
- $[6] = width;
123
- $[7] = t2;
124
- } else t2 = $[7];
125
- const { iframe, mount, iframeProps } = useCanvasFrame(t2);
126
- const { title, synced } = block._internal;
127
- let t3;
128
- if ($[8] !== iframeProps || $[9] !== title || $[10] !== viewportHeight || $[11] !== width) {
129
- t3 = iframeProps.srcDoc && /* @__PURE__ */ jsx("iframe", {
130
- ...iframeProps,
131
- title: `Block preview: ${title}`,
132
- style: {
133
- display: "block",
134
- width,
135
- height: viewportHeight,
136
- border: 0
137
- }
138
- });
139
- $[8] = iframeProps;
140
- $[9] = title;
141
- $[10] = viewportHeight;
142
- $[11] = width;
143
- $[12] = t3;
144
- } else t3 = $[12];
145
- let t4;
146
- if ($[13] !== block || $[14] !== href || $[15] !== iframe || $[16] !== mode || $[17] !== mount || $[18] !== onSelect || $[19] !== projectId || $[20] !== selected || $[21] !== synced) {
147
- t4 = mount && createPortal(/* @__PURE__ */ jsx(BlockEditingRuntimeProvider, {
148
- runtime: null,
149
- children: /* @__PURE__ */ jsx(ArtifactStudioContext, {
150
- value: CATALOG_ARTIFACT_STUDIO,
151
- children: /* @__PURE__ */ jsx(ArtifactsRunContext, {
152
- value: selected,
153
- children: /* @__PURE__ */ jsx(CanvasFrameProviders, {
154
- pathname: "/",
155
- href,
156
- mount,
157
- iframe,
158
- children: /* @__PURE__ */ jsx(React.Activity, {
159
- mode: mode === "resting" ? "hidden" : "visible",
160
- children: /* @__PURE__ */ jsx("div", {
161
- style: { display: "flow-root" },
162
- onPointerDownCapture: onSelect,
163
- onFocusCapture: onSelect,
164
- onClick: preventLinkNavigation,
165
- children: /* @__PURE__ */ jsx(React.Suspense, {
166
- fallback: /* @__PURE__ */ jsx("div", {
167
- role: "status",
168
- children: "Loading block…"
169
- }),
170
- children: synced ? /* @__PURE__ */ jsx(SyncedBlockContent, {
171
- block,
172
- projectId
173
- }) : /* @__PURE__ */ jsx(DefaultBlockContent, { block })
174
- })
175
- })
176
- })
177
- })
178
- })
179
- })
180
- }), mount);
181
- $[13] = block;
182
- $[14] = href;
183
- $[15] = iframe;
184
- $[16] = mode;
185
- $[17] = mount;
186
- $[18] = onSelect;
187
- $[19] = projectId;
188
- $[20] = selected;
189
- $[21] = synced;
190
- $[22] = t4;
191
- } else t4 = $[22];
192
- let t5;
193
- if ($[23] !== t3 || $[24] !== t4) {
194
- t5 = /* @__PURE__ */ jsxs(Fragment, { children: [t3, t4] });
195
- $[23] = t3;
196
- $[24] = t4;
197
- $[25] = t5;
198
- } else t5 = $[25];
199
- return t5;
200
- }
201
- function DefaultBlockContent(t0) {
202
- const $ = c(13);
203
- const { block } = t0;
204
- let t1;
205
- if ($[0] !== block._internal) {
206
- t1 = block._internal.getPeekBundle();
207
- $[0] = block._internal;
208
- $[1] = t1;
209
- } else t1 = $[1];
210
- const bundle = t1;
211
- let t2;
212
- if ($[2] !== bundle.block.content || $[3] !== bundle.block.id || $[4] !== bundle.block.position || $[5] !== bundle.block.settings || $[6] !== bundle.block.type) {
213
- t2 = {
214
- _id: bundle.block.id,
215
- type: bundle.block.type,
216
- content: bundle.block.content,
217
- settings: bundle.block.settings,
218
- position: bundle.block.position
219
- };
220
- $[2] = bundle.block.content;
221
- $[3] = bundle.block.id;
222
- $[4] = bundle.block.position;
223
- $[5] = bundle.block.settings;
224
- $[6] = bundle.block.type;
225
- $[7] = t2;
226
- } else t2 = $[7];
227
- let t3;
228
- if ($[8] !== block || $[9] !== bundle.files || $[10] !== bundle.repeatableItems || $[11] !== t2) {
229
- t3 = /* @__PURE__ */ jsx(BlockContent, {
230
- block,
231
- files: bundle.files,
232
- repeatableItems: bundle.repeatableItems,
233
- blockData: t2
234
- });
235
- $[8] = block;
236
- $[9] = bundle.files;
237
- $[10] = bundle.repeatableItems;
238
- $[11] = t2;
239
- $[12] = t3;
240
- } else t3 = $[12];
241
- return t3;
242
- }
243
- /** A Synced Block shows the project's shared content, or its defaults until it has some. */
244
- function SyncedBlockContent(t0) {
245
- const $ = c(19);
246
- const { block, projectId } = t0;
247
- let t1;
248
- if ($[0] !== block._internal.id || $[1] !== projectId) {
249
- t1 = reads.syncedContent({
250
- projectId,
251
- type: block._internal.id
252
- });
253
- $[0] = block._internal.id;
254
- $[1] = projectId;
255
- $[2] = t1;
256
- } else t1 = $[2];
257
- const shared = useRead(t1);
258
- if (!shared) {
259
- let t2;
260
- if ($[3] !== block) {
261
- t2 = /* @__PURE__ */ jsx(DefaultBlockContent, { block });
262
- $[3] = block;
263
- $[4] = t2;
264
- } else t2 = $[4];
265
- return t2;
266
- }
267
- let t2;
268
- if ($[5] !== shared.block) {
269
- t2 = [shared.block];
270
- $[5] = shared.block;
271
- $[6] = t2;
272
- } else t2 = $[6];
273
- const t3 = shared.block.content;
274
- const t4 = shared.block.settings;
275
- let t5;
276
- if ($[7] !== shared.block.id || $[8] !== shared.block.position || $[9] !== shared.block.type || $[10] !== t3 || $[11] !== t4) {
277
- t5 = {
278
- _id: shared.block.id,
279
- type: shared.block.type,
280
- content: t3,
281
- settings: t4,
282
- position: shared.block.position
283
- };
284
- $[7] = shared.block.id;
285
- $[8] = shared.block.position;
286
- $[9] = shared.block.type;
287
- $[10] = t3;
288
- $[11] = t4;
289
- $[12] = t5;
290
- } else t5 = $[12];
291
- let t6;
292
- if ($[13] !== block || $[14] !== shared.files || $[15] !== shared.repeatableItems || $[16] !== t2 || $[17] !== t5) {
293
- t6 = /* @__PURE__ */ jsx(BlockContent, {
294
- block,
295
- files: shared.files,
296
- repeatableItems: shared.repeatableItems,
297
- references: t2,
298
- blockData: t5
299
- });
300
- $[13] = block;
301
- $[14] = shared.files;
302
- $[15] = shared.repeatableItems;
303
- $[16] = t2;
304
- $[17] = t5;
305
- $[18] = t6;
306
- } else t6 = $[18];
307
- return t6;
308
- }
309
- function BlockContent(t0) {
310
- const $ = c(12);
311
- const { block, files, repeatableItems, references, blockData } = t0;
312
- const { id, Component } = block._internal;
313
- let t1;
314
- if ($[0] !== Component || $[1] !== blockData) {
315
- t1 = /* @__PURE__ */ jsx(Component, {
316
- blockData,
317
- mode: "peek"
318
- });
319
- $[0] = Component;
320
- $[1] = blockData;
321
- $[2] = t1;
322
- } else t1 = $[2];
323
- let t2;
324
- if ($[3] !== files || $[4] !== references || $[5] !== repeatableItems || $[6] !== t1) {
325
- t2 = /* @__PURE__ */ jsx(NormalizedDataProvider, {
326
- files,
327
- repeatableItems,
328
- blocks: references,
329
- children: t1
330
- });
331
- $[3] = files;
332
- $[4] = references;
333
- $[5] = repeatableItems;
334
- $[6] = t1;
335
- $[7] = t2;
336
- } else t2 = $[7];
337
- let t3;
338
- if ($[8] !== blockData._id || $[9] !== id || $[10] !== t2) {
339
- t3 = /* @__PURE__ */ jsx(BlockErrorBoundary, {
340
- blockId: blockData._id,
341
- blockType: id,
342
- children: t2
343
- });
344
- $[8] = blockData._id;
345
- $[9] = id;
346
- $[10] = t2;
347
- $[11] = t3;
348
- } else t3 = $[11];
349
- return t3;
350
- }
351
-
352
- //#endregion
353
- export { CanvasBlockFrame };
@@ -1,55 +0,0 @@
1
- import { c } from "react/compiler-runtime";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
-
4
- //#region src/features/canvas/CanvasBlockHeader.tsx
5
- /** How many Pages place a block, as shown in its header. */
6
- function formatCanvasBlockUsage(pageCount) {
7
- if (pageCount === 0) return "Unused";
8
- return `Used on ${pageCount} ${pageCount === 1 ? "page" : "pages"}`;
9
- }
10
- /**
11
- * The header above a block of the Block Catalog. Its title sits on the line of
12
- * Page nicknames and selects the block.
13
- * Its usage sits above the title once known, like a Page header's path.
14
- */
15
- function CanvasBlockHeader(t0) {
16
- const $ = c(8);
17
- const { block, pageCount, onSelect } = t0;
18
- const { title } = block._internal;
19
- let t1;
20
- if ($[0] !== pageCount) {
21
- t1 = pageCount !== void 0 && /* @__PURE__ */ jsx("span", {
22
- "data-canvas-block-usage": true,
23
- className: "text-muted-foreground w-full min-w-0 truncate text-left text-xs font-normal",
24
- children: formatCanvasBlockUsage(pageCount)
25
- });
26
- $[0] = pageCount;
27
- $[1] = t1;
28
- } else t1 = $[1];
29
- let t2;
30
- if ($[2] !== onSelect || $[3] !== title) {
31
- t2 = /* @__PURE__ */ jsx("button", {
32
- type: "button",
33
- className: "focus-visible:ring-ring max-w-full min-w-0 truncate text-left text-sm font-medium outline-none focus-visible:ring-2",
34
- onClick: onSelect,
35
- children: title
36
- });
37
- $[2] = onSelect;
38
- $[3] = title;
39
- $[4] = t2;
40
- } else t2 = $[4];
41
- let t3;
42
- if ($[5] !== t1 || $[6] !== t2) {
43
- t3 = /* @__PURE__ */ jsxs("h2", {
44
- className: "text-foreground flex h-10 w-full min-w-0 flex-col items-start justify-end gap-1 text-left",
45
- children: [t1, t2]
46
- });
47
- $[5] = t1;
48
- $[6] = t2;
49
- $[7] = t3;
50
- } else t3 = $[7];
51
- return t3;
52
- }
53
-
54
- //#endregion
55
- export { CanvasBlockHeader, formatCanvasBlockUsage };
@@ -1,255 +0,0 @@
1
- import "../preview/previewPageFrame.js";
2
- import "./canvasItems.js";
3
- import { canvasScreenAbove, canvasScreenLength, canvasScreenX } from "./canvasScreenSpace.js";
4
- import { c } from "react/compiler-runtime";
5
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
-
7
- //#region src/features/canvas/CanvasShelfMarker.tsx
8
- const BAR_SIZE = 24;
9
- const CANVAS_SHELF_MARKER_OVERHANG = 12;
10
- const MIN_BAR_SEPARATION = 8;
11
- const OVERHANG = `clamp(0px, ${canvasScreenLength(480)} / 2 - ${MIN_BAR_SEPARATION / 2}px, ${12}px)`;
12
- const LABEL_CLASS_NAME = "text-muted-foreground text-xs font-medium tracking-wider whitespace-nowrap uppercase";
13
- const BAR_CLASS_NAME = "bg-foreground/10 hover:bg-foreground/15 focus-visible:ring-ring absolute top-0 left-0 cursor-pointer rounded-sm outline-none focus-visible:ring-2";
14
- /**
15
- * Each marker's bar, from its area's on-screen extent. A collapsed bar keeps its
16
- * thickness at every zoom, so when it no longer fits in the gap next to its
17
- * area, it moves right, after the previous bar.
18
- */
19
- function getCanvasShelfMarkerBars(markers) {
20
- let previousRight;
21
- return markers.map((marker) => {
22
- const start = canvasScreenX(marker.start);
23
- const ownLeft = marker.collapsed ? `calc(${start} - ${BAR_SIZE / 2}px)` : `calc(${start} - ${OVERHANG})`;
24
- const left = previousRight ? `max(${ownLeft}, calc(${previousRight} + ${MIN_BAR_SEPARATION}px))` : ownLeft;
25
- const right = marker.collapsed ? `calc(${left} + ${BAR_SIZE}px)` : `max(calc(${canvasScreenX(marker.end)} + ${OVERHANG}), ${left})`;
26
- previousRight = right;
27
- return {
28
- left,
29
- right
30
- };
31
- });
32
- }
33
- /** The Shelf Markers of the Canvas row, in row order. */
34
- function CanvasShelfMarkers({ markers, onToggle }) {
35
- const bars = getCanvasShelfMarkerBars(markers);
36
- return markers.map((marker, index) => /* @__PURE__ */ jsx(CanvasShelfMarker, {
37
- marker,
38
- bar: bars[index],
39
- onToggle: () => onToggle(marker)
40
- }, marker.key));
41
- }
42
- /**
43
- * A labelled bar naming an area of the Canvas. Clicking it collapses or expands the area.
44
- *
45
- * Expanded, it is a horizontal bar above the Page headers. The bar follows world
46
- * space horizontally, so it spans its area's items at every zoom, but keeps a
47
- * constant on-screen height, like Page headers. The label sticks near the
48
- * viewport's left edge while the area is in view, at the inset of a snapped
49
- * Page so it lines up with that Page's header, and the end of the area pushes it out.
50
- *
51
- * Collapsed, the area's items are hidden and the bar turns vertical in their
52
- * place, running from the header row to the bottom of the viewport. It is the
53
- * horizontal bar rotated, so its label reads upwards and sits at the top.
54
- */
55
- function CanvasShelfMarker(t0) {
56
- const $ = c(47);
57
- const { marker, bar, onToggle } = t0;
58
- let t1;
59
- if ($[0] !== marker.start) {
60
- t1 = canvasScreenX(marker.start);
61
- $[0] = marker.start;
62
- $[1] = t1;
63
- } else t1 = $[1];
64
- const start = t1;
65
- let t2;
66
- if ($[2] !== marker.end) {
67
- t2 = canvasScreenX(marker.end);
68
- $[2] = marker.end;
69
- $[3] = t2;
70
- } else t2 = $[3];
71
- const end = t2;
72
- let t3;
73
- if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
74
- t3 = canvasScreenAbove(52 + 32);
75
- $[4] = t3;
76
- } else t3 = $[4];
77
- const y = t3;
78
- const t4 = !marker.collapsed;
79
- const t5 = `${marker.collapsed ? "Expand" : "Collapse"} ${marker.label}`;
80
- const t6 = marker.count === 0;
81
- let t7;
82
- if ($[5] !== marker.key || $[6] !== onToggle || $[7] !== t4 || $[8] !== t5 || $[9] !== t6) {
83
- t7 = {
84
- "data-canvas-shelf-marker": marker.key,
85
- "aria-expanded": t4,
86
- "aria-label": t5,
87
- disabled: t6,
88
- onClick: onToggle
89
- };
90
- $[5] = marker.key;
91
- $[6] = onToggle;
92
- $[7] = t4;
93
- $[8] = t5;
94
- $[9] = t6;
95
- $[10] = t7;
96
- } else t7 = $[10];
97
- const button = t7;
98
- if (marker.collapsed) {
99
- const t8 = `translate(${bar.left}, ${y})`;
100
- let t9;
101
- if ($[11] !== t8) {
102
- t9 = {
103
- width: BAR_SIZE,
104
- height: `calc(100% - ${y})`,
105
- transform: t8,
106
- willChange: "transform",
107
- zIndex: 2
108
- };
109
- $[11] = t8;
110
- $[12] = t9;
111
- } else t9 = $[12];
112
- let t10;
113
- if ($[13] !== button || $[14] !== t9) {
114
- t10 = /* @__PURE__ */ jsx("button", {
115
- type: "button",
116
- ...button,
117
- className: BAR_CLASS_NAME,
118
- style: t9
119
- });
120
- $[13] = button;
121
- $[14] = t9;
122
- $[15] = t10;
123
- } else t10 = $[15];
124
- const t11 = `translate(${bar.left}, max(${y}, 0px))`;
125
- let t12;
126
- if ($[16] !== t11) {
127
- t12 = {
128
- width: BAR_SIZE,
129
- transform: t11,
130
- willChange: "transform",
131
- zIndex: 2
132
- };
133
- $[16] = t11;
134
- $[17] = t12;
135
- } else t12 = $[17];
136
- let t13;
137
- if ($[18] !== marker.count || $[19] !== marker.label) {
138
- t13 = /* @__PURE__ */ jsxs("span", {
139
- className: `${LABEL_CLASS_NAME} rotate-180 [writing-mode:vertical-rl]`,
140
- children: [
141
- marker.label,
142
- " (",
143
- marker.count,
144
- ")"
145
- ]
146
- });
147
- $[18] = marker.count;
148
- $[19] = marker.label;
149
- $[20] = t13;
150
- } else t13 = $[20];
151
- let t14;
152
- if ($[21] !== marker.key || $[22] !== t12 || $[23] !== t13) {
153
- t14 = /* @__PURE__ */ jsx("div", {
154
- "data-canvas-shelf-marker-label": marker.key,
155
- className: "pointer-events-none absolute top-0 left-0 flex justify-center pt-3",
156
- style: t12,
157
- children: t13
158
- });
159
- $[21] = marker.key;
160
- $[22] = t12;
161
- $[23] = t13;
162
- $[24] = t14;
163
- } else t14 = $[24];
164
- let t15;
165
- if ($[25] !== t10 || $[26] !== t14) {
166
- t15 = /* @__PURE__ */ jsxs(Fragment, { children: [t10, t14] });
167
- $[25] = t10;
168
- $[26] = t14;
169
- $[27] = t15;
170
- } else t15 = $[27];
171
- return t15;
172
- }
173
- const labelStart = `max(${start}, calc(${bar.left} + ${12}px), ${24}px)`;
174
- const t8 = `calc(${bar.right} - ${bar.left})`;
175
- const t9 = `translate(${bar.left}, ${y})`;
176
- let t10;
177
- if ($[28] !== t8 || $[29] !== t9) {
178
- t10 = {
179
- height: BAR_SIZE,
180
- width: t8,
181
- transform: t9,
182
- willChange: "transform",
183
- zIndex: 2
184
- };
185
- $[28] = t8;
186
- $[29] = t9;
187
- $[30] = t10;
188
- } else t10 = $[30];
189
- let t11;
190
- if ($[31] !== button || $[32] !== t10) {
191
- t11 = /* @__PURE__ */ jsx("button", {
192
- type: "button",
193
- ...button,
194
- className: BAR_CLASS_NAME,
195
- style: t10
196
- });
197
- $[31] = button;
198
- $[32] = t10;
199
- $[33] = t11;
200
- } else t11 = $[33];
201
- const t12 = `max(0px, calc(${end} - ${labelStart}))`;
202
- const t13 = `translate(${labelStart}, ${y})`;
203
- let t14;
204
- if ($[34] !== t12 || $[35] !== t13) {
205
- t14 = {
206
- height: BAR_SIZE,
207
- width: t12,
208
- transform: t13,
209
- willChange: "transform",
210
- zIndex: 2
211
- };
212
- $[34] = t12;
213
- $[35] = t13;
214
- $[36] = t14;
215
- } else t14 = $[36];
216
- let t15;
217
- if ($[37] !== marker.count || $[38] !== marker.label) {
218
- t15 = /* @__PURE__ */ jsxs("span", {
219
- className: LABEL_CLASS_NAME,
220
- children: [
221
- marker.label,
222
- " (",
223
- marker.count,
224
- ")"
225
- ]
226
- });
227
- $[37] = marker.count;
228
- $[38] = marker.label;
229
- $[39] = t15;
230
- } else t15 = $[39];
231
- let t16;
232
- if ($[40] !== marker.key || $[41] !== t14 || $[42] !== t15) {
233
- t16 = /* @__PURE__ */ jsx("div", {
234
- "data-canvas-shelf-marker-label": marker.key,
235
- className: "pointer-events-none absolute top-0 left-0 flex items-center overflow-hidden",
236
- style: t14,
237
- children: t15
238
- });
239
- $[40] = marker.key;
240
- $[41] = t14;
241
- $[42] = t15;
242
- $[43] = t16;
243
- } else t16 = $[43];
244
- let t17;
245
- if ($[44] !== t11 || $[45] !== t16) {
246
- t17 = /* @__PURE__ */ jsxs(Fragment, { children: [t11, t16] });
247
- $[44] = t11;
248
- $[45] = t16;
249
- $[46] = t17;
250
- } else t17 = $[46];
251
- return t17;
252
- }
253
-
254
- //#endregion
255
- export { CanvasShelfMarkers };