@jfdevelops/react-layout 1.0.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/create-config/create-defined-resource-layout.cjs +14 -7
  2. package/dist/create-config/create-defined-resource-layout.cjs.map +1 -1
  3. package/dist/create-config/create-defined-resource-layout.d.cts +30 -17
  4. package/dist/create-config/create-defined-resource-layout.d.cts.map +1 -1
  5. package/dist/create-config/create-defined-resource-layout.d.mts +30 -17
  6. package/dist/create-config/create-defined-resource-layout.d.mts.map +1 -1
  7. package/dist/create-config/create-defined-resource-layout.mjs +14 -7
  8. package/dist/create-config/create-defined-resource-layout.mjs.map +1 -1
  9. package/dist/create-config/define-layout.cjs +67 -28
  10. package/dist/create-config/define-layout.cjs.map +1 -1
  11. package/dist/create-config/define-layout.d.cts +88 -71
  12. package/dist/create-config/define-layout.d.cts.map +1 -1
  13. package/dist/create-config/define-layout.d.mts +88 -71
  14. package/dist/create-config/define-layout.d.mts.map +1 -1
  15. package/dist/create-config/define-layout.mjs +67 -28
  16. package/dist/create-config/define-layout.mjs.map +1 -1
  17. package/dist/create-config/for-resource.cjs.map +1 -1
  18. package/dist/create-config/for-resource.d.cts +24 -16
  19. package/dist/create-config/for-resource.d.cts.map +1 -1
  20. package/dist/create-config/for-resource.d.mts +24 -16
  21. package/dist/create-config/for-resource.d.mts.map +1 -1
  22. package/dist/create-config/for-resource.mjs.map +1 -1
  23. package/dist/create-config/for-resources/create-for-resources.cjs +1 -0
  24. package/dist/create-config/for-resources/create-for-resources.cjs.map +1 -1
  25. package/dist/create-config/for-resources/create-for-resources.mjs +1 -0
  26. package/dist/create-config/for-resources/create-for-resources.mjs.map +1 -1
  27. package/dist/create-config/for-resources/scoped-layout.d.cts +14 -12
  28. package/dist/create-config/for-resources/scoped-layout.d.cts.map +1 -1
  29. package/dist/create-config/for-resources/scoped-layout.d.mts +14 -12
  30. package/dist/create-config/for-resources/scoped-layout.d.mts.map +1 -1
  31. package/dist/create-config/index.d.cts +2 -1
  32. package/dist/create-config/index.d.mts +2 -1
  33. package/dist/create-config/lazy-resource-layout.cjs +1 -1
  34. package/dist/create-config/lazy-resource-layout.cjs.map +1 -1
  35. package/dist/create-config/lazy-resource-layout.d.cts +4 -1
  36. package/dist/create-config/lazy-resource-layout.d.cts.map +1 -1
  37. package/dist/create-config/lazy-resource-layout.d.mts +4 -1
  38. package/dist/create-config/lazy-resource-layout.d.mts.map +1 -1
  39. package/dist/create-config/lazy-resource-layout.mjs +1 -1
  40. package/dist/create-config/lazy-resource-layout.mjs.map +1 -1
  41. package/dist/create-config/render-state.cjs +96 -7
  42. package/dist/create-config/render-state.cjs.map +1 -1
  43. package/dist/create-config/render-state.d.cts +100 -15
  44. package/dist/create-config/render-state.d.cts.map +1 -1
  45. package/dist/create-config/render-state.d.mts +100 -15
  46. package/dist/create-config/render-state.d.mts.map +1 -1
  47. package/dist/create-config/render-state.mjs +97 -7
  48. package/dist/create-config/render-state.mjs.map +1 -1
  49. package/dist/create-config/state-composable.cjs +49 -0
  50. package/dist/create-config/state-composable.cjs.map +1 -0
  51. package/dist/create-config/state-composable.d.cts +27 -0
  52. package/dist/create-config/state-composable.d.cts.map +1 -0
  53. package/dist/create-config/state-composable.d.mts +27 -0
  54. package/dist/create-config/state-composable.d.mts.map +1 -0
  55. package/dist/create-config/state-composable.mjs +46 -0
  56. package/dist/create-config/state-composable.mjs.map +1 -0
  57. package/dist/index.d.cts +3 -2
  58. package/dist/index.d.mts +3 -2
  59. package/package.json +1 -1
@@ -11,6 +11,7 @@ import { createResourceLinksFn } from "./create-resource-links.mjs";
11
11
  import { createForResource } from "./for-resource.mjs";
12
12
  import { createForResources } from "./for-resources/create-for-resources.mjs";
13
13
  import { ResourceLayoutShellPublisherContext, useResourceLayoutShellPublisher } from "./shell-context.mjs";
14
+ import { StateComposableContext, createStateReferences } from "./state-composable.mjs";
14
15
  import { deferredRenderStateSymbol, definedResourceLayoutComponentSymbol, findDefinedRenderState, isDeferredRenderState, isLazyRenderState, lazyRenderStateSymbol } from "./render-state.mjs";
15
16
  import { LayoutComposablePresetProvider, collectComposablePresetEntries, makeComposable, resolveLayoutComposables } from "@jfdevelops/react-layout-composables";
16
17
  import { Component, Suspense, createContext, lazy, useCallback, useContext, useLayoutEffect, useMemo, useReducer, useRef, useState } from "react";
@@ -137,8 +138,8 @@ function assertUnreservedResourceSlugs(resources, owner) {
137
138
  if (typeof resource !== "string") assertUnreservedResourceSlugs(resource.subResources, slug);
138
139
  }
139
140
  }
140
- function defineResourceLayoutImpl(options) {
141
- const { options: inProps = {}, resources, layout } = options;
141
+ function defineResourceLayoutImpl(options, inheritedStateScope) {
142
+ const { options: inProps = {}, resources, layout, namespace: defaultNamespace = false } = options;
142
143
  const shellId = options.shellId;
143
144
  assertUnreservedResourceSlugs(resources);
144
145
  const resourcesAccessor = createLayoutResourcesAccessor(resources);
@@ -157,7 +158,7 @@ function defineResourceLayoutImpl(options) {
157
158
  const normalizedResources = normalizeResources(resources);
158
159
  const resourcesEnum = createPrimitivePropBuilder("string").enum(toResourceEnum(normalizedResources));
159
160
  const definedResourceLayout = ((layoutOptions) => {
160
- const { name, props: instancePropDefinitions, ...layoutOptionProps } = layoutOptions;
161
+ const { name, props: instancePropDefinitions, namespace = defaultNamespace, ...layoutOptionProps } = layoutOptions;
161
162
  const createComposableLayout = makeComposable();
162
163
  const nameProp = createProp.string().literal(name);
163
164
  const { resolvedInProps, splitInProps } = splitLayoutInProps({
@@ -170,6 +171,19 @@ function defineResourceLayoutImpl(options) {
170
171
  });
171
172
  const { composables, props: legacyLayoutProps } = layout;
172
173
  const renderStates = typeof layout.render === "function" ? { default: layout.render } : layout.render;
174
+ const referenceComponents = /* @__PURE__ */ new Map();
175
+ const stateScope = inheritedStateScope ?? {
176
+ states: createStateReferences(renderStates),
177
+ resolve(source) {
178
+ for (const [stateName, input] of Object.entries(renderStates)) if (input === source.input) return stateName === "default" ? Component : stateComponents[stateName];
179
+ let reference = referenceComponents.get(source.input);
180
+ if (!reference) {
181
+ reference = createStateComponent(source.name, source.input, false, source.fallbackStateName);
182
+ referenceComponents.set(source.input, reference);
183
+ }
184
+ return reference;
185
+ }
186
+ };
173
187
  const defaultRenderInput = renderStates.default;
174
188
  const createdDefaultState = isDeferredRenderState(defaultRenderInput) || isLazyRenderState(defaultRenderInput);
175
189
  const defaultRenderDefinition = getSynchronousRenderStateDefinition(defaultRenderInput, legacyLayoutProps) ?? { render: () => null };
@@ -190,10 +204,10 @@ function defineResourceLayoutImpl(options) {
190
204
  layoutName: name,
191
205
  resource: layoutContext.resource
192
206
  };
193
- const defaultComposables = defaultState.composables ? (create) => ({
194
- ...composables?.(create) ?? {},
195
- ...defaultState.composables?.(create)
196
- }) : composables;
207
+ const defaultComposables = composables || defaultState.composables ? (create) => ({
208
+ ...composables?.(create, stateScope.states) ?? {},
209
+ ...defaultState.composables?.(create, stateScope.states)
210
+ }) : void 0;
197
211
  const resolvedComposables = defaultComposables ? resolveLayoutComposables(defaultComposables, layoutContext) : void 0;
198
212
  const mergedResolvedInProps = { ...resolvedInProps };
199
213
  for (const { props: presetPropDefinitions } of collectComposablePresetEntries(resolvedComposables)) Object.assign(mergedResolvedInProps, presetPropDefinitions);
@@ -254,7 +268,14 @@ function defineResourceLayoutImpl(options) {
254
268
  resource: layoutContext.resource,
255
269
  children: /* @__PURE__ */ jsx(LayoutComposablePresetProvider, {
256
270
  value: composablePresetProps,
257
- children: /* @__PURE__ */ jsx(RenderDefaultState, { renderProps: layoutRenderProps })
271
+ children: /* @__PURE__ */ jsx(StateComposableContext.Provider, {
272
+ value: {
273
+ scope: stateScope,
274
+ props: layoutRenderProps,
275
+ definitions: mergedResolvedInProps
276
+ },
277
+ children: /* @__PURE__ */ jsx(RenderDefaultState, { renderProps: layoutRenderProps })
278
+ })
258
279
  })
259
280
  });
260
281
  const ErrorComponent = stateComponents.Error;
@@ -273,24 +294,24 @@ function defineResourceLayoutImpl(options) {
273
294
  if (!compositionOptions.components) return {};
274
295
  return { makeComposable: createComposableLayout(compositionOptions) };
275
296
  }
276
- function createStateComponent(stateName, input) {
297
+ function createStateComponent(stateName, input, validateStateName = true, fallbackStateName = stateName) {
277
298
  if (isLazyRenderState(input)) {
278
299
  const loadState = input[lazyRenderStateSymbol];
279
300
  function createLazyState() {
280
301
  return lazy(async () => {
281
- const stateDefinition = findDefinedRenderState(await loadState().catch((error) => {
302
+ const stateDefinition = await findDefinedRenderState(await loadState().catch((error) => {
282
303
  throw new ResourceModuleLoadError(String(layoutContext.resource), error);
283
304
  }));
284
- if (stateDefinition.state !== void 0 && stateDefinition.state !== stateName) throw new LayoutConfigurationError(`Lazy render state "${stateDefinition.state}" cannot be used as "${stateName}"`);
285
- return { default: createLoadedStateComponent(stateName, stateDefinition) };
305
+ if (validateStateName && stateDefinition.state !== void 0 && stateDefinition.state !== stateName) throw new LayoutConfigurationError(`Lazy render state "${stateDefinition.state}" cannot be used as "${stateName}"`);
306
+ return { default: createLoadedStateComponent(validateStateName ? stateName : stateDefinition.state ?? stateName, stateDefinition) };
286
307
  });
287
308
  }
288
309
  function LazyStateComponent(props) {
289
310
  const [, rerender] = useReducer((version) => version + 1, 0);
290
311
  const LazyState = useRef(createLazyState());
291
312
  const CurrentLazyState = LazyState.current;
292
- const LoadingComponent = stateName === "Loading" ? void 0 : stateComponents.Loading;
293
- const ErrorComponent = stateName === "Error" ? void 0 : stateComponents.Error;
313
+ const LoadingComponent = fallbackStateName === "Loading" ? void 0 : stateComponents.Loading;
314
+ const ErrorComponent = fallbackStateName === "Error" ? void 0 : stateComponents.Error;
294
315
  function retry() {
295
316
  LazyState.current = createLazyState();
296
317
  rerender();
@@ -319,8 +340,8 @@ function defineResourceLayoutImpl(options) {
319
340
  if (!isDeferredRenderState(input)) return StateComponent;
320
341
  const DeferredState = lazy(() => Promise.resolve({ default: StateComponent }));
321
342
  function DeferredStateComponent(props) {
322
- const LoadingComponent = stateName === "Loading" ? void 0 : stateComponents.Loading;
323
- const ErrorComponent = stateName === "Error" ? void 0 : stateComponents.Error;
343
+ const LoadingComponent = fallbackStateName === "Loading" ? void 0 : stateComponents.Loading;
344
+ const ErrorComponent = fallbackStateName === "Error" ? void 0 : stateComponents.Error;
324
345
  const rendered = /* @__PURE__ */ jsx(Suspense, {
325
346
  fallback: LoadingComponent ? /* @__PURE__ */ jsx(LoadingComponent, {}) : null,
326
347
  children: /* @__PURE__ */ jsx(DeferredState, { ...props })
@@ -339,10 +360,10 @@ function defineResourceLayoutImpl(options) {
339
360
  return DeferredStateComponent;
340
361
  }
341
362
  function createLoadedStateComponent(stateName, definition) {
342
- const stateComposables = definition.composables ? (create) => ({
343
- ...composables?.(create) ?? {},
344
- ...definition.composables?.(create)
345
- }) : composables;
363
+ const stateComposables = composables || definition.composables ? (create) => ({
364
+ ...composables?.(create, stateScope.states) ?? {},
365
+ ...definition.composables?.(create, stateScope.states)
366
+ }) : void 0;
346
367
  const stateRender = stateName === "Error" ? (props, context) => /* @__PURE__ */ jsx(RenderStateRetryContext.Consumer, { children: (retry) => definition.render(props, {
347
368
  ...context,
348
369
  retry
@@ -355,7 +376,10 @@ function defineResourceLayoutImpl(options) {
355
376
  props: definition.props,
356
377
  render: stateRender
357
378
  }
358
- }).createResourceLayout(layoutOptions);
379
+ }, stateScope).createResourceLayout({
380
+ ...layoutOptions,
381
+ namespace: false
382
+ });
359
383
  StateComponent.displayName = `${name}.${stateName}`;
360
384
  return StateComponent;
361
385
  }
@@ -364,6 +388,7 @@ function defineResourceLayoutImpl(options) {
364
388
  if (stateName === "default") continue;
365
389
  if ([
366
390
  "__proto__",
391
+ "asComposable",
367
392
  "apply",
368
393
  "arguments",
369
394
  "bind",
@@ -384,7 +409,7 @@ function defineResourceLayoutImpl(options) {
384
409
  const definition = mergedResolvedInProps[key];
385
410
  return [[key, isIncludedPropRequired(includeLayoutProps?.[key]) ? definition : definition.optional?.() ?? definition]];
386
411
  }));
387
- return attachComponentPropDefinitions(Object.assign(Component, {
412
+ const rootComponent = attachComponentPropDefinitions(Object.assign(Component, {
388
413
  displayName: name,
389
414
  props: void 0,
390
415
  resource: void 0,
@@ -398,10 +423,21 @@ function defineResourceLayoutImpl(options) {
398
423
  ...customLayoutProps,
399
424
  ...includedComponentDefinitions
400
425
  });
426
+ if (namespace) {
427
+ if (Object.prototype.hasOwnProperty.call(stateComponents, "Root")) throw new LayoutConfigurationError("Render state name \"Root\" is reserved when namespace is true");
428
+ return {
429
+ Root: rootComponent,
430
+ ...stateComponents
431
+ };
432
+ }
433
+ return rootComponent;
401
434
  });
402
435
  const createTopLevelMakeComposable = () => {
403
436
  return (options) => {
404
- const layout = definedResourceLayout(options);
437
+ const layout = definedResourceLayout({
438
+ ...options,
439
+ namespace: false
440
+ });
405
441
  if (!("makeComposable" in layout) || typeof layout.makeComposable !== "function") throw new LayoutConfigurationError("makeComposable requires composables to be defined in the layout");
406
442
  return layout.makeComposable();
407
443
  };
@@ -412,11 +448,13 @@ function defineResourceLayoutImpl(options) {
412
448
  resource: resourcesEnum,
413
449
  name: createProp.string().literal(componentName)
414
450
  }) : inProps);
415
- const defaultState = getSynchronousRenderStateDefinition((typeof layout.render === "function" ? { default: layout.render } : layout.render).default, layout.props);
416
- const defaultComposables = defaultState?.composables ? (create) => ({
417
- ...layout.composables?.(create) ?? {},
418
- ...defaultState.composables?.(create)
419
- }) : layout.composables;
451
+ const renderStates = typeof layout.render === "function" ? { default: layout.render } : layout.render;
452
+ const defaultState = getSynchronousRenderStateDefinition(renderStates.default, layout.props);
453
+ const stateReferences = createStateReferences(renderStates);
454
+ const defaultComposables = layout.composables || defaultState?.composables ? (create) => ({
455
+ ...layout.composables?.(create, stateReferences) ?? {},
456
+ ...defaultState?.composables?.(create, stateReferences)
457
+ }) : void 0;
420
458
  const resolvedComposables = defaultComposables ? resolveLayoutComposables(defaultComposables, {
421
459
  resource,
422
460
  name: componentName,
@@ -619,6 +657,7 @@ function defineResourceLayoutWithLayoutImpl(options) {
619
657
  resources,
620
658
  options: inProps,
621
659
  layout: resolvedLayout,
660
+ namespace: options.namespace,
622
661
  shellId
623
662
  });
624
663
  const Shell = createResourceLayoutShellComponent(resources, inProps ?? {}, shell, shellId);