@ankhorage/zora 27.0.3 → 27.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/README.md +1 -1
- package/dist/authoring.d.ts +6 -0
- package/dist/authoring.d.ts.map +1 -0
- package/dist/authoring.js +5 -0
- package/dist/authoring.js.map +1 -0
- package/dist/features/button/utils/resolveButtonThemeRecipe.d.ts +1 -1
- package/dist/features/registry/adapters/inbound/AuthoringBindingEditorAdapter.d.ts +5 -0
- package/dist/features/registry/adapters/inbound/AuthoringBindingEditorAdapter.d.ts.map +1 -0
- package/dist/features/registry/adapters/inbound/AuthoringBindingEditorAdapter.js +34 -0
- package/dist/features/registry/adapters/inbound/AuthoringBindingEditorAdapter.js.map +1 -0
- package/dist/features/registry/adapters/inbound/AuthoringPropertyInspectorAdapter.d.ts +5 -0
- package/dist/features/registry/adapters/inbound/AuthoringPropertyInspectorAdapter.d.ts.map +1 -0
- package/dist/features/registry/adapters/inbound/AuthoringPropertyInspectorAdapter.js +30 -0
- package/dist/features/registry/adapters/inbound/AuthoringPropertyInspectorAdapter.js.map +1 -0
- package/dist/features/registry/adapters/inbound/AuthoringSelectionAdapter.d.ts +5 -0
- package/dist/features/registry/adapters/inbound/AuthoringSelectionAdapter.d.ts.map +1 -0
- package/dist/features/registry/adapters/inbound/AuthoringSelectionAdapter.js +22 -0
- package/dist/features/registry/adapters/inbound/AuthoringSelectionAdapter.js.map +1 -0
- package/dist/features/registry/adapters/inbound/ThemeEditorAdapter.d.ts +5 -0
- package/dist/features/registry/adapters/inbound/ThemeEditorAdapter.d.ts.map +1 -0
- package/dist/features/registry/adapters/inbound/ThemeEditorAdapter.js +37 -0
- package/dist/features/registry/adapters/inbound/ThemeEditorAdapter.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/types/authoring-adapters.d.ts +79 -0
- package/dist/types/authoring-adapters.d.ts.map +1 -0
- package/dist/types/authoring-adapters.js +2 -0
- package/dist/types/authoring-adapters.js.map +1 -0
- package/package.json +8 -1
- package/src/authoring.ts +14 -0
- package/src/features/registry/adapters/inbound/AuthoringBindingEditorAdapter.tsx +53 -0
- package/src/features/registry/adapters/inbound/AuthoringPropertyInspectorAdapter.tsx +50 -0
- package/src/features/registry/adapters/inbound/AuthoringSelectionAdapter.tsx +42 -0
- package/src/features/registry/adapters/inbound/ThemeEditorAdapter.tsx +61 -0
- package/src/features/registry/adapters/inbound/authoringAdapters.test.tsx +242 -0
- package/src/features/registry/registry.test.ts +11 -0
- package/src/index.ts +16 -0
- package/src/types/authoring-adapters.ts +112 -0
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
# @ankhorage/zora
|
|
5
5
|
|
|
6
|
-
         
|
|
7
7
|
|
|
8
8
|
Opinionated React Native and React Native Web UI kit built on @ankhorage/surface.
|
|
9
9
|
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { AuthoringBindingEditorAdapter } from './features/registry/adapters/inbound/AuthoringBindingEditorAdapter';
|
|
2
|
+
export { AuthoringPropertyInspectorAdapter } from './features/registry/adapters/inbound/AuthoringPropertyInspectorAdapter';
|
|
3
|
+
export { AuthoringSelectionAdapter } from './features/registry/adapters/inbound/AuthoringSelectionAdapter';
|
|
4
|
+
export { ThemeEditorAdapter } from './features/registry/adapters/inbound/ThemeEditorAdapter';
|
|
5
|
+
export type { AuthoringBindingControlState, AuthoringBindingEditorAdapterProps, AuthoringPropertyControlState, AuthoringPropertyInspectorAdapterProps, AuthoringSelectionAdapterProps, AuthoringSelectionItemState, ThemeEditorAdapterProps, ThemeRecipeFieldControlState, } from './types/authoring-adapters';
|
|
6
|
+
//# sourceMappingURL=authoring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authoring.d.ts","sourceRoot":"","sources":["../src/authoring.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,MAAM,oEAAoE,CAAC;AACnH,OAAO,EAAE,iCAAiC,EAAE,MAAM,wEAAwE,CAAC;AAC3H,OAAO,EAAE,yBAAyB,EAAE,MAAM,gEAAgE,CAAC;AAC3G,OAAO,EAAE,kBAAkB,EAAE,MAAM,yDAAyD,CAAC;AAC7F,YAAY,EACV,4BAA4B,EAC5B,kCAAkC,EAClC,6BAA6B,EAC7B,sCAAsC,EACtC,8BAA8B,EAC9B,2BAA2B,EAC3B,uBAAuB,EACvB,4BAA4B,GAC7B,MAAM,4BAA4B,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { AuthoringBindingEditorAdapter } from './features/registry/adapters/inbound/AuthoringBindingEditorAdapter';
|
|
2
|
+
export { AuthoringPropertyInspectorAdapter } from './features/registry/adapters/inbound/AuthoringPropertyInspectorAdapter';
|
|
3
|
+
export { AuthoringSelectionAdapter } from './features/registry/adapters/inbound/AuthoringSelectionAdapter';
|
|
4
|
+
export { ThemeEditorAdapter } from './features/registry/adapters/inbound/ThemeEditorAdapter';
|
|
5
|
+
//# sourceMappingURL=authoring.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authoring.js","sourceRoot":"","sources":["../src/authoring.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,MAAM,oEAAoE,CAAC;AACnH,OAAO,EAAE,iCAAiC,EAAE,MAAM,wEAAwE,CAAC;AAC3H,OAAO,EAAE,yBAAyB,EAAE,MAAM,gEAAgE,CAAC;AAC3G,OAAO,EAAE,kBAAkB,EAAE,MAAM,yDAAyD,CAAC","sourcesContent":["export { AuthoringBindingEditorAdapter } from './features/registry/adapters/inbound/AuthoringBindingEditorAdapter';\nexport { AuthoringPropertyInspectorAdapter } from './features/registry/adapters/inbound/AuthoringPropertyInspectorAdapter';\nexport { AuthoringSelectionAdapter } from './features/registry/adapters/inbound/AuthoringSelectionAdapter';\nexport { ThemeEditorAdapter } from './features/registry/adapters/inbound/ThemeEditorAdapter';\nexport type {\n AuthoringBindingControlState,\n AuthoringBindingEditorAdapterProps,\n AuthoringPropertyControlState,\n AuthoringPropertyInspectorAdapterProps,\n AuthoringSelectionAdapterProps,\n AuthoringSelectionItemState,\n ThemeEditorAdapterProps,\n ThemeRecipeFieldControlState,\n} from './types/authoring-adapters';\n"]}
|
|
@@ -7,5 +7,5 @@ export declare function resolveButtonThemeRecipe(input: {
|
|
|
7
7
|
readonly variant?: ZoraButtonVariant;
|
|
8
8
|
readonly size?: ZoraControlSize;
|
|
9
9
|
readonly themeFields: Readonly<Record<string, ThemeRecipeOverrideValue>>;
|
|
10
|
-
}): Pick<import("@ankhorage/surface").ButtonProps, "
|
|
10
|
+
}): Pick<import("@ankhorage/surface").ButtonProps, "color" | "size" | "variant">;
|
|
11
11
|
//# sourceMappingURL=resolveButtonThemeRecipe.d.ts.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { AuthoringBindingEditorAdapterProps } from '../../../../types/authoring-adapters';
|
|
3
|
+
/*** Presents canonical bindable properties while leaving binding representation and mutation ownership external. */
|
|
4
|
+
export declare function AuthoringBindingEditorAdapter<TNode, TBinding>({ node, component, getBinding, onBindingChange, renderBinding, isBindingDisabled, isBindingRequired, disabled, }: AuthoringBindingEditorAdapterProps<TNode, TBinding>): React.JSX.Element | null;
|
|
5
|
+
//# sourceMappingURL=AuthoringBindingEditorAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthoringBindingEditorAdapter.d.ts","sourceRoot":"","sources":["../../../../../src/features/registry/adapters/inbound/AuthoringBindingEditorAdapter.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,sCAAsC,CAAC;AAI/F,oHAAoH;AACpH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,QAAQ,EAAE,EAC7D,IAAI,EACJ,SAAS,EACT,UAAU,EACV,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,QAAgB,GACjB,EAAE,kCAAkC,CAAC,KAAK,EAAE,QAAQ,CAAC,4BAoCrD"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Field } from '../../../form/public';
|
|
3
|
+
import { View } from '../../../layout/public';
|
|
4
|
+
/*** Presents canonical bindable properties while leaving binding representation and mutation ownership external. */
|
|
5
|
+
export function AuthoringBindingEditorAdapter({ node, component, getBinding, onBindingChange, renderBinding, isBindingDisabled, isBindingRequired, disabled = false, }) {
|
|
6
|
+
if (node === null || component === null)
|
|
7
|
+
return null;
|
|
8
|
+
const bindings = component.bindings?.props;
|
|
9
|
+
if (bindings === undefined)
|
|
10
|
+
return null;
|
|
11
|
+
return (<View gap="m">
|
|
12
|
+
{Object.entries(bindings).map(([name, meta]) => {
|
|
13
|
+
const controlDisabled = disabled || isBindingDisabled?.(node, name) === true;
|
|
14
|
+
const required = isBindingRequired?.(node, name) === true;
|
|
15
|
+
return (<Field key={name} description={meta.description} disabled={controlDisabled} label={meta.label ?? name} required={required}>
|
|
16
|
+
{renderBinding({
|
|
17
|
+
node,
|
|
18
|
+
component,
|
|
19
|
+
name,
|
|
20
|
+
label: meta.label ?? name,
|
|
21
|
+
description: meta.description,
|
|
22
|
+
binding: getBinding(node, name),
|
|
23
|
+
disabled: controlDisabled,
|
|
24
|
+
required,
|
|
25
|
+
onChange: (binding) => {
|
|
26
|
+
if (!controlDisabled)
|
|
27
|
+
onBindingChange?.(node, name, binding);
|
|
28
|
+
},
|
|
29
|
+
})}
|
|
30
|
+
</Field>);
|
|
31
|
+
})}
|
|
32
|
+
</View>);
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=AuthoringBindingEditorAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthoringBindingEditorAdapter.js","sourceRoot":"","sources":["../../../../../src/features/registry/adapters/inbound/AuthoringBindingEditorAdapter.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAE9C,oHAAoH;AACpH,MAAM,UAAU,6BAA6B,CAAkB,EAC7D,IAAI,EACJ,SAAS,EACT,UAAU,EACV,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,QAAQ,GAAG,KAAK,GACoC;IACpD,IAAI,IAAI,KAAK,IAAI,IAAI,SAAS,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACrD,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC;IAC3C,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAExC,OAAO,CACL,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CACX;MAAA,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;YAC7C,MAAM,eAAe,GAAG,QAAQ,IAAI,iBAAiB,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,IAAI,CAAC;YAC7E,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,IAAI,CAAC;YAC1D,OAAO,CACL,CAAC,KAAK,CACJ,GAAG,CAAC,CAAC,IAAI,CAAC,CACV,WAAW,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAC9B,QAAQ,CAAC,CAAC,eAAe,CAAC,CAC1B,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,CAC1B,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAEnB;YAAA,CAAC,aAAa,CAAC;oBACb,IAAI;oBACJ,SAAS;oBACT,IAAI;oBACJ,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI;oBACzB,WAAW,EAAE,IAAI,CAAC,WAAW;oBAC7B,OAAO,EAAE,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC;oBAC/B,QAAQ,EAAE,eAAe;oBACzB,QAAQ;oBACR,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE;wBACpB,IAAI,CAAC,eAAe;4BAAE,eAAe,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;oBAC/D,CAAC;iBACF,CAAC,CACJ;UAAA,EAAE,KAAK,CAAC,CACT,CAAC;QACJ,CAAC,CAAC,CACJ;IAAA,EAAE,IAAI,CAAC,CACR,CAAC;AACJ,CAAC","sourcesContent":["import React from 'react';\n\nimport type { AuthoringBindingEditorAdapterProps } from '../../../../types/authoring-adapters';\nimport { Field } from '../../../form/public';\nimport { View } from '../../../layout/public';\n\n/*** Presents canonical bindable properties while leaving binding representation and mutation ownership external. */\nexport function AuthoringBindingEditorAdapter<TNode, TBinding>({\n node,\n component,\n getBinding,\n onBindingChange,\n renderBinding,\n isBindingDisabled,\n isBindingRequired,\n disabled = false,\n}: AuthoringBindingEditorAdapterProps<TNode, TBinding>) {\n if (node === null || component === null) return null;\n const bindings = component.bindings?.props;\n if (bindings === undefined) return null;\n\n return (\n <View gap=\"m\">\n {Object.entries(bindings).map(([name, meta]) => {\n const controlDisabled = disabled || isBindingDisabled?.(node, name) === true;\n const required = isBindingRequired?.(node, name) === true;\n return (\n <Field\n key={name}\n description={meta.description}\n disabled={controlDisabled}\n label={meta.label ?? name}\n required={required}\n >\n {renderBinding({\n node,\n component,\n name,\n label: meta.label ?? name,\n description: meta.description,\n binding: getBinding(node, name),\n disabled: controlDisabled,\n required,\n onChange: (binding) => {\n if (!controlDisabled) onBindingChange?.(node, name, binding);\n },\n })}\n </Field>\n );\n })}\n </View>\n );\n}\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { AuthoringPropertyInspectorAdapterProps } from '../../../../types/authoring-adapters';
|
|
3
|
+
/*** Presents canonical component properties while keeping node storage and mutations with the consumer. */
|
|
4
|
+
export declare function AuthoringPropertyInspectorAdapter<TNode>({ node, component, getPropertyValue, onPropertyChange, renderProperty, isPropertyDisabled, isPropertyRequired, disabled, }: AuthoringPropertyInspectorAdapterProps<TNode>): React.JSX.Element | null;
|
|
5
|
+
//# sourceMappingURL=AuthoringPropertyInspectorAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthoringPropertyInspectorAdapter.d.ts","sourceRoot":"","sources":["../../../../../src/features/registry/adapters/inbound/AuthoringPropertyInspectorAdapter.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,sCAAsC,EAAE,MAAM,sCAAsC,CAAC;AAInG,2GAA2G;AAC3G,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,EACvD,IAAI,EACJ,SAAS,EACT,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,kBAAkB,EAClB,QAAgB,GACjB,EAAE,sCAAsC,CAAC,KAAK,CAAC,4BAiC/C"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Field } from '../../../form/public';
|
|
3
|
+
import { View } from '../../../layout/public';
|
|
4
|
+
/*** Presents canonical component properties while keeping node storage and mutations with the consumer. */
|
|
5
|
+
export function AuthoringPropertyInspectorAdapter({ node, component, getPropertyValue, onPropertyChange, renderProperty, isPropertyDisabled, isPropertyRequired, disabled = false, }) {
|
|
6
|
+
if (node === null || component === null)
|
|
7
|
+
return null;
|
|
8
|
+
return (<View gap="m">
|
|
9
|
+
{Object.entries(component.props).map(([name, schema]) => {
|
|
10
|
+
const controlDisabled = disabled || isPropertyDisabled?.(node, name, schema) === true;
|
|
11
|
+
const required = isPropertyRequired?.(node, name, schema) === true;
|
|
12
|
+
return (<Field key={name} description={schema.label === undefined ? undefined : schema.category} disabled={controlDisabled} label={schema.label ?? name} required={required}>
|
|
13
|
+
{renderProperty({
|
|
14
|
+
node,
|
|
15
|
+
component,
|
|
16
|
+
name,
|
|
17
|
+
schema,
|
|
18
|
+
value: getPropertyValue(node, name),
|
|
19
|
+
disabled: controlDisabled,
|
|
20
|
+
required,
|
|
21
|
+
onChange: (value) => {
|
|
22
|
+
if (!controlDisabled)
|
|
23
|
+
onPropertyChange?.(node, name, value);
|
|
24
|
+
},
|
|
25
|
+
})}
|
|
26
|
+
</Field>);
|
|
27
|
+
})}
|
|
28
|
+
</View>);
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=AuthoringPropertyInspectorAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthoringPropertyInspectorAdapter.js","sourceRoot":"","sources":["../../../../../src/features/registry/adapters/inbound/AuthoringPropertyInspectorAdapter.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAE9C,2GAA2G;AAC3G,MAAM,UAAU,iCAAiC,CAAQ,EACvD,IAAI,EACJ,SAAS,EACT,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,kBAAkB,EAClB,QAAQ,GAAG,KAAK,GAC8B;IAC9C,IAAI,IAAI,KAAK,IAAI,IAAI,SAAS,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAErD,OAAO,CACL,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CACX;MAAA,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE;YACtD,MAAM,eAAe,GAAG,QAAQ,IAAI,kBAAkB,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;YACtF,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;YACnE,OAAO,CACL,CAAC,KAAK,CACJ,GAAG,CAAC,CAAC,IAAI,CAAC,CACV,WAAW,CAAC,CAAC,MAAM,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CACtE,QAAQ,CAAC,CAAC,eAAe,CAAC,CAC1B,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,CAC5B,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAEnB;YAAA,CAAC,cAAc,CAAC;oBACd,IAAI;oBACJ,SAAS;oBACT,IAAI;oBACJ,MAAM;oBACN,KAAK,EAAE,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC;oBACnC,QAAQ,EAAE,eAAe;oBACzB,QAAQ;oBACR,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;wBAClB,IAAI,CAAC,eAAe;4BAAE,gBAAgB,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;oBAC9D,CAAC;iBACF,CAAC,CACJ;UAAA,EAAE,KAAK,CAAC,CACT,CAAC;QACJ,CAAC,CAAC,CACJ;IAAA,EAAE,IAAI,CAAC,CACR,CAAC;AACJ,CAAC","sourcesContent":["import React from 'react';\n\nimport type { AuthoringPropertyInspectorAdapterProps } from '../../../../types/authoring-adapters';\nimport { Field } from '../../../form/public';\nimport { View } from '../../../layout/public';\n\n/*** Presents canonical component properties while keeping node storage and mutations with the consumer. */\nexport function AuthoringPropertyInspectorAdapter<TNode>({\n node,\n component,\n getPropertyValue,\n onPropertyChange,\n renderProperty,\n isPropertyDisabled,\n isPropertyRequired,\n disabled = false,\n}: AuthoringPropertyInspectorAdapterProps<TNode>) {\n if (node === null || component === null) return null;\n\n return (\n <View gap=\"m\">\n {Object.entries(component.props).map(([name, schema]) => {\n const controlDisabled = disabled || isPropertyDisabled?.(node, name, schema) === true;\n const required = isPropertyRequired?.(node, name, schema) === true;\n return (\n <Field\n key={name}\n description={schema.label === undefined ? undefined : schema.category}\n disabled={controlDisabled}\n label={schema.label ?? name}\n required={required}\n >\n {renderProperty({\n node,\n component,\n name,\n schema,\n value: getPropertyValue(node, name),\n disabled: controlDisabled,\n required,\n onChange: (value) => {\n if (!controlDisabled) onPropertyChange?.(node, name, value);\n },\n })}\n </Field>\n );\n })}\n </View>\n );\n}\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { AuthoringSelectionAdapterProps } from '../../../../types/authoring-adapters';
|
|
3
|
+
/*** Connects consumer-owned items to ZORA's controlled single-selection behavior. */
|
|
4
|
+
export declare function AuthoringSelectionAdapter<TItem>({ items, selectedItemId, getItemId, onSelectionChange, renderItem, disabled, }: AuthoringSelectionAdapterProps<TItem>): React.JSX.Element;
|
|
5
|
+
//# sourceMappingURL=AuthoringSelectionAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthoringSelectionAdapter.d.ts","sourceRoot":"","sources":["../../../../../src/features/registry/adapters/inbound/AuthoringSelectionAdapter.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,sCAAsC,CAAC;AAG3F,qFAAqF;AACrF,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,EAC/C,KAAK,EACL,cAAc,EACd,SAAS,EACT,iBAAiB,EACjB,UAAU,EACV,QAAQ,GACT,EAAE,8BAA8B,CAAC,KAAK,CAAC,qBA4BvC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SelectableItem, SelectionProvider } from '../../../selection/public';
|
|
3
|
+
/*** Connects consumer-owned items to ZORA's controlled single-selection behavior. */
|
|
4
|
+
export function AuthoringSelectionAdapter({ items, selectedItemId, getItemId, onSelectionChange, renderItem, disabled, }) {
|
|
5
|
+
return (<SelectionProvider disabled={disabled} mode="single" selectedIds={selectedItemId === undefined ? [] : [selectedItemId]} onSelectionChange={(ids) => {
|
|
6
|
+
const [selectedId] = ids;
|
|
7
|
+
onSelectionChange?.(items.find((item) => getItemId(item) === selectedId) ?? null);
|
|
8
|
+
}}>
|
|
9
|
+
{items.map((item) => {
|
|
10
|
+
const id = getItemId(item);
|
|
11
|
+
return (<SelectableItem key={id} id={id} trigger="press">
|
|
12
|
+
{(state) => renderItem({
|
|
13
|
+
item,
|
|
14
|
+
selected: state.selected,
|
|
15
|
+
disabled: state.disabled,
|
|
16
|
+
select: state.select,
|
|
17
|
+
})}
|
|
18
|
+
</SelectableItem>);
|
|
19
|
+
})}
|
|
20
|
+
</SelectionProvider>);
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=AuthoringSelectionAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthoringSelectionAdapter.js","sourceRoot":"","sources":["../../../../../src/features/registry/adapters/inbound/AuthoringSelectionAdapter.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9E,qFAAqF;AACrF,MAAM,UAAU,yBAAyB,CAAQ,EAC/C,KAAK,EACL,cAAc,EACd,SAAS,EACT,iBAAiB,EACjB,UAAU,EACV,QAAQ,GAC8B;IACtC,OAAO,CACL,CAAC,iBAAiB,CAChB,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,IAAI,CAAC,QAAQ,CACb,WAAW,CAAC,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAClE,iBAAiB,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE;YACzB,MAAM,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC;YACzB,iBAAiB,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,IAAI,IAAI,CAAC,CAAC;QACpF,CAAC,CAAC,CAEF;MAAA,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YAClB,MAAM,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAC3B,OAAO,CACL,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAC9C;YAAA,CAAC,CAAC,KAAK,EAAE,EAAE,CACT,UAAU,CAAC;oBACT,IAAI;oBACJ,QAAQ,EAAE,KAAK,CAAC,QAAQ;oBACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;oBACxB,MAAM,EAAE,KAAK,CAAC,MAAM;iBACrB,CACH,CACF;UAAA,EAAE,cAAc,CAAC,CAClB,CAAC;QACJ,CAAC,CAAC,CACJ;IAAA,EAAE,iBAAiB,CAAC,CACrB,CAAC;AACJ,CAAC","sourcesContent":["import React from 'react';\n\nimport type { AuthoringSelectionAdapterProps } from '../../../../types/authoring-adapters';\nimport { SelectableItem, SelectionProvider } from '../../../selection/public';\n\n/*** Connects consumer-owned items to ZORA's controlled single-selection behavior. */\nexport function AuthoringSelectionAdapter<TItem>({\n items,\n selectedItemId,\n getItemId,\n onSelectionChange,\n renderItem,\n disabled,\n}: AuthoringSelectionAdapterProps<TItem>) {\n return (\n <SelectionProvider\n disabled={disabled}\n mode=\"single\"\n selectedIds={selectedItemId === undefined ? [] : [selectedItemId]}\n onSelectionChange={(ids) => {\n const [selectedId] = ids;\n onSelectionChange?.(items.find((item) => getItemId(item) === selectedId) ?? null);\n }}\n >\n {items.map((item) => {\n const id = getItemId(item);\n return (\n <SelectableItem key={id} id={id} trigger=\"press\">\n {(state) =>\n renderItem({\n item,\n selected: state.selected,\n disabled: state.disabled,\n select: state.select,\n })\n }\n </SelectableItem>\n );\n })}\n </SelectionProvider>\n );\n}\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ThemeEditorAdapterProps } from '../../../../types/authoring-adapters';
|
|
3
|
+
/*** Presents ZORA recipe fields without taking ownership of a consumer's theme document. */
|
|
4
|
+
export declare function ThemeEditorAdapter<TTheme>({ theme, recipes, getRecipeFieldValue, onRecipeFieldChange, renderField, isFieldDisabled, isFieldRequired, disabled, }: ThemeEditorAdapterProps<TTheme>): React.JSX.Element | null;
|
|
5
|
+
//# sourceMappingURL=ThemeEditorAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThemeEditorAdapter.d.ts","sourceRoot":"","sources":["../../../../../src/features/registry/adapters/inbound/ThemeEditorAdapter.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAMpF,4FAA4F;AAC5F,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,EACzC,KAAK,EACL,OAAgC,EAChC,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,eAAe,EACf,eAAe,EACf,QAAgB,GACjB,EAAE,uBAAuB,CAAC,MAAM,CAAC,4BA0CjC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Card } from '../../../card/public';
|
|
3
|
+
import { Field } from '../../../form/public';
|
|
4
|
+
import { View } from '../../../layout/public';
|
|
5
|
+
import { ZORA_THEME_RECIPE_META } from '../../themeRecipeMeta';
|
|
6
|
+
/*** Presents ZORA recipe fields without taking ownership of a consumer's theme document. */
|
|
7
|
+
export function ThemeEditorAdapter({ theme, recipes = ZORA_THEME_RECIPE_META, getRecipeFieldValue, onRecipeFieldChange, renderField, isFieldDisabled, isFieldRequired, disabled = false, }) {
|
|
8
|
+
if (theme === null)
|
|
9
|
+
return null;
|
|
10
|
+
return (<View gap="m">
|
|
11
|
+
{Object.entries(recipes).map(([recipeName, recipe]) => (<Card key={recipeName} description={recipe.description} title={recipe.name}>
|
|
12
|
+
<View gap="m">
|
|
13
|
+
{Object.entries(recipe.fields).map(([fieldName, field]) => {
|
|
14
|
+
const controlDisabled = disabled || isFieldDisabled?.(theme, recipeName, fieldName) === true;
|
|
15
|
+
const required = isFieldRequired?.(theme, recipeName, fieldName) === true;
|
|
16
|
+
return (<Field key={fieldName} description={field.description} disabled={controlDisabled} label={field.label} required={required}>
|
|
17
|
+
{renderField({
|
|
18
|
+
theme,
|
|
19
|
+
recipeName,
|
|
20
|
+
fieldName,
|
|
21
|
+
field,
|
|
22
|
+
value: getRecipeFieldValue(theme, recipeName, fieldName),
|
|
23
|
+
disabled: controlDisabled,
|
|
24
|
+
required,
|
|
25
|
+
onChange: (value) => {
|
|
26
|
+
if (!controlDisabled) {
|
|
27
|
+
onRecipeFieldChange?.(theme, recipeName, fieldName, value);
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
})}
|
|
31
|
+
</Field>);
|
|
32
|
+
})}
|
|
33
|
+
</View>
|
|
34
|
+
</Card>))}
|
|
35
|
+
</View>);
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=ThemeEditorAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThemeEditorAdapter.js","sourceRoot":"","sources":["../../../../../src/features/registry/adapters/inbound/ThemeEditorAdapter.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,4FAA4F;AAC5F,MAAM,UAAU,kBAAkB,CAAS,EACzC,KAAK,EACL,OAAO,GAAG,sBAAsB,EAChC,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,eAAe,EACf,eAAe,EACf,QAAQ,GAAG,KAAK,GACgB;IAChC,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAEhC,OAAO,CACL,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CACX;MAAA,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CACrD,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CACzE;UAAA,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CACX;YAAA,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,EAAE;gBACxD,MAAM,eAAe,GACnB,QAAQ,IAAI,eAAe,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,SAAS,CAAC,KAAK,IAAI,CAAC;gBACvE,MAAM,QAAQ,GAAG,eAAe,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,SAAS,CAAC,KAAK,IAAI,CAAC;gBAC1E,OAAO,CACL,CAAC,KAAK,CACJ,GAAG,CAAC,CAAC,SAAS,CAAC,CACf,WAAW,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAC/B,QAAQ,CAAC,CAAC,eAAe,CAAC,CAC1B,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CACnB,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAEnB;kBAAA,CAAC,WAAW,CAAC;wBACX,KAAK;wBACL,UAAU;wBACV,SAAS;wBACT,KAAK;wBACL,KAAK,EAAE,mBAAmB,CAAC,KAAK,EAAE,UAAU,EAAE,SAAS,CAAC;wBACxD,QAAQ,EAAE,eAAe;wBACzB,QAAQ;wBACR,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;4BAClB,IAAI,CAAC,eAAe,EAAE,CAAC;gCACrB,mBAAmB,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;4BAC7D,CAAC;wBACH,CAAC;qBACF,CAAC,CACJ;gBAAA,EAAE,KAAK,CAAC,CACT,CAAC;YACJ,CAAC,CAAC,CACJ;UAAA,EAAE,IAAI,CACR;QAAA,EAAE,IAAI,CAAC,CACR,CAAC,CACJ;IAAA,EAAE,IAAI,CAAC,CACR,CAAC;AACJ,CAAC","sourcesContent":["import React from 'react';\n\nimport type { ThemeEditorAdapterProps } from '../../../../types/authoring-adapters';\nimport { Card } from '../../../card/public';\nimport { Field } from '../../../form/public';\nimport { View } from '../../../layout/public';\nimport { ZORA_THEME_RECIPE_META } from '../../themeRecipeMeta';\n\n/*** Presents ZORA recipe fields without taking ownership of a consumer's theme document. */\nexport function ThemeEditorAdapter<TTheme>({\n theme,\n recipes = ZORA_THEME_RECIPE_META,\n getRecipeFieldValue,\n onRecipeFieldChange,\n renderField,\n isFieldDisabled,\n isFieldRequired,\n disabled = false,\n}: ThemeEditorAdapterProps<TTheme>) {\n if (theme === null) return null;\n\n return (\n <View gap=\"m\">\n {Object.entries(recipes).map(([recipeName, recipe]) => (\n <Card key={recipeName} description={recipe.description} title={recipe.name}>\n <View gap=\"m\">\n {Object.entries(recipe.fields).map(([fieldName, field]) => {\n const controlDisabled =\n disabled || isFieldDisabled?.(theme, recipeName, fieldName) === true;\n const required = isFieldRequired?.(theme, recipeName, fieldName) === true;\n return (\n <Field\n key={fieldName}\n description={field.description}\n disabled={controlDisabled}\n label={field.label}\n required={required}\n >\n {renderField({\n theme,\n recipeName,\n fieldName,\n field,\n value: getRecipeFieldValue(theme, recipeName, fieldName),\n disabled: controlDisabled,\n required,\n onChange: (value) => {\n if (!controlDisabled) {\n onRecipeFieldChange?.(theme, recipeName, fieldName, value);\n }\n },\n })}\n </Field>\n );\n })}\n </View>\n </Card>\n ))}\n </View>\n );\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export type { AuthoringBindingControlState, AuthoringBindingEditorAdapterProps, AuthoringPropertyControlState, AuthoringPropertyInspectorAdapterProps, AuthoringSelectionAdapterProps, AuthoringSelectionItemState, ThemeEditorAdapterProps, ThemeRecipeFieldControlState, } from './authoring';
|
|
2
|
+
export { AuthoringBindingEditorAdapter, AuthoringPropertyInspectorAdapter, AuthoringSelectionAdapter, ThemeEditorAdapter, } from './authoring';
|
|
1
3
|
export type { ReaderColorScheme, ReaderDocumentFormat, ReaderErrorCode, ReaderErrorEvent, ReaderExternalLinkEvent, ReaderLineHeight, ReaderLocationChangeEvent, ReaderNavigationTrigger, ReaderProps, ReaderResolvedSource, ReaderStatus, } from './features/reader/public';
|
|
2
4
|
export { Reader, resolveReaderProgress } from './features/reader/public';
|
|
3
5
|
export { ZORA_COMPONENT_REGISTRY } from './features/registry/public';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EAChB,uBAAuB,EACvB,gBAAgB,EAChB,yBAAyB,EACzB,uBAAuB,EACvB,WAAW,EACX,oBAAoB,EACpB,YAAY,GACb,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,cAAc,cAAc,CAAC;AAC7B,YAAY,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,4BAA4B,EAC5B,kCAAkC,EAClC,6BAA6B,EAC7B,sCAAsC,EACtC,8BAA8B,EAC9B,2BAA2B,EAC3B,uBAAuB,EACvB,4BAA4B,GAC7B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,6BAA6B,EAC7B,iCAAiC,EACjC,yBAAyB,EACzB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EAChB,uBAAuB,EACvB,gBAAgB,EAChB,yBAAyB,EACzB,uBAAuB,EACvB,WAAW,EACX,oBAAoB,EACpB,YAAY,GACb,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,cAAc,cAAc,CAAC;AAC7B,YAAY,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { AuthoringBindingEditorAdapter, AuthoringPropertyInspectorAdapter, AuthoringSelectionAdapter, ThemeEditorAdapter, } from './authoring';
|
|
1
2
|
export { Reader, resolveReaderProgress } from './features/reader/public';
|
|
2
3
|
export { ZORA_COMPONENT_REGISTRY } from './features/registry/public';
|
|
3
4
|
export * from './readerFree';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAUA,OAAO,EACL,6BAA6B,EAC7B,iCAAiC,EACjC,yBAAyB,EACzB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAcrB,OAAO,EAAE,MAAM,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,cAAc,cAAc,CAAC","sourcesContent":["export type {\n AuthoringBindingControlState,\n AuthoringBindingEditorAdapterProps,\n AuthoringPropertyControlState,\n AuthoringPropertyInspectorAdapterProps,\n AuthoringSelectionAdapterProps,\n AuthoringSelectionItemState,\n ThemeEditorAdapterProps,\n ThemeRecipeFieldControlState,\n} from './authoring';\nexport {\n AuthoringBindingEditorAdapter,\n AuthoringPropertyInspectorAdapter,\n AuthoringSelectionAdapter,\n ThemeEditorAdapter,\n} from './authoring';\nexport type {\n ReaderColorScheme,\n ReaderDocumentFormat,\n ReaderErrorCode,\n ReaderErrorEvent,\n ReaderExternalLinkEvent,\n ReaderLineHeight,\n ReaderLocationChangeEvent,\n ReaderNavigationTrigger,\n ReaderProps,\n ReaderResolvedSource,\n ReaderStatus,\n} from './features/reader/public';\nexport { Reader, resolveReaderProgress } from './features/reader/public';\nexport { ZORA_COMPONENT_REGISTRY } from './features/registry/public';\nexport * from './readerFree';\nexport type { ZoraComponentRegistry } from './types/registry';\n"]}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import type { ZoraComponentMeta, ZoraComponentPropSchema, ZoraComponentPropValue } from './authoring';
|
|
3
|
+
import type { ZoraThemeRecipeFieldMeta, ZoraThemeRecipeMetaRegistry } from './theme-recipe';
|
|
4
|
+
export interface AuthoringSelectionItemState<TItem> {
|
|
5
|
+
readonly item: TItem;
|
|
6
|
+
readonly selected: boolean;
|
|
7
|
+
readonly disabled: boolean;
|
|
8
|
+
readonly select: () => void;
|
|
9
|
+
}
|
|
10
|
+
export interface AuthoringSelectionAdapterProps<TItem> {
|
|
11
|
+
readonly items: readonly TItem[];
|
|
12
|
+
readonly selectedItemId?: string;
|
|
13
|
+
readonly getItemId: (item: TItem) => string;
|
|
14
|
+
readonly onSelectionChange?: (item: TItem | null) => void;
|
|
15
|
+
readonly renderItem: (state: AuthoringSelectionItemState<TItem>) => React.ReactNode;
|
|
16
|
+
readonly disabled?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface AuthoringPropertyControlState<TNode> {
|
|
19
|
+
readonly node: TNode;
|
|
20
|
+
readonly component: ZoraComponentMeta;
|
|
21
|
+
readonly name: string;
|
|
22
|
+
readonly schema: ZoraComponentPropSchema;
|
|
23
|
+
readonly value: ZoraComponentPropValue | undefined;
|
|
24
|
+
readonly disabled: boolean;
|
|
25
|
+
readonly required: boolean;
|
|
26
|
+
readonly onChange: (value: ZoraComponentPropValue | undefined) => void;
|
|
27
|
+
}
|
|
28
|
+
export interface AuthoringPropertyInspectorAdapterProps<TNode> {
|
|
29
|
+
readonly node: TNode | null;
|
|
30
|
+
readonly component: ZoraComponentMeta | null;
|
|
31
|
+
readonly getPropertyValue: (node: TNode, name: string) => ZoraComponentPropValue | undefined;
|
|
32
|
+
readonly onPropertyChange?: (node: TNode, name: string, value: ZoraComponentPropValue | undefined) => void;
|
|
33
|
+
readonly renderProperty: (state: AuthoringPropertyControlState<TNode>) => React.ReactNode;
|
|
34
|
+
readonly isPropertyDisabled?: (node: TNode, name: string, schema: ZoraComponentPropSchema) => boolean;
|
|
35
|
+
readonly isPropertyRequired?: (node: TNode, name: string, schema: ZoraComponentPropSchema) => boolean;
|
|
36
|
+
readonly disabled?: boolean;
|
|
37
|
+
}
|
|
38
|
+
export interface AuthoringBindingControlState<TNode, TBinding> {
|
|
39
|
+
readonly node: TNode;
|
|
40
|
+
readonly component: ZoraComponentMeta;
|
|
41
|
+
readonly name: string;
|
|
42
|
+
readonly label: string;
|
|
43
|
+
readonly description?: string;
|
|
44
|
+
readonly binding: TBinding | undefined;
|
|
45
|
+
readonly disabled: boolean;
|
|
46
|
+
readonly required: boolean;
|
|
47
|
+
readonly onChange: (binding: TBinding | undefined) => void;
|
|
48
|
+
}
|
|
49
|
+
export interface AuthoringBindingEditorAdapterProps<TNode, TBinding> {
|
|
50
|
+
readonly node: TNode | null;
|
|
51
|
+
readonly component: ZoraComponentMeta | null;
|
|
52
|
+
readonly getBinding: (node: TNode, name: string) => TBinding | undefined;
|
|
53
|
+
readonly onBindingChange?: (node: TNode, name: string, binding: TBinding | undefined) => void;
|
|
54
|
+
readonly renderBinding: (state: AuthoringBindingControlState<TNode, TBinding>) => React.ReactNode;
|
|
55
|
+
readonly isBindingDisabled?: (node: TNode, name: string) => boolean;
|
|
56
|
+
readonly isBindingRequired?: (node: TNode, name: string) => boolean;
|
|
57
|
+
readonly disabled?: boolean;
|
|
58
|
+
}
|
|
59
|
+
export interface ThemeRecipeFieldControlState<TTheme> {
|
|
60
|
+
readonly theme: TTheme;
|
|
61
|
+
readonly recipeName: string;
|
|
62
|
+
readonly fieldName: string;
|
|
63
|
+
readonly field: ZoraThemeRecipeFieldMeta;
|
|
64
|
+
readonly value: string | boolean | undefined;
|
|
65
|
+
readonly disabled: boolean;
|
|
66
|
+
readonly required: boolean;
|
|
67
|
+
readonly onChange: (value: string | boolean | undefined) => void;
|
|
68
|
+
}
|
|
69
|
+
export interface ThemeEditorAdapterProps<TTheme> {
|
|
70
|
+
readonly theme: TTheme | null;
|
|
71
|
+
readonly recipes?: ZoraThemeRecipeMetaRegistry;
|
|
72
|
+
readonly getRecipeFieldValue: (theme: TTheme, recipeName: string, fieldName: string) => string | boolean | undefined;
|
|
73
|
+
readonly onRecipeFieldChange?: (theme: TTheme, recipeName: string, fieldName: string, value: string | boolean | undefined) => void;
|
|
74
|
+
readonly renderField: (state: ThemeRecipeFieldControlState<TTheme>) => React.ReactNode;
|
|
75
|
+
readonly isFieldDisabled?: (theme: TTheme, recipeName: string, fieldName: string) => boolean;
|
|
76
|
+
readonly isFieldRequired?: (theme: TTheme, recipeName: string, fieldName: string) => boolean;
|
|
77
|
+
readonly disabled?: boolean;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=authoring-adapters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authoring-adapters.d.ts","sourceRoot":"","sources":["../../src/types/authoring-adapters.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authoring-adapters.js","sourceRoot":"","sources":["../../src/types/authoring-adapters.ts"],"names":[],"mappings":"","sourcesContent":["import type React from 'react';\n\nimport type {\n ZoraComponentMeta,\n ZoraComponentPropSchema,\n ZoraComponentPropValue,\n} from './authoring';\nimport type { ZoraThemeRecipeFieldMeta, ZoraThemeRecipeMetaRegistry } from './theme-recipe';\n\nexport interface AuthoringSelectionItemState<TItem> {\n readonly item: TItem;\n readonly selected: boolean;\n readonly disabled: boolean;\n readonly select: () => void;\n}\n\nexport interface AuthoringSelectionAdapterProps<TItem> {\n readonly items: readonly TItem[];\n readonly selectedItemId?: string;\n readonly getItemId: (item: TItem) => string;\n readonly onSelectionChange?: (item: TItem | null) => void;\n readonly renderItem: (state: AuthoringSelectionItemState<TItem>) => React.ReactNode;\n readonly disabled?: boolean;\n}\n\nexport interface AuthoringPropertyControlState<TNode> {\n readonly node: TNode;\n readonly component: ZoraComponentMeta;\n readonly name: string;\n readonly schema: ZoraComponentPropSchema;\n readonly value: ZoraComponentPropValue | undefined;\n readonly disabled: boolean;\n readonly required: boolean;\n readonly onChange: (value: ZoraComponentPropValue | undefined) => void;\n}\n\nexport interface AuthoringPropertyInspectorAdapterProps<TNode> {\n readonly node: TNode | null;\n readonly component: ZoraComponentMeta | null;\n readonly getPropertyValue: (node: TNode, name: string) => ZoraComponentPropValue | undefined;\n readonly onPropertyChange?: (\n node: TNode,\n name: string,\n value: ZoraComponentPropValue | undefined,\n ) => void;\n readonly renderProperty: (state: AuthoringPropertyControlState<TNode>) => React.ReactNode;\n readonly isPropertyDisabled?: (\n node: TNode,\n name: string,\n schema: ZoraComponentPropSchema,\n ) => boolean;\n readonly isPropertyRequired?: (\n node: TNode,\n name: string,\n schema: ZoraComponentPropSchema,\n ) => boolean;\n readonly disabled?: boolean;\n}\n\nexport interface AuthoringBindingControlState<TNode, TBinding> {\n readonly node: TNode;\n readonly component: ZoraComponentMeta;\n readonly name: string;\n readonly label: string;\n readonly description?: string;\n readonly binding: TBinding | undefined;\n readonly disabled: boolean;\n readonly required: boolean;\n readonly onChange: (binding: TBinding | undefined) => void;\n}\n\nexport interface AuthoringBindingEditorAdapterProps<TNode, TBinding> {\n readonly node: TNode | null;\n readonly component: ZoraComponentMeta | null;\n readonly getBinding: (node: TNode, name: string) => TBinding | undefined;\n readonly onBindingChange?: (node: TNode, name: string, binding: TBinding | undefined) => void;\n readonly renderBinding: (state: AuthoringBindingControlState<TNode, TBinding>) => React.ReactNode;\n readonly isBindingDisabled?: (node: TNode, name: string) => boolean;\n readonly isBindingRequired?: (node: TNode, name: string) => boolean;\n readonly disabled?: boolean;\n}\n\nexport interface ThemeRecipeFieldControlState<TTheme> {\n readonly theme: TTheme;\n readonly recipeName: string;\n readonly fieldName: string;\n readonly field: ZoraThemeRecipeFieldMeta;\n readonly value: string | boolean | undefined;\n readonly disabled: boolean;\n readonly required: boolean;\n readonly onChange: (value: string | boolean | undefined) => void;\n}\n\nexport interface ThemeEditorAdapterProps<TTheme> {\n readonly theme: TTheme | null;\n readonly recipes?: ZoraThemeRecipeMetaRegistry;\n readonly getRecipeFieldValue: (\n theme: TTheme,\n recipeName: string,\n fieldName: string,\n ) => string | boolean | undefined;\n readonly onRecipeFieldChange?: (\n theme: TTheme,\n recipeName: string,\n fieldName: string,\n value: string | boolean | undefined,\n ) => void;\n readonly renderField: (state: ThemeRecipeFieldControlState<TTheme>) => React.ReactNode;\n readonly isFieldDisabled?: (theme: TTheme, recipeName: string, fieldName: string) => boolean;\n readonly isFieldRequired?: (theme: TTheme, recipeName: string, fieldName: string) => boolean;\n readonly disabled?: boolean;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ankhorage/zora",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "27.0
|
|
4
|
+
"version": "27.1.0",
|
|
5
5
|
"description": "Opinionated React Native and React Native Web UI kit built on @ankhorage/surface.",
|
|
6
6
|
"homepage": "https://github.com/ankhorage/zora#readme",
|
|
7
7
|
"bugs": {
|
|
@@ -118,6 +118,13 @@
|
|
|
118
118
|
"import": "./dist/features/theme/public.js",
|
|
119
119
|
"default": "./dist/features/theme/public.js"
|
|
120
120
|
},
|
|
121
|
+
"./authoring": {
|
|
122
|
+
"react-native": "./src/authoring.ts",
|
|
123
|
+
"browser": "./src/authoring.ts",
|
|
124
|
+
"types": "./dist/authoring.d.ts",
|
|
125
|
+
"import": "./dist/authoring.js",
|
|
126
|
+
"default": "./dist/authoring.js"
|
|
127
|
+
},
|
|
121
128
|
"./web/runtime": {
|
|
122
129
|
"types": "./web-dist/runtime/ZoraProvider.d.ts",
|
|
123
130
|
"import": "./web-dist/runtime/ZoraProvider.js",
|
package/src/authoring.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { AuthoringBindingEditorAdapter } from './features/registry/adapters/inbound/AuthoringBindingEditorAdapter';
|
|
2
|
+
export { AuthoringPropertyInspectorAdapter } from './features/registry/adapters/inbound/AuthoringPropertyInspectorAdapter';
|
|
3
|
+
export { AuthoringSelectionAdapter } from './features/registry/adapters/inbound/AuthoringSelectionAdapter';
|
|
4
|
+
export { ThemeEditorAdapter } from './features/registry/adapters/inbound/ThemeEditorAdapter';
|
|
5
|
+
export type {
|
|
6
|
+
AuthoringBindingControlState,
|
|
7
|
+
AuthoringBindingEditorAdapterProps,
|
|
8
|
+
AuthoringPropertyControlState,
|
|
9
|
+
AuthoringPropertyInspectorAdapterProps,
|
|
10
|
+
AuthoringSelectionAdapterProps,
|
|
11
|
+
AuthoringSelectionItemState,
|
|
12
|
+
ThemeEditorAdapterProps,
|
|
13
|
+
ThemeRecipeFieldControlState,
|
|
14
|
+
} from './types/authoring-adapters';
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import type { AuthoringBindingEditorAdapterProps } from '../../../../types/authoring-adapters';
|
|
4
|
+
import { Field } from '../../../form/public';
|
|
5
|
+
import { View } from '../../../layout/public';
|
|
6
|
+
|
|
7
|
+
/*** Presents canonical bindable properties while leaving binding representation and mutation ownership external. */
|
|
8
|
+
export function AuthoringBindingEditorAdapter<TNode, TBinding>({
|
|
9
|
+
node,
|
|
10
|
+
component,
|
|
11
|
+
getBinding,
|
|
12
|
+
onBindingChange,
|
|
13
|
+
renderBinding,
|
|
14
|
+
isBindingDisabled,
|
|
15
|
+
isBindingRequired,
|
|
16
|
+
disabled = false,
|
|
17
|
+
}: AuthoringBindingEditorAdapterProps<TNode, TBinding>) {
|
|
18
|
+
if (node === null || component === null) return null;
|
|
19
|
+
const bindings = component.bindings?.props;
|
|
20
|
+
if (bindings === undefined) return null;
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<View gap="m">
|
|
24
|
+
{Object.entries(bindings).map(([name, meta]) => {
|
|
25
|
+
const controlDisabled = disabled || isBindingDisabled?.(node, name) === true;
|
|
26
|
+
const required = isBindingRequired?.(node, name) === true;
|
|
27
|
+
return (
|
|
28
|
+
<Field
|
|
29
|
+
key={name}
|
|
30
|
+
description={meta.description}
|
|
31
|
+
disabled={controlDisabled}
|
|
32
|
+
label={meta.label ?? name}
|
|
33
|
+
required={required}
|
|
34
|
+
>
|
|
35
|
+
{renderBinding({
|
|
36
|
+
node,
|
|
37
|
+
component,
|
|
38
|
+
name,
|
|
39
|
+
label: meta.label ?? name,
|
|
40
|
+
description: meta.description,
|
|
41
|
+
binding: getBinding(node, name),
|
|
42
|
+
disabled: controlDisabled,
|
|
43
|
+
required,
|
|
44
|
+
onChange: (binding) => {
|
|
45
|
+
if (!controlDisabled) onBindingChange?.(node, name, binding);
|
|
46
|
+
},
|
|
47
|
+
})}
|
|
48
|
+
</Field>
|
|
49
|
+
);
|
|
50
|
+
})}
|
|
51
|
+
</View>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import type { AuthoringPropertyInspectorAdapterProps } from '../../../../types/authoring-adapters';
|
|
4
|
+
import { Field } from '../../../form/public';
|
|
5
|
+
import { View } from '../../../layout/public';
|
|
6
|
+
|
|
7
|
+
/*** Presents canonical component properties while keeping node storage and mutations with the consumer. */
|
|
8
|
+
export function AuthoringPropertyInspectorAdapter<TNode>({
|
|
9
|
+
node,
|
|
10
|
+
component,
|
|
11
|
+
getPropertyValue,
|
|
12
|
+
onPropertyChange,
|
|
13
|
+
renderProperty,
|
|
14
|
+
isPropertyDisabled,
|
|
15
|
+
isPropertyRequired,
|
|
16
|
+
disabled = false,
|
|
17
|
+
}: AuthoringPropertyInspectorAdapterProps<TNode>) {
|
|
18
|
+
if (node === null || component === null) return null;
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<View gap="m">
|
|
22
|
+
{Object.entries(component.props).map(([name, schema]) => {
|
|
23
|
+
const controlDisabled = disabled || isPropertyDisabled?.(node, name, schema) === true;
|
|
24
|
+
const required = isPropertyRequired?.(node, name, schema) === true;
|
|
25
|
+
return (
|
|
26
|
+
<Field
|
|
27
|
+
key={name}
|
|
28
|
+
description={schema.label === undefined ? undefined : schema.category}
|
|
29
|
+
disabled={controlDisabled}
|
|
30
|
+
label={schema.label ?? name}
|
|
31
|
+
required={required}
|
|
32
|
+
>
|
|
33
|
+
{renderProperty({
|
|
34
|
+
node,
|
|
35
|
+
component,
|
|
36
|
+
name,
|
|
37
|
+
schema,
|
|
38
|
+
value: getPropertyValue(node, name),
|
|
39
|
+
disabled: controlDisabled,
|
|
40
|
+
required,
|
|
41
|
+
onChange: (value) => {
|
|
42
|
+
if (!controlDisabled) onPropertyChange?.(node, name, value);
|
|
43
|
+
},
|
|
44
|
+
})}
|
|
45
|
+
</Field>
|
|
46
|
+
);
|
|
47
|
+
})}
|
|
48
|
+
</View>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import type { AuthoringSelectionAdapterProps } from '../../../../types/authoring-adapters';
|
|
4
|
+
import { SelectableItem, SelectionProvider } from '../../../selection/public';
|
|
5
|
+
|
|
6
|
+
/*** Connects consumer-owned items to ZORA's controlled single-selection behavior. */
|
|
7
|
+
export function AuthoringSelectionAdapter<TItem>({
|
|
8
|
+
items,
|
|
9
|
+
selectedItemId,
|
|
10
|
+
getItemId,
|
|
11
|
+
onSelectionChange,
|
|
12
|
+
renderItem,
|
|
13
|
+
disabled,
|
|
14
|
+
}: AuthoringSelectionAdapterProps<TItem>) {
|
|
15
|
+
return (
|
|
16
|
+
<SelectionProvider
|
|
17
|
+
disabled={disabled}
|
|
18
|
+
mode="single"
|
|
19
|
+
selectedIds={selectedItemId === undefined ? [] : [selectedItemId]}
|
|
20
|
+
onSelectionChange={(ids) => {
|
|
21
|
+
const [selectedId] = ids;
|
|
22
|
+
onSelectionChange?.(items.find((item) => getItemId(item) === selectedId) ?? null);
|
|
23
|
+
}}
|
|
24
|
+
>
|
|
25
|
+
{items.map((item) => {
|
|
26
|
+
const id = getItemId(item);
|
|
27
|
+
return (
|
|
28
|
+
<SelectableItem key={id} id={id} trigger="press">
|
|
29
|
+
{(state) =>
|
|
30
|
+
renderItem({
|
|
31
|
+
item,
|
|
32
|
+
selected: state.selected,
|
|
33
|
+
disabled: state.disabled,
|
|
34
|
+
select: state.select,
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
</SelectableItem>
|
|
38
|
+
);
|
|
39
|
+
})}
|
|
40
|
+
</SelectionProvider>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import type { ThemeEditorAdapterProps } from '../../../../types/authoring-adapters';
|
|
4
|
+
import { Card } from '../../../card/public';
|
|
5
|
+
import { Field } from '../../../form/public';
|
|
6
|
+
import { View } from '../../../layout/public';
|
|
7
|
+
import { ZORA_THEME_RECIPE_META } from '../../themeRecipeMeta';
|
|
8
|
+
|
|
9
|
+
/*** Presents ZORA recipe fields without taking ownership of a consumer's theme document. */
|
|
10
|
+
export function ThemeEditorAdapter<TTheme>({
|
|
11
|
+
theme,
|
|
12
|
+
recipes = ZORA_THEME_RECIPE_META,
|
|
13
|
+
getRecipeFieldValue,
|
|
14
|
+
onRecipeFieldChange,
|
|
15
|
+
renderField,
|
|
16
|
+
isFieldDisabled,
|
|
17
|
+
isFieldRequired,
|
|
18
|
+
disabled = false,
|
|
19
|
+
}: ThemeEditorAdapterProps<TTheme>) {
|
|
20
|
+
if (theme === null) return null;
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<View gap="m">
|
|
24
|
+
{Object.entries(recipes).map(([recipeName, recipe]) => (
|
|
25
|
+
<Card key={recipeName} description={recipe.description} title={recipe.name}>
|
|
26
|
+
<View gap="m">
|
|
27
|
+
{Object.entries(recipe.fields).map(([fieldName, field]) => {
|
|
28
|
+
const controlDisabled =
|
|
29
|
+
disabled || isFieldDisabled?.(theme, recipeName, fieldName) === true;
|
|
30
|
+
const required = isFieldRequired?.(theme, recipeName, fieldName) === true;
|
|
31
|
+
return (
|
|
32
|
+
<Field
|
|
33
|
+
key={fieldName}
|
|
34
|
+
description={field.description}
|
|
35
|
+
disabled={controlDisabled}
|
|
36
|
+
label={field.label}
|
|
37
|
+
required={required}
|
|
38
|
+
>
|
|
39
|
+
{renderField({
|
|
40
|
+
theme,
|
|
41
|
+
recipeName,
|
|
42
|
+
fieldName,
|
|
43
|
+
field,
|
|
44
|
+
value: getRecipeFieldValue(theme, recipeName, fieldName),
|
|
45
|
+
disabled: controlDisabled,
|
|
46
|
+
required,
|
|
47
|
+
onChange: (value) => {
|
|
48
|
+
if (!controlDisabled) {
|
|
49
|
+
onRecipeFieldChange?.(theme, recipeName, fieldName, value);
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
})}
|
|
53
|
+
</Field>
|
|
54
|
+
);
|
|
55
|
+
})}
|
|
56
|
+
</View>
|
|
57
|
+
</Card>
|
|
58
|
+
))}
|
|
59
|
+
</View>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test';
|
|
2
|
+
import { isValidElement, type ReactElement } from 'react';
|
|
3
|
+
|
|
4
|
+
import type { ZoraComponentMeta } from '../../../../types/authoring';
|
|
5
|
+
import type {
|
|
6
|
+
AuthoringBindingEditorAdapterProps,
|
|
7
|
+
AuthoringPropertyInspectorAdapterProps,
|
|
8
|
+
AuthoringSelectionAdapterProps,
|
|
9
|
+
ThemeEditorAdapterProps,
|
|
10
|
+
} from '../../../../types/authoring-adapters';
|
|
11
|
+
import type { ZoraThemeRecipeMetaRegistry } from '../../../../types/theme-recipe';
|
|
12
|
+
|
|
13
|
+
type AuthoringSelectionAdapter = <TItem>(
|
|
14
|
+
props: AuthoringSelectionAdapterProps<TItem>,
|
|
15
|
+
) => ReactElement;
|
|
16
|
+
type AuthoringPropertyInspectorAdapter = <TNode>(
|
|
17
|
+
props: AuthoringPropertyInspectorAdapterProps<TNode>,
|
|
18
|
+
) => ReactElement | null;
|
|
19
|
+
type AuthoringBindingEditorAdapter = <TNode, TBinding>(
|
|
20
|
+
props: AuthoringBindingEditorAdapterProps<TNode, TBinding>,
|
|
21
|
+
) => ReactElement | null;
|
|
22
|
+
type ThemeEditorAdapter = <TTheme>(props: ThemeEditorAdapterProps<TTheme>) => ReactElement | null;
|
|
23
|
+
|
|
24
|
+
interface LoadedAdapters {
|
|
25
|
+
readonly AuthoringBindingEditorAdapter: AuthoringBindingEditorAdapter;
|
|
26
|
+
readonly AuthoringPropertyInspectorAdapter: AuthoringPropertyInspectorAdapter;
|
|
27
|
+
readonly AuthoringSelectionAdapter: AuthoringSelectionAdapter;
|
|
28
|
+
readonly ThemeEditorAdapter: ThemeEditorAdapter;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const component: ZoraComponentMeta = {
|
|
32
|
+
name: 'Example',
|
|
33
|
+
category: 'component',
|
|
34
|
+
directManifestNode: true,
|
|
35
|
+
allowedChildren: [],
|
|
36
|
+
props: {
|
|
37
|
+
title: { type: 'string', category: 'Content', label: 'Title' },
|
|
38
|
+
},
|
|
39
|
+
bindings: {
|
|
40
|
+
props: {
|
|
41
|
+
title: {
|
|
42
|
+
label: 'Title binding',
|
|
43
|
+
value: { type: 'string' },
|
|
44
|
+
acceptsFallback: true,
|
|
45
|
+
acceptsTransforms: true,
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const recipes: ZoraThemeRecipeMetaRegistry = {
|
|
52
|
+
Example: {
|
|
53
|
+
name: 'Example',
|
|
54
|
+
kind: 'component',
|
|
55
|
+
fields: {
|
|
56
|
+
color: { type: 'token', label: 'Color', tokenFamily: 'colors' },
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
describe('authoring adapters', () => {
|
|
62
|
+
test('maps consumer-owned selection data back from ZORA selection ids', async () => {
|
|
63
|
+
const { AuthoringSelectionAdapter } = await loadAdapters();
|
|
64
|
+
const selected: ({ id: string } | null)[] = [];
|
|
65
|
+
const element = AuthoringSelectionAdapter({
|
|
66
|
+
items: [{ id: 'first' }, { id: 'second' }],
|
|
67
|
+
selectedItemId: 'first',
|
|
68
|
+
getItemId: (item) => item.id,
|
|
69
|
+
onSelectionChange: (item) => selected.push(item),
|
|
70
|
+
renderItem: ({ item }) => <item data-id={item.id} />,
|
|
71
|
+
});
|
|
72
|
+
const change = findElement(element, 'SelectionProvider')?.props.onSelectionChange;
|
|
73
|
+
|
|
74
|
+
if (typeof change !== 'function') throw new Error('Missing selection mutation callback.');
|
|
75
|
+
Reflect.apply(change, undefined, [['second']]);
|
|
76
|
+
Reflect.apply(change, undefined, [[]]);
|
|
77
|
+
|
|
78
|
+
expect(selected).toEqual([{ id: 'second' }, null]);
|
|
79
|
+
expect(findElement(element, 'SelectionProvider')?.props.selectedIds).toEqual(['first']);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test('passes required state and real property mutations while preventing disabled mutations', async () => {
|
|
83
|
+
const { AuthoringPropertyInspectorAdapter } = await loadAdapters();
|
|
84
|
+
const mutations: [string, string | undefined][] = [];
|
|
85
|
+
const enabled = AuthoringPropertyInspectorAdapter({
|
|
86
|
+
node: { title: 'Current title' },
|
|
87
|
+
component,
|
|
88
|
+
getPropertyValue: (node, name) => (name === 'title' ? node.title : undefined),
|
|
89
|
+
onPropertyChange: (_node, name, value) => mutations.push([name, value as string | undefined]),
|
|
90
|
+
isPropertyRequired: () => true,
|
|
91
|
+
renderProperty: ({ disabled, onChange, required }) => (
|
|
92
|
+
<property disabled={disabled} onChange={onChange} required={required} />
|
|
93
|
+
),
|
|
94
|
+
});
|
|
95
|
+
const enabledControl = findElement(enabled, 'property');
|
|
96
|
+
const change = readStringChange(enabledControl, 'property mutation callback');
|
|
97
|
+
change('Updated title');
|
|
98
|
+
|
|
99
|
+
const disabled = AuthoringPropertyInspectorAdapter({
|
|
100
|
+
node: { title: 'Current title' },
|
|
101
|
+
component,
|
|
102
|
+
getPropertyValue: (node, name) => (name === 'title' ? node.title : undefined),
|
|
103
|
+
onPropertyChange: (_node, name, value) => mutations.push([name, value as string | undefined]),
|
|
104
|
+
disabled: true,
|
|
105
|
+
renderProperty: ({ disabled: controlDisabled, onChange }) => (
|
|
106
|
+
<property disabled={controlDisabled} onChange={onChange} />
|
|
107
|
+
),
|
|
108
|
+
});
|
|
109
|
+
const disabledChange = readStringChange(
|
|
110
|
+
findElement(disabled, 'property'),
|
|
111
|
+
'disabled property callback',
|
|
112
|
+
);
|
|
113
|
+
disabledChange('Ignored title');
|
|
114
|
+
|
|
115
|
+
expect(enabledControl?.props.required).toBe(true);
|
|
116
|
+
expect(findElement(disabled, 'property')?.props.disabled).toBe(true);
|
|
117
|
+
expect(mutations).toEqual([['title', 'Updated title']]);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test('passes disabled binding state and suppresses disabled binding mutations', async () => {
|
|
121
|
+
const { AuthoringBindingEditorAdapter } = await loadAdapters();
|
|
122
|
+
const mutations: [string, string | undefined][] = [];
|
|
123
|
+
const element = AuthoringBindingEditorAdapter({
|
|
124
|
+
node: { binding: 'source.title' },
|
|
125
|
+
component,
|
|
126
|
+
getBinding: (node) => node.binding,
|
|
127
|
+
onBindingChange: (_node, name, binding) => mutations.push([name, binding]),
|
|
128
|
+
disabled: true,
|
|
129
|
+
isBindingRequired: () => true,
|
|
130
|
+
renderBinding: ({ disabled, onChange, required }) => (
|
|
131
|
+
<binding disabled={disabled} onChange={onChange} required={required} />
|
|
132
|
+
),
|
|
133
|
+
});
|
|
134
|
+
const control = findElement(element, 'binding');
|
|
135
|
+
const change = readStringChange(control, 'binding mutation callback');
|
|
136
|
+
change('replacement.title');
|
|
137
|
+
|
|
138
|
+
expect(control?.props.disabled).toBe(true);
|
|
139
|
+
expect(control?.props.required).toBe(true);
|
|
140
|
+
expect(mutations).toEqual([]);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
test('passes theme field state and suppresses disabled theme mutations', async () => {
|
|
144
|
+
const { ThemeEditorAdapter } = await loadAdapters();
|
|
145
|
+
const mutations: [string, string, string | boolean | undefined][] = [];
|
|
146
|
+
const element = ThemeEditorAdapter({
|
|
147
|
+
theme: { color: 'primary' },
|
|
148
|
+
recipes,
|
|
149
|
+
getRecipeFieldValue: (theme) => theme.color,
|
|
150
|
+
onRecipeFieldChange: (_theme, recipeName, fieldName, value) =>
|
|
151
|
+
mutations.push([recipeName, fieldName, value]),
|
|
152
|
+
disabled: true,
|
|
153
|
+
isFieldRequired: () => true,
|
|
154
|
+
renderField: ({ disabled, onChange, required }) => (
|
|
155
|
+
<theme-field disabled={disabled} onChange={onChange} required={required} />
|
|
156
|
+
),
|
|
157
|
+
});
|
|
158
|
+
const control = findElement(element, 'theme-field');
|
|
159
|
+
const change = readStringChange(control, 'theme mutation callback');
|
|
160
|
+
change('secondary');
|
|
161
|
+
|
|
162
|
+
expect(control?.props.disabled).toBe(true);
|
|
163
|
+
expect(control?.props.required).toBe(true);
|
|
164
|
+
expect(mutations).toEqual([]);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
/*** Find a host element emitted by an adapter render prop without mounting platform controls. */
|
|
169
|
+
function findElement(
|
|
170
|
+
node: unknown,
|
|
171
|
+
type: string,
|
|
172
|
+
): ReactElement<Record<string, unknown>> | undefined {
|
|
173
|
+
if (Array.isArray(node)) {
|
|
174
|
+
return node.map((item) => findElement(item, type)).find((item) => item !== undefined);
|
|
175
|
+
}
|
|
176
|
+
if (!isValidElement<Record<string, unknown>>(node)) return undefined;
|
|
177
|
+
if (node.type === type) return node;
|
|
178
|
+
return findElement(node.props.children, type);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/*** Read the string-valued render-prop mutation callback after its runtime boundary check. */
|
|
182
|
+
function readStringChange(
|
|
183
|
+
element: ReactElement<Record<string, unknown>> | undefined,
|
|
184
|
+
description: string,
|
|
185
|
+
): (value: string) => void {
|
|
186
|
+
const value = element?.props.onChange;
|
|
187
|
+
if (typeof value !== 'function') throw new Error(`Missing ${description}.`);
|
|
188
|
+
return value as (nextValue: string) => void;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/*** Load adapter modules with inert ZORA controls so unit assertions stay at the public callback boundary. */
|
|
192
|
+
async function loadAdapters(): Promise<LoadedAdapters> {
|
|
193
|
+
const build = await Bun.build({
|
|
194
|
+
entrypoints: [new URL('../../../../authoring.ts', import.meta.url).pathname],
|
|
195
|
+
target: 'bun',
|
|
196
|
+
plugins: [
|
|
197
|
+
{
|
|
198
|
+
name: 'inert-zora-authoring-controls',
|
|
199
|
+
setup(builder) {
|
|
200
|
+
builder.onResolve(
|
|
201
|
+
{ filter: /(?:card|form|layout|registry|selection)\/public$/u },
|
|
202
|
+
({ path }) => ({ path, namespace: 'inert-zora-controls' }),
|
|
203
|
+
);
|
|
204
|
+
builder.onLoad({ filter: /.*/u, namespace: 'inert-zora-controls' }, () => ({
|
|
205
|
+
loader: 'js',
|
|
206
|
+
contents: `export const Card='Card', Field='Field', View='View',
|
|
207
|
+
SelectableItem='SelectableItem', SelectionProvider='SelectionProvider';`,
|
|
208
|
+
}));
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
],
|
|
212
|
+
});
|
|
213
|
+
if (!build.success || !build.outputs[0]) {
|
|
214
|
+
throw new Error(build.logs.map((log) => log.message).join('\n'));
|
|
215
|
+
}
|
|
216
|
+
const loaded: unknown = await import(
|
|
217
|
+
`data:text/javascript;base64,${Buffer.from(await build.outputs[0].text()).toString('base64')}`
|
|
218
|
+
);
|
|
219
|
+
return {
|
|
220
|
+
AuthoringBindingEditorAdapter: readAdapter(loaded, 'AuthoringBindingEditorAdapter'),
|
|
221
|
+
AuthoringPropertyInspectorAdapter: readAdapter(loaded, 'AuthoringPropertyInspectorAdapter'),
|
|
222
|
+
AuthoringSelectionAdapter: readAdapter(loaded, 'AuthoringSelectionAdapter'),
|
|
223
|
+
ThemeEditorAdapter: readAdapter(loaded, 'ThemeEditorAdapter'),
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/*** Read one bundled adapter only after its runtime export has been verified as callable. */
|
|
228
|
+
function readAdapter<TAdapter extends (...arguments_: never[]) => unknown>(
|
|
229
|
+
module: unknown,
|
|
230
|
+
name: string,
|
|
231
|
+
): TAdapter {
|
|
232
|
+
const value = isRecord(module)
|
|
233
|
+
? Object.entries(module).find(([key]) => key === name)?.[1]
|
|
234
|
+
: undefined;
|
|
235
|
+
if (typeof value !== 'function') throw new Error(`Missing ${name}.`);
|
|
236
|
+
return value as TAdapter;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/*** Narrow an unknown module namespace before reading a dynamic public export. */
|
|
240
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
241
|
+
return typeof value === 'object' && value !== null;
|
|
242
|
+
}
|
|
@@ -126,4 +126,15 @@ describe('ZORA_COMPONENT_REGISTRY', () => {
|
|
|
126
126
|
expect(registryEntries).not.toContain('ToastProvider');
|
|
127
127
|
expect(registryEntries).not.toContain('SelectionProvider');
|
|
128
128
|
});
|
|
129
|
+
|
|
130
|
+
test('keeps public authoring adapters outside the reader-free runtime catalog', async () => {
|
|
131
|
+
const [authoringSource, readerFreeSource] = await Promise.all([
|
|
132
|
+
Bun.file('src/authoring.ts').text(),
|
|
133
|
+
Bun.file('src/readerFree.ts').text(),
|
|
134
|
+
]);
|
|
135
|
+
|
|
136
|
+
expect(authoringSource).toContain("from './features/registry/adapters/inbound/");
|
|
137
|
+
expect(readerFreeSource).not.toContain('AuthoringSelectionAdapter');
|
|
138
|
+
expect(await listRuntimeRegistryEntries()).not.toContain('AuthoringSelectionAdapter');
|
|
139
|
+
});
|
|
129
140
|
});
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
export type {
|
|
2
|
+
AuthoringBindingControlState,
|
|
3
|
+
AuthoringBindingEditorAdapterProps,
|
|
4
|
+
AuthoringPropertyControlState,
|
|
5
|
+
AuthoringPropertyInspectorAdapterProps,
|
|
6
|
+
AuthoringSelectionAdapterProps,
|
|
7
|
+
AuthoringSelectionItemState,
|
|
8
|
+
ThemeEditorAdapterProps,
|
|
9
|
+
ThemeRecipeFieldControlState,
|
|
10
|
+
} from './authoring';
|
|
11
|
+
export {
|
|
12
|
+
AuthoringBindingEditorAdapter,
|
|
13
|
+
AuthoringPropertyInspectorAdapter,
|
|
14
|
+
AuthoringSelectionAdapter,
|
|
15
|
+
ThemeEditorAdapter,
|
|
16
|
+
} from './authoring';
|
|
1
17
|
export type {
|
|
2
18
|
ReaderColorScheme,
|
|
3
19
|
ReaderDocumentFormat,
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
ZoraComponentMeta,
|
|
5
|
+
ZoraComponentPropSchema,
|
|
6
|
+
ZoraComponentPropValue,
|
|
7
|
+
} from './authoring';
|
|
8
|
+
import type { ZoraThemeRecipeFieldMeta, ZoraThemeRecipeMetaRegistry } from './theme-recipe';
|
|
9
|
+
|
|
10
|
+
export interface AuthoringSelectionItemState<TItem> {
|
|
11
|
+
readonly item: TItem;
|
|
12
|
+
readonly selected: boolean;
|
|
13
|
+
readonly disabled: boolean;
|
|
14
|
+
readonly select: () => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface AuthoringSelectionAdapterProps<TItem> {
|
|
18
|
+
readonly items: readonly TItem[];
|
|
19
|
+
readonly selectedItemId?: string;
|
|
20
|
+
readonly getItemId: (item: TItem) => string;
|
|
21
|
+
readonly onSelectionChange?: (item: TItem | null) => void;
|
|
22
|
+
readonly renderItem: (state: AuthoringSelectionItemState<TItem>) => React.ReactNode;
|
|
23
|
+
readonly disabled?: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface AuthoringPropertyControlState<TNode> {
|
|
27
|
+
readonly node: TNode;
|
|
28
|
+
readonly component: ZoraComponentMeta;
|
|
29
|
+
readonly name: string;
|
|
30
|
+
readonly schema: ZoraComponentPropSchema;
|
|
31
|
+
readonly value: ZoraComponentPropValue | undefined;
|
|
32
|
+
readonly disabled: boolean;
|
|
33
|
+
readonly required: boolean;
|
|
34
|
+
readonly onChange: (value: ZoraComponentPropValue | undefined) => void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface AuthoringPropertyInspectorAdapterProps<TNode> {
|
|
38
|
+
readonly node: TNode | null;
|
|
39
|
+
readonly component: ZoraComponentMeta | null;
|
|
40
|
+
readonly getPropertyValue: (node: TNode, name: string) => ZoraComponentPropValue | undefined;
|
|
41
|
+
readonly onPropertyChange?: (
|
|
42
|
+
node: TNode,
|
|
43
|
+
name: string,
|
|
44
|
+
value: ZoraComponentPropValue | undefined,
|
|
45
|
+
) => void;
|
|
46
|
+
readonly renderProperty: (state: AuthoringPropertyControlState<TNode>) => React.ReactNode;
|
|
47
|
+
readonly isPropertyDisabled?: (
|
|
48
|
+
node: TNode,
|
|
49
|
+
name: string,
|
|
50
|
+
schema: ZoraComponentPropSchema,
|
|
51
|
+
) => boolean;
|
|
52
|
+
readonly isPropertyRequired?: (
|
|
53
|
+
node: TNode,
|
|
54
|
+
name: string,
|
|
55
|
+
schema: ZoraComponentPropSchema,
|
|
56
|
+
) => boolean;
|
|
57
|
+
readonly disabled?: boolean;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface AuthoringBindingControlState<TNode, TBinding> {
|
|
61
|
+
readonly node: TNode;
|
|
62
|
+
readonly component: ZoraComponentMeta;
|
|
63
|
+
readonly name: string;
|
|
64
|
+
readonly label: string;
|
|
65
|
+
readonly description?: string;
|
|
66
|
+
readonly binding: TBinding | undefined;
|
|
67
|
+
readonly disabled: boolean;
|
|
68
|
+
readonly required: boolean;
|
|
69
|
+
readonly onChange: (binding: TBinding | undefined) => void;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface AuthoringBindingEditorAdapterProps<TNode, TBinding> {
|
|
73
|
+
readonly node: TNode | null;
|
|
74
|
+
readonly component: ZoraComponentMeta | null;
|
|
75
|
+
readonly getBinding: (node: TNode, name: string) => TBinding | undefined;
|
|
76
|
+
readonly onBindingChange?: (node: TNode, name: string, binding: TBinding | undefined) => void;
|
|
77
|
+
readonly renderBinding: (state: AuthoringBindingControlState<TNode, TBinding>) => React.ReactNode;
|
|
78
|
+
readonly isBindingDisabled?: (node: TNode, name: string) => boolean;
|
|
79
|
+
readonly isBindingRequired?: (node: TNode, name: string) => boolean;
|
|
80
|
+
readonly disabled?: boolean;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface ThemeRecipeFieldControlState<TTheme> {
|
|
84
|
+
readonly theme: TTheme;
|
|
85
|
+
readonly recipeName: string;
|
|
86
|
+
readonly fieldName: string;
|
|
87
|
+
readonly field: ZoraThemeRecipeFieldMeta;
|
|
88
|
+
readonly value: string | boolean | undefined;
|
|
89
|
+
readonly disabled: boolean;
|
|
90
|
+
readonly required: boolean;
|
|
91
|
+
readonly onChange: (value: string | boolean | undefined) => void;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface ThemeEditorAdapterProps<TTheme> {
|
|
95
|
+
readonly theme: TTheme | null;
|
|
96
|
+
readonly recipes?: ZoraThemeRecipeMetaRegistry;
|
|
97
|
+
readonly getRecipeFieldValue: (
|
|
98
|
+
theme: TTheme,
|
|
99
|
+
recipeName: string,
|
|
100
|
+
fieldName: string,
|
|
101
|
+
) => string | boolean | undefined;
|
|
102
|
+
readonly onRecipeFieldChange?: (
|
|
103
|
+
theme: TTheme,
|
|
104
|
+
recipeName: string,
|
|
105
|
+
fieldName: string,
|
|
106
|
+
value: string | boolean | undefined,
|
|
107
|
+
) => void;
|
|
108
|
+
readonly renderField: (state: ThemeRecipeFieldControlState<TTheme>) => React.ReactNode;
|
|
109
|
+
readonly isFieldDisabled?: (theme: TTheme, recipeName: string, fieldName: string) => boolean;
|
|
110
|
+
readonly isFieldRequired?: (theme: TTheme, recipeName: string, fieldName: string) => boolean;
|
|
111
|
+
readonly disabled?: boolean;
|
|
112
|
+
}
|