@jfdevelops/react-layout 0.15.1 → 0.17.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 (60) hide show
  1. package/dist/create-config/define-layout.cjs +15 -4
  2. package/dist/create-config/define-layout.cjs.map +1 -1
  3. package/dist/create-config/define-layout.d.cts +31 -5
  4. package/dist/create-config/define-layout.d.cts.map +1 -1
  5. package/dist/create-config/define-layout.d.mts +31 -5
  6. package/dist/create-config/define-layout.d.mts.map +1 -1
  7. package/dist/create-config/define-layout.mjs +14 -3
  8. package/dist/create-config/define-layout.mjs.map +1 -1
  9. package/dist/create-config/for-resources/create-component.d.cts +284 -0
  10. package/dist/create-config/for-resources/create-component.d.cts.map +1 -0
  11. package/dist/create-config/for-resources/create-component.d.mts +284 -0
  12. package/dist/create-config/for-resources/create-component.d.mts.map +1 -0
  13. package/dist/create-config/{for-resources.cjs → for-resources/create-for-resources.cjs} +78 -39
  14. package/dist/create-config/for-resources/create-for-resources.cjs.map +1 -0
  15. package/dist/create-config/for-resources/create-for-resources.d.cts +1 -0
  16. package/dist/create-config/for-resources/create-for-resources.d.mts +1 -0
  17. package/dist/create-config/{for-resources.mjs → for-resources/create-for-resources.mjs} +77 -38
  18. package/dist/create-config/for-resources/create-for-resources.mjs.map +1 -0
  19. package/dist/create-config/for-resources/index.d.cts +1 -0
  20. package/dist/create-config/for-resources/index.d.mts +1 -0
  21. package/dist/create-config/for-resources/resource-selection.d.cts +47 -0
  22. package/dist/create-config/for-resources/resource-selection.d.cts.map +1 -0
  23. package/dist/create-config/for-resources/resource-selection.d.mts +47 -0
  24. package/dist/create-config/for-resources/resource-selection.d.mts.map +1 -0
  25. package/dist/create-config/for-resources/scoped-layout.d.cts +185 -0
  26. package/dist/create-config/for-resources/scoped-layout.d.cts.map +1 -0
  27. package/dist/create-config/for-resources/scoped-layout.d.mts +185 -0
  28. package/dist/create-config/for-resources/scoped-layout.d.mts.map +1 -0
  29. package/dist/create-config/for-resources/scoped-render.cjs +103 -0
  30. package/dist/create-config/for-resources/scoped-render.cjs.map +1 -0
  31. package/dist/create-config/for-resources/scoped-render.d.cts +18 -0
  32. package/dist/create-config/for-resources/scoped-render.d.cts.map +1 -0
  33. package/dist/create-config/for-resources/scoped-render.d.mts +18 -0
  34. package/dist/create-config/for-resources/scoped-render.d.mts.map +1 -0
  35. package/dist/create-config/for-resources/scoped-render.mjs +100 -0
  36. package/dist/create-config/for-resources/scoped-render.mjs.map +1 -0
  37. package/dist/create-config/index.d.cts +1 -1
  38. package/dist/create-config/index.d.mts +1 -1
  39. package/dist/index.d.cts +2 -2
  40. package/dist/index.d.mts +2 -2
  41. package/dist/props.d.cts +22 -1
  42. package/dist/props.d.cts.map +1 -1
  43. package/dist/props.d.mts +22 -1
  44. package/dist/props.d.mts.map +1 -1
  45. package/dist/utils.cjs.map +1 -1
  46. package/dist/utils.d.cts.map +1 -1
  47. package/dist/utils.d.mts.map +1 -1
  48. package/dist/utils.mjs.map +1 -1
  49. package/package.json +3 -2
  50. package/skills/build-react-layouts/SKILL.md +132 -0
  51. package/skills/build-react-layouts/agents/openai.yaml +4 -0
  52. package/skills/build-react-layouts/references/architecture.md +184 -0
  53. package/skills/build-react-layouts/references/factory-patterns.md +156 -0
  54. package/skills/build-react-layouts/references/routing-and-navigation.md +174 -0
  55. package/dist/create-config/for-resources.cjs.map +0 -1
  56. package/dist/create-config/for-resources.d.cts +0 -358
  57. package/dist/create-config/for-resources.d.cts.map +0 -1
  58. package/dist/create-config/for-resources.d.mts +0 -358
  59. package/dist/create-config/for-resources.d.mts.map +0 -1
  60. package/dist/create-config/for-resources.mjs.map +0 -1
@@ -0,0 +1,100 @@
1
+ import { createElement, isValidElement } from "react";
2
+
3
+ //#region src/create-config/for-resources/scoped-render.ts
4
+ /**
5
+ * Names a scoped component cannot use. Scoped components are attached to
6
+ * function objects, so they collide with the component's own statics and with
7
+ * non-writable `Function.prototype` properties. `__proto__` is reserved so
8
+ * assignment cannot hit the prototype setter on a normal object.
9
+ */
10
+ const reservedScopedComponentNames = new Set([
11
+ "__proto__",
12
+ "apply",
13
+ "arguments",
14
+ "bind",
15
+ "call",
16
+ "caller",
17
+ "displayName",
18
+ "length",
19
+ "name",
20
+ "props",
21
+ "prototype",
22
+ "resource"
23
+ ]);
24
+ /**
25
+ * `$$typeof` tags for object component wrappers that `createElement` accepts
26
+ * as `type` (forwardRef, memo, lazy).
27
+ *
28
+ * Do not treat "any object with `$$typeof`" as a component: portals also have
29
+ * `$$typeof` (`Symbol.for('react.portal')`) and `isValidElement(portal)` is
30
+ * false, so a naive check would mis-classify them.
31
+ */
32
+ const reactForwardRefType = Symbol.for("react.forward_ref");
33
+ const reactMemoType = Symbol.for("react.memo");
34
+ const reactLazyType = Symbol.for("react.lazy");
35
+ /**
36
+ * True when `value` can be passed as the `type` argument to `createElement`.
37
+ *
38
+ * Functions always qualify. Object wrappers qualify only for the forwardRef /
39
+ * memo / lazy tags above — not portals or other React nodes that happen to
40
+ * carry `$$typeof`.
41
+ */
42
+ function isRenderableComponentType(value) {
43
+ if (typeof value === "function") return true;
44
+ if (typeof value !== "object" || value === null || Array.isArray(value) || isValidElement(value) || !("$$typeof" in value)) return false;
45
+ const typeTag = value.$$typeof;
46
+ return typeTag === reactForwardRefType || typeTag === reactMemoType || typeTag === reactLazyType;
47
+ }
48
+ /**
49
+ * If `render` returned a component type, mount it with `props`; otherwise
50
+ * return the node as-is (elements, portals, null, etc.).
51
+ */
52
+ function resolveScopedRenderResult(result, props = {}) {
53
+ if (isRenderableComponentType(result)) return createElement(result, props);
54
+ return result;
55
+ }
56
+ /**
57
+ * Runtime counterpart of `ScopedComponentCompoundStaticKey` — keys that must
58
+ * not be treated as compound component statics on a scoped wrapper.
59
+ */
60
+ const reservedScopedCompoundStaticKeys = new Set([
61
+ "apply",
62
+ "arguments",
63
+ "bind",
64
+ "call",
65
+ "caller",
66
+ "childContextTypes",
67
+ "contextTypes",
68
+ "defaultProps",
69
+ "displayName",
70
+ "length",
71
+ "name",
72
+ "propTypes",
73
+ "prototype",
74
+ "toLocaleString",
75
+ "toString",
76
+ "valueOf",
77
+ "$$typeof"
78
+ ]);
79
+ /**
80
+ * Exposes compound statics (e.g. `DataTable.Loading`) on a scoped wrapper so
81
+ * runtime matches `ScopedComponentCompoundStatics`.
82
+ *
83
+ * Why a Proxy: JSX reads `components.DataTable.Loading` while building the
84
+ * element tree — before `DataTable` itself renders — so statics cannot be
85
+ * copied only after the first `render` call. Property access lazily creates a
86
+ * stable wrapper component that re-runs the scoped `render` under context and
87
+ * mounts the matching static from the returned component type.
88
+ */
89
+ function withScopedCompoundStatics(wrapper, createCompoundStatic) {
90
+ return new Proxy(wrapper, { get(target, property, receiver) {
91
+ if (typeof property === "symbol" || reservedScopedCompoundStaticKeys.has(property) || property in target) return Reflect.get(target, property, receiver);
92
+ const CompoundStatic = createCompoundStatic(property);
93
+ target[property] = CompoundStatic;
94
+ return CompoundStatic;
95
+ } });
96
+ }
97
+
98
+ //#endregion
99
+ export { isRenderableComponentType, reservedScopedComponentNames, resolveScopedRenderResult, withScopedCompoundStatics };
100
+ //# sourceMappingURL=scoped-render.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scoped-render.mjs","names":[],"sources":["../../../src/create-config/for-resources/scoped-render.ts"],"sourcesContent":["import {\n createElement,\n isValidElement,\n type ComponentType,\n type JSX,\n type ReactNode,\n} from 'react';\n\n/**\n * Names a scoped component cannot use. Scoped components are attached to\n * function objects, so they collide with the component's own statics and with\n * non-writable `Function.prototype` properties. `__proto__` is reserved so\n * assignment cannot hit the prototype setter on a normal object.\n */\nexport const reservedScopedComponentNames = new Set([\n '__proto__',\n 'apply',\n 'arguments',\n 'bind',\n 'call',\n 'caller',\n 'displayName',\n 'length',\n 'name',\n 'props',\n 'prototype',\n 'resource',\n]);\n\n/**\n * Values a createComponent / scoped-component `render` may return.\n *\n * Alongside rendered nodes, a component type is allowed — the type constituent\n * of a React element — so factories like `createDataTable(columns)` can be\n * returned directly and mounted with the call-site props.\n *\n * At runtime, `resolveScopedRenderResult` distinguishes component types from\n * nodes (including portals). Getting that wrong mounts a portal via\n * `createElement` and blows up with an invalid-element-type error.\n */\n// Returned components declare their own props; a concrete props parameter would\n// be contravariant and reject the factories callers actually return.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- see above\nexport type ScopedRenderResult = ReactNode | ComponentType<any>;\n\n/**\n * `$$typeof` tags for object component wrappers that `createElement` accepts\n * as `type` (forwardRef, memo, lazy).\n *\n * Do not treat \"any object with `$$typeof`\" as a component: portals also have\n * `$$typeof` (`Symbol.for('react.portal')`) and `isValidElement(portal)` is\n * false, so a naive check would mis-classify them.\n */\nconst reactForwardRefType = Symbol.for('react.forward_ref');\nconst reactMemoType = Symbol.for('react.memo');\nconst reactLazyType = Symbol.for('react.lazy');\n\n/**\n * True when `value` can be passed as the `type` argument to `createElement`.\n *\n * Functions always qualify. Object wrappers qualify only for the forwardRef /\n * memo / lazy tags above — not portals or other React nodes that happen to\n * carry `$$typeof`.\n */\nexport function isRenderableComponentType(\n value: unknown,\n): value is ComponentType<Record<string, unknown>> {\n if (typeof value === 'function') {\n return true;\n }\n\n if (\n typeof value !== 'object' ||\n value === null ||\n Array.isArray(value) ||\n isValidElement(value) ||\n !('$$typeof' in value)\n ) {\n return false;\n }\n\n const typeTag = (value as { $$typeof: unknown }).$$typeof;\n\n return (\n typeTag === reactForwardRefType ||\n typeTag === reactMemoType ||\n typeTag === reactLazyType\n );\n}\n\n/**\n * If `render` returned a component type, mount it with `props`; otherwise\n * return the node as-is (elements, portals, null, etc.).\n */\nexport function resolveScopedRenderResult(\n result: ScopedRenderResult,\n props: Record<string, unknown> = {},\n): JSX.Element {\n if (isRenderableComponentType(result)) {\n return createElement(result, props);\n }\n\n return result as JSX.Element;\n}\n\n/**\n * Runtime counterpart of `ScopedComponentCompoundStaticKey` — keys that must\n * not be treated as compound component statics on a scoped wrapper.\n */\nconst reservedScopedCompoundStaticKeys = new Set<PropertyKey>([\n 'apply',\n 'arguments',\n 'bind',\n 'call',\n 'caller',\n 'childContextTypes',\n 'contextTypes',\n 'defaultProps',\n 'displayName',\n 'length',\n 'name',\n 'propTypes',\n 'prototype',\n 'toLocaleString',\n 'toString',\n 'valueOf',\n '$$typeof',\n]);\n\ntype ScopedComponentWrapper = ((\n props?: Record<string, unknown>,\n) => JSX.Element) &\n Record<string, unknown>;\n\n/**\n * Exposes compound statics (e.g. `DataTable.Loading`) on a scoped wrapper so\n * runtime matches `ScopedComponentCompoundStatics`.\n *\n * Why a Proxy: JSX reads `components.DataTable.Loading` while building the\n * element tree — before `DataTable` itself renders — so statics cannot be\n * copied only after the first `render` call. Property access lazily creates a\n * stable wrapper component that re-runs the scoped `render` under context and\n * mounts the matching static from the returned component type.\n */\nexport function withScopedCompoundStatics(\n wrapper: (props?: Record<string, unknown>) => JSX.Element,\n createCompoundStatic: (\n staticName: string,\n ) => (ownProps?: Record<string, unknown>) => JSX.Element,\n): ScopedComponentWrapper {\n return new Proxy(wrapper as ScopedComponentWrapper, {\n get(target, property, receiver) {\n if (\n typeof property === 'symbol' ||\n reservedScopedCompoundStaticKeys.has(property) ||\n property in target\n ) {\n return Reflect.get(target, property, receiver);\n }\n\n // Cache on the target so repeated `.Loading` access keeps one identity.\n const CompoundStatic = createCompoundStatic(property);\n target[property] = CompoundStatic;\n return CompoundStatic;\n },\n });\n}\n"],"mappings":";;;;;;;;;AAcA,MAAa,+BAA+B,IAAI,IAAI;CAClD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;;;;;;;;AA0BD,MAAM,sBAAsB,OAAO,IAAI,mBAAmB;AAC1D,MAAM,gBAAgB,OAAO,IAAI,YAAY;AAC7C,MAAM,gBAAgB,OAAO,IAAI,YAAY;;;;;;;;AAS7C,SAAgB,0BACd,OACiD;CACjD,IAAI,OAAO,UAAU,YACnB,OAAO;CAGT,IACE,OAAO,UAAU,YACjB,UAAU,QACV,MAAM,QAAQ,KAAK,KACnB,eAAe,KAAK,KACpB,EAAE,cAAc,QAEhB,OAAO;CAGT,MAAM,UAAW,MAAgC;CAEjD,OACE,YAAY,uBACZ,YAAY,iBACZ,YAAY;AAEhB;;;;;AAMA,SAAgB,0BACd,QACA,QAAiC,CAAC,GACrB;CACb,IAAI,0BAA0B,MAAM,GAClC,OAAO,cAAc,QAAQ,KAAK;CAGpC,OAAO;AACT;;;;;AAMA,MAAM,mCAAmC,IAAI,IAAiB;CAC5D;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;;;;;;;;;;AAiBD,SAAgB,0BACd,SACA,sBAGwB;CACxB,OAAO,IAAI,MAAM,SAAmC,EAClD,IAAI,QAAQ,UAAU,UAAU;EAC9B,IACE,OAAO,aAAa,YACpB,iCAAiC,IAAI,QAAQ,KAC7C,YAAY,QAEZ,OAAO,QAAQ,IAAI,QAAQ,UAAU,QAAQ;EAI/C,MAAM,iBAAiB,qBAAqB,QAAQ;EACpD,OAAO,YAAY;EACnB,OAAO;CACT,EACF,CAAC;AACH"}
@@ -1,4 +1,4 @@
1
1
  import { BaseResourceConfigComponents, ResourceConfig, ResourceConfigComponentKey, ResourceConfigComponents, ResourceConfigInput, ResourceConfigMap, SharedResourceConfigOptions, SubResourceConfig, SubResourceConfigComponentsFor } from "./types.cjs";
2
2
  import { CreateResourceConfigFn, CreatedResourceConfig, GetComponent, GetComponentAtBound, GetComponentForResource, GetComponentForResourceOptions, GetComponentOptions, GetComponentOptionsForResource, ResourceFromGetComponentBound, SubResourceFromGetComponentBound, ValidateForResourceBound } from "./get-component.cjs";
3
3
  import { CreateResourceLinkConfig, CreateResourceLinkGroupInput, CreateResourceLinkGroupOptions, CreateResourceLinkOptions, CreateResourceLinksFn, CreateResourceLinksWithGroups, CreateResourceLinksWithGroupsFn, CreatedResourceHref, CreatedResourceLink, CreatedResourceLinkBase, InferHashFromResourceLinkHref, ResourceAnchorLinkFn, ResourceLinkHref } from "./create-resource-links.cjs";
4
- import { CreateResourceLayoutFn, CreateResourceLayoutMakeComposableOptions, defineResourceLayout } from "./define-layout.cjs";
4
+ import { CreateResourceLayoutFn, CreateResourceLayoutMakeComposableOptions, DefineResourceLayout, DefineResourceLayoutFn, DefineResourceLayoutForResources, DefineResourceLayoutForResourcesFactory, defineResourceLayout } from "./define-layout.cjs";
@@ -1,4 +1,4 @@
1
1
  import { BaseResourceConfigComponents, ResourceConfig, ResourceConfigComponentKey, ResourceConfigComponents, ResourceConfigInput, ResourceConfigMap, SharedResourceConfigOptions, SubResourceConfig, SubResourceConfigComponentsFor } from "./types.mjs";
2
2
  import { CreateResourceConfigFn, CreatedResourceConfig, GetComponent, GetComponentAtBound, GetComponentForResource, GetComponentForResourceOptions, GetComponentOptions, GetComponentOptionsForResource, ResourceFromGetComponentBound, SubResourceFromGetComponentBound, ValidateForResourceBound } from "./get-component.mjs";
3
3
  import { CreateResourceLinkConfig, CreateResourceLinkGroupInput, CreateResourceLinkGroupOptions, CreateResourceLinkOptions, CreateResourceLinksFn, CreateResourceLinksWithGroups, CreateResourceLinksWithGroupsFn, CreatedResourceHref, CreatedResourceLink, CreatedResourceLinkBase, InferHashFromResourceLinkHref, ResourceAnchorLinkFn, ResourceLinkHref } from "./create-resource-links.mjs";
4
- import { CreateResourceLayoutFn, CreateResourceLayoutMakeComposableOptions, defineResourceLayout } from "./define-layout.mjs";
4
+ import { CreateResourceLayoutFn, CreateResourceLayoutMakeComposableOptions, DefineResourceLayout, DefineResourceLayoutFn, DefineResourceLayoutForResources, DefineResourceLayoutForResourcesFactory, defineResourceLayout } from "./define-layout.mjs";
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { BaseComponent, MergeIntersection, Show, UnionToIntersection, pick } from "./utils.cjs";
2
2
  import { LayoutResourceKey, NormalizeResource, NormalizeResources, ResourceDefinition, ResourceEnum, ResourceLayoutComponentProps, ResourceTree, normalizeResource, normalizeResources, toResourceEnum } from "./resource.cjs";
3
- import { InPropsDefinition, InPropsFunction, InPropsObject, InPropsOptions, IncludedProps, InferredInProps, LayoutRenderProps, MergedLayoutInProps, ResolvedIncludedProps, ResolvedIncludedPropsAsDefined } from "./props.cjs";
3
+ import { InPropsDefinition, InPropsFunction, InPropsObject, InPropsOptions, IncludedProps, InferredInProps, LayoutRenderProps, MergedLayoutInProps, PropsContextRender, PropsRenderDefinition, ResolvedIncludedProps, ResolvedIncludedPropsAsDefined } from "./props.cjs";
4
4
  import { defineResourceLayout } from "./create-config/define-layout.cjs";
5
5
  import { AnyComposableComponent, ComposableComponent, ComposableComponentCallable, ComposableComponents, ComposableNameContext, ComposablePresetComponent, ComposablePresetComponentCallProps, ComposablePresetMeta, ComposablePresetProps, ComposableResourceLayout, CreateLayoutComposable, DefinedComposableComponentRecord, LayoutComposablePresetProvider, LayoutComposablesFactory, MakeComposable, MakeComposableOptions, MergePresetProps, PresetPropsFromComposable, RequiredPresetLayoutProps, RequiredPresetRenderProps, ResolveLayoutComposables, collectComposablePresetEntries, createComposableComponent, createLayoutComposableFactory, defineComposableComponent, makeComposable, resolveComposablePresetProps, resolveLayoutComposables } from "@jfdevelops/react-layout-composables";
6
6
  import { AnyBuiltPropDefinition, ExtractDefinitionValue, ResolveLayoutProps, ResolveLayoutPropsAsDefined, ResolveProps, ResolvedBuiltPropShape, createPrimitivePropBuilder, createProp, isPropDefinitionShape, resolvePropDefinitionValues, validateProps } from "@jfdevelops/react-layout-validator";
7
- export { type AnyBuiltPropDefinition, type AnyComposableComponent, type BaseComponent, type ComposableComponent, type ComposableComponentCallable, type ComposableComponents, type ComposableNameContext, type ComposablePresetComponent, type ComposablePresetComponentCallProps, type ComposablePresetMeta, type ComposablePresetProps, type ComposableResourceLayout, type CreateLayoutComposable, type DefinedComposableComponentRecord, type ExtractDefinitionValue, type InPropsDefinition, type InPropsFunction, type InPropsObject, type InPropsOptions, type IncludedProps, type InferredInProps, LayoutComposablePresetProvider, type LayoutComposablesFactory, type LayoutRenderProps, type LayoutResourceKey, type MakeComposable, type MakeComposableOptions, type MergeIntersection, type MergePresetProps, type MergedLayoutInProps, type NormalizeResource, type NormalizeResources, type PresetPropsFromComposable, type RequiredPresetLayoutProps, type RequiredPresetRenderProps, type ResolveLayoutComposables, type ResolveLayoutProps, type ResolveLayoutPropsAsDefined, type ResolveProps, type ResolvedBuiltPropShape, type ResolvedIncludedProps, type ResolvedIncludedPropsAsDefined, type ResourceDefinition, type ResourceEnum, type ResourceLayoutComponentProps, type ResourceTree, type Show, type UnionToIntersection, collectComposablePresetEntries, createComposableComponent, createLayoutComposableFactory, createPrimitivePropBuilder, createProp, defineComposableComponent, defineResourceLayout, isPropDefinitionShape, makeComposable, normalizeResource, normalizeResources, pick, resolveComposablePresetProps, resolveLayoutComposables, resolvePropDefinitionValues, toResourceEnum, validateProps };
7
+ export { type AnyBuiltPropDefinition, type AnyComposableComponent, type BaseComponent, type ComposableComponent, type ComposableComponentCallable, type ComposableComponents, type ComposableNameContext, type ComposablePresetComponent, type ComposablePresetComponentCallProps, type ComposablePresetMeta, type ComposablePresetProps, type ComposableResourceLayout, type CreateLayoutComposable, type DefinedComposableComponentRecord, type ExtractDefinitionValue, type InPropsDefinition, type InPropsFunction, type InPropsObject, type InPropsOptions, type IncludedProps, type InferredInProps, LayoutComposablePresetProvider, type LayoutComposablesFactory, type LayoutRenderProps, type LayoutResourceKey, type MakeComposable, type MakeComposableOptions, type MergeIntersection, type MergePresetProps, type MergedLayoutInProps, type NormalizeResource, type NormalizeResources, type PresetPropsFromComposable, type PropsContextRender, type PropsRenderDefinition, type RequiredPresetLayoutProps, type RequiredPresetRenderProps, type ResolveLayoutComposables, type ResolveLayoutProps, type ResolveLayoutPropsAsDefined, type ResolveProps, type ResolvedBuiltPropShape, type ResolvedIncludedProps, type ResolvedIncludedPropsAsDefined, type ResourceDefinition, type ResourceEnum, type ResourceLayoutComponentProps, type ResourceTree, type Show, type UnionToIntersection, collectComposablePresetEntries, createComposableComponent, createLayoutComposableFactory, createPrimitivePropBuilder, createProp, defineComposableComponent, defineResourceLayout, isPropDefinitionShape, makeComposable, normalizeResource, normalizeResources, pick, resolveComposablePresetProps, resolveLayoutComposables, resolvePropDefinitionValues, toResourceEnum, validateProps };
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { BaseComponent, MergeIntersection, Show, UnionToIntersection, pick } from "./utils.mjs";
2
2
  import { LayoutResourceKey, NormalizeResource, NormalizeResources, ResourceDefinition, ResourceEnum, ResourceLayoutComponentProps, ResourceTree, normalizeResource, normalizeResources, toResourceEnum } from "./resource.mjs";
3
- import { InPropsDefinition, InPropsFunction, InPropsObject, InPropsOptions, IncludedProps, InferredInProps, LayoutRenderProps, MergedLayoutInProps, ResolvedIncludedProps, ResolvedIncludedPropsAsDefined } from "./props.mjs";
3
+ import { InPropsDefinition, InPropsFunction, InPropsObject, InPropsOptions, IncludedProps, InferredInProps, LayoutRenderProps, MergedLayoutInProps, PropsContextRender, PropsRenderDefinition, ResolvedIncludedProps, ResolvedIncludedPropsAsDefined } from "./props.mjs";
4
4
  import { defineResourceLayout } from "./create-config/define-layout.mjs";
5
5
  import { AnyComposableComponent, ComposableComponent, ComposableComponentCallable, ComposableComponents, ComposableNameContext, ComposablePresetComponent, ComposablePresetComponentCallProps, ComposablePresetMeta, ComposablePresetProps, ComposableResourceLayout, CreateLayoutComposable, DefinedComposableComponentRecord, LayoutComposablePresetProvider, LayoutComposablesFactory, MakeComposable, MakeComposableOptions, MergePresetProps, PresetPropsFromComposable, RequiredPresetLayoutProps, RequiredPresetRenderProps, ResolveLayoutComposables, collectComposablePresetEntries, createComposableComponent, createLayoutComposableFactory, defineComposableComponent, makeComposable, resolveComposablePresetProps, resolveLayoutComposables } from "@jfdevelops/react-layout-composables";
6
6
  import { AnyBuiltPropDefinition, ExtractDefinitionValue, ResolveLayoutProps, ResolveLayoutPropsAsDefined, ResolveProps, ResolvedBuiltPropShape, createPrimitivePropBuilder, createProp, isPropDefinitionShape, resolvePropDefinitionValues, validateProps } from "@jfdevelops/react-layout-validator";
7
- export { type AnyBuiltPropDefinition, type AnyComposableComponent, type BaseComponent, type ComposableComponent, type ComposableComponentCallable, type ComposableComponents, type ComposableNameContext, type ComposablePresetComponent, type ComposablePresetComponentCallProps, type ComposablePresetMeta, type ComposablePresetProps, type ComposableResourceLayout, type CreateLayoutComposable, type DefinedComposableComponentRecord, type ExtractDefinitionValue, type InPropsDefinition, type InPropsFunction, type InPropsObject, type InPropsOptions, type IncludedProps, type InferredInProps, LayoutComposablePresetProvider, type LayoutComposablesFactory, type LayoutRenderProps, type LayoutResourceKey, type MakeComposable, type MakeComposableOptions, type MergeIntersection, type MergePresetProps, type MergedLayoutInProps, type NormalizeResource, type NormalizeResources, type PresetPropsFromComposable, type RequiredPresetLayoutProps, type RequiredPresetRenderProps, type ResolveLayoutComposables, type ResolveLayoutProps, type ResolveLayoutPropsAsDefined, type ResolveProps, type ResolvedBuiltPropShape, type ResolvedIncludedProps, type ResolvedIncludedPropsAsDefined, type ResourceDefinition, type ResourceEnum, type ResourceLayoutComponentProps, type ResourceTree, type Show, type UnionToIntersection, collectComposablePresetEntries, createComposableComponent, createLayoutComposableFactory, createPrimitivePropBuilder, createProp, defineComposableComponent, defineResourceLayout, isPropDefinitionShape, makeComposable, normalizeResource, normalizeResources, pick, resolveComposablePresetProps, resolveLayoutComposables, resolvePropDefinitionValues, toResourceEnum, validateProps };
7
+ export { type AnyBuiltPropDefinition, type AnyComposableComponent, type BaseComponent, type ComposableComponent, type ComposableComponentCallable, type ComposableComponents, type ComposableNameContext, type ComposablePresetComponent, type ComposablePresetComponentCallProps, type ComposablePresetMeta, type ComposablePresetProps, type ComposableResourceLayout, type CreateLayoutComposable, type DefinedComposableComponentRecord, type ExtractDefinitionValue, type InPropsDefinition, type InPropsFunction, type InPropsObject, type InPropsOptions, type IncludedProps, type InferredInProps, LayoutComposablePresetProvider, type LayoutComposablesFactory, type LayoutRenderProps, type LayoutResourceKey, type MakeComposable, type MakeComposableOptions, type MergeIntersection, type MergePresetProps, type MergedLayoutInProps, type NormalizeResource, type NormalizeResources, type PresetPropsFromComposable, type PropsContextRender, type PropsRenderDefinition, type RequiredPresetLayoutProps, type RequiredPresetRenderProps, type ResolveLayoutComposables, type ResolveLayoutProps, type ResolveLayoutPropsAsDefined, type ResolveProps, type ResolvedBuiltPropShape, type ResolvedIncludedProps, type ResolvedIncludedPropsAsDefined, type ResourceDefinition, type ResourceEnum, type ResourceLayoutComponentProps, type ResourceTree, type Show, type UnionToIntersection, collectComposablePresetEntries, createComposableComponent, createLayoutComposableFactory, createPrimitivePropBuilder, createProp, defineComposableComponent, defineResourceLayout, isPropDefinitionShape, makeComposable, normalizeResource, normalizeResources, pick, resolveComposablePresetProps, resolveLayoutComposables, resolvePropDefinitionValues, toResourceEnum, validateProps };
package/dist/props.d.cts CHANGED
@@ -4,6 +4,27 @@ import { ComposableComponents, InPropsObject, MergePresetProps } from "@jfdevelo
4
4
  import { EnumWrappedProp, LiteralWrappedProp, ResolveLayoutProps, ResolveLayoutPropsAsDefined, ResolveProps } from "@jfdevelops/react-layout-validator";
5
5
 
6
6
  //#region src/props.d.ts
7
+ /**
8
+ * Two-argument `render(props, context)` used by createComponent and scoped
9
+ * resource components. `Context` is sibling components (scoped) or the
10
+ * resource render context (top-level).
11
+ */
12
+ type PropsContextRender<RenderProps, Context, Result = unknown> = (props: RenderProps, context: Context) => Result;
13
+ /**
14
+ * Shared `{ props?, render }` shape used by createComponent, scoped
15
+ * components, and anywhere else a value declares props and a two-arg render.
16
+ *
17
+ * @typeParam Props - Declared on the entry (`props`). Often an
18
+ * {@link InPropsObject}, or a layout include/custom bag.
19
+ * @typeParam RenderProps - First argument to `render` (defaults to
20
+ * {@link ResolveProps}<Props> when Props is an {@link InPropsObject})
21
+ * @typeParam Result - `render` return type
22
+ * @typeParam Context - Second argument to `render`
23
+ */
24
+ interface PropsRenderDefinition<Props = InPropsObject, RenderProps = (Props extends InPropsObject ? ResolveProps<Props> : unknown), Result = unknown, Context = unknown> {
25
+ props?: Props;
26
+ render: PropsContextRender<RenderProps, Context, Result>;
27
+ }
7
28
  type InPropsOptions<Resources extends ReadonlyArray<ResourceDefinition>, Name extends string> = {
8
29
  name: LiteralWrappedProp<Name, 'string', 'required'>;
9
30
  resource: EnumWrappedProp<ResourceEnum<Resources>, 'string', 'required'>;
@@ -26,5 +47,5 @@ type ResolvedIncludedProps<Props extends InPropsObject, IncludeProps extends Inc
26
47
  type ResolvedIncludedPropsAsDefined<Props extends InPropsObject, IncludeProps extends IncludedProps<Props>> = ResolveLayoutPropsAsDefined<Pick<Props, RequiredIncludedPropKeys<IncludeProps> & keyof Props>> & Partial<ResolveLayoutPropsAsDefined<Pick<Props, OptionalIncludedPropKeys<IncludeProps> & keyof Props>>>;
27
48
  type LayoutRenderProps<Resources extends ReadonlyArray<ResourceDefinition>, Options extends InPropsDefinition<Resources>, Composables extends ComposableComponents = {}, IncludeProps extends IncludedProps<MergedLayoutInProps<Resources, Options, Composables>> = {}, CustomProps extends InPropsObject = {}> = Show<ResolveProps<CustomProps> & ResolvedIncludedProps<MergedLayoutInProps<Resources, Options, Composables>, IncludeProps>>;
28
49
  //#endregion
29
- export { InPropsDefinition, InPropsFunction, type InPropsObject, InPropsOptions, IncludedProps, InferredInProps, LayoutRenderProps, MergedLayoutInProps, ResolvedIncludedProps, ResolvedIncludedPropsAsDefined };
50
+ export { InPropsDefinition, InPropsFunction, type InPropsObject, InPropsOptions, IncludedProps, InferredInProps, LayoutRenderProps, MergedLayoutInProps, PropsContextRender, PropsRenderDefinition, ResolvedIncludedProps, ResolvedIncludedPropsAsDefined };
30
51
  //# sourceMappingURL=props.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"props.d.cts","names":[],"sources":["../src/props.ts"],"mappings":";;;;;;KAaY,cAAA,mBACQ,aAAA,CAAc,kBAAA;EAGhC,IAAA,EAAM,kBAAA,CAAmB,IAAA;EACzB,QAAA,EAAU,eAAA,CAAgB,YAAA,CAAa,SAAA;AAAA;AAAA,KAE7B,eAAA,mBACQ,aAAA,CAAc,kBAAA,2BAEhC,KAAA,EAAO,IAAA,CAAK,cAAA,CAAe,SAAA,EAAW,IAAA,OACnC,aAAA;AAAA,KACO,iBAAA,mBACQ,aAAA,CAAc,kBAAA,KAC9B,aAAA,GAAgB,eAAA,CAAgB,SAAA;AAAA,KACxB,eAAA,mBACQ,aAAA,CAAc,kBAAA,mBAChB,iBAAA,CAAkB,SAAA,KAChC,OAAA,SAAgB,eAAA,CAAgB,SAAA,IAAa,UAAA,CAAW,OAAA,IAAW,OAAA;AAAA,KAC3D,mBAAA,mBACQ,aAAA,CAAc,kBAAA,mBAChB,iBAAA,CAAkB,SAAA,uBACd,oBAAA,IAClB,eAAA,CAAgB,SAAA,EAAW,OAAA,UAAiB,aAAA,GAC5C,eAAA,CAAgB,SAAA,EAAW,OAAA,IAAW,gBAAA,CAAiB,WAAA;;;;KAK/C,aAAA,mCACE,CAAC;AAAA,KAGV,wBAAA,gDACW,YAAA,GAAe,YAAA,CAAa,GAAA,iBAAoB,GAAA,iBACxD,YAAA;AAAA,KAEH,wBAAA,gDACW,YAAA,GAAe,YAAA,CAAa,GAAA,uBACtC,GAAA,iBAEE,YAAA;AAAA,KAEI,qBAAA,eACI,aAAA,uBACO,aAAA,CAAc,KAAA,KACjC,kBAAA,CACF,IAAA,CAAK,KAAA,EAAO,wBAAA,CAAyB,YAAA,UAAsB,KAAA,KAE3D,OAAA,CACE,kBAAA,CACE,IAAA,CAAK,KAAA,EAAO,wBAAA,CAAyB,YAAA,UAAsB,KAAA;;;;AA9Cf;KAsDtC,8BAAA,eACI,aAAA,uBACO,aAAA,CAAc,KAAA,KACjC,2BAAA,CACF,IAAA,CAAK,KAAA,EAAO,wBAAA,CAAyB,YAAA,UAAsB,KAAA,KAE3D,OAAA,CACE,2BAAA,CACE,IAAA,CAAK,KAAA,EAAO,wBAAA,CAAyB,YAAA,UAAsB,KAAA;AAAA,KAGrD,iBAAA,mBACQ,aAAA,CAAc,kBAAA,mBAChB,iBAAA,CAAkB,SAAA,uBACd,oBAAA,4BACC,aAAA,CACnB,mBAAA,CAAoB,SAAA,EAAW,OAAA,EAAS,WAAA,6BAEtB,aAAA,SAClB,IAAA,CACF,YAAA,CAAa,WAAA,IACX,qBAAA,CACE,mBAAA,CAAoB,SAAA,EAAW,OAAA,EAAS,WAAA,GACxC,YAAA"}
1
+ {"version":3,"file":"props.d.cts","names":[],"sources":["../src/props.ts"],"mappings":";;;;;;AAmBA;;;;;AAAA,KAAY,kBAAA,4CAIP,KAAA,EAAO,WAAA,EAAa,OAAA,EAAS,OAAA,KAAY,MAAA;;;;;;;;;;;;UAa7B,qBAAA,SACP,aAAA,iBACM,KAAA,SAAc,aAAA,GAAgB,YAAA,CAAa,KAAA;EAIzD,KAAA,GAAQ,KAAA;EACR,MAAA,EAAQ,kBAAA,CAAmB,WAAA,EAAa,OAAA,EAAS,MAAA;AAAA;AAAA,KAGvC,cAAA,mBACQ,aAAA,CAAc,kBAAA;EAGhC,IAAA,EAAM,kBAAA,CAAmB,IAAA;EACzB,QAAA,EAAU,eAAA,CAAgB,YAAA,CAAa,SAAA;AAAA;AAAA,KAE7B,eAAA,mBACQ,aAAA,CAAc,kBAAA,2BAEhC,KAAA,EAAO,IAAA,CAAK,cAAA,CAAe,SAAA,EAAW,IAAA,OACnC,aAAA;AAAA,KACO,iBAAA,mBACQ,aAAA,CAAc,kBAAA,KAC9B,aAAA,GAAgB,eAAA,CAAgB,SAAA;AAAA,KACxB,eAAA,mBACQ,aAAA,CAAc,kBAAA,mBAChB,iBAAA,CAAkB,SAAA,KAChC,OAAA,SAAgB,eAAA,CAAgB,SAAA,IAAa,UAAA,CAAW,OAAA,IAAW,OAAA;AAAA,KAC3D,mBAAA,mBACQ,aAAA,CAAc,kBAAA,mBAChB,iBAAA,CAAkB,SAAA,uBACd,oBAAA,IAClB,eAAA,CAAgB,SAAA,EAAW,OAAA,UAAiB,aAAA,GAC5C,eAAA,CAAgB,SAAA,EAAW,OAAA,IAAW,gBAAA,CAAiB,WAAA;;;;KAK/C,aAAA,mCACE,CAAC;AAAA,KAGV,wBAAA,gDACW,YAAA,GAAe,YAAA,CAAa,GAAA,iBAAoB,GAAA,iBACxD,YAAA;AAAA,KAEH,wBAAA,gDACW,YAAA,GAAe,YAAA,CAAa,GAAA,uBACtC,GAAA,iBAEE,YAAA;AAAA,KAEI,qBAAA,eACI,aAAA,uBACO,aAAA,CAAc,KAAA,KACjC,kBAAA,CACF,IAAA,CAAK,KAAA,EAAO,wBAAA,CAAyB,YAAA,UAAsB,KAAA,KAE3D,OAAA,CACE,kBAAA,CACE,IAAA,CAAK,KAAA,EAAO,wBAAA,CAAyB,YAAA,UAAsB,KAAA;;;;;KAQrD,8BAAA,eACI,aAAA,uBACO,aAAA,CAAc,KAAA,KACjC,2BAAA,CACF,IAAA,CAAK,KAAA,EAAO,wBAAA,CAAyB,YAAA,UAAsB,KAAA,KAE3D,OAAA,CACE,2BAAA,CACE,IAAA,CAAK,KAAA,EAAO,wBAAA,CAAyB,YAAA,UAAsB,KAAA;AAAA,KAGrD,iBAAA,mBACQ,aAAA,CAAc,kBAAA,mBAChB,iBAAA,CAAkB,SAAA,uBACd,oBAAA,4BACC,aAAA,CACnB,mBAAA,CAAoB,SAAA,EAAW,OAAA,EAAS,WAAA,6BAEtB,aAAA,SAClB,IAAA,CACF,YAAA,CAAa,WAAA,IACX,qBAAA,CACE,mBAAA,CAAoB,SAAA,EAAW,OAAA,EAAS,WAAA,GACxC,YAAA"}
package/dist/props.d.mts CHANGED
@@ -4,6 +4,27 @@ import { ComposableComponents, InPropsObject, MergePresetProps } from "@jfdevelo
4
4
  import { EnumWrappedProp, LiteralWrappedProp, ResolveLayoutProps, ResolveLayoutPropsAsDefined, ResolveProps } from "@jfdevelops/react-layout-validator";
5
5
 
6
6
  //#region src/props.d.ts
7
+ /**
8
+ * Two-argument `render(props, context)` used by createComponent and scoped
9
+ * resource components. `Context` is sibling components (scoped) or the
10
+ * resource render context (top-level).
11
+ */
12
+ type PropsContextRender<RenderProps, Context, Result = unknown> = (props: RenderProps, context: Context) => Result;
13
+ /**
14
+ * Shared `{ props?, render }` shape used by createComponent, scoped
15
+ * components, and anywhere else a value declares props and a two-arg render.
16
+ *
17
+ * @typeParam Props - Declared on the entry (`props`). Often an
18
+ * {@link InPropsObject}, or a layout include/custom bag.
19
+ * @typeParam RenderProps - First argument to `render` (defaults to
20
+ * {@link ResolveProps}<Props> when Props is an {@link InPropsObject})
21
+ * @typeParam Result - `render` return type
22
+ * @typeParam Context - Second argument to `render`
23
+ */
24
+ interface PropsRenderDefinition<Props = InPropsObject, RenderProps = (Props extends InPropsObject ? ResolveProps<Props> : unknown), Result = unknown, Context = unknown> {
25
+ props?: Props;
26
+ render: PropsContextRender<RenderProps, Context, Result>;
27
+ }
7
28
  type InPropsOptions<Resources extends ReadonlyArray<ResourceDefinition>, Name extends string> = {
8
29
  name: LiteralWrappedProp<Name, 'string', 'required'>;
9
30
  resource: EnumWrappedProp<ResourceEnum<Resources>, 'string', 'required'>;
@@ -26,5 +47,5 @@ type ResolvedIncludedProps<Props extends InPropsObject, IncludeProps extends Inc
26
47
  type ResolvedIncludedPropsAsDefined<Props extends InPropsObject, IncludeProps extends IncludedProps<Props>> = ResolveLayoutPropsAsDefined<Pick<Props, RequiredIncludedPropKeys<IncludeProps> & keyof Props>> & Partial<ResolveLayoutPropsAsDefined<Pick<Props, OptionalIncludedPropKeys<IncludeProps> & keyof Props>>>;
27
48
  type LayoutRenderProps<Resources extends ReadonlyArray<ResourceDefinition>, Options extends InPropsDefinition<Resources>, Composables extends ComposableComponents = {}, IncludeProps extends IncludedProps<MergedLayoutInProps<Resources, Options, Composables>> = {}, CustomProps extends InPropsObject = {}> = Show<ResolveProps<CustomProps> & ResolvedIncludedProps<MergedLayoutInProps<Resources, Options, Composables>, IncludeProps>>;
28
49
  //#endregion
29
- export { InPropsDefinition, InPropsFunction, type InPropsObject, InPropsOptions, IncludedProps, InferredInProps, LayoutRenderProps, MergedLayoutInProps, ResolvedIncludedProps, ResolvedIncludedPropsAsDefined };
50
+ export { InPropsDefinition, InPropsFunction, type InPropsObject, InPropsOptions, IncludedProps, InferredInProps, LayoutRenderProps, MergedLayoutInProps, PropsContextRender, PropsRenderDefinition, ResolvedIncludedProps, ResolvedIncludedPropsAsDefined };
30
51
  //# sourceMappingURL=props.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"props.d.mts","names":[],"sources":["../src/props.ts"],"mappings":";;;;;;KAaY,cAAA,mBACQ,aAAA,CAAc,kBAAA;EAGhC,IAAA,EAAM,kBAAA,CAAmB,IAAA;EACzB,QAAA,EAAU,eAAA,CAAgB,YAAA,CAAa,SAAA;AAAA;AAAA,KAE7B,eAAA,mBACQ,aAAA,CAAc,kBAAA,2BAEhC,KAAA,EAAO,IAAA,CAAK,cAAA,CAAe,SAAA,EAAW,IAAA,OACnC,aAAA;AAAA,KACO,iBAAA,mBACQ,aAAA,CAAc,kBAAA,KAC9B,aAAA,GAAgB,eAAA,CAAgB,SAAA;AAAA,KACxB,eAAA,mBACQ,aAAA,CAAc,kBAAA,mBAChB,iBAAA,CAAkB,SAAA,KAChC,OAAA,SAAgB,eAAA,CAAgB,SAAA,IAAa,UAAA,CAAW,OAAA,IAAW,OAAA;AAAA,KAC3D,mBAAA,mBACQ,aAAA,CAAc,kBAAA,mBAChB,iBAAA,CAAkB,SAAA,uBACd,oBAAA,IAClB,eAAA,CAAgB,SAAA,EAAW,OAAA,UAAiB,aAAA,GAC5C,eAAA,CAAgB,SAAA,EAAW,OAAA,IAAW,gBAAA,CAAiB,WAAA;;;;KAK/C,aAAA,mCACE,CAAC;AAAA,KAGV,wBAAA,gDACW,YAAA,GAAe,YAAA,CAAa,GAAA,iBAAoB,GAAA,iBACxD,YAAA;AAAA,KAEH,wBAAA,gDACW,YAAA,GAAe,YAAA,CAAa,GAAA,uBACtC,GAAA,iBAEE,YAAA;AAAA,KAEI,qBAAA,eACI,aAAA,uBACO,aAAA,CAAc,KAAA,KACjC,kBAAA,CACF,IAAA,CAAK,KAAA,EAAO,wBAAA,CAAyB,YAAA,UAAsB,KAAA,KAE3D,OAAA,CACE,kBAAA,CACE,IAAA,CAAK,KAAA,EAAO,wBAAA,CAAyB,YAAA,UAAsB,KAAA;;;;AA9Cf;KAsDtC,8BAAA,eACI,aAAA,uBACO,aAAA,CAAc,KAAA,KACjC,2BAAA,CACF,IAAA,CAAK,KAAA,EAAO,wBAAA,CAAyB,YAAA,UAAsB,KAAA,KAE3D,OAAA,CACE,2BAAA,CACE,IAAA,CAAK,KAAA,EAAO,wBAAA,CAAyB,YAAA,UAAsB,KAAA;AAAA,KAGrD,iBAAA,mBACQ,aAAA,CAAc,kBAAA,mBAChB,iBAAA,CAAkB,SAAA,uBACd,oBAAA,4BACC,aAAA,CACnB,mBAAA,CAAoB,SAAA,EAAW,OAAA,EAAS,WAAA,6BAEtB,aAAA,SAClB,IAAA,CACF,YAAA,CAAa,WAAA,IACX,qBAAA,CACE,mBAAA,CAAoB,SAAA,EAAW,OAAA,EAAS,WAAA,GACxC,YAAA"}
1
+ {"version":3,"file":"props.d.mts","names":[],"sources":["../src/props.ts"],"mappings":";;;;;;AAmBA;;;;;AAAA,KAAY,kBAAA,4CAIP,KAAA,EAAO,WAAA,EAAa,OAAA,EAAS,OAAA,KAAY,MAAA;;;;;;;;;;;;UAa7B,qBAAA,SACP,aAAA,iBACM,KAAA,SAAc,aAAA,GAAgB,YAAA,CAAa,KAAA;EAIzD,KAAA,GAAQ,KAAA;EACR,MAAA,EAAQ,kBAAA,CAAmB,WAAA,EAAa,OAAA,EAAS,MAAA;AAAA;AAAA,KAGvC,cAAA,mBACQ,aAAA,CAAc,kBAAA;EAGhC,IAAA,EAAM,kBAAA,CAAmB,IAAA;EACzB,QAAA,EAAU,eAAA,CAAgB,YAAA,CAAa,SAAA;AAAA;AAAA,KAE7B,eAAA,mBACQ,aAAA,CAAc,kBAAA,2BAEhC,KAAA,EAAO,IAAA,CAAK,cAAA,CAAe,SAAA,EAAW,IAAA,OACnC,aAAA;AAAA,KACO,iBAAA,mBACQ,aAAA,CAAc,kBAAA,KAC9B,aAAA,GAAgB,eAAA,CAAgB,SAAA;AAAA,KACxB,eAAA,mBACQ,aAAA,CAAc,kBAAA,mBAChB,iBAAA,CAAkB,SAAA,KAChC,OAAA,SAAgB,eAAA,CAAgB,SAAA,IAAa,UAAA,CAAW,OAAA,IAAW,OAAA;AAAA,KAC3D,mBAAA,mBACQ,aAAA,CAAc,kBAAA,mBAChB,iBAAA,CAAkB,SAAA,uBACd,oBAAA,IAClB,eAAA,CAAgB,SAAA,EAAW,OAAA,UAAiB,aAAA,GAC5C,eAAA,CAAgB,SAAA,EAAW,OAAA,IAAW,gBAAA,CAAiB,WAAA;;;;KAK/C,aAAA,mCACE,CAAC;AAAA,KAGV,wBAAA,gDACW,YAAA,GAAe,YAAA,CAAa,GAAA,iBAAoB,GAAA,iBACxD,YAAA;AAAA,KAEH,wBAAA,gDACW,YAAA,GAAe,YAAA,CAAa,GAAA,uBACtC,GAAA,iBAEE,YAAA;AAAA,KAEI,qBAAA,eACI,aAAA,uBACO,aAAA,CAAc,KAAA,KACjC,kBAAA,CACF,IAAA,CAAK,KAAA,EAAO,wBAAA,CAAyB,YAAA,UAAsB,KAAA,KAE3D,OAAA,CACE,kBAAA,CACE,IAAA,CAAK,KAAA,EAAO,wBAAA,CAAyB,YAAA,UAAsB,KAAA;;;;;KAQrD,8BAAA,eACI,aAAA,uBACO,aAAA,CAAc,KAAA,KACjC,2BAAA,CACF,IAAA,CAAK,KAAA,EAAO,wBAAA,CAAyB,YAAA,UAAsB,KAAA,KAE3D,OAAA,CACE,2BAAA,CACE,IAAA,CAAK,KAAA,EAAO,wBAAA,CAAyB,YAAA,UAAsB,KAAA;AAAA,KAGrD,iBAAA,mBACQ,aAAA,CAAc,kBAAA,mBAChB,iBAAA,CAAkB,SAAA,uBACd,oBAAA,4BACC,aAAA,CACnB,mBAAA,CAAoB,SAAA,EAAW,OAAA,EAAS,WAAA,6BAEtB,aAAA,SAClB,IAAA,CACF,YAAA,CAAa,WAAA,IACX,qBAAA,CACE,mBAAA,CAAoB,SAAA,EAAW,OAAA,EAAS,WAAA,GACxC,YAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.cjs","names":[],"sources":["../src/utils.ts"],"sourcesContent":["export type Show<T> = T extends (...args: infer A) => infer R\n ? (...args: A) => R\n : { [K in keyof T]: T[K] } & {};\nexport type MergeIntersection<T> = {\n [Key in keyof T]: T[Key];\n};\nexport type IsUnion<T, U = T> = T extends unknown\n ? [U] extends [T]\n ? false\n : true\n : never;\nexport type UnionToIntersection<Union> = (\n Union extends unknown ? (value: Union) => void : never\n) extends (value: infer Intersection) => void\n ? Intersection\n : never;\nexport type Updater<T> = T | ((prev: T) => T);\n\nexport interface BaseComponent<Name extends string, Props = {}> {\n /**\n * The name of the component. Useful for debugging and error messages.\n */\n displayName: Name;\n /**\n * A type only property to get the type of the props. At runtime,\n * this is `undefined`.\n */\n props: Props;\n}\n\nexport function pick<T extends object, K extends keyof T>(obj: T, keys: K[]) {\n if (keys.length === 0) {\n return {} as Pick<T, K>;\n }\n\n return keys.reduce(\n (acc, key) => {\n if (key in obj) acc[key] = obj[key];\n\n return acc;\n },\n {} as Pick<T, K>,\n );\n}\n\nexport function functionalUpdate<T>(value: T, updater: Updater<T>){\n if (typeof updater === 'function') {\n return (updater as (prev: T) => T)(value);\n }\n\n return updater;\n}\n"],"mappings":";;AA8BA,SAAgB,KAA0C,KAAQ,MAAW;CAC3E,IAAI,KAAK,WAAW,GAClB,OAAO,CAAC;CAGV,OAAO,KAAK,QACT,KAAK,QAAQ;EACZ,IAAI,OAAO,KAAK,IAAI,OAAO,IAAI;EAE/B,OAAO;CACT,GACA,CAAC,CACH;AACF;AAEA,SAAgB,iBAAoB,OAAU,SAAoB;CAChE,IAAI,OAAO,YAAY,YACrB,OAAQ,QAA2B,KAAK;CAG1C,OAAO;AACT"}
1
+ {"version":3,"file":"utils.cjs","names":[],"sources":["../src/utils.ts"],"sourcesContent":["export type Show<T> = T extends (...args: infer A) => infer R\n ? (...args: A) => R\n : { [K in keyof T]: T[K] } & {};\nexport type MergeIntersection<T> = {\n [Key in keyof T]: T[Key];\n};\nexport type IsUnion<T, U = T> = T extends unknown\n ? [U] extends [T]\n ? false\n : true\n : never;\nexport type UnionToIntersection<Union> = (\n Union extends unknown ? (value: Union) => void : never\n) extends (value: infer Intersection) => void\n ? Intersection\n : never;\nexport type Updater<T> = T | ((prev: T) => T);\nexport type OptionalRecord<K extends string, V = unknown> = {\n [key in K]?: V;\n};\n\nexport interface BaseComponent<Name extends string, Props = {}> {\n /**\n * The name of the component. Useful for debugging and error messages.\n */\n displayName: Name;\n /**\n * A type only property to get the type of the props. At runtime,\n * this is `undefined`.\n */\n props: Props;\n}\n\nexport function pick<T extends object, K extends keyof T>(obj: T, keys: K[]) {\n if (keys.length === 0) {\n return {} as Pick<T, K>;\n }\n\n return keys.reduce(\n (acc, key) => {\n if (key in obj) acc[key] = obj[key];\n\n return acc;\n },\n {} as Pick<T, K>,\n );\n}\n\nexport function functionalUpdate<T>(value: T, updater: Updater<T>){\n if (typeof updater === 'function') {\n return (updater as (prev: T) => T)(value);\n }\n\n return updater;\n}\n"],"mappings":";;AAiCA,SAAgB,KAA0C,KAAQ,MAAW;CAC3E,IAAI,KAAK,WAAW,GAClB,OAAO,CAAC;CAGV,OAAO,KAAK,QACT,KAAK,QAAQ;EACZ,IAAI,OAAO,KAAK,IAAI,OAAO,IAAI;EAE/B,OAAO;CACT,GACA,CAAC,CACH;AACF;AAEA,SAAgB,iBAAoB,OAAU,SAAoB;CAChE,IAAI,OAAO,YAAY,YACrB,OAAQ,QAA2B,KAAK;CAG1C,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.cts","names":[],"sources":["../src/utils.ts"],"mappings":";KAAY,IAAA,MAAU,CAAA,cAAc,IAAA,6BAC5B,IAAA,EAAM,CAAA,KAAM,CAAA,iBACF,CAAA,GAAI,CAAA,CAAE,CAAA;AAAA,KACZ,iBAAA,sBACI,CAAA,GAAI,CAAA,CAAE,GAAA;AAAA,KAOV,mBAAA,WACV,KAAA,oBAAyB,KAAA,EAAO,KAAK,6BAC5B,KAAA,iCACP,YAAA;AAAA,KAEQ,OAAA,MAAa,CAAA,KAAM,IAAA,EAAM,CAAA,KAAM,CAAA;AAAA,UAE1B,aAAA;EAhBQ;;;EAoBvB,WAAA,EAAa,IAAA;EAtBqB;;;;EA2BlC,KAAA,EAAO,KAAK;AAAA;AAAA,iBAGE,IAAA,mCAAuC,CAAA,EAAG,GAAA,EAAK,CAAA,EAAG,IAAA,EAAM,CAAA,KAAG,IAAA,CAAA,CAAA,EAAA,CAAA"}
1
+ {"version":3,"file":"utils.d.cts","names":[],"sources":["../src/utils.ts"],"mappings":";KAAY,IAAA,MAAU,CAAA,cAAc,IAAA,6BAC5B,IAAA,EAAM,CAAA,KAAM,CAAA,iBACF,CAAA,GAAI,CAAA,CAAE,CAAA;AAAA,KACZ,iBAAA,sBACI,CAAA,GAAI,CAAA,CAAE,GAAA;AAAA,KAOV,mBAAA,WACV,KAAA,oBAAyB,KAAA,EAAO,KAAK,6BAC5B,KAAA,iCACP,YAAA;AAAA,KAEQ,OAAA,MAAa,CAAA,KAAM,IAAA,EAAM,CAAA,KAAM,CAAA;AAAA,UAK1B,aAAA;EArBK;;;EAyBpB,WAAA,EAAa,IAAA;EAxBP;;;;EA6BN,KAAA,EAAO,KAAK;AAAA;AAAA,iBAGE,IAAA,mCAAuC,CAAA,EAAG,GAAA,EAAK,CAAA,EAAG,IAAA,EAAM,CAAA,KAAG,IAAA,CAAA,CAAA,EAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.mts","names":[],"sources":["../src/utils.ts"],"mappings":";KAAY,IAAA,MAAU,CAAA,cAAc,IAAA,6BAC5B,IAAA,EAAM,CAAA,KAAM,CAAA,iBACF,CAAA,GAAI,CAAA,CAAE,CAAA;AAAA,KACZ,iBAAA,sBACI,CAAA,GAAI,CAAA,CAAE,GAAA;AAAA,KAOV,mBAAA,WACV,KAAA,oBAAyB,KAAA,EAAO,KAAK,6BAC5B,KAAA,iCACP,YAAA;AAAA,KAEQ,OAAA,MAAa,CAAA,KAAM,IAAA,EAAM,CAAA,KAAM,CAAA;AAAA,UAE1B,aAAA;EAhBQ;;;EAoBvB,WAAA,EAAa,IAAA;EAtBqB;;;;EA2BlC,KAAA,EAAO,KAAK;AAAA;AAAA,iBAGE,IAAA,mCAAuC,CAAA,EAAG,GAAA,EAAK,CAAA,EAAG,IAAA,EAAM,CAAA,KAAG,IAAA,CAAA,CAAA,EAAA,CAAA"}
1
+ {"version":3,"file":"utils.d.mts","names":[],"sources":["../src/utils.ts"],"mappings":";KAAY,IAAA,MAAU,CAAA,cAAc,IAAA,6BAC5B,IAAA,EAAM,CAAA,KAAM,CAAA,iBACF,CAAA,GAAI,CAAA,CAAE,CAAA;AAAA,KACZ,iBAAA,sBACI,CAAA,GAAI,CAAA,CAAE,GAAA;AAAA,KAOV,mBAAA,WACV,KAAA,oBAAyB,KAAA,EAAO,KAAK,6BAC5B,KAAA,iCACP,YAAA;AAAA,KAEQ,OAAA,MAAa,CAAA,KAAM,IAAA,EAAM,CAAA,KAAM,CAAA;AAAA,UAK1B,aAAA;EArBK;;;EAyBpB,WAAA,EAAa,IAAA;EAxBP;;;;EA6BN,KAAA,EAAO,KAAK;AAAA;AAAA,iBAGE,IAAA,mCAAuC,CAAA,EAAG,GAAA,EAAK,CAAA,EAAG,IAAA,EAAM,CAAA,KAAG,IAAA,CAAA,CAAA,EAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.mjs","names":[],"sources":["../src/utils.ts"],"sourcesContent":["export type Show<T> = T extends (...args: infer A) => infer R\n ? (...args: A) => R\n : { [K in keyof T]: T[K] } & {};\nexport type MergeIntersection<T> = {\n [Key in keyof T]: T[Key];\n};\nexport type IsUnion<T, U = T> = T extends unknown\n ? [U] extends [T]\n ? false\n : true\n : never;\nexport type UnionToIntersection<Union> = (\n Union extends unknown ? (value: Union) => void : never\n) extends (value: infer Intersection) => void\n ? Intersection\n : never;\nexport type Updater<T> = T | ((prev: T) => T);\n\nexport interface BaseComponent<Name extends string, Props = {}> {\n /**\n * The name of the component. Useful for debugging and error messages.\n */\n displayName: Name;\n /**\n * A type only property to get the type of the props. At runtime,\n * this is `undefined`.\n */\n props: Props;\n}\n\nexport function pick<T extends object, K extends keyof T>(obj: T, keys: K[]) {\n if (keys.length === 0) {\n return {} as Pick<T, K>;\n }\n\n return keys.reduce(\n (acc, key) => {\n if (key in obj) acc[key] = obj[key];\n\n return acc;\n },\n {} as Pick<T, K>,\n );\n}\n\nexport function functionalUpdate<T>(value: T, updater: Updater<T>){\n if (typeof updater === 'function') {\n return (updater as (prev: T) => T)(value);\n }\n\n return updater;\n}\n"],"mappings":";AA8BA,SAAgB,KAA0C,KAAQ,MAAW;CAC3E,IAAI,KAAK,WAAW,GAClB,OAAO,CAAC;CAGV,OAAO,KAAK,QACT,KAAK,QAAQ;EACZ,IAAI,OAAO,KAAK,IAAI,OAAO,IAAI;EAE/B,OAAO;CACT,GACA,CAAC,CACH;AACF;AAEA,SAAgB,iBAAoB,OAAU,SAAoB;CAChE,IAAI,OAAO,YAAY,YACrB,OAAQ,QAA2B,KAAK;CAG1C,OAAO;AACT"}
1
+ {"version":3,"file":"utils.mjs","names":[],"sources":["../src/utils.ts"],"sourcesContent":["export type Show<T> = T extends (...args: infer A) => infer R\n ? (...args: A) => R\n : { [K in keyof T]: T[K] } & {};\nexport type MergeIntersection<T> = {\n [Key in keyof T]: T[Key];\n};\nexport type IsUnion<T, U = T> = T extends unknown\n ? [U] extends [T]\n ? false\n : true\n : never;\nexport type UnionToIntersection<Union> = (\n Union extends unknown ? (value: Union) => void : never\n) extends (value: infer Intersection) => void\n ? Intersection\n : never;\nexport type Updater<T> = T | ((prev: T) => T);\nexport type OptionalRecord<K extends string, V = unknown> = {\n [key in K]?: V;\n};\n\nexport interface BaseComponent<Name extends string, Props = {}> {\n /**\n * The name of the component. Useful for debugging and error messages.\n */\n displayName: Name;\n /**\n * A type only property to get the type of the props. At runtime,\n * this is `undefined`.\n */\n props: Props;\n}\n\nexport function pick<T extends object, K extends keyof T>(obj: T, keys: K[]) {\n if (keys.length === 0) {\n return {} as Pick<T, K>;\n }\n\n return keys.reduce(\n (acc, key) => {\n if (key in obj) acc[key] = obj[key];\n\n return acc;\n },\n {} as Pick<T, K>,\n );\n}\n\nexport function functionalUpdate<T>(value: T, updater: Updater<T>){\n if (typeof updater === 'function') {\n return (updater as (prev: T) => T)(value);\n }\n\n return updater;\n}\n"],"mappings":";AAiCA,SAAgB,KAA0C,KAAQ,MAAW;CAC3E,IAAI,KAAK,WAAW,GAClB,OAAO,CAAC;CAGV,OAAO,KAAK,QACT,KAAK,QAAQ;EACZ,IAAI,OAAO,KAAK,IAAI,OAAO,IAAI;EAE/B,OAAO;CACT,GACA,CAAC,CACH;AACF;AAEA,SAAgB,iBAAoB,OAAU,SAAoB;CAChE,IAAI,OAAO,YAAY,YACrB,OAAQ,QAA2B,KAAK;CAG1C,OAAO;AACT"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jfdevelops/react-layout",
3
- "version": "0.15.1",
3
+ "version": "0.17.0",
4
4
  "description": "A React library for creating layout components.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -8,7 +8,8 @@
8
8
  },
9
9
  "type": "module",
10
10
  "files": [
11
- "dist"
11
+ "dist",
12
+ "skills"
12
13
  ],
13
14
  "sideEffects": false,
14
15
  "main": "./dist/index.cjs",
@@ -0,0 +1,132 @@
1
+ ---
2
+ name: build-react-layouts
3
+ description: Build, extend, refactor, and review typed resource-based React application layouts using @jfdevelops/react-layout. Use when defining shared application shells with defineResourceLayout, generating resource pages with createResourceLayout, creating semantic composables, configuring grouped resource navigation, dispatching route components with createResourceConfig, building create or detail panes, or sharing implementations across multiple resources.
4
+ ---
5
+
6
+ # Build React Layouts
7
+
8
+ Use `@jfdevelops/react-layout` as a typed application-structure layer.
9
+
10
+ Model the application around a central resource definition, a shared layout
11
+ contract, small resource-specific page configurations, and router adapters that
12
+ dispatch through the resource configuration. Create additional layout
13
+ definitions for structurally different surfaces such as side panes.
14
+
15
+ Do not treat the library as a replacement for routing, data fetching, form
16
+ state, or application business logic.
17
+
18
+ ## Follow the workflow
19
+
20
+ 1. Inspect the existing layout definition and resource list.
21
+ 2. Identify whether the requested surface belongs to an existing layout family.
22
+ 3. Add or reuse the resource in the central definition.
23
+ 4. Define shared configuration values with `createProp`.
24
+ 5. Expose semantic layout regions through composables.
25
+ 6. Generate the narrowest suitable page factory.
26
+ 7. Connect navigation and route-state dispatch through the helpers returned by
27
+ `defineResourceLayout`.
28
+ 8. Run the application's typecheck and relevant tests.
29
+
30
+ Read [references/architecture.md](references/architecture.md) before creating
31
+ or substantially restructuring a layout definition.
32
+
33
+ Read [references/factory-patterns.md](references/factory-patterns.md) when
34
+ choosing between direct creation, `forResource`, `forResources`,
35
+ `makeComposable`, or `createComponent(...).asHOF()`.
36
+
37
+ Read
38
+ [references/routing-and-navigation.md](references/routing-and-navigation.md)
39
+ when integrating resource links, route components, pending states, errors, or
40
+ not-found states.
41
+
42
+ ## Apply the core conventions
43
+
44
+ - Import `defineResourceLayout` and `createProp` from
45
+ `@jfdevelops/react-layout`.
46
+ - Import optional preset composables from their dedicated packages.
47
+ - Export the helpers returned by the central `defineResourceLayout` call.
48
+ - Keep the authoritative resource list in the central layout definition.
49
+ - Use resource names that match the application's route vocabulary.
50
+ - Define reusable configuration in `options`.
51
+ - Use `layout.props.include` for definition-time values consumed by the shared
52
+ renderer.
53
+ - Use `layout.props.custom` for props passed when rendering the generated React
54
+ component.
55
+ - Use `createProp.component({ type: 'ReactNode' })` for React content.
56
+ - Mark genuinely optional values with `.optional()`.
57
+ - Give optional custom values defaults in the shared renderer when appropriate.
58
+ - Name composables by semantic role rather than visual implementation.
59
+ - Connect semantic composables to design-system components with `wrapWith`.
60
+ - Use resource-aware composable names so generated components remain
61
+ identifiable in React DevTools.
62
+ - Keep page configuration close to the corresponding resource feature.
63
+ - Keep resource routing generic instead of building a separate route component
64
+ for every resource.
65
+ - Confirm helper signatures against the installed package version and let the
66
+ current TypeScript types determine which resource-configuration branches are
67
+ supported.
68
+ - Reuse the consuming application's router and runtime-validation tools. Do not
69
+ add a schema dependency solely to connect a route parameter to a resource.
70
+ - Create a separate `defineResourceLayout` definition for a surface with a
71
+ meaningfully different structural contract, such as a create or detail pane.
72
+ - Preserve inferred types. Do not use `any`, broad casts, or duplicated
73
+ hand-written resource types to work around a layout mismatch.
74
+
75
+ ## Define semantic composables
76
+
77
+ Prefer names that describe application structure, such as `Layout`, `Header`,
78
+ `Content`, `ResourceLayout`, `ResourceHeader`, `ResourceHeaderActions`, and
79
+ `Breadcrumb`.
80
+
81
+ Do not expose every wrapper element as a composable. Expose a region when
82
+ consumers may need to replace it, compose it, style it, or address it through a
83
+ generated component.
84
+
85
+ ## Separate definition-time and render-time props
86
+
87
+ Use `options` for values supplied while creating a resource layout:
88
+
89
+ ```tsx
90
+ options: {
91
+ title: createProp.component({ type: 'ReactNode' }).optional(),
92
+ }
93
+ ```
94
+
95
+ Make an option available to the shared renderer through `include`:
96
+
97
+ ```tsx
98
+ layout: {
99
+ props: {
100
+ include: {
101
+ title: true,
102
+ },
103
+ },
104
+ }
105
+ ```
106
+
107
+ Use `custom` for values supplied when rendering the resulting component:
108
+
109
+ ```tsx
110
+ layout: {
111
+ props: {
112
+ custom: {
113
+ children: createProp.component({ type: 'ReactNode' }),
114
+ actions: createProp.component({ type: 'ReactNode' }).optional(),
115
+ showHeader: createProp.boolean().optional(),
116
+ },
117
+ },
118
+ }
119
+ ```
120
+
121
+ Keep these categories distinct. Do not turn a definition-time page contract
122
+ into a custom render prop merely because both eventually reach the renderer.
123
+
124
+ ## Verify the result
125
+
126
+ 1. Typecheck the consuming application.
127
+ 2. Run relevant component and route tests.
128
+ 3. Exercise at least one resource page.
129
+ 4. Exercise pending, error, and not-found dispatch if route configuration
130
+ changed.
131
+ 5. Exercise create and detail panes if pane configuration changed.
132
+ 6. Confirm grouped navigation generates the intended resource and route.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Build React Layouts"
3
+ short_description: "Build typed resource-driven React layouts"
4
+ default_prompt: "Use $build-react-layouts to build or refactor a typed resource-based React application layout."
@@ -0,0 +1,184 @@
1
+ # Application Architecture
2
+
3
+ ## Contents
4
+
5
+ - Central layout definition
6
+ - Shared layout contract
7
+ - Semantic composables
8
+ - Preset composables
9
+ - Secondary layout families
10
+ - Feature organization
11
+
12
+ ## Create a central layout definition
13
+
14
+ Create one central definition for resources that share the same application
15
+ shell. Export the generated helpers from that module:
16
+
17
+ ```tsx
18
+ import {
19
+ createProp,
20
+ defineResourceLayout,
21
+ } from '@jfdevelops/react-layout';
22
+
23
+ export const {
24
+ createResourceConfig,
25
+ createResourceLayout,
26
+ createResourceLinks,
27
+ } = defineResourceLayout({
28
+ resources: ['appointments', 'locations', 'services', 'settings'],
29
+ options: {
30
+ title: createProp.component({ type: 'ReactNode' }).optional(),
31
+ },
32
+ layout: {
33
+ // Define the shared contract here.
34
+ },
35
+ });
36
+ ```
37
+
38
+ Import these generated helpers in feature modules instead of defining parallel
39
+ resource lists or rebuilding the application shell.
40
+
41
+ ## Define the shared layout contract
42
+
43
+ Separate definition-time configuration from render-time component props:
44
+
45
+ ```tsx
46
+ layout: {
47
+ props: {
48
+ include: {
49
+ title: true,
50
+ segments: true,
51
+ },
52
+ custom: {
53
+ children: createProp.component({ type: 'ReactNode' }),
54
+ actions: createProp.component({ type: 'ReactNode' }).optional(),
55
+ showHeader: createProp.boolean().optional(),
56
+ },
57
+ },
58
+ }
59
+ ```
60
+
61
+ Use included props for values that describe the generated page. Use custom
62
+ props for content supplied when the generated page component is rendered.
63
+
64
+ Default optional behavioral props in the renderer:
65
+
66
+ ```tsx
67
+ render: (
68
+ { children, actions, showHeader = true, segments },
69
+ { composables },
70
+ ) => {
71
+ // Render the shared shell.
72
+ }
73
+ ```
74
+
75
+ ## Create semantic composables
76
+
77
+ Define named layout regions through the scoped `create` function:
78
+
79
+ ```tsx
80
+ composables: (create) => ({
81
+ Layout: create({
82
+ name: ({ capitalize, resource }) =>
83
+ `${capitalize(resource)}Layout`,
84
+ wrapWith: AppLayout,
85
+ }),
86
+ Header: create({
87
+ name: ({ capitalize, resource }) =>
88
+ `${capitalize(resource)}Header`,
89
+ wrapWith: AppHeader,
90
+ }),
91
+ Content: create({
92
+ name: ({ capitalize, resource }) =>
93
+ `${capitalize(resource)}Content`,
94
+ wrapWith: AppContent,
95
+ }),
96
+ ResourceHeaderActions: create({
97
+ name: ({ capitalize, resource }) =>
98
+ `${capitalize(resource)}ResourceHeaderActions`,
99
+ wrapWith: AppResourceHeaderActions,
100
+ }),
101
+ }),
102
+ ```
103
+
104
+ Make the composable name communicate the region's role. Use `wrapWith` to
105
+ connect that role to the application's design-system implementation.
106
+
107
+ ## Merge preset composables
108
+
109
+ Merge optional preset composables into the same semantic map:
110
+
111
+ ```tsx
112
+ import {
113
+ createBreadcrumbComposable,
114
+ } from '@jfdevelops/react-layout-composable-breadcrumb';
115
+
116
+ composables: (create) => ({
117
+ Layout: create({ name: 'Layout', wrapWith: AppLayout }),
118
+ ...createBreadcrumbComposable(({ segments }) => (
119
+ <AppBreadcrumb segments={segments} />
120
+ )),
121
+ })
122
+ ```
123
+
124
+ Include the preset's required values in `layout.props.include`. Keep
125
+ presentation in the preset renderer and segment definitions in resource page
126
+ configuration.
127
+
128
+ ## Create secondary layout families
129
+
130
+ Create another `defineResourceLayout` when a surface has a distinct structural
131
+ contract. A side pane is not merely a variation of the main page shell:
132
+
133
+ ```tsx
134
+ export const resourcePaneLayout = defineResourceLayout({
135
+ resources: ['create', 'detail'],
136
+ options: {
137
+ title: createProp.component({ type: 'ReactNode' }),
138
+ },
139
+ layout: {
140
+ props: {
141
+ include: {
142
+ title: true,
143
+ },
144
+ custom: {
145
+ children: createProp.component({ type: 'ReactNode' }),
146
+ },
147
+ },
148
+ render: function Render({ children, title }) {
149
+ return (
150
+ <Panel>
151
+ <PanelHeader>
152
+ <PanelTitle>{title}</PanelTitle>
153
+ </PanelHeader>
154
+ <PanelContent>{children}</PanelContent>
155
+ </Panel>
156
+ );
157
+ },
158
+ },
159
+ });
160
+ ```
161
+
162
+ Do not overload the main page layout with pane-specific flags and conditional
163
+ branches.
164
+
165
+ ## Organize by feature
166
+
167
+ Keep the general layout definition centralized and concrete page definitions
168
+ beside their feature:
169
+
170
+ ```text
171
+ admin/
172
+ ├── -utils/
173
+ │ └── layout.tsx
174
+ ├── $resource/
175
+ │ ├── -page-config.tsx
176
+ │ ├── -pane/
177
+ │ │ └── layout.tsx
178
+ │ ├── -appointments/
179
+ │ │ └── pages-config.ts
180
+ │ ├── -locations/
181
+ │ │ └── pages-config.ts
182
+ │ └── index.tsx
183
+ └── route.tsx
184
+ ```