camox 0.76.0 → 0.76.1

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 (49) hide show
  1. package/dist/core/editing/createEditableBlock.js +1077 -1681
  2. package/dist/core/editing/fieldSlot.js +251 -0
  3. package/dist/core/editing/useFieldSlot.js +159 -0
  4. package/dist/core/layoutContext.d.ts +2 -0
  5. package/dist/core/layoutContext.js +27 -1
  6. package/dist/features/canvas/CanvasPageFrame.js +2 -2
  7. package/dist/features/canvas/CanvasPreviewPageSlot.js +1 -1
  8. package/dist/features/canvas/canvasCameraController.js +595 -0
  9. package/dist/features/canvas/useCanvasCamera.js +141 -587
  10. package/dist/features/canvas/useCanvasFrame.js +1 -1
  11. package/dist/features/page/DerivedPageContent.js +4 -8
  12. package/dist/features/preview/components/AssetLightbox.js +6 -65
  13. package/dist/features/preview/components/CanvasPreview.js +2 -2
  14. package/dist/features/preview/components/Frame.js +3 -3
  15. package/dist/features/preview/components/ItemFieldsEditor.js +376 -460
  16. package/dist/features/preview/components/Overlays.js +4 -9
  17. package/dist/features/preview/components/PreviewPanel.js +3 -3
  18. package/dist/features/preview/components/RemovedBlockPlaceholder.js +2 -2
  19. package/dist/features/preview/components/SelectionEditor.js +285 -339
  20. package/dist/features/preview/components/ZoomableImage.js +105 -0
  21. package/dist/features/preview/components/contentFieldSchema.js +3 -1
  22. package/dist/features/preview/components/useFieldWriter.js +30 -51
  23. package/dist/features/preview/components/useRecordView.js +3 -3
  24. package/dist/features/preview/overlayMessages.js +20 -58
  25. package/dist/features/preview/previewStore.js +6 -123
  26. package/dist/features/preview/repeatableItemPath.js +47 -0
  27. package/dist/features/renderer/RendererApp.js +6 -6
  28. package/dist/features/renderer/RendererFrames.js +2 -2
  29. package/dist/features/renderer/rendererHost.js +1 -1
  30. package/dist/features/routes/pageRuntime.d.ts +2 -8
  31. package/dist/features/routes/pageRuntime.js +21 -105
  32. package/dist/features/runtime/pageApp.js +1 -1
  33. package/dist/features/runtime/pageRead.js +105 -0
  34. package/dist/features/runtime/reader.d.ts +25 -0
  35. package/dist/features/runtime/reader.js +142 -0
  36. package/dist/features/runtime/runtime.d.ts +9 -3
  37. package/dist/features/runtime/runtime.js +608 -776
  38. package/dist/features/sdkBundle/buildSdkBundle.d.ts +5 -0
  39. package/dist/features/sdkBundle/buildSdkBundle.js +9 -3
  40. package/dist/features/studio/components/DraftsSheet.js +124 -65
  41. package/dist/features/studio/components/ThreadMessages.js +5 -9
  42. package/dist/features/studio/showInCanvas.js +9 -19
  43. package/dist/features/studio/useEditorSelection.js +8 -19
  44. package/dist/package.js +1 -1
  45. package/dist/studio.css +1 -1
  46. package/package.json +4 -4
  47. package/dist/core/hooks/useFieldSelection.js +0 -67
  48. package/dist/core/hooks/useIsEditable.js +0 -21
  49. package/dist/core/hooks/useOverlayMessage.js +0 -70
@@ -15,6 +15,11 @@ export interface BuiltSdkBundle {
15
15
  name: string;
16
16
  /** Its files, every one at the root: entries, chunks and assets. */
17
17
  dir: string;
18
+ /**
19
+ * The modules a page loads at first paint, by id, for the browser bundle as just built: what
20
+ * every visitor downloads, before anything loads lazily.
21
+ */
22
+ firstPaint?: string[];
18
23
  }
19
24
  export type SdkBundleBuild = Record<SdkBundleTarget, BuiltSdkBundle>;
20
25
  /** The lockfile a website installed from, and the website's importer in it. */
@@ -62,7 +62,7 @@ async function buildSdkBundle({ root, outDir, settings }) {
62
62
  importer,
63
63
  target
64
64
  });
65
- const entries = await buildTarget({
65
+ const { entries, firstPaint } = await buildTarget({
66
66
  root: resolve(root),
67
67
  dir,
68
68
  target,
@@ -79,7 +79,8 @@ async function buildSdkBundle({ root, outDir, settings }) {
79
79
  await writeFile(join(dir, SDK_BUNDLE_MANIFEST), `${JSON.stringify(manifest, null, 2)}\n`);
80
80
  result[target] = {
81
81
  name: names[target],
82
- dir
82
+ dir,
83
+ ...firstPaint ? { firstPaint } : {}
83
84
  };
84
85
  }
85
86
  return result;
@@ -164,9 +165,11 @@ async function buildTarget({ root, dir, target, specifiers, names, settings }) {
164
165
  }
165
166
  }
166
167
  };
168
+ let firstPaint;
167
169
  if (!workerd) {
168
170
  const input = config.build.rolldownOptions.input;
169
171
  const pageModules = await modulesLoadedStatically(config, Object.fromEntries(specifiers.filter(loadsAtFirstPaint).map((specifier) => [entryName(specifier), input[entryName(specifier)]])));
172
+ firstPaint = [...pageModules];
170
173
  const output = config.build.rolldownOptions.output;
171
174
  output.codeSplitting = { groups: [{
172
175
  name: "react",
@@ -179,7 +182,10 @@ async function buildTarget({ root, dir, target, specifiers, names, settings }) {
179
182
  }] };
180
183
  }
181
184
  await build(config);
182
- return Object.fromEntries(specifiers.map((specifier) => [specifier, sdkBundleEntryFile(specifier)]));
185
+ return {
186
+ entries: Object.fromEntries(specifiers.map((specifier) => [specifier, sdkBundleEntryFile(specifier)])),
187
+ ...firstPaint ? { firstPaint } : {}
188
+ };
183
189
  }
184
190
  /**
185
191
  * The chunks a page loads at first paint, beside the entry files it imports: its code, React, and
@@ -18,101 +18,160 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@camox/ui/tabs";
18
18
  * restore or delete (ADR 0046), and a tab of Publications, to read why Live changed (ADR 0045).
19
19
  */
20
20
  function DraftsSheet(t0) {
21
- const $ = c(21);
21
+ const $ = c(36);
22
22
  const { projectId, open, onOpenChange } = t0;
23
23
  let t1;
24
- if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
25
- t1 = /* @__PURE__ */ jsxs(SheetHeader, {
24
+ if ($[0] !== projectId) {
25
+ t1 = reads.archivedDrafts({ projectId });
26
+ $[0] = projectId;
27
+ $[1] = t1;
28
+ } else t1 = $[1];
29
+ let t2;
30
+ if ($[2] !== open) {
31
+ t2 = { enabled: open };
32
+ $[2] = open;
33
+ $[3] = t2;
34
+ } else t2 = $[3];
35
+ const archived = useReadQuery(t1, t2);
36
+ let t3;
37
+ if ($[4] !== projectId) {
38
+ t3 = reads.publications({ projectId });
39
+ $[4] = projectId;
40
+ $[5] = t3;
41
+ } else t3 = $[5];
42
+ let t4;
43
+ if ($[6] !== open) {
44
+ t4 = { enabled: open };
45
+ $[6] = open;
46
+ $[7] = t4;
47
+ } else t4 = $[7];
48
+ const publications = useReadQuery(t3, t4);
49
+ let t5;
50
+ if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
51
+ t5 = /* @__PURE__ */ jsxs(SheetHeader, {
26
52
  className: "border-b",
27
53
  children: [/* @__PURE__ */ jsx(SheetTitle, { children: "Drafts" }), /* @__PURE__ */ jsx(SheetDescription, { children: "Drafts set aside, to bring back or delete, and what was published." })]
28
54
  });
29
- $[0] = t1;
30
- } else t1 = $[0];
31
- let t2;
32
- if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
33
- t2 = /* @__PURE__ */ jsxs(TabsList, { children: [/* @__PURE__ */ jsx(TabsTrigger, {
55
+ $[8] = t5;
56
+ } else t5 = $[8];
57
+ const t6 = archived.data?.length;
58
+ let t7;
59
+ if ($[9] !== t6) {
60
+ t7 = /* @__PURE__ */ jsxs(TabsTrigger, {
34
61
  value: "archived",
35
- children: "Archived"
36
- }), /* @__PURE__ */ jsx(TabsTrigger, {
62
+ children: ["Archived ", /* @__PURE__ */ jsx(TabCount, { count: t6 })]
63
+ });
64
+ $[9] = t6;
65
+ $[10] = t7;
66
+ } else t7 = $[10];
67
+ const t8 = publications.data?.length;
68
+ let t9;
69
+ if ($[11] !== t8) {
70
+ t9 = /* @__PURE__ */ jsxs(TabsTrigger, {
37
71
  value: "published",
38
- children: "Published"
39
- })] });
40
- $[1] = t2;
41
- } else t2 = $[1];
42
- let t3;
43
- if ($[2] !== onOpenChange || $[3] !== open || $[4] !== projectId) {
44
- t3 = open && /* @__PURE__ */ jsx(ArchivedDrafts, {
72
+ children: ["Published ", /* @__PURE__ */ jsx(TabCount, { count: t8 })]
73
+ });
74
+ $[11] = t8;
75
+ $[12] = t9;
76
+ } else t9 = $[12];
77
+ let t10;
78
+ if ($[13] !== t7 || $[14] !== t9) {
79
+ t10 = /* @__PURE__ */ jsxs(TabsList, { children: [t7, t9] });
80
+ $[13] = t7;
81
+ $[14] = t9;
82
+ $[15] = t10;
83
+ } else t10 = $[15];
84
+ let t11;
85
+ if ($[16] !== onOpenChange || $[17] !== open || $[18] !== projectId) {
86
+ t11 = open && /* @__PURE__ */ jsx(ArchivedDrafts, {
45
87
  projectId,
46
88
  onRestored: () => onOpenChange(false)
47
89
  });
48
- $[2] = onOpenChange;
49
- $[3] = open;
50
- $[4] = projectId;
51
- $[5] = t3;
52
- } else t3 = $[5];
53
- let t4;
54
- if ($[6] !== t3) {
55
- t4 = /* @__PURE__ */ jsx(TabsContent, {
90
+ $[16] = onOpenChange;
91
+ $[17] = open;
92
+ $[18] = projectId;
93
+ $[19] = t11;
94
+ } else t11 = $[19];
95
+ let t12;
96
+ if ($[20] !== t11) {
97
+ t12 = /* @__PURE__ */ jsx(TabsContent, {
56
98
  value: "archived",
57
99
  className: "overflow-y-auto",
58
- children: t3
100
+ children: t11
59
101
  });
60
- $[6] = t3;
61
- $[7] = t4;
62
- } else t4 = $[7];
63
- let t5;
64
- if ($[8] !== onOpenChange || $[9] !== open || $[10] !== projectId) {
65
- t5 = open && /* @__PURE__ */ jsx(PublishedTab, {
102
+ $[20] = t11;
103
+ $[21] = t12;
104
+ } else t12 = $[21];
105
+ let t13;
106
+ if ($[22] !== onOpenChange || $[23] !== open || $[24] !== projectId) {
107
+ t13 = open && /* @__PURE__ */ jsx(PublishedTab, {
66
108
  projectId,
67
109
  onEntered: () => onOpenChange(false)
68
110
  });
69
- $[8] = onOpenChange;
70
- $[9] = open;
71
- $[10] = projectId;
72
- $[11] = t5;
73
- } else t5 = $[11];
74
- let t6;
75
- if ($[12] !== t5) {
76
- t6 = /* @__PURE__ */ jsx(TabsContent, {
111
+ $[22] = onOpenChange;
112
+ $[23] = open;
113
+ $[24] = projectId;
114
+ $[25] = t13;
115
+ } else t13 = $[25];
116
+ let t14;
117
+ if ($[26] !== t13) {
118
+ t14 = /* @__PURE__ */ jsx(TabsContent, {
77
119
  value: "published",
78
120
  className: "overflow-y-auto",
79
- children: t5
121
+ children: t13
80
122
  });
81
- $[12] = t5;
82
- $[13] = t6;
83
- } else t6 = $[13];
84
- let t7;
85
- if ($[14] !== t4 || $[15] !== t6) {
86
- t7 = /* @__PURE__ */ jsxs(SheetContent, {
123
+ $[26] = t13;
124
+ $[27] = t14;
125
+ } else t14 = $[27];
126
+ let t15;
127
+ if ($[28] !== t10 || $[29] !== t12 || $[30] !== t14) {
128
+ t15 = /* @__PURE__ */ jsxs(SheetContent, {
87
129
  side: "right",
88
130
  className: "gap-0 data-[side=right]:sm:max-w-3xl",
89
- children: [t1, /* @__PURE__ */ jsxs(Tabs, {
131
+ children: [t5, /* @__PURE__ */ jsxs(Tabs, {
90
132
  defaultValue: "archived",
91
133
  className: "flex-1 overflow-hidden p-4",
92
134
  children: [
93
- t2,
94
- t4,
95
- t6
135
+ t10,
136
+ t12,
137
+ t14
96
138
  ]
97
139
  })]
98
140
  });
99
- $[14] = t4;
100
- $[15] = t6;
101
- $[16] = t7;
102
- } else t7 = $[16];
103
- let t8;
104
- if ($[17] !== onOpenChange || $[18] !== open || $[19] !== t7) {
105
- t8 = /* @__PURE__ */ jsx(Sheet, {
141
+ $[28] = t10;
142
+ $[29] = t12;
143
+ $[30] = t14;
144
+ $[31] = t15;
145
+ } else t15 = $[31];
146
+ let t16;
147
+ if ($[32] !== onOpenChange || $[33] !== open || $[34] !== t15) {
148
+ t16 = /* @__PURE__ */ jsx(Sheet, {
106
149
  open,
107
150
  onOpenChange,
108
- children: t7
151
+ children: t15
152
+ });
153
+ $[32] = onOpenChange;
154
+ $[33] = open;
155
+ $[34] = t15;
156
+ $[35] = t16;
157
+ } else t16 = $[35];
158
+ return t16;
159
+ }
160
+ /** How many items a tab holds, once they've loaded. */
161
+ function TabCount(t0) {
162
+ const $ = c(2);
163
+ const { count } = t0;
164
+ if (count === void 0) return null;
165
+ let t1;
166
+ if ($[0] !== count) {
167
+ t1 = /* @__PURE__ */ jsx("span", {
168
+ className: "text-muted-foreground tabular-nums",
169
+ children: count
109
170
  });
110
- $[17] = onOpenChange;
111
- $[18] = open;
112
- $[19] = t7;
113
- $[20] = t8;
114
- } else t8 = $[20];
115
- return t8;
171
+ $[0] = count;
172
+ $[1] = t1;
173
+ } else t1 = $[1];
174
+ return t1;
116
175
  }
117
176
  /** The archived drafts, each with Restore and Delete. */
118
177
  function ArchivedDrafts(t0) {
@@ -1,4 +1,5 @@
1
1
  import { cn } from "../../../lib/utils.js";
2
+ import { ZoomableImage } from "../../preview/components/ZoomableImage.js";
2
3
  import { Squareling } from "./Squareling.js";
3
4
  import { ThreadMarkdown } from "./ThreadMarkdown.js";
4
5
  import { c } from "react/compiler-runtime";
@@ -706,15 +707,10 @@ function AttachmentThumbnails(t0) {
706
707
  } else t7 = $[8];
707
708
  let t8;
708
709
  if ($[9] !== opened) {
709
- t8 = opened && /* @__PURE__ */ jsx("div", {
710
- className: "checkered absolute inset-0 flex items-center justify-center overflow-hidden p-6",
711
- children: /* @__PURE__ */ jsx("img", {
712
- src: opened.url,
713
- alt: opened.filename,
714
- className: "max-h-full max-w-full object-contain shadow-lg",
715
- draggable: false
716
- })
717
- });
710
+ t8 = opened && /* @__PURE__ */ jsx(ZoomableImage, {
711
+ src: opened.url,
712
+ alt: opened.filename
713
+ }, opened.url);
718
714
  $[9] = opened;
719
715
  $[10] = t8;
720
716
  } else t8 = $[10];
@@ -3,6 +3,7 @@ import { useViewLocale } from "../../lib/view-locale-context.js";
3
3
  import { useLocation, useNavigate } from "../navigation/navigation.js";
4
4
  import { useProjectUuid } from "../../lib/auth.js";
5
5
  import { reads, useStudioCache } from "../../lib/studio-reads.js";
6
+ import { fieldOwner, ownerSelection, slotSelection } from "../../core/editing/fieldSlot.js";
6
7
  import { previewStore, sameEditingOwner } from "../preview/previewStore.js";
7
8
  import { fieldTypesDictionary } from "../../core/lib/fieldTypes.js";
8
9
  import { c } from "react/compiler-runtime";
@@ -18,27 +19,16 @@ const isFieldType = (kind) => !!kind && Object.hasOwn(fieldTypesDictionary, kind
18
19
  /** What to select on the target's page: its field, else its item or block, else nothing. */
19
20
  function selectionOf({ blockId, itemId, field }) {
20
21
  if (!blockId) return null;
21
- const fieldType = field && isFieldType(field.kind) ? field.kind : null;
22
- if (itemId) return field && fieldType ? {
23
- type: "item-field",
24
- blockId,
25
- itemId,
26
- fieldName: field.name,
27
- fieldType
28
- } : {
29
- type: "item",
22
+ const owner = fieldOwner({
30
23
  blockId,
31
24
  itemId
32
- };
33
- return field && fieldType ? {
34
- type: "block-field",
35
- blockId,
36
- fieldName: field.name,
37
- fieldType
38
- } : {
39
- type: "block",
40
- blockId
41
- };
25
+ });
26
+ if (!field || !isFieldType(field.kind)) return ownerSelection(owner);
27
+ return slotSelection({
28
+ owner,
29
+ name: field.name,
30
+ type: field.kind
31
+ });
42
32
  }
43
33
  /** Stops selecting what was last shown in the Canvas. */
44
34
  let stopSelecting = null;
@@ -1,11 +1,11 @@
1
1
  import { placedRecords } from "../../lib/normalized-data.js";
2
2
  import { reads, useReadQuery } from "../../lib/studio-reads.js";
3
3
  import { useBlockDefinition, useCollectionDefinition } from "../../lib/studio-definitions.js";
4
- import { isBlockPlacement, previewStore, selectionBlockId, selectionForOwner, selectionItemId } from "../preview/previewStore.js";
4
+ import { isBlockPlacement, slotOf } from "../../core/editing/fieldSlot.js";
5
+ import { previewStore, selectionBlockId, selectionForOwner, selectionItemId } from "../preview/previewStore.js";
5
6
  import { entityName } from "../preview/entityName.js";
6
- import { contentFieldSchema } from "../preview/components/contentFieldSchema.js";
7
- import { formatFieldName } from "../preview/components/ItemFieldsEditor.js";
8
- import { getSchemaForItem } from "../preview/components/SelectionEditor.js";
7
+ import { itemContentSchema, itemPath } from "../preview/repeatableItemPath.js";
8
+ import { contentFieldSchema, formatFieldName } from "../preview/components/contentFieldSchema.js";
9
9
  import { c } from "react/compiler-runtime";
10
10
  import { useSelector } from "@xstate/store-react";
11
11
 
@@ -32,14 +32,8 @@ function editorSelectionOf({ selection, block, items, schema, records, recordSch
32
32
  for (const item of items) path.push(entityName(item, "Item"));
33
33
  const recordSelected = selection.type === "record" || selection.type === "record-field";
34
34
  if (recordSelected) path.push(...records.length > 0 ? records.map((record) => record.title || "Record") : ["Record"]);
35
- let fieldName;
36
- if (selection.type === "block-field" || selection.type === "item-field") {
37
- fieldName = selection.fieldName;
38
- path.push(fieldLabel(schema, fieldName));
39
- } else if (selection.type === "record-field") {
40
- fieldName = selection.recordFieldName;
41
- path.push(fieldLabel(recordSchema, fieldName));
42
- }
35
+ const fieldName = slotOf(selection)?.name;
36
+ if (fieldName) path.push(fieldLabel(recordSelected ? recordSchema : schema, fieldName));
43
37
  const itemId = selectionItemId(selection) ?? void 0;
44
38
  const recordId = recordSelected ? selection.nested?.recordId ?? selection.recordId : void 0;
45
39
  return {
@@ -94,13 +88,8 @@ function useEditorSelection(where) {
94
88
  $[8] = t4;
95
89
  $[9] = t5;
96
90
  } else t5 = $[9];
97
- const itemsMap = t5;
98
- const items = [];
99
- for (let item_0 = itemId ? itemsMap.get(itemId) : void 0; item_0;) {
100
- items.unshift(item_0);
101
- item_0 = item_0.parentItemId ? itemsMap.get(item_0.parentItemId) : void 0;
102
- }
103
- const schema = blockDef && itemId ? getSchemaForItem(blockDef.contentSchema, itemId, itemsMap) : blockDef?.contentSchema;
91
+ const items = itemPath(itemId, t5);
92
+ const schema = blockDef && itemContentSchema(blockDef.contentSchema, items);
104
93
  const records = [];
105
94
  if ((selection?.type === "record" || selection?.type === "record-field") && isBlockPlacement(selection)) {
106
95
  const placer = itemId ? items.at(-1) : bundle?.block;
package/dist/package.js CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
- var version = "0.76.0";
2
+ var version = "0.76.1";
3
3
 
4
4
  //#endregion
5
5
  export { version };