@jfdevelops/react-layout 1.6.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/create-config/create-defined-resource-layout.cjs +18 -14
- package/dist/create-config/create-defined-resource-layout.cjs.map +1 -1
- package/dist/create-config/create-defined-resource-layout.d.cts +9 -5
- package/dist/create-config/create-defined-resource-layout.d.cts.map +1 -1
- package/dist/create-config/create-defined-resource-layout.d.mts +9 -5
- package/dist/create-config/create-defined-resource-layout.d.mts.map +1 -1
- package/dist/create-config/create-defined-resource-layout.mjs +19 -15
- package/dist/create-config/create-defined-resource-layout.mjs.map +1 -1
- package/dist/create-config/define-layout.cjs +66 -39
- package/dist/create-config/define-layout.cjs.map +1 -1
- package/dist/create-config/define-layout.d.cts +0 -5
- package/dist/create-config/define-layout.d.cts.map +1 -1
- package/dist/create-config/define-layout.d.mts +0 -5
- package/dist/create-config/define-layout.d.mts.map +1 -1
- package/dist/create-config/define-layout.mjs +67 -40
- package/dist/create-config/define-layout.mjs.map +1 -1
- package/dist/create-config/for-resources/create-component.d.cts +39 -21
- package/dist/create-config/for-resources/create-component.d.cts.map +1 -1
- package/dist/create-config/for-resources/create-component.d.mts +39 -21
- package/dist/create-config/for-resources/create-component.d.mts.map +1 -1
- package/dist/create-config/for-resources/create-for-resources.cjs +62 -7
- package/dist/create-config/for-resources/create-for-resources.cjs.map +1 -1
- package/dist/create-config/for-resources/create-for-resources.mjs +62 -7
- package/dist/create-config/for-resources/create-for-resources.mjs.map +1 -1
- package/dist/create-config/for-resources/scoped-render.cjs +1 -0
- package/dist/create-config/for-resources/scoped-render.cjs.map +1 -1
- package/dist/create-config/for-resources/scoped-render.d.cts.map +1 -1
- package/dist/create-config/for-resources/scoped-render.d.mts.map +1 -1
- package/dist/create-config/for-resources/scoped-render.mjs +1 -0
- package/dist/create-config/for-resources/scoped-render.mjs.map +1 -1
- package/dist/create-config/index.d.cts +2 -1
- package/dist/create-config/index.d.mts +2 -1
- package/dist/create-config/layout-name.cjs +1 -1
- package/dist/create-config/layout-name.mjs +1 -1
- package/dist/create-config/lazy-resource-layout.cjs +70 -86
- package/dist/create-config/lazy-resource-layout.cjs.map +1 -1
- package/dist/create-config/lazy-resource-layout.d.cts +9 -31
- package/dist/create-config/lazy-resource-layout.d.cts.map +1 -1
- package/dist/create-config/lazy-resource-layout.d.mts +9 -31
- package/dist/create-config/lazy-resource-layout.d.mts.map +1 -1
- package/dist/create-config/lazy-resource-layout.mjs +70 -86
- package/dist/create-config/lazy-resource-layout.mjs.map +1 -1
- package/dist/create-config/preview.cjs +1 -1
- package/dist/create-config/preview.d.cts +2 -0
- package/dist/create-config/preview.d.cts.map +1 -1
- package/dist/create-config/preview.d.mts +2 -0
- package/dist/create-config/preview.d.mts.map +1 -1
- package/dist/create-config/preview.mjs +1 -1
- package/dist/create-config/render-state.cjs +57 -18
- package/dist/create-config/render-state.cjs.map +1 -1
- package/dist/create-config/render-state.d.cts +18 -6
- package/dist/create-config/render-state.d.cts.map +1 -1
- package/dist/create-config/render-state.d.mts +18 -6
- package/dist/create-config/render-state.d.mts.map +1 -1
- package/dist/create-config/render-state.mjs +54 -18
- package/dist/create-config/render-state.mjs.map +1 -1
- package/dist/errors/lazy-resource-error.cjs +37 -0
- package/dist/errors/lazy-resource-error.cjs.map +1 -0
- package/dist/errors/lazy-resource-error.d.cts +26 -0
- package/dist/errors/lazy-resource-error.d.cts.map +1 -0
- package/dist/errors/lazy-resource-error.d.mts +26 -0
- package/dist/errors/lazy-resource-error.d.mts.map +1 -0
- package/dist/errors/lazy-resource-error.mjs +35 -0
- package/dist/errors/lazy-resource-error.mjs.map +1 -0
- package/dist/errors/react-layout-error.cjs +1 -1
- package/dist/errors/react-layout-error.mjs +1 -1
- package/dist/errors/resource-state-error.cjs +4 -1
- package/dist/errors/resource-state-error.cjs.map +1 -1
- package/dist/errors/resource-state-error.d.cts +1 -0
- package/dist/errors/resource-state-error.d.cts.map +1 -1
- package/dist/errors/resource-state-error.d.mts +1 -0
- package/dist/errors/resource-state-error.d.mts.map +1 -1
- package/dist/errors/resource-state-error.mjs +4 -1
- package/dist/errors/resource-state-error.mjs.map +1 -1
- package/dist/index.cjs +6 -2
- package/dist/index.d.cts +7 -4
- package/dist/index.d.mts +7 -4
- package/dist/index.mjs +4 -3
- package/dist/lazy/create-error-component.cjs +17 -0
- package/dist/lazy/create-error-component.cjs.map +1 -0
- package/dist/lazy/create-error-component.mjs +16 -0
- package/dist/lazy/create-error-component.mjs.map +1 -0
- package/dist/lazy/create-lazy-loader.cjs +78 -0
- package/dist/lazy/create-lazy-loader.cjs.map +1 -0
- package/dist/lazy/create-lazy-loader.d.cts +19 -0
- package/dist/lazy/create-lazy-loader.d.cts.map +1 -0
- package/dist/lazy/create-lazy-loader.d.mts +19 -0
- package/dist/lazy/create-lazy-loader.d.mts.map +1 -0
- package/dist/lazy/create-lazy-loader.mjs +78 -0
- package/dist/lazy/create-lazy-loader.mjs.map +1 -0
- package/dist/lazy/fallback-props.cjs +9 -0
- package/dist/lazy/fallback-props.cjs.map +1 -0
- package/dist/lazy/fallback-props.mjs +9 -0
- package/dist/lazy/fallback-props.mjs.map +1 -0
- package/dist/lazy/inspection.cjs +51 -0
- package/dist/lazy/inspection.cjs.map +1 -0
- package/dist/lazy/inspection.d.cts +28 -0
- package/dist/lazy/inspection.d.cts.map +1 -0
- package/dist/lazy/inspection.d.mts +28 -0
- package/dist/lazy/inspection.d.mts.map +1 -0
- package/dist/lazy/inspection.mjs +50 -0
- package/dist/lazy/inspection.mjs.map +1 -0
- package/dist/lazy/lazy-boundary.cjs +55 -0
- package/dist/lazy/lazy-boundary.cjs.map +1 -0
- package/dist/lazy/lazy-boundary.mjs +55 -0
- package/dist/lazy/lazy-boundary.mjs.map +1 -0
- package/dist/lazy/scoped-content.cjs +87 -0
- package/dist/lazy/scoped-content.cjs.map +1 -0
- package/dist/lazy/scoped-content.d.cts +19 -0
- package/dist/lazy/scoped-content.d.cts.map +1 -0
- package/dist/lazy/scoped-content.d.mts +19 -0
- package/dist/lazy/scoped-content.d.mts.map +1 -0
- package/dist/lazy/scoped-content.mjs +86 -0
- package/dist/lazy/scoped-content.mjs.map +1 -0
- package/dist/lazy/types.cjs +10 -0
- package/dist/lazy/types.cjs.map +1 -0
- package/dist/lazy/types.d.cts +39 -0
- package/dist/lazy/types.d.cts.map +1 -0
- package/dist/lazy/types.d.mts +39 -0
- package/dist/lazy/types.d.mts.map +1 -0
- package/dist/lazy/types.mjs +8 -0
- package/dist/lazy/types.mjs.map +1 -0
- package/dist/props.cjs +4 -2
- package/dist/props.cjs.map +1 -1
- package/dist/props.d.cts +6 -50
- package/dist/props.d.cts.map +1 -1
- package/dist/props.d.mts +6 -50
- package/dist/props.d.mts.map +1 -1
- package/dist/props.mjs +5 -2
- package/dist/props.mjs.map +1 -1
- package/dist/resource.cjs.map +1 -1
- package/dist/resource.d.cts +1 -1
- package/dist/resource.d.cts.map +1 -1
- package/dist/resource.d.mts +1 -1
- package/dist/resource.d.mts.map +1 -1
- package/dist/resource.mjs.map +1 -1
- package/package.json +3 -3
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
const require_layout_configuration_error = require('../../errors/layout-configuration-error.cjs');
|
|
2
2
|
const require_capitalize = require('../../utils/capitalize.cjs');
|
|
3
|
+
const require_inspection = require('../../lazy/inspection.cjs');
|
|
3
4
|
const require_scoped_render = require('./scoped-render.cjs');
|
|
5
|
+
const require_scoped_content = require('../../lazy/scoped-content.cjs');
|
|
4
6
|
let react = require("react");
|
|
5
7
|
let _jfdevelops_react_layout_validator = require("@jfdevelops/react-layout-validator");
|
|
6
8
|
|
|
7
9
|
//#region src/create-config/for-resources/create-for-resources.ts
|
|
8
|
-
function createForResources({ createLayoutForResource, createMakeComposableLayout, createResourceLayout, getComponentPropDefinitions }) {
|
|
10
|
+
function createForResources({ createLayoutForResource, createMakeComposableLayout, createResourceLayout, getComponentPropDefinitions, lazyEnvironment }) {
|
|
9
11
|
return ((...resourcesOrOptions) => {
|
|
10
12
|
const firstArgument = resourcesOrOptions[0];
|
|
11
13
|
let resourceOptions;
|
|
@@ -31,6 +33,44 @@ function createForResources({ createLayoutForResource, createMakeComposableLayou
|
|
|
31
33
|
function scopedForResource(options) {
|
|
32
34
|
return createLayoutForResource(options.name ?? defaultNames.get(options.resource), options.resource);
|
|
33
35
|
}
|
|
36
|
+
function normalizeContent(definition, resource, label) {
|
|
37
|
+
if (definition.lazy !== void 0 && definition.render !== void 0) throw new require_layout_configuration_error.LayoutConfigurationError(`Scoped content "${label}" must define render or lazy, never both`);
|
|
38
|
+
if (definition[require_scoped_content.scopedLazySymbol]) return definition;
|
|
39
|
+
if (definition.lazy === void 0) {
|
|
40
|
+
if (typeof definition.render !== "function") throw new require_layout_configuration_error.LayoutConfigurationError(`Scoped content "${label}" requires render or lazy`);
|
|
41
|
+
return definition;
|
|
42
|
+
}
|
|
43
|
+
const Content = require_scoped_content.createScopedLazyContent(definition, resource, label, lazyEnvironment);
|
|
44
|
+
return require_inspection.withLazyHandle({
|
|
45
|
+
...definition,
|
|
46
|
+
lazy: void 0,
|
|
47
|
+
render: (callProps, context) => (0, react.createElement)(Content, {
|
|
48
|
+
callProps,
|
|
49
|
+
context
|
|
50
|
+
}),
|
|
51
|
+
[require_scoped_content.scopedLazySymbol]: Content
|
|
52
|
+
}, Content);
|
|
53
|
+
}
|
|
54
|
+
function aggregateHandle(handles) {
|
|
55
|
+
let imports = [];
|
|
56
|
+
let pending;
|
|
57
|
+
return {
|
|
58
|
+
preload() {
|
|
59
|
+
const next = handles.map((handle) => handle.preload());
|
|
60
|
+
if (!pending || next.some((promise, index) => promise !== imports[index])) {
|
|
61
|
+
imports = next;
|
|
62
|
+
pending = Promise.all(next).then(() => void 0);
|
|
63
|
+
}
|
|
64
|
+
return pending;
|
|
65
|
+
},
|
|
66
|
+
get status() {
|
|
67
|
+
if (handles.some((handle) => handle.status === "error")) return "error";
|
|
68
|
+
if (handles.some((handle) => handle.status === "loading")) return "loading";
|
|
69
|
+
if (handles.some((handle) => handle.status === "unresolved")) return "unresolved";
|
|
70
|
+
return "resolved";
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}
|
|
34
74
|
function mergeCreateComponentProps(...bags) {
|
|
35
75
|
const include = {};
|
|
36
76
|
const custom = {};
|
|
@@ -49,12 +89,15 @@ function createForResources({ createLayoutForResource, createMakeComposableLayou
|
|
|
49
89
|
const include = mergedProps.include ?? {};
|
|
50
90
|
const custom = mergedProps.custom ?? {};
|
|
51
91
|
const selectedResources = new Set(resourceOptions.map(({ resource }) => resource));
|
|
92
|
+
const topLevelContent = new Map([...selectedResources].map((resource) => [resource, normalizeContent(componentOptions, resource, `${resource}:content`)]));
|
|
52
93
|
const componentPropsContext = (0, react.createContext)(void 0);
|
|
53
94
|
const definedEntries = /* @__PURE__ */ new Map();
|
|
54
95
|
for (const [key, entry] of Object.entries(componentOptions.resources ?? {})) {
|
|
55
96
|
const resource = key;
|
|
56
97
|
if (!selectedResources.has(resource)) throw new require_layout_configuration_error.LayoutConfigurationError(`Resource "${key}" is not available in this scoped component`);
|
|
57
|
-
|
|
98
|
+
const normalized = normalizeContent(entry, resource, resource);
|
|
99
|
+
normalized.components = Object.fromEntries(Object.entries(entry.components ?? {}).map(([name, definition]) => [name, normalizeContent(definition, resource, `${resource}.${name}`)]));
|
|
100
|
+
definedEntries.set(resource, normalized);
|
|
58
101
|
}
|
|
59
102
|
/** Resolved scoped components, per resource. */
|
|
60
103
|
const resourceScopedComponents = /* @__PURE__ */ new Map();
|
|
@@ -93,6 +136,7 @@ function createForResources({ createLayoutForResource, createMakeComposableLayou
|
|
|
93
136
|
if (require_scoped_render.isRenderableComponentType(result)) cachedReturnedComponent = result;
|
|
94
137
|
return require_scoped_render.resolveScopedRenderResult(result, resolvedOwnProps);
|
|
95
138
|
}
|
|
139
|
+
if (definition[require_scoped_content.scopedLazySymbol]) require_inspection.withLazyHandle(ScopedComponent, definition[require_scoped_content.scopedLazySymbol]);
|
|
96
140
|
scopedComponents[name] = require_scoped_render.withScopedCompoundStatics(ScopedComponent, (staticName) => {
|
|
97
141
|
function CompoundStatic(ownProps) {
|
|
98
142
|
const componentProps = (0, react.useContext)(componentPropsContext);
|
|
@@ -123,7 +167,7 @@ function createForResources({ createLayoutForResource, createMakeComposableLayou
|
|
|
123
167
|
};
|
|
124
168
|
return require_scoped_render.resolveScopedRenderResult(entry.render(callProps, scopedComponents), ownProps);
|
|
125
169
|
}
|
|
126
|
-
return [contextKey, Object.assign(ResourceRender, scopedComponents)];
|
|
170
|
+
return [contextKey, require_inspection.withLazyHandle(Object.assign(ResourceRender, scopedComponents), aggregateHandle([...entry[require_scoped_content.scopedLazySymbol] ? [entry[require_scoped_content.scopedLazySymbol]] : [], ...Object.values(entry.components ?? {}).flatMap((definition) => definition[require_scoped_content.scopedLazySymbol] ? [definition[require_scoped_content.scopedLazySymbol]] : [])]))];
|
|
127
171
|
}));
|
|
128
172
|
/**
|
|
129
173
|
* Layouts are created once per resource and cached. Creating one during
|
|
@@ -195,7 +239,7 @@ function createForResources({ createLayoutForResource, createMakeComposableLayou
|
|
|
195
239
|
layoutName: definedEntries.get(componentResource)?.name ?? defaultNames.get(componentResource) ?? require_capitalize.capitalize(componentResource),
|
|
196
240
|
resource: componentResource
|
|
197
241
|
});
|
|
198
|
-
return (0, react.createElement)(componentPropsContext.Provider, { value: resolvedComponentProps }, require_scoped_render.resolveScopedRenderResult(
|
|
242
|
+
return (0, react.createElement)(componentPropsContext.Provider, { value: resolvedComponentProps }, require_scoped_render.resolveScopedRenderResult(topLevelContent.get(componentResource).render(resolvedComponentProps, renderContext), resolvedComponentProps));
|
|
199
243
|
}
|
|
200
244
|
/**
|
|
201
245
|
* Bound components are created once per resource and cached. Returning a
|
|
@@ -215,6 +259,13 @@ function createForResources({ createLayoutForResource, createMakeComposableLayou
|
|
|
215
259
|
props: void 0,
|
|
216
260
|
resource: void 0
|
|
217
261
|
}, resourceScopedComponents.get(resource) ?? {});
|
|
262
|
+
if (createMakeComposableLayout) Object.assign(boundComponent, { makeComposable: (options = {}) => scopedExtras.makeComposable?.({
|
|
263
|
+
...options,
|
|
264
|
+
resource
|
|
265
|
+
}) });
|
|
266
|
+
const renderResource = renderContext[require_capitalize.capitalize(resource)];
|
|
267
|
+
const ownContent = topLevelContent.get(resource)?.[require_scoped_content.scopedLazySymbol];
|
|
268
|
+
require_inspection.withLazyHandle(boundComponent, aggregateHandle([...renderResource ? [renderResource] : [], ...ownContent ? [ownContent] : []]));
|
|
218
269
|
boundComponents.set(resource, boundComponent);
|
|
219
270
|
}
|
|
220
271
|
return boundComponent;
|
|
@@ -222,6 +273,7 @@ function createForResources({ createLayoutForResource, createMakeComposableLayou
|
|
|
222
273
|
function asHOF() {
|
|
223
274
|
return bindResource;
|
|
224
275
|
}
|
|
276
|
+
require_inspection.withLazyHandle(Component, aggregateHandle([...Object.values(renderContext).filter((value) => "preload" in value), ...[...topLevelContent.values()].flatMap((entry) => entry[require_scoped_content.scopedLazySymbol] ? [entry[require_scoped_content.scopedLazySymbol]] : [])]));
|
|
225
277
|
return Object.assign(Component, {
|
|
226
278
|
asHOF,
|
|
227
279
|
displayName: "ScopedResourceComponent",
|
|
@@ -241,10 +293,13 @@ function createForResources({ createLayoutForResource, createMakeComposableLayou
|
|
|
241
293
|
function createResourceComponents(options) {
|
|
242
294
|
const { resource, props, ...entry } = options;
|
|
243
295
|
if (!resourceOptions.some((resourceOption) => resourceOption.resource === resource)) throw new require_layout_configuration_error.LayoutConfigurationError(`Resource "${resource}" is not available in this scoped component`);
|
|
244
|
-
|
|
245
|
-
|
|
296
|
+
const normalized = normalizeContent(entry, resource, String(resource));
|
|
297
|
+
const components = Object.fromEntries(Object.entries(normalized.components ?? {}).map(([name, definition]) => [name, normalizeContent(definition, resource, `${resource}.${name}`)]));
|
|
298
|
+
return require_inspection.withLazyHandle({
|
|
299
|
+
...normalized,
|
|
300
|
+
components,
|
|
246
301
|
props: props ?? {}
|
|
247
|
-
};
|
|
302
|
+
}, aggregateHandle([...normalized[require_scoped_content.scopedLazySymbol] ? [normalized[require_scoped_content.scopedLazySymbol]] : [], ...Object.values(components).flatMap((definition) => definition[require_scoped_content.scopedLazySymbol] ? [definition[require_scoped_content.scopedLazySymbol]] : [])]));
|
|
248
303
|
}
|
|
249
304
|
Object.assign(createComponent, { setProps: createComponentSetProps });
|
|
250
305
|
const scopedExtras = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-for-resources.cjs","names":["capitalize","LayoutConfigurationError","reservedScopedComponentNames","isRenderableComponentType","resolveScopedRenderResult","withScopedCompoundStatics"],"sources":["../../../src/create-config/for-resources/create-for-resources.ts"],"sourcesContent":["import {\n createContext,\n createElement,\n type ComponentType,\n type JSX,\n useContext,\n} from 'react';\nimport type { ComposableComponents } from '@jfdevelops/react-layout-composables';\nimport {\n type AnyBuiltPropDefinition,\n validateProps,\n} from '@jfdevelops/react-layout-validator';\nimport type { InPropsDefinition, InPropsObject } from '../../props';\nimport type { LayoutResourceKey, ResourceDefinition } from '../../resource';\nimport { capitalize } from '../../utils/capitalize';\nimport { LayoutConfigurationError } from '../../errors';\nimport type { LayoutIncludeProps } from '../define-layout';\nimport type {\n CapitalizedResource,\n ResourcesLayoutName,\n} from './resource-selection';\nimport type { CreateResourceLayoutForResourcesFn } from './scoped-layout';\nimport {\n isRenderableComponentType,\n reservedScopedComponentNames,\n resolveScopedRenderResult,\n type ScopedRenderResult,\n withScopedCompoundStatics,\n} from './scoped-render';\n\ntype CreateForResourcesOptions<\n Resources extends ReadonlyArray<ResourceDefinition>,\n> = {\n createLayoutForResource: (\n defaultName: string | undefined,\n resource: LayoutResourceKey<Resources>,\n ) => unknown;\n createMakeComposableLayout?: () => (\n options: Record<string, unknown>,\n ) => unknown;\n createResourceLayout: (options: Record<string, unknown>) => unknown;\n getComponentPropDefinitions: (\n resource: LayoutResourceKey<Resources>,\n ) => Record<string, AnyBuiltPropDefinition>;\n};\n\nexport function createForResources<\n Resources extends ReadonlyArray<ResourceDefinition>,\n InProps extends InPropsDefinition<Resources>,\n Composables extends ComposableComponents,\n IncludeProps extends LayoutIncludeProps<Resources, InProps, Composables>,\n CustomProps extends InPropsObject,\n>({\n createLayoutForResource,\n createMakeComposableLayout,\n createResourceLayout,\n getComponentPropDefinitions,\n}: CreateForResourcesOptions<Resources>) {\n return ((...resourcesOrOptions: Array<unknown>) => {\n const firstArgument = resourcesOrOptions[0];\n let resourceOptions: Array<{\n resource: LayoutResourceKey<Resources>;\n name?:\n | string\n | ((\n resource: CapitalizedResource<LayoutResourceKey<Resources>>,\n ) => string);\n }>;\n\n if (typeof firstArgument === 'string') {\n resourceOptions = resourcesOrOptions.map((resource) => ({\n resource: resource as LayoutResourceKey<Resources>,\n }));\n } else if (\n firstArgument !== null &&\n typeof firstArgument === 'object' &&\n 'resources' in firstArgument &&\n Array.isArray(firstArgument.resources)\n ) {\n const { name, resources } = firstArgument as {\n name?: ResourcesLayoutName<LayoutResourceKey<Resources>>;\n resources: Array<LayoutResourceKey<Resources>>;\n };\n resourceOptions = resources.map((resource) => ({\n name: typeof name === 'function' ? name : name?.[resource],\n resource,\n }));\n } else {\n resourceOptions = Object.entries(firstArgument ?? {}).map(\n ([resource, options]) => ({\n ...(options as {\n name?:\n | string\n | ((\n resource: CapitalizedResource<LayoutResourceKey<Resources>>,\n ) => string);\n }),\n resource: resource as LayoutResourceKey<Resources>,\n }),\n );\n }\n\n const defaultNames = new Map(\n resourceOptions.map(({ name, resource }) => [\n resource,\n typeof name === 'function'\n ? name(\n capitalize(resource) as CapitalizedResource<\n LayoutResourceKey<Resources>\n >,\n )\n : name,\n ]),\n );\n\n function scopedCreateResourceLayout(options: Record<string, unknown>) {\n const resource = options.resource as LayoutResourceKey<Resources>;\n\n return createResourceLayout({\n ...options,\n name: options.name ?? defaultNames.get(resource),\n });\n }\n\n function scopedForResource(options: {\n name?: string;\n resource: LayoutResourceKey<Resources>;\n }) {\n return createLayoutForResource(\n options.name ?? defaultNames.get(options.resource),\n options.resource,\n );\n }\n\n type ScopedComponentRenderFn = (\n props: Record<string, unknown>,\n components: Record<string, (props?: never) => JSX.Element>,\n ) => ScopedRenderResult;\n\n type ScopedResourceScopedComponentDefinition = {\n props?: Record<string, AnyBuiltPropDefinition>;\n render: ScopedComponentRenderFn;\n };\n\n type ScopedComponentEntry = {\n [option: string]: unknown;\n name?: string;\n props?: CreateComponentPropsBag;\n components?: Record<string, ScopedResourceScopedComponentDefinition>;\n render: ScopedComponentRenderFn;\n };\n\n type CreateComponentPropsBag = {\n include?: Record<string, true | 'optional'>;\n custom?: Record<string, AnyBuiltPropDefinition>;\n defined?: Record<string, unknown>;\n };\n\n function mergeCreateComponentProps(\n ...bags: Array<CreateComponentPropsBag | undefined>\n ): CreateComponentPropsBag {\n const include: Record<string, true | 'optional'> = {};\n const custom: Record<string, AnyBuiltPropDefinition> = {};\n\n for (const bag of bags) {\n Object.assign(include, bag?.include);\n Object.assign(custom, bag?.custom);\n\n for (const key of Object.keys(bag?.defined ?? {})) {\n include[key] = true;\n }\n }\n\n return { include, custom };\n }\n\n function createComponent(componentOptions: {\n props?: {\n include?: Record<string, true | 'optional'>;\n custom?: Record<string, AnyBuiltPropDefinition>;\n };\n resources?: Record<string, ScopedComponentEntry>;\n render: (\n props: Record<string, unknown>,\n context: Record<string, (props: never) => JSX.Element>,\n ) => ScopedRenderResult;\n }) {\n const mergedProps = mergeCreateComponentProps(\n componentOptions.props,\n ...Object.values(componentOptions.resources ?? {}).map(\n (entry) => entry.props,\n ),\n );\n const include = mergedProps.include ?? {};\n const custom = mergedProps.custom ?? {};\n const selectedResources = new Set(\n resourceOptions.map(({ resource }) => resource),\n );\n const componentPropsContext = createContext<\n Record<string, unknown> | undefined\n >(undefined);\n const definedEntries = new Map<\n LayoutResourceKey<Resources>,\n ScopedComponentEntry\n >();\n\n for (const [key, entry] of Object.entries(\n componentOptions.resources ?? {},\n )) {\n const resource = key as LayoutResourceKey<Resources>;\n\n if (!selectedResources.has(resource)) {\n throw new LayoutConfigurationError(\n `Resource \"${key}\" is not available in this scoped component`,\n );\n }\n\n definedEntries.set(resource, entry);\n }\n\n /** Resolved scoped components, per resource. */\n const resourceScopedComponents = new Map<\n LayoutResourceKey<Resources>,\n Record<string, (props?: never) => JSX.Element>\n >();\n const contextResources = new Map<string, LayoutResourceKey<Resources>>();\n const renderContext: Record<string, (props: never) => JSX.Element> =\n Object.fromEntries(\n [...definedEntries].map(([resource, entry]) => {\n const contextKey = capitalize(resource);\n\n if (contextKey === 'Root') {\n throw new LayoutConfigurationError(\n `Resource \"${resource}\" maps to the reserved render context key \"Root\"`,\n );\n }\n\n const existingResource = contextResources.get(contextKey);\n\n if (existingResource !== undefined) {\n throw new LayoutConfigurationError(\n `Resources \"${existingResource}\" and \"${resource}\" both map to render context key \"${contextKey}\"`,\n );\n }\n\n contextResources.set(contextKey, resource);\n\n /**\n * Built once per resource so every scoped component keeps a stable\n * identity, and shared by the resource render, the render context,\n * and any component bound through `asHOF()`.\n */\n const scopedComponents: Record<\n string,\n (props?: never) => JSX.Element\n > = {};\n\n for (const [name, definition] of Object.entries(\n entry.components ?? {},\n )) {\n if (reservedScopedComponentNames.has(name)) {\n throw new LayoutConfigurationError(\n `Scoped component \"${name}\" for resource \"${resource}\" uses a reserved name`,\n );\n }\n\n const ownPropDefinitions = definition.props ?? {};\n // Last call-site own-props / returned component for this scoped\n // entry. Compound statics re-run `render` with these so\n // `<DataTable variant=\"b\" />` then `<DataTable.Loading />` sees \"b\".\n let cachedOwnProps: Record<string, unknown> = {};\n let cachedReturnedComponent:\n | ComponentType<Record<string, unknown>>\n | undefined;\n\n function ScopedComponent(ownProps?: Record<string, unknown>) {\n const componentProps = useContext(componentPropsContext);\n\n if (componentProps === undefined) {\n throw new LayoutConfigurationError(\n `Scoped component \"${name}\" must be rendered inside its scoped component`,\n );\n }\n\n const resolvedOwnProps = ownProps ?? {};\n cachedOwnProps = resolvedOwnProps;\n\n validateProps(ownPropDefinitions, resolvedOwnProps, {\n layoutName:\n entry.name ??\n defaultNames.get(resource) ??\n capitalize(resource),\n resource,\n });\n\n // Mount a returned component type with call-site props; pass\n // nodes (elements, portals, null) through unchanged.\n const result = definition.render(\n { ...componentProps, ...resolvedOwnProps, resource },\n scopedComponents,\n );\n\n if (isRenderableComponentType(result)) {\n cachedReturnedComponent = result as ComponentType<\n Record<string, unknown>\n >;\n }\n\n return resolveScopedRenderResult(result, resolvedOwnProps);\n }\n\n // Types expose compound statics from the returned component\n // (`DataTable.Loading`); attach matching runtime wrappers.\n scopedComponents[name] = withScopedCompoundStatics(\n ScopedComponent,\n (staticName) => {\n function CompoundStatic(ownProps?: Record<string, unknown>) {\n const componentProps = useContext(componentPropsContext);\n\n if (componentProps === undefined) {\n throw new LayoutConfigurationError(\n `Scoped component \"${name}.${staticName}\" must be rendered inside its scoped component`,\n );\n }\n\n // Prefer the component from the last parent call (same\n // closure as that call's own-props). Fall back to re-running\n // render with cached parent props when needed.\n let result: unknown = cachedReturnedComponent;\n\n if (!isRenderableComponentType(result)) {\n result = definition.render(\n {\n ...componentProps,\n ...cachedOwnProps,\n resource,\n },\n scopedComponents,\n );\n }\n\n if (!isRenderableComponentType(result)) {\n throw new LayoutConfigurationError(\n `Scoped component \"${name}\" must return a component type to use static \"${staticName}\"`,\n );\n }\n\n const staticComponent = (\n result as ComponentType<Record<string, unknown>> &\n Record<string, unknown>\n )[staticName];\n\n if (!isRenderableComponentType(staticComponent)) {\n throw new LayoutConfigurationError(\n `Scoped component \"${name}\" has no component static \"${staticName}\"`,\n );\n }\n\n // Loading's props — those mount the static itself.\n return createElement(staticComponent, ownProps ?? {});\n }\n\n CompoundStatic.displayName = `${name}.${staticName}`;\n return CompoundStatic;\n },\n ) as (props?: never) => JSX.Element;\n }\n\n resourceScopedComponents.set(resource, scopedComponents);\n\n function ResourceRender(ownProps?: Record<string, unknown>) {\n const componentProps = useContext(componentPropsContext);\n\n if (componentProps === undefined) {\n throw new LayoutConfigurationError(\n `Render context component \"${contextKey}\" must be rendered inside its scoped component`,\n );\n }\n\n // Call-site props on `context.Users({ title, heading })` merge into\n // the resource render props and mount a returned component type.\n const callProps = { ...componentProps, ...ownProps, resource };\n return resolveScopedRenderResult(\n entry.render(callProps, scopedComponents),\n ownProps,\n );\n }\n\n return [\n contextKey,\n Object.assign(ResourceRender, scopedComponents),\n ];\n }),\n );\n\n /**\n * Layouts are created once per resource and cached. Creating one during\n * render would hand React a new component type on every pass, remounting\n * the whole subtree.\n */\n const roots = new Map<\n LayoutResourceKey<Resources>,\n (props: Record<string, unknown>) => JSX.Element\n >();\n\n function Root(rootProps: Record<string, unknown>) {\n const componentProps = useContext(componentPropsContext);\n\n if (componentProps === undefined) {\n throw new LayoutConfigurationError(\n 'Render context component \"Root\" must be rendered inside its scoped component',\n );\n }\n\n const resource =\n componentProps.resource as LayoutResourceKey<Resources>;\n let root = roots.get(resource);\n\n if (root === undefined) {\n const entry = definedEntries.get(resource);\n\n if (entry === undefined) {\n throw new LayoutConfigurationError(\n `Render context component \"Root\" requires a \"resources.${resource}\" entry to build the layout for resource \"${resource}\"`,\n );\n }\n\n // Layout option values come from the outer component call site\n // (`<Directory title=\"…\" />`), not from the resource entry.\n const availableDefinitions =\n getComponentPropDefinitions(resource);\n const layoutOptions: Record<string, unknown> = {};\n const defined = entry.props?.defined ?? {};\n\n for (const key of Object.keys(availableDefinitions)) {\n if (key in defined) {\n layoutOptions[key] = defined[key];\n }\n\n const capitalized = capitalize(key);\n if (capitalized in defined) {\n layoutOptions[capitalized] = defined[capitalized];\n }\n\n if (key in componentProps) {\n layoutOptions[key] = componentProps[key];\n }\n\n if (capitalized in componentProps) {\n layoutOptions[capitalized] = componentProps[capitalized];\n }\n }\n\n root = scopedCreateResourceLayout({\n ...layoutOptions,\n namespace: false,\n name:\n entry.name ??\n defaultNames.get(resource) ??\n capitalize(resource),\n resource,\n }) as (props: Record<string, unknown>) => JSX.Element;\n roots.set(resource, root);\n }\n\n const entry = definedEntries.get(resource);\n const definedCustom: Record<string, unknown> = {};\n const forwardedRootProps: Record<string, unknown> = {};\n\n for (const key of Object.keys(getComponentPropDefinitions(resource))) {\n if (key in componentProps) {\n forwardedRootProps[key] = componentProps[key];\n }\n\n const capitalized = capitalize(key);\n if (capitalized in componentProps) {\n forwardedRootProps[capitalized] = componentProps[capitalized];\n }\n }\n\n for (const [key, value] of Object.entries(\n entry?.props?.defined ?? {},\n )) {\n if (key in custom) {\n definedCustom[key] = value;\n }\n }\n\n return createElement(root, {\n ...forwardedRootProps,\n ...definedCustom,\n ...rootProps,\n });\n }\n\n renderContext.Root = Root;\n\n function Component(componentProps: Record<string, unknown>) {\n const componentResource =\n componentProps.resource as LayoutResourceKey<Resources>;\n\n if (!selectedResources.has(componentResource)) {\n throw new LayoutConfigurationError(\n `Resource \"${componentResource}\" is not available in this scoped component`,\n );\n }\n\n const defined =\n definedEntries.get(componentResource)?.props?.defined ?? {};\n const resolvedComponentProps = { ...defined, ...componentProps };\n const availableDefinitions =\n getComponentPropDefinitions(componentResource);\n const definitionsToValidate: Record<string, AnyBuiltPropDefinition> =\n {};\n\n for (const [key, inclusion] of Object.entries(include)) {\n const definition = availableDefinitions[key];\n\n if (!definition) {\n continue;\n }\n\n // Keep declared keys as-is — do not capitalize JSX.Element props.\n if (inclusion === true || key in resolvedComponentProps) {\n definitionsToValidate[key] = definition;\n }\n }\n\n for (const [key, definition] of Object.entries(custom)) {\n if (key === 'children' || key === 'resource') {\n continue;\n }\n\n definitionsToValidate[key] = definition;\n }\n\n validateProps(definitionsToValidate, resolvedComponentProps, {\n layoutName:\n definedEntries.get(componentResource)?.name ??\n defaultNames.get(componentResource) ??\n capitalize(componentResource),\n resource: componentResource,\n });\n\n // Top-level render may return a component type; mount it with the full\n // component props (include/custom + inferred return-type props).\n return createElement(\n componentPropsContext.Provider,\n { value: resolvedComponentProps },\n resolveScopedRenderResult(\n componentOptions.render(resolvedComponentProps, renderContext),\n resolvedComponentProps,\n ),\n );\n }\n\n /**\n * Bound components are created once per resource and cached. Returning a\n * fresh component from the factory would hand React a new component type\n * whenever the caller rebinds, remounting the subtree.\n */\n const boundComponents = new Map<\n LayoutResourceKey<Resources>,\n (props: Record<string, unknown>) => JSX.Element\n >();\n\n function bindResource(resource: LayoutResourceKey<Resources>) {\n if (!selectedResources.has(resource)) {\n throw new LayoutConfigurationError(\n `Resource \"${resource}\" is not available in this scoped component`,\n );\n }\n\n let boundComponent = boundComponents.get(resource);\n\n if (boundComponent === undefined) {\n boundComponent = Object.assign(\n (boundProps: Record<string, unknown>) =>\n createElement(Component, { ...boundProps, resource }),\n {\n displayName: `ScopedResourceComponent(${resource})`,\n props: undefined,\n resource: undefined,\n },\n resourceScopedComponents.get(resource) ?? {},\n );\n boundComponents.set(resource, boundComponent);\n }\n\n return boundComponent;\n }\n\n function asHOF() {\n return bindResource;\n }\n\n return Object.assign(Component, {\n asHOF,\n displayName: 'ScopedResourceComponent',\n props: undefined,\n });\n }\n\n function createComponentSetProps(baseProps: CreateComponentPropsBag) {\n function createWithProps(componentOptions: {\n props?: CreateComponentPropsBag;\n resources?: Record<string, ScopedComponentEntry>;\n render: (\n props: Record<string, unknown>,\n context: Record<string, (props: never) => JSX.Element>,\n ) => ScopedRenderResult;\n }) {\n return createComponent({\n ...componentOptions,\n props: mergeCreateComponentProps(baseProps, componentOptions.props),\n });\n }\n\n createWithProps.createResourceComponents = createResourceComponents;\n\n return createWithProps;\n }\n\n function createResourceComponents(options: {\n resource: LayoutResourceKey<Resources>;\n props?: CreateComponentPropsBag;\n name?: string;\n components?: Record<string, ScopedResourceScopedComponentDefinition>;\n render: ScopedComponentRenderFn;\n }) {\n const { resource, props, ...entry } = options;\n\n if (\n !resourceOptions.some(\n (resourceOption) => resourceOption.resource === resource,\n )\n ) {\n throw new LayoutConfigurationError(\n `Resource \"${resource}\" is not available in this scoped component`,\n );\n }\n\n return { ...entry, props: props ?? {} };\n }\n\n Object.assign(createComponent, {\n setProps: createComponentSetProps,\n });\n\n const scopedExtras: {\n createComponent: typeof createComponent;\n createResourceComponents: typeof createResourceComponents;\n forResource: typeof scopedForResource;\n makeComposable?: (options: Record<string, unknown>) => unknown;\n resources: undefined;\n } = {\n createComponent,\n createResourceComponents,\n forResource: scopedForResource,\n resources: undefined,\n };\n\n if (createMakeComposableLayout) {\n const makeComposableLayout = createMakeComposableLayout();\n\n scopedExtras.makeComposable = (options) => {\n const resource = options.resource as LayoutResourceKey<Resources>;\n\n return makeComposableLayout({\n ...options,\n name: options.name ?? defaultNames.get(resource),\n });\n };\n }\n\n return Object.assign(scopedCreateResourceLayout, scopedExtras);\n }) as unknown as CreateResourceLayoutForResourcesFn<\n Resources,\n InProps,\n Composables,\n IncludeProps,\n CustomProps\n >;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"create-for-resources.cjs","names":["capitalize","LayoutConfigurationError","scopedLazySymbol","createScopedLazyContent","withLazyHandle","reservedScopedComponentNames","isRenderableComponentType","resolveScopedRenderResult","withScopedCompoundStatics"],"sources":["../../../src/create-config/for-resources/create-for-resources.ts"],"sourcesContent":["import {\n createScopedLazyContent,\n scopedLazySymbol,\n type LazyEnvironment,\n type ScopedLazyContent,\n} from '../../lazy/scoped-content';\nimport { withLazyHandle } from '../../lazy/inspection';\nimport type { LazyHandle } from '../../lazy/types';\nimport {\n createContext,\n createElement,\n type ComponentType,\n type JSX,\n useContext,\n} from 'react';\nimport type { ComposableComponents } from '@jfdevelops/react-layout-composables';\nimport {\n type AnyBuiltPropDefinition,\n validateProps,\n} from '@jfdevelops/react-layout-validator';\nimport type { InPropsDefinition, InPropsObject } from '../../props';\nimport type { LayoutResourceKey, ResourceDefinition } from '../../resource';\nimport { capitalize } from '../../utils/capitalize';\nimport { LayoutConfigurationError } from '../../errors';\nimport type { LayoutIncludeProps } from '../define-layout';\nimport type {\n CapitalizedResource,\n ResourcesLayoutName,\n} from './resource-selection';\nimport type { CreateResourceLayoutForResourcesFn } from './scoped-layout';\nimport {\n isRenderableComponentType,\n reservedScopedComponentNames,\n resolveScopedRenderResult,\n type ScopedRenderResult,\n withScopedCompoundStatics,\n} from './scoped-render';\n\ntype CreateForResourcesOptions<\n Resources extends ReadonlyArray<ResourceDefinition>,\n> = {\n lazyEnvironment?: LazyEnvironment;\n createLayoutForResource: (\n defaultName: string | undefined,\n resource: LayoutResourceKey<Resources>,\n ) => unknown;\n createMakeComposableLayout?: () => (\n options: Record<string, unknown>,\n ) => unknown;\n createResourceLayout: (options: Record<string, unknown>) => unknown;\n getComponentPropDefinitions: (\n resource: LayoutResourceKey<Resources>,\n ) => Record<string, AnyBuiltPropDefinition>;\n};\n\nexport function createForResources<\n Resources extends ReadonlyArray<ResourceDefinition>,\n InProps extends InPropsDefinition<Resources>,\n Composables extends ComposableComponents,\n IncludeProps extends LayoutIncludeProps<Resources, InProps, Composables>,\n CustomProps extends InPropsObject,\n>({\n createLayoutForResource,\n createMakeComposableLayout,\n createResourceLayout,\n getComponentPropDefinitions,\n lazyEnvironment,\n}: CreateForResourcesOptions<Resources>) {\n return ((...resourcesOrOptions: Array<unknown>) => {\n const firstArgument = resourcesOrOptions[0];\n let resourceOptions: Array<{\n resource: LayoutResourceKey<Resources>;\n name?:\n | string\n | ((\n resource: CapitalizedResource<LayoutResourceKey<Resources>>,\n ) => string);\n }>;\n\n if (typeof firstArgument === 'string') {\n resourceOptions = resourcesOrOptions.map((resource) => ({\n resource: resource as LayoutResourceKey<Resources>,\n }));\n } else if (\n firstArgument !== null &&\n typeof firstArgument === 'object' &&\n 'resources' in firstArgument &&\n Array.isArray(firstArgument.resources)\n ) {\n const { name, resources } = firstArgument as {\n name?: ResourcesLayoutName<LayoutResourceKey<Resources>>;\n resources: Array<LayoutResourceKey<Resources>>;\n };\n resourceOptions = resources.map((resource) => ({\n name: typeof name === 'function' ? name : name?.[resource],\n resource,\n }));\n } else {\n resourceOptions = Object.entries(firstArgument ?? {}).map(\n ([resource, options]) => ({\n ...(options as {\n name?:\n | string\n | ((\n resource: CapitalizedResource<LayoutResourceKey<Resources>>,\n ) => string);\n }),\n resource: resource as LayoutResourceKey<Resources>,\n }),\n );\n }\n\n const defaultNames = new Map(\n resourceOptions.map(({ name, resource }) => [\n resource,\n typeof name === 'function'\n ? name(\n capitalize(resource) as CapitalizedResource<\n LayoutResourceKey<Resources>\n >,\n )\n : name,\n ]),\n );\n\n function scopedCreateResourceLayout(options: Record<string, unknown>) {\n const resource = options.resource as LayoutResourceKey<Resources>;\n\n return createResourceLayout({\n ...options,\n name: options.name ?? defaultNames.get(resource),\n });\n }\n\n function scopedForResource(options: {\n name?: string;\n resource: LayoutResourceKey<Resources>;\n }) {\n return createLayoutForResource(\n options.name ?? defaultNames.get(options.resource),\n options.resource,\n );\n }\n\n type ScopedComponentRenderFn = (\n props: Record<string, unknown>,\n components: Record<string, (props?: never) => JSX.Element>,\n ) => ScopedRenderResult;\n\n type ScopedResourceScopedComponentDefinition = {\n props?: Record<string, AnyBuiltPropDefinition>;\n [scopedLazySymbol]?: LazyHandle;\n } & ScopedLazyContent<ScopedComponentRenderFn>;\n\n type ScopedComponentEntry = {\n [option: string]: unknown;\n name?: string;\n props?: CreateComponentPropsBag;\n components?: Record<string, ScopedResourceScopedComponentDefinition>;\n render: ScopedComponentRenderFn;\n [scopedLazySymbol]?: LazyHandle;\n };\n\n type CreateComponentPropsBag = {\n include?: Record<string, true | 'optional'>;\n custom?: Record<string, AnyBuiltPropDefinition>;\n defined?: Record<string, unknown>;\n };\n\n function normalizeContent<\n T extends {\n render?: ScopedComponentRenderFn;\n lazy?: unknown;\n fallback?: React.ReactNode;\n [scopedLazySymbol]?: LazyHandle;\n },\n >(\n definition: T,\n resource: string,\n label: string,\n ): T & {\n render: ScopedComponentRenderFn;\n [scopedLazySymbol]?: LazyHandle;\n } {\n if (definition.lazy !== undefined && definition.render !== undefined)\n throw new LayoutConfigurationError(\n `Scoped content \"${label}\" must define render or lazy, never both`,\n );\n if (definition[scopedLazySymbol])\n return definition as T & {\n render: ScopedComponentRenderFn;\n [scopedLazySymbol]?: LazyHandle;\n };\n if (definition.lazy === undefined) {\n if (typeof definition.render !== 'function')\n throw new LayoutConfigurationError(\n `Scoped content \"${label}\" requires render or lazy`,\n );\n return definition as T & {\n render: ScopedComponentRenderFn;\n [scopedLazySymbol]?: LazyHandle;\n };\n }\n const Content = createScopedLazyContent(\n definition as Parameters<typeof createScopedLazyContent>[0],\n resource,\n label,\n lazyEnvironment,\n );\n const result = {\n ...definition,\n lazy: undefined,\n render: (\n callProps: Record<string, unknown>,\n context: Record<string, (props?: never) => JSX.Element>,\n ) => createElement(Content, { callProps, context }),\n [scopedLazySymbol]: Content,\n };\n return withLazyHandle(result, Content) as T & {\n render: ScopedComponentRenderFn;\n [scopedLazySymbol]?: LazyHandle;\n };\n }\n\n function aggregateHandle(handles: LazyHandle[]): LazyHandle {\n let imports: Promise<void>[] = [];\n let pending: Promise<void> | undefined;\n return {\n preload() {\n const next = handles.map((handle) => handle.preload());\n if (\n !pending ||\n next.some((promise, index) => promise !== imports[index])\n ) {\n imports = next;\n pending = Promise.all(next).then(() => undefined);\n }\n return pending;\n },\n get status() {\n if (handles.some((handle) => handle.status === 'error'))\n return 'error';\n if (handles.some((handle) => handle.status === 'loading'))\n return 'loading';\n if (handles.some((handle) => handle.status === 'unresolved'))\n return 'unresolved';\n return 'resolved';\n },\n };\n }\n\n function mergeCreateComponentProps(\n ...bags: Array<CreateComponentPropsBag | undefined>\n ): CreateComponentPropsBag {\n const include: Record<string, true | 'optional'> = {};\n const custom: Record<string, AnyBuiltPropDefinition> = {};\n\n for (const bag of bags) {\n Object.assign(include, bag?.include);\n Object.assign(custom, bag?.custom);\n\n for (const key of Object.keys(bag?.defined ?? {})) {\n include[key] = true;\n }\n }\n\n return { include, custom };\n }\n\n function createComponent(componentOptions: {\n props?: {\n include?: Record<string, true | 'optional'>;\n custom?: Record<string, AnyBuiltPropDefinition>;\n };\n resources?: Record<string, ScopedComponentEntry>;\n render?: ScopedComponentRenderFn;\n lazy?: Parameters<typeof createScopedLazyContent>[0]['lazy'];\n fallback?: React.ReactNode;\n }) {\n const mergedProps = mergeCreateComponentProps(\n componentOptions.props,\n ...Object.values(componentOptions.resources ?? {}).map(\n (entry) => entry.props,\n ),\n );\n const include = mergedProps.include ?? {};\n const custom = mergedProps.custom ?? {};\n const selectedResources = new Set(\n resourceOptions.map(({ resource }) => resource),\n );\n const topLevelContent = new Map(\n [...selectedResources].map((resource) => [\n resource,\n normalizeContent(componentOptions, resource, `${resource}:content`),\n ]),\n );\n const componentPropsContext = createContext<\n Record<string, unknown> | undefined\n >(undefined);\n const definedEntries = new Map<\n LayoutResourceKey<Resources>,\n ScopedComponentEntry\n >();\n\n for (const [key, entry] of Object.entries(\n componentOptions.resources ?? {},\n )) {\n const resource = key as LayoutResourceKey<Resources>;\n\n if (!selectedResources.has(resource)) {\n throw new LayoutConfigurationError(\n `Resource \"${key}\" is not available in this scoped component`,\n );\n }\n\n const normalized = normalizeContent(entry, resource, resource);\n normalized.components = Object.fromEntries(\n Object.entries(entry.components ?? {}).map(([name, definition]) => [\n name,\n normalizeContent(definition, resource, `${resource}.${name}`),\n ]),\n );\n definedEntries.set(resource, normalized);\n }\n\n /** Resolved scoped components, per resource. */\n const resourceScopedComponents = new Map<\n LayoutResourceKey<Resources>,\n Record<string, (props?: never) => JSX.Element>\n >();\n const contextResources = new Map<string, LayoutResourceKey<Resources>>();\n const renderContext: Record<string, (props: never) => JSX.Element> =\n Object.fromEntries(\n [...definedEntries].map(([resource, entry]) => {\n const contextKey = capitalize(resource);\n\n if (contextKey === 'Root') {\n throw new LayoutConfigurationError(\n `Resource \"${resource}\" maps to the reserved render context key \"Root\"`,\n );\n }\n\n const existingResource = contextResources.get(contextKey);\n\n if (existingResource !== undefined) {\n throw new LayoutConfigurationError(\n `Resources \"${existingResource}\" and \"${resource}\" both map to render context key \"${contextKey}\"`,\n );\n }\n\n contextResources.set(contextKey, resource);\n\n /**\n * Built once per resource so every scoped component keeps a stable\n * identity, and shared by the resource render, the render context,\n * and any component bound through `asHOF()`.\n */\n const scopedComponents: Record<\n string,\n (props?: never) => JSX.Element\n > = {};\n\n for (const [name, definition] of Object.entries(\n entry.components ?? {},\n )) {\n if (reservedScopedComponentNames.has(name)) {\n throw new LayoutConfigurationError(\n `Scoped component \"${name}\" for resource \"${resource}\" uses a reserved name`,\n );\n }\n\n const ownPropDefinitions = definition.props ?? {};\n // Last call-site own-props / returned component for this scoped\n // entry. Compound statics re-run `render` with these so\n // `<DataTable variant=\"b\" />` then `<DataTable.Loading />` sees \"b\".\n let cachedOwnProps: Record<string, unknown> = {};\n let cachedReturnedComponent:\n | ComponentType<Record<string, unknown>>\n | undefined;\n\n function ScopedComponent(ownProps?: Record<string, unknown>) {\n const componentProps = useContext(componentPropsContext);\n\n if (componentProps === undefined) {\n throw new LayoutConfigurationError(\n `Scoped component \"${name}\" must be rendered inside its scoped component`,\n );\n }\n\n const resolvedOwnProps = ownProps ?? {};\n cachedOwnProps = resolvedOwnProps;\n\n validateProps(ownPropDefinitions, resolvedOwnProps, {\n layoutName:\n entry.name ??\n defaultNames.get(resource) ??\n capitalize(resource),\n resource,\n });\n\n // Mount a returned component type with call-site props; pass\n // nodes (elements, portals, null) through unchanged.\n const result = definition.render!(\n { ...componentProps, ...resolvedOwnProps, resource },\n scopedComponents,\n );\n\n if (isRenderableComponentType(result)) {\n cachedReturnedComponent = result as ComponentType<\n Record<string, unknown>\n >;\n }\n\n return resolveScopedRenderResult(result, resolvedOwnProps);\n }\n\n // Types expose compound statics from the returned component\n // (`DataTable.Loading`); attach matching runtime wrappers.\n if (definition[scopedLazySymbol])\n withLazyHandle(ScopedComponent, definition[scopedLazySymbol]);\n scopedComponents[name] = withScopedCompoundStatics(\n ScopedComponent,\n (staticName) => {\n function CompoundStatic(ownProps?: Record<string, unknown>) {\n const componentProps = useContext(componentPropsContext);\n\n if (componentProps === undefined) {\n throw new LayoutConfigurationError(\n `Scoped component \"${name}.${staticName}\" must be rendered inside its scoped component`,\n );\n }\n\n // Prefer the component from the last parent call (same\n // closure as that call's own-props). Fall back to re-running\n // render with cached parent props when needed.\n let result: unknown = cachedReturnedComponent;\n\n if (!isRenderableComponentType(result)) {\n result = definition.render!(\n {\n ...componentProps,\n ...cachedOwnProps,\n resource,\n },\n scopedComponents,\n );\n }\n\n if (!isRenderableComponentType(result)) {\n throw new LayoutConfigurationError(\n `Scoped component \"${name}\" must return a component type to use static \"${staticName}\"`,\n );\n }\n\n const staticComponent = (\n result as ComponentType<Record<string, unknown>> &\n Record<string, unknown>\n )[staticName];\n\n if (!isRenderableComponentType(staticComponent)) {\n throw new LayoutConfigurationError(\n `Scoped component \"${name}\" has no component static \"${staticName}\"`,\n );\n }\n\n // Loading's props — those mount the static itself.\n return createElement(staticComponent, ownProps ?? {});\n }\n\n CompoundStatic.displayName = `${name}.${staticName}`;\n return CompoundStatic;\n },\n ) as (props?: never) => JSX.Element;\n }\n\n resourceScopedComponents.set(resource, scopedComponents);\n\n function ResourceRender(ownProps?: Record<string, unknown>) {\n const componentProps = useContext(componentPropsContext);\n\n if (componentProps === undefined) {\n throw new LayoutConfigurationError(\n `Render context component \"${contextKey}\" must be rendered inside its scoped component`,\n );\n }\n\n // Call-site props on `context.Users({ title, heading })` merge into\n // the resource render props and mount a returned component type.\n const callProps = { ...componentProps, ...ownProps, resource };\n return resolveScopedRenderResult(\n entry.render(callProps, scopedComponents),\n ownProps,\n );\n }\n\n return [\n contextKey,\n withLazyHandle(\n Object.assign(ResourceRender, scopedComponents),\n aggregateHandle([\n ...(entry[scopedLazySymbol] ? [entry[scopedLazySymbol]] : []),\n ...Object.values(entry.components ?? {}).flatMap(\n (definition) =>\n definition[scopedLazySymbol]\n ? [definition[scopedLazySymbol]]\n : [],\n ),\n ]),\n ),\n ];\n }),\n );\n\n /**\n * Layouts are created once per resource and cached. Creating one during\n * render would hand React a new component type on every pass, remounting\n * the whole subtree.\n */\n const roots = new Map<\n LayoutResourceKey<Resources>,\n (props: Record<string, unknown>) => JSX.Element\n >();\n\n function Root(rootProps: Record<string, unknown>) {\n const componentProps = useContext(componentPropsContext);\n\n if (componentProps === undefined) {\n throw new LayoutConfigurationError(\n 'Render context component \"Root\" must be rendered inside its scoped component',\n );\n }\n\n const resource =\n componentProps.resource as LayoutResourceKey<Resources>;\n let root = roots.get(resource);\n\n if (root === undefined) {\n const entry = definedEntries.get(resource);\n\n if (entry === undefined) {\n throw new LayoutConfigurationError(\n `Render context component \"Root\" requires a \"resources.${resource}\" entry to build the layout for resource \"${resource}\"`,\n );\n }\n\n // Layout option values come from the outer component call site\n // (`<Directory title=\"…\" />`), not from the resource entry.\n const availableDefinitions = getComponentPropDefinitions(resource);\n const layoutOptions: Record<string, unknown> = {};\n const defined = entry.props?.defined ?? {};\n\n for (const key of Object.keys(availableDefinitions)) {\n if (key in defined) {\n layoutOptions[key] = defined[key];\n }\n\n const capitalized = capitalize(key);\n if (capitalized in defined) {\n layoutOptions[capitalized] = defined[capitalized];\n }\n\n if (key in componentProps) {\n layoutOptions[key] = componentProps[key];\n }\n\n if (capitalized in componentProps) {\n layoutOptions[capitalized] = componentProps[capitalized];\n }\n }\n\n root = scopedCreateResourceLayout({\n ...layoutOptions,\n namespace: false,\n name:\n entry.name ?? defaultNames.get(resource) ?? capitalize(resource),\n resource,\n }) as (props: Record<string, unknown>) => JSX.Element;\n roots.set(resource, root);\n }\n\n const entry = definedEntries.get(resource);\n const definedCustom: Record<string, unknown> = {};\n const forwardedRootProps: Record<string, unknown> = {};\n\n for (const key of Object.keys(getComponentPropDefinitions(resource))) {\n if (key in componentProps) {\n forwardedRootProps[key] = componentProps[key];\n }\n\n const capitalized = capitalize(key);\n if (capitalized in componentProps) {\n forwardedRootProps[capitalized] = componentProps[capitalized];\n }\n }\n\n for (const [key, value] of Object.entries(\n entry?.props?.defined ?? {},\n )) {\n if (key in custom) {\n definedCustom[key] = value;\n }\n }\n\n return createElement(root, {\n ...forwardedRootProps,\n ...definedCustom,\n ...rootProps,\n });\n }\n\n renderContext.Root = Root;\n\n function Component(componentProps: Record<string, unknown>) {\n const componentResource =\n componentProps.resource as LayoutResourceKey<Resources>;\n\n if (!selectedResources.has(componentResource)) {\n throw new LayoutConfigurationError(\n `Resource \"${componentResource}\" is not available in this scoped component`,\n );\n }\n\n const defined =\n definedEntries.get(componentResource)?.props?.defined ?? {};\n const resolvedComponentProps = { ...defined, ...componentProps };\n const availableDefinitions =\n getComponentPropDefinitions(componentResource);\n const definitionsToValidate: Record<string, AnyBuiltPropDefinition> =\n {};\n\n for (const [key, inclusion] of Object.entries(include)) {\n const definition = availableDefinitions[key];\n\n if (!definition) {\n continue;\n }\n\n // Keep declared keys as-is — do not capitalize JSX.Element props.\n if (inclusion === true || key in resolvedComponentProps) {\n definitionsToValidate[key] = definition;\n }\n }\n\n for (const [key, definition] of Object.entries(custom)) {\n if (key === 'children' || key === 'resource') {\n continue;\n }\n\n definitionsToValidate[key] = definition;\n }\n\n validateProps(definitionsToValidate, resolvedComponentProps, {\n layoutName:\n definedEntries.get(componentResource)?.name ??\n defaultNames.get(componentResource) ??\n capitalize(componentResource),\n resource: componentResource,\n });\n\n // Top-level render may return a component type; mount it with the full\n // component props (include/custom + inferred return-type props).\n return createElement(\n componentPropsContext.Provider,\n { value: resolvedComponentProps },\n resolveScopedRenderResult(\n topLevelContent\n .get(componentResource)!\n .render(\n resolvedComponentProps,\n renderContext as Record<string, (props?: never) => JSX.Element>,\n ),\n resolvedComponentProps,\n ),\n );\n }\n\n /**\n * Bound components are created once per resource and cached. Returning a\n * fresh component from the factory would hand React a new component type\n * whenever the caller rebinds, remounting the subtree.\n */\n const boundComponents = new Map<\n LayoutResourceKey<Resources>,\n (props: Record<string, unknown>) => JSX.Element\n >();\n\n function bindResource(resource: LayoutResourceKey<Resources>) {\n if (!selectedResources.has(resource)) {\n throw new LayoutConfigurationError(\n `Resource \"${resource}\" is not available in this scoped component`,\n );\n }\n\n let boundComponent = boundComponents.get(resource);\n\n if (boundComponent === undefined) {\n boundComponent = Object.assign(\n (boundProps: Record<string, unknown>) =>\n createElement(Component, { ...boundProps, resource }),\n {\n displayName: `ScopedResourceComponent(${resource})`,\n props: undefined,\n resource: undefined,\n },\n resourceScopedComponents.get(resource) ?? {},\n );\n if (createMakeComposableLayout) {\n Object.assign(boundComponent, {\n makeComposable: (options: Record<string, unknown> = {}) =>\n scopedExtras.makeComposable?.({ ...options, resource }),\n });\n }\n const renderResource = renderContext[\n capitalize(resource)\n ] as unknown as LazyHandle;\n const ownContent = topLevelContent.get(resource)?.[scopedLazySymbol];\n withLazyHandle(\n boundComponent,\n aggregateHandle([\n ...(renderResource ? [renderResource] : []),\n ...(ownContent ? [ownContent] : []),\n ]),\n );\n boundComponents.set(resource, boundComponent);\n }\n\n return boundComponent;\n }\n\n function asHOF() {\n return bindResource;\n }\n\n withLazyHandle(\n Component,\n aggregateHandle([\n ...(Object.values(renderContext).filter(\n (value) => 'preload' in value,\n ) as unknown as LazyHandle[]),\n ...[...topLevelContent.values()].flatMap((entry) =>\n entry[scopedLazySymbol] ? [entry[scopedLazySymbol]] : [],\n ),\n ]),\n );\n return Object.assign(Component, {\n asHOF,\n displayName: 'ScopedResourceComponent',\n props: undefined,\n });\n }\n\n function createComponentSetProps(baseProps: CreateComponentPropsBag) {\n function createWithProps(componentOptions: {\n props?: CreateComponentPropsBag;\n resources?: Record<string, ScopedComponentEntry>;\n render: (\n props: Record<string, unknown>,\n context: Record<string, (props: never) => JSX.Element>,\n ) => ScopedRenderResult;\n }) {\n return createComponent({\n ...componentOptions,\n props: mergeCreateComponentProps(baseProps, componentOptions.props),\n });\n }\n\n createWithProps.createResourceComponents = createResourceComponents;\n\n return createWithProps;\n }\n\n function createResourceComponents(options: {\n resource: LayoutResourceKey<Resources>;\n props?: CreateComponentPropsBag;\n name?: string;\n components?: Record<string, ScopedResourceScopedComponentDefinition>;\n render?: ScopedComponentRenderFn;\n lazy?: Parameters<typeof createScopedLazyContent>[0]['lazy'];\n fallback?: React.ReactNode;\n }) {\n const { resource, props, ...entry } = options;\n\n if (\n !resourceOptions.some(\n (resourceOption) => resourceOption.resource === resource,\n )\n ) {\n throw new LayoutConfigurationError(\n `Resource \"${resource}\" is not available in this scoped component`,\n );\n }\n\n const normalized = normalizeContent(entry, resource, String(resource));\n const components = Object.fromEntries(\n Object.entries(normalized.components ?? {}).map(\n ([name, definition]) => [\n name,\n normalizeContent(definition, resource, `${resource}.${name}`),\n ],\n ),\n );\n const result = { ...normalized, components, props: props ?? {} };\n return withLazyHandle(\n result,\n aggregateHandle([\n ...(normalized[scopedLazySymbol]\n ? [normalized[scopedLazySymbol]]\n : []),\n ...Object.values(components).flatMap((definition) =>\n definition[scopedLazySymbol] ? [definition[scopedLazySymbol]] : [],\n ),\n ]),\n );\n }\n\n Object.assign(createComponent, {\n setProps: createComponentSetProps,\n });\n\n const scopedExtras: {\n createComponent: typeof createComponent;\n createResourceComponents: typeof createResourceComponents;\n forResource: typeof scopedForResource;\n makeComposable?: (options: Record<string, unknown>) => unknown;\n resources: undefined;\n } = {\n createComponent,\n createResourceComponents,\n forResource: scopedForResource,\n resources: undefined,\n };\n\n if (createMakeComposableLayout) {\n const makeComposableLayout = createMakeComposableLayout();\n\n scopedExtras.makeComposable = (options) => {\n const resource = options.resource as LayoutResourceKey<Resources>;\n\n return makeComposableLayout({\n ...options,\n name: options.name ?? defaultNames.get(resource),\n });\n };\n }\n\n return Object.assign(scopedCreateResourceLayout, scopedExtras);\n }) as unknown as CreateResourceLayoutForResourcesFn<\n Resources,\n InProps,\n Composables,\n IncludeProps,\n CustomProps\n >;\n}\n"],"mappings":"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"}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { LayoutConfigurationError } from "../../errors/layout-configuration-error.mjs";
|
|
2
2
|
import { capitalize } from "../../utils/capitalize.mjs";
|
|
3
|
+
import { withLazyHandle } from "../../lazy/inspection.mjs";
|
|
3
4
|
import { isRenderableComponentType, reservedScopedComponentNames, resolveScopedRenderResult, withScopedCompoundStatics } from "./scoped-render.mjs";
|
|
5
|
+
import { createScopedLazyContent, scopedLazySymbol } from "../../lazy/scoped-content.mjs";
|
|
4
6
|
import { createContext, createElement, useContext } from "react";
|
|
5
7
|
import { validateProps } from "@jfdevelops/react-layout-validator";
|
|
6
8
|
|
|
7
9
|
//#region src/create-config/for-resources/create-for-resources.ts
|
|
8
|
-
function createForResources({ createLayoutForResource, createMakeComposableLayout, createResourceLayout, getComponentPropDefinitions }) {
|
|
10
|
+
function createForResources({ createLayoutForResource, createMakeComposableLayout, createResourceLayout, getComponentPropDefinitions, lazyEnvironment }) {
|
|
9
11
|
return ((...resourcesOrOptions) => {
|
|
10
12
|
const firstArgument = resourcesOrOptions[0];
|
|
11
13
|
let resourceOptions;
|
|
@@ -31,6 +33,44 @@ function createForResources({ createLayoutForResource, createMakeComposableLayou
|
|
|
31
33
|
function scopedForResource(options) {
|
|
32
34
|
return createLayoutForResource(options.name ?? defaultNames.get(options.resource), options.resource);
|
|
33
35
|
}
|
|
36
|
+
function normalizeContent(definition, resource, label) {
|
|
37
|
+
if (definition.lazy !== void 0 && definition.render !== void 0) throw new LayoutConfigurationError(`Scoped content "${label}" must define render or lazy, never both`);
|
|
38
|
+
if (definition[scopedLazySymbol]) return definition;
|
|
39
|
+
if (definition.lazy === void 0) {
|
|
40
|
+
if (typeof definition.render !== "function") throw new LayoutConfigurationError(`Scoped content "${label}" requires render or lazy`);
|
|
41
|
+
return definition;
|
|
42
|
+
}
|
|
43
|
+
const Content = createScopedLazyContent(definition, resource, label, lazyEnvironment);
|
|
44
|
+
return withLazyHandle({
|
|
45
|
+
...definition,
|
|
46
|
+
lazy: void 0,
|
|
47
|
+
render: (callProps, context) => createElement(Content, {
|
|
48
|
+
callProps,
|
|
49
|
+
context
|
|
50
|
+
}),
|
|
51
|
+
[scopedLazySymbol]: Content
|
|
52
|
+
}, Content);
|
|
53
|
+
}
|
|
54
|
+
function aggregateHandle(handles) {
|
|
55
|
+
let imports = [];
|
|
56
|
+
let pending;
|
|
57
|
+
return {
|
|
58
|
+
preload() {
|
|
59
|
+
const next = handles.map((handle) => handle.preload());
|
|
60
|
+
if (!pending || next.some((promise, index) => promise !== imports[index])) {
|
|
61
|
+
imports = next;
|
|
62
|
+
pending = Promise.all(next).then(() => void 0);
|
|
63
|
+
}
|
|
64
|
+
return pending;
|
|
65
|
+
},
|
|
66
|
+
get status() {
|
|
67
|
+
if (handles.some((handle) => handle.status === "error")) return "error";
|
|
68
|
+
if (handles.some((handle) => handle.status === "loading")) return "loading";
|
|
69
|
+
if (handles.some((handle) => handle.status === "unresolved")) return "unresolved";
|
|
70
|
+
return "resolved";
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}
|
|
34
74
|
function mergeCreateComponentProps(...bags) {
|
|
35
75
|
const include = {};
|
|
36
76
|
const custom = {};
|
|
@@ -49,12 +89,15 @@ function createForResources({ createLayoutForResource, createMakeComposableLayou
|
|
|
49
89
|
const include = mergedProps.include ?? {};
|
|
50
90
|
const custom = mergedProps.custom ?? {};
|
|
51
91
|
const selectedResources = new Set(resourceOptions.map(({ resource }) => resource));
|
|
92
|
+
const topLevelContent = new Map([...selectedResources].map((resource) => [resource, normalizeContent(componentOptions, resource, `${resource}:content`)]));
|
|
52
93
|
const componentPropsContext = createContext(void 0);
|
|
53
94
|
const definedEntries = /* @__PURE__ */ new Map();
|
|
54
95
|
for (const [key, entry] of Object.entries(componentOptions.resources ?? {})) {
|
|
55
96
|
const resource = key;
|
|
56
97
|
if (!selectedResources.has(resource)) throw new LayoutConfigurationError(`Resource "${key}" is not available in this scoped component`);
|
|
57
|
-
|
|
98
|
+
const normalized = normalizeContent(entry, resource, resource);
|
|
99
|
+
normalized.components = Object.fromEntries(Object.entries(entry.components ?? {}).map(([name, definition]) => [name, normalizeContent(definition, resource, `${resource}.${name}`)]));
|
|
100
|
+
definedEntries.set(resource, normalized);
|
|
58
101
|
}
|
|
59
102
|
/** Resolved scoped components, per resource. */
|
|
60
103
|
const resourceScopedComponents = /* @__PURE__ */ new Map();
|
|
@@ -93,6 +136,7 @@ function createForResources({ createLayoutForResource, createMakeComposableLayou
|
|
|
93
136
|
if (isRenderableComponentType(result)) cachedReturnedComponent = result;
|
|
94
137
|
return resolveScopedRenderResult(result, resolvedOwnProps);
|
|
95
138
|
}
|
|
139
|
+
if (definition[scopedLazySymbol]) withLazyHandle(ScopedComponent, definition[scopedLazySymbol]);
|
|
96
140
|
scopedComponents[name] = withScopedCompoundStatics(ScopedComponent, (staticName) => {
|
|
97
141
|
function CompoundStatic(ownProps) {
|
|
98
142
|
const componentProps = useContext(componentPropsContext);
|
|
@@ -123,7 +167,7 @@ function createForResources({ createLayoutForResource, createMakeComposableLayou
|
|
|
123
167
|
};
|
|
124
168
|
return resolveScopedRenderResult(entry.render(callProps, scopedComponents), ownProps);
|
|
125
169
|
}
|
|
126
|
-
return [contextKey, Object.assign(ResourceRender, scopedComponents)];
|
|
170
|
+
return [contextKey, withLazyHandle(Object.assign(ResourceRender, scopedComponents), aggregateHandle([...entry[scopedLazySymbol] ? [entry[scopedLazySymbol]] : [], ...Object.values(entry.components ?? {}).flatMap((definition) => definition[scopedLazySymbol] ? [definition[scopedLazySymbol]] : [])]))];
|
|
127
171
|
}));
|
|
128
172
|
/**
|
|
129
173
|
* Layouts are created once per resource and cached. Creating one during
|
|
@@ -195,7 +239,7 @@ function createForResources({ createLayoutForResource, createMakeComposableLayou
|
|
|
195
239
|
layoutName: definedEntries.get(componentResource)?.name ?? defaultNames.get(componentResource) ?? capitalize(componentResource),
|
|
196
240
|
resource: componentResource
|
|
197
241
|
});
|
|
198
|
-
return createElement(componentPropsContext.Provider, { value: resolvedComponentProps }, resolveScopedRenderResult(
|
|
242
|
+
return createElement(componentPropsContext.Provider, { value: resolvedComponentProps }, resolveScopedRenderResult(topLevelContent.get(componentResource).render(resolvedComponentProps, renderContext), resolvedComponentProps));
|
|
199
243
|
}
|
|
200
244
|
/**
|
|
201
245
|
* Bound components are created once per resource and cached. Returning a
|
|
@@ -215,6 +259,13 @@ function createForResources({ createLayoutForResource, createMakeComposableLayou
|
|
|
215
259
|
props: void 0,
|
|
216
260
|
resource: void 0
|
|
217
261
|
}, resourceScopedComponents.get(resource) ?? {});
|
|
262
|
+
if (createMakeComposableLayout) Object.assign(boundComponent, { makeComposable: (options = {}) => scopedExtras.makeComposable?.({
|
|
263
|
+
...options,
|
|
264
|
+
resource
|
|
265
|
+
}) });
|
|
266
|
+
const renderResource = renderContext[capitalize(resource)];
|
|
267
|
+
const ownContent = topLevelContent.get(resource)?.[scopedLazySymbol];
|
|
268
|
+
withLazyHandle(boundComponent, aggregateHandle([...renderResource ? [renderResource] : [], ...ownContent ? [ownContent] : []]));
|
|
218
269
|
boundComponents.set(resource, boundComponent);
|
|
219
270
|
}
|
|
220
271
|
return boundComponent;
|
|
@@ -222,6 +273,7 @@ function createForResources({ createLayoutForResource, createMakeComposableLayou
|
|
|
222
273
|
function asHOF() {
|
|
223
274
|
return bindResource;
|
|
224
275
|
}
|
|
276
|
+
withLazyHandle(Component, aggregateHandle([...Object.values(renderContext).filter((value) => "preload" in value), ...[...topLevelContent.values()].flatMap((entry) => entry[scopedLazySymbol] ? [entry[scopedLazySymbol]] : [])]));
|
|
225
277
|
return Object.assign(Component, {
|
|
226
278
|
asHOF,
|
|
227
279
|
displayName: "ScopedResourceComponent",
|
|
@@ -241,10 +293,13 @@ function createForResources({ createLayoutForResource, createMakeComposableLayou
|
|
|
241
293
|
function createResourceComponents(options) {
|
|
242
294
|
const { resource, props, ...entry } = options;
|
|
243
295
|
if (!resourceOptions.some((resourceOption) => resourceOption.resource === resource)) throw new LayoutConfigurationError(`Resource "${resource}" is not available in this scoped component`);
|
|
244
|
-
|
|
245
|
-
|
|
296
|
+
const normalized = normalizeContent(entry, resource, String(resource));
|
|
297
|
+
const components = Object.fromEntries(Object.entries(normalized.components ?? {}).map(([name, definition]) => [name, normalizeContent(definition, resource, `${resource}.${name}`)]));
|
|
298
|
+
return withLazyHandle({
|
|
299
|
+
...normalized,
|
|
300
|
+
components,
|
|
246
301
|
props: props ?? {}
|
|
247
|
-
};
|
|
302
|
+
}, aggregateHandle([...normalized[scopedLazySymbol] ? [normalized[scopedLazySymbol]] : [], ...Object.values(components).flatMap((definition) => definition[scopedLazySymbol] ? [definition[scopedLazySymbol]] : [])]));
|
|
248
303
|
}
|
|
249
304
|
Object.assign(createComponent, { setProps: createComponentSetProps });
|
|
250
305
|
const scopedExtras = {
|