@jfdevelops/react-layout 0.24.2 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/dist/create-config/create-defined-resource-layout.cjs +67 -0
  2. package/dist/create-config/create-defined-resource-layout.cjs.map +1 -0
  3. package/dist/create-config/create-defined-resource-layout.d.cts +68 -0
  4. package/dist/create-config/create-defined-resource-layout.d.cts.map +1 -0
  5. package/dist/create-config/create-defined-resource-layout.d.mts +68 -0
  6. package/dist/create-config/create-defined-resource-layout.d.mts.map +1 -0
  7. package/dist/create-config/create-defined-resource-layout.mjs +67 -0
  8. package/dist/create-config/create-defined-resource-layout.mjs.map +1 -0
  9. package/dist/create-config/create-resource-links.cjs.map +1 -1
  10. package/dist/create-config/create-resource-links.d.cts +41 -28
  11. package/dist/create-config/create-resource-links.d.cts.map +1 -1
  12. package/dist/create-config/create-resource-links.d.mts +41 -28
  13. package/dist/create-config/create-resource-links.d.mts.map +1 -1
  14. package/dist/create-config/create-resource-links.mjs.map +1 -1
  15. package/dist/create-config/define-layout.cjs +187 -8
  16. package/dist/create-config/define-layout.cjs.map +1 -1
  17. package/dist/create-config/define-layout.d.cts +152 -21
  18. package/dist/create-config/define-layout.d.cts.map +1 -1
  19. package/dist/create-config/define-layout.d.mts +152 -21
  20. package/dist/create-config/define-layout.d.mts.map +1 -1
  21. package/dist/create-config/define-layout.mjs +189 -10
  22. package/dist/create-config/define-layout.mjs.map +1 -1
  23. package/dist/create-config/for-resources/create-for-resources.cjs +7 -0
  24. package/dist/create-config/for-resources/create-for-resources.cjs.map +1 -1
  25. package/dist/create-config/for-resources/create-for-resources.mjs +7 -0
  26. package/dist/create-config/for-resources/create-for-resources.mjs.map +1 -1
  27. package/dist/create-config/index.d.cts +4 -1
  28. package/dist/create-config/index.d.mts +4 -1
  29. package/dist/create-config/lazy-resource-layout.cjs +111 -0
  30. package/dist/create-config/lazy-resource-layout.cjs.map +1 -0
  31. package/dist/create-config/lazy-resource-layout.d.cts +51 -0
  32. package/dist/create-config/lazy-resource-layout.d.cts.map +1 -0
  33. package/dist/create-config/lazy-resource-layout.d.mts +51 -0
  34. package/dist/create-config/lazy-resource-layout.d.mts.map +1 -0
  35. package/dist/create-config/lazy-resource-layout.mjs +111 -0
  36. package/dist/create-config/lazy-resource-layout.mjs.map +1 -0
  37. package/dist/create-config/render-state.cjs +75 -0
  38. package/dist/create-config/render-state.cjs.map +1 -0
  39. package/dist/create-config/render-state.d.cts +120 -0
  40. package/dist/create-config/render-state.d.cts.map +1 -0
  41. package/dist/create-config/render-state.d.mts +120 -0
  42. package/dist/create-config/render-state.d.mts.map +1 -0
  43. package/dist/create-config/render-state.mjs +68 -0
  44. package/dist/create-config/render-state.mjs.map +1 -0
  45. package/dist/errors/resource-state-error.cjs +29 -0
  46. package/dist/errors/resource-state-error.cjs.map +1 -0
  47. package/dist/errors/resource-state-error.d.cts +19 -0
  48. package/dist/errors/resource-state-error.d.cts.map +1 -0
  49. package/dist/errors/resource-state-error.d.mts +19 -0
  50. package/dist/errors/resource-state-error.d.mts.map +1 -0
  51. package/dist/errors/resource-state-error.mjs +27 -0
  52. package/dist/errors/resource-state-error.mjs.map +1 -0
  53. package/dist/index.cjs +5 -0
  54. package/dist/index.d.cts +8 -4
  55. package/dist/index.d.mts +8 -4
  56. package/dist/index.mjs +3 -1
  57. package/dist/props.d.cts +6 -1
  58. package/dist/props.d.cts.map +1 -1
  59. package/dist/props.d.mts +6 -1
  60. package/dist/props.d.mts.map +1 -1
  61. package/dist/resource.cjs.map +1 -1
  62. package/dist/resource.d.cts +7 -1
  63. package/dist/resource.d.cts.map +1 -1
  64. package/dist/resource.d.mts +7 -1
  65. package/dist/resource.d.mts.map +1 -1
  66. package/dist/resource.mjs.map +1 -1
  67. package/package.json +3 -3
@@ -1,6 +1,7 @@
1
1
  const require_invalid_config = require('../errors/invalid-config.cjs');
2
2
  const require_missing_resource_provider = require('../errors/missing-resource-provider.cjs');
3
3
  const require_layout_configuration_error = require('../errors/layout-configuration-error.cjs');
4
+ const require_resource_state_error = require('../errors/resource-state-error.cjs');
4
5
  const require_resource = require('../resource.cjs');
5
6
  const require_utils = require('../utils.cjs');
6
7
  const require_capitalize = require('../utils/capitalize.cjs');
@@ -10,12 +11,31 @@ const require_create_resource_links = require('./create-resource-links.cjs');
10
11
  const require_for_resource = require('./for-resource.cjs');
11
12
  const require_create_for_resources = require('./for-resources/create-for-resources.cjs');
12
13
  const require_shell_context = require('./shell-context.cjs');
14
+ const require_render_state = require('./render-state.cjs');
13
15
  let _jfdevelops_react_layout_composables = require("@jfdevelops/react-layout-composables");
14
16
  let react = require("react");
15
17
  let _jfdevelops_react_layout_validator = require("@jfdevelops/react-layout-validator");
16
18
  let react_jsx_runtime = require("react/jsx-runtime");
17
19
 
18
20
  //#region src/create-config/define-layout.tsx
21
+ const RenderStateRetryContext = (0, react.createContext)(void 0);
22
+ var RenderStateBoundary = class extends react.Component {
23
+ state = {};
24
+ static getDerivedStateFromError(error) {
25
+ return { error };
26
+ }
27
+ retry = () => {
28
+ this.props.onRetry?.();
29
+ this.setState({ error: void 0 });
30
+ };
31
+ render() {
32
+ if (this.state.error !== void 0) return this.props.fallback(this.state.error, this.retry);
33
+ return this.props.children;
34
+ }
35
+ };
36
+ function toResourceStateError(resource, state, error) {
37
+ return error instanceof require_resource_state_error.ResourceModuleLoadError || error instanceof require_resource_state_error.ResourceRenderError ? error : new require_resource_state_error.ResourceRenderError(resource, state, error);
38
+ }
19
39
  function createResourceSelection(definitions) {
20
40
  const selection = (() => definitions);
21
41
  selection.isResource = require_resource.createIsValidResourceFn(definitions);
@@ -88,6 +108,15 @@ function resolveLayoutOptionDefaults(defaults, options) {
88
108
  else resolved[key] = require_utils.functionalUpdate(defaultValue, options[key]);
89
109
  return resolved;
90
110
  }
111
+ function getSynchronousRenderStateDefinition(input, fallbackProps) {
112
+ if (require_render_state.isLazyRenderState(input)) return;
113
+ if (require_render_state.isDeferredRenderState(input)) return input[require_render_state.deferredRenderStateSymbol];
114
+ if (typeof input === "function") return {
115
+ props: fallbackProps,
116
+ render: input
117
+ };
118
+ return typeof input === "object" && input !== null ? input : void 0;
119
+ }
91
120
  function readResourceSlug(resource) {
92
121
  return typeof resource === "string" ? resource : resource.value;
93
122
  }
@@ -129,7 +158,15 @@ function defineResourceLayoutImpl(options) {
129
158
  ...instancePropDefinitions,
130
159
  ...layoutOptionProps
131
160
  });
132
- const { composables, render, props: layoutProps } = layout;
161
+ const { composables, props: legacyLayoutProps } = layout;
162
+ const renderStates = typeof layout.render === "function" ? { default: layout.render } : layout.render;
163
+ const defaultRenderInput = renderStates.default;
164
+ const createdDefaultState = require_render_state.isDeferredRenderState(defaultRenderInput) || require_render_state.isLazyRenderState(defaultRenderInput);
165
+ const defaultRenderDefinition = getSynchronousRenderStateDefinition(defaultRenderInput, legacyLayoutProps) ?? { render: () => null };
166
+ if (typeof defaultRenderDefinition !== "object" || defaultRenderDefinition === null || !("render" in defaultRenderDefinition) || typeof defaultRenderDefinition.render !== "function") throw new require_layout_configuration_error.LayoutConfigurationError("The \"default\" render state must define a render function");
167
+ const defaultState = defaultRenderDefinition;
168
+ const render = defaultState.render;
169
+ const layoutProps = defaultState.props ?? legacyLayoutProps;
133
170
  const customLayoutProps = layoutProps?.custom;
134
171
  const includeLayoutProps = layoutProps?.include;
135
172
  const layoutOptionValues = layoutOptionProps;
@@ -143,7 +180,11 @@ function defineResourceLayoutImpl(options) {
143
180
  layoutName: name,
144
181
  resource: layoutContext.resource
145
182
  };
146
- const resolvedComposables = composables ? (0, _jfdevelops_react_layout_composables.resolveLayoutComposables)(composables, layoutContext) : void 0;
183
+ const defaultComposables = defaultState.composables ? (create) => ({
184
+ ...composables?.(create) ?? {},
185
+ ...defaultState.composables?.(create)
186
+ }) : composables;
187
+ const resolvedComposables = defaultComposables ? (0, _jfdevelops_react_layout_composables.resolveLayoutComposables)(defaultComposables, layoutContext) : void 0;
147
188
  const mergedResolvedInProps = { ...resolvedInProps };
148
189
  for (const { props: presetPropDefinitions } of (0, _jfdevelops_react_layout_composables.collectComposablePresetEntries)(resolvedComposables)) Object.assign(mergedResolvedInProps, presetPropDefinitions);
149
190
  const composablePresetProps = Object.fromEntries((0, _jfdevelops_react_layout_composables.collectComposablePresetEntries)(resolvedComposables).map(({ key, props: presetPropDefinitions }) => {
@@ -160,6 +201,12 @@ function defineResourceLayoutImpl(options) {
160
201
  name: layoutContext.name,
161
202
  inProps: splitInProps
162
203
  };
204
+ const stateComponents = {};
205
+ let CreatedDefaultStateComponent;
206
+ function RenderDefaultState({ renderProps }) {
207
+ if (CreatedDefaultStateComponent) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CreatedDefaultStateComponent, { ...renderProps });
208
+ return render(renderProps, mergedRenderContext);
209
+ }
163
210
  function Component(props) {
164
211
  const publishResource = require_shell_context.useResourceLayoutShellPublisher();
165
212
  (0, react.useLayoutEffect)(() => {
@@ -193,26 +240,153 @@ function defineResourceLayoutImpl(options) {
193
240
  ...validatedProps,
194
241
  ...layoutRenderIncludedProps
195
242
  };
196
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ResourceProvider, {
243
+ const rendered = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ResourceProvider, {
197
244
  resource: layoutContext.resource,
198
245
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_jfdevelops_react_layout_composables.LayoutComposablePresetProvider, {
199
246
  value: composablePresetProps,
200
- children: render(layoutRenderProps, mergedRenderContext)
247
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderDefaultState, { renderProps: layoutRenderProps })
201
248
  })
202
249
  });
250
+ const ErrorComponent = stateComponents.Error;
251
+ return ErrorComponent ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderStateBoundary, {
252
+ fallback: (error, retry) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderStateRetryContext.Provider, {
253
+ value: retry,
254
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorComponent, {
255
+ error: toResourceStateError(String(layoutContext.resource), "default", error),
256
+ retry
257
+ })
258
+ }),
259
+ children: rendered
260
+ }) : rendered;
203
261
  }
204
262
  function createComposition(compositionOptions) {
205
263
  if (!compositionOptions.components) return {};
206
264
  return { makeComposable: createComposableLayout(compositionOptions) };
207
265
  }
208
- return Object.assign(Component, {
266
+ function createStateComponent(stateName, input) {
267
+ if (require_render_state.isLazyRenderState(input)) {
268
+ const loadState = input[require_render_state.lazyRenderStateSymbol];
269
+ function createLazyState() {
270
+ return (0, react.lazy)(async () => {
271
+ const stateDefinition = require_render_state.findDefinedRenderState(await loadState().catch((error) => {
272
+ throw new require_resource_state_error.ResourceModuleLoadError(String(layoutContext.resource), error);
273
+ }));
274
+ if (stateDefinition.state !== void 0 && stateDefinition.state !== stateName) throw new require_layout_configuration_error.LayoutConfigurationError(`Lazy render state "${stateDefinition.state}" cannot be used as "${stateName}"`);
275
+ return { default: createLoadedStateComponent(stateName, stateDefinition) };
276
+ });
277
+ }
278
+ function LazyStateComponent(props) {
279
+ const [, rerender] = (0, react.useReducer)((version) => version + 1, 0);
280
+ const LazyState = (0, react.useRef)(createLazyState());
281
+ const CurrentLazyState = LazyState.current;
282
+ const LoadingComponent = stateName === "Loading" ? void 0 : stateComponents.Loading;
283
+ const ErrorComponent = stateName === "Error" ? void 0 : stateComponents.Error;
284
+ function retry() {
285
+ LazyState.current = createLazyState();
286
+ rerender();
287
+ }
288
+ const rendered = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Suspense, {
289
+ fallback: LoadingComponent ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LoadingComponent, {}) : null,
290
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CurrentLazyState, { ...props })
291
+ });
292
+ return ErrorComponent ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderStateBoundary, {
293
+ fallback: (error, reset) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderStateRetryContext.Provider, {
294
+ value: reset,
295
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorComponent, {
296
+ error: toResourceStateError(String(layoutContext.resource), stateName, error),
297
+ retry: reset
298
+ })
299
+ }),
300
+ onRetry: retry,
301
+ children: rendered
302
+ }) : rendered;
303
+ }
304
+ return LazyStateComponent;
305
+ }
306
+ const definition = require_render_state.isDeferredRenderState(input) ? input[require_render_state.deferredRenderStateSymbol] : typeof input === "function" ? { render: input } : input;
307
+ if (typeof definition !== "object" || definition === null || !("render" in definition) || typeof definition.render !== "function") throw new require_layout_configuration_error.LayoutConfigurationError(`Render state "${stateName}" must define a render function`);
308
+ const StateComponent = createLoadedStateComponent(stateName, definition);
309
+ if (!require_render_state.isDeferredRenderState(input)) return StateComponent;
310
+ const DeferredState = (0, react.lazy)(() => Promise.resolve({ default: StateComponent }));
311
+ function DeferredStateComponent(props) {
312
+ const LoadingComponent = stateName === "Loading" ? void 0 : stateComponents.Loading;
313
+ const ErrorComponent = stateName === "Error" ? void 0 : stateComponents.Error;
314
+ const rendered = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Suspense, {
315
+ fallback: LoadingComponent ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LoadingComponent, {}) : null,
316
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeferredState, { ...props })
317
+ });
318
+ return ErrorComponent ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderStateBoundary, {
319
+ fallback: (error, retry) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderStateRetryContext.Provider, {
320
+ value: retry,
321
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorComponent, {
322
+ error: toResourceStateError(String(layoutContext.resource), stateName, error),
323
+ retry
324
+ })
325
+ }),
326
+ children: rendered
327
+ }) : rendered;
328
+ }
329
+ return DeferredStateComponent;
330
+ }
331
+ function createLoadedStateComponent(stateName, definition) {
332
+ const stateComposables = definition.composables ? (create) => ({
333
+ ...composables?.(create) ?? {},
334
+ ...definition.composables?.(create)
335
+ }) : composables;
336
+ const stateRender = stateName === "Error" ? (props, context) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderStateRetryContext.Consumer, { children: (retry) => definition.render(props, {
337
+ ...context,
338
+ retry
339
+ }) }) : definition.render;
340
+ const StateComponent = defineResourceLayoutImpl({
341
+ resources,
342
+ options: inProps,
343
+ layout: {
344
+ composables: stateComposables,
345
+ props: definition.props,
346
+ render: stateRender
347
+ }
348
+ }).createResourceLayout(layoutOptions);
349
+ StateComponent.displayName = `${name}.${stateName}`;
350
+ return StateComponent;
351
+ }
352
+ if (createdDefaultState) CreatedDefaultStateComponent = createStateComponent("default", defaultRenderInput);
353
+ for (const [stateName, input] of Object.entries(renderStates)) {
354
+ if (stateName === "default") continue;
355
+ if ([
356
+ "__proto__",
357
+ "apply",
358
+ "arguments",
359
+ "bind",
360
+ "call",
361
+ "caller",
362
+ "displayName",
363
+ "length",
364
+ "makeComposable",
365
+ "name",
366
+ "props",
367
+ "prototype",
368
+ "resource"
369
+ ].includes(stateName)) throw new require_layout_configuration_error.LayoutConfigurationError(`Render state name "${stateName}" is reserved`);
370
+ stateComponents[stateName] = createStateComponent(stateName, input);
371
+ }
372
+ const includedComponentDefinitions = Object.fromEntries(Object.keys(includeLayoutProps ?? {}).flatMap((key) => {
373
+ if (!allowsComponentPassthrough(includeLayoutProps?.[key]) || !(key in mergedResolvedInProps)) return [];
374
+ const definition = mergedResolvedInProps[key];
375
+ return [[key, isIncludedPropRequired(includeLayoutProps?.[key]) ? definition : definition.optional?.() ?? definition]];
376
+ }));
377
+ return (0, _jfdevelops_react_layout_validator.attachComponentPropDefinitions)(Object.assign(Component, {
209
378
  displayName: name,
210
379
  props: void 0,
211
380
  resource: void 0,
212
381
  ...createComposition({
213
382
  components: resolvedComposables,
214
383
  name
215
- })
384
+ }),
385
+ ...stateComponents,
386
+ [require_render_state.definedResourceLayoutComponentSymbol]: true
387
+ }), {
388
+ ...customLayoutProps,
389
+ ...includedComponentDefinitions
216
390
  });
217
391
  });
218
392
  const createTopLevelMakeComposable = () => {
@@ -228,7 +402,12 @@ function defineResourceLayoutImpl(options) {
228
402
  resource: resourcesEnum,
229
403
  name: _jfdevelops_react_layout_validator.createProp.string().literal(componentName)
230
404
  }) : inProps);
231
- const resolvedComposables = layout.composables ? (0, _jfdevelops_react_layout_composables.resolveLayoutComposables)(layout.composables, {
405
+ const defaultState = getSynchronousRenderStateDefinition((typeof layout.render === "function" ? { default: layout.render } : layout.render).default, layout.props);
406
+ const defaultComposables = defaultState?.composables ? (create) => ({
407
+ ...layout.composables?.(create) ?? {},
408
+ ...defaultState.composables?.(create)
409
+ }) : layout.composables;
410
+ const resolvedComposables = defaultComposables ? (0, _jfdevelops_react_layout_composables.resolveLayoutComposables)(defaultComposables, {
232
411
  resource,
233
412
  name: componentName,
234
413
  capitalize: require_capitalize.capitalize
@@ -236,7 +415,7 @@ function defineResourceLayoutImpl(options) {
236
415
  for (const { props: presetPropDefinitions } of (0, _jfdevelops_react_layout_composables.collectComposablePresetEntries)(resolvedComposables)) Object.assign(resolvedInProps, presetPropDefinitions);
237
416
  return {
238
417
  ...resolvedInProps,
239
- ...layout.props?.custom
418
+ ...(defaultState?.props ?? layout.props)?.custom
240
419
  };
241
420
  }
242
421
  const { createLayoutForResourceBuilder, forResource } = require_for_resource.createForResource({