@jfdevelops/react-layout 2.1.0 → 2.2.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 (29) hide show
  1. package/dist/create-config/create-defined-resource-layout.cjs +4 -3
  2. package/dist/create-config/create-defined-resource-layout.cjs.map +1 -1
  3. package/dist/create-config/create-defined-resource-layout.d.cts +1 -1
  4. package/dist/create-config/create-defined-resource-layout.d.mts +1 -1
  5. package/dist/create-config/create-defined-resource-layout.mjs +4 -3
  6. package/dist/create-config/create-defined-resource-layout.mjs.map +1 -1
  7. package/dist/create-config/define-layout.cjs +8 -4
  8. package/dist/create-config/define-layout.cjs.map +1 -1
  9. package/dist/create-config/define-layout.d.cts.map +1 -1
  10. package/dist/create-config/define-layout.d.mts.map +1 -1
  11. package/dist/create-config/define-layout.mjs +11 -7
  12. package/dist/create-config/define-layout.mjs.map +1 -1
  13. package/dist/create-config/inspection.cjs +23 -1
  14. package/dist/create-config/inspection.cjs.map +1 -1
  15. package/dist/create-config/inspection.mjs +24 -3
  16. package/dist/create-config/inspection.mjs.map +1 -1
  17. package/dist/create-config/lazy-resource-layout.cjs +4 -4
  18. package/dist/create-config/lazy-resource-layout.cjs.map +1 -1
  19. package/dist/create-config/lazy-resource-layout.d.cts +1 -1
  20. package/dist/create-config/lazy-resource-layout.d.cts.map +1 -1
  21. package/dist/create-config/lazy-resource-layout.d.mts +1 -1
  22. package/dist/create-config/lazy-resource-layout.d.mts.map +1 -1
  23. package/dist/create-config/lazy-resource-layout.mjs +4 -4
  24. package/dist/create-config/lazy-resource-layout.mjs.map +1 -1
  25. package/dist/lazy/create-lazy-loader.cjs +30 -9
  26. package/dist/lazy/create-lazy-loader.cjs.map +1 -1
  27. package/dist/lazy/create-lazy-loader.mjs +31 -10
  28. package/dist/lazy/create-lazy-loader.mjs.map +1 -1
  29. package/package.json +5 -5
@@ -34,15 +34,36 @@ function inspectDefinition(resources, source) {
34
34
  resourceIds
35
35
  };
36
36
  }
37
+ const inspectedComposables = /* @__PURE__ */ new WeakSet();
38
+ /** Mark existing roots only; never add wrappers or forward props to user components. */
39
+ function markInspectionRoots(children, owners) {
40
+ if (process.env.NODE_ENV === "production") return children;
41
+ if (Array.isArray(children)) return children.map((child) => markInspectionRoots(child, owners));
42
+ if (!(0, react.isValidElement)(children)) return children;
43
+ if (children.type === react.Fragment) return (0, react.cloneElement)(children, { children: markInspectionRoots(children.props.children, owners) });
44
+ if (typeof children.type !== "string" && (typeof children.type !== "object" || !inspectedComposables.has(children.type))) return children;
45
+ let previous = [];
46
+ try {
47
+ const parsed = JSON.parse(children.props["data-rl-owners"] ?? "[]");
48
+ if (Array.isArray(parsed)) previous = parsed.filter((id) => typeof id === "string");
49
+ } catch {}
50
+ return (0, react.cloneElement)(children, { "data-rl-owners": JSON.stringify([...new Set([...previous, ...owners])]) });
51
+ }
37
52
  /** Preserve composable metadata while measuring committed React instances, not declarations. */
38
53
  function trackComposable(component, store, id) {
39
54
  const Tracked = (0, react.forwardRef)(function InspectedComposable(props, ref) {
40
55
  (0, react.useLayoutEffect)(() => store.mount(id), [store, id]);
41
- return (0, react.createElement)(component, ref == null ? props : {
56
+ const inspectedProps = process.env.NODE_ENV === "production" ? props : {
42
57
  ...props,
58
+ "data-rl-node": id,
59
+ "data-rl-composable": component.displayName ?? "Composable"
60
+ };
61
+ return (0, react.createElement)(component, ref == null ? inspectedProps : {
62
+ ...inspectedProps,
43
63
  ref
44
64
  });
45
65
  });
66
+ inspectedComposables.add(Tracked);
46
67
  for (const key of Reflect.ownKeys(component)) {
47
68
  if (typeof key === "string" && [
48
69
  "name",
@@ -63,5 +84,6 @@ function trackComposable(component, store, id) {
63
84
 
64
85
  //#endregion
65
86
  exports.inspectDefinition = inspectDefinition;
87
+ exports.markInspectionRoots = markInspectionRoots;
66
88
  exports.trackComposable = trackComposable;
67
89
  //# sourceMappingURL=inspection.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"inspection.cjs","names":[],"sources":["../../src/create-config/inspection.ts"],"sourcesContent":["import {\n createElement,\n forwardRef,\n useLayoutEffect,\n type ComponentType,\n} from 'react';\nimport {\n createInspectionStore,\n inspectionId,\n type InspectionStore,\n type SourceLocation,\n} from '@jfdevelops/react-layout-devtools-core';\nimport type { ResourceDefinition } from '../resource';\n\nexport function inspectDefinition(\n resources: readonly ResourceDefinition[],\n source?: SourceLocation\n) {\n const store = createInspectionStore();\n const definition = store.node({\n id: inspectionId('definition'),\n kind: 'definition',\n label: 'Layout definition',\n source,\n });\n const resourceIds = new Map<string, string>();\n\n function visit(\n items: readonly ResourceDefinition[],\n parent: string,\n prefix = ''\n ) {\n for (const item of items) {\n const slug = typeof item === 'string' ? item : item.value;\n const path = prefix ? `${prefix}.${slug}` : slug;\n const id = store.node({\n id: inspectionId('resource'),\n kind: 'resource',\n label: path,\n source,\n details: { path },\n });\n\n resourceIds.set(path, id);\n\n store.edge(parent, id, 'contains');\n\n if (typeof item !== 'string') visit(item.subResources, id, path);\n }\n }\n\n visit(resources, definition);\n\n return { store, definition, resourceIds };\n}\n\nexport interface ActiveInspection {\n store: InspectionStore;\n layout: string;\n resource?: string;\n state: string;\n}\n\n/** Preserve composable metadata while measuring committed React instances, not declarations. */\nexport function trackComposable<T extends object>(\n component: T,\n store: InspectionStore,\n id: string\n): T {\n const Tracked = forwardRef<unknown, Record<string, unknown>>(\n function InspectedComposable(props, ref) {\n useLayoutEffect(() => store.mount(id), [store, id]);\n\n return createElement(\n component as ComponentType<Record<string, unknown>>,\n ref == null ? props : { ...props, ref }\n );\n }\n );\n\n for (const key of Reflect.ownKeys(component)) {\n if (\n typeof key === 'string' &&\n [\n 'name',\n 'length',\n 'prototype',\n 'caller',\n 'arguments',\n '$$typeof',\n 'render',\n 'compare',\n 'type',\n ].includes(key)\n )\n continue;\n\n const descriptor = Object.getOwnPropertyDescriptor(component, key);\n\n if (descriptor) Object.defineProperty(Tracked, key, descriptor);\n }\n\n return Tracked as unknown as T;\n}\n"],"mappings":";;;;AAcA,SAAgB,kBACd,WACA,QACA;CACA,MAAM,0EAA8B;CACpC,MAAM,aAAa,MAAM,KAAK;EAC5B,6DAAiB,YAAY;EAC7B,MAAM;EACN,OAAO;EACP;CACF,CAAC;CACD,MAAM,8BAAc,IAAI,IAAoB;CAE5C,SAAS,MACP,OACA,QACA,SAAS,IACT;EACA,KAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,OAAO,OAAO,SAAS,WAAW,OAAO,KAAK;GACpD,MAAM,OAAO,SAAS,GAAG,OAAO,GAAG,SAAS;GAC5C,MAAM,KAAK,MAAM,KAAK;IACpB,6DAAiB,UAAU;IAC3B,MAAM;IACN,OAAO;IACP;IACA,SAAS,EAAE,KAAK;GAClB,CAAC;GAED,YAAY,IAAI,MAAM,EAAE;GAExB,MAAM,KAAK,QAAQ,IAAI,UAAU;GAEjC,IAAI,OAAO,SAAS,UAAU,MAAM,KAAK,cAAc,IAAI,IAAI;EACjE;CACF;CAEA,MAAM,WAAW,UAAU;CAE3B,OAAO;EAAE;EAAO;EAAY;CAAY;AAC1C;;AAUA,SAAgB,gBACd,WACA,OACA,IACG;CACH,MAAM,gCACJ,SAAS,oBAAoB,OAAO,KAAK;EACvC,iCAAsB,MAAM,MAAM,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;EAElD,gCACE,WACA,OAAO,OAAO,QAAQ;GAAE,GAAG;GAAO;EAAI,CACxC;CACF,CACF;CAEA,KAAK,MAAM,OAAO,QAAQ,QAAQ,SAAS,GAAG;EAC5C,IACE,OAAO,QAAQ,YACf;GACE;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF,EAAE,SAAS,GAAG,GAEd;EAEF,MAAM,aAAa,OAAO,yBAAyB,WAAW,GAAG;EAEjE,IAAI,YAAY,OAAO,eAAe,SAAS,KAAK,UAAU;CAChE;CAEA,OAAO;AACT"}
1
+ {"version":3,"file":"inspection.cjs","names":["Fragment"],"sources":["../../src/create-config/inspection.ts"],"sourcesContent":["import {\n createElement,\n cloneElement,\n Fragment,\n isValidElement,\n type ReactNode,\n forwardRef,\n useLayoutEffect,\n type ComponentType,\n} from 'react';\nimport {\n createInspectionStore,\n inspectionId,\n type InspectionStore,\n type SourceLocation,\n} from '@jfdevelops/react-layout-devtools-core';\nimport type { ResourceDefinition } from '../resource';\n\nexport function inspectDefinition(\n resources: readonly ResourceDefinition[],\n source?: SourceLocation\n) {\n const store = createInspectionStore();\n const definition = store.node({\n id: inspectionId('definition'),\n kind: 'definition',\n label: 'Layout definition',\n source,\n });\n const resourceIds = new Map<string, string>();\n\n function visit(\n items: readonly ResourceDefinition[],\n parent: string,\n prefix = ''\n ) {\n for (const item of items) {\n const slug = typeof item === 'string' ? item : item.value;\n const path = prefix ? `${prefix}.${slug}` : slug;\n const id = store.node({\n id: inspectionId('resource'),\n kind: 'resource',\n label: path,\n source,\n details: { path },\n });\n\n resourceIds.set(path, id);\n\n store.edge(parent, id, 'contains');\n\n if (typeof item !== 'string') visit(item.subResources, id, path);\n }\n }\n\n visit(resources, definition);\n\n return { store, definition, resourceIds };\n}\n\nexport interface ActiveInspection {\n store: InspectionStore;\n layout: string;\n resource?: string;\n state: string;\n}\n\nconst inspectedComposables = new WeakSet<object>();\n\n/** Mark existing roots only; never add wrappers or forward props to user components. */\nexport function markInspectionRoots(\n children: ReactNode,\n owners: readonly string[]\n): ReactNode {\n if (process.env.NODE_ENV === 'production') return children;\n if (Array.isArray(children))\n return children.map((child) => markInspectionRoots(child, owners));\n if (\n !isValidElement<{ children?: ReactNode; 'data-rl-owners'?: string }>(\n children\n )\n )\n return children;\n if (children.type === Fragment) {\n return cloneElement(children, {\n children: markInspectionRoots(children.props.children, owners),\n });\n }\n if (\n typeof children.type !== 'string' &&\n (typeof children.type !== 'object' ||\n !inspectedComposables.has(children.type))\n )\n return children;\n let previous: string[] = [];\n try {\n const parsed: unknown = JSON.parse(\n children.props['data-rl-owners'] ?? '[]'\n );\n if (Array.isArray(parsed))\n previous = parsed.filter((id): id is string => typeof id === 'string');\n } catch {}\n return cloneElement(children, {\n 'data-rl-owners': JSON.stringify([...new Set([...previous, ...owners])]),\n });\n}\n\n/** Preserve composable metadata while measuring committed React instances, not declarations. */\nexport function trackComposable<T extends object>(\n component: T,\n store: InspectionStore,\n id: string\n): T {\n const Tracked = forwardRef<unknown, Record<string, unknown>>(\n function InspectedComposable(props, ref) {\n useLayoutEffect(() => store.mount(id), [store, id]);\n\n const inspectedProps =\n process.env.NODE_ENV === 'production'\n ? props\n : {\n ...props,\n 'data-rl-node': id,\n 'data-rl-composable':\n (component as { displayName?: string }).displayName ??\n 'Composable',\n };\n return createElement(\n component as ComponentType<Record<string, unknown>>,\n ref == null ? inspectedProps : { ...inspectedProps, ref }\n );\n }\n );\n\n inspectedComposables.add(Tracked);\n\n for (const key of Reflect.ownKeys(component)) {\n if (\n typeof key === 'string' &&\n [\n 'name',\n 'length',\n 'prototype',\n 'caller',\n 'arguments',\n '$$typeof',\n 'render',\n 'compare',\n 'type',\n ].includes(key)\n )\n continue;\n\n const descriptor = Object.getOwnPropertyDescriptor(component, key);\n\n if (descriptor) Object.defineProperty(Tracked, key, descriptor);\n }\n\n return Tracked as unknown as T;\n}\n"],"mappings":";;;;AAkBA,SAAgB,kBACd,WACA,QACA;CACA,MAAM,0EAA8B;CACpC,MAAM,aAAa,MAAM,KAAK;EAC5B,6DAAiB,YAAY;EAC7B,MAAM;EACN,OAAO;EACP;CACF,CAAC;CACD,MAAM,8BAAc,IAAI,IAAoB;CAE5C,SAAS,MACP,OACA,QACA,SAAS,IACT;EACA,KAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,OAAO,OAAO,SAAS,WAAW,OAAO,KAAK;GACpD,MAAM,OAAO,SAAS,GAAG,OAAO,GAAG,SAAS;GAC5C,MAAM,KAAK,MAAM,KAAK;IACpB,6DAAiB,UAAU;IAC3B,MAAM;IACN,OAAO;IACP;IACA,SAAS,EAAE,KAAK;GAClB,CAAC;GAED,YAAY,IAAI,MAAM,EAAE;GAExB,MAAM,KAAK,QAAQ,IAAI,UAAU;GAEjC,IAAI,OAAO,SAAS,UAAU,MAAM,KAAK,cAAc,IAAI,IAAI;EACjE;CACF;CAEA,MAAM,WAAW,UAAU;CAE3B,OAAO;EAAE;EAAO;EAAY;CAAY;AAC1C;AASA,MAAM,uCAAuB,IAAI,QAAgB;;AAGjD,SAAgB,oBACd,UACA,QACW;CACX,IAAI,QAAQ,IAAI,aAAa,cAAc,OAAO;CAClD,IAAI,MAAM,QAAQ,QAAQ,GACxB,OAAO,SAAS,KAAK,UAAU,oBAAoB,OAAO,MAAM,CAAC;CACnE,IACE,2BACE,QACF,GAEA,OAAO;CACT,IAAI,SAAS,SAASA,gBACpB,+BAAoB,UAAU,EAC5B,UAAU,oBAAoB,SAAS,MAAM,UAAU,MAAM,EAC/D,CAAC;CAEH,IACE,OAAO,SAAS,SAAS,aACxB,OAAO,SAAS,SAAS,YACxB,CAAC,qBAAqB,IAAI,SAAS,IAAI,IAEzC,OAAO;CACT,IAAI,WAAqB,CAAC;CAC1B,IAAI;EACF,MAAM,SAAkB,KAAK,MAC3B,SAAS,MAAM,qBAAqB,IACtC;EACA,IAAI,MAAM,QAAQ,MAAM,GACtB,WAAW,OAAO,QAAQ,OAAqB,OAAO,OAAO,QAAQ;CACzE,QAAQ,CAAC;CACT,+BAAoB,UAAU,EAC5B,kBAAkB,KAAK,UAAU,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,EACzE,CAAC;AACH;;AAGA,SAAgB,gBACd,WACA,OACA,IACG;CACH,MAAM,gCACJ,SAAS,oBAAoB,OAAO,KAAK;EACvC,iCAAsB,MAAM,MAAM,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;EAElD,MAAM,iBACJ,QAAQ,IAAI,aAAa,eACrB,QACA;GACE,GAAG;GACH,gBAAgB;GAChB,sBACG,UAAuC,eACxC;EACJ;EACN,gCACE,WACA,OAAO,OAAO,iBAAiB;GAAE,GAAG;GAAgB;EAAI,CAC1D;CACF,CACF;CAEA,qBAAqB,IAAI,OAAO;CAEhC,KAAK,MAAM,OAAO,QAAQ,QAAQ,SAAS,GAAG;EAC5C,IACE,OAAO,QAAQ,YACf;GACE;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF,EAAE,SAAS,GAAG,GAEd;EAEF,MAAM,aAAa,OAAO,yBAAyB,WAAW,GAAG;EAEjE,IAAI,YAAY,OAAO,eAAe,SAAS,KAAK,UAAU;CAChE;CAEA,OAAO;AACT"}
@@ -1,4 +1,4 @@
1
- import { createElement, forwardRef, useLayoutEffect } from "react";
1
+ import { Fragment, cloneElement, createElement, forwardRef, isValidElement, useLayoutEffect } from "react";
2
2
  import { createInspectionStore, inspectionId } from "@jfdevelops/react-layout-devtools-core";
3
3
 
4
4
  //#region src/create-config/inspection.ts
@@ -34,15 +34,36 @@ function inspectDefinition(resources, source) {
34
34
  resourceIds
35
35
  };
36
36
  }
37
+ const inspectedComposables = /* @__PURE__ */ new WeakSet();
38
+ /** Mark existing roots only; never add wrappers or forward props to user components. */
39
+ function markInspectionRoots(children, owners) {
40
+ if (process.env.NODE_ENV === "production") return children;
41
+ if (Array.isArray(children)) return children.map((child) => markInspectionRoots(child, owners));
42
+ if (!isValidElement(children)) return children;
43
+ if (children.type === Fragment) return cloneElement(children, { children: markInspectionRoots(children.props.children, owners) });
44
+ if (typeof children.type !== "string" && (typeof children.type !== "object" || !inspectedComposables.has(children.type))) return children;
45
+ let previous = [];
46
+ try {
47
+ const parsed = JSON.parse(children.props["data-rl-owners"] ?? "[]");
48
+ if (Array.isArray(parsed)) previous = parsed.filter((id) => typeof id === "string");
49
+ } catch {}
50
+ return cloneElement(children, { "data-rl-owners": JSON.stringify([...new Set([...previous, ...owners])]) });
51
+ }
37
52
  /** Preserve composable metadata while measuring committed React instances, not declarations. */
38
53
  function trackComposable(component, store, id) {
39
54
  const Tracked = forwardRef(function InspectedComposable(props, ref) {
40
55
  useLayoutEffect(() => store.mount(id), [store, id]);
41
- return createElement(component, ref == null ? props : {
56
+ const inspectedProps = process.env.NODE_ENV === "production" ? props : {
42
57
  ...props,
58
+ "data-rl-node": id,
59
+ "data-rl-composable": component.displayName ?? "Composable"
60
+ };
61
+ return createElement(component, ref == null ? inspectedProps : {
62
+ ...inspectedProps,
43
63
  ref
44
64
  });
45
65
  });
66
+ inspectedComposables.add(Tracked);
46
67
  for (const key of Reflect.ownKeys(component)) {
47
68
  if (typeof key === "string" && [
48
69
  "name",
@@ -62,5 +83,5 @@ function trackComposable(component, store, id) {
62
83
  }
63
84
 
64
85
  //#endregion
65
- export { inspectDefinition, trackComposable };
86
+ export { inspectDefinition, markInspectionRoots, trackComposable };
66
87
  //# sourceMappingURL=inspection.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"inspection.mjs","names":[],"sources":["../../src/create-config/inspection.ts"],"sourcesContent":["import {\n createElement,\n forwardRef,\n useLayoutEffect,\n type ComponentType,\n} from 'react';\nimport {\n createInspectionStore,\n inspectionId,\n type InspectionStore,\n type SourceLocation,\n} from '@jfdevelops/react-layout-devtools-core';\nimport type { ResourceDefinition } from '../resource';\n\nexport function inspectDefinition(\n resources: readonly ResourceDefinition[],\n source?: SourceLocation\n) {\n const store = createInspectionStore();\n const definition = store.node({\n id: inspectionId('definition'),\n kind: 'definition',\n label: 'Layout definition',\n source,\n });\n const resourceIds = new Map<string, string>();\n\n function visit(\n items: readonly ResourceDefinition[],\n parent: string,\n prefix = ''\n ) {\n for (const item of items) {\n const slug = typeof item === 'string' ? item : item.value;\n const path = prefix ? `${prefix}.${slug}` : slug;\n const id = store.node({\n id: inspectionId('resource'),\n kind: 'resource',\n label: path,\n source,\n details: { path },\n });\n\n resourceIds.set(path, id);\n\n store.edge(parent, id, 'contains');\n\n if (typeof item !== 'string') visit(item.subResources, id, path);\n }\n }\n\n visit(resources, definition);\n\n return { store, definition, resourceIds };\n}\n\nexport interface ActiveInspection {\n store: InspectionStore;\n layout: string;\n resource?: string;\n state: string;\n}\n\n/** Preserve composable metadata while measuring committed React instances, not declarations. */\nexport function trackComposable<T extends object>(\n component: T,\n store: InspectionStore,\n id: string\n): T {\n const Tracked = forwardRef<unknown, Record<string, unknown>>(\n function InspectedComposable(props, ref) {\n useLayoutEffect(() => store.mount(id), [store, id]);\n\n return createElement(\n component as ComponentType<Record<string, unknown>>,\n ref == null ? props : { ...props, ref }\n );\n }\n );\n\n for (const key of Reflect.ownKeys(component)) {\n if (\n typeof key === 'string' &&\n [\n 'name',\n 'length',\n 'prototype',\n 'caller',\n 'arguments',\n '$$typeof',\n 'render',\n 'compare',\n 'type',\n ].includes(key)\n )\n continue;\n\n const descriptor = Object.getOwnPropertyDescriptor(component, key);\n\n if (descriptor) Object.defineProperty(Tracked, key, descriptor);\n }\n\n return Tracked as unknown as T;\n}\n"],"mappings":";;;;AAcA,SAAgB,kBACd,WACA,QACA;CACA,MAAM,QAAQ,sBAAsB;CACpC,MAAM,aAAa,MAAM,KAAK;EAC5B,IAAI,aAAa,YAAY;EAC7B,MAAM;EACN,OAAO;EACP;CACF,CAAC;CACD,MAAM,8BAAc,IAAI,IAAoB;CAE5C,SAAS,MACP,OACA,QACA,SAAS,IACT;EACA,KAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,OAAO,OAAO,SAAS,WAAW,OAAO,KAAK;GACpD,MAAM,OAAO,SAAS,GAAG,OAAO,GAAG,SAAS;GAC5C,MAAM,KAAK,MAAM,KAAK;IACpB,IAAI,aAAa,UAAU;IAC3B,MAAM;IACN,OAAO;IACP;IACA,SAAS,EAAE,KAAK;GAClB,CAAC;GAED,YAAY,IAAI,MAAM,EAAE;GAExB,MAAM,KAAK,QAAQ,IAAI,UAAU;GAEjC,IAAI,OAAO,SAAS,UAAU,MAAM,KAAK,cAAc,IAAI,IAAI;EACjE;CACF;CAEA,MAAM,WAAW,UAAU;CAE3B,OAAO;EAAE;EAAO;EAAY;CAAY;AAC1C;;AAUA,SAAgB,gBACd,WACA,OACA,IACG;CACH,MAAM,UAAU,WACd,SAAS,oBAAoB,OAAO,KAAK;EACvC,sBAAsB,MAAM,MAAM,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;EAElD,OAAO,cACL,WACA,OAAO,OAAO,QAAQ;GAAE,GAAG;GAAO;EAAI,CACxC;CACF,CACF;CAEA,KAAK,MAAM,OAAO,QAAQ,QAAQ,SAAS,GAAG;EAC5C,IACE,OAAO,QAAQ,YACf;GACE;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF,EAAE,SAAS,GAAG,GAEd;EAEF,MAAM,aAAa,OAAO,yBAAyB,WAAW,GAAG;EAEjE,IAAI,YAAY,OAAO,eAAe,SAAS,KAAK,UAAU;CAChE;CAEA,OAAO;AACT"}
1
+ {"version":3,"file":"inspection.mjs","names":[],"sources":["../../src/create-config/inspection.ts"],"sourcesContent":["import {\n createElement,\n cloneElement,\n Fragment,\n isValidElement,\n type ReactNode,\n forwardRef,\n useLayoutEffect,\n type ComponentType,\n} from 'react';\nimport {\n createInspectionStore,\n inspectionId,\n type InspectionStore,\n type SourceLocation,\n} from '@jfdevelops/react-layout-devtools-core';\nimport type { ResourceDefinition } from '../resource';\n\nexport function inspectDefinition(\n resources: readonly ResourceDefinition[],\n source?: SourceLocation\n) {\n const store = createInspectionStore();\n const definition = store.node({\n id: inspectionId('definition'),\n kind: 'definition',\n label: 'Layout definition',\n source,\n });\n const resourceIds = new Map<string, string>();\n\n function visit(\n items: readonly ResourceDefinition[],\n parent: string,\n prefix = ''\n ) {\n for (const item of items) {\n const slug = typeof item === 'string' ? item : item.value;\n const path = prefix ? `${prefix}.${slug}` : slug;\n const id = store.node({\n id: inspectionId('resource'),\n kind: 'resource',\n label: path,\n source,\n details: { path },\n });\n\n resourceIds.set(path, id);\n\n store.edge(parent, id, 'contains');\n\n if (typeof item !== 'string') visit(item.subResources, id, path);\n }\n }\n\n visit(resources, definition);\n\n return { store, definition, resourceIds };\n}\n\nexport interface ActiveInspection {\n store: InspectionStore;\n layout: string;\n resource?: string;\n state: string;\n}\n\nconst inspectedComposables = new WeakSet<object>();\n\n/** Mark existing roots only; never add wrappers or forward props to user components. */\nexport function markInspectionRoots(\n children: ReactNode,\n owners: readonly string[]\n): ReactNode {\n if (process.env.NODE_ENV === 'production') return children;\n if (Array.isArray(children))\n return children.map((child) => markInspectionRoots(child, owners));\n if (\n !isValidElement<{ children?: ReactNode; 'data-rl-owners'?: string }>(\n children\n )\n )\n return children;\n if (children.type === Fragment) {\n return cloneElement(children, {\n children: markInspectionRoots(children.props.children, owners),\n });\n }\n if (\n typeof children.type !== 'string' &&\n (typeof children.type !== 'object' ||\n !inspectedComposables.has(children.type))\n )\n return children;\n let previous: string[] = [];\n try {\n const parsed: unknown = JSON.parse(\n children.props['data-rl-owners'] ?? '[]'\n );\n if (Array.isArray(parsed))\n previous = parsed.filter((id): id is string => typeof id === 'string');\n } catch {}\n return cloneElement(children, {\n 'data-rl-owners': JSON.stringify([...new Set([...previous, ...owners])]),\n });\n}\n\n/** Preserve composable metadata while measuring committed React instances, not declarations. */\nexport function trackComposable<T extends object>(\n component: T,\n store: InspectionStore,\n id: string\n): T {\n const Tracked = forwardRef<unknown, Record<string, unknown>>(\n function InspectedComposable(props, ref) {\n useLayoutEffect(() => store.mount(id), [store, id]);\n\n const inspectedProps =\n process.env.NODE_ENV === 'production'\n ? props\n : {\n ...props,\n 'data-rl-node': id,\n 'data-rl-composable':\n (component as { displayName?: string }).displayName ??\n 'Composable',\n };\n return createElement(\n component as ComponentType<Record<string, unknown>>,\n ref == null ? inspectedProps : { ...inspectedProps, ref }\n );\n }\n );\n\n inspectedComposables.add(Tracked);\n\n for (const key of Reflect.ownKeys(component)) {\n if (\n typeof key === 'string' &&\n [\n 'name',\n 'length',\n 'prototype',\n 'caller',\n 'arguments',\n '$$typeof',\n 'render',\n 'compare',\n 'type',\n ].includes(key)\n )\n continue;\n\n const descriptor = Object.getOwnPropertyDescriptor(component, key);\n\n if (descriptor) Object.defineProperty(Tracked, key, descriptor);\n }\n\n return Tracked as unknown as T;\n}\n"],"mappings":";;;;AAkBA,SAAgB,kBACd,WACA,QACA;CACA,MAAM,QAAQ,sBAAsB;CACpC,MAAM,aAAa,MAAM,KAAK;EAC5B,IAAI,aAAa,YAAY;EAC7B,MAAM;EACN,OAAO;EACP;CACF,CAAC;CACD,MAAM,8BAAc,IAAI,IAAoB;CAE5C,SAAS,MACP,OACA,QACA,SAAS,IACT;EACA,KAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,OAAO,OAAO,SAAS,WAAW,OAAO,KAAK;GACpD,MAAM,OAAO,SAAS,GAAG,OAAO,GAAG,SAAS;GAC5C,MAAM,KAAK,MAAM,KAAK;IACpB,IAAI,aAAa,UAAU;IAC3B,MAAM;IACN,OAAO;IACP;IACA,SAAS,EAAE,KAAK;GAClB,CAAC;GAED,YAAY,IAAI,MAAM,EAAE;GAExB,MAAM,KAAK,QAAQ,IAAI,UAAU;GAEjC,IAAI,OAAO,SAAS,UAAU,MAAM,KAAK,cAAc,IAAI,IAAI;EACjE;CACF;CAEA,MAAM,WAAW,UAAU;CAE3B,OAAO;EAAE;EAAO;EAAY;CAAY;AAC1C;AASA,MAAM,uCAAuB,IAAI,QAAgB;;AAGjD,SAAgB,oBACd,UACA,QACW;CACX,IAAI,QAAQ,IAAI,aAAa,cAAc,OAAO;CAClD,IAAI,MAAM,QAAQ,QAAQ,GACxB,OAAO,SAAS,KAAK,UAAU,oBAAoB,OAAO,MAAM,CAAC;CACnE,IACE,CAAC,eACC,QACF,GAEA,OAAO;CACT,IAAI,SAAS,SAAS,UACpB,OAAO,aAAa,UAAU,EAC5B,UAAU,oBAAoB,SAAS,MAAM,UAAU,MAAM,EAC/D,CAAC;CAEH,IACE,OAAO,SAAS,SAAS,aACxB,OAAO,SAAS,SAAS,YACxB,CAAC,qBAAqB,IAAI,SAAS,IAAI,IAEzC,OAAO;CACT,IAAI,WAAqB,CAAC;CAC1B,IAAI;EACF,MAAM,SAAkB,KAAK,MAC3B,SAAS,MAAM,qBAAqB,IACtC;EACA,IAAI,MAAM,QAAQ,MAAM,GACtB,WAAW,OAAO,QAAQ,OAAqB,OAAO,OAAO,QAAQ;CACzE,QAAQ,CAAC;CACT,OAAO,aAAa,UAAU,EAC5B,kBAAkB,KAAK,UAAU,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,EACzE,CAAC;AACH;;AAGA,SAAgB,gBACd,WACA,OACA,IACG;CACH,MAAM,UAAU,WACd,SAAS,oBAAoB,OAAO,KAAK;EACvC,sBAAsB,MAAM,MAAM,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;EAElD,MAAM,iBACJ,QAAQ,IAAI,aAAa,eACrB,QACA;GACE,GAAG;GACH,gBAAgB;GAChB,sBACG,UAAuC,eACxC;EACJ;EACN,OAAO,cACL,WACA,OAAO,OAAO,iBAAiB;GAAE,GAAG;GAAgB;EAAI,CAC1D;CACF,CACF;CAEA,qBAAqB,IAAI,OAAO;CAEhC,KAAK,MAAM,OAAO,QAAQ,QAAQ,SAAS,GAAG;EAC5C,IACE,OAAO,QAAQ,YACf;GACE;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF,EAAE,SAAS,GAAG,GAEd;EAEF,MAAM,aAAa,OAAO,yBAAyB,WAAW,GAAG;EAEjE,IAAI,YAAY,OAAO,eAAe,SAAS,KAAK,UAAU;CAChE;CAEA,OAAO;AACT"}
@@ -15,10 +15,6 @@ function findDefinedLayoutComponent(module, resource) {
15
15
  function createLazyResourceLayout(options, defaults, hooks = {}) {
16
16
  const runtime = options;
17
17
  const resource = runtime.resource;
18
- const states = {
19
- ...defaults,
20
- ...runtime.states
21
- };
22
18
  const loader = require_create_lazy_loader.createLazyLoader({
23
19
  load: runtime.load,
24
20
  select: (module) => findDefinedLayoutComponent(module, resource),
@@ -28,6 +24,10 @@ function createLazyResourceLayout(options, defaults, hooks = {}) {
28
24
  const members = /* @__PURE__ */ new Map();
29
25
  function createMember(member) {
30
26
  function LazyMember(props) {
27
+ const states = {
28
+ ...typeof defaults === "function" ? defaults() : defaults,
29
+ ...runtime.states
30
+ };
31
31
  const Loading = states.Loading;
32
32
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_lazy_boundary.LazyBoundary, {
33
33
  loader,
@@ -1 +1 @@
1
- {"version":3,"file":"lazy-resource-layout.cjs","names":["definedResourceLayoutComponentSymbol","LazyResourceModuleShapeError","createLazyLoader","LazyBoundary","componentPropDefinitionsSymbol"],"sources":["../../src/create-config/lazy-resource-layout.tsx"],"sourcesContent":["import { type ComponentProps, type ComponentType } from 'react';\nimport { LazyResourceModuleShapeError } from '../errors/lazy-resource-error';\nimport { componentPropDefinitionsSymbol } from '@jfdevelops/react-layout-validator';\nimport type { ResourcePath, ResourceDefinition } from '../resource';\nimport { definedResourceLayoutComponentSymbol } from './render-state';\nimport {\n createLazyLoader,\n type LazyResourceLoadHooks,\n} from '../lazy/create-lazy-loader';\nimport { LazyBoundary } from '../lazy/lazy-boundary';\nimport type {\n LazyHandle,\n LazyOptions,\n LazyResourceStates,\n} from '../lazy/types';\nexport type {\n LazyResourceErrorComponent,\n LazyResourceLoadingComponent,\n LazyResourceStates,\n} from '../lazy/types';\nexport type { LazyResourceLoadHooks } from '../lazy/create-lazy-loader';\n\ntype DefinedLayoutComponent = ComponentType<any> & {\n readonly [definedResourceLayoutComponentSymbol]: true;\n};\n\ntype UnwrapDefinedLayout<Export> = Export extends DefinedLayoutComponent\n ? Export\n : Export extends { Root: infer Root extends DefinedLayoutComponent }\n ? Root\n : never;\n\ntype DefinedLayoutFromModule<Module> = UnwrapDefinedLayout<\n Module[keyof Module]\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 LazyHandle &\n Pick<\n DefinedLayoutFromModule<Module>,\n Exclude<keyof DefinedLayoutFromModule<Module>, LazyUnsupportedStatic>\n >;\n\n/** Lazy resource options, sharing import and fallback semantics with lazy states. */\nexport type LazyResourceLayoutOptions<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Module extends Record<string, unknown>,\n> = LazyOptions<Module> & {\n resource: ResourcePath<Resources>;\n states?: LazyResourceStates<ResourcePath<Resources>>;\n};\n\nfunction findDefinedLayoutComponent(\n module: Record<string, unknown>,\n resource: string,\n) {\n const components = Object.values(module)\n .map((value) =>\n typeof value === 'object' && value !== null && 'Root' in value\n ? value.Root\n : value,\n )\n .filter(\n (value): value is DefinedLayoutComponent =>\n typeof value === 'function' &&\n definedResourceLayoutComponentSymbol in value,\n );\n if (components.length !== 1)\n throw new LazyResourceModuleShapeError(resource, components.length);\n return components[0];\n}\n\n/** Cached resource component and its compound states, backed by the shared loader. */\nexport function createLazyResourceLayout<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Module extends Record<string, unknown>,\n>(\n options: LazyResourceLayoutOptions<Resources, Module>,\n defaults: LazyResourceStates<any>,\n hooks: LazyResourceLoadHooks = {},\n): LazyResourceLayoutComponent<Module> {\n const runtime = options as unknown as LazyOptions<Module> & {\n resource: string;\n states?: LazyResourceStates;\n };\n const resource = runtime.resource;\n const states = { ...defaults, ...runtime.states } as LazyResourceStates;\n const loader = createLazyLoader({\n load: runtime.load,\n select: (module) => findDefinedLayoutComponent(module, resource),\n label: resource,\n hooks,\n });\n const members = new Map<string, ComponentType<any>>();\n function createMember(member?: string) {\n function LazyMember(props: Record<string, unknown>) {\n const Loading = states.Loading;\n return (\n <LazyBoundary\n loader={loader}\n member={member}\n resource={resource}\n componentProps={props}\n ErrorComponent={states.Error}\n onMount={hooks.onMount}\n fallback={\n runtime.fallback !== undefined ? (\n runtime.fallback\n ) : Loading ? (\n <Loading resource={resource} />\n ) : null\n }\n />\n );\n }\n LazyMember.displayName = `LazyResource(${resource})${member ? `.${member}` : ''}`;\n Object.defineProperties(LazyMember, {\n preload: { value: loader.preload },\n status: { get: () => loader.status },\n });\n return LazyMember;\n }\n const Component = createMember();\n const reservedStatics = new Set<PropertyKey>([\n 'makeComposable',\n 'props',\n 'resource',\n componentPropDefinitionsSymbol,\n definedResourceLayoutComponentSymbol,\n 'contextTypes',\n 'childContextTypes',\n 'contextType',\n 'propTypes',\n 'defaultProps',\n 'getDerivedStateFromProps',\n 'getDerivedStateFromError',\n 'getDefaultProps',\n '$$typeof',\n '_payload',\n '_init',\n 'render',\n 'compare',\n 'type',\n 'then',\n 'catch',\n 'finally',\n 'toJSON',\n 'asymmetricMatch',\n '__esModule',\n 'default',\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 if (\n typeof property !== 'string' ||\n reservedStatics.has(property) ||\n !/^[A-Z]/.test(property)\n )\n return undefined;\n let component = members.get(property);\n if (!component) {\n component = createMember(property);\n members.set(property, component);\n }\n return component;\n },\n has: (target, property) => Reflect.has(target, property),\n }) as unknown as LazyResourceLayoutComponent<Module>;\n}\n"],"mappings":";;;;;;;;AAkEA,SAAS,2BACP,QACA,UACA;CACA,MAAM,aAAa,OAAO,OAAO,MAAM,EACpC,KAAK,UACJ,OAAO,UAAU,YAAY,UAAU,QAAQ,UAAU,QACrD,MAAM,OACN,KACN,EACC,QACE,UACC,OAAO,UAAU,cACjBA,6DAAwC,KAC5C;CACF,IAAI,WAAW,WAAW,GACxB,MAAM,IAAIC,yDAA6B,UAAU,WAAW,MAAM;CACpE,OAAO,WAAW;AACpB;;AAGA,SAAgB,yBAId,SACA,UACA,QAA+B,CAAC,GACK;CACrC,MAAM,UAAU;CAIhB,MAAM,WAAW,QAAQ;CACzB,MAAM,SAAS;EAAE,GAAG;EAAU,GAAG,QAAQ;CAAO;CAChD,MAAM,SAASC,4CAAiB;EAC9B,MAAM,QAAQ;EACd,SAAS,WAAW,2BAA2B,QAAQ,QAAQ;EAC/D,OAAO;EACP;CACF,CAAC;CACD,MAAM,0BAAU,IAAI,IAAgC;CACpD,SAAS,aAAa,QAAiB;EACrC,SAAS,WAAW,OAAgC;GAClD,MAAM,UAAU,OAAO;GACvB,OACE,2CAACC,oCAAD;IACU;IACA;IACE;IACV,gBAAgB;IAChB,gBAAgB,OAAO;IACvB,SAAS,MAAM;IACf,UACE,QAAQ,aAAa,SACnB,QAAQ,WACN,UACF,2CAAC,SAAD,EAAmB,SAAW,KAC5B;GAEP;EAEL;EACA,WAAW,cAAc,gBAAgB,SAAS,GAAG,SAAS,IAAI,WAAW;EAC7E,OAAO,iBAAiB,YAAY;GAClC,SAAS,EAAE,OAAO,OAAO,QAAQ;GACjC,QAAQ,EAAE,WAAW,OAAO,OAAO;EACrC,CAAC;EACD,OAAO;CACT;CACA,MAAM,YAAY,aAAa;CAC/B,MAAM,kBAAkB,IAAI,IAAiB;EAC3C;EACA;EACA;EACAC;EACAJ;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CACD,OAAO,IAAI,MAAM,WAAW;EAC1B,IAAI,QAAQ,UAAU,UAAU;GAC9B,IAAI,QAAQ,IAAI,QAAQ,QAAQ,GAC9B,OAAO,QAAQ,IAAI,QAAQ,UAAU,QAAQ;GAC/C,IACE,OAAO,aAAa,YACpB,gBAAgB,IAAI,QAAQ,KAC5B,CAAC,SAAS,KAAK,QAAQ,GAEvB,OAAO;GACT,IAAI,YAAY,QAAQ,IAAI,QAAQ;GACpC,IAAI,CAAC,WAAW;IACd,YAAY,aAAa,QAAQ;IACjC,QAAQ,IAAI,UAAU,SAAS;GACjC;GACA,OAAO;EACT;EACA,MAAM,QAAQ,aAAa,QAAQ,IAAI,QAAQ,QAAQ;CACzD,CAAC;AACH"}
1
+ {"version":3,"file":"lazy-resource-layout.cjs","names":["definedResourceLayoutComponentSymbol","LazyResourceModuleShapeError","createLazyLoader","LazyBoundary","componentPropDefinitionsSymbol"],"sources":["../../src/create-config/lazy-resource-layout.tsx"],"sourcesContent":["import { type ComponentProps, type ComponentType } from 'react';\nimport { LazyResourceModuleShapeError } from '../errors/lazy-resource-error';\nimport { componentPropDefinitionsSymbol } from '@jfdevelops/react-layout-validator';\nimport type { ResourcePath, ResourceDefinition } from '../resource';\nimport { definedResourceLayoutComponentSymbol } from './render-state';\nimport {\n createLazyLoader,\n type LazyResourceLoadHooks,\n} from '../lazy/create-lazy-loader';\nimport { LazyBoundary } from '../lazy/lazy-boundary';\nimport type {\n LazyHandle,\n LazyOptions,\n LazyResourceStates,\n} from '../lazy/types';\nexport type {\n LazyResourceErrorComponent,\n LazyResourceLoadingComponent,\n LazyResourceStates,\n} from '../lazy/types';\nexport type { LazyResourceLoadHooks } from '../lazy/create-lazy-loader';\n\ntype DefinedLayoutComponent = ComponentType<any> & {\n readonly [definedResourceLayoutComponentSymbol]: true;\n};\n\ntype UnwrapDefinedLayout<Export> = Export extends DefinedLayoutComponent\n ? Export\n : Export extends { Root: infer Root extends DefinedLayoutComponent }\n ? Root\n : never;\n\ntype DefinedLayoutFromModule<Module> = UnwrapDefinedLayout<\n Module[keyof Module]\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 LazyHandle &\n Pick<\n DefinedLayoutFromModule<Module>,\n Exclude<keyof DefinedLayoutFromModule<Module>, LazyUnsupportedStatic>\n >;\n\n/** Lazy resource options, sharing import and fallback semantics with lazy states. */\nexport type LazyResourceLayoutOptions<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Module extends Record<string, unknown>,\n> = LazyOptions<Module> & {\n resource: ResourcePath<Resources>;\n states?: LazyResourceStates<ResourcePath<Resources>>;\n};\n\nfunction findDefinedLayoutComponent(\n module: Record<string, unknown>,\n resource: string,\n) {\n const components = Object.values(module)\n .map((value) =>\n typeof value === 'object' && value !== null && 'Root' in value\n ? value.Root\n : value,\n )\n .filter(\n (value): value is DefinedLayoutComponent =>\n typeof value === 'function' &&\n definedResourceLayoutComponentSymbol in value,\n );\n if (components.length !== 1)\n throw new LazyResourceModuleShapeError(resource, components.length);\n return components[0];\n}\n\n/** Cached resource component and its compound states, backed by the shared loader. */\nexport function createLazyResourceLayout<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Module extends Record<string, unknown>,\n>(\n options: LazyResourceLayoutOptions<Resources, Module>,\n defaults: LazyResourceStates<any> | (() => LazyResourceStates<any>),\n hooks: LazyResourceLoadHooks = {},\n): LazyResourceLayoutComponent<Module> {\n const runtime = options as unknown as LazyOptions<Module> & {\n resource: string;\n states?: LazyResourceStates;\n };\n const resource = runtime.resource;\n const loader = createLazyLoader({\n load: runtime.load,\n select: (module) => findDefinedLayoutComponent(module, resource),\n label: resource,\n hooks,\n });\n const members = new Map<string, ComponentType<any>>();\n function createMember(member?: string) {\n function LazyMember(props: Record<string, unknown>) {\n const states = { ...(typeof defaults === 'function' ? defaults() : defaults), ...runtime.states } as LazyResourceStates;\n const Loading = states.Loading;\n return (\n <LazyBoundary\n loader={loader}\n member={member}\n resource={resource}\n componentProps={props}\n ErrorComponent={states.Error}\n onMount={hooks.onMount}\n fallback={\n runtime.fallback !== undefined ? (\n runtime.fallback\n ) : Loading ? (\n <Loading resource={resource} />\n ) : null\n }\n />\n );\n }\n LazyMember.displayName = `LazyResource(${resource})${member ? `.${member}` : ''}`;\n Object.defineProperties(LazyMember, {\n preload: { value: loader.preload },\n status: { get: () => loader.status },\n });\n return LazyMember;\n }\n const Component = createMember();\n const reservedStatics = new Set<PropertyKey>([\n 'makeComposable',\n 'props',\n 'resource',\n componentPropDefinitionsSymbol,\n definedResourceLayoutComponentSymbol,\n 'contextTypes',\n 'childContextTypes',\n 'contextType',\n 'propTypes',\n 'defaultProps',\n 'getDerivedStateFromProps',\n 'getDerivedStateFromError',\n 'getDefaultProps',\n '$$typeof',\n '_payload',\n '_init',\n 'render',\n 'compare',\n 'type',\n 'then',\n 'catch',\n 'finally',\n 'toJSON',\n 'asymmetricMatch',\n '__esModule',\n 'default',\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 if (\n typeof property !== 'string' ||\n reservedStatics.has(property) ||\n !/^[A-Z]/.test(property)\n )\n return undefined;\n let component = members.get(property);\n if (!component) {\n component = createMember(property);\n members.set(property, component);\n }\n return component;\n },\n has: (target, property) => Reflect.has(target, property),\n }) as unknown as LazyResourceLayoutComponent<Module>;\n}\n"],"mappings":";;;;;;;;AAkEA,SAAS,2BACP,QACA,UACA;CACA,MAAM,aAAa,OAAO,OAAO,MAAM,EACpC,KAAK,UACJ,OAAO,UAAU,YAAY,UAAU,QAAQ,UAAU,QACrD,MAAM,OACN,KACN,EACC,QACE,UACC,OAAO,UAAU,cACjBA,6DAAwC,KAC5C;CACF,IAAI,WAAW,WAAW,GACxB,MAAM,IAAIC,yDAA6B,UAAU,WAAW,MAAM;CACpE,OAAO,WAAW;AACpB;;AAGA,SAAgB,yBAId,SACA,UACA,QAA+B,CAAC,GACK;CACrC,MAAM,UAAU;CAIhB,MAAM,WAAW,QAAQ;CACzB,MAAM,SAASC,4CAAiB;EAC9B,MAAM,QAAQ;EACd,SAAS,WAAW,2BAA2B,QAAQ,QAAQ;EAC/D,OAAO;EACP;CACF,CAAC;CACD,MAAM,0BAAU,IAAI,IAAgC;CACpD,SAAS,aAAa,QAAiB;EACrC,SAAS,WAAW,OAAgC;GAClD,MAAM,SAAS;IAAE,GAAI,OAAO,aAAa,aAAa,SAAS,IAAI;IAAW,GAAG,QAAQ;GAAO;GAChG,MAAM,UAAU,OAAO;GACvB,OACE,2CAACC,oCAAD;IACU;IACA;IACE;IACV,gBAAgB;IAChB,gBAAgB,OAAO;IACvB,SAAS,MAAM;IACf,UACE,QAAQ,aAAa,SACnB,QAAQ,WACN,UACF,2CAAC,SAAD,EAAmB,SAAW,KAC5B;GAEP;EAEL;EACA,WAAW,cAAc,gBAAgB,SAAS,GAAG,SAAS,IAAI,WAAW;EAC7E,OAAO,iBAAiB,YAAY;GAClC,SAAS,EAAE,OAAO,OAAO,QAAQ;GACjC,QAAQ,EAAE,WAAW,OAAO,OAAO;EACrC,CAAC;EACD,OAAO;CACT;CACA,MAAM,YAAY,aAAa;CAC/B,MAAM,kBAAkB,IAAI,IAAiB;EAC3C;EACA;EACA;EACAC;EACAJ;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CACD,OAAO,IAAI,MAAM,WAAW;EAC1B,IAAI,QAAQ,UAAU,UAAU;GAC9B,IAAI,QAAQ,IAAI,QAAQ,QAAQ,GAC9B,OAAO,QAAQ,IAAI,QAAQ,UAAU,QAAQ;GAC/C,IACE,OAAO,aAAa,YACpB,gBAAgB,IAAI,QAAQ,KAC5B,CAAC,SAAS,KAAK,QAAQ,GAEvB,OAAO;GACT,IAAI,YAAY,QAAQ,IAAI,QAAQ;GACpC,IAAI,CAAC,WAAW;IACd,YAAY,aAAa,QAAQ;IACjC,QAAQ,IAAI,UAAU,SAAS;GACjC;GACA,OAAO;EACT;EACA,MAAM,QAAQ,aAAa,QAAQ,IAAI,QAAQ,QAAQ;CACzD,CAAC;AACH"}
@@ -26,7 +26,7 @@ type LazyResourceLayoutOptions<Resources extends ReadonlyArray<ResourceDefinitio
26
26
  states?: LazyResourceStates<ResourcePath<Resources>>;
27
27
  };
28
28
  /** Cached resource component and its compound states, backed by the shared loader. */
29
- declare function createLazyResourceLayout<Resources extends ReadonlyArray<ResourceDefinition>, Module extends Record<string, unknown>>(options: LazyResourceLayoutOptions<Resources, Module>, defaults: LazyResourceStates<any>, hooks?: LazyResourceLoadHooks): LazyResourceLayoutComponent<Module>;
29
+ declare function createLazyResourceLayout<Resources extends ReadonlyArray<ResourceDefinition>, Module extends Record<string, unknown>>(options: LazyResourceLayoutOptions<Resources, Module>, defaults: LazyResourceStates<any> | (() => LazyResourceStates<any>), hooks?: LazyResourceLoadHooks): LazyResourceLayoutComponent<Module>;
30
30
  //#endregion
31
31
  export { LazyResourceLayoutComponent, LazyResourceLayoutOptions, createLazyResourceLayout };
32
32
  //# sourceMappingURL=lazy-resource-layout.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lazy-resource-layout.d.cts","names":[],"sources":["../../src/create-config/lazy-resource-layout.tsx"],"mappings":";;;;;;;;KAsBK,sBAAA,GAAyB,aAAA;EAAA,UAClB,oCAAoC;AAAA;AAAA,KAG3C,mBAAA,WAA8B,MAAA,SAAe,sBAAA,GAC9C,MAAA,GACA,MAAA;EAAiB,IAAA,qBAAyB,sBAAA;AAAA,IACxC,IAAA;AAAA,KAGD,uBAAA,WAAkC,mBAAA,CACrC,MAAA,OAAa,MAAA;AAAA,KAGV,qBAAA,oDAIM,8BAAA,UACA,oCAAoC;;;;;;KAOnC,2BAAA,WAAsC,aAAA,CAChD,cAAA,CAAe,uBAAA,CAAwB,MAAA,MAEvC,UAAA,GACA,IAAA,CACE,uBAAA,CAAwB,MAAA,GACxB,OAAA,OAAc,uBAAA,CAAwB,MAAA,GAAS,qBAAA;;KAIvC,yBAAA,mBACQ,aAAA,CAAc,kBAAA,kBACjB,MAAA,qBACb,WAAA,CAAY,MAAA;EACd,QAAA,EAAU,YAAA,CAAa,SAAA;EACvB,MAAA,GAAS,kBAAA,CAAmB,YAAA,CAAa,SAAA;AAAA;;iBAwB3B,wBAAA,mBACI,aAAA,CAAc,kBAAA,kBACjB,MAAA,mBAEf,OAAA,EAAS,yBAAA,CAA0B,SAAA,EAAW,MAAA,GAC9C,QAAA,EAAU,kBAAA,OACV,KAAA,GAAO,qBAAA,GACN,2BAAA,CAA4B,MAAA"}
1
+ {"version":3,"file":"lazy-resource-layout.d.cts","names":[],"sources":["../../src/create-config/lazy-resource-layout.tsx"],"mappings":";;;;;;;;KAsBK,sBAAA,GAAyB,aAAA;EAAA,UAClB,oCAAoC;AAAA;AAAA,KAG3C,mBAAA,WAA8B,MAAA,SAAe,sBAAA,GAC9C,MAAA,GACA,MAAA;EAAiB,IAAA,qBAAyB,sBAAA;AAAA,IACxC,IAAA;AAAA,KAGD,uBAAA,WAAkC,mBAAA,CACrC,MAAA,OAAa,MAAA;AAAA,KAGV,qBAAA,oDAIM,8BAAA,UACA,oCAAoC;;;;;;KAOnC,2BAAA,WAAsC,aAAA,CAChD,cAAA,CAAe,uBAAA,CAAwB,MAAA,MAEvC,UAAA,GACA,IAAA,CACE,uBAAA,CAAwB,MAAA,GACxB,OAAA,OAAc,uBAAA,CAAwB,MAAA,GAAS,qBAAA;;KAIvC,yBAAA,mBACQ,aAAA,CAAc,kBAAA,kBACjB,MAAA,qBACb,WAAA,CAAY,MAAA;EACd,QAAA,EAAU,YAAA,CAAa,SAAA;EACvB,MAAA,GAAS,kBAAA,CAAmB,YAAA,CAAa,SAAA;AAAA;;iBAwB3B,wBAAA,mBACI,aAAA,CAAc,kBAAA,kBACjB,MAAA,mBAEf,OAAA,EAAS,yBAAA,CAA0B,SAAA,EAAW,MAAA,GAC9C,QAAA,EAAU,kBAAA,eAAiC,kBAAA,QAC3C,KAAA,GAAO,qBAAA,GACN,2BAAA,CAA4B,MAAA"}
@@ -26,7 +26,7 @@ type LazyResourceLayoutOptions<Resources extends ReadonlyArray<ResourceDefinitio
26
26
  states?: LazyResourceStates<ResourcePath<Resources>>;
27
27
  };
28
28
  /** Cached resource component and its compound states, backed by the shared loader. */
29
- declare function createLazyResourceLayout<Resources extends ReadonlyArray<ResourceDefinition>, Module extends Record<string, unknown>>(options: LazyResourceLayoutOptions<Resources, Module>, defaults: LazyResourceStates<any>, hooks?: LazyResourceLoadHooks): LazyResourceLayoutComponent<Module>;
29
+ declare function createLazyResourceLayout<Resources extends ReadonlyArray<ResourceDefinition>, Module extends Record<string, unknown>>(options: LazyResourceLayoutOptions<Resources, Module>, defaults: LazyResourceStates<any> | (() => LazyResourceStates<any>), hooks?: LazyResourceLoadHooks): LazyResourceLayoutComponent<Module>;
30
30
  //#endregion
31
31
  export { LazyResourceLayoutComponent, LazyResourceLayoutOptions, createLazyResourceLayout };
32
32
  //# sourceMappingURL=lazy-resource-layout.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lazy-resource-layout.d.mts","names":[],"sources":["../../src/create-config/lazy-resource-layout.tsx"],"mappings":";;;;;;;;KAsBK,sBAAA,GAAyB,aAAA;EAAA,UAClB,oCAAoC;AAAA;AAAA,KAG3C,mBAAA,WAA8B,MAAA,SAAe,sBAAA,GAC9C,MAAA,GACA,MAAA;EAAiB,IAAA,qBAAyB,sBAAA;AAAA,IACxC,IAAA;AAAA,KAGD,uBAAA,WAAkC,mBAAA,CACrC,MAAA,OAAa,MAAA;AAAA,KAGV,qBAAA,oDAIM,8BAAA,UACA,oCAAoC;;;;;;KAOnC,2BAAA,WAAsC,aAAA,CAChD,cAAA,CAAe,uBAAA,CAAwB,MAAA,MAEvC,UAAA,GACA,IAAA,CACE,uBAAA,CAAwB,MAAA,GACxB,OAAA,OAAc,uBAAA,CAAwB,MAAA,GAAS,qBAAA;;KAIvC,yBAAA,mBACQ,aAAA,CAAc,kBAAA,kBACjB,MAAA,qBACb,WAAA,CAAY,MAAA;EACd,QAAA,EAAU,YAAA,CAAa,SAAA;EACvB,MAAA,GAAS,kBAAA,CAAmB,YAAA,CAAa,SAAA;AAAA;;iBAwB3B,wBAAA,mBACI,aAAA,CAAc,kBAAA,kBACjB,MAAA,mBAEf,OAAA,EAAS,yBAAA,CAA0B,SAAA,EAAW,MAAA,GAC9C,QAAA,EAAU,kBAAA,OACV,KAAA,GAAO,qBAAA,GACN,2BAAA,CAA4B,MAAA"}
1
+ {"version":3,"file":"lazy-resource-layout.d.mts","names":[],"sources":["../../src/create-config/lazy-resource-layout.tsx"],"mappings":";;;;;;;;KAsBK,sBAAA,GAAyB,aAAA;EAAA,UAClB,oCAAoC;AAAA;AAAA,KAG3C,mBAAA,WAA8B,MAAA,SAAe,sBAAA,GAC9C,MAAA,GACA,MAAA;EAAiB,IAAA,qBAAyB,sBAAA;AAAA,IACxC,IAAA;AAAA,KAGD,uBAAA,WAAkC,mBAAA,CACrC,MAAA,OAAa,MAAA;AAAA,KAGV,qBAAA,oDAIM,8BAAA,UACA,oCAAoC;;;;;;KAOnC,2BAAA,WAAsC,aAAA,CAChD,cAAA,CAAe,uBAAA,CAAwB,MAAA,MAEvC,UAAA,GACA,IAAA,CACE,uBAAA,CAAwB,MAAA,GACxB,OAAA,OAAc,uBAAA,CAAwB,MAAA,GAAS,qBAAA;;KAIvC,yBAAA,mBACQ,aAAA,CAAc,kBAAA,kBACjB,MAAA,qBACb,WAAA,CAAY,MAAA;EACd,QAAA,EAAU,YAAA,CAAa,SAAA;EACvB,MAAA,GAAS,kBAAA,CAAmB,YAAA,CAAa,SAAA;AAAA;;iBAwB3B,wBAAA,mBACI,aAAA,CAAc,kBAAA,kBACjB,MAAA,mBAEf,OAAA,EAAS,yBAAA,CAA0B,SAAA,EAAW,MAAA,GAC9C,QAAA,EAAU,kBAAA,eAAiC,kBAAA,QAC3C,KAAA,GAAO,qBAAA,GACN,2BAAA,CAA4B,MAAA"}
@@ -15,10 +15,6 @@ function findDefinedLayoutComponent(module, resource) {
15
15
  function createLazyResourceLayout(options, defaults, hooks = {}) {
16
16
  const runtime = options;
17
17
  const resource = runtime.resource;
18
- const states = {
19
- ...defaults,
20
- ...runtime.states
21
- };
22
18
  const loader = createLazyLoader({
23
19
  load: runtime.load,
24
20
  select: (module) => findDefinedLayoutComponent(module, resource),
@@ -28,6 +24,10 @@ function createLazyResourceLayout(options, defaults, hooks = {}) {
28
24
  const members = /* @__PURE__ */ new Map();
29
25
  function createMember(member) {
30
26
  function LazyMember(props) {
27
+ const states = {
28
+ ...typeof defaults === "function" ? defaults() : defaults,
29
+ ...runtime.states
30
+ };
31
31
  const Loading = states.Loading;
32
32
  return /* @__PURE__ */ jsx(LazyBoundary, {
33
33
  loader,
@@ -1 +1 @@
1
- {"version":3,"file":"lazy-resource-layout.mjs","names":[],"sources":["../../src/create-config/lazy-resource-layout.tsx"],"sourcesContent":["import { type ComponentProps, type ComponentType } from 'react';\nimport { LazyResourceModuleShapeError } from '../errors/lazy-resource-error';\nimport { componentPropDefinitionsSymbol } from '@jfdevelops/react-layout-validator';\nimport type { ResourcePath, ResourceDefinition } from '../resource';\nimport { definedResourceLayoutComponentSymbol } from './render-state';\nimport {\n createLazyLoader,\n type LazyResourceLoadHooks,\n} from '../lazy/create-lazy-loader';\nimport { LazyBoundary } from '../lazy/lazy-boundary';\nimport type {\n LazyHandle,\n LazyOptions,\n LazyResourceStates,\n} from '../lazy/types';\nexport type {\n LazyResourceErrorComponent,\n LazyResourceLoadingComponent,\n LazyResourceStates,\n} from '../lazy/types';\nexport type { LazyResourceLoadHooks } from '../lazy/create-lazy-loader';\n\ntype DefinedLayoutComponent = ComponentType<any> & {\n readonly [definedResourceLayoutComponentSymbol]: true;\n};\n\ntype UnwrapDefinedLayout<Export> = Export extends DefinedLayoutComponent\n ? Export\n : Export extends { Root: infer Root extends DefinedLayoutComponent }\n ? Root\n : never;\n\ntype DefinedLayoutFromModule<Module> = UnwrapDefinedLayout<\n Module[keyof Module]\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 LazyHandle &\n Pick<\n DefinedLayoutFromModule<Module>,\n Exclude<keyof DefinedLayoutFromModule<Module>, LazyUnsupportedStatic>\n >;\n\n/** Lazy resource options, sharing import and fallback semantics with lazy states. */\nexport type LazyResourceLayoutOptions<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Module extends Record<string, unknown>,\n> = LazyOptions<Module> & {\n resource: ResourcePath<Resources>;\n states?: LazyResourceStates<ResourcePath<Resources>>;\n};\n\nfunction findDefinedLayoutComponent(\n module: Record<string, unknown>,\n resource: string,\n) {\n const components = Object.values(module)\n .map((value) =>\n typeof value === 'object' && value !== null && 'Root' in value\n ? value.Root\n : value,\n )\n .filter(\n (value): value is DefinedLayoutComponent =>\n typeof value === 'function' &&\n definedResourceLayoutComponentSymbol in value,\n );\n if (components.length !== 1)\n throw new LazyResourceModuleShapeError(resource, components.length);\n return components[0];\n}\n\n/** Cached resource component and its compound states, backed by the shared loader. */\nexport function createLazyResourceLayout<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Module extends Record<string, unknown>,\n>(\n options: LazyResourceLayoutOptions<Resources, Module>,\n defaults: LazyResourceStates<any>,\n hooks: LazyResourceLoadHooks = {},\n): LazyResourceLayoutComponent<Module> {\n const runtime = options as unknown as LazyOptions<Module> & {\n resource: string;\n states?: LazyResourceStates;\n };\n const resource = runtime.resource;\n const states = { ...defaults, ...runtime.states } as LazyResourceStates;\n const loader = createLazyLoader({\n load: runtime.load,\n select: (module) => findDefinedLayoutComponent(module, resource),\n label: resource,\n hooks,\n });\n const members = new Map<string, ComponentType<any>>();\n function createMember(member?: string) {\n function LazyMember(props: Record<string, unknown>) {\n const Loading = states.Loading;\n return (\n <LazyBoundary\n loader={loader}\n member={member}\n resource={resource}\n componentProps={props}\n ErrorComponent={states.Error}\n onMount={hooks.onMount}\n fallback={\n runtime.fallback !== undefined ? (\n runtime.fallback\n ) : Loading ? (\n <Loading resource={resource} />\n ) : null\n }\n />\n );\n }\n LazyMember.displayName = `LazyResource(${resource})${member ? `.${member}` : ''}`;\n Object.defineProperties(LazyMember, {\n preload: { value: loader.preload },\n status: { get: () => loader.status },\n });\n return LazyMember;\n }\n const Component = createMember();\n const reservedStatics = new Set<PropertyKey>([\n 'makeComposable',\n 'props',\n 'resource',\n componentPropDefinitionsSymbol,\n definedResourceLayoutComponentSymbol,\n 'contextTypes',\n 'childContextTypes',\n 'contextType',\n 'propTypes',\n 'defaultProps',\n 'getDerivedStateFromProps',\n 'getDerivedStateFromError',\n 'getDefaultProps',\n '$$typeof',\n '_payload',\n '_init',\n 'render',\n 'compare',\n 'type',\n 'then',\n 'catch',\n 'finally',\n 'toJSON',\n 'asymmetricMatch',\n '__esModule',\n 'default',\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 if (\n typeof property !== 'string' ||\n reservedStatics.has(property) ||\n !/^[A-Z]/.test(property)\n )\n return undefined;\n let component = members.get(property);\n if (!component) {\n component = createMember(property);\n members.set(property, component);\n }\n return component;\n },\n has: (target, property) => Reflect.has(target, property),\n }) as unknown as LazyResourceLayoutComponent<Module>;\n}\n"],"mappings":";;;;;;;;AAkEA,SAAS,2BACP,QACA,UACA;CACA,MAAM,aAAa,OAAO,OAAO,MAAM,EACpC,KAAK,UACJ,OAAO,UAAU,YAAY,UAAU,QAAQ,UAAU,QACrD,MAAM,OACN,KACN,EACC,QACE,UACC,OAAO,UAAU,cACjB,wCAAwC,KAC5C;CACF,IAAI,WAAW,WAAW,GACxB,MAAM,IAAI,6BAA6B,UAAU,WAAW,MAAM;CACpE,OAAO,WAAW;AACpB;;AAGA,SAAgB,yBAId,SACA,UACA,QAA+B,CAAC,GACK;CACrC,MAAM,UAAU;CAIhB,MAAM,WAAW,QAAQ;CACzB,MAAM,SAAS;EAAE,GAAG;EAAU,GAAG,QAAQ;CAAO;CAChD,MAAM,SAAS,iBAAiB;EAC9B,MAAM,QAAQ;EACd,SAAS,WAAW,2BAA2B,QAAQ,QAAQ;EAC/D,OAAO;EACP;CACF,CAAC;CACD,MAAM,0BAAU,IAAI,IAAgC;CACpD,SAAS,aAAa,QAAiB;EACrC,SAAS,WAAW,OAAgC;GAClD,MAAM,UAAU,OAAO;GACvB,OACE,oBAAC,cAAD;IACU;IACA;IACE;IACV,gBAAgB;IAChB,gBAAgB,OAAO;IACvB,SAAS,MAAM;IACf,UACE,QAAQ,aAAa,SACnB,QAAQ,WACN,UACF,oBAAC,SAAD,EAAmB,SAAW,KAC5B;GAEP;EAEL;EACA,WAAW,cAAc,gBAAgB,SAAS,GAAG,SAAS,IAAI,WAAW;EAC7E,OAAO,iBAAiB,YAAY;GAClC,SAAS,EAAE,OAAO,OAAO,QAAQ;GACjC,QAAQ,EAAE,WAAW,OAAO,OAAO;EACrC,CAAC;EACD,OAAO;CACT;CACA,MAAM,YAAY,aAAa;CAC/B,MAAM,kBAAkB,IAAI,IAAiB;EAC3C;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CACD,OAAO,IAAI,MAAM,WAAW;EAC1B,IAAI,QAAQ,UAAU,UAAU;GAC9B,IAAI,QAAQ,IAAI,QAAQ,QAAQ,GAC9B,OAAO,QAAQ,IAAI,QAAQ,UAAU,QAAQ;GAC/C,IACE,OAAO,aAAa,YACpB,gBAAgB,IAAI,QAAQ,KAC5B,CAAC,SAAS,KAAK,QAAQ,GAEvB,OAAO;GACT,IAAI,YAAY,QAAQ,IAAI,QAAQ;GACpC,IAAI,CAAC,WAAW;IACd,YAAY,aAAa,QAAQ;IACjC,QAAQ,IAAI,UAAU,SAAS;GACjC;GACA,OAAO;EACT;EACA,MAAM,QAAQ,aAAa,QAAQ,IAAI,QAAQ,QAAQ;CACzD,CAAC;AACH"}
1
+ {"version":3,"file":"lazy-resource-layout.mjs","names":[],"sources":["../../src/create-config/lazy-resource-layout.tsx"],"sourcesContent":["import { type ComponentProps, type ComponentType } from 'react';\nimport { LazyResourceModuleShapeError } from '../errors/lazy-resource-error';\nimport { componentPropDefinitionsSymbol } from '@jfdevelops/react-layout-validator';\nimport type { ResourcePath, ResourceDefinition } from '../resource';\nimport { definedResourceLayoutComponentSymbol } from './render-state';\nimport {\n createLazyLoader,\n type LazyResourceLoadHooks,\n} from '../lazy/create-lazy-loader';\nimport { LazyBoundary } from '../lazy/lazy-boundary';\nimport type {\n LazyHandle,\n LazyOptions,\n LazyResourceStates,\n} from '../lazy/types';\nexport type {\n LazyResourceErrorComponent,\n LazyResourceLoadingComponent,\n LazyResourceStates,\n} from '../lazy/types';\nexport type { LazyResourceLoadHooks } from '../lazy/create-lazy-loader';\n\ntype DefinedLayoutComponent = ComponentType<any> & {\n readonly [definedResourceLayoutComponentSymbol]: true;\n};\n\ntype UnwrapDefinedLayout<Export> = Export extends DefinedLayoutComponent\n ? Export\n : Export extends { Root: infer Root extends DefinedLayoutComponent }\n ? Root\n : never;\n\ntype DefinedLayoutFromModule<Module> = UnwrapDefinedLayout<\n Module[keyof Module]\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 LazyHandle &\n Pick<\n DefinedLayoutFromModule<Module>,\n Exclude<keyof DefinedLayoutFromModule<Module>, LazyUnsupportedStatic>\n >;\n\n/** Lazy resource options, sharing import and fallback semantics with lazy states. */\nexport type LazyResourceLayoutOptions<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Module extends Record<string, unknown>,\n> = LazyOptions<Module> & {\n resource: ResourcePath<Resources>;\n states?: LazyResourceStates<ResourcePath<Resources>>;\n};\n\nfunction findDefinedLayoutComponent(\n module: Record<string, unknown>,\n resource: string,\n) {\n const components = Object.values(module)\n .map((value) =>\n typeof value === 'object' && value !== null && 'Root' in value\n ? value.Root\n : value,\n )\n .filter(\n (value): value is DefinedLayoutComponent =>\n typeof value === 'function' &&\n definedResourceLayoutComponentSymbol in value,\n );\n if (components.length !== 1)\n throw new LazyResourceModuleShapeError(resource, components.length);\n return components[0];\n}\n\n/** Cached resource component and its compound states, backed by the shared loader. */\nexport function createLazyResourceLayout<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Module extends Record<string, unknown>,\n>(\n options: LazyResourceLayoutOptions<Resources, Module>,\n defaults: LazyResourceStates<any> | (() => LazyResourceStates<any>),\n hooks: LazyResourceLoadHooks = {},\n): LazyResourceLayoutComponent<Module> {\n const runtime = options as unknown as LazyOptions<Module> & {\n resource: string;\n states?: LazyResourceStates;\n };\n const resource = runtime.resource;\n const loader = createLazyLoader({\n load: runtime.load,\n select: (module) => findDefinedLayoutComponent(module, resource),\n label: resource,\n hooks,\n });\n const members = new Map<string, ComponentType<any>>();\n function createMember(member?: string) {\n function LazyMember(props: Record<string, unknown>) {\n const states = { ...(typeof defaults === 'function' ? defaults() : defaults), ...runtime.states } as LazyResourceStates;\n const Loading = states.Loading;\n return (\n <LazyBoundary\n loader={loader}\n member={member}\n resource={resource}\n componentProps={props}\n ErrorComponent={states.Error}\n onMount={hooks.onMount}\n fallback={\n runtime.fallback !== undefined ? (\n runtime.fallback\n ) : Loading ? (\n <Loading resource={resource} />\n ) : null\n }\n />\n );\n }\n LazyMember.displayName = `LazyResource(${resource})${member ? `.${member}` : ''}`;\n Object.defineProperties(LazyMember, {\n preload: { value: loader.preload },\n status: { get: () => loader.status },\n });\n return LazyMember;\n }\n const Component = createMember();\n const reservedStatics = new Set<PropertyKey>([\n 'makeComposable',\n 'props',\n 'resource',\n componentPropDefinitionsSymbol,\n definedResourceLayoutComponentSymbol,\n 'contextTypes',\n 'childContextTypes',\n 'contextType',\n 'propTypes',\n 'defaultProps',\n 'getDerivedStateFromProps',\n 'getDerivedStateFromError',\n 'getDefaultProps',\n '$$typeof',\n '_payload',\n '_init',\n 'render',\n 'compare',\n 'type',\n 'then',\n 'catch',\n 'finally',\n 'toJSON',\n 'asymmetricMatch',\n '__esModule',\n 'default',\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 if (\n typeof property !== 'string' ||\n reservedStatics.has(property) ||\n !/^[A-Z]/.test(property)\n )\n return undefined;\n let component = members.get(property);\n if (!component) {\n component = createMember(property);\n members.set(property, component);\n }\n return component;\n },\n has: (target, property) => Reflect.has(target, property),\n }) as unknown as LazyResourceLayoutComponent<Module>;\n}\n"],"mappings":";;;;;;;;AAkEA,SAAS,2BACP,QACA,UACA;CACA,MAAM,aAAa,OAAO,OAAO,MAAM,EACpC,KAAK,UACJ,OAAO,UAAU,YAAY,UAAU,QAAQ,UAAU,QACrD,MAAM,OACN,KACN,EACC,QACE,UACC,OAAO,UAAU,cACjB,wCAAwC,KAC5C;CACF,IAAI,WAAW,WAAW,GACxB,MAAM,IAAI,6BAA6B,UAAU,WAAW,MAAM;CACpE,OAAO,WAAW;AACpB;;AAGA,SAAgB,yBAId,SACA,UACA,QAA+B,CAAC,GACK;CACrC,MAAM,UAAU;CAIhB,MAAM,WAAW,QAAQ;CACzB,MAAM,SAAS,iBAAiB;EAC9B,MAAM,QAAQ;EACd,SAAS,WAAW,2BAA2B,QAAQ,QAAQ;EAC/D,OAAO;EACP;CACF,CAAC;CACD,MAAM,0BAAU,IAAI,IAAgC;CACpD,SAAS,aAAa,QAAiB;EACrC,SAAS,WAAW,OAAgC;GAClD,MAAM,SAAS;IAAE,GAAI,OAAO,aAAa,aAAa,SAAS,IAAI;IAAW,GAAG,QAAQ;GAAO;GAChG,MAAM,UAAU,OAAO;GACvB,OACE,oBAAC,cAAD;IACU;IACA;IACE;IACV,gBAAgB;IAChB,gBAAgB,OAAO;IACvB,SAAS,MAAM;IACf,UACE,QAAQ,aAAa,SACnB,QAAQ,WACN,UACF,oBAAC,SAAD,EAAmB,SAAW,KAC5B;GAEP;EAEL;EACA,WAAW,cAAc,gBAAgB,SAAS,GAAG,SAAS,IAAI,WAAW;EAC7E,OAAO,iBAAiB,YAAY;GAClC,SAAS,EAAE,OAAO,OAAO,QAAQ;GACjC,QAAQ,EAAE,WAAW,OAAO,OAAO;EACrC,CAAC;EACD,OAAO;CACT;CACA,MAAM,YAAY,aAAa;CAC/B,MAAM,kBAAkB,IAAI,IAAiB;EAC3C;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CACD,OAAO,IAAI,MAAM,WAAW;EAC1B,IAAI,QAAQ,UAAU,UAAU;GAC9B,IAAI,QAAQ,IAAI,QAAQ,QAAQ,GAC9B,OAAO,QAAQ,IAAI,QAAQ,UAAU,QAAQ;GAC/C,IACE,OAAO,aAAa,YACpB,gBAAgB,IAAI,QAAQ,KAC5B,CAAC,SAAS,KAAK,QAAQ,GAEvB,OAAO;GACT,IAAI,YAAY,QAAQ,IAAI,QAAQ;GACpC,IAAI,CAAC,WAAW;IACd,YAAY,aAAa,QAAQ;IACjC,QAAQ,IAAI,UAAU,SAAS;GACjC;GACA,OAAO;EACT;EACA,MAAM,QAAQ,aAAa,QAAQ,IAAI,QAAQ,QAAQ;CACzD,CAAC;AACH"}
@@ -8,6 +8,7 @@ function createLazyLoader(options) {
8
8
  let promise;
9
9
  let preloadPromise;
10
10
  let status = "unresolved";
11
+ let settled;
11
12
  const components = /* @__PURE__ */ new Map();
12
13
  let generation = 0;
13
14
  function get() {
@@ -21,12 +22,20 @@ function createLazyLoader(options) {
21
22
  throw new require_resource_state_error.ResourceModuleLoadError(options.label, cause);
22
23
  }).then(options.select).then((selected) => {
23
24
  if (attempt === generation) {
25
+ settled = {
26
+ ok: true,
27
+ value: selected
28
+ };
24
29
  status = "resolved";
25
30
  options.hooks?.onLoadSuccess?.();
26
31
  }
27
32
  return selected;
28
33
  }, (error) => {
29
34
  if (attempt === generation) {
35
+ settled = {
36
+ ok: false,
37
+ error
38
+ };
30
39
  status = "error";
31
40
  options.hooks?.onLoadError?.(error);
32
41
  }
@@ -44,6 +53,7 @@ function createLazyLoader(options) {
44
53
  generation++;
45
54
  promise = void 0;
46
55
  preloadPromise = void 0;
56
+ settled = void 0;
47
57
  components.clear();
48
58
  status = "unresolved";
49
59
  },
@@ -51,21 +61,32 @@ function createLazyLoader(options) {
51
61
  const key = map ?? member;
52
62
  let component = components.get(key);
53
63
  if (!component) {
54
- component = (0, react.lazy)(async () => {
55
- const attempt = generation;
56
- const selected = await get();
57
- try {
58
- const candidate = map ? map(selected) : member === void 0 ? selected : selected[member];
64
+ let resolved;
65
+ component = function LazyMember(props) {
66
+ if (!settled) throw get();
67
+ if (!settled.ok) throw settled.error;
68
+ if (!resolved || resolved.generation !== generation) try {
69
+ const candidate = map ? map(settled.value) : member === void 0 ? settled.value : settled.value[member];
59
70
  if (typeof candidate !== "function") throw new require_lazy_resource_error.LazyResourceStateNotFoundError(options.label, String(member));
60
- return { default: candidate };
71
+ resolved = {
72
+ generation,
73
+ ok: true,
74
+ value: candidate
75
+ };
61
76
  } catch (error) {
62
- if (attempt === generation && require_lazy_resource_error.isLazyResourceError(error)) {
77
+ resolved = {
78
+ generation,
79
+ ok: false,
80
+ error
81
+ };
82
+ if (require_lazy_resource_error.isLazyResourceError(error)) {
63
83
  status = "error";
64
84
  options.hooks?.onLoadError?.(error);
65
85
  }
66
- throw error;
67
86
  }
68
- });
87
+ if (!resolved.ok) throw resolved.error;
88
+ return (0, react.createElement)(resolved.value, props);
89
+ };
69
90
  components.set(key, component);
70
91
  }
71
92
  return component;
@@ -1 +1 @@
1
- {"version":3,"file":"create-lazy-loader.cjs","names":["isLazyResourceError","ResourceModuleLoadError","LazyResourceStateNotFoundError"],"sources":["../../src/lazy/create-lazy-loader.ts"],"sourcesContent":["import { lazy, type ComponentType } from 'react';\nimport { ResourceModuleLoadError } from '../errors/resource-state-error';\nimport {\n LazyResourceStateNotFoundError,\n isLazyResourceError,\n type LazyResourceError,\n} from '../errors/lazy-resource-error';\nimport type { LazyHandle, LoadStatus } from './types';\n\nexport type LazyResourceLoadHooks = {\n onLoadStart?: () => void;\n onLoadSuccess?: () => void;\n onLoadError?: (error: LazyResourceError) => void;\n onMount?: () => (() => void) | undefined;\n};\n\nexport type LazyLoader<Selected> = LazyHandle & {\n get(): Promise<Selected>;\n reset(): void;\n component(\n member?: PropertyKey,\n map?: (selected: Selected) => ComponentType<any>,\n ): ComponentType<any>;\n};\n\n/** A single import cache and lifecycle shared by every lazy entry point. */\nexport function createLazyLoader<Module, Selected>(options: {\n load: () => Promise<Module>;\n select: (module: Module) => Selected | Promise<Selected>;\n label: string;\n hooks?: LazyResourceLoadHooks;\n}): LazyLoader<Selected> {\n let promise: Promise<Selected> | undefined;\n let preloadPromise: Promise<void> | undefined;\n let status: LoadStatus = 'unresolved';\n const components = new Map<unknown, ComponentType<any>>();\n let generation = 0;\n\n function get() {\n if (promise) return promise;\n const attempt = generation;\n status = 'loading';\n options.hooks?.onLoadStart?.();\n promise = Promise.resolve()\n .then(options.load)\n .catch((cause: unknown) => {\n if (isLazyResourceError(cause)) throw cause;\n if (process.env.NODE_ENV !== 'production') {\n console.error(\n `[react-layout] lazy \"${options.label}\" failed to load`,\n cause,\n );\n }\n throw new ResourceModuleLoadError(options.label, cause);\n })\n .then(options.select)\n .then(\n (selected) => {\n if (attempt === generation) {\n status = 'resolved';\n options.hooks?.onLoadSuccess?.();\n }\n return selected;\n },\n (error: LazyResourceError) => {\n if (attempt === generation) {\n status = 'error';\n options.hooks?.onLoadError?.(error);\n }\n throw error;\n },\n );\n return promise;\n }\n\n return {\n get,\n get status() {\n return status;\n },\n preload: () => (preloadPromise ??= get().then(() => undefined)),\n reset() {\n generation++;\n promise = undefined;\n preloadPromise = undefined;\n components.clear();\n status = 'unresolved';\n },\n component(member, map) {\n const key = map ?? member;\n let component = components.get(key);\n if (!component) {\n component = lazy(async () => {\n const attempt = generation;\n const selected = await get();\n try {\n const candidate = map\n ? map(selected)\n : member === undefined\n ? selected\n : (selected as Record<PropertyKey, unknown>)[member];\n if (typeof candidate !== 'function') {\n throw new LazyResourceStateNotFoundError(\n options.label,\n String(member),\n );\n }\n return { default: candidate as ComponentType<any> };\n } catch (error) {\n if (attempt === generation && isLazyResourceError(error)) {\n status = 'error';\n options.hooks?.onLoadError?.(error);\n }\n throw error;\n }\n });\n components.set(key, component);\n }\n return component;\n },\n };\n}\n"],"mappings":";;;;;;AA0BA,SAAgB,iBAAmC,SAK1B;CACvB,IAAI;CACJ,IAAI;CACJ,IAAI,SAAqB;CACzB,MAAM,6BAAa,IAAI,IAAiC;CACxD,IAAI,aAAa;CAEjB,SAAS,MAAM;EACb,IAAI,SAAS,OAAO;EACpB,MAAM,UAAU;EAChB,SAAS;EACT,QAAQ,OAAO,cAAc;EAC7B,UAAU,QAAQ,QAAQ,EACvB,KAAK,QAAQ,IAAI,EACjB,OAAO,UAAmB;GACzB,IAAIA,gDAAoB,KAAK,GAAG,MAAM;GACtC,IAAI,QAAQ,IAAI,aAAa,cAC3B,QAAQ,MACN,wBAAwB,QAAQ,MAAM,mBACtC,KACF;GAEF,MAAM,IAAIC,qDAAwB,QAAQ,OAAO,KAAK;EACxD,CAAC,EACA,KAAK,QAAQ,MAAM,EACnB,MACE,aAAa;GACZ,IAAI,YAAY,YAAY;IAC1B,SAAS;IACT,QAAQ,OAAO,gBAAgB;GACjC;GACA,OAAO;EACT,IACC,UAA6B;GAC5B,IAAI,YAAY,YAAY;IAC1B,SAAS;IACT,QAAQ,OAAO,cAAc,KAAK;GACpC;GACA,MAAM;EACR,CACF;EACF,OAAO;CACT;CAEA,OAAO;EACL;EACA,IAAI,SAAS;GACX,OAAO;EACT;EACA,eAAgB,mBAAmB,IAAI,EAAE,WAAW,MAAS;EAC7D,QAAQ;GACN;GACA,UAAU;GACV,iBAAiB;GACjB,WAAW,MAAM;GACjB,SAAS;EACX;EACA,UAAU,QAAQ,KAAK;GACrB,MAAM,MAAM,OAAO;GACnB,IAAI,YAAY,WAAW,IAAI,GAAG;GAClC,IAAI,CAAC,WAAW;IACd,4BAAiB,YAAY;KAC3B,MAAM,UAAU;KAChB,MAAM,WAAW,MAAM,IAAI;KAC3B,IAAI;MACF,MAAM,YAAY,MACd,IAAI,QAAQ,IACZ,WAAW,SACT,WACC,SAA0C;MACjD,IAAI,OAAO,cAAc,YACvB,MAAM,IAAIC,2DACR,QAAQ,OACR,OAAO,MAAM,CACf;MAEF,OAAO,EAAE,SAAS,UAAgC;KACpD,SAAS,OAAO;MACd,IAAI,YAAY,cAAcF,gDAAoB,KAAK,GAAG;OACxD,SAAS;OACT,QAAQ,OAAO,cAAc,KAAK;MACpC;MACA,MAAM;KACR;IACF,CAAC;IACD,WAAW,IAAI,KAAK,SAAS;GAC/B;GACA,OAAO;EACT;CACF;AACF"}
1
+ {"version":3,"file":"create-lazy-loader.cjs","names":["isLazyResourceError","ResourceModuleLoadError","LazyResourceStateNotFoundError"],"sources":["../../src/lazy/create-lazy-loader.ts"],"sourcesContent":["import { createElement, type ComponentType } from 'react';\nimport { ResourceModuleLoadError } from '../errors/resource-state-error';\nimport {\n LazyResourceStateNotFoundError,\n isLazyResourceError,\n type LazyResourceError,\n} from '../errors/lazy-resource-error';\nimport type { LazyHandle, LoadStatus } from './types';\n\nexport type LazyResourceLoadHooks = {\n onLoadStart?: () => void;\n onLoadSuccess?: () => void;\n onLoadError?: (error: LazyResourceError) => void;\n onMount?: () => (() => void) | undefined;\n};\n\nexport type LazyLoader<Selected> = LazyHandle & {\n get(): Promise<Selected>;\n reset(): void;\n component(\n member?: PropertyKey,\n map?: (selected: Selected) => ComponentType<any>\n ): ComponentType<any>;\n};\n\n/** A single import cache and lifecycle shared by every lazy entry point. */\nexport function createLazyLoader<Module, Selected>(options: {\n load: () => Promise<Module>;\n select: (module: Module) => Selected | Promise<Selected>;\n label: string;\n hooks?: LazyResourceLoadHooks;\n}): LazyLoader<Selected> {\n let promise: Promise<Selected> | undefined;\n let preloadPromise: Promise<void> | undefined;\n let status: LoadStatus = 'unresolved';\n let settled:\n { ok: true; value: Selected } | { ok: false; error: unknown } | undefined;\n const components = new Map<unknown, ComponentType<any>>();\n let generation = 0;\n\n function get() {\n if (promise) return promise;\n const attempt = generation;\n status = 'loading';\n options.hooks?.onLoadStart?.();\n promise = Promise.resolve()\n .then(options.load)\n .catch((cause: unknown) => {\n if (isLazyResourceError(cause)) throw cause;\n if (process.env.NODE_ENV !== 'production') {\n console.error(\n `[react-layout] lazy \"${options.label}\" failed to load`,\n cause\n );\n }\n throw new ResourceModuleLoadError(options.label, cause);\n })\n .then(options.select)\n .then(\n (selected) => {\n if (attempt === generation) {\n settled = { ok: true, value: selected };\n status = 'resolved';\n options.hooks?.onLoadSuccess?.();\n }\n return selected;\n },\n (error: LazyResourceError) => {\n if (attempt === generation) {\n settled = { ok: false, error };\n status = 'error';\n options.hooks?.onLoadError?.(error);\n }\n throw error;\n }\n );\n return promise;\n }\n\n return {\n get,\n get status() {\n return status;\n },\n preload: () => (preloadPromise ??= get().then(() => undefined)),\n reset() {\n generation++;\n promise = undefined;\n preloadPromise = undefined;\n settled = undefined;\n components.clear();\n status = 'unresolved';\n },\n component(member, map) {\n const key = map ?? member;\n let component = components.get(key);\n if (!component) {\n let resolved:\n | { generation: number; ok: true; value: ComponentType<any> }\n | { generation: number; ok: false; error: unknown }\n | undefined;\n // Every member reads the same module result. Throw only while that\n // shared import is pending, rather than starting a promise per member.\n // Keep this component stable so later renders preserve child state.\n component = function LazyMember(props: Record<string, unknown>) {\n if (!settled) throw get();\n if (!settled.ok) throw settled.error;\n if (!resolved || resolved.generation !== generation) {\n try {\n const candidate = map\n ? map(settled.value)\n : member === undefined\n ? settled.value\n : (settled.value as Record<PropertyKey, unknown>)[member];\n if (typeof candidate !== 'function') {\n throw new LazyResourceStateNotFoundError(\n options.label,\n String(member)\n );\n }\n resolved = {\n generation,\n ok: true,\n value: candidate as ComponentType<any>,\n };\n } catch (error) {\n resolved = { generation, ok: false, error };\n if (isLazyResourceError(error)) {\n status = 'error';\n options.hooks?.onLoadError?.(error);\n }\n }\n }\n if (!resolved.ok) throw resolved.error;\n return createElement(resolved.value, props);\n };\n components.set(key, component);\n }\n return component;\n },\n };\n}\n"],"mappings":";;;;;;AA0BA,SAAgB,iBAAmC,SAK1B;CACvB,IAAI;CACJ,IAAI;CACJ,IAAI,SAAqB;CACzB,IAAI;CAEJ,MAAM,6BAAa,IAAI,IAAiC;CACxD,IAAI,aAAa;CAEjB,SAAS,MAAM;EACb,IAAI,SAAS,OAAO;EACpB,MAAM,UAAU;EAChB,SAAS;EACT,QAAQ,OAAO,cAAc;EAC7B,UAAU,QAAQ,QAAQ,EACvB,KAAK,QAAQ,IAAI,EACjB,OAAO,UAAmB;GACzB,IAAIA,gDAAoB,KAAK,GAAG,MAAM;GACtC,IAAI,QAAQ,IAAI,aAAa,cAC3B,QAAQ,MACN,wBAAwB,QAAQ,MAAM,mBACtC,KACF;GAEF,MAAM,IAAIC,qDAAwB,QAAQ,OAAO,KAAK;EACxD,CAAC,EACA,KAAK,QAAQ,MAAM,EACnB,MACE,aAAa;GACZ,IAAI,YAAY,YAAY;IAC1B,UAAU;KAAE,IAAI;KAAM,OAAO;IAAS;IACtC,SAAS;IACT,QAAQ,OAAO,gBAAgB;GACjC;GACA,OAAO;EACT,IACC,UAA6B;GAC5B,IAAI,YAAY,YAAY;IAC1B,UAAU;KAAE,IAAI;KAAO;IAAM;IAC7B,SAAS;IACT,QAAQ,OAAO,cAAc,KAAK;GACpC;GACA,MAAM;EACR,CACF;EACF,OAAO;CACT;CAEA,OAAO;EACL;EACA,IAAI,SAAS;GACX,OAAO;EACT;EACA,eAAgB,mBAAmB,IAAI,EAAE,WAAW,MAAS;EAC7D,QAAQ;GACN;GACA,UAAU;GACV,iBAAiB;GACjB,UAAU;GACV,WAAW,MAAM;GACjB,SAAS;EACX;EACA,UAAU,QAAQ,KAAK;GACrB,MAAM,MAAM,OAAO;GACnB,IAAI,YAAY,WAAW,IAAI,GAAG;GAClC,IAAI,CAAC,WAAW;IACd,IAAI;IAOJ,YAAY,SAAS,WAAW,OAAgC;KAC9D,IAAI,CAAC,SAAS,MAAM,IAAI;KACxB,IAAI,CAAC,QAAQ,IAAI,MAAM,QAAQ;KAC/B,IAAI,CAAC,YAAY,SAAS,eAAe,YACvC,IAAI;MACF,MAAM,YAAY,MACd,IAAI,QAAQ,KAAK,IACjB,WAAW,SACT,QAAQ,QACP,QAAQ,MAAuC;MACtD,IAAI,OAAO,cAAc,YACvB,MAAM,IAAIC,2DACR,QAAQ,OACR,OAAO,MAAM,CACf;MAEF,WAAW;OACT;OACA,IAAI;OACJ,OAAO;MACT;KACF,SAAS,OAAO;MACd,WAAW;OAAE;OAAY,IAAI;OAAO;MAAM;MAC1C,IAAIF,gDAAoB,KAAK,GAAG;OAC9B,SAAS;OACT,QAAQ,OAAO,cAAc,KAAK;MACpC;KACF;KAEF,IAAI,CAAC,SAAS,IAAI,MAAM,SAAS;KACjC,gCAAqB,SAAS,OAAO,KAAK;IAC5C;IACA,WAAW,IAAI,KAAK,SAAS;GAC/B;GACA,OAAO;EACT;CACF;AACF"}
@@ -1,6 +1,6 @@
1
1
  import { ResourceModuleLoadError } from "../errors/resource-state-error.mjs";
2
2
  import { LazyResourceStateNotFoundError, isLazyResourceError } from "../errors/lazy-resource-error.mjs";
3
- import { lazy } from "react";
3
+ import { createElement } from "react";
4
4
 
5
5
  //#region src/lazy/create-lazy-loader.ts
6
6
  /** A single import cache and lifecycle shared by every lazy entry point. */
@@ -8,6 +8,7 @@ function createLazyLoader(options) {
8
8
  let promise;
9
9
  let preloadPromise;
10
10
  let status = "unresolved";
11
+ let settled;
11
12
  const components = /* @__PURE__ */ new Map();
12
13
  let generation = 0;
13
14
  function get() {
@@ -21,12 +22,20 @@ function createLazyLoader(options) {
21
22
  throw new ResourceModuleLoadError(options.label, cause);
22
23
  }).then(options.select).then((selected) => {
23
24
  if (attempt === generation) {
25
+ settled = {
26
+ ok: true,
27
+ value: selected
28
+ };
24
29
  status = "resolved";
25
30
  options.hooks?.onLoadSuccess?.();
26
31
  }
27
32
  return selected;
28
33
  }, (error) => {
29
34
  if (attempt === generation) {
35
+ settled = {
36
+ ok: false,
37
+ error
38
+ };
30
39
  status = "error";
31
40
  options.hooks?.onLoadError?.(error);
32
41
  }
@@ -44,6 +53,7 @@ function createLazyLoader(options) {
44
53
  generation++;
45
54
  promise = void 0;
46
55
  preloadPromise = void 0;
56
+ settled = void 0;
47
57
  components.clear();
48
58
  status = "unresolved";
49
59
  },
@@ -51,21 +61,32 @@ function createLazyLoader(options) {
51
61
  const key = map ?? member;
52
62
  let component = components.get(key);
53
63
  if (!component) {
54
- component = lazy(async () => {
55
- const attempt = generation;
56
- const selected = await get();
57
- try {
58
- const candidate = map ? map(selected) : member === void 0 ? selected : selected[member];
64
+ let resolved;
65
+ component = function LazyMember(props) {
66
+ if (!settled) throw get();
67
+ if (!settled.ok) throw settled.error;
68
+ if (!resolved || resolved.generation !== generation) try {
69
+ const candidate = map ? map(settled.value) : member === void 0 ? settled.value : settled.value[member];
59
70
  if (typeof candidate !== "function") throw new LazyResourceStateNotFoundError(options.label, String(member));
60
- return { default: candidate };
71
+ resolved = {
72
+ generation,
73
+ ok: true,
74
+ value: candidate
75
+ };
61
76
  } catch (error) {
62
- if (attempt === generation && isLazyResourceError(error)) {
77
+ resolved = {
78
+ generation,
79
+ ok: false,
80
+ error
81
+ };
82
+ if (isLazyResourceError(error)) {
63
83
  status = "error";
64
84
  options.hooks?.onLoadError?.(error);
65
85
  }
66
- throw error;
67
86
  }
68
- });
87
+ if (!resolved.ok) throw resolved.error;
88
+ return createElement(resolved.value, props);
89
+ };
69
90
  components.set(key, component);
70
91
  }
71
92
  return component;
@@ -1 +1 @@
1
- {"version":3,"file":"create-lazy-loader.mjs","names":[],"sources":["../../src/lazy/create-lazy-loader.ts"],"sourcesContent":["import { lazy, type ComponentType } from 'react';\nimport { ResourceModuleLoadError } from '../errors/resource-state-error';\nimport {\n LazyResourceStateNotFoundError,\n isLazyResourceError,\n type LazyResourceError,\n} from '../errors/lazy-resource-error';\nimport type { LazyHandle, LoadStatus } from './types';\n\nexport type LazyResourceLoadHooks = {\n onLoadStart?: () => void;\n onLoadSuccess?: () => void;\n onLoadError?: (error: LazyResourceError) => void;\n onMount?: () => (() => void) | undefined;\n};\n\nexport type LazyLoader<Selected> = LazyHandle & {\n get(): Promise<Selected>;\n reset(): void;\n component(\n member?: PropertyKey,\n map?: (selected: Selected) => ComponentType<any>,\n ): ComponentType<any>;\n};\n\n/** A single import cache and lifecycle shared by every lazy entry point. */\nexport function createLazyLoader<Module, Selected>(options: {\n load: () => Promise<Module>;\n select: (module: Module) => Selected | Promise<Selected>;\n label: string;\n hooks?: LazyResourceLoadHooks;\n}): LazyLoader<Selected> {\n let promise: Promise<Selected> | undefined;\n let preloadPromise: Promise<void> | undefined;\n let status: LoadStatus = 'unresolved';\n const components = new Map<unknown, ComponentType<any>>();\n let generation = 0;\n\n function get() {\n if (promise) return promise;\n const attempt = generation;\n status = 'loading';\n options.hooks?.onLoadStart?.();\n promise = Promise.resolve()\n .then(options.load)\n .catch((cause: unknown) => {\n if (isLazyResourceError(cause)) throw cause;\n if (process.env.NODE_ENV !== 'production') {\n console.error(\n `[react-layout] lazy \"${options.label}\" failed to load`,\n cause,\n );\n }\n throw new ResourceModuleLoadError(options.label, cause);\n })\n .then(options.select)\n .then(\n (selected) => {\n if (attempt === generation) {\n status = 'resolved';\n options.hooks?.onLoadSuccess?.();\n }\n return selected;\n },\n (error: LazyResourceError) => {\n if (attempt === generation) {\n status = 'error';\n options.hooks?.onLoadError?.(error);\n }\n throw error;\n },\n );\n return promise;\n }\n\n return {\n get,\n get status() {\n return status;\n },\n preload: () => (preloadPromise ??= get().then(() => undefined)),\n reset() {\n generation++;\n promise = undefined;\n preloadPromise = undefined;\n components.clear();\n status = 'unresolved';\n },\n component(member, map) {\n const key = map ?? member;\n let component = components.get(key);\n if (!component) {\n component = lazy(async () => {\n const attempt = generation;\n const selected = await get();\n try {\n const candidate = map\n ? map(selected)\n : member === undefined\n ? selected\n : (selected as Record<PropertyKey, unknown>)[member];\n if (typeof candidate !== 'function') {\n throw new LazyResourceStateNotFoundError(\n options.label,\n String(member),\n );\n }\n return { default: candidate as ComponentType<any> };\n } catch (error) {\n if (attempt === generation && isLazyResourceError(error)) {\n status = 'error';\n options.hooks?.onLoadError?.(error);\n }\n throw error;\n }\n });\n components.set(key, component);\n }\n return component;\n },\n };\n}\n"],"mappings":";;;;;;AA0BA,SAAgB,iBAAmC,SAK1B;CACvB,IAAI;CACJ,IAAI;CACJ,IAAI,SAAqB;CACzB,MAAM,6BAAa,IAAI,IAAiC;CACxD,IAAI,aAAa;CAEjB,SAAS,MAAM;EACb,IAAI,SAAS,OAAO;EACpB,MAAM,UAAU;EAChB,SAAS;EACT,QAAQ,OAAO,cAAc;EAC7B,UAAU,QAAQ,QAAQ,EACvB,KAAK,QAAQ,IAAI,EACjB,OAAO,UAAmB;GACzB,IAAI,oBAAoB,KAAK,GAAG,MAAM;GACtC,IAAI,QAAQ,IAAI,aAAa,cAC3B,QAAQ,MACN,wBAAwB,QAAQ,MAAM,mBACtC,KACF;GAEF,MAAM,IAAI,wBAAwB,QAAQ,OAAO,KAAK;EACxD,CAAC,EACA,KAAK,QAAQ,MAAM,EACnB,MACE,aAAa;GACZ,IAAI,YAAY,YAAY;IAC1B,SAAS;IACT,QAAQ,OAAO,gBAAgB;GACjC;GACA,OAAO;EACT,IACC,UAA6B;GAC5B,IAAI,YAAY,YAAY;IAC1B,SAAS;IACT,QAAQ,OAAO,cAAc,KAAK;GACpC;GACA,MAAM;EACR,CACF;EACF,OAAO;CACT;CAEA,OAAO;EACL;EACA,IAAI,SAAS;GACX,OAAO;EACT;EACA,eAAgB,mBAAmB,IAAI,EAAE,WAAW,MAAS;EAC7D,QAAQ;GACN;GACA,UAAU;GACV,iBAAiB;GACjB,WAAW,MAAM;GACjB,SAAS;EACX;EACA,UAAU,QAAQ,KAAK;GACrB,MAAM,MAAM,OAAO;GACnB,IAAI,YAAY,WAAW,IAAI,GAAG;GAClC,IAAI,CAAC,WAAW;IACd,YAAY,KAAK,YAAY;KAC3B,MAAM,UAAU;KAChB,MAAM,WAAW,MAAM,IAAI;KAC3B,IAAI;MACF,MAAM,YAAY,MACd,IAAI,QAAQ,IACZ,WAAW,SACT,WACC,SAA0C;MACjD,IAAI,OAAO,cAAc,YACvB,MAAM,IAAI,+BACR,QAAQ,OACR,OAAO,MAAM,CACf;MAEF,OAAO,EAAE,SAAS,UAAgC;KACpD,SAAS,OAAO;MACd,IAAI,YAAY,cAAc,oBAAoB,KAAK,GAAG;OACxD,SAAS;OACT,QAAQ,OAAO,cAAc,KAAK;MACpC;MACA,MAAM;KACR;IACF,CAAC;IACD,WAAW,IAAI,KAAK,SAAS;GAC/B;GACA,OAAO;EACT;CACF;AACF"}
1
+ {"version":3,"file":"create-lazy-loader.mjs","names":[],"sources":["../../src/lazy/create-lazy-loader.ts"],"sourcesContent":["import { createElement, type ComponentType } from 'react';\nimport { ResourceModuleLoadError } from '../errors/resource-state-error';\nimport {\n LazyResourceStateNotFoundError,\n isLazyResourceError,\n type LazyResourceError,\n} from '../errors/lazy-resource-error';\nimport type { LazyHandle, LoadStatus } from './types';\n\nexport type LazyResourceLoadHooks = {\n onLoadStart?: () => void;\n onLoadSuccess?: () => void;\n onLoadError?: (error: LazyResourceError) => void;\n onMount?: () => (() => void) | undefined;\n};\n\nexport type LazyLoader<Selected> = LazyHandle & {\n get(): Promise<Selected>;\n reset(): void;\n component(\n member?: PropertyKey,\n map?: (selected: Selected) => ComponentType<any>\n ): ComponentType<any>;\n};\n\n/** A single import cache and lifecycle shared by every lazy entry point. */\nexport function createLazyLoader<Module, Selected>(options: {\n load: () => Promise<Module>;\n select: (module: Module) => Selected | Promise<Selected>;\n label: string;\n hooks?: LazyResourceLoadHooks;\n}): LazyLoader<Selected> {\n let promise: Promise<Selected> | undefined;\n let preloadPromise: Promise<void> | undefined;\n let status: LoadStatus = 'unresolved';\n let settled:\n { ok: true; value: Selected } | { ok: false; error: unknown } | undefined;\n const components = new Map<unknown, ComponentType<any>>();\n let generation = 0;\n\n function get() {\n if (promise) return promise;\n const attempt = generation;\n status = 'loading';\n options.hooks?.onLoadStart?.();\n promise = Promise.resolve()\n .then(options.load)\n .catch((cause: unknown) => {\n if (isLazyResourceError(cause)) throw cause;\n if (process.env.NODE_ENV !== 'production') {\n console.error(\n `[react-layout] lazy \"${options.label}\" failed to load`,\n cause\n );\n }\n throw new ResourceModuleLoadError(options.label, cause);\n })\n .then(options.select)\n .then(\n (selected) => {\n if (attempt === generation) {\n settled = { ok: true, value: selected };\n status = 'resolved';\n options.hooks?.onLoadSuccess?.();\n }\n return selected;\n },\n (error: LazyResourceError) => {\n if (attempt === generation) {\n settled = { ok: false, error };\n status = 'error';\n options.hooks?.onLoadError?.(error);\n }\n throw error;\n }\n );\n return promise;\n }\n\n return {\n get,\n get status() {\n return status;\n },\n preload: () => (preloadPromise ??= get().then(() => undefined)),\n reset() {\n generation++;\n promise = undefined;\n preloadPromise = undefined;\n settled = undefined;\n components.clear();\n status = 'unresolved';\n },\n component(member, map) {\n const key = map ?? member;\n let component = components.get(key);\n if (!component) {\n let resolved:\n | { generation: number; ok: true; value: ComponentType<any> }\n | { generation: number; ok: false; error: unknown }\n | undefined;\n // Every member reads the same module result. Throw only while that\n // shared import is pending, rather than starting a promise per member.\n // Keep this component stable so later renders preserve child state.\n component = function LazyMember(props: Record<string, unknown>) {\n if (!settled) throw get();\n if (!settled.ok) throw settled.error;\n if (!resolved || resolved.generation !== generation) {\n try {\n const candidate = map\n ? map(settled.value)\n : member === undefined\n ? settled.value\n : (settled.value as Record<PropertyKey, unknown>)[member];\n if (typeof candidate !== 'function') {\n throw new LazyResourceStateNotFoundError(\n options.label,\n String(member)\n );\n }\n resolved = {\n generation,\n ok: true,\n value: candidate as ComponentType<any>,\n };\n } catch (error) {\n resolved = { generation, ok: false, error };\n if (isLazyResourceError(error)) {\n status = 'error';\n options.hooks?.onLoadError?.(error);\n }\n }\n }\n if (!resolved.ok) throw resolved.error;\n return createElement(resolved.value, props);\n };\n components.set(key, component);\n }\n return component;\n },\n };\n}\n"],"mappings":";;;;;;AA0BA,SAAgB,iBAAmC,SAK1B;CACvB,IAAI;CACJ,IAAI;CACJ,IAAI,SAAqB;CACzB,IAAI;CAEJ,MAAM,6BAAa,IAAI,IAAiC;CACxD,IAAI,aAAa;CAEjB,SAAS,MAAM;EACb,IAAI,SAAS,OAAO;EACpB,MAAM,UAAU;EAChB,SAAS;EACT,QAAQ,OAAO,cAAc;EAC7B,UAAU,QAAQ,QAAQ,EACvB,KAAK,QAAQ,IAAI,EACjB,OAAO,UAAmB;GACzB,IAAI,oBAAoB,KAAK,GAAG,MAAM;GACtC,IAAI,QAAQ,IAAI,aAAa,cAC3B,QAAQ,MACN,wBAAwB,QAAQ,MAAM,mBACtC,KACF;GAEF,MAAM,IAAI,wBAAwB,QAAQ,OAAO,KAAK;EACxD,CAAC,EACA,KAAK,QAAQ,MAAM,EACnB,MACE,aAAa;GACZ,IAAI,YAAY,YAAY;IAC1B,UAAU;KAAE,IAAI;KAAM,OAAO;IAAS;IACtC,SAAS;IACT,QAAQ,OAAO,gBAAgB;GACjC;GACA,OAAO;EACT,IACC,UAA6B;GAC5B,IAAI,YAAY,YAAY;IAC1B,UAAU;KAAE,IAAI;KAAO;IAAM;IAC7B,SAAS;IACT,QAAQ,OAAO,cAAc,KAAK;GACpC;GACA,MAAM;EACR,CACF;EACF,OAAO;CACT;CAEA,OAAO;EACL;EACA,IAAI,SAAS;GACX,OAAO;EACT;EACA,eAAgB,mBAAmB,IAAI,EAAE,WAAW,MAAS;EAC7D,QAAQ;GACN;GACA,UAAU;GACV,iBAAiB;GACjB,UAAU;GACV,WAAW,MAAM;GACjB,SAAS;EACX;EACA,UAAU,QAAQ,KAAK;GACrB,MAAM,MAAM,OAAO;GACnB,IAAI,YAAY,WAAW,IAAI,GAAG;GAClC,IAAI,CAAC,WAAW;IACd,IAAI;IAOJ,YAAY,SAAS,WAAW,OAAgC;KAC9D,IAAI,CAAC,SAAS,MAAM,IAAI;KACxB,IAAI,CAAC,QAAQ,IAAI,MAAM,QAAQ;KAC/B,IAAI,CAAC,YAAY,SAAS,eAAe,YACvC,IAAI;MACF,MAAM,YAAY,MACd,IAAI,QAAQ,KAAK,IACjB,WAAW,SACT,QAAQ,QACP,QAAQ,MAAuC;MACtD,IAAI,OAAO,cAAc,YACvB,MAAM,IAAI,+BACR,QAAQ,OACR,OAAO,MAAM,CACf;MAEF,WAAW;OACT;OACA,IAAI;OACJ,OAAO;MACT;KACF,SAAS,OAAO;MACd,WAAW;OAAE;OAAY,IAAI;OAAO;MAAM;MAC1C,IAAI,oBAAoB,KAAK,GAAG;OAC9B,SAAS;OACT,QAAQ,OAAO,cAAc,KAAK;MACpC;KACF;KAEF,IAAI,CAAC,SAAS,IAAI,MAAM,SAAS;KACjC,OAAO,cAAc,SAAS,OAAO,KAAK;IAC5C;IACA,WAAW,IAAI,KAAK,SAAS;GAC/B;GACA,OAAO;EACT;CACF;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jfdevelops/react-layout",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "A React library for creating layout components.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -29,9 +29,9 @@
29
29
  "dependencies": {
30
30
  "@jfdevelops/create-error": "0.2.0",
31
31
  "arktype": "2.2.8",
32
- "@jfdevelops/react-layout-composables": "0.3.1",
33
- "@jfdevelops/react-layout-devtools-core": "0.3.0",
34
- "@jfdevelops/react-layout-validator": "0.3.1"
32
+ "@jfdevelops/react-layout-composables": "0.4.0",
33
+ "@jfdevelops/react-layout-validator": "0.3.1",
34
+ "@jfdevelops/react-layout-devtools-core": "0.4.0"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "react": ">=18",
@@ -59,7 +59,7 @@
59
59
  "unrun": "0.3.0",
60
60
  "vite": "8.0.10",
61
61
  "vitest": "4.1.5",
62
- "@jfdevelops/react-layout-composable-breadcrumb": "0.2.10"
62
+ "@jfdevelops/react-layout-composable-breadcrumb": "0.2.11"
63
63
  },
64
64
  "scripts": {
65
65
  "dev": "portless react-layout vite",