@jfdevelops/react-layout 0.24.2 → 0.25.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.
Files changed (67) hide show
  1. package/dist/create-config/create-defined-resource-layout.cjs +67 -0
  2. package/dist/create-config/create-defined-resource-layout.cjs.map +1 -0
  3. package/dist/create-config/create-defined-resource-layout.d.cts +68 -0
  4. package/dist/create-config/create-defined-resource-layout.d.cts.map +1 -0
  5. package/dist/create-config/create-defined-resource-layout.d.mts +68 -0
  6. package/dist/create-config/create-defined-resource-layout.d.mts.map +1 -0
  7. package/dist/create-config/create-defined-resource-layout.mjs +67 -0
  8. package/dist/create-config/create-defined-resource-layout.mjs.map +1 -0
  9. package/dist/create-config/create-resource-links.cjs.map +1 -1
  10. package/dist/create-config/create-resource-links.d.cts +41 -28
  11. package/dist/create-config/create-resource-links.d.cts.map +1 -1
  12. package/dist/create-config/create-resource-links.d.mts +41 -28
  13. package/dist/create-config/create-resource-links.d.mts.map +1 -1
  14. package/dist/create-config/create-resource-links.mjs.map +1 -1
  15. package/dist/create-config/define-layout.cjs +187 -8
  16. package/dist/create-config/define-layout.cjs.map +1 -1
  17. package/dist/create-config/define-layout.d.cts +152 -21
  18. package/dist/create-config/define-layout.d.cts.map +1 -1
  19. package/dist/create-config/define-layout.d.mts +152 -21
  20. package/dist/create-config/define-layout.d.mts.map +1 -1
  21. package/dist/create-config/define-layout.mjs +189 -10
  22. package/dist/create-config/define-layout.mjs.map +1 -1
  23. package/dist/create-config/for-resources/create-for-resources.cjs +7 -0
  24. package/dist/create-config/for-resources/create-for-resources.cjs.map +1 -1
  25. package/dist/create-config/for-resources/create-for-resources.mjs +7 -0
  26. package/dist/create-config/for-resources/create-for-resources.mjs.map +1 -1
  27. package/dist/create-config/index.d.cts +4 -1
  28. package/dist/create-config/index.d.mts +4 -1
  29. package/dist/create-config/lazy-resource-layout.cjs +111 -0
  30. package/dist/create-config/lazy-resource-layout.cjs.map +1 -0
  31. package/dist/create-config/lazy-resource-layout.d.cts +51 -0
  32. package/dist/create-config/lazy-resource-layout.d.cts.map +1 -0
  33. package/dist/create-config/lazy-resource-layout.d.mts +51 -0
  34. package/dist/create-config/lazy-resource-layout.d.mts.map +1 -0
  35. package/dist/create-config/lazy-resource-layout.mjs +111 -0
  36. package/dist/create-config/lazy-resource-layout.mjs.map +1 -0
  37. package/dist/create-config/render-state.cjs +75 -0
  38. package/dist/create-config/render-state.cjs.map +1 -0
  39. package/dist/create-config/render-state.d.cts +120 -0
  40. package/dist/create-config/render-state.d.cts.map +1 -0
  41. package/dist/create-config/render-state.d.mts +120 -0
  42. package/dist/create-config/render-state.d.mts.map +1 -0
  43. package/dist/create-config/render-state.mjs +68 -0
  44. package/dist/create-config/render-state.mjs.map +1 -0
  45. package/dist/errors/resource-state-error.cjs +29 -0
  46. package/dist/errors/resource-state-error.cjs.map +1 -0
  47. package/dist/errors/resource-state-error.d.cts +19 -0
  48. package/dist/errors/resource-state-error.d.cts.map +1 -0
  49. package/dist/errors/resource-state-error.d.mts +19 -0
  50. package/dist/errors/resource-state-error.d.mts.map +1 -0
  51. package/dist/errors/resource-state-error.mjs +27 -0
  52. package/dist/errors/resource-state-error.mjs.map +1 -0
  53. package/dist/index.cjs +5 -0
  54. package/dist/index.d.cts +8 -4
  55. package/dist/index.d.mts +8 -4
  56. package/dist/index.mjs +3 -1
  57. package/dist/props.d.cts +6 -1
  58. package/dist/props.d.cts.map +1 -1
  59. package/dist/props.d.mts +6 -1
  60. package/dist/props.d.mts.map +1 -1
  61. package/dist/resource.cjs.map +1 -1
  62. package/dist/resource.d.cts +7 -1
  63. package/dist/resource.d.cts.map +1 -1
  64. package/dist/resource.d.mts +7 -1
  65. package/dist/resource.d.mts.map +1 -1
  66. package/dist/resource.mjs.map +1 -1
  67. package/package.json +3 -3
@@ -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 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\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, { ...definedCustom, ...rootProps });\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","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 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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"}
@@ -158,8 +158,15 @@ function createForResources({ createLayoutForResource, createMakeComposableLayou
158
158
  }
159
159
  const entry = definedEntries.get(resource);
160
160
  const definedCustom = {};
161
+ const forwardedRootProps = {};
162
+ for (const key of Object.keys(getComponentPropDefinitions(resource))) {
163
+ if (key in componentProps) forwardedRootProps[key] = componentProps[key];
164
+ const capitalized = capitalize(key);
165
+ if (capitalized in componentProps) forwardedRootProps[capitalized] = componentProps[capitalized];
166
+ }
161
167
  for (const [key, value] of Object.entries(entry?.props?.defined ?? {})) if (key in custom) definedCustom[key] = value;
162
168
  return createElement(root, {
169
+ ...forwardedRootProps,
163
170
  ...definedCustom,
164
171
  ...rootProps
165
172
  });
@@ -1 +1 @@
1
- {"version":3,"file":"create-for-resources.mjs","names":[],"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 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\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, { ...definedCustom, ...rootProps });\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.mjs","names":[],"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 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,3 +1,4 @@
1
+ import { AnyRenderStateDefinition, CreateLayoutBuildingBlocks, CreateLayoutBuildingBlocksArguments, CreateLayoutBuildingBlocksResult, CreateRenderState, CreateRenderStateBuilderArguments, CreateRenderStateBuilderResult, DeferredRenderState, DefineLayoutComposables, LayoutComposablesDefinition, LazyRenderState, RenderStateCallback, RenderStateComposablesDefinition, RenderStateContext, RenderStateFragment, RenderStateProps } from "./render-state.cjs";
1
2
  import { BaseResourceConfigComponents, ResourceConfig, ResourceConfigComponentKey, ResourceConfigComponents, ResourceConfigInput, ResourceConfigMap, SharedResourceConfigOptions, SubResourceConfig, SubResourceConfigComponentsFor } from "./types.cjs";
2
3
  import { ComponentPathVariable, ExtractPathVariables, PATH_VARIABLE_IDENTIFIER, PathHasVariables, PathVariable, ResourcePathVariable, SubResourcePathVariable } from "./paths/variables.cjs";
3
4
  import { ConfigResourceKeys, ConfigSubResourceKeys, ParameterizedEntryPath, ParameterizedResourcePath, PathComponentKeys, PathResourceCandidates, PathSubResourceKeys, PathVariables, PathVariablesForResource, ResolveParameterizedPathValue, ResourceSubResourceKeys } from "./paths/types.cjs";
@@ -6,5 +7,7 @@ import { ForPaths, ForPathsRenderContext, RenderedPathComponent, RenderedPathCom
6
7
  import { IsSubResourceKey, IsSubResourceKeyOptions, IsSubResourceKeyResult } from "./is-sub-resource-key.cjs";
7
8
  import { ComponentTypes, CreateResourceConfigFn, CreatedResourceConfig, GetComponent, GetComponentAtBound, GetComponentForResource, GetComponentForResourceOptions, GetComponentOptions, GetComponentOptionsForResource, ResourceConfigPath, ResourceFromGetComponentBound, SubResourceFromGetComponentBound, ValidateForResourceBound } from "./get-component.cjs";
8
9
  import { CreateResourceLinkConfig, CreateResourceLinkGroupInput, CreateResourceLinkGroupOptions, CreateResourceLinkOptions, CreateResourceLinksFn, CreateResourceLinksWithGroups, CreateResourceLinksWithGroupsFn, CreateResourceLinksWithGroupsResult, CreateResourceMap, CreateResourceMapFn, CreatedResourceHref, CreatedResourceLink, CreatedResourceLinkBase, CreatedResourceMap, DefineResourceIconFn, DefineResourceIconInputHelpers, DefineResourceIconInputResult, FindResolvedResourceGroupResult, FindResourceGroupResult, InferHashFromResourceLinkHref, ResolveResourceIconInput, ResolvedResourceLinksWithGroups, ResolvedResourceLinksWithGroupsResult, ResourceAnchorLinkFn, ResourceIcon, ResourceIconFn, ResourceLinkHref, ValidateResource } from "./create-resource-links.cjs";
9
- import { CreateResourceLayoutFn, CreateResourceLayoutMakeComposableOptions, CreateResourceLayoutWithLayoutOptions, DefineResourceLayout, DefineResourceLayoutFn, DefineResourceLayoutForResources, DefineResourceLayoutForResourcesFactory, DefineResourceLayoutWithLayoutFn, DefineResourcesFn, DefinedResourceLayoutWithShell, LayoutRenderResourcesAccessor, LayoutResourcesAccessor, ResourceLayoutProvider, ResourceLayoutProviderProps, ResourceLayoutShellComponent, ResourceLayoutShellProps, ResourceSelection, ShellLayoutDefinition, ShellRenderContext, defineResourceLayout } from "./define-layout.cjs";
10
+ import { ContextualInlineRenderState, ContextualInlineRenderStates, CreateResourceLayoutFn, CreateResourceLayoutMakeComposableOptions, CreateResourceLayoutWithLayoutOptions, CreateViewMapBuiltInRenderStatesOptions, CreateViewMapFunctionRenderOptions, CreateViewMapInlineRenderStatesOptions, CreateViewMapOptions, CreateViewMapRenderStatesOptions, DefineResourceLayout, DefineResourceLayoutFn, DefineResourceLayoutForResources, DefineResourceLayoutForResourcesFactory, DefineResourceLayoutWithLayoutFn, DefineResourcesFn, DefinedResourceLayout, DefinedResourceLayoutWithShell, LayoutDefinition, LayoutIncludeProps, LayoutRenderResourcesAccessor, LayoutResourcesAccessor, ResourceLayoutProvider, ResourceLayoutProviderProps, ResourceLayoutShellComponent, ResourceLayoutShellProps, ResourceSelection, ShellLayoutDefinition, ShellRenderContext, TypedBuiltInRenderStates, TypedInlineRenderState, defineResourceLayout } from "./define-layout.cjs";
11
+ import { LazyResourceErrorComponent, LazyResourceLayoutComponent, LazyResourceLayoutOptions, LazyResourceLoadingComponent, LazyResourceStates } from "./lazy-resource-layout.cjs";
12
+ import { BoundDefineResourceLayout, CreateDefinedResourceLayoutResult, DefineLazyDefaults, DefineOptions, DefinedResourceLayoutBuilder, DefinedResourceLayoutInput, NonEmptyResources, createDefinedResourceLayout } from "./create-defined-resource-layout.cjs";
10
13
  import { ResourceLayoutShellPublisher } from "./shell-context.cjs";
@@ -1,3 +1,4 @@
1
+ import { AnyRenderStateDefinition, CreateLayoutBuildingBlocks, CreateLayoutBuildingBlocksArguments, CreateLayoutBuildingBlocksResult, CreateRenderState, CreateRenderStateBuilderArguments, CreateRenderStateBuilderResult, DeferredRenderState, DefineLayoutComposables, LayoutComposablesDefinition, LazyRenderState, RenderStateCallback, RenderStateComposablesDefinition, RenderStateContext, RenderStateFragment, RenderStateProps } from "./render-state.mjs";
1
2
  import { BaseResourceConfigComponents, ResourceConfig, ResourceConfigComponentKey, ResourceConfigComponents, ResourceConfigInput, ResourceConfigMap, SharedResourceConfigOptions, SubResourceConfig, SubResourceConfigComponentsFor } from "./types.mjs";
2
3
  import { ComponentPathVariable, ExtractPathVariables, PATH_VARIABLE_IDENTIFIER, PathHasVariables, PathVariable, ResourcePathVariable, SubResourcePathVariable } from "./paths/variables.mjs";
3
4
  import { ConfigResourceKeys, ConfigSubResourceKeys, ParameterizedEntryPath, ParameterizedResourcePath, PathComponentKeys, PathResourceCandidates, PathSubResourceKeys, PathVariables, PathVariablesForResource, ResolveParameterizedPathValue, ResourceSubResourceKeys } from "./paths/types.mjs";
@@ -6,5 +7,7 @@ import { ForPaths, ForPathsRenderContext, RenderedPathComponent, RenderedPathCom
6
7
  import { IsSubResourceKey, IsSubResourceKeyOptions, IsSubResourceKeyResult } from "./is-sub-resource-key.mjs";
7
8
  import { ComponentTypes, CreateResourceConfigFn, CreatedResourceConfig, GetComponent, GetComponentAtBound, GetComponentForResource, GetComponentForResourceOptions, GetComponentOptions, GetComponentOptionsForResource, ResourceConfigPath, ResourceFromGetComponentBound, SubResourceFromGetComponentBound, ValidateForResourceBound } from "./get-component.mjs";
8
9
  import { CreateResourceLinkConfig, CreateResourceLinkGroupInput, CreateResourceLinkGroupOptions, CreateResourceLinkOptions, CreateResourceLinksFn, CreateResourceLinksWithGroups, CreateResourceLinksWithGroupsFn, CreateResourceLinksWithGroupsResult, CreateResourceMap, CreateResourceMapFn, CreatedResourceHref, CreatedResourceLink, CreatedResourceLinkBase, CreatedResourceMap, DefineResourceIconFn, DefineResourceIconInputHelpers, DefineResourceIconInputResult, FindResolvedResourceGroupResult, FindResourceGroupResult, InferHashFromResourceLinkHref, ResolveResourceIconInput, ResolvedResourceLinksWithGroups, ResolvedResourceLinksWithGroupsResult, ResourceAnchorLinkFn, ResourceIcon, ResourceIconFn, ResourceLinkHref, ValidateResource } from "./create-resource-links.mjs";
9
- import { CreateResourceLayoutFn, CreateResourceLayoutMakeComposableOptions, CreateResourceLayoutWithLayoutOptions, DefineResourceLayout, DefineResourceLayoutFn, DefineResourceLayoutForResources, DefineResourceLayoutForResourcesFactory, DefineResourceLayoutWithLayoutFn, DefineResourcesFn, DefinedResourceLayoutWithShell, LayoutRenderResourcesAccessor, LayoutResourcesAccessor, ResourceLayoutProvider, ResourceLayoutProviderProps, ResourceLayoutShellComponent, ResourceLayoutShellProps, ResourceSelection, ShellLayoutDefinition, ShellRenderContext, defineResourceLayout } from "./define-layout.mjs";
10
+ import { ContextualInlineRenderState, ContextualInlineRenderStates, CreateResourceLayoutFn, CreateResourceLayoutMakeComposableOptions, CreateResourceLayoutWithLayoutOptions, CreateViewMapBuiltInRenderStatesOptions, CreateViewMapFunctionRenderOptions, CreateViewMapInlineRenderStatesOptions, CreateViewMapOptions, CreateViewMapRenderStatesOptions, DefineResourceLayout, DefineResourceLayoutFn, DefineResourceLayoutForResources, DefineResourceLayoutForResourcesFactory, DefineResourceLayoutWithLayoutFn, DefineResourcesFn, DefinedResourceLayout, DefinedResourceLayoutWithShell, LayoutDefinition, LayoutIncludeProps, LayoutRenderResourcesAccessor, LayoutResourcesAccessor, ResourceLayoutProvider, ResourceLayoutProviderProps, ResourceLayoutShellComponent, ResourceLayoutShellProps, ResourceSelection, ShellLayoutDefinition, ShellRenderContext, TypedBuiltInRenderStates, TypedInlineRenderState, defineResourceLayout } from "./define-layout.mjs";
11
+ import { LazyResourceErrorComponent, LazyResourceLayoutComponent, LazyResourceLayoutOptions, LazyResourceLoadingComponent, LazyResourceStates } from "./lazy-resource-layout.mjs";
12
+ import { BoundDefineResourceLayout, CreateDefinedResourceLayoutResult, DefineLazyDefaults, DefineOptions, DefinedResourceLayoutBuilder, DefinedResourceLayoutInput, NonEmptyResources, createDefinedResourceLayout } from "./create-defined-resource-layout.mjs";
10
13
  import { ResourceLayoutShellPublisher } from "./shell-context.mjs";
@@ -0,0 +1,111 @@
1
+ const require_layout_configuration_error = require('../errors/layout-configuration-error.cjs');
2
+ const require_resource_state_error = require('../errors/resource-state-error.cjs');
3
+ const require_render_state = require('./render-state.cjs');
4
+ let react = require("react");
5
+ let _jfdevelops_react_layout_validator = require("@jfdevelops/react-layout-validator");
6
+ let react_jsx_runtime = require("react/jsx-runtime");
7
+
8
+ //#region src/create-config/lazy-resource-layout.tsx
9
+ var LazyResourceErrorBoundary = class extends react.Component {
10
+ state = {};
11
+ static getDerivedStateFromError(error) {
12
+ return { error };
13
+ }
14
+ retry = () => {
15
+ this.props.onRetry();
16
+ this.setState({ error: void 0 });
17
+ };
18
+ render() {
19
+ if (this.state.error !== void 0) {
20
+ const { ErrorComponent } = this.props;
21
+ if (!ErrorComponent) throw this.state.error;
22
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorComponent, {
23
+ error: this.state.error,
24
+ retry: this.retry
25
+ });
26
+ }
27
+ return this.props.children;
28
+ }
29
+ };
30
+ function findDefinedLayoutComponent(module) {
31
+ const components = Object.values(module).filter((value) => typeof value === "function" && require_render_state.definedResourceLayoutComponentSymbol in value);
32
+ if (components.length !== 1) throw new require_layout_configuration_error.LayoutConfigurationError(`A lazy resource module must export exactly one created resource layout component; received ${components.length}`);
33
+ return components[0];
34
+ }
35
+ /**
36
+ * Creates a cached lazy proxy for a resource component and all of its compound
37
+ * state components. This is normally called through
38
+ * `defineResourceLayout.lazy(...)`, which supplies shared defaults.
39
+ */
40
+ function createLazyResourceLayout(options, defaults) {
41
+ const runtimeOptions = options;
42
+ let loadedComponentPromise;
43
+ const stateComponents = /* @__PURE__ */ new Map();
44
+ const resolvedStates = {
45
+ ...defaults,
46
+ ...runtimeOptions.states
47
+ };
48
+ function loadComponent() {
49
+ loadedComponentPromise ??= runtimeOptions.load().then(findDefinedLayoutComponent).catch((error) => {
50
+ throw new require_resource_state_error.ResourceModuleLoadError(runtimeOptions.resource, error);
51
+ });
52
+ return loadedComponentPromise;
53
+ }
54
+ function resetLoad() {
55
+ loadedComponentPromise = void 0;
56
+ stateComponents.clear();
57
+ }
58
+ function createMemberComponent(member) {
59
+ function createLazyComponent() {
60
+ return (0, react.lazy)(async () => {
61
+ const component = await loadComponent();
62
+ const selected = member === void 0 ? component : component[member];
63
+ if (typeof selected !== "function") throw new require_layout_configuration_error.LayoutConfigurationError(`Lazy resource "${runtimeOptions.resource}" does not define state "${String(member)}"`);
64
+ return { default: selected };
65
+ });
66
+ }
67
+ function LazyMember(props) {
68
+ const [, rerender] = (0, react.useReducer)((version) => version + 1, 0);
69
+ const LazyComponent = (0, react.useRef)(createLazyComponent());
70
+ const LoadingComponent = resolvedStates.Loading;
71
+ const CurrentLazyComponent = LazyComponent.current;
72
+ function retry() {
73
+ resetLoad();
74
+ LazyComponent.current = createLazyComponent();
75
+ rerender();
76
+ }
77
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LazyResourceErrorBoundary, {
78
+ ErrorComponent: resolvedStates.Error,
79
+ onRetry: retry,
80
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Suspense, {
81
+ fallback: LoadingComponent ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LoadingComponent, {}) : null,
82
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CurrentLazyComponent, { ...props })
83
+ })
84
+ });
85
+ }
86
+ const resourceName = runtimeOptions.resource;
87
+ LazyMember.displayName = member === void 0 ? `LazyResource(${resourceName})` : `LazyResource(${resourceName}).${String(member)}`;
88
+ return LazyMember;
89
+ }
90
+ const Component = createMemberComponent();
91
+ const unsupportedStatics = new Set([
92
+ "makeComposable",
93
+ "props",
94
+ "resource",
95
+ _jfdevelops_react_layout_validator.componentPropDefinitionsSymbol,
96
+ require_render_state.definedResourceLayoutComponentSymbol
97
+ ]);
98
+ return new Proxy(Component, { get(target, property, receiver) {
99
+ if (Reflect.has(target, property)) return Reflect.get(target, property, receiver);
100
+ if (typeof property !== "string" || unsupportedStatics.has(property)) return;
101
+ const existing = stateComponents.get(property);
102
+ if (existing) return existing;
103
+ const stateComponent = createMemberComponent(property);
104
+ stateComponents.set(property, stateComponent);
105
+ return stateComponent;
106
+ } });
107
+ }
108
+
109
+ //#endregion
110
+ exports.createLazyResourceLayout = createLazyResourceLayout;
111
+ //# sourceMappingURL=lazy-resource-layout.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lazy-resource-layout.cjs","names":["Component","definedResourceLayoutComponentSymbol","LayoutConfigurationError","ResourceModuleLoadError","Suspense","componentPropDefinitionsSymbol"],"sources":["../../src/create-config/lazy-resource-layout.tsx"],"sourcesContent":["import {\n Component,\n type ComponentProps,\n type ComponentType,\n type JSX,\n lazy,\n Suspense,\n useReducer,\n useRef,\n} from 'react';\nimport {\n LayoutConfigurationError,\n ResourceModuleLoadError,\n} from '../errors';\nimport { componentPropDefinitionsSymbol } from '@jfdevelops/react-layout-validator';\nimport type { ResourcePath, ResourceDefinition } from '../resource';\nimport { definedResourceLayoutComponentSymbol } from './render-state';\n\ntype DefinedLayoutComponent = ComponentType<any> & {\n readonly [definedResourceLayoutComponentSymbol]: true;\n};\n\ntype DefinedLayoutFromModule<Module> = Extract<\n Module[keyof Module],\n DefinedLayoutComponent\n>;\n\ntype LazyUnsupportedStatic =\n | 'makeComposable'\n | 'props'\n | 'resource'\n | typeof componentPropDefinitionsSymbol\n | typeof definedResourceLayoutComponentSymbol;\n\n/**\n * Public surface available before a lazy module resolves. Component metadata\n * and composition factories are intentionally omitted because they cannot be\n * read synchronously without loading the module.\n */\nexport type LazyResourceLayoutComponent<Module> = ComponentType<\n ComponentProps<DefinedLayoutFromModule<Module>>\n> &\n Pick<\n DefinedLayoutFromModule<Module>,\n Exclude<keyof DefinedLayoutFromModule<Module>, LazyUnsupportedStatic>\n >;\n\n/** Component rendered while a resource module or one of its states is loading. */\nexport type LazyResourceLoadingComponent = ComponentType;\n/**\n * Component rendered when a resource module cannot be loaded. Calling\n * `retry` discards React's rejected lazy cache entry and imports it again.\n */\nexport type LazyResourceErrorComponent = ComponentType<{\n error: unknown;\n retry: () => void;\n}>;\n\n/** Loading and module-error UI used around a lazy resource component. */\nexport type LazyResourceStates = {\n Error?: LazyResourceErrorComponent;\n Loading?: LazyResourceLoadingComponent;\n};\n\n/**\n * Configuration for a lazy resource component. `resource` is checked against\n * the bound resource paths, including dot-delimited subresources, and `load`\n * must resolve to a module with exactly one created resource component.\n */\nexport type LazyResourceLayoutOptions<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Module extends Record<string, unknown>,\n> = {\n load: () => Promise<Module>;\n resource: ResourcePath<Resources>;\n states?: LazyResourceStates;\n};\n\ntype BoundaryProps = {\n children: JSX.Element;\n ErrorComponent?: LazyResourceErrorComponent;\n onRetry: () => void;\n};\n\ntype BoundaryState = {\n error?: unknown;\n};\n\nclass LazyResourceErrorBoundary extends Component<\n BoundaryProps,\n BoundaryState\n> {\n state: BoundaryState = {};\n\n static getDerivedStateFromError(error: unknown): BoundaryState {\n return { error };\n }\n\n retry = () => {\n this.props.onRetry();\n this.setState({ error: undefined });\n };\n\n render() {\n if (this.state.error !== undefined) {\n const { ErrorComponent } = this.props;\n\n if (!ErrorComponent) {\n throw this.state.error;\n }\n\n return <ErrorComponent error={this.state.error} retry={this.retry} />;\n }\n\n return this.props.children;\n }\n}\n\nfunction findDefinedLayoutComponent(module: Record<string, unknown>) {\n const components = Object.values(module).filter(\n (value): value is DefinedLayoutComponent =>\n typeof value === 'function' &&\n definedResourceLayoutComponentSymbol in value,\n );\n\n if (components.length !== 1) {\n throw new LayoutConfigurationError(\n `A lazy resource module must export exactly one created resource layout component; received ${components.length}`,\n );\n }\n\n return components[0];\n}\n\n/**\n * Creates a cached lazy proxy for a resource component and all of its compound\n * state components. This is normally called through\n * `defineResourceLayout.lazy(...)`, which supplies shared defaults.\n */\nexport function createLazyResourceLayout<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Module extends Record<string, unknown>,\n>(\n options: LazyResourceLayoutOptions<Resources, Module>,\n defaults: LazyResourceStates,\n): LazyResourceLayoutComponent<Module> {\n const runtimeOptions = options as {\n load: () => Promise<Record<string, unknown>>;\n resource: string;\n states?: LazyResourceStates;\n };\n let loadedComponentPromise: Promise<DefinedLayoutComponent> | undefined;\n const stateComponents = new Map<PropertyKey, ComponentType<any>>();\n const resolvedStates = { ...defaults, ...runtimeOptions.states };\n\n function loadComponent() {\n loadedComponentPromise ??= runtimeOptions\n .load()\n .then(findDefinedLayoutComponent)\n .catch((error: unknown) => {\n throw new ResourceModuleLoadError(runtimeOptions.resource, error);\n });\n\n return loadedComponentPromise;\n }\n\n function resetLoad() {\n loadedComponentPromise = undefined;\n stateComponents.clear();\n }\n\n function createMemberComponent(member?: PropertyKey) {\n function createLazyComponent() {\n return lazy(async () => {\n const component = await loadComponent();\n const selected =\n member === undefined\n ? component\n : (component as unknown as Record<PropertyKey, unknown>)[member];\n\n if (typeof selected !== 'function') {\n throw new LayoutConfigurationError(\n `Lazy resource \"${runtimeOptions.resource}\" does not define state \"${String(member)}\"`,\n );\n }\n\n return { default: selected as ComponentType<any> };\n });\n }\n\n function LazyMember(props: Record<string, unknown>) {\n const [, rerender] = useReducer((version) => version + 1, 0);\n const LazyComponent = useRef(createLazyComponent());\n const LoadingComponent = resolvedStates.Loading;\n const CurrentLazyComponent = LazyComponent.current;\n\n function retry() {\n resetLoad();\n LazyComponent.current = createLazyComponent();\n rerender();\n }\n\n return (\n <LazyResourceErrorBoundary\n ErrorComponent={resolvedStates.Error}\n onRetry={retry}\n >\n <Suspense\n fallback={LoadingComponent ? <LoadingComponent /> : null}\n >\n <CurrentLazyComponent {...props} />\n </Suspense>\n </LazyResourceErrorBoundary>\n );\n }\n\n const resourceName = runtimeOptions.resource;\n LazyMember.displayName =\n member === undefined\n ? `LazyResource(${resourceName})`\n : `LazyResource(${resourceName}).${String(member)}`;\n\n return LazyMember;\n }\n\n const Component = createMemberComponent();\n const unsupportedStatics = new Set<PropertyKey>([\n 'makeComposable',\n 'props',\n 'resource',\n componentPropDefinitionsSymbol,\n definedResourceLayoutComponentSymbol,\n ]);\n\n return new Proxy(Component, {\n get(target, property, receiver) {\n if (Reflect.has(target, property)) {\n return Reflect.get(target, property, receiver);\n }\n\n if (typeof property !== 'string' || unsupportedStatics.has(property)) {\n return undefined;\n }\n\n const existing = stateComponents.get(property);\n\n if (existing) {\n return existing;\n }\n\n const stateComponent = createMemberComponent(property);\n stateComponents.set(property, stateComponent);\n\n return stateComponent;\n },\n }) as unknown as LazyResourceLayoutComponent<Module>;\n}\n"],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import { ResourceDefinition, ResourcePath } from "../resource.cjs";
2
+ import { definedResourceLayoutComponentSymbol } from "./render-state.cjs";
3
+ import { ComponentProps, ComponentType } from "react";
4
+ import { componentPropDefinitionsSymbol } from "@jfdevelops/react-layout-validator";
5
+
6
+ //#region src/create-config/lazy-resource-layout.d.ts
7
+ type DefinedLayoutComponent = ComponentType<any> & {
8
+ readonly [definedResourceLayoutComponentSymbol]: true;
9
+ };
10
+ type DefinedLayoutFromModule<Module> = Extract<Module[keyof Module], DefinedLayoutComponent>;
11
+ type LazyUnsupportedStatic = 'makeComposable' | 'props' | 'resource' | typeof componentPropDefinitionsSymbol | typeof definedResourceLayoutComponentSymbol;
12
+ /**
13
+ * Public surface available before a lazy module resolves. Component metadata
14
+ * and composition factories are intentionally omitted because they cannot be
15
+ * read synchronously without loading the module.
16
+ */
17
+ type LazyResourceLayoutComponent<Module> = ComponentType<ComponentProps<DefinedLayoutFromModule<Module>>> & Pick<DefinedLayoutFromModule<Module>, Exclude<keyof DefinedLayoutFromModule<Module>, LazyUnsupportedStatic>>;
18
+ /** Component rendered while a resource module or one of its states is loading. */
19
+ type LazyResourceLoadingComponent = ComponentType;
20
+ /**
21
+ * Component rendered when a resource module cannot be loaded. Calling
22
+ * `retry` discards React's rejected lazy cache entry and imports it again.
23
+ */
24
+ type LazyResourceErrorComponent = ComponentType<{
25
+ error: unknown;
26
+ retry: () => void;
27
+ }>;
28
+ /** Loading and module-error UI used around a lazy resource component. */
29
+ type LazyResourceStates = {
30
+ Error?: LazyResourceErrorComponent;
31
+ Loading?: LazyResourceLoadingComponent;
32
+ };
33
+ /**
34
+ * Configuration for a lazy resource component. `resource` is checked against
35
+ * the bound resource paths, including dot-delimited subresources, and `load`
36
+ * must resolve to a module with exactly one created resource component.
37
+ */
38
+ type LazyResourceLayoutOptions<Resources extends ReadonlyArray<ResourceDefinition>, Module extends Record<string, unknown>> = {
39
+ load: () => Promise<Module>;
40
+ resource: ResourcePath<Resources>;
41
+ states?: LazyResourceStates;
42
+ };
43
+ /**
44
+ * Creates a cached lazy proxy for a resource component and all of its compound
45
+ * state components. This is normally called through
46
+ * `defineResourceLayout.lazy(...)`, which supplies shared defaults.
47
+ */
48
+ declare function createLazyResourceLayout<Resources extends ReadonlyArray<ResourceDefinition>, Module extends Record<string, unknown>>(options: LazyResourceLayoutOptions<Resources, Module>, defaults: LazyResourceStates): LazyResourceLayoutComponent<Module>;
49
+ //#endregion
50
+ export { LazyResourceErrorComponent, LazyResourceLayoutComponent, LazyResourceLayoutOptions, LazyResourceLoadingComponent, LazyResourceStates, createLazyResourceLayout };
51
+ //# sourceMappingURL=lazy-resource-layout.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lazy-resource-layout.d.cts","names":[],"sources":["../../src/create-config/lazy-resource-layout.tsx"],"mappings":";;;;;;KAkBK,sBAAA,GAAyB,aAAA;EAAA,UAClB,oCAAoC;AAAA;AAAA,KAG3C,uBAAA,WAAkC,OAAA,CACrC,MAAA,OAAa,MAAA,GACb,sBAAA;AAAA,KAGG,qBAAA,oDAIM,8BAAA,UACA,oCAAoC;;AAbC;AAAA;;;KAoBpC,2BAAA,WAAsC,aAAA,CAChD,cAAA,CAAe,uBAAA,CAAwB,MAAA,MAEvC,IAAA,CACE,uBAAA,CAAwB,MAAA,GACxB,OAAA,OAAc,uBAAA,CAAwB,MAAA,GAAS,qBAAA;;KAIvC,4BAAA,GAA+B,aAAa;;;;;KAK5C,0BAAA,GAA6B,aAAa;EACpD,KAAA;EACA,KAAA;AAAA;;KAIU,kBAAA;EACV,KAAA,GAAQ,0BAAA;EACR,OAAA,GAAU,4BAA4B;AAAA;;AA7BO;AAO/C;;;KA8BY,yBAAA,mBACQ,aAAA,CAAc,kBAAA,kBACjB,MAAA;EAEf,IAAA,QAAY,OAAA,CAAQ,MAAA;EACpB,QAAA,EAAU,YAAA,CAAa,SAAA;EACvB,MAAA,GAAS,kBAAA;AAAA;;;;;;iBAgEK,wBAAA,mBACI,aAAA,CAAc,kBAAA,kBACjB,MAAA,mBAEf,OAAA,EAAS,yBAAA,CAA0B,SAAA,EAAW,MAAA,GAC9C,QAAA,EAAU,kBAAA,GACT,2BAAA,CAA4B,MAAA"}
@@ -0,0 +1,51 @@
1
+ import { ResourceDefinition, ResourcePath } from "../resource.mjs";
2
+ import { definedResourceLayoutComponentSymbol } from "./render-state.mjs";
3
+ import { ComponentProps, ComponentType } from "react";
4
+ import { componentPropDefinitionsSymbol } from "@jfdevelops/react-layout-validator";
5
+
6
+ //#region src/create-config/lazy-resource-layout.d.ts
7
+ type DefinedLayoutComponent = ComponentType<any> & {
8
+ readonly [definedResourceLayoutComponentSymbol]: true;
9
+ };
10
+ type DefinedLayoutFromModule<Module> = Extract<Module[keyof Module], DefinedLayoutComponent>;
11
+ type LazyUnsupportedStatic = 'makeComposable' | 'props' | 'resource' | typeof componentPropDefinitionsSymbol | typeof definedResourceLayoutComponentSymbol;
12
+ /**
13
+ * Public surface available before a lazy module resolves. Component metadata
14
+ * and composition factories are intentionally omitted because they cannot be
15
+ * read synchronously without loading the module.
16
+ */
17
+ type LazyResourceLayoutComponent<Module> = ComponentType<ComponentProps<DefinedLayoutFromModule<Module>>> & Pick<DefinedLayoutFromModule<Module>, Exclude<keyof DefinedLayoutFromModule<Module>, LazyUnsupportedStatic>>;
18
+ /** Component rendered while a resource module or one of its states is loading. */
19
+ type LazyResourceLoadingComponent = ComponentType;
20
+ /**
21
+ * Component rendered when a resource module cannot be loaded. Calling
22
+ * `retry` discards React's rejected lazy cache entry and imports it again.
23
+ */
24
+ type LazyResourceErrorComponent = ComponentType<{
25
+ error: unknown;
26
+ retry: () => void;
27
+ }>;
28
+ /** Loading and module-error UI used around a lazy resource component. */
29
+ type LazyResourceStates = {
30
+ Error?: LazyResourceErrorComponent;
31
+ Loading?: LazyResourceLoadingComponent;
32
+ };
33
+ /**
34
+ * Configuration for a lazy resource component. `resource` is checked against
35
+ * the bound resource paths, including dot-delimited subresources, and `load`
36
+ * must resolve to a module with exactly one created resource component.
37
+ */
38
+ type LazyResourceLayoutOptions<Resources extends ReadonlyArray<ResourceDefinition>, Module extends Record<string, unknown>> = {
39
+ load: () => Promise<Module>;
40
+ resource: ResourcePath<Resources>;
41
+ states?: LazyResourceStates;
42
+ };
43
+ /**
44
+ * Creates a cached lazy proxy for a resource component and all of its compound
45
+ * state components. This is normally called through
46
+ * `defineResourceLayout.lazy(...)`, which supplies shared defaults.
47
+ */
48
+ declare function createLazyResourceLayout<Resources extends ReadonlyArray<ResourceDefinition>, Module extends Record<string, unknown>>(options: LazyResourceLayoutOptions<Resources, Module>, defaults: LazyResourceStates): LazyResourceLayoutComponent<Module>;
49
+ //#endregion
50
+ export { LazyResourceErrorComponent, LazyResourceLayoutComponent, LazyResourceLayoutOptions, LazyResourceLoadingComponent, LazyResourceStates, createLazyResourceLayout };
51
+ //# sourceMappingURL=lazy-resource-layout.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lazy-resource-layout.d.mts","names":[],"sources":["../../src/create-config/lazy-resource-layout.tsx"],"mappings":";;;;;;KAkBK,sBAAA,GAAyB,aAAA;EAAA,UAClB,oCAAoC;AAAA;AAAA,KAG3C,uBAAA,WAAkC,OAAA,CACrC,MAAA,OAAa,MAAA,GACb,sBAAA;AAAA,KAGG,qBAAA,oDAIM,8BAAA,UACA,oCAAoC;;AAbC;AAAA;;;KAoBpC,2BAAA,WAAsC,aAAA,CAChD,cAAA,CAAe,uBAAA,CAAwB,MAAA,MAEvC,IAAA,CACE,uBAAA,CAAwB,MAAA,GACxB,OAAA,OAAc,uBAAA,CAAwB,MAAA,GAAS,qBAAA;;KAIvC,4BAAA,GAA+B,aAAa;;;;;KAK5C,0BAAA,GAA6B,aAAa;EACpD,KAAA;EACA,KAAA;AAAA;;KAIU,kBAAA;EACV,KAAA,GAAQ,0BAAA;EACR,OAAA,GAAU,4BAA4B;AAAA;;AA7BO;AAO/C;;;KA8BY,yBAAA,mBACQ,aAAA,CAAc,kBAAA,kBACjB,MAAA;EAEf,IAAA,QAAY,OAAA,CAAQ,MAAA;EACpB,QAAA,EAAU,YAAA,CAAa,SAAA;EACvB,MAAA,GAAS,kBAAA;AAAA;;;;;;iBAgEK,wBAAA,mBACI,aAAA,CAAc,kBAAA,kBACjB,MAAA,mBAEf,OAAA,EAAS,yBAAA,CAA0B,SAAA,EAAW,MAAA,GAC9C,QAAA,EAAU,kBAAA,GACT,2BAAA,CAA4B,MAAA"}