@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.
- package/dist/create-config/define-layout.cjs +15 -4
- package/dist/create-config/define-layout.cjs.map +1 -1
- package/dist/create-config/define-layout.d.cts +31 -5
- package/dist/create-config/define-layout.d.cts.map +1 -1
- package/dist/create-config/define-layout.d.mts +31 -5
- package/dist/create-config/define-layout.d.mts.map +1 -1
- package/dist/create-config/define-layout.mjs +14 -3
- package/dist/create-config/define-layout.mjs.map +1 -1
- package/dist/create-config/for-resources/create-component.d.cts +284 -0
- package/dist/create-config/for-resources/create-component.d.cts.map +1 -0
- package/dist/create-config/for-resources/create-component.d.mts +284 -0
- package/dist/create-config/for-resources/create-component.d.mts.map +1 -0
- package/dist/create-config/{for-resources.cjs → for-resources/create-for-resources.cjs} +78 -39
- package/dist/create-config/for-resources/create-for-resources.cjs.map +1 -0
- package/dist/create-config/for-resources/create-for-resources.d.cts +1 -0
- package/dist/create-config/for-resources/create-for-resources.d.mts +1 -0
- package/dist/create-config/{for-resources.mjs → for-resources/create-for-resources.mjs} +77 -38
- package/dist/create-config/for-resources/create-for-resources.mjs.map +1 -0
- package/dist/create-config/for-resources/index.d.cts +1 -0
- package/dist/create-config/for-resources/index.d.mts +1 -0
- package/dist/create-config/for-resources/resource-selection.d.cts +47 -0
- package/dist/create-config/for-resources/resource-selection.d.cts.map +1 -0
- package/dist/create-config/for-resources/resource-selection.d.mts +47 -0
- package/dist/create-config/for-resources/resource-selection.d.mts.map +1 -0
- package/dist/create-config/for-resources/scoped-layout.d.cts +185 -0
- package/dist/create-config/for-resources/scoped-layout.d.cts.map +1 -0
- package/dist/create-config/for-resources/scoped-layout.d.mts +185 -0
- package/dist/create-config/for-resources/scoped-layout.d.mts.map +1 -0
- package/dist/create-config/for-resources/scoped-render.cjs +103 -0
- package/dist/create-config/for-resources/scoped-render.cjs.map +1 -0
- package/dist/create-config/for-resources/scoped-render.d.cts +18 -0
- package/dist/create-config/for-resources/scoped-render.d.cts.map +1 -0
- package/dist/create-config/for-resources/scoped-render.d.mts +18 -0
- package/dist/create-config/for-resources/scoped-render.d.mts.map +1 -0
- package/dist/create-config/for-resources/scoped-render.mjs +100 -0
- package/dist/create-config/for-resources/scoped-render.mjs.map +1 -0
- package/dist/create-config/index.d.cts +1 -1
- package/dist/create-config/index.d.mts +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/props.d.cts +22 -1
- package/dist/props.d.cts.map +1 -1
- package/dist/props.d.mts +22 -1
- package/dist/props.d.mts.map +1 -1
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts.map +1 -1
- package/dist/utils.d.mts.map +1 -1
- package/dist/utils.mjs.map +1 -1
- package/package.json +3 -2
- package/skills/build-react-layouts/SKILL.md +132 -0
- package/skills/build-react-layouts/agents/openai.yaml +4 -0
- package/skills/build-react-layouts/references/architecture.md +184 -0
- package/skills/build-react-layouts/references/factory-patterns.md +156 -0
- package/skills/build-react-layouts/references/routing-and-navigation.md +174 -0
- package/dist/create-config/for-resources.cjs.map +0 -1
- package/dist/create-config/for-resources.d.cts +0 -358
- package/dist/create-config/for-resources.d.cts.map +0 -1
- package/dist/create-config/for-resources.d.mts +0 -358
- package/dist/create-config/for-resources.d.mts.map +0 -1
- 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
|
package/dist/props.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"props.d.cts","names":[],"sources":["../src/props.ts"],"mappings":";;;;;;
|
|
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
|
package/dist/props.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"props.d.mts","names":[],"sources":["../src/props.ts"],"mappings":";;;;;;
|
|
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"}
|
package/dist/utils.cjs.map
CHANGED
|
@@ -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":";;
|
|
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"}
|
package/dist/utils.d.cts.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/dist/utils.d.mts.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/dist/utils.mjs.map
CHANGED
|
@@ -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":";
|
|
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.
|
|
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,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
|
+
```
|