@makeswift/runtime 0.23.6 → 0.23.7-canary.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.
- package/dist/cjs/next/api-handler/handlers/manifest.js +1 -1
- package/dist/cjs/runtimes/react/hooks/use-resolvable-record.js +68 -0
- package/dist/cjs/runtimes/react/hooks/use-resolvable-record.js.map +1 -0
- package/dist/cjs/runtimes/react/hooks/use-resolved-props.js +3 -3
- package/dist/cjs/runtimes/react/hooks/use-resolved-props.js.map +1 -1
- package/dist/cjs/state/modules/element-trees.js +10 -7
- package/dist/cjs/state/modules/element-trees.js.map +1 -1
- package/dist/esm/next/api-handler/handlers/manifest.js +1 -1
- package/dist/esm/runtimes/react/hooks/use-resolvable-record.js +44 -0
- package/dist/esm/runtimes/react/hooks/use-resolvable-record.js.map +1 -0
- package/dist/esm/runtimes/react/hooks/use-resolved-props.js +3 -3
- package/dist/esm/runtimes/react/hooks/use-resolved-props.js.map +1 -1
- package/dist/esm/state/modules/element-trees.js +10 -7
- package/dist/esm/state/modules/element-trees.js.map +1 -1
- package/dist/types/runtimes/react/hooks/use-resolvable-record.d.ts +3 -0
- package/dist/types/runtimes/react/hooks/use-resolvable-record.d.ts.map +1 -0
- package/dist/types/state/modules/__tests__/fixtures/element-trees-demo-component.d.ts +7 -0
- package/dist/types/state/modules/__tests__/fixtures/element-trees-demo-component.d.ts.map +1 -0
- package/dist/types/state/modules/__tests__/fixtures/element-trees.d.ts +239 -0
- package/dist/types/state/modules/__tests__/fixtures/element-trees.d.ts.map +1 -1
- package/dist/types/state/modules/element-trees.d.ts +1 -1
- package/dist/types/state/modules/element-trees.d.ts.map +1 -1
- package/package.json +3 -3
- package/dist/cjs/runtimes/react/resolvable-record.js +0 -67
- package/dist/cjs/runtimes/react/resolvable-record.js.map +0 -1
- package/dist/esm/runtimes/react/resolvable-record.js +0 -43
- package/dist/esm/runtimes/react/resolvable-record.js.map +0 -1
- package/dist/types/runtimes/react/resolvable-record.d.ts +0 -3
- package/dist/types/runtimes/react/resolvable-record.d.ts.map +0 -1
|
@@ -37,7 +37,7 @@ async function handler(...args) {
|
|
|
37
37
|
const supportsDraftMode = (0, import_ts_pattern.match)(args).with(routeHandlerPattern, () => true).with(apiRoutePattern, () => false).exhaustive();
|
|
38
38
|
const supportsWebhook = (0, import_ts_pattern.match)(args).with(routeHandlerPattern, () => true).with(apiRoutePattern, () => false).exhaustive();
|
|
39
39
|
const body = {
|
|
40
|
-
version: "0.23.
|
|
40
|
+
version: "0.23.7-canary.1",
|
|
41
41
|
previewMode: supportsPreviewMode,
|
|
42
42
|
draftMode: supportsDraftMode,
|
|
43
43
|
interactionMode: true,
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var use_resolvable_record_exports = {};
|
|
20
|
+
__export(use_resolvable_record_exports, {
|
|
21
|
+
useResolvableRecord: () => useResolvableRecord
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(use_resolvable_record_exports);
|
|
24
|
+
var import_react = require("react");
|
|
25
|
+
function useResolvableRecord(resolvables) {
|
|
26
|
+
const snapshot = (0, import_react.useRef)({ resolvedValues: {}, dirtyProps: /* @__PURE__ */ new Set() });
|
|
27
|
+
return (0, import_react.useMemo)(() => {
|
|
28
|
+
return {
|
|
29
|
+
name: "resolvable-record",
|
|
30
|
+
subscribe: (onUpdate) => {
|
|
31
|
+
const unsubscribes = Object.values(resolvables).map((s) => s.subscribe(onUpdate));
|
|
32
|
+
return () => {
|
|
33
|
+
unsubscribes.forEach((u) => u());
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
readStable: () => {
|
|
37
|
+
const nextSnapshot = Object.entries(resolvables).reduce(
|
|
38
|
+
({ dirtyProps, resolvedValues }, [propName, subscription]) => {
|
|
39
|
+
const lastPropValue = snapshot.current.resolvedValues[propName];
|
|
40
|
+
const propValue = subscription.readStable();
|
|
41
|
+
const isDirty = propValue !== lastPropValue;
|
|
42
|
+
return {
|
|
43
|
+
dirtyProps: isDirty ? dirtyProps.add(propName) : dirtyProps,
|
|
44
|
+
resolvedValues: { ...resolvedValues, [propName]: propValue }
|
|
45
|
+
};
|
|
46
|
+
},
|
|
47
|
+
{ resolvedValues: {}, dirtyProps: /* @__PURE__ */ new Set() }
|
|
48
|
+
);
|
|
49
|
+
if (nextSnapshot.dirtyProps.size > 0) {
|
|
50
|
+
snapshot.current = nextSnapshot;
|
|
51
|
+
}
|
|
52
|
+
return snapshot.current.resolvedValues;
|
|
53
|
+
},
|
|
54
|
+
triggerResolve: async () => {
|
|
55
|
+
return await Promise.all(
|
|
56
|
+
Object.entries(resolvables).map(
|
|
57
|
+
([propName, sub]) => sub.triggerResolve(snapshot.current.resolvedValues[propName])
|
|
58
|
+
)
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}, [resolvables]);
|
|
63
|
+
}
|
|
64
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
65
|
+
0 && (module.exports = {
|
|
66
|
+
useResolvableRecord
|
|
67
|
+
});
|
|
68
|
+
//# sourceMappingURL=use-resolvable-record.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../src/runtimes/react/hooks/use-resolvable-record.tsx"],"sourcesContent":["import { type Resolvable } from '@makeswift/controls'\nimport { useMemo, useRef } from 'react'\n\ntype Snapshot = {\n resolvedValues: Record<string, unknown>\n dirtyProps: Set<string>\n}\n\nexport function useResolvableRecord(\n resolvables: Record<string, Resolvable<unknown>>,\n): Resolvable<Record<string, unknown>> {\n const snapshot = useRef<Snapshot>({ resolvedValues: {}, dirtyProps: new Set() })\n\n return useMemo<Resolvable<Record<string, unknown>>>(() => {\n return {\n name: 'resolvable-record',\n subscribe: (onUpdate: () => void): (() => void) => {\n const unsubscribes = Object.values(resolvables).map(s => s.subscribe(onUpdate))\n return () => {\n unsubscribes.forEach(u => u())\n }\n },\n\n readStable: () => {\n const nextSnapshot = Object.entries(resolvables).reduce<Snapshot>(\n ({ dirtyProps, resolvedValues }, [propName, subscription]) => {\n const lastPropValue = snapshot.current.resolvedValues[propName]\n const propValue = subscription.readStable()\n const isDirty = propValue !== lastPropValue\n\n return {\n dirtyProps: isDirty ? dirtyProps.add(propName) : dirtyProps,\n resolvedValues: { ...resolvedValues, [propName]: propValue },\n }\n },\n { resolvedValues: {}, dirtyProps: new Set() },\n )\n\n if (nextSnapshot.dirtyProps.size > 0) {\n snapshot.current = nextSnapshot\n }\n\n return snapshot.current.resolvedValues\n },\n\n triggerResolve: async () => {\n // While we _could_ only trigger resolution on the dirty props, this is\n // not an airtight solution. Some controls will resolve to nullish\n // values even when the underlying data changes, so they won't be dirty\n // (ex: an Image control where the data changes from `undefined` to a\n // file that has not yet been fetched). Even if you add a nullish check\n // on the resolved value, some controls can resolve to non-nullish value\n // when the resolution does not occur (ex: swatches can resolve to\n // black). The true solution is to trigger resolve on underlying data\n // change, and moving these dirtiness optimizations for resolution\n // triggering at the control level.\n return await Promise.all(\n Object.entries(resolvables).map(([propName, sub]) =>\n sub.triggerResolve(snapshot.current.resolvedValues[propName]),\n ),\n )\n },\n }\n }, [resolvables])\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAAgC;AAOzB,SAAS,oBACd,aACqC;AACrC,QAAM,eAAW,qBAAiB,EAAE,gBAAgB,CAAC,GAAG,YAAY,oBAAI,IAAI,EAAE,CAAC;AAE/E,aAAO,sBAA6C,MAAM;AACxD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,WAAW,CAAC,aAAuC;AACjD,cAAM,eAAe,OAAO,OAAO,WAAW,EAAE,IAAI,OAAK,EAAE,UAAU,QAAQ,CAAC;AAC9E,eAAO,MAAM;AACX,uBAAa,QAAQ,OAAK,EAAE,CAAC;AAAA,QAC/B;AAAA,MACF;AAAA,MAEA,YAAY,MAAM;AAChB,cAAM,eAAe,OAAO,QAAQ,WAAW,EAAE;AAAA,UAC/C,CAAC,EAAE,YAAY,eAAe,GAAG,CAAC,UAAU,YAAY,MAAM;AAC5D,kBAAM,gBAAgB,SAAS,QAAQ,eAAe,QAAQ;AAC9D,kBAAM,YAAY,aAAa,WAAW;AAC1C,kBAAM,UAAU,cAAc;AAE9B,mBAAO;AAAA,cACL,YAAY,UAAU,WAAW,IAAI,QAAQ,IAAI;AAAA,cACjD,gBAAgB,EAAE,GAAG,gBAAgB,CAAC,QAAQ,GAAG,UAAU;AAAA,YAC7D;AAAA,UACF;AAAA,UACA,EAAE,gBAAgB,CAAC,GAAG,YAAY,oBAAI,IAAI,EAAE;AAAA,QAC9C;AAEA,YAAI,aAAa,WAAW,OAAO,GAAG;AACpC,mBAAS,UAAU;AAAA,QACrB;AAEA,eAAO,SAAS,QAAQ;AAAA,MAC1B;AAAA,MAEA,gBAAgB,YAAY;AAW1B,eAAO,MAAM,QAAQ;AAAA,UACnB,OAAO,QAAQ,WAAW,EAAE;AAAA,YAAI,CAAC,CAAC,UAAU,GAAG,MAC7C,IAAI,eAAe,SAAS,QAAQ,eAAe,QAAQ,CAAC;AAAA,UAC9D;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,GAAG,CAAC,WAAW,CAAC;AAClB;","names":[]}
|
|
@@ -38,7 +38,7 @@ var import_use_resource_resolver = require("./use-resource-resolver");
|
|
|
38
38
|
var import_use_document_context = require("./use-document-context");
|
|
39
39
|
var import_use_selector = require("./use-selector");
|
|
40
40
|
var import_use_stylesheet_factory = require("./use-stylesheet-factory");
|
|
41
|
-
var
|
|
41
|
+
var import_use_resolvable_record = require("./use-resolvable-record");
|
|
42
42
|
var import_prop_error_handling_proxy = require("../utils/prop-error-handling-proxy");
|
|
43
43
|
function useControlInstances(elementKey) {
|
|
44
44
|
const documentKey = (0, import_use_document_context.useDocumentKey)();
|
|
@@ -83,10 +83,10 @@ function useResolvedProps(propDefs, elementData, elementKey) {
|
|
|
83
83
|
}),
|
|
84
84
|
[propDefs, resolveProp]
|
|
85
85
|
);
|
|
86
|
-
const props = (0,
|
|
86
|
+
const props = (0, import_use_resolvable_record.useResolvableRecord)(resolvables);
|
|
87
87
|
(0, import_react.useEffect)(() => {
|
|
88
88
|
props.triggerResolve();
|
|
89
|
-
}, []);
|
|
89
|
+
}, [props]);
|
|
90
90
|
const resolvedProps = (0, import_react.useSyncExternalStore)(props.subscribe, props.readStable, props.readStable);
|
|
91
91
|
stylesheetFactory.useDefinedStyles();
|
|
92
92
|
return resolvedProps;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/runtimes/react/hooks/use-resolved-props.ts"],"sourcesContent":["import { useMemo, useEffect, useRef, useSyncExternalStore, useCallback } from 'react'\nimport {\n ControlDefinition,\n ControlInstance,\n mapValues,\n type Data,\n type Resolvable,\n} from '@makeswift/controls'\n\nimport * as ReactPage from '../../../state/react-page'\nimport { useResourceResolver } from './use-resource-resolver'\nimport { useDocumentKey } from './use-document-context'\nimport { useSelector } from './use-selector'\n\nimport { useStylesheetFactory } from './use-stylesheet-factory'\n\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../../../src/runtimes/react/hooks/use-resolved-props.ts"],"sourcesContent":["import { useMemo, useEffect, useRef, useSyncExternalStore, useCallback } from 'react'\nimport {\n ControlDefinition,\n ControlInstance,\n mapValues,\n type Data,\n type Resolvable,\n} from '@makeswift/controls'\n\nimport * as ReactPage from '../../../state/react-page'\nimport { useResourceResolver } from './use-resource-resolver'\nimport { useDocumentKey } from './use-document-context'\nimport { useSelector } from './use-selector'\n\nimport { useStylesheetFactory } from './use-stylesheet-factory'\n\nimport { useResolvableRecord } from './use-resolvable-record'\nimport { propErrorHandlingProxy } from '../utils/prop-error-handling-proxy'\n\nfunction useControlInstances(elementKey: string): Record<string, ControlInstance> | null {\n const documentKey = useDocumentKey()\n\n return useSelector(state => {\n if (documentKey == null) return null\n\n return ReactPage.getPropControllers(state, documentKey, elementKey)\n })\n}\n\ntype CacheItem = {\n data: Data\n control: ControlInstance | undefined\n resolvedValue: Resolvable<unknown>\n}\n\nexport function useResolvedProps(\n propDefs: Record<string, ControlDefinition>,\n elementData: Record<string, Data>,\n elementKey: string,\n): Record<string, unknown> {\n const stylesheetFactory = useStylesheetFactory()\n const resourceResolver = useResourceResolver()\n const controls = useControlInstances(elementKey)\n\n const cache = useRef<Record<string, CacheItem>>({}).current\n const resolveProp = useCallback(\n (def: ControlDefinition, propName: string) => {\n const data = elementData[propName]\n const control = controls?.[propName]\n\n if (\n cache[propName] != null &&\n data === cache[propName].data &&\n control === cache[propName].control\n ) {\n return cache[propName].resolvedValue\n }\n\n const resolvedValue = def.resolveValue(\n data,\n resourceResolver,\n stylesheetFactory.get(propName),\n control,\n )\n\n cache[propName] = { data, control, resolvedValue }\n return resolvedValue\n },\n [controls, elementData, resourceResolver, stylesheetFactory],\n )\n\n const resolvables = useMemo<Record<string, Resolvable<unknown>>>(\n () =>\n mapValues(propDefs, (def, propName) => {\n const defaultValue = (def.config as any)?.defaultValue\n return propErrorHandlingProxy(resolveProp(def, propName), defaultValue, error => {\n console.warn(\n `Error reading value for prop \"${propName}\", falling back to \\`${defaultValue}\\`.`,\n { control: def, error },\n )\n })\n }),\n [propDefs, resolveProp],\n )\n\n const props = useResolvableRecord(resolvables)\n\n // no need to call `triggerResolve` on the server, all the resources should already be in\n // the host API client's cache (populated from the snapshot's cache)\n useEffect(() => {\n props.triggerResolve()\n }, [props])\n\n // the order is important here, the styles are defined in the process of the props resolution,\n // calling `useDefinedStyles` before the props are resolved would effectively be a noop\n const resolvedProps = useSyncExternalStore(props.subscribe, props.readStable, props.readStable)\n\n stylesheetFactory.useDefinedStyles()\n\n return resolvedProps\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA8E;AAC9E,sBAMO;AAEP,gBAA2B;AAC3B,mCAAoC;AACpC,kCAA+B;AAC/B,0BAA4B;AAE5B,oCAAqC;AAErC,mCAAoC;AACpC,uCAAuC;AAEvC,SAAS,oBAAoB,YAA4D;AACvF,QAAM,kBAAc,4CAAe;AAEnC,aAAO,iCAAY,WAAS;AAC1B,QAAI,eAAe;AAAM,aAAO;AAEhC,WAAO,UAAU,mBAAmB,OAAO,aAAa,UAAU;AAAA,EACpE,CAAC;AACH;AAQO,SAAS,iBACd,UACA,aACA,YACyB;AACzB,QAAM,wBAAoB,oDAAqB;AAC/C,QAAM,uBAAmB,kDAAoB;AAC7C,QAAM,WAAW,oBAAoB,UAAU;AAE/C,QAAM,YAAQ,qBAAkC,CAAC,CAAC,EAAE;AACpD,QAAM,kBAAc;AAAA,IAClB,CAAC,KAAwB,aAAqB;AAC5C,YAAM,OAAO,YAAY,QAAQ;AACjC,YAAM,UAAU,WAAW,QAAQ;AAEnC,UACE,MAAM,QAAQ,KAAK,QACnB,SAAS,MAAM,QAAQ,EAAE,QACzB,YAAY,MAAM,QAAQ,EAAE,SAC5B;AACA,eAAO,MAAM,QAAQ,EAAE;AAAA,MACzB;AAEA,YAAM,gBAAgB,IAAI;AAAA,QACxB;AAAA,QACA;AAAA,QACA,kBAAkB,IAAI,QAAQ;AAAA,QAC9B;AAAA,MACF;AAEA,YAAM,QAAQ,IAAI,EAAE,MAAM,SAAS,cAAc;AACjD,aAAO;AAAA,IACT;AAAA,IACA,CAAC,UAAU,aAAa,kBAAkB,iBAAiB;AAAA,EAC7D;AAEA,QAAM,kBAAc;AAAA,IAClB,UACE,2BAAU,UAAU,CAAC,KAAK,aAAa;AACrC,YAAM,eAAgB,IAAI,QAAgB;AAC1C,iBAAO,yDAAuB,YAAY,KAAK,QAAQ,GAAG,cAAc,WAAS;AAC/E,gBAAQ;AAAA,UACN,iCAAiC,QAAQ,wBAAwB,YAAY;AAAA,UAC7E,EAAE,SAAS,KAAK,MAAM;AAAA,QACxB;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,IACH,CAAC,UAAU,WAAW;AAAA,EACxB;AAEA,QAAM,YAAQ,kDAAoB,WAAW;AAI7C,8BAAU,MAAM;AACd,UAAM,eAAe;AAAA,EACvB,GAAG,CAAC,KAAK,CAAC;AAIV,QAAM,oBAAgB,mCAAqB,MAAM,WAAW,MAAM,YAAY,MAAM,UAAU;AAE9F,oBAAkB,iBAAiB;AAEnC,SAAO;AACT;","names":[]}
|
|
@@ -43,8 +43,8 @@ function getInitialState(documents, descriptors) {
|
|
|
43
43
|
}
|
|
44
44
|
return state;
|
|
45
45
|
}
|
|
46
|
-
function getElementTree(state,
|
|
47
|
-
return state.get(
|
|
46
|
+
function getElementTree(state, documentKey) {
|
|
47
|
+
return state.get(documentKey) ?? null;
|
|
48
48
|
}
|
|
49
49
|
function getElements(state, documentKey) {
|
|
50
50
|
return getElementTree(state, documentKey)?.elements ?? /* @__PURE__ */ new Map();
|
|
@@ -142,12 +142,15 @@ function isElement(item) {
|
|
|
142
142
|
return typeof item === "object" && item != null && "key" in item && "type" in item && typeof item.key === "string" && typeof item.type === "string";
|
|
143
143
|
}
|
|
144
144
|
function getElementOperationPath(path) {
|
|
145
|
+
if (path.length === 0) {
|
|
146
|
+
return { elementPath: [], propName: null };
|
|
147
|
+
}
|
|
145
148
|
const i = path.findLastIndex(
|
|
146
149
|
(fragment, i2) => typeof fragment === "number" && (i2 === path.length - 1 || path[i2 + 1] === "props")
|
|
147
150
|
);
|
|
148
|
-
if (
|
|
151
|
+
if (i === -1 && path[0] !== "props" || path.length - i < 3) {
|
|
149
152
|
console.error("Operation path does not point to an element property", { path });
|
|
150
|
-
return { elementPath: [], propName:
|
|
153
|
+
return { elementPath: [], propName: null };
|
|
151
154
|
}
|
|
152
155
|
return { elementPath: path.slice(0, i + 1), propName: `${path.slice(i + 1).at(1)}` };
|
|
153
156
|
}
|
|
@@ -173,7 +176,7 @@ function getElementByPath(rootElement, elementPath) {
|
|
|
173
176
|
}
|
|
174
177
|
function getElementAndPropName(rootElement, { elementPath, propName }) {
|
|
175
178
|
const element = getElementByPath(rootElement, elementPath);
|
|
176
|
-
return element != null ? [element, propName] : [rootElement,
|
|
179
|
+
return element != null ? [element, propName] : [rootElement, null];
|
|
177
180
|
}
|
|
178
181
|
function updateParentElements(elements, elementPaths, rootElement) {
|
|
179
182
|
elementPaths.forEach(({ elementPath }) => {
|
|
@@ -192,7 +195,7 @@ function hasChildren(element, propName, descriptors) {
|
|
|
192
195
|
return children.length > 0;
|
|
193
196
|
}
|
|
194
197
|
function deleteElement({ elements, elementIds }, deletedElement, propName, descriptors) {
|
|
195
|
-
if (hasChildren(deletedElement, propName, descriptors)) {
|
|
198
|
+
if (propName == null || hasChildren(deletedElement, propName, descriptors)) {
|
|
196
199
|
for (const element of traverseElementTree(deletedElement, descriptors)) {
|
|
197
200
|
elements.delete(element.key);
|
|
198
201
|
elementIds.delete(element.key);
|
|
@@ -215,7 +218,7 @@ function applyDelete(elementTree, descriptors, rootElements, path) {
|
|
|
215
218
|
};
|
|
216
219
|
}
|
|
217
220
|
function insertElement({ elements, elementIds }, insertedElement, propName, descriptors) {
|
|
218
|
-
if (hasChildren(insertedElement, propName, descriptors)) {
|
|
221
|
+
if (propName == null || hasChildren(insertedElement, propName, descriptors)) {
|
|
219
222
|
for (const element of traverseElementTree(insertedElement, descriptors)) {
|
|
220
223
|
elements.set(element.key, element);
|
|
221
224
|
if (!(0, import_controls.isElementReference)(element)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/state/modules/element-trees.ts"],"sourcesContent":["import { type Operation } from 'ot-json0'\nimport { getIn } from 'immutable'\n\nimport { type Element, type ElementData, isElementReference } from '@makeswift/controls'\n\nimport { Introspection } from '../../prop-controllers'\n\nimport { type Action, ActionTypes } from '../actions'\n\nimport { getRootElement, type Document } from './read-only-documents'\nimport { type DescriptorsByComponentType } from './prop-controllers'\n\nexport type ElementTree = {\n elements: Map<string, Element>\n elementIds: Map<string, string>\n}\n\nexport type State = Map<string, ElementTree>\n\nexport function getInitialState(\n documents?: Map<string, Document>,\n descriptors?: DescriptorsByComponentType,\n): State {\n const state = new Map<string, ElementTree>()\n if (documents == null || descriptors == null) return state\n\n for (const [documentKey, document] of documents) {\n state.set(documentKey, buildElementTree(getRootElement(document), descriptors))\n }\n\n return state\n}\n\nfunction getElementTree(state: State, id: string): ElementTree | null {\n return state.get(id) ?? null\n}\n\nexport function getElements(state: State, documentKey: string): Map<string, Element> {\n return getElementTree(state, documentKey)?.elements ?? new Map()\n}\n\nexport function getElementIds(state: State, documentKey: string): Map<string, string> {\n return getElementTree(state, documentKey)?.elementIds ?? new Map()\n}\n\nexport function getElement(state: State, documentKey: string, elementKey: string): Element | null {\n return getElements(state, documentKey).get(elementKey) ?? null\n}\n\nexport function getElementId(state: State, documentKey: string, elementKey: string): string | null {\n return getElementIds(state, documentKey).get(elementKey) ?? null\n}\n\nexport function reducer(state: State = getInitialState(), action: Action): State {\n switch (action.type) {\n case ActionTypes.CREATE_ELEMENT_TREE: {\n const { document, descriptors } = action.payload\n return new Map(state).set(\n document.key,\n buildElementTree(getRootElement(document), descriptors),\n )\n }\n\n case ActionTypes.DELETE_ELEMENT_TREE: {\n const nextState = new Map(state)\n const deleted = nextState.delete(action.payload.documentKey)\n return deleted ? nextState : state\n }\n\n case ActionTypes.CHANGE_ELEMENT_TREE: {\n const { oldDocument, newDocument, descriptors, operation } = action.payload\n const documentKey = oldDocument.key\n console.assert(\n documentKey === newDocument.key,\n `Mismatching document keys ${documentKey} !== ${newDocument.key}`,\n )\n\n const elementTree = state.get(documentKey)\n if (elementTree == null) return state\n\n const updatedElementTree = applyChanges(\n elementTree,\n descriptors,\n {\n old: getRootElement(oldDocument),\n new: getRootElement(newDocument),\n },\n operation,\n )\n\n return new Map(state).set(documentKey, updatedElementTree)\n }\n\n default:\n return state\n }\n}\n\nexport function* traverseElementTree(\n element: Element,\n descriptors: DescriptorsByComponentType,\n): Generator<Element> {\n yield element\n if (isElementReference(element)) return\n\n const elementDescriptors = descriptors.get(element.type)\n if (elementDescriptors == null) return\n\n for (const [propKey, descriptor] of Object.entries(elementDescriptors)) {\n const children = Introspection.getElementChildren(descriptor, element.props[propKey])\n for (const child of children) {\n yield* traverseElementTree(child, descriptors)\n }\n }\n}\n\nfunction getElementIdProp(\n element: ElementData,\n descriptors: DescriptorsByComponentType,\n): string | null {\n const elementDescriptors = descriptors.get(element.type)\n if (elementDescriptors == null) return null\n\n for (const [propName, descriptor] of Object.entries(elementDescriptors)) {\n const elementId = Introspection.getElementId(descriptor, element.props[propName])\n if (elementId != null) return elementId\n }\n\n return null\n}\n\nexport function buildElementTree(\n rootElement: Element,\n descriptors: DescriptorsByComponentType,\n): ElementTree {\n const elements = new Map<string, Element>()\n const elementIds = new Map<string, string>()\n\n for (const element of traverseElementTree(rootElement, descriptors)) {\n elements.set(element.key, element)\n if (!isElementReference(element)) {\n const elementId = getElementIdProp(element, descriptors)\n if (elementId != null) elementIds.set(element.key, elementId)\n }\n }\n\n return {\n elements,\n elementIds,\n }\n}\n\ntype OperationPath = Operation[number]['p']\n\n// performance-sensitive function, intentionally not using `elementData` schema here\nfunction isElement(item: unknown): item is Element {\n return (\n typeof item === 'object' &&\n item != null &&\n 'key' in item &&\n 'type' in item &&\n typeof item.key === 'string' &&\n typeof item.type === 'string'\n )\n}\n\ntype ElementOperationPath = { elementPath: OperationPath; propName: string }\n\nfunction getElementOperationPath(path: OperationPath): ElementOperationPath {\n const i = path.findLastIndex(\n (fragment, i) =>\n typeof fragment === 'number' && (i === path.length - 1 || path[i + 1] === 'props'),\n )\n\n if (path.length === 0 || (i === -1 && path[0] !== 'props') || path.length - i < 3) {\n console.error('Operation path does not point to an element property', { path })\n return { elementPath: [], propName: 'children' }\n }\n\n return { elementPath: path.slice(0, i + 1), propName: `${path.slice(i + 1).at(1)}` }\n}\n\nexport function getChangedElementsPaths(\n path: OperationPath,\n): [ElementOperationPath, ...ElementOperationPath[]] {\n let elementOp = getElementOperationPath(path)\n const result: [ElementOperationPath, ...ElementOperationPath[]] = [elementOp]\n while (elementOp.elementPath.length > 0) {\n elementOp = getElementOperationPath(elementOp.elementPath.slice(0, -1))\n result.push(elementOp)\n }\n\n return result\n}\n\nfunction getElementByPath(rootElement: Element, elementPath: OperationPath): Element | null {\n const item = getIn(rootElement, elementPath)\n if (!isElement(item)) {\n console.error('Expected an element, got', item, {\n rootElement,\n elementPath,\n })\n\n return null\n }\n\n return item\n}\n\nfunction getElementAndPropName(\n rootElement: Element,\n { elementPath, propName }: ElementOperationPath,\n): [Element, string] {\n const element = getElementByPath(rootElement, elementPath)\n return element != null ? [element, propName] : [rootElement, 'children']\n}\n\nfunction updateParentElements(\n elements: ElementTree['elements'],\n elementPaths: ElementOperationPath[],\n rootElement: Element,\n): void {\n elementPaths.forEach(({ elementPath }) => {\n const element = getElementByPath(rootElement, elementPath)\n if (element != null) elements.set(element.key, element)\n })\n}\n\nfunction hasChildren(\n element: Element,\n propName: string,\n descriptors: DescriptorsByComponentType,\n): boolean {\n if (isElementReference(element)) return false\n\n const propDescriptor = descriptors.get(element.type)?.[propName]\n if (propDescriptor == null) return false\n\n const children = Introspection.getElementChildren(propDescriptor, element.props[propName])\n return children.length > 0\n}\n\nfunction deleteElement(\n { elements, elementIds }: ElementTree,\n deletedElement: Element,\n propName: string,\n descriptors: DescriptorsByComponentType,\n) {\n if (hasChildren(deletedElement, propName, descriptors)) {\n for (const element of traverseElementTree(deletedElement, descriptors)) {\n elements.delete(element.key)\n elementIds.delete(element.key)\n }\n } else {\n elements.delete(deletedElement.key)\n elementIds.delete(deletedElement.key)\n }\n}\n\nfunction applyDelete(\n elementTree: ElementTree,\n descriptors: DescriptorsByComponentType,\n rootElements: { old: Element; new: Element },\n path: OperationPath,\n): ElementTree {\n const [deleteElementPath, ...parentElementPaths] = getChangedElementsPaths(path)\n const [deletedElement, propName] = getElementAndPropName(rootElements.old, deleteElementPath)\n\n const elements = new Map(elementTree.elements)\n const elementIds = new Map(elementTree.elementIds)\n\n deleteElement({ elements, elementIds }, deletedElement, propName, descriptors)\n updateParentElements(elements, parentElementPaths, rootElements.new)\n\n return {\n elements,\n elementIds,\n }\n}\n\nfunction insertElement(\n { elements, elementIds }: ElementTree,\n insertedElement: Element,\n propName: string,\n descriptors: DescriptorsByComponentType,\n) {\n if (hasChildren(insertedElement, propName, descriptors)) {\n for (const element of traverseElementTree(insertedElement, descriptors)) {\n elements.set(element.key, element)\n if (!isElementReference(element)) {\n const elementId = getElementIdProp(element, descriptors)\n if (elementId != null) elementIds.set(element.key, elementId)\n }\n }\n } else {\n elements.set(insertedElement.key, insertedElement)\n if (!isElementReference(insertedElement)) {\n const elementId = getElementIdProp(insertedElement, descriptors)\n if (elementId != null) elementIds.set(insertedElement.key, elementId)\n }\n }\n}\n\nfunction applyInsert(\n elementTree: ElementTree,\n descriptors: DescriptorsByComponentType,\n rootElements: { old: Element; new: Element },\n path: OperationPath,\n): ElementTree {\n const [insertedElementPath, ...parentElementPaths] = getChangedElementsPaths(path)\n const [insertedElement, propName] = getElementAndPropName(rootElements.new, insertedElementPath)\n\n const elements = new Map(elementTree.elements)\n const elementIds = new Map(elementTree.elementIds)\n\n insertElement({ elements, elementIds }, insertedElement, propName, descriptors)\n updateParentElements(elements, parentElementPaths, rootElements.new)\n\n return {\n elements,\n elementIds,\n }\n}\n\nfunction applyUpdate(\n elementTree: ElementTree,\n descriptors: DescriptorsByComponentType,\n rootElements: { old: Element; new: Element },\n path: OperationPath,\n): ElementTree {\n const [updateElementPath, ...parentElementPaths] = getChangedElementsPaths(path)\n const [deletedElement, propName] = getElementAndPropName(rootElements.old, updateElementPath)\n const [insertedElement, _] = getElementAndPropName(rootElements.new, updateElementPath)\n\n const elements = new Map(elementTree.elements)\n const elementIds = new Map(elementTree.elementIds)\n\n deleteElement({ elements, elementIds }, deletedElement, propName, descriptors)\n insertElement({ elements, elementIds }, insertedElement, propName, descriptors)\n\n updateParentElements(elements, parentElementPaths, rootElements.new)\n\n return {\n elements,\n elementIds,\n }\n}\n\nfunction applyChanges(\n elementTree: ElementTree,\n descriptors: DescriptorsByComponentType,\n rootElements: { old: Element; new: Element },\n operation: Operation,\n): ElementTree {\n return operation.reduce((tree, op) => {\n const hasDelete = 'ld' in op || 'od' in op\n const hasInsert = 'li' in op || 'oi' in op\n if (hasDelete && hasInsert) {\n return applyUpdate(tree, descriptors, rootElements, op.p)\n }\n\n if (hasDelete) return applyDelete(tree, descriptors, rootElements, op.p)\n if (hasInsert) return applyInsert(tree, descriptors, rootElements, op.p)\n return tree\n }, elementTree)\n}\n"],"mappings":"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","names":["i"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/state/modules/element-trees.ts"],"sourcesContent":["import { type Operation } from 'ot-json0'\nimport { getIn } from 'immutable'\n\nimport { type Element, type ElementData, isElementReference } from '@makeswift/controls'\n\nimport { Introspection } from '../../prop-controllers'\n\nimport { type Action, ActionTypes } from '../actions'\n\nimport { getRootElement, type Document } from './read-only-documents'\nimport { type DescriptorsByComponentType } from './prop-controllers'\n\nexport type ElementTree = {\n elements: Map<string, Element>\n elementIds: Map<string, string>\n}\n\nexport type State = Map<string, ElementTree>\n\nexport function getInitialState(\n documents?: Map<string, Document>,\n descriptors?: DescriptorsByComponentType,\n): State {\n const state = new Map<string, ElementTree>()\n if (documents == null || descriptors == null) return state\n\n for (const [documentKey, document] of documents) {\n state.set(documentKey, buildElementTree(getRootElement(document), descriptors))\n }\n\n return state\n}\n\nfunction getElementTree(state: State, documentKey: string): ElementTree | null {\n return state.get(documentKey) ?? null\n}\n\nexport function getElements(state: State, documentKey: string): Map<string, Element> {\n return getElementTree(state, documentKey)?.elements ?? new Map()\n}\n\nexport function getElementIds(state: State, documentKey: string): Map<string, string> {\n return getElementTree(state, documentKey)?.elementIds ?? new Map()\n}\n\nexport function getElement(state: State, documentKey: string, elementKey: string): Element | null {\n return getElements(state, documentKey).get(elementKey) ?? null\n}\n\nexport function getElementId(state: State, documentKey: string, elementKey: string): string | null {\n return getElementIds(state, documentKey).get(elementKey) ?? null\n}\n\nexport function reducer(state: State = getInitialState(), action: Action): State {\n switch (action.type) {\n case ActionTypes.CREATE_ELEMENT_TREE: {\n const { document, descriptors } = action.payload\n return new Map(state).set(\n document.key,\n buildElementTree(getRootElement(document), descriptors),\n )\n }\n\n case ActionTypes.DELETE_ELEMENT_TREE: {\n const nextState = new Map(state)\n const deleted = nextState.delete(action.payload.documentKey)\n return deleted ? nextState : state\n }\n\n case ActionTypes.CHANGE_ELEMENT_TREE: {\n const { oldDocument, newDocument, descriptors, operation } = action.payload\n const documentKey = oldDocument.key\n console.assert(\n documentKey === newDocument.key,\n `Mismatching document keys ${documentKey} !== ${newDocument.key}`,\n )\n\n const elementTree = state.get(documentKey)\n if (elementTree == null) return state\n\n const updatedElementTree = applyChanges(\n elementTree,\n descriptors,\n {\n old: getRootElement(oldDocument),\n new: getRootElement(newDocument),\n },\n operation,\n )\n\n return new Map(state).set(documentKey, updatedElementTree)\n }\n\n default:\n return state\n }\n}\n\nexport function* traverseElementTree(\n element: Element,\n descriptors: DescriptorsByComponentType,\n): Generator<Element> {\n yield element\n if (isElementReference(element)) return\n\n const elementDescriptors = descriptors.get(element.type)\n if (elementDescriptors == null) return\n\n for (const [propKey, descriptor] of Object.entries(elementDescriptors)) {\n const children = Introspection.getElementChildren(descriptor, element.props[propKey])\n for (const child of children) {\n yield* traverseElementTree(child, descriptors)\n }\n }\n}\n\nfunction getElementIdProp(\n element: ElementData,\n descriptors: DescriptorsByComponentType,\n): string | null {\n const elementDescriptors = descriptors.get(element.type)\n if (elementDescriptors == null) return null\n\n for (const [propName, descriptor] of Object.entries(elementDescriptors)) {\n const elementId = Introspection.getElementId(descriptor, element.props[propName])\n if (elementId != null) return elementId\n }\n\n return null\n}\n\nexport function buildElementTree(\n rootElement: Element,\n descriptors: DescriptorsByComponentType,\n): ElementTree {\n const elements = new Map<string, Element>()\n const elementIds = new Map<string, string>()\n\n for (const element of traverseElementTree(rootElement, descriptors)) {\n elements.set(element.key, element)\n if (!isElementReference(element)) {\n const elementId = getElementIdProp(element, descriptors)\n if (elementId != null) elementIds.set(element.key, elementId)\n }\n }\n\n return {\n elements,\n elementIds,\n }\n}\n\ntype OperationPath = Operation[number]['p']\n\n// performance-sensitive function, intentionally not using `elementData` schema here\nfunction isElement(item: unknown): item is Element {\n return (\n typeof item === 'object' &&\n item != null &&\n 'key' in item &&\n 'type' in item &&\n typeof item.key === 'string' &&\n typeof item.type === 'string'\n )\n}\n\ntype ElementOperationPath = { elementPath: OperationPath; propName: string | null }\n\nfunction getElementOperationPath(path: OperationPath): ElementOperationPath {\n if (path.length === 0) {\n return { elementPath: [], propName: null }\n }\n\n const i = path.findLastIndex(\n (fragment, i) =>\n typeof fragment === 'number' && (i === path.length - 1 || path[i + 1] === 'props'),\n )\n\n if ((i === -1 && path[0] !== 'props') || path.length - i < 3) {\n console.error('Operation path does not point to an element property', { path })\n return { elementPath: [], propName: null }\n }\n\n return { elementPath: path.slice(0, i + 1), propName: `${path.slice(i + 1).at(1)}` }\n}\n\nexport function getChangedElementsPaths(\n path: OperationPath,\n): [ElementOperationPath, ...ElementOperationPath[]] {\n let elementOp = getElementOperationPath(path)\n const result: [ElementOperationPath, ...ElementOperationPath[]] = [elementOp]\n while (elementOp.elementPath.length > 0) {\n elementOp = getElementOperationPath(elementOp.elementPath.slice(0, -1))\n result.push(elementOp)\n }\n\n return result\n}\n\nfunction getElementByPath(rootElement: Element, elementPath: OperationPath): Element | null {\n const item = getIn(rootElement, elementPath)\n if (!isElement(item)) {\n console.error('Expected an element, got', item, {\n rootElement,\n elementPath,\n })\n\n return null\n }\n\n return item\n}\n\nfunction getElementAndPropName(\n rootElement: Element,\n { elementPath, propName }: ElementOperationPath,\n): [Element, string | null] {\n const element = getElementByPath(rootElement, elementPath)\n return element != null ? [element, propName] : [rootElement, null]\n}\n\nfunction updateParentElements(\n elements: ElementTree['elements'],\n elementPaths: ElementOperationPath[],\n rootElement: Element,\n): void {\n elementPaths.forEach(({ elementPath }) => {\n const element = getElementByPath(rootElement, elementPath)\n if (element != null) elements.set(element.key, element)\n })\n}\n\nfunction hasChildren(\n element: Element,\n propName: string,\n descriptors: DescriptorsByComponentType,\n): boolean {\n if (isElementReference(element)) return false\n\n const propDescriptor = descriptors.get(element.type)?.[propName]\n if (propDescriptor == null) return false\n\n const children = Introspection.getElementChildren(propDescriptor, element.props[propName])\n return children.length > 0\n}\n\nfunction deleteElement(\n { elements, elementIds }: ElementTree,\n deletedElement: Element,\n propName: string | null,\n descriptors: DescriptorsByComponentType,\n) {\n if (propName == null || hasChildren(deletedElement, propName, descriptors)) {\n for (const element of traverseElementTree(deletedElement, descriptors)) {\n elements.delete(element.key)\n elementIds.delete(element.key)\n }\n } else {\n elements.delete(deletedElement.key)\n elementIds.delete(deletedElement.key)\n }\n}\n\nfunction applyDelete(\n elementTree: ElementTree,\n descriptors: DescriptorsByComponentType,\n rootElements: { old: Element; new: Element },\n path: OperationPath,\n): ElementTree {\n const [deleteElementPath, ...parentElementPaths] = getChangedElementsPaths(path)\n const [deletedElement, propName] = getElementAndPropName(rootElements.old, deleteElementPath)\n\n const elements = new Map(elementTree.elements)\n const elementIds = new Map(elementTree.elementIds)\n\n deleteElement({ elements, elementIds }, deletedElement, propName, descriptors)\n updateParentElements(elements, parentElementPaths, rootElements.new)\n\n return {\n elements,\n elementIds,\n }\n}\n\nfunction insertElement(\n { elements, elementIds }: ElementTree,\n insertedElement: Element,\n propName: string | null,\n descriptors: DescriptorsByComponentType,\n) {\n if (propName == null || hasChildren(insertedElement, propName, descriptors)) {\n for (const element of traverseElementTree(insertedElement, descriptors)) {\n elements.set(element.key, element)\n if (!isElementReference(element)) {\n const elementId = getElementIdProp(element, descriptors)\n if (elementId != null) elementIds.set(element.key, elementId)\n }\n }\n } else {\n elements.set(insertedElement.key, insertedElement)\n if (!isElementReference(insertedElement)) {\n const elementId = getElementIdProp(insertedElement, descriptors)\n if (elementId != null) elementIds.set(insertedElement.key, elementId)\n }\n }\n}\n\nfunction applyInsert(\n elementTree: ElementTree,\n descriptors: DescriptorsByComponentType,\n rootElements: { old: Element; new: Element },\n path: OperationPath,\n): ElementTree {\n const [insertedElementPath, ...parentElementPaths] = getChangedElementsPaths(path)\n const [insertedElement, propName] = getElementAndPropName(rootElements.new, insertedElementPath)\n\n const elements = new Map(elementTree.elements)\n const elementIds = new Map(elementTree.elementIds)\n\n insertElement({ elements, elementIds }, insertedElement, propName, descriptors)\n updateParentElements(elements, parentElementPaths, rootElements.new)\n\n return {\n elements,\n elementIds,\n }\n}\n\nfunction applyUpdate(\n elementTree: ElementTree,\n descriptors: DescriptorsByComponentType,\n rootElements: { old: Element; new: Element },\n path: OperationPath,\n): ElementTree {\n const [updateElementPath, ...parentElementPaths] = getChangedElementsPaths(path)\n const [deletedElement, propName] = getElementAndPropName(rootElements.old, updateElementPath)\n const [insertedElement, _] = getElementAndPropName(rootElements.new, updateElementPath)\n\n const elements = new Map(elementTree.elements)\n const elementIds = new Map(elementTree.elementIds)\n\n deleteElement({ elements, elementIds }, deletedElement, propName, descriptors)\n insertElement({ elements, elementIds }, insertedElement, propName, descriptors)\n\n updateParentElements(elements, parentElementPaths, rootElements.new)\n\n return {\n elements,\n elementIds,\n }\n}\n\nfunction applyChanges(\n elementTree: ElementTree,\n descriptors: DescriptorsByComponentType,\n rootElements: { old: Element; new: Element },\n operation: Operation,\n): ElementTree {\n return operation.reduce((tree, op) => {\n const hasDelete = 'ld' in op || 'od' in op\n const hasInsert = 'li' in op || 'oi' in op\n if (hasDelete && hasInsert) {\n return applyUpdate(tree, descriptors, rootElements, op.p)\n }\n\n if (hasDelete) return applyDelete(tree, descriptors, rootElements, op.p)\n if (hasInsert) return applyInsert(tree, descriptors, rootElements, op.p)\n return tree\n }, elementTree)\n}\n"],"mappings":"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","names":["i"]}
|
|
@@ -14,7 +14,7 @@ async function handler(...args) {
|
|
|
14
14
|
const supportsDraftMode = match(args).with(routeHandlerPattern, () => true).with(apiRoutePattern, () => false).exhaustive();
|
|
15
15
|
const supportsWebhook = match(args).with(routeHandlerPattern, () => true).with(apiRoutePattern, () => false).exhaustive();
|
|
16
16
|
const body = {
|
|
17
|
-
version: "0.23.
|
|
17
|
+
version: "0.23.7-canary.1",
|
|
18
18
|
previewMode: supportsPreviewMode,
|
|
19
19
|
draftMode: supportsDraftMode,
|
|
20
20
|
interactionMode: true,
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { useMemo, useRef } from "react";
|
|
2
|
+
function useResolvableRecord(resolvables) {
|
|
3
|
+
const snapshot = useRef({ resolvedValues: {}, dirtyProps: /* @__PURE__ */ new Set() });
|
|
4
|
+
return useMemo(() => {
|
|
5
|
+
return {
|
|
6
|
+
name: "resolvable-record",
|
|
7
|
+
subscribe: (onUpdate) => {
|
|
8
|
+
const unsubscribes = Object.values(resolvables).map((s) => s.subscribe(onUpdate));
|
|
9
|
+
return () => {
|
|
10
|
+
unsubscribes.forEach((u) => u());
|
|
11
|
+
};
|
|
12
|
+
},
|
|
13
|
+
readStable: () => {
|
|
14
|
+
const nextSnapshot = Object.entries(resolvables).reduce(
|
|
15
|
+
({ dirtyProps, resolvedValues }, [propName, subscription]) => {
|
|
16
|
+
const lastPropValue = snapshot.current.resolvedValues[propName];
|
|
17
|
+
const propValue = subscription.readStable();
|
|
18
|
+
const isDirty = propValue !== lastPropValue;
|
|
19
|
+
return {
|
|
20
|
+
dirtyProps: isDirty ? dirtyProps.add(propName) : dirtyProps,
|
|
21
|
+
resolvedValues: { ...resolvedValues, [propName]: propValue }
|
|
22
|
+
};
|
|
23
|
+
},
|
|
24
|
+
{ resolvedValues: {}, dirtyProps: /* @__PURE__ */ new Set() }
|
|
25
|
+
);
|
|
26
|
+
if (nextSnapshot.dirtyProps.size > 0) {
|
|
27
|
+
snapshot.current = nextSnapshot;
|
|
28
|
+
}
|
|
29
|
+
return snapshot.current.resolvedValues;
|
|
30
|
+
},
|
|
31
|
+
triggerResolve: async () => {
|
|
32
|
+
return await Promise.all(
|
|
33
|
+
Object.entries(resolvables).map(
|
|
34
|
+
([propName, sub]) => sub.triggerResolve(snapshot.current.resolvedValues[propName])
|
|
35
|
+
)
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}, [resolvables]);
|
|
40
|
+
}
|
|
41
|
+
export {
|
|
42
|
+
useResolvableRecord
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=use-resolvable-record.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../src/runtimes/react/hooks/use-resolvable-record.tsx"],"sourcesContent":["import { type Resolvable } from '@makeswift/controls'\nimport { useMemo, useRef } from 'react'\n\ntype Snapshot = {\n resolvedValues: Record<string, unknown>\n dirtyProps: Set<string>\n}\n\nexport function useResolvableRecord(\n resolvables: Record<string, Resolvable<unknown>>,\n): Resolvable<Record<string, unknown>> {\n const snapshot = useRef<Snapshot>({ resolvedValues: {}, dirtyProps: new Set() })\n\n return useMemo<Resolvable<Record<string, unknown>>>(() => {\n return {\n name: 'resolvable-record',\n subscribe: (onUpdate: () => void): (() => void) => {\n const unsubscribes = Object.values(resolvables).map(s => s.subscribe(onUpdate))\n return () => {\n unsubscribes.forEach(u => u())\n }\n },\n\n readStable: () => {\n const nextSnapshot = Object.entries(resolvables).reduce<Snapshot>(\n ({ dirtyProps, resolvedValues }, [propName, subscription]) => {\n const lastPropValue = snapshot.current.resolvedValues[propName]\n const propValue = subscription.readStable()\n const isDirty = propValue !== lastPropValue\n\n return {\n dirtyProps: isDirty ? dirtyProps.add(propName) : dirtyProps,\n resolvedValues: { ...resolvedValues, [propName]: propValue },\n }\n },\n { resolvedValues: {}, dirtyProps: new Set() },\n )\n\n if (nextSnapshot.dirtyProps.size > 0) {\n snapshot.current = nextSnapshot\n }\n\n return snapshot.current.resolvedValues\n },\n\n triggerResolve: async () => {\n // While we _could_ only trigger resolution on the dirty props, this is\n // not an airtight solution. Some controls will resolve to nullish\n // values even when the underlying data changes, so they won't be dirty\n // (ex: an Image control where the data changes from `undefined` to a\n // file that has not yet been fetched). Even if you add a nullish check\n // on the resolved value, some controls can resolve to non-nullish value\n // when the resolution does not occur (ex: swatches can resolve to\n // black). The true solution is to trigger resolve on underlying data\n // change, and moving these dirtiness optimizations for resolution\n // triggering at the control level.\n return await Promise.all(\n Object.entries(resolvables).map(([propName, sub]) =>\n sub.triggerResolve(snapshot.current.resolvedValues[propName]),\n ),\n )\n },\n }\n }, [resolvables])\n}\n"],"mappings":"AACA,SAAS,SAAS,cAAc;AAOzB,SAAS,oBACd,aACqC;AACrC,QAAM,WAAW,OAAiB,EAAE,gBAAgB,CAAC,GAAG,YAAY,oBAAI,IAAI,EAAE,CAAC;AAE/E,SAAO,QAA6C,MAAM;AACxD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,WAAW,CAAC,aAAuC;AACjD,cAAM,eAAe,OAAO,OAAO,WAAW,EAAE,IAAI,OAAK,EAAE,UAAU,QAAQ,CAAC;AAC9E,eAAO,MAAM;AACX,uBAAa,QAAQ,OAAK,EAAE,CAAC;AAAA,QAC/B;AAAA,MACF;AAAA,MAEA,YAAY,MAAM;AAChB,cAAM,eAAe,OAAO,QAAQ,WAAW,EAAE;AAAA,UAC/C,CAAC,EAAE,YAAY,eAAe,GAAG,CAAC,UAAU,YAAY,MAAM;AAC5D,kBAAM,gBAAgB,SAAS,QAAQ,eAAe,QAAQ;AAC9D,kBAAM,YAAY,aAAa,WAAW;AAC1C,kBAAM,UAAU,cAAc;AAE9B,mBAAO;AAAA,cACL,YAAY,UAAU,WAAW,IAAI,QAAQ,IAAI;AAAA,cACjD,gBAAgB,EAAE,GAAG,gBAAgB,CAAC,QAAQ,GAAG,UAAU;AAAA,YAC7D;AAAA,UACF;AAAA,UACA,EAAE,gBAAgB,CAAC,GAAG,YAAY,oBAAI,IAAI,EAAE;AAAA,QAC9C;AAEA,YAAI,aAAa,WAAW,OAAO,GAAG;AACpC,mBAAS,UAAU;AAAA,QACrB;AAEA,eAAO,SAAS,QAAQ;AAAA,MAC1B;AAAA,MAEA,gBAAgB,YAAY;AAW1B,eAAO,MAAM,QAAQ;AAAA,UACnB,OAAO,QAAQ,WAAW,EAAE;AAAA,YAAI,CAAC,CAAC,UAAU,GAAG,MAC7C,IAAI,eAAe,SAAS,QAAQ,eAAe,QAAQ,CAAC;AAAA,UAC9D;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,GAAG,CAAC,WAAW,CAAC;AAClB;","names":[]}
|
|
@@ -7,7 +7,7 @@ import { useResourceResolver } from "./use-resource-resolver";
|
|
|
7
7
|
import { useDocumentKey } from "./use-document-context";
|
|
8
8
|
import { useSelector } from "./use-selector";
|
|
9
9
|
import { useStylesheetFactory } from "./use-stylesheet-factory";
|
|
10
|
-
import {
|
|
10
|
+
import { useResolvableRecord } from "./use-resolvable-record";
|
|
11
11
|
import { propErrorHandlingProxy } from "../utils/prop-error-handling-proxy";
|
|
12
12
|
function useControlInstances(elementKey) {
|
|
13
13
|
const documentKey = useDocumentKey();
|
|
@@ -52,10 +52,10 @@ function useResolvedProps(propDefs, elementData, elementKey) {
|
|
|
52
52
|
}),
|
|
53
53
|
[propDefs, resolveProp]
|
|
54
54
|
);
|
|
55
|
-
const props =
|
|
55
|
+
const props = useResolvableRecord(resolvables);
|
|
56
56
|
useEffect(() => {
|
|
57
57
|
props.triggerResolve();
|
|
58
|
-
}, []);
|
|
58
|
+
}, [props]);
|
|
59
59
|
const resolvedProps = useSyncExternalStore(props.subscribe, props.readStable, props.readStable);
|
|
60
60
|
stylesheetFactory.useDefinedStyles();
|
|
61
61
|
return resolvedProps;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/runtimes/react/hooks/use-resolved-props.ts"],"sourcesContent":["import { useMemo, useEffect, useRef, useSyncExternalStore, useCallback } from 'react'\nimport {\n ControlDefinition,\n ControlInstance,\n mapValues,\n type Data,\n type Resolvable,\n} from '@makeswift/controls'\n\nimport * as ReactPage from '../../../state/react-page'\nimport { useResourceResolver } from './use-resource-resolver'\nimport { useDocumentKey } from './use-document-context'\nimport { useSelector } from './use-selector'\n\nimport { useStylesheetFactory } from './use-stylesheet-factory'\n\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../../../src/runtimes/react/hooks/use-resolved-props.ts"],"sourcesContent":["import { useMemo, useEffect, useRef, useSyncExternalStore, useCallback } from 'react'\nimport {\n ControlDefinition,\n ControlInstance,\n mapValues,\n type Data,\n type Resolvable,\n} from '@makeswift/controls'\n\nimport * as ReactPage from '../../../state/react-page'\nimport { useResourceResolver } from './use-resource-resolver'\nimport { useDocumentKey } from './use-document-context'\nimport { useSelector } from './use-selector'\n\nimport { useStylesheetFactory } from './use-stylesheet-factory'\n\nimport { useResolvableRecord } from './use-resolvable-record'\nimport { propErrorHandlingProxy } from '../utils/prop-error-handling-proxy'\n\nfunction useControlInstances(elementKey: string): Record<string, ControlInstance> | null {\n const documentKey = useDocumentKey()\n\n return useSelector(state => {\n if (documentKey == null) return null\n\n return ReactPage.getPropControllers(state, documentKey, elementKey)\n })\n}\n\ntype CacheItem = {\n data: Data\n control: ControlInstance | undefined\n resolvedValue: Resolvable<unknown>\n}\n\nexport function useResolvedProps(\n propDefs: Record<string, ControlDefinition>,\n elementData: Record<string, Data>,\n elementKey: string,\n): Record<string, unknown> {\n const stylesheetFactory = useStylesheetFactory()\n const resourceResolver = useResourceResolver()\n const controls = useControlInstances(elementKey)\n\n const cache = useRef<Record<string, CacheItem>>({}).current\n const resolveProp = useCallback(\n (def: ControlDefinition, propName: string) => {\n const data = elementData[propName]\n const control = controls?.[propName]\n\n if (\n cache[propName] != null &&\n data === cache[propName].data &&\n control === cache[propName].control\n ) {\n return cache[propName].resolvedValue\n }\n\n const resolvedValue = def.resolveValue(\n data,\n resourceResolver,\n stylesheetFactory.get(propName),\n control,\n )\n\n cache[propName] = { data, control, resolvedValue }\n return resolvedValue\n },\n [controls, elementData, resourceResolver, stylesheetFactory],\n )\n\n const resolvables = useMemo<Record<string, Resolvable<unknown>>>(\n () =>\n mapValues(propDefs, (def, propName) => {\n const defaultValue = (def.config as any)?.defaultValue\n return propErrorHandlingProxy(resolveProp(def, propName), defaultValue, error => {\n console.warn(\n `Error reading value for prop \"${propName}\", falling back to \\`${defaultValue}\\`.`,\n { control: def, error },\n )\n })\n }),\n [propDefs, resolveProp],\n )\n\n const props = useResolvableRecord(resolvables)\n\n // no need to call `triggerResolve` on the server, all the resources should already be in\n // the host API client's cache (populated from the snapshot's cache)\n useEffect(() => {\n props.triggerResolve()\n }, [props])\n\n // the order is important here, the styles are defined in the process of the props resolution,\n // calling `useDefinedStyles` before the props are resolved would effectively be a noop\n const resolvedProps = useSyncExternalStore(props.subscribe, props.readStable, props.readStable)\n\n stylesheetFactory.useDefinedStyles()\n\n return resolvedProps\n}\n"],"mappings":"AAAA,SAAS,SAAS,WAAW,QAAQ,sBAAsB,mBAAmB;AAC9E;AAAA,EAGE;AAAA,OAGK;AAEP,YAAY,eAAe;AAC3B,SAAS,2BAA2B;AACpC,SAAS,sBAAsB;AAC/B,SAAS,mBAAmB;AAE5B,SAAS,4BAA4B;AAErC,SAAS,2BAA2B;AACpC,SAAS,8BAA8B;AAEvC,SAAS,oBAAoB,YAA4D;AACvF,QAAM,cAAc,eAAe;AAEnC,SAAO,YAAY,WAAS;AAC1B,QAAI,eAAe;AAAM,aAAO;AAEhC,WAAO,UAAU,mBAAmB,OAAO,aAAa,UAAU;AAAA,EACpE,CAAC;AACH;AAQO,SAAS,iBACd,UACA,aACA,YACyB;AACzB,QAAM,oBAAoB,qBAAqB;AAC/C,QAAM,mBAAmB,oBAAoB;AAC7C,QAAM,WAAW,oBAAoB,UAAU;AAE/C,QAAM,QAAQ,OAAkC,CAAC,CAAC,EAAE;AACpD,QAAM,cAAc;AAAA,IAClB,CAAC,KAAwB,aAAqB;AAC5C,YAAM,OAAO,YAAY,QAAQ;AACjC,YAAM,UAAU,WAAW,QAAQ;AAEnC,UACE,MAAM,QAAQ,KAAK,QACnB,SAAS,MAAM,QAAQ,EAAE,QACzB,YAAY,MAAM,QAAQ,EAAE,SAC5B;AACA,eAAO,MAAM,QAAQ,EAAE;AAAA,MACzB;AAEA,YAAM,gBAAgB,IAAI;AAAA,QACxB;AAAA,QACA;AAAA,QACA,kBAAkB,IAAI,QAAQ;AAAA,QAC9B;AAAA,MACF;AAEA,YAAM,QAAQ,IAAI,EAAE,MAAM,SAAS,cAAc;AACjD,aAAO;AAAA,IACT;AAAA,IACA,CAAC,UAAU,aAAa,kBAAkB,iBAAiB;AAAA,EAC7D;AAEA,QAAM,cAAc;AAAA,IAClB,MACE,UAAU,UAAU,CAAC,KAAK,aAAa;AACrC,YAAM,eAAgB,IAAI,QAAgB;AAC1C,aAAO,uBAAuB,YAAY,KAAK,QAAQ,GAAG,cAAc,WAAS;AAC/E,gBAAQ;AAAA,UACN,iCAAiC,QAAQ,wBAAwB,YAAY;AAAA,UAC7E,EAAE,SAAS,KAAK,MAAM;AAAA,QACxB;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,IACH,CAAC,UAAU,WAAW;AAAA,EACxB;AAEA,QAAM,QAAQ,oBAAoB,WAAW;AAI7C,YAAU,MAAM;AACd,UAAM,eAAe;AAAA,EACvB,GAAG,CAAC,KAAK,CAAC;AAIV,QAAM,gBAAgB,qBAAqB,MAAM,WAAW,MAAM,YAAY,MAAM,UAAU;AAE9F,oBAAkB,iBAAiB;AAEnC,SAAO;AACT;","names":[]}
|
|
@@ -12,8 +12,8 @@ function getInitialState(documents, descriptors) {
|
|
|
12
12
|
}
|
|
13
13
|
return state;
|
|
14
14
|
}
|
|
15
|
-
function getElementTree(state,
|
|
16
|
-
return state.get(
|
|
15
|
+
function getElementTree(state, documentKey) {
|
|
16
|
+
return state.get(documentKey) ?? null;
|
|
17
17
|
}
|
|
18
18
|
function getElements(state, documentKey) {
|
|
19
19
|
return getElementTree(state, documentKey)?.elements ?? /* @__PURE__ */ new Map();
|
|
@@ -111,12 +111,15 @@ function isElement(item) {
|
|
|
111
111
|
return typeof item === "object" && item != null && "key" in item && "type" in item && typeof item.key === "string" && typeof item.type === "string";
|
|
112
112
|
}
|
|
113
113
|
function getElementOperationPath(path) {
|
|
114
|
+
if (path.length === 0) {
|
|
115
|
+
return { elementPath: [], propName: null };
|
|
116
|
+
}
|
|
114
117
|
const i = path.findLastIndex(
|
|
115
118
|
(fragment, i2) => typeof fragment === "number" && (i2 === path.length - 1 || path[i2 + 1] === "props")
|
|
116
119
|
);
|
|
117
|
-
if (
|
|
120
|
+
if (i === -1 && path[0] !== "props" || path.length - i < 3) {
|
|
118
121
|
console.error("Operation path does not point to an element property", { path });
|
|
119
|
-
return { elementPath: [], propName:
|
|
122
|
+
return { elementPath: [], propName: null };
|
|
120
123
|
}
|
|
121
124
|
return { elementPath: path.slice(0, i + 1), propName: `${path.slice(i + 1).at(1)}` };
|
|
122
125
|
}
|
|
@@ -142,7 +145,7 @@ function getElementByPath(rootElement, elementPath) {
|
|
|
142
145
|
}
|
|
143
146
|
function getElementAndPropName(rootElement, { elementPath, propName }) {
|
|
144
147
|
const element = getElementByPath(rootElement, elementPath);
|
|
145
|
-
return element != null ? [element, propName] : [rootElement,
|
|
148
|
+
return element != null ? [element, propName] : [rootElement, null];
|
|
146
149
|
}
|
|
147
150
|
function updateParentElements(elements, elementPaths, rootElement) {
|
|
148
151
|
elementPaths.forEach(({ elementPath }) => {
|
|
@@ -161,7 +164,7 @@ function hasChildren(element, propName, descriptors) {
|
|
|
161
164
|
return children.length > 0;
|
|
162
165
|
}
|
|
163
166
|
function deleteElement({ elements, elementIds }, deletedElement, propName, descriptors) {
|
|
164
|
-
if (hasChildren(deletedElement, propName, descriptors)) {
|
|
167
|
+
if (propName == null || hasChildren(deletedElement, propName, descriptors)) {
|
|
165
168
|
for (const element of traverseElementTree(deletedElement, descriptors)) {
|
|
166
169
|
elements.delete(element.key);
|
|
167
170
|
elementIds.delete(element.key);
|
|
@@ -184,7 +187,7 @@ function applyDelete(elementTree, descriptors, rootElements, path) {
|
|
|
184
187
|
};
|
|
185
188
|
}
|
|
186
189
|
function insertElement({ elements, elementIds }, insertedElement, propName, descriptors) {
|
|
187
|
-
if (hasChildren(insertedElement, propName, descriptors)) {
|
|
190
|
+
if (propName == null || hasChildren(insertedElement, propName, descriptors)) {
|
|
188
191
|
for (const element of traverseElementTree(insertedElement, descriptors)) {
|
|
189
192
|
elements.set(element.key, element);
|
|
190
193
|
if (!isElementReference(element)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/state/modules/element-trees.ts"],"sourcesContent":["import { type Operation } from 'ot-json0'\nimport { getIn } from 'immutable'\n\nimport { type Element, type ElementData, isElementReference } from '@makeswift/controls'\n\nimport { Introspection } from '../../prop-controllers'\n\nimport { type Action, ActionTypes } from '../actions'\n\nimport { getRootElement, type Document } from './read-only-documents'\nimport { type DescriptorsByComponentType } from './prop-controllers'\n\nexport type ElementTree = {\n elements: Map<string, Element>\n elementIds: Map<string, string>\n}\n\nexport type State = Map<string, ElementTree>\n\nexport function getInitialState(\n documents?: Map<string, Document>,\n descriptors?: DescriptorsByComponentType,\n): State {\n const state = new Map<string, ElementTree>()\n if (documents == null || descriptors == null) return state\n\n for (const [documentKey, document] of documents) {\n state.set(documentKey, buildElementTree(getRootElement(document), descriptors))\n }\n\n return state\n}\n\nfunction getElementTree(state: State, id: string): ElementTree | null {\n return state.get(id) ?? null\n}\n\nexport function getElements(state: State, documentKey: string): Map<string, Element> {\n return getElementTree(state, documentKey)?.elements ?? new Map()\n}\n\nexport function getElementIds(state: State, documentKey: string): Map<string, string> {\n return getElementTree(state, documentKey)?.elementIds ?? new Map()\n}\n\nexport function getElement(state: State, documentKey: string, elementKey: string): Element | null {\n return getElements(state, documentKey).get(elementKey) ?? null\n}\n\nexport function getElementId(state: State, documentKey: string, elementKey: string): string | null {\n return getElementIds(state, documentKey).get(elementKey) ?? null\n}\n\nexport function reducer(state: State = getInitialState(), action: Action): State {\n switch (action.type) {\n case ActionTypes.CREATE_ELEMENT_TREE: {\n const { document, descriptors } = action.payload\n return new Map(state).set(\n document.key,\n buildElementTree(getRootElement(document), descriptors),\n )\n }\n\n case ActionTypes.DELETE_ELEMENT_TREE: {\n const nextState = new Map(state)\n const deleted = nextState.delete(action.payload.documentKey)\n return deleted ? nextState : state\n }\n\n case ActionTypes.CHANGE_ELEMENT_TREE: {\n const { oldDocument, newDocument, descriptors, operation } = action.payload\n const documentKey = oldDocument.key\n console.assert(\n documentKey === newDocument.key,\n `Mismatching document keys ${documentKey} !== ${newDocument.key}`,\n )\n\n const elementTree = state.get(documentKey)\n if (elementTree == null) return state\n\n const updatedElementTree = applyChanges(\n elementTree,\n descriptors,\n {\n old: getRootElement(oldDocument),\n new: getRootElement(newDocument),\n },\n operation,\n )\n\n return new Map(state).set(documentKey, updatedElementTree)\n }\n\n default:\n return state\n }\n}\n\nexport function* traverseElementTree(\n element: Element,\n descriptors: DescriptorsByComponentType,\n): Generator<Element> {\n yield element\n if (isElementReference(element)) return\n\n const elementDescriptors = descriptors.get(element.type)\n if (elementDescriptors == null) return\n\n for (const [propKey, descriptor] of Object.entries(elementDescriptors)) {\n const children = Introspection.getElementChildren(descriptor, element.props[propKey])\n for (const child of children) {\n yield* traverseElementTree(child, descriptors)\n }\n }\n}\n\nfunction getElementIdProp(\n element: ElementData,\n descriptors: DescriptorsByComponentType,\n): string | null {\n const elementDescriptors = descriptors.get(element.type)\n if (elementDescriptors == null) return null\n\n for (const [propName, descriptor] of Object.entries(elementDescriptors)) {\n const elementId = Introspection.getElementId(descriptor, element.props[propName])\n if (elementId != null) return elementId\n }\n\n return null\n}\n\nexport function buildElementTree(\n rootElement: Element,\n descriptors: DescriptorsByComponentType,\n): ElementTree {\n const elements = new Map<string, Element>()\n const elementIds = new Map<string, string>()\n\n for (const element of traverseElementTree(rootElement, descriptors)) {\n elements.set(element.key, element)\n if (!isElementReference(element)) {\n const elementId = getElementIdProp(element, descriptors)\n if (elementId != null) elementIds.set(element.key, elementId)\n }\n }\n\n return {\n elements,\n elementIds,\n }\n}\n\ntype OperationPath = Operation[number]['p']\n\n// performance-sensitive function, intentionally not using `elementData` schema here\nfunction isElement(item: unknown): item is Element {\n return (\n typeof item === 'object' &&\n item != null &&\n 'key' in item &&\n 'type' in item &&\n typeof item.key === 'string' &&\n typeof item.type === 'string'\n )\n}\n\ntype ElementOperationPath = { elementPath: OperationPath; propName: string }\n\nfunction getElementOperationPath(path: OperationPath): ElementOperationPath {\n const i = path.findLastIndex(\n (fragment, i) =>\n typeof fragment === 'number' && (i === path.length - 1 || path[i + 1] === 'props'),\n )\n\n if (path.length === 0 || (i === -1 && path[0] !== 'props') || path.length - i < 3) {\n console.error('Operation path does not point to an element property', { path })\n return { elementPath: [], propName: 'children' }\n }\n\n return { elementPath: path.slice(0, i + 1), propName: `${path.slice(i + 1).at(1)}` }\n}\n\nexport function getChangedElementsPaths(\n path: OperationPath,\n): [ElementOperationPath, ...ElementOperationPath[]] {\n let elementOp = getElementOperationPath(path)\n const result: [ElementOperationPath, ...ElementOperationPath[]] = [elementOp]\n while (elementOp.elementPath.length > 0) {\n elementOp = getElementOperationPath(elementOp.elementPath.slice(0, -1))\n result.push(elementOp)\n }\n\n return result\n}\n\nfunction getElementByPath(rootElement: Element, elementPath: OperationPath): Element | null {\n const item = getIn(rootElement, elementPath)\n if (!isElement(item)) {\n console.error('Expected an element, got', item, {\n rootElement,\n elementPath,\n })\n\n return null\n }\n\n return item\n}\n\nfunction getElementAndPropName(\n rootElement: Element,\n { elementPath, propName }: ElementOperationPath,\n): [Element, string] {\n const element = getElementByPath(rootElement, elementPath)\n return element != null ? [element, propName] : [rootElement, 'children']\n}\n\nfunction updateParentElements(\n elements: ElementTree['elements'],\n elementPaths: ElementOperationPath[],\n rootElement: Element,\n): void {\n elementPaths.forEach(({ elementPath }) => {\n const element = getElementByPath(rootElement, elementPath)\n if (element != null) elements.set(element.key, element)\n })\n}\n\nfunction hasChildren(\n element: Element,\n propName: string,\n descriptors: DescriptorsByComponentType,\n): boolean {\n if (isElementReference(element)) return false\n\n const propDescriptor = descriptors.get(element.type)?.[propName]\n if (propDescriptor == null) return false\n\n const children = Introspection.getElementChildren(propDescriptor, element.props[propName])\n return children.length > 0\n}\n\nfunction deleteElement(\n { elements, elementIds }: ElementTree,\n deletedElement: Element,\n propName: string,\n descriptors: DescriptorsByComponentType,\n) {\n if (hasChildren(deletedElement, propName, descriptors)) {\n for (const element of traverseElementTree(deletedElement, descriptors)) {\n elements.delete(element.key)\n elementIds.delete(element.key)\n }\n } else {\n elements.delete(deletedElement.key)\n elementIds.delete(deletedElement.key)\n }\n}\n\nfunction applyDelete(\n elementTree: ElementTree,\n descriptors: DescriptorsByComponentType,\n rootElements: { old: Element; new: Element },\n path: OperationPath,\n): ElementTree {\n const [deleteElementPath, ...parentElementPaths] = getChangedElementsPaths(path)\n const [deletedElement, propName] = getElementAndPropName(rootElements.old, deleteElementPath)\n\n const elements = new Map(elementTree.elements)\n const elementIds = new Map(elementTree.elementIds)\n\n deleteElement({ elements, elementIds }, deletedElement, propName, descriptors)\n updateParentElements(elements, parentElementPaths, rootElements.new)\n\n return {\n elements,\n elementIds,\n }\n}\n\nfunction insertElement(\n { elements, elementIds }: ElementTree,\n insertedElement: Element,\n propName: string,\n descriptors: DescriptorsByComponentType,\n) {\n if (hasChildren(insertedElement, propName, descriptors)) {\n for (const element of traverseElementTree(insertedElement, descriptors)) {\n elements.set(element.key, element)\n if (!isElementReference(element)) {\n const elementId = getElementIdProp(element, descriptors)\n if (elementId != null) elementIds.set(element.key, elementId)\n }\n }\n } else {\n elements.set(insertedElement.key, insertedElement)\n if (!isElementReference(insertedElement)) {\n const elementId = getElementIdProp(insertedElement, descriptors)\n if (elementId != null) elementIds.set(insertedElement.key, elementId)\n }\n }\n}\n\nfunction applyInsert(\n elementTree: ElementTree,\n descriptors: DescriptorsByComponentType,\n rootElements: { old: Element; new: Element },\n path: OperationPath,\n): ElementTree {\n const [insertedElementPath, ...parentElementPaths] = getChangedElementsPaths(path)\n const [insertedElement, propName] = getElementAndPropName(rootElements.new, insertedElementPath)\n\n const elements = new Map(elementTree.elements)\n const elementIds = new Map(elementTree.elementIds)\n\n insertElement({ elements, elementIds }, insertedElement, propName, descriptors)\n updateParentElements(elements, parentElementPaths, rootElements.new)\n\n return {\n elements,\n elementIds,\n }\n}\n\nfunction applyUpdate(\n elementTree: ElementTree,\n descriptors: DescriptorsByComponentType,\n rootElements: { old: Element; new: Element },\n path: OperationPath,\n): ElementTree {\n const [updateElementPath, ...parentElementPaths] = getChangedElementsPaths(path)\n const [deletedElement, propName] = getElementAndPropName(rootElements.old, updateElementPath)\n const [insertedElement, _] = getElementAndPropName(rootElements.new, updateElementPath)\n\n const elements = new Map(elementTree.elements)\n const elementIds = new Map(elementTree.elementIds)\n\n deleteElement({ elements, elementIds }, deletedElement, propName, descriptors)\n insertElement({ elements, elementIds }, insertedElement, propName, descriptors)\n\n updateParentElements(elements, parentElementPaths, rootElements.new)\n\n return {\n elements,\n elementIds,\n }\n}\n\nfunction applyChanges(\n elementTree: ElementTree,\n descriptors: DescriptorsByComponentType,\n rootElements: { old: Element; new: Element },\n operation: Operation,\n): ElementTree {\n return operation.reduce((tree, op) => {\n const hasDelete = 'ld' in op || 'od' in op\n const hasInsert = 'li' in op || 'oi' in op\n if (hasDelete && hasInsert) {\n return applyUpdate(tree, descriptors, rootElements, op.p)\n }\n\n if (hasDelete) return applyDelete(tree, descriptors, rootElements, op.p)\n if (hasInsert) return applyInsert(tree, descriptors, rootElements, op.p)\n return tree\n }, elementTree)\n}\n"],"mappings":"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","names":["i"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/state/modules/element-trees.ts"],"sourcesContent":["import { type Operation } from 'ot-json0'\nimport { getIn } from 'immutable'\n\nimport { type Element, type ElementData, isElementReference } from '@makeswift/controls'\n\nimport { Introspection } from '../../prop-controllers'\n\nimport { type Action, ActionTypes } from '../actions'\n\nimport { getRootElement, type Document } from './read-only-documents'\nimport { type DescriptorsByComponentType } from './prop-controllers'\n\nexport type ElementTree = {\n elements: Map<string, Element>\n elementIds: Map<string, string>\n}\n\nexport type State = Map<string, ElementTree>\n\nexport function getInitialState(\n documents?: Map<string, Document>,\n descriptors?: DescriptorsByComponentType,\n): State {\n const state = new Map<string, ElementTree>()\n if (documents == null || descriptors == null) return state\n\n for (const [documentKey, document] of documents) {\n state.set(documentKey, buildElementTree(getRootElement(document), descriptors))\n }\n\n return state\n}\n\nfunction getElementTree(state: State, documentKey: string): ElementTree | null {\n return state.get(documentKey) ?? null\n}\n\nexport function getElements(state: State, documentKey: string): Map<string, Element> {\n return getElementTree(state, documentKey)?.elements ?? new Map()\n}\n\nexport function getElementIds(state: State, documentKey: string): Map<string, string> {\n return getElementTree(state, documentKey)?.elementIds ?? new Map()\n}\n\nexport function getElement(state: State, documentKey: string, elementKey: string): Element | null {\n return getElements(state, documentKey).get(elementKey) ?? null\n}\n\nexport function getElementId(state: State, documentKey: string, elementKey: string): string | null {\n return getElementIds(state, documentKey).get(elementKey) ?? null\n}\n\nexport function reducer(state: State = getInitialState(), action: Action): State {\n switch (action.type) {\n case ActionTypes.CREATE_ELEMENT_TREE: {\n const { document, descriptors } = action.payload\n return new Map(state).set(\n document.key,\n buildElementTree(getRootElement(document), descriptors),\n )\n }\n\n case ActionTypes.DELETE_ELEMENT_TREE: {\n const nextState = new Map(state)\n const deleted = nextState.delete(action.payload.documentKey)\n return deleted ? nextState : state\n }\n\n case ActionTypes.CHANGE_ELEMENT_TREE: {\n const { oldDocument, newDocument, descriptors, operation } = action.payload\n const documentKey = oldDocument.key\n console.assert(\n documentKey === newDocument.key,\n `Mismatching document keys ${documentKey} !== ${newDocument.key}`,\n )\n\n const elementTree = state.get(documentKey)\n if (elementTree == null) return state\n\n const updatedElementTree = applyChanges(\n elementTree,\n descriptors,\n {\n old: getRootElement(oldDocument),\n new: getRootElement(newDocument),\n },\n operation,\n )\n\n return new Map(state).set(documentKey, updatedElementTree)\n }\n\n default:\n return state\n }\n}\n\nexport function* traverseElementTree(\n element: Element,\n descriptors: DescriptorsByComponentType,\n): Generator<Element> {\n yield element\n if (isElementReference(element)) return\n\n const elementDescriptors = descriptors.get(element.type)\n if (elementDescriptors == null) return\n\n for (const [propKey, descriptor] of Object.entries(elementDescriptors)) {\n const children = Introspection.getElementChildren(descriptor, element.props[propKey])\n for (const child of children) {\n yield* traverseElementTree(child, descriptors)\n }\n }\n}\n\nfunction getElementIdProp(\n element: ElementData,\n descriptors: DescriptorsByComponentType,\n): string | null {\n const elementDescriptors = descriptors.get(element.type)\n if (elementDescriptors == null) return null\n\n for (const [propName, descriptor] of Object.entries(elementDescriptors)) {\n const elementId = Introspection.getElementId(descriptor, element.props[propName])\n if (elementId != null) return elementId\n }\n\n return null\n}\n\nexport function buildElementTree(\n rootElement: Element,\n descriptors: DescriptorsByComponentType,\n): ElementTree {\n const elements = new Map<string, Element>()\n const elementIds = new Map<string, string>()\n\n for (const element of traverseElementTree(rootElement, descriptors)) {\n elements.set(element.key, element)\n if (!isElementReference(element)) {\n const elementId = getElementIdProp(element, descriptors)\n if (elementId != null) elementIds.set(element.key, elementId)\n }\n }\n\n return {\n elements,\n elementIds,\n }\n}\n\ntype OperationPath = Operation[number]['p']\n\n// performance-sensitive function, intentionally not using `elementData` schema here\nfunction isElement(item: unknown): item is Element {\n return (\n typeof item === 'object' &&\n item != null &&\n 'key' in item &&\n 'type' in item &&\n typeof item.key === 'string' &&\n typeof item.type === 'string'\n )\n}\n\ntype ElementOperationPath = { elementPath: OperationPath; propName: string | null }\n\nfunction getElementOperationPath(path: OperationPath): ElementOperationPath {\n if (path.length === 0) {\n return { elementPath: [], propName: null }\n }\n\n const i = path.findLastIndex(\n (fragment, i) =>\n typeof fragment === 'number' && (i === path.length - 1 || path[i + 1] === 'props'),\n )\n\n if ((i === -1 && path[0] !== 'props') || path.length - i < 3) {\n console.error('Operation path does not point to an element property', { path })\n return { elementPath: [], propName: null }\n }\n\n return { elementPath: path.slice(0, i + 1), propName: `${path.slice(i + 1).at(1)}` }\n}\n\nexport function getChangedElementsPaths(\n path: OperationPath,\n): [ElementOperationPath, ...ElementOperationPath[]] {\n let elementOp = getElementOperationPath(path)\n const result: [ElementOperationPath, ...ElementOperationPath[]] = [elementOp]\n while (elementOp.elementPath.length > 0) {\n elementOp = getElementOperationPath(elementOp.elementPath.slice(0, -1))\n result.push(elementOp)\n }\n\n return result\n}\n\nfunction getElementByPath(rootElement: Element, elementPath: OperationPath): Element | null {\n const item = getIn(rootElement, elementPath)\n if (!isElement(item)) {\n console.error('Expected an element, got', item, {\n rootElement,\n elementPath,\n })\n\n return null\n }\n\n return item\n}\n\nfunction getElementAndPropName(\n rootElement: Element,\n { elementPath, propName }: ElementOperationPath,\n): [Element, string | null] {\n const element = getElementByPath(rootElement, elementPath)\n return element != null ? [element, propName] : [rootElement, null]\n}\n\nfunction updateParentElements(\n elements: ElementTree['elements'],\n elementPaths: ElementOperationPath[],\n rootElement: Element,\n): void {\n elementPaths.forEach(({ elementPath }) => {\n const element = getElementByPath(rootElement, elementPath)\n if (element != null) elements.set(element.key, element)\n })\n}\n\nfunction hasChildren(\n element: Element,\n propName: string,\n descriptors: DescriptorsByComponentType,\n): boolean {\n if (isElementReference(element)) return false\n\n const propDescriptor = descriptors.get(element.type)?.[propName]\n if (propDescriptor == null) return false\n\n const children = Introspection.getElementChildren(propDescriptor, element.props[propName])\n return children.length > 0\n}\n\nfunction deleteElement(\n { elements, elementIds }: ElementTree,\n deletedElement: Element,\n propName: string | null,\n descriptors: DescriptorsByComponentType,\n) {\n if (propName == null || hasChildren(deletedElement, propName, descriptors)) {\n for (const element of traverseElementTree(deletedElement, descriptors)) {\n elements.delete(element.key)\n elementIds.delete(element.key)\n }\n } else {\n elements.delete(deletedElement.key)\n elementIds.delete(deletedElement.key)\n }\n}\n\nfunction applyDelete(\n elementTree: ElementTree,\n descriptors: DescriptorsByComponentType,\n rootElements: { old: Element; new: Element },\n path: OperationPath,\n): ElementTree {\n const [deleteElementPath, ...parentElementPaths] = getChangedElementsPaths(path)\n const [deletedElement, propName] = getElementAndPropName(rootElements.old, deleteElementPath)\n\n const elements = new Map(elementTree.elements)\n const elementIds = new Map(elementTree.elementIds)\n\n deleteElement({ elements, elementIds }, deletedElement, propName, descriptors)\n updateParentElements(elements, parentElementPaths, rootElements.new)\n\n return {\n elements,\n elementIds,\n }\n}\n\nfunction insertElement(\n { elements, elementIds }: ElementTree,\n insertedElement: Element,\n propName: string | null,\n descriptors: DescriptorsByComponentType,\n) {\n if (propName == null || hasChildren(insertedElement, propName, descriptors)) {\n for (const element of traverseElementTree(insertedElement, descriptors)) {\n elements.set(element.key, element)\n if (!isElementReference(element)) {\n const elementId = getElementIdProp(element, descriptors)\n if (elementId != null) elementIds.set(element.key, elementId)\n }\n }\n } else {\n elements.set(insertedElement.key, insertedElement)\n if (!isElementReference(insertedElement)) {\n const elementId = getElementIdProp(insertedElement, descriptors)\n if (elementId != null) elementIds.set(insertedElement.key, elementId)\n }\n }\n}\n\nfunction applyInsert(\n elementTree: ElementTree,\n descriptors: DescriptorsByComponentType,\n rootElements: { old: Element; new: Element },\n path: OperationPath,\n): ElementTree {\n const [insertedElementPath, ...parentElementPaths] = getChangedElementsPaths(path)\n const [insertedElement, propName] = getElementAndPropName(rootElements.new, insertedElementPath)\n\n const elements = new Map(elementTree.elements)\n const elementIds = new Map(elementTree.elementIds)\n\n insertElement({ elements, elementIds }, insertedElement, propName, descriptors)\n updateParentElements(elements, parentElementPaths, rootElements.new)\n\n return {\n elements,\n elementIds,\n }\n}\n\nfunction applyUpdate(\n elementTree: ElementTree,\n descriptors: DescriptorsByComponentType,\n rootElements: { old: Element; new: Element },\n path: OperationPath,\n): ElementTree {\n const [updateElementPath, ...parentElementPaths] = getChangedElementsPaths(path)\n const [deletedElement, propName] = getElementAndPropName(rootElements.old, updateElementPath)\n const [insertedElement, _] = getElementAndPropName(rootElements.new, updateElementPath)\n\n const elements = new Map(elementTree.elements)\n const elementIds = new Map(elementTree.elementIds)\n\n deleteElement({ elements, elementIds }, deletedElement, propName, descriptors)\n insertElement({ elements, elementIds }, insertedElement, propName, descriptors)\n\n updateParentElements(elements, parentElementPaths, rootElements.new)\n\n return {\n elements,\n elementIds,\n }\n}\n\nfunction applyChanges(\n elementTree: ElementTree,\n descriptors: DescriptorsByComponentType,\n rootElements: { old: Element; new: Element },\n operation: Operation,\n): ElementTree {\n return operation.reduce((tree, op) => {\n const hasDelete = 'ld' in op || 'od' in op\n const hasInsert = 'li' in op || 'oi' in op\n if (hasDelete && hasInsert) {\n return applyUpdate(tree, descriptors, rootElements, op.p)\n }\n\n if (hasDelete) return applyDelete(tree, descriptors, rootElements, op.p)\n if (hasInsert) return applyInsert(tree, descriptors, rootElements, op.p)\n return tree\n }, elementTree)\n}\n"],"mappings":"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","names":["i"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-resolvable-record.d.ts","sourceRoot":"","sources":["../../../../../src/runtimes/react/hooks/use-resolvable-record.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAQrD,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,GAC/C,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAsDrC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
export declare const ELEMENT_TREE_DEMO_COMPONENT_TYPE = "Demo";
|
|
3
|
+
export declare function ElementTreesDemo({ left, right }: {
|
|
4
|
+
left: ReactNode;
|
|
5
|
+
right: ReactNode;
|
|
6
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
//# sourceMappingURL=element-trees-demo-component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"element-trees-demo-component.d.ts","sourceRoot":"","sources":["../../../../../../src/state/modules/__tests__/fixtures/element-trees-demo-component.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,eAAO,MAAM,gCAAgC,SAAS,CAAA;AAEtD,wBAAgB,gBAAgB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,2CAOtF"}
|
|
@@ -1542,4 +1542,243 @@ export declare const homePage: {
|
|
|
1542
1542
|
};
|
|
1543
1543
|
type: string;
|
|
1544
1544
|
};
|
|
1545
|
+
export declare const resetElementTree: {
|
|
1546
|
+
beforeReset: {
|
|
1547
|
+
type: string;
|
|
1548
|
+
key: string;
|
|
1549
|
+
props: {
|
|
1550
|
+
left: {
|
|
1551
|
+
columns: {
|
|
1552
|
+
value: {
|
|
1553
|
+
count: number;
|
|
1554
|
+
spans: number[][];
|
|
1555
|
+
};
|
|
1556
|
+
deviceId: string;
|
|
1557
|
+
}[];
|
|
1558
|
+
elements: {
|
|
1559
|
+
key: string;
|
|
1560
|
+
type: string;
|
|
1561
|
+
props: {
|
|
1562
|
+
padding: {
|
|
1563
|
+
value: {
|
|
1564
|
+
paddingTop: {
|
|
1565
|
+
unit: string;
|
|
1566
|
+
value: number;
|
|
1567
|
+
};
|
|
1568
|
+
paddingLeft: {
|
|
1569
|
+
unit: string;
|
|
1570
|
+
value: number;
|
|
1571
|
+
};
|
|
1572
|
+
paddingRight: {
|
|
1573
|
+
unit: string;
|
|
1574
|
+
value: number;
|
|
1575
|
+
};
|
|
1576
|
+
paddingBottom: {
|
|
1577
|
+
unit: string;
|
|
1578
|
+
value: number;
|
|
1579
|
+
};
|
|
1580
|
+
};
|
|
1581
|
+
deviceId: string;
|
|
1582
|
+
}[];
|
|
1583
|
+
children: {
|
|
1584
|
+
value: {
|
|
1585
|
+
columns: {
|
|
1586
|
+
value: {
|
|
1587
|
+
count: number;
|
|
1588
|
+
spans: number[][];
|
|
1589
|
+
};
|
|
1590
|
+
deviceId: string;
|
|
1591
|
+
}[];
|
|
1592
|
+
elements: ({
|
|
1593
|
+
key: string;
|
|
1594
|
+
type: string;
|
|
1595
|
+
props: {
|
|
1596
|
+
padding: {
|
|
1597
|
+
value: {
|
|
1598
|
+
paddingTop: {
|
|
1599
|
+
unit: string;
|
|
1600
|
+
value: number;
|
|
1601
|
+
};
|
|
1602
|
+
paddingLeft: {
|
|
1603
|
+
unit: string;
|
|
1604
|
+
value: number;
|
|
1605
|
+
};
|
|
1606
|
+
paddingRight: {
|
|
1607
|
+
unit: string;
|
|
1608
|
+
value: number;
|
|
1609
|
+
};
|
|
1610
|
+
paddingBottom: {
|
|
1611
|
+
unit: string;
|
|
1612
|
+
value: number;
|
|
1613
|
+
};
|
|
1614
|
+
};
|
|
1615
|
+
deviceId: string;
|
|
1616
|
+
}[];
|
|
1617
|
+
children: {
|
|
1618
|
+
value: {
|
|
1619
|
+
columns: {
|
|
1620
|
+
value: {
|
|
1621
|
+
count: number;
|
|
1622
|
+
spans: number[][];
|
|
1623
|
+
};
|
|
1624
|
+
deviceId: string;
|
|
1625
|
+
}[];
|
|
1626
|
+
elements: {
|
|
1627
|
+
key: string;
|
|
1628
|
+
type: string;
|
|
1629
|
+
props: {};
|
|
1630
|
+
}[];
|
|
1631
|
+
};
|
|
1632
|
+
'@@makeswift/type': string;
|
|
1633
|
+
};
|
|
1634
|
+
};
|
|
1635
|
+
} | {
|
|
1636
|
+
key: string;
|
|
1637
|
+
type: string;
|
|
1638
|
+
props: {
|
|
1639
|
+
padding: {
|
|
1640
|
+
value: {
|
|
1641
|
+
paddingTop: {
|
|
1642
|
+
unit: string;
|
|
1643
|
+
value: number;
|
|
1644
|
+
};
|
|
1645
|
+
paddingLeft: {
|
|
1646
|
+
unit: string;
|
|
1647
|
+
value: number;
|
|
1648
|
+
};
|
|
1649
|
+
paddingRight: {
|
|
1650
|
+
unit: string;
|
|
1651
|
+
value: number;
|
|
1652
|
+
};
|
|
1653
|
+
paddingBottom: {
|
|
1654
|
+
unit: string;
|
|
1655
|
+
value: number;
|
|
1656
|
+
};
|
|
1657
|
+
};
|
|
1658
|
+
deviceId: string;
|
|
1659
|
+
}[];
|
|
1660
|
+
children?: undefined;
|
|
1661
|
+
};
|
|
1662
|
+
})[];
|
|
1663
|
+
};
|
|
1664
|
+
'@@makeswift/type': string;
|
|
1665
|
+
};
|
|
1666
|
+
};
|
|
1667
|
+
}[];
|
|
1668
|
+
};
|
|
1669
|
+
right: {
|
|
1670
|
+
columns: {
|
|
1671
|
+
value: {
|
|
1672
|
+
count: number;
|
|
1673
|
+
spans: number[][];
|
|
1674
|
+
};
|
|
1675
|
+
deviceId: string;
|
|
1676
|
+
}[];
|
|
1677
|
+
elements: {
|
|
1678
|
+
key: string;
|
|
1679
|
+
type: string;
|
|
1680
|
+
props: {
|
|
1681
|
+
padding: {
|
|
1682
|
+
value: {
|
|
1683
|
+
paddingTop: {
|
|
1684
|
+
unit: string;
|
|
1685
|
+
value: number;
|
|
1686
|
+
};
|
|
1687
|
+
paddingLeft: {
|
|
1688
|
+
unit: string;
|
|
1689
|
+
value: number;
|
|
1690
|
+
};
|
|
1691
|
+
paddingRight: {
|
|
1692
|
+
unit: string;
|
|
1693
|
+
value: number;
|
|
1694
|
+
};
|
|
1695
|
+
paddingBottom: {
|
|
1696
|
+
unit: string;
|
|
1697
|
+
value: number;
|
|
1698
|
+
};
|
|
1699
|
+
};
|
|
1700
|
+
deviceId: string;
|
|
1701
|
+
}[];
|
|
1702
|
+
children: {
|
|
1703
|
+
value: {
|
|
1704
|
+
columns: {
|
|
1705
|
+
value: {
|
|
1706
|
+
count: number;
|
|
1707
|
+
spans: number[][];
|
|
1708
|
+
};
|
|
1709
|
+
deviceId: string;
|
|
1710
|
+
}[];
|
|
1711
|
+
elements: {
|
|
1712
|
+
key: string;
|
|
1713
|
+
type: string;
|
|
1714
|
+
props: {
|
|
1715
|
+
padding: {
|
|
1716
|
+
value: {
|
|
1717
|
+
paddingTop: {
|
|
1718
|
+
unit: string;
|
|
1719
|
+
value: number;
|
|
1720
|
+
};
|
|
1721
|
+
paddingLeft: {
|
|
1722
|
+
unit: string;
|
|
1723
|
+
value: number;
|
|
1724
|
+
};
|
|
1725
|
+
paddingRight: {
|
|
1726
|
+
unit: string;
|
|
1727
|
+
value: number;
|
|
1728
|
+
};
|
|
1729
|
+
paddingBottom: {
|
|
1730
|
+
unit: string;
|
|
1731
|
+
value: number;
|
|
1732
|
+
};
|
|
1733
|
+
};
|
|
1734
|
+
deviceId: string;
|
|
1735
|
+
}[];
|
|
1736
|
+
children: {
|
|
1737
|
+
value: {
|
|
1738
|
+
columns: {
|
|
1739
|
+
value: {
|
|
1740
|
+
count: number;
|
|
1741
|
+
spans: number[][];
|
|
1742
|
+
};
|
|
1743
|
+
deviceId: string;
|
|
1744
|
+
}[];
|
|
1745
|
+
elements: {
|
|
1746
|
+
key: string;
|
|
1747
|
+
type: string;
|
|
1748
|
+
props: {};
|
|
1749
|
+
}[];
|
|
1750
|
+
};
|
|
1751
|
+
'@@makeswift/type': string;
|
|
1752
|
+
};
|
|
1753
|
+
};
|
|
1754
|
+
}[];
|
|
1755
|
+
};
|
|
1756
|
+
'@@makeswift/type': string;
|
|
1757
|
+
};
|
|
1758
|
+
};
|
|
1759
|
+
}[];
|
|
1760
|
+
};
|
|
1761
|
+
};
|
|
1762
|
+
};
|
|
1763
|
+
afterReset: {
|
|
1764
|
+
type: string;
|
|
1765
|
+
key: string;
|
|
1766
|
+
props: {
|
|
1767
|
+
left: {
|
|
1768
|
+
columns: {
|
|
1769
|
+
value: {
|
|
1770
|
+
count: number;
|
|
1771
|
+
spans: number[][];
|
|
1772
|
+
};
|
|
1773
|
+
deviceId: string;
|
|
1774
|
+
}[];
|
|
1775
|
+
elements: {
|
|
1776
|
+
key: string;
|
|
1777
|
+
type: string;
|
|
1778
|
+
props: {};
|
|
1779
|
+
}[];
|
|
1780
|
+
};
|
|
1781
|
+
};
|
|
1782
|
+
};
|
|
1783
|
+
};
|
|
1545
1784
|
//# sourceMappingURL=element-trees.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"element-trees.d.ts","sourceRoot":"","sources":["../../../../../../src/state/modules/__tests__/fixtures/element-trees.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAy6HpB,CAAA"}
|
|
1
|
+
{"version":3,"file":"element-trees.d.ts","sourceRoot":"","sources":["../../../../../../src/state/modules/__tests__/fixtures/element-trees.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAy6HpB,CAAA;AAED,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqR5B,CAAA"}
|
|
@@ -19,7 +19,7 @@ export declare function buildElementTree(rootElement: Element, descriptors: Desc
|
|
|
19
19
|
type OperationPath = Operation[number]['p'];
|
|
20
20
|
type ElementOperationPath = {
|
|
21
21
|
elementPath: OperationPath;
|
|
22
|
-
propName: string;
|
|
22
|
+
propName: string | null;
|
|
23
23
|
};
|
|
24
24
|
export declare function getChangedElementsPaths(path: OperationPath): [ElementOperationPath, ...ElementOperationPath[]];
|
|
25
25
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"element-trees.d.ts","sourceRoot":"","sources":["../../../../src/state/modules/element-trees.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,UAAU,CAAA;AAGzC,OAAO,EAAE,KAAK,OAAO,EAAwC,MAAM,qBAAqB,CAAA;AAIxF,OAAO,EAAE,KAAK,MAAM,EAAe,MAAM,YAAY,CAAA;AAErD,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AACrE,OAAO,EAAE,KAAK,0BAA0B,EAAE,MAAM,oBAAoB,CAAA;AAEpE,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAChC,CAAA;AAED,MAAM,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;AAE5C,wBAAgB,eAAe,CAC7B,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,EACjC,WAAW,CAAC,EAAE,0BAA0B,GACvC,KAAK,CASP;AAMD,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAEnF;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAEpF;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAEhG;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEjG;AAED,wBAAgB,OAAO,CAAC,KAAK,mBAA2B,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,CA2C/E;AAED,wBAAiB,mBAAmB,CAClC,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,0BAA0B,GACtC,SAAS,CAAC,OAAO,CAAC,CAapB;AAiBD,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,OAAO,EACpB,WAAW,EAAE,0BAA0B,GACtC,WAAW,CAgBb;AAED,KAAK,aAAa,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAA;AAc3C,KAAK,oBAAoB,GAAG;IAAE,WAAW,EAAE,aAAa,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"element-trees.d.ts","sourceRoot":"","sources":["../../../../src/state/modules/element-trees.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,UAAU,CAAA;AAGzC,OAAO,EAAE,KAAK,OAAO,EAAwC,MAAM,qBAAqB,CAAA;AAIxF,OAAO,EAAE,KAAK,MAAM,EAAe,MAAM,YAAY,CAAA;AAErD,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AACrE,OAAO,EAAE,KAAK,0BAA0B,EAAE,MAAM,oBAAoB,CAAA;AAEpE,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAChC,CAAA;AAED,MAAM,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;AAE5C,wBAAgB,eAAe,CAC7B,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,EACjC,WAAW,CAAC,EAAE,0BAA0B,GACvC,KAAK,CASP;AAMD,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAEnF;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAEpF;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAEhG;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEjG;AAED,wBAAgB,OAAO,CAAC,KAAK,mBAA2B,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,CA2C/E;AAED,wBAAiB,mBAAmB,CAClC,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,0BAA0B,GACtC,SAAS,CAAC,OAAO,CAAC,CAapB;AAiBD,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,OAAO,EACpB,WAAW,EAAE,0BAA0B,GACtC,WAAW,CAgBb;AAED,KAAK,aAAa,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAA;AAc3C,KAAK,oBAAoB,GAAG;IAAE,WAAW,EAAE,aAAa,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAA;AAoBnF,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,aAAa,GAClB,CAAC,oBAAoB,EAAE,GAAG,oBAAoB,EAAE,CAAC,CASnD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@makeswift/runtime",
|
|
3
|
-
"version": "0.23.
|
|
3
|
+
"version": "0.23.7-canary.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -157,8 +157,8 @@
|
|
|
157
157
|
"uuid": "^9.0.0",
|
|
158
158
|
"zod": "^3.21.4",
|
|
159
159
|
"@makeswift/controls": "0.1.8",
|
|
160
|
-
"@makeswift/
|
|
161
|
-
"@makeswift/
|
|
160
|
+
"@makeswift/next-plugin": "0.3.1",
|
|
161
|
+
"@makeswift/prop-controllers": "0.4.1"
|
|
162
162
|
},
|
|
163
163
|
"devDependencies": {
|
|
164
164
|
"@emotion/jest": "^11.11.0",
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
var resolvable_record_exports = {};
|
|
20
|
-
__export(resolvable_record_exports, {
|
|
21
|
-
resolvableRecord: () => resolvableRecord
|
|
22
|
-
});
|
|
23
|
-
module.exports = __toCommonJS(resolvable_record_exports);
|
|
24
|
-
function resolvableRecord(resolvables) {
|
|
25
|
-
let resolvedValues = {};
|
|
26
|
-
return {
|
|
27
|
-
name: "resolvable-record",
|
|
28
|
-
subscribe: (onUpdate) => {
|
|
29
|
-
const unsubscribes = Object.values(resolvables).map((s) => s.subscribe(onUpdate));
|
|
30
|
-
return () => {
|
|
31
|
-
unsubscribes.forEach((u) => u());
|
|
32
|
-
};
|
|
33
|
-
},
|
|
34
|
-
readStable: () => {
|
|
35
|
-
const { isDirty, resolved } = Object.entries(resolvables).reduce(
|
|
36
|
-
({ isDirty: isDirty2, resolved: resolved2 }, [propName, subscription]) => {
|
|
37
|
-
const lastPropValue = resolvedValues[propName];
|
|
38
|
-
const propValue = subscription.readStable();
|
|
39
|
-
return {
|
|
40
|
-
isDirty: isDirty2 || propValue !== lastPropValue,
|
|
41
|
-
resolved: {
|
|
42
|
-
...resolved2,
|
|
43
|
-
[propName]: propValue
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
},
|
|
47
|
-
{ isDirty: false, resolved: {} }
|
|
48
|
-
);
|
|
49
|
-
if (isDirty) {
|
|
50
|
-
resolvedValues = resolved;
|
|
51
|
-
}
|
|
52
|
-
return resolvedValues;
|
|
53
|
-
},
|
|
54
|
-
triggerResolve: async () => {
|
|
55
|
-
return await Promise.all(
|
|
56
|
-
Object.entries(resolvables).map(
|
|
57
|
-
([propName, sub]) => sub.triggerResolve(resolvedValues[propName])
|
|
58
|
-
)
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
64
|
-
0 && (module.exports = {
|
|
65
|
-
resolvableRecord
|
|
66
|
-
});
|
|
67
|
-
//# sourceMappingURL=resolvable-record.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/runtimes/react/resolvable-record.tsx"],"sourcesContent":["import { type Resolvable } from '@makeswift/controls'\n\nexport function resolvableRecord(\n resolvables: Record<string, Resolvable<unknown>>,\n): Resolvable<Record<string, unknown>> {\n let resolvedValues: Record<string, unknown> = {}\n\n return {\n name: 'resolvable-record',\n subscribe: (onUpdate: () => void): (() => void) => {\n const unsubscribes = Object.values(resolvables).map(s => s.subscribe(onUpdate))\n return () => {\n unsubscribes.forEach(u => u())\n }\n },\n\n readStable: () => {\n const { isDirty, resolved } = Object.entries(resolvables).reduce(\n ({ isDirty, resolved }, [propName, subscription]) => {\n const lastPropValue = resolvedValues[propName]\n const propValue = subscription.readStable()\n return {\n isDirty: isDirty || propValue !== lastPropValue,\n resolved: {\n ...resolved,\n [propName]: propValue,\n },\n }\n },\n { isDirty: false, resolved: {} },\n )\n\n if (isDirty) {\n resolvedValues = resolved\n }\n\n return resolvedValues\n },\n\n triggerResolve: async () => {\n return await Promise.all(\n Object.entries(resolvables).map(([propName, sub]) =>\n sub.triggerResolve(resolvedValues[propName]),\n ),\n )\n },\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEO,SAAS,iBACd,aACqC;AACrC,MAAI,iBAA0C,CAAC;AAE/C,SAAO;AAAA,IACL,MAAM;AAAA,IACN,WAAW,CAAC,aAAuC;AACjD,YAAM,eAAe,OAAO,OAAO,WAAW,EAAE,IAAI,OAAK,EAAE,UAAU,QAAQ,CAAC;AAC9E,aAAO,MAAM;AACX,qBAAa,QAAQ,OAAK,EAAE,CAAC;AAAA,MAC/B;AAAA,IACF;AAAA,IAEA,YAAY,MAAM;AAChB,YAAM,EAAE,SAAS,SAAS,IAAI,OAAO,QAAQ,WAAW,EAAE;AAAA,QACxD,CAAC,EAAE,SAAAA,UAAS,UAAAC,UAAS,GAAG,CAAC,UAAU,YAAY,MAAM;AACnD,gBAAM,gBAAgB,eAAe,QAAQ;AAC7C,gBAAM,YAAY,aAAa,WAAW;AAC1C,iBAAO;AAAA,YACL,SAASD,YAAW,cAAc;AAAA,YAClC,UAAU;AAAA,cACR,GAAGC;AAAA,cACH,CAAC,QAAQ,GAAG;AAAA,YACd;AAAA,UACF;AAAA,QACF;AAAA,QACA,EAAE,SAAS,OAAO,UAAU,CAAC,EAAE;AAAA,MACjC;AAEA,UAAI,SAAS;AACX,yBAAiB;AAAA,MACnB;AAEA,aAAO;AAAA,IACT;AAAA,IAEA,gBAAgB,YAAY;AAC1B,aAAO,MAAM,QAAQ;AAAA,QACnB,OAAO,QAAQ,WAAW,EAAE;AAAA,UAAI,CAAC,CAAC,UAAU,GAAG,MAC7C,IAAI,eAAe,eAAe,QAAQ,CAAC;AAAA,QAC7C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":["isDirty","resolved"]}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
function resolvableRecord(resolvables) {
|
|
2
|
-
let resolvedValues = {};
|
|
3
|
-
return {
|
|
4
|
-
name: "resolvable-record",
|
|
5
|
-
subscribe: (onUpdate) => {
|
|
6
|
-
const unsubscribes = Object.values(resolvables).map((s) => s.subscribe(onUpdate));
|
|
7
|
-
return () => {
|
|
8
|
-
unsubscribes.forEach((u) => u());
|
|
9
|
-
};
|
|
10
|
-
},
|
|
11
|
-
readStable: () => {
|
|
12
|
-
const { isDirty, resolved } = Object.entries(resolvables).reduce(
|
|
13
|
-
({ isDirty: isDirty2, resolved: resolved2 }, [propName, subscription]) => {
|
|
14
|
-
const lastPropValue = resolvedValues[propName];
|
|
15
|
-
const propValue = subscription.readStable();
|
|
16
|
-
return {
|
|
17
|
-
isDirty: isDirty2 || propValue !== lastPropValue,
|
|
18
|
-
resolved: {
|
|
19
|
-
...resolved2,
|
|
20
|
-
[propName]: propValue
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
},
|
|
24
|
-
{ isDirty: false, resolved: {} }
|
|
25
|
-
);
|
|
26
|
-
if (isDirty) {
|
|
27
|
-
resolvedValues = resolved;
|
|
28
|
-
}
|
|
29
|
-
return resolvedValues;
|
|
30
|
-
},
|
|
31
|
-
triggerResolve: async () => {
|
|
32
|
-
return await Promise.all(
|
|
33
|
-
Object.entries(resolvables).map(
|
|
34
|
-
([propName, sub]) => sub.triggerResolve(resolvedValues[propName])
|
|
35
|
-
)
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
export {
|
|
41
|
-
resolvableRecord
|
|
42
|
-
};
|
|
43
|
-
//# sourceMappingURL=resolvable-record.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/runtimes/react/resolvable-record.tsx"],"sourcesContent":["import { type Resolvable } from '@makeswift/controls'\n\nexport function resolvableRecord(\n resolvables: Record<string, Resolvable<unknown>>,\n): Resolvable<Record<string, unknown>> {\n let resolvedValues: Record<string, unknown> = {}\n\n return {\n name: 'resolvable-record',\n subscribe: (onUpdate: () => void): (() => void) => {\n const unsubscribes = Object.values(resolvables).map(s => s.subscribe(onUpdate))\n return () => {\n unsubscribes.forEach(u => u())\n }\n },\n\n readStable: () => {\n const { isDirty, resolved } = Object.entries(resolvables).reduce(\n ({ isDirty, resolved }, [propName, subscription]) => {\n const lastPropValue = resolvedValues[propName]\n const propValue = subscription.readStable()\n return {\n isDirty: isDirty || propValue !== lastPropValue,\n resolved: {\n ...resolved,\n [propName]: propValue,\n },\n }\n },\n { isDirty: false, resolved: {} },\n )\n\n if (isDirty) {\n resolvedValues = resolved\n }\n\n return resolvedValues\n },\n\n triggerResolve: async () => {\n return await Promise.all(\n Object.entries(resolvables).map(([propName, sub]) =>\n sub.triggerResolve(resolvedValues[propName]),\n ),\n )\n },\n }\n}\n"],"mappings":"AAEO,SAAS,iBACd,aACqC;AACrC,MAAI,iBAA0C,CAAC;AAE/C,SAAO;AAAA,IACL,MAAM;AAAA,IACN,WAAW,CAAC,aAAuC;AACjD,YAAM,eAAe,OAAO,OAAO,WAAW,EAAE,IAAI,OAAK,EAAE,UAAU,QAAQ,CAAC;AAC9E,aAAO,MAAM;AACX,qBAAa,QAAQ,OAAK,EAAE,CAAC;AAAA,MAC/B;AAAA,IACF;AAAA,IAEA,YAAY,MAAM;AAChB,YAAM,EAAE,SAAS,SAAS,IAAI,OAAO,QAAQ,WAAW,EAAE;AAAA,QACxD,CAAC,EAAE,SAAAA,UAAS,UAAAC,UAAS,GAAG,CAAC,UAAU,YAAY,MAAM;AACnD,gBAAM,gBAAgB,eAAe,QAAQ;AAC7C,gBAAM,YAAY,aAAa,WAAW;AAC1C,iBAAO;AAAA,YACL,SAASD,YAAW,cAAc;AAAA,YAClC,UAAU;AAAA,cACR,GAAGC;AAAA,cACH,CAAC,QAAQ,GAAG;AAAA,YACd;AAAA,UACF;AAAA,QACF;AAAA,QACA,EAAE,SAAS,OAAO,UAAU,CAAC,EAAE;AAAA,MACjC;AAEA,UAAI,SAAS;AACX,yBAAiB;AAAA,MACnB;AAEA,aAAO;AAAA,IACT;AAAA,IAEA,gBAAgB,YAAY;AAC1B,aAAO,MAAM,QAAQ;AAAA,QACnB,OAAO,QAAQ,WAAW,EAAE;AAAA,UAAI,CAAC,CAAC,UAAU,GAAG,MAC7C,IAAI,eAAe,eAAe,QAAQ,CAAC;AAAA,QAC7C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":["isDirty","resolved"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resolvable-record.d.ts","sourceRoot":"","sources":["../../../../src/runtimes/react/resolvable-record.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAErD,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,GAC/C,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA2CrC"}
|