camox 0.60.2 → 0.62.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.
- package/dist/core/createApp.d.ts +8 -8
- package/dist/core/createBlock.d.ts +1 -2
- package/dist/core/createLayout.d.ts +10 -2
- package/dist/core/createLayout.js +1 -3
- package/dist/core/editing/BlockEditingRuntime.d.ts +1 -0
- package/dist/core/editing/CompleteBlockEditingRuntime.js +12 -9
- package/dist/core/editing/createEditableBlock.d.ts +4 -4
- package/dist/core/editing/createEditableBlock.js +19 -25
- package/dist/core/lib/artifactData.js +2 -2
- package/dist/core/lib/contentType.js +5 -4
- package/dist/features/content/CamoxContent.js +40 -32
- package/dist/features/renderer/rendererHost.js +23 -16
- package/dist/features/renderer/studioConnection.js +8 -4
- package/dist/features/sdkBundle/buildSdkBundle.js +0 -1
- package/dist/features/sdkBundle/localSdkBundle.js +2 -2
- package/dist/features/sdkBundle/sdkBundleName.d.ts +0 -1
- package/dist/features/sdkBundle/sdkBundleName.js +0 -1
- package/dist/features/settings/CamoxSettings.js +5 -0
- package/dist/features/settings/ExperimentalFeaturesSettings.js +74 -0
- package/dist/features/settings/useProjectMutation.js +6 -5
- package/dist/features/vite/vite.d.ts +0 -2
- package/dist/features/vite/vite.js +0 -2
- package/dist/lib/queries.js +1 -0
- package/dist/package.js +1 -1
- package/dist/studio.css +1 -1
- package/package.json +4 -4
- package/skills/camox/references/field-styling.md +2 -2
- package/skills/camoxify/SKILL.md +1 -1
package/dist/core/createApp.d.ts
CHANGED
|
@@ -139,7 +139,7 @@ export declare function createApp({ blocks, lazyBlocks, layouts, collections, do
|
|
|
139
139
|
[attribute: `data-camox-${string}`]: string | boolean | undefined;
|
|
140
140
|
}, data: FileValue) => React.ReactNode;
|
|
141
141
|
}) => React.ReactNode;
|
|
142
|
-
Repeater: <K extends never>(
|
|
142
|
+
Repeater: <K extends never>(props: {
|
|
143
143
|
name: K;
|
|
144
144
|
children: (item: {
|
|
145
145
|
Field: <F extends keyof { [F_1 in keyof ({}[K] extends (infer U)[] ? U : never) as ({}[K] extends (infer U)[] ? U : never)[F_1] extends IconValue | ArtifactSource ? never : ({}[K] extends (infer U)[] ? U : never)[F_1] extends string ? F_1 : never]: ({}[K] extends (infer U)[] ? U : never)[F_1]; }>(props: InlineTextStyles & {
|
|
@@ -402,12 +402,12 @@ export declare function createApp({ blocks, lazyBlocks, layouts, collections, do
|
|
|
402
402
|
}) => React.ReactNode;
|
|
403
403
|
useSetting: <F extends string>(name: F) => never;
|
|
404
404
|
}, index: number) => React.ReactNode;
|
|
405
|
-
}) =>
|
|
406
|
-
Reference: <K extends never>(
|
|
405
|
+
}) => React.ReactNode;
|
|
406
|
+
Reference: <K extends never>(props: {
|
|
407
407
|
name: K;
|
|
408
408
|
children: (scope: ReferenceScope<never>) => React.ReactNode;
|
|
409
409
|
}) => React.ReactNode;
|
|
410
|
-
ReferenceList: <K extends never>(
|
|
410
|
+
ReferenceList: <K extends never>(props: {
|
|
411
411
|
name: K;
|
|
412
412
|
children: (scope: ReferenceScope<never>) => React.ReactNode;
|
|
413
413
|
}) => React.ReactNode;
|
|
@@ -581,7 +581,7 @@ export declare function createApp({ blocks, lazyBlocks, layouts, collections, do
|
|
|
581
581
|
[attribute: `data-camox-${string}`]: string | boolean | undefined;
|
|
582
582
|
}, data: FileValue) => React.ReactNode;
|
|
583
583
|
}) => React.ReactNode;
|
|
584
|
-
Repeater: <K extends never>(
|
|
584
|
+
Repeater: <K extends never>(props: {
|
|
585
585
|
name: K;
|
|
586
586
|
children: (item: {
|
|
587
587
|
Field: <F extends keyof { [F_1 in keyof ({}[K] extends (infer U)[] ? U : never) as ({}[K] extends (infer U)[] ? U : never)[F_1] extends IconValue | ArtifactSource ? never : ({}[K] extends (infer U)[] ? U : never)[F_1] extends string ? F_1 : never]: ({}[K] extends (infer U)[] ? U : never)[F_1]; }>(props: InlineTextStyles & {
|
|
@@ -844,12 +844,12 @@ export declare function createApp({ blocks, lazyBlocks, layouts, collections, do
|
|
|
844
844
|
}) => React.ReactNode;
|
|
845
845
|
useSetting: <F extends string>(name: F) => never;
|
|
846
846
|
}, index: number) => React.ReactNode;
|
|
847
|
-
}) =>
|
|
848
|
-
Reference: <K extends never>(
|
|
847
|
+
}) => React.ReactNode;
|
|
848
|
+
Reference: <K extends never>(props: {
|
|
849
849
|
name: K;
|
|
850
850
|
children: (scope: ReferenceScope<never>) => React.ReactNode;
|
|
851
851
|
}) => React.ReactNode;
|
|
852
|
-
ReferenceList: <K extends never>(
|
|
852
|
+
ReferenceList: <K extends never>(props: {
|
|
853
853
|
name: K;
|
|
854
854
|
children: (scope: ReferenceScope<never>) => React.ReactNode;
|
|
855
855
|
}) => React.ReactNode;
|
|
@@ -3,8 +3,7 @@ import "./lib/lexicalReact.js";
|
|
|
3
3
|
import { ContentFieldBuilder, SettingBuilder } from "./lib/contentType.js";
|
|
4
4
|
import { BlockComponentProps, PeekItem, RepeatableItemSeed, createEditableBlock } from "./editing/createEditableBlock.js";
|
|
5
5
|
//#region src/core/createBlock.d.ts
|
|
6
|
-
|
|
7
|
-
export declare const createBlock: EditableCreateBlock;
|
|
6
|
+
export declare const createBlock: typeof createEditableBlock;
|
|
8
7
|
export type Block = ReturnType<typeof createBlock>;
|
|
9
8
|
//#endregion
|
|
10
9
|
export type { BlockComponentProps, ContentFieldBuilder, InlineStyle, InlineTextStyles, PeekItem, RepeatableItemSeed, SettingBuilder, TextLinkStyleData, TextStyleData };
|
|
@@ -211,8 +211,16 @@ type CreateLayoutOptions<TBefore extends readonly LayoutBlock[], TAfter extends
|
|
|
211
211
|
} & LayoutOutputs<LoadedContext<LoaderData<Result>, Record<string, string>, RecordFields<Result>>, {
|
|
212
212
|
children: React.ReactNode;
|
|
213
213
|
}, Declared>;
|
|
214
|
-
/**
|
|
215
|
-
|
|
214
|
+
/**
|
|
215
|
+
* Every option a layout may define, as the implementation reads them. The public signatures
|
|
216
|
+
* validated which slot each block may go in.
|
|
217
|
+
*/
|
|
218
|
+
type AnyLayoutOptions = Omit<LayoutBaseOptions<any, any, any>, "blocks"> & {
|
|
219
|
+
blocks: {
|
|
220
|
+
before: readonly LayoutBlock<true>[];
|
|
221
|
+
after: readonly LayoutBlock<true>[];
|
|
222
|
+
initial?: readonly InitialBlockImport[];
|
|
223
|
+
};
|
|
216
224
|
kind?: "curated" | "derived" | "singleton";
|
|
217
225
|
loader?: (context: LayoutLoaderContext) => LoaderReturn;
|
|
218
226
|
routes?: (context: LayoutRoutesContext) => RoutesReturn<Record<string, string>>;
|
|
@@ -16,9 +16,7 @@ function createLayoutDefinition(options) {
|
|
|
16
16
|
if (options.routes && options.kind !== "derived") throw new Error(`Only derived layouts can define routes: ${options.id}`);
|
|
17
17
|
if (options.toMarkdown && (options.kind ?? "curated") === "curated") throw new Error(`Curated layouts cannot define toMarkdown: ${options.id}`);
|
|
18
18
|
const LayoutContext = React.createContext(null);
|
|
19
|
-
const beforeBlocks = options.blocks
|
|
20
|
-
const afterBlocks = options.blocks.after;
|
|
21
|
-
const initialBlocks = options.blocks.initial;
|
|
19
|
+
const { before: beforeBlocks, after: afterBlocks, initial: initialBlocks } = options.blocks;
|
|
22
20
|
const BeforeBlocks = () => {
|
|
23
21
|
const $ = c(4);
|
|
24
22
|
const ctx = React.use(LayoutContext);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { LoadedRecord } from "../requestContext.js";
|
|
2
2
|
import { Collection } from "../createCollection.js";
|
|
3
|
+
import "./createEditableBlock.js";
|
|
3
4
|
import * as React from "react";
|
|
4
5
|
//#region src/core/editing/BlockEditingRuntime.d.ts
|
|
5
6
|
/** A record page's record, as `layout.Item` hands it to the editing runtime. */
|
|
@@ -13,6 +13,10 @@ function getEditableDefinition(options) {
|
|
|
13
13
|
editableDefinitions.set(options, definition);
|
|
14
14
|
return definition;
|
|
15
15
|
}
|
|
16
|
+
/** A primitive of the editable definition, rendered with the props the view block received. */
|
|
17
|
+
function editingPrimitive(definition, primitive) {
|
|
18
|
+
return definition[primitive];
|
|
19
|
+
}
|
|
16
20
|
function EditableBlock(t0) {
|
|
17
21
|
const $ = c(5);
|
|
18
22
|
const { options, props } = t0;
|
|
@@ -23,15 +27,14 @@ function EditableBlock(t0) {
|
|
|
23
27
|
$[1] = t1;
|
|
24
28
|
} else t1 = $[1];
|
|
25
29
|
const Component = t1._internal.Component;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
t3 = /* @__PURE__ */ jsx(Component, { ...t2 });
|
|
30
|
+
let t2;
|
|
31
|
+
if ($[2] !== Component || $[3] !== props) {
|
|
32
|
+
t2 = /* @__PURE__ */ jsx(Component, { ...props });
|
|
30
33
|
$[2] = Component;
|
|
31
|
-
$[3] =
|
|
32
|
-
$[4] =
|
|
33
|
-
} else
|
|
34
|
-
return
|
|
34
|
+
$[3] = props;
|
|
35
|
+
$[4] = t2;
|
|
36
|
+
} else t2 = $[4];
|
|
37
|
+
return t2;
|
|
35
38
|
}
|
|
36
39
|
/** Record pages' records render through the record scope of a block without fields. */
|
|
37
40
|
const layoutItemOptions = {
|
|
@@ -58,7 +61,7 @@ const completeEditingRuntime = {
|
|
|
58
61
|
});
|
|
59
62
|
},
|
|
60
63
|
renderPrimitive(options, primitive, props) {
|
|
61
|
-
const Primitive = getEditableDefinition(options)
|
|
64
|
+
const Primitive = editingPrimitive(getEditableDefinition(options), primitive);
|
|
62
65
|
if (!Primitive) throw new Error(`Unknown Camox editing primitive: ${primitive}`);
|
|
63
66
|
return /* @__PURE__ */ jsx(Primitive, { ...props });
|
|
64
67
|
}
|
|
@@ -527,7 +527,7 @@ export declare function createEditableBlock<TSchemaShape extends Record<string,
|
|
|
527
527
|
params: unknown[] & [];
|
|
528
528
|
})["static"]; }, { [K_4 in keyof TSchemaShape]: TSchemaShape[K_4] extends import("@sinclair/typebox").TOptional<TSchema> ? TSchemaShape[K_4] extends import("@sinclair/typebox").TReadonly<TSchemaShape[K_4]> ? never : K_4 : never; }[keyof TSchemaShape]>> & Required<Pick<{ [K_1 in keyof TSchemaShape]: (TSchemaShape[K_1] & {
|
|
529
529
|
params: unknown[] & [];
|
|
530
|
-
})["static"]; }, Exclude<keyof TSchemaShape, { [K_2 in keyof TSchemaShape]: TSchemaShape[K_2] extends import("@sinclair/typebox").TReadonly<TSchema> ? TSchemaShape[K_2] extends import("@sinclair/typebox").TOptional<TSchemaShape[K_2]> ? K_2 : never : never; }[keyof TSchemaShape] | { [K_3 in keyof TSchemaShape]: TSchemaShape[K_3] extends import("@sinclair/typebox").TReadonly<TSchema> ? TSchemaShape[K_3] extends import("@sinclair/typebox").TOptional<TSchemaShape[K_3]> ? never : K_3 : never; }[keyof TSchemaShape] | { [K_4 in keyof TSchemaShape]: TSchemaShape[K_4] extends import("@sinclair/typebox").TOptional<TSchema> ? TSchemaShape[K_4] extends import("@sinclair/typebox").TReadonly<TSchemaShape[K_4]> ? never : K_4 : never; }[keyof TSchemaShape]>>>>[K_5]; }>(
|
|
530
|
+
})["static"]; }, Exclude<keyof TSchemaShape, { [K_2 in keyof TSchemaShape]: TSchemaShape[K_2] extends import("@sinclair/typebox").TReadonly<TSchema> ? TSchemaShape[K_2] extends import("@sinclair/typebox").TOptional<TSchemaShape[K_2]> ? K_2 : never : never; }[keyof TSchemaShape] | { [K_3 in keyof TSchemaShape]: TSchemaShape[K_3] extends import("@sinclair/typebox").TReadonly<TSchema> ? TSchemaShape[K_3] extends import("@sinclair/typebox").TOptional<TSchemaShape[K_3]> ? never : K_3 : never; }[keyof TSchemaShape] | { [K_4 in keyof TSchemaShape]: TSchemaShape[K_4] extends import("@sinclair/typebox").TOptional<TSchema> ? TSchemaShape[K_4] extends import("@sinclair/typebox").TReadonly<TSchemaShape[K_4]> ? never : K_4 : never; }[keyof TSchemaShape]>>>>[K_5]; }>(props: {
|
|
531
531
|
name: K;
|
|
532
532
|
children: (item: {
|
|
533
533
|
Field: <F extends keyof { [F_1 in keyof ({ [K_5 in keyof import("@sinclair/typebox").Evaluate<Readonly<Partial<Pick<{ [K_1 in keyof TSchemaShape]: (TSchemaShape[K_1] & {
|
|
@@ -1652,12 +1652,12 @@ export declare function createEditableBlock<TSchemaShape extends Record<string,
|
|
|
1652
1652
|
params: unknown[] & [];
|
|
1653
1653
|
})["static"]; }, Exclude<keyof S, { [K_7 in keyof S]: S[K_7] extends import("@sinclair/typebox").TReadonly<TSchema> ? S[K_7] extends import("@sinclair/typebox").TOptional<S[K_7]> ? K_7 : never : never; }[keyof S] | { [K_8 in keyof S]: S[K_8] extends import("@sinclair/typebox").TReadonly<TSchema> ? S[K_8] extends import("@sinclair/typebox").TOptional<S[K_8]> ? never : K_8 : never; }[keyof S] | { [K_9 in keyof S]: S[K_9] extends import("@sinclair/typebox").TOptional<TSchema> ? S[K_9] extends import("@sinclair/typebox").TReadonly<S[K_9]> ? never : K_9 : never; }[keyof S]>>>> : Record<string, never> : Record<string, never>)[F];
|
|
1654
1654
|
}, index: number) => React.ReactNode;
|
|
1655
|
-
}) => React.
|
|
1656
|
-
Reference: <K extends ReferenceKeys<TSchemaShape>>(
|
|
1655
|
+
}) => React.ReactNode;
|
|
1656
|
+
Reference: <K extends ReferenceKeys<TSchemaShape>>(props: {
|
|
1657
1657
|
name: K;
|
|
1658
1658
|
children: (scope: ReferenceScope<ReferenceContent<TSchemaShape[K]>>) => React.ReactNode;
|
|
1659
1659
|
}) => React.ReactNode;
|
|
1660
|
-
ReferenceList: <K extends ReferenceListKeys<TSchemaShape>>(
|
|
1660
|
+
ReferenceList: <K extends ReferenceListKeys<TSchemaShape>>(props: {
|
|
1661
1661
|
name: K;
|
|
1662
1662
|
children: (scope: ReferenceScope<ReferenceContent<TSchemaShape[K]>>) => React.ReactNode;
|
|
1663
1663
|
}) => React.ReactNode;
|
|
@@ -1455,7 +1455,7 @@ function createEditableBlock(options) {
|
|
|
1455
1455
|
} else t4 = $[5];
|
|
1456
1456
|
return t4;
|
|
1457
1457
|
};
|
|
1458
|
-
const
|
|
1458
|
+
const RepeaterImpl = (t0) => {
|
|
1459
1459
|
const $ = c(29);
|
|
1460
1460
|
const { name, children } = t0;
|
|
1461
1461
|
const blockContext = React.use(Context);
|
|
@@ -1463,16 +1463,7 @@ function createEditableBlock(options) {
|
|
|
1463
1463
|
const { blockId, content, mode } = blockContext;
|
|
1464
1464
|
const parentRepeaterContext = React.use(RepeatableItemContext);
|
|
1465
1465
|
const fieldName = String(name);
|
|
1466
|
-
const
|
|
1467
|
-
const ItemLink = Link;
|
|
1468
|
-
const ItemEmbed = Embed;
|
|
1469
|
-
const ItemArtifact = Artifact;
|
|
1470
|
-
const ItemImage = Image;
|
|
1471
|
-
const ItemImageList = _AssetList;
|
|
1472
|
-
const ItemFileList = _AssetList;
|
|
1473
|
-
const ItemFile = File;
|
|
1474
|
-
const ItemRepeater = Repeater;
|
|
1475
|
-
const source = parentRepeaterContext ? parentRepeaterContext.itemContent[name] : content[name];
|
|
1466
|
+
const source = parentRepeaterContext ? parentRepeaterContext.itemContent[fieldName] : content[fieldName];
|
|
1476
1467
|
const { itemsMap } = useNormalizedData();
|
|
1477
1468
|
let t1;
|
|
1478
1469
|
if ($[0] !== source) {
|
|
@@ -1481,7 +1472,7 @@ function createEditableBlock(options) {
|
|
|
1481
1472
|
$[1] = t1;
|
|
1482
1473
|
} else t1 = $[1];
|
|
1483
1474
|
const storedValue = t1;
|
|
1484
|
-
if (!Array.isArray(storedValue)) throw new Error(`Field "${
|
|
1475
|
+
if (!Array.isArray(storedValue)) throw new Error(`Field "${fieldName}" is not an array`);
|
|
1485
1476
|
let T0;
|
|
1486
1477
|
let t2;
|
|
1487
1478
|
let t3;
|
|
@@ -1518,18 +1509,18 @@ function createEditableBlock(options) {
|
|
|
1518
1509
|
const itemId = isDbItem ? item_0.id : void 0;
|
|
1519
1510
|
const useItemSetting = (settingName) => itemSettings[settingName];
|
|
1520
1511
|
const itemApi = {
|
|
1521
|
-
Field
|
|
1522
|
-
Link
|
|
1512
|
+
Field,
|
|
1513
|
+
Link,
|
|
1523
1514
|
Icon,
|
|
1524
|
-
Embed
|
|
1525
|
-
Artifact
|
|
1526
|
-
Image
|
|
1527
|
-
File
|
|
1528
|
-
ImageList:
|
|
1529
|
-
FileList:
|
|
1530
|
-
Repeater:
|
|
1531
|
-
Reference,
|
|
1532
|
-
ReferenceList,
|
|
1515
|
+
Embed,
|
|
1516
|
+
Artifact,
|
|
1517
|
+
Image,
|
|
1518
|
+
File,
|
|
1519
|
+
ImageList: _AssetList,
|
|
1520
|
+
FileList: _AssetList,
|
|
1521
|
+
Repeater: RepeaterImpl,
|
|
1522
|
+
Reference: ReferenceImpl,
|
|
1523
|
+
ReferenceList: ReferenceListImpl,
|
|
1533
1524
|
useSetting: useItemSetting
|
|
1534
1525
|
};
|
|
1535
1526
|
return /* @__PURE__ */ jsx(RepeatableItemContext.Provider, {
|
|
@@ -1595,6 +1586,7 @@ function createEditableBlock(options) {
|
|
|
1595
1586
|
} else t5 = $[28];
|
|
1596
1587
|
return t5;
|
|
1597
1588
|
};
|
|
1589
|
+
const Repeater = RepeaterImpl;
|
|
1598
1590
|
const BlockComponent = (t0) => {
|
|
1599
1591
|
const $ = c(63);
|
|
1600
1592
|
const { blockData, mode, isFirstBlock, showAddBlockTop, showAddBlockBottom, addBlockAfterPosition } = t0;
|
|
@@ -2313,7 +2305,7 @@ function createEditableBlock(options) {
|
|
|
2313
2305
|
} else t4 = $[9];
|
|
2314
2306
|
return t4;
|
|
2315
2307
|
};
|
|
2316
|
-
const
|
|
2308
|
+
const ReferenceImpl = (t0) => {
|
|
2317
2309
|
const $ = c(21);
|
|
2318
2310
|
const { name, children } = t0;
|
|
2319
2311
|
const block = React.use(Context);
|
|
@@ -2386,6 +2378,7 @@ function createEditableBlock(options) {
|
|
|
2386
2378
|
} else t4 = $[20];
|
|
2387
2379
|
return t4;
|
|
2388
2380
|
};
|
|
2381
|
+
const Reference = ReferenceImpl;
|
|
2389
2382
|
const ListedRecord = (t0) => {
|
|
2390
2383
|
const $ = c(14);
|
|
2391
2384
|
const { block, owner, field, fieldName, record, listHovered, children } = t0;
|
|
@@ -2565,7 +2558,7 @@ function createEditableBlock(options) {
|
|
|
2565
2558
|
} else t3 = $[8];
|
|
2566
2559
|
return t3;
|
|
2567
2560
|
};
|
|
2568
|
-
const
|
|
2561
|
+
const ReferenceListImpl = (t0) => {
|
|
2569
2562
|
const $ = c(44);
|
|
2570
2563
|
const { name, children } = t0;
|
|
2571
2564
|
const block = React.use(Context);
|
|
@@ -2698,6 +2691,7 @@ function createEditableBlock(options) {
|
|
|
2698
2691
|
if (t5 !== Symbol.for("react.early_return_sentinel")) return t5;
|
|
2699
2692
|
return t4;
|
|
2700
2693
|
};
|
|
2694
|
+
const ReferenceList = ReferenceListImpl;
|
|
2701
2695
|
const Detached = (t0) => {
|
|
2702
2696
|
const $ = c(30);
|
|
2703
2697
|
const { children } = t0;
|
|
@@ -87,7 +87,7 @@ function attachArtifactData(content, settings, owner) {
|
|
|
87
87
|
sources[name] = source;
|
|
88
88
|
}
|
|
89
89
|
field.dataSchema = objectSchema(Object.fromEntries(Object.entries(sources).map(([name, s]) => [name, valueSchema(s.schema)])));
|
|
90
|
-
|
|
90
|
+
field[DATA_SOURCES] = sources;
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
function normalizeAsset(fieldType, file) {
|
|
@@ -122,7 +122,7 @@ function normalizeValue(schema, value, resolve) {
|
|
|
122
122
|
* to hrefs and assets to URLs. Artifacts without `data` receive an empty object.
|
|
123
123
|
*/
|
|
124
124
|
function artifactData(field, owner, resolve) {
|
|
125
|
-
const sources = field
|
|
125
|
+
const sources = field?.[DATA_SOURCES];
|
|
126
126
|
if (!sources) return {};
|
|
127
127
|
return Object.fromEntries(Object.entries(sources).map(([name, { scope, schema }]) => [name, normalizeValue(schema, owner[scope][name], resolve)]));
|
|
128
128
|
}
|
|
@@ -43,6 +43,7 @@ var Conditional = class {
|
|
|
43
43
|
return "{{/if}}";
|
|
44
44
|
}
|
|
45
45
|
};
|
|
46
|
+
/** Reads each field as its token. `TProxy` is how the template reads the fields. */
|
|
46
47
|
function createContentProxy(shape, prefix = "") {
|
|
47
48
|
return new Proxy({}, { get(_target, prop) {
|
|
48
49
|
if (typeof prop !== "string") return void 0;
|
|
@@ -58,8 +59,8 @@ function createContentProxy(shape, prefix = "") {
|
|
|
58
59
|
*/
|
|
59
60
|
function referenceToken(shape, path) {
|
|
60
61
|
const fields = createContentProxy(shape, path);
|
|
61
|
-
return new Proxy(new FieldToken(path), { get(target, prop
|
|
62
|
-
if (typeof prop !== "string" || prop in target) return
|
|
62
|
+
return new Proxy(new FieldToken(path), { get(target, prop) {
|
|
63
|
+
if (typeof prop !== "string" || prop in target) return target[prop];
|
|
63
64
|
return fields[prop];
|
|
64
65
|
} });
|
|
65
66
|
}
|
|
@@ -156,10 +157,10 @@ function resolveRecordStructuredData(builder, contentShape) {
|
|
|
156
157
|
const ARTIFACT_MAX_LENGTH = 262144;
|
|
157
158
|
const IMAGE_PLACEHOLDER = Symbol("camox.imagePlaceholder");
|
|
158
159
|
function isImagePlaceholder(value) {
|
|
159
|
-
return typeof
|
|
160
|
+
return typeof value[IMAGE_PLACEHOLDER] === "string" && !value._fileId;
|
|
160
161
|
}
|
|
161
162
|
function getImagePlaceholderTitle(value) {
|
|
162
|
-
return
|
|
163
|
+
return value[IMAGE_PLACEHOLDER];
|
|
163
164
|
}
|
|
164
165
|
function _imageSingle(options) {
|
|
165
166
|
return Type.Unsafe({
|
|
@@ -13,54 +13,62 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
13
13
|
|
|
14
14
|
//#region src/features/content/CamoxContent.tsx
|
|
15
15
|
const CamoxContent = () => {
|
|
16
|
-
const $ = c(
|
|
16
|
+
const $ = c(9);
|
|
17
|
+
const projectUuid = useProjectUuid();
|
|
18
|
+
let t0;
|
|
19
|
+
if ($[0] !== projectUuid) {
|
|
20
|
+
t0 = reads.project({ projectUuid });
|
|
21
|
+
$[0] = projectUuid;
|
|
22
|
+
$[1] = t0;
|
|
23
|
+
} else t0 = $[1];
|
|
24
|
+
const { data: project } = useReadQuery(t0);
|
|
17
25
|
const pathname = useLocalePath();
|
|
18
26
|
const localized = useLocalizedPath();
|
|
19
27
|
if (pathname === "/camox/content" || pathname === `${"/camox/content"}/`) {
|
|
20
|
-
let t0;
|
|
21
|
-
if ($[0] !== localized) {
|
|
22
|
-
t0 = localized(STUDIO_ASSETS_PATH);
|
|
23
|
-
$[0] = localized;
|
|
24
|
-
$[1] = t0;
|
|
25
|
-
} else t0 = $[1];
|
|
26
28
|
let t1;
|
|
27
|
-
if ($[2] !==
|
|
28
|
-
t1 =
|
|
29
|
-
|
|
30
|
-
replace: true
|
|
31
|
-
});
|
|
32
|
-
$[2] = t0;
|
|
29
|
+
if ($[2] !== localized) {
|
|
30
|
+
t1 = localized(STUDIO_ASSETS_PATH);
|
|
31
|
+
$[2] = localized;
|
|
33
32
|
$[3] = t1;
|
|
34
33
|
} else t1 = $[3];
|
|
35
|
-
|
|
34
|
+
let t2;
|
|
35
|
+
if ($[4] !== t1) {
|
|
36
|
+
t2 = /* @__PURE__ */ jsx(Navigate, {
|
|
37
|
+
to: t1,
|
|
38
|
+
replace: true
|
|
39
|
+
});
|
|
40
|
+
$[4] = t1;
|
|
41
|
+
$[5] = t2;
|
|
42
|
+
} else t2 = $[5];
|
|
43
|
+
return t2;
|
|
36
44
|
}
|
|
37
|
-
if (
|
|
38
|
-
let
|
|
39
|
-
if ($[
|
|
40
|
-
|
|
41
|
-
$[
|
|
42
|
-
} else
|
|
43
|
-
return
|
|
45
|
+
if (project?.experimentalFeatures) {
|
|
46
|
+
let t1;
|
|
47
|
+
if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
|
|
48
|
+
t1 = /* @__PURE__ */ jsx(ExperimentalContent, {});
|
|
49
|
+
$[6] = t1;
|
|
50
|
+
} else t1 = $[6];
|
|
51
|
+
return t1;
|
|
44
52
|
}
|
|
45
|
-
let t0;
|
|
46
|
-
if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
|
|
47
|
-
t0 = [];
|
|
48
|
-
$[5] = t0;
|
|
49
|
-
} else t0 = $[5];
|
|
50
53
|
let t1;
|
|
51
|
-
if ($[
|
|
52
|
-
t1 =
|
|
54
|
+
if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
|
|
55
|
+
t1 = [];
|
|
56
|
+
$[7] = t1;
|
|
57
|
+
} else t1 = $[7];
|
|
58
|
+
let t2;
|
|
59
|
+
if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
|
|
60
|
+
t2 = /* @__PURE__ */ jsxs("div", {
|
|
53
61
|
className: "flex min-h-0 flex-1 flex-row",
|
|
54
62
|
children: [/* @__PURE__ */ jsx(ContentSidebar, {
|
|
55
|
-
collections:
|
|
63
|
+
collections: t1,
|
|
56
64
|
selectedCollectionId: null,
|
|
57
65
|
collectionsError: false,
|
|
58
66
|
children: /* @__PURE__ */ jsx(MissingFromLocaleGroup, { collections: [] })
|
|
59
67
|
}), /* @__PURE__ */ jsx(ContentAssets, {})]
|
|
60
68
|
});
|
|
61
|
-
$[
|
|
62
|
-
} else
|
|
63
|
-
return
|
|
69
|
+
$[8] = t2;
|
|
70
|
+
} else t2 = $[8];
|
|
71
|
+
return t2;
|
|
64
72
|
};
|
|
65
73
|
const ExperimentalContent = () => {
|
|
66
74
|
const $ = c(38);
|
|
@@ -6,14 +6,30 @@ import { createContentEditor } from "../../core/editing/contentEdits.js";
|
|
|
6
6
|
import { LIVE_KEY_SCOPE, scopeOfKey } from "@camox/api-contract/query-keys";
|
|
7
7
|
|
|
8
8
|
//#region src/features/renderer/rendererHost.ts
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
/** The studio's state of each store the renderer mirrors. */
|
|
10
|
+
const storeMessages = {
|
|
11
|
+
preview: () => ({
|
|
12
|
+
type: "store",
|
|
13
|
+
store: "preview",
|
|
14
|
+
context: previewStore.getSnapshot().context
|
|
15
|
+
}),
|
|
16
|
+
canvas: () => ({
|
|
17
|
+
type: "store",
|
|
18
|
+
store: "canvas",
|
|
19
|
+
context: canvasStore.getSnapshot().context
|
|
20
|
+
})
|
|
12
21
|
};
|
|
22
|
+
/** The stores the renderer forwards its events to, as the host applies them. */
|
|
13
23
|
const forwarded = {
|
|
14
24
|
preview: previewStore,
|
|
15
25
|
referencePickerFocus
|
|
16
26
|
};
|
|
27
|
+
/** Applies an event the renderer forwarded to the studio's store. */
|
|
28
|
+
const applyStoreEvent = (message) => {
|
|
29
|
+
const store = forwarded[message.store];
|
|
30
|
+
if (!store) return;
|
|
31
|
+
store.send(message.event);
|
|
32
|
+
};
|
|
17
33
|
/**
|
|
18
34
|
* The host of the studio whose cache is `studioCache`, viewing the draft `draftScope` names, which
|
|
19
35
|
* the renderer shows too. Without them, the renderer hears nothing of the studio's cache.
|
|
@@ -45,12 +61,8 @@ function createRendererHost({ studioCache, draftScope, queryClient, notify } = {
|
|
|
45
61
|
const post = (message) => {
|
|
46
62
|
if (welcomed) renderer?.(message);
|
|
47
63
|
};
|
|
48
|
-
const postStore = (store) => post(
|
|
49
|
-
|
|
50
|
-
store,
|
|
51
|
-
context: mirrored[store].getSnapshot().context
|
|
52
|
-
});
|
|
53
|
-
const subscriptions = Object.keys(mirrored).map((store) => mirrored[store].subscribe(() => postStore(store)));
|
|
64
|
+
const postStore = (store) => post(storeMessages[store]());
|
|
65
|
+
const subscriptions = [previewStore.subscribe(() => postStore("preview")), canvasStore.subscribe(() => postStore("canvas"))];
|
|
54
66
|
const shownScope = () => draftScope?.current() ?? LIVE_KEY_SCOPE;
|
|
55
67
|
const shown = (queryKey) => scopeOfKey(queryKey) === shownScope();
|
|
56
68
|
/** Whether a project room invalidation reaches the reads of the draft the renderer shows. */
|
|
@@ -103,7 +115,7 @@ function createRendererHost({ studioCache, draftScope, queryClient, notify } = {
|
|
|
103
115
|
if (message.sdkVersion !== SDK_VERSION) return setStatus("updating");
|
|
104
116
|
welcomed = true;
|
|
105
117
|
setStatus("connected");
|
|
106
|
-
for (const store of Object.keys(
|
|
118
|
+
for (const store of Object.keys(storeMessages)) postStore(store);
|
|
107
119
|
for (const [frameId, { slot, target }] of frames) post({
|
|
108
120
|
type: "frame",
|
|
109
121
|
frameId,
|
|
@@ -123,12 +135,7 @@ function createRendererHost({ studioCache, draftScope, queryClient, notify } = {
|
|
|
123
135
|
});
|
|
124
136
|
for (const listener of connectionListeners) listener();
|
|
125
137
|
return;
|
|
126
|
-
case "storeEvent":
|
|
127
|
-
const store = forwarded[message.store];
|
|
128
|
-
if (!store) return;
|
|
129
|
-
store.send(message.event);
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
138
|
+
case "storeEvent": return applyStoreEvent(message);
|
|
132
139
|
case "rendered": return frames.get(message.frameId)?.hears.rendered?.();
|
|
133
140
|
case "error": return frames.get(message.frameId)?.hears.failed?.(message.message);
|
|
134
141
|
case "navigate": return frames.get(message.frameId)?.hears.navigate?.(message.to);
|
|
@@ -5,14 +5,21 @@ import { SDK_VERSION, deferredInbox } from "./protocol.js";
|
|
|
5
5
|
import { answerFromCode } from "./definitionAnswers.js";
|
|
6
6
|
|
|
7
7
|
//#region src/features/renderer/studioConnection.ts
|
|
8
|
+
/** The stores of this document that take the studio's state as it is (`mirror`). */
|
|
8
9
|
const mirrors = {
|
|
9
10
|
preview: previewStore,
|
|
10
11
|
canvas: canvasStore
|
|
11
12
|
};
|
|
13
|
+
/** The stores of this document whose events are forwarded to the studio's. */
|
|
12
14
|
const forwards = {
|
|
13
15
|
preview: previewStore,
|
|
14
16
|
referencePickerFocus
|
|
15
17
|
};
|
|
18
|
+
/** Has this document's copy of a mirrored store take the studio's state. */
|
|
19
|
+
const mirror = (message) => mirrors[message.store]?.send({
|
|
20
|
+
type: "mirror",
|
|
21
|
+
context: message.context
|
|
22
|
+
});
|
|
16
23
|
/**
|
|
17
24
|
* Connects the renderer document to the studio through its handle. This document's stores then
|
|
18
25
|
* mirror the studio's, its own events are forwarded to the studio, which owns their truth, and
|
|
@@ -64,10 +71,7 @@ function connectToStudio(handle, { queryClient, studioCache, draftScope, camoxAp
|
|
|
64
71
|
setFrames(frames.filter(({ frameId }) => frameId !== message.frameId));
|
|
65
72
|
return;
|
|
66
73
|
case "store":
|
|
67
|
-
|
|
68
|
-
type: "mirror",
|
|
69
|
-
context: message.context
|
|
70
|
-
});
|
|
74
|
+
mirror(message);
|
|
71
75
|
return;
|
|
72
76
|
case "draftStarted":
|
|
73
77
|
draftScope.enterStarted(message.draftId);
|
|
@@ -106,7 +106,6 @@ async function buildTarget({ root, dir, target, specifiers, names, settings }) {
|
|
|
106
106
|
define: {
|
|
107
107
|
__CAMOX_ICON_IDS__: JSON.stringify(settings.iconIds),
|
|
108
108
|
__CAMOX_TELEMETRY_DISABLED__: JSON.stringify(settings.telemetryDisabled),
|
|
109
|
-
__CAMOX_ENABLE_EXPERIMENTAL_FEATURES__: JSON.stringify(settings.experimentalFeatures),
|
|
110
109
|
__CAMOX_API_URL__: JSON.stringify(settings.apiUrl),
|
|
111
110
|
"process.env.NODE_ENV": JSON.stringify("production")
|
|
112
111
|
},
|
|
@@ -13,8 +13,8 @@ import { cp, mkdir, mkdtemp, readFile, rename, rm } from "node:fs/promises";
|
|
|
13
13
|
*/
|
|
14
14
|
/** Turns building against an SDK Bundle on (`1`) or off (`0`) for `vite build`. */
|
|
15
15
|
const SDK_BUNDLE_SWITCH_ENV = "CAMOX_INTERNAL_SDK_BUNDLE";
|
|
16
|
-
/**
|
|
17
|
-
const SDK_BUNDLE_SWITCH_DEFAULT =
|
|
16
|
+
/** On: websites build against an SDK Bundle by default (#670, ADR 0029). */
|
|
17
|
+
const SDK_BUNDLE_SWITCH_DEFAULT = true;
|
|
18
18
|
/** The folder SDK Bundles are cached in, when not the website's own. */
|
|
19
19
|
const SDK_BUNDLE_CACHE_ENV = "CAMOX_INTERNAL_SDK_BUNDLE_CACHE";
|
|
20
20
|
/** Whether `vite build` builds against an SDK Bundle. */
|
|
@@ -67,7 +67,6 @@ async function sdkBundleName({ lockfile, importer = ".", target, settings, build
|
|
|
67
67
|
settings: {
|
|
68
68
|
iconIds: settings.iconIds,
|
|
69
69
|
telemetryDisabled: settings.telemetryDisabled,
|
|
70
|
-
experimentalFeatures: settings.experimentalFeatures,
|
|
71
70
|
apiUrl: settings.apiUrl
|
|
72
71
|
},
|
|
73
72
|
packages: resolutions
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useProjectUuid } from "../../lib/auth.js";
|
|
2
2
|
import { reads, useReadQuery } from "../../lib/studio-reads.js";
|
|
3
3
|
import { AnalyticsSettings } from "./AnalyticsSettings.js";
|
|
4
|
+
import { ExperimentalFeaturesSettings } from "./ExperimentalFeaturesSettings.js";
|
|
4
5
|
import { FaviconSettings } from "./FaviconSettings.js";
|
|
5
6
|
import { ProjectNameSettings } from "./ProjectNameSettings.js";
|
|
6
7
|
import { SocialProfilesSettings } from "./SocialProfilesSettings.js";
|
|
@@ -30,6 +31,10 @@ const parts = [
|
|
|
30
31
|
{
|
|
31
32
|
id: "analytics",
|
|
32
33
|
Part: AnalyticsSettings
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: "experimental-features",
|
|
37
|
+
Part: ExperimentalFeaturesSettings
|
|
33
38
|
}
|
|
34
39
|
];
|
|
35
40
|
/**
|