@btst/plugin-cms 1.0.0 → 1.2.0-beta.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 (76) hide show
  1. package/dist/api/getters.cjs +37 -25
  2. package/dist/api/getters.mjs +37 -25
  3. package/dist/api/index.cjs +1 -0
  4. package/dist/api/index.d.cts +17 -8
  5. package/dist/api/index.d.mts +17 -8
  6. package/dist/api/index.d.ts +17 -8
  7. package/dist/api/index.mjs +1 -1
  8. package/dist/api/mutations.cjs +46 -19
  9. package/dist/api/mutations.mjs +46 -20
  10. package/dist/api/operations.cjs +586 -177
  11. package/dist/api/operations.mjs +585 -178
  12. package/dist/api/plugin.cjs +56 -7
  13. package/dist/api/plugin.mjs +57 -8
  14. package/dist/api/publication.cjs +8 -0
  15. package/dist/api/publication.mjs +6 -0
  16. package/dist/client/components/forms/content-form.cjs +107 -1
  17. package/dist/client/components/forms/content-form.mjs +108 -2
  18. package/dist/client/components/pages/content-editor-page.internal.cjs +23 -5
  19. package/dist/client/components/pages/content-editor-page.internal.mjs +23 -5
  20. package/dist/client/components/pages/content-list-page.internal.cjs +3 -0
  21. package/dist/client/components/pages/content-list-page.internal.mjs +3 -0
  22. package/dist/client/components/pages/dashboard-page.internal.cjs +10 -30
  23. package/dist/client/components/pages/dashboard-page.internal.mjs +10 -30
  24. package/dist/client/components/revision-history.cjs +161 -0
  25. package/dist/client/components/revision-history.mjs +159 -0
  26. package/dist/client/components/shared/content-type-card.cjs +56 -0
  27. package/dist/client/components/shared/content-type-card.mjs +54 -0
  28. package/dist/client/components/shared/empty-state.cjs +18 -1
  29. package/dist/client/components/shared/empty-state.mjs +19 -2
  30. package/dist/client/hooks/cms-hooks.cjs +18 -2
  31. package/dist/client/hooks/cms-hooks.mjs +17 -3
  32. package/dist/client/hooks/index.cjs +2 -0
  33. package/dist/client/hooks/index.d.cts +306 -2
  34. package/dist/client/hooks/index.d.mts +306 -2
  35. package/dist/client/hooks/index.d.ts +306 -2
  36. package/dist/client/hooks/index.mjs +1 -1
  37. package/dist/client/index.d.cts +55 -2
  38. package/dist/client/index.d.mts +55 -2
  39. package/dist/client/index.d.ts +55 -2
  40. package/dist/db.cjs +25 -0
  41. package/dist/db.mjs +25 -0
  42. package/dist/permissions.cjs +2 -0
  43. package/dist/permissions.d.cts +1 -0
  44. package/dist/permissions.d.mts +1 -0
  45. package/dist/permissions.d.ts +1 -0
  46. package/dist/permissions.mjs +2 -0
  47. package/dist/query-keys.cjs +31 -1
  48. package/dist/query-keys.d.cts +1 -1
  49. package/dist/query-keys.d.mts +1 -1
  50. package/dist/query-keys.d.ts +1 -1
  51. package/dist/query-keys.mjs +31 -1
  52. package/dist/shared/{plugin-cms.W4Le8D91.d.mts → plugin-cms.DAAUZ41w.d.mts} +377 -144
  53. package/dist/shared/{plugin-cms.c-GeWvTf.d.cts → plugin-cms.DJ_293QU.d.cts} +377 -144
  54. package/dist/shared/{plugin-cms.DQLAoogy.d.ts → plugin-cms.DlUSv7wz.d.ts} +377 -144
  55. package/dist/types.d.cts +38 -2
  56. package/dist/types.d.mts +38 -2
  57. package/dist/types.d.ts +38 -2
  58. package/dist/ui/src/components/auto-form/config.cjs +2 -0
  59. package/dist/ui/src/components/auto-form/config.mjs +2 -0
  60. package/dist/ui/src/components/auto-form/fields/file.cjs +68 -0
  61. package/dist/ui/src/components/auto-form/fields/file.mjs +63 -0
  62. package/dist/ui/src/components/auto-form/fields/object.cjs +9 -2
  63. package/dist/ui/src/components/auto-form/fields/object.mjs +9 -2
  64. package/dist/ui/src/components/auto-form/helpers.cjs +9 -0
  65. package/dist/ui/src/components/auto-form/helpers.mjs +9 -0
  66. package/dist/ui/src/components/auto-form/index.cjs +29 -4
  67. package/dist/ui/src/components/auto-form/index.mjs +31 -6
  68. package/dist/ui/src/components/auto-form/stepped-auto-form.cjs +34 -29
  69. package/dist/ui/src/components/auto-form/stepped-auto-form.mjs +35 -30
  70. package/dist/ui/src/components/sheet.cjs +126 -0
  71. package/dist/ui/src/components/sheet.mjs +105 -0
  72. package/dist/ui/src/lib/form-visibility.cjs +20 -0
  73. package/dist/ui/src/lib/form-visibility.mjs +18 -0
  74. package/dist/ui/src/lib/schema-converter.cjs +101 -0
  75. package/dist/ui/src/lib/schema-converter.mjs +100 -1
  76. package/package.json +5 -4
package/dist/types.d.cts CHANGED
@@ -1,5 +1,11 @@
1
1
  import { z } from 'zod';
2
2
 
3
+ /** Explicit publication state stored in one top-level content data field. */
4
+ interface CMSPublicationPolicy {
5
+ stateField: string;
6
+ scheduledValue: string;
7
+ publishedValue: string;
8
+ }
3
9
  /**
4
10
  * Configuration for a content type defined by the developer.
5
11
  *
@@ -21,6 +27,8 @@ interface ContentTypeConfig {
21
27
  description?: string;
22
28
  /** Zod schema defining the content type's fields. Use .meta({ fieldType: "..." }) for field type overrides. */
23
29
  schema: z.ZodObject<z.ZodRawShape>;
30
+ /** Opt in to scheduled transitions and visibility filtering for content views. */
31
+ publication?: CMSPublicationPolicy;
24
32
  }
25
33
  /**
26
34
  * Content type stored in the database
@@ -55,9 +63,30 @@ type ContentItem = {
55
63
  data: string;
56
64
  /** Optional author ID for tracking who created/modified */
57
65
  authorId?: string;
66
+ /** Optional schedule; only explicitly configured content types execute publication. */
67
+ publishAt?: Date | null;
58
68
  createdAt: Date;
59
69
  updatedAt: Date;
60
70
  };
71
+ /** Immutable snapshot appended after each successful CMS write. */
72
+ type ContentRevision = {
73
+ id: string;
74
+ contentItemId: string;
75
+ /** Unique item/version key protects against concurrent revision numbering. */
76
+ revisionKey: string;
77
+ version: number;
78
+ slug: string;
79
+ data: string;
80
+ publishAt?: Date | null;
81
+ /** Identity that performed the write; absent for trusted jobs. */
82
+ authorId?: string | null;
83
+ createdAt: Date;
84
+ };
85
+ /** Revision transported over HTTP, with dates as ISO strings. */
86
+ type SerializedContentRevision = Omit<ContentRevision, "createdAt" | "publishAt"> & {
87
+ createdAt: string;
88
+ publishAt?: string | null;
89
+ };
61
90
  /**
62
91
  * Content item with its content type joined
63
92
  */
@@ -157,9 +186,10 @@ interface SerializedContentType extends Omit<ContentType, "createdAt" | "updated
157
186
  /**
158
187
  * Serialized content item for API responses (dates as strings)
159
188
  */
160
- interface SerializedContentItem extends Omit<ContentItem, "createdAt" | "updatedAt"> {
189
+ interface SerializedContentItem extends Omit<ContentItem, "createdAt" | "updatedAt" | "publishAt"> {
161
190
  createdAt: string;
162
191
  updatedAt: string;
192
+ publishAt?: string | null;
163
193
  }
164
194
  /**
165
195
  * Serialized content item with parsed data and joined content type
@@ -276,6 +306,7 @@ interface CMSCreateOperationContext extends CMSOperationContextBase<{
276
306
  readonly body: {
277
307
  readonly slug: string;
278
308
  readonly data: Readonly<Record<string, CMSOperationData>>;
309
+ readonly publishAt?: string | null;
279
310
  };
280
311
  }, {
281
312
  contentType: string;
@@ -288,6 +319,7 @@ interface CMSCreateOperationContext extends CMSOperationContextBase<{
288
319
  readonly slug: string;
289
320
  /** Validated JSON-safe request fields, including any inline `_new` relation values. */
290
321
  readonly data: Readonly<Record<string, CMSOperationData>>;
322
+ readonly publishAt?: string | null;
291
323
  };
292
324
  }
293
325
  /** CMS create context after execution. */
@@ -302,6 +334,7 @@ interface CMSUpdateOperationContext extends CMSOperationContextBase<{
302
334
  readonly body: {
303
335
  readonly slug?: string;
304
336
  readonly data?: Readonly<Record<string, CMSOperationData>>;
337
+ readonly publishAt?: string | null;
305
338
  };
306
339
  }, {
307
340
  contentType: string;
@@ -321,6 +354,7 @@ interface CMSUpdateOperationContext extends CMSOperationContextBase<{
321
354
  readonly slug?: string;
322
355
  /** Optional record-field fragment; hooks receive its merged validated result. */
323
356
  readonly data?: Readonly<Record<string, CMSOperationData>>;
357
+ readonly publishAt?: string | null;
324
358
  };
325
359
  }
326
360
  /** CMS update context after execution. */
@@ -376,6 +410,8 @@ interface CMSBackendHooks {
376
410
  onBeforeUpdateContent?: (id: string, data: Readonly<Record<string, CMSOperationData>>, context: CMSUpdateOperationContext) => Promise<void> | void;
377
411
  /** Observes the fully updated record after the atomic update succeeds. */
378
412
  onAfterUpdateContent?: (item: CMSDeepReadonly<SerializedContentItemWithType>, context: CMSUpdateResultContext) => Promise<void> | void;
413
+ /** Runs after a scheduled publication commits; invalidate host caches or rebuild static output here. */
414
+ onAfterPublishContent?: (item: CMSDeepReadonly<SerializedContentItemWithType>, context: CMSUpdateResultContext) => Promise<void> | void;
379
415
  /** Runs after authorization and before the record is deleted. */
380
416
  onBeforeDeleteContent?: (id: string, context: CMSDeleteOperationContext) => Promise<void> | void;
381
417
  /** Observes the deleted record ID after the atomic delete succeeds. */
@@ -403,4 +439,4 @@ interface CMSBackendConfig {
403
439
  maxPageSize?: number;
404
440
  }
405
441
 
406
- export type { CMSBackendConfig, CMSBackendHooks, CMSContentFields, CMSContentItemResult, CMSContentTypeMap, CMSCreateOperationContext, CMSCreateResultContext, CMSDeleteOperationContext, CMSDeleteResultContext, CMSHookContext, CMSOperationData, CMSOperationErrorContext, CMSOperationLifecycleContext, CMSReadOptions, CMSReadView, CMSSelectedData, CMSUpdateOperationContext, CMSUpdateResultContext, ContentItem, ContentItemWithType, ContentRelation, ContentType, ContentTypeConfig, InverseRelation, PaginatedContentItems, RelationConfig, RelationValue, SerializedContentItem, SerializedContentItemContent, SerializedContentItemWithType, SerializedContentType };
442
+ export type { CMSBackendConfig, CMSBackendHooks, CMSContentFields, CMSContentItemResult, CMSContentTypeMap, CMSCreateOperationContext, CMSCreateResultContext, CMSDeleteOperationContext, CMSDeleteResultContext, CMSHookContext, CMSOperationData, CMSOperationErrorContext, CMSOperationLifecycleContext, CMSPublicationPolicy, CMSReadOptions, CMSReadView, CMSSelectedData, CMSUpdateOperationContext, CMSUpdateResultContext, ContentItem, ContentItemWithType, ContentRelation, ContentRevision, ContentType, ContentTypeConfig, InverseRelation, PaginatedContentItems, RelationConfig, RelationValue, SerializedContentItem, SerializedContentItemContent, SerializedContentItemWithType, SerializedContentRevision, SerializedContentType };
package/dist/types.d.mts CHANGED
@@ -1,5 +1,11 @@
1
1
  import { z } from 'zod';
2
2
 
3
+ /** Explicit publication state stored in one top-level content data field. */
4
+ interface CMSPublicationPolicy {
5
+ stateField: string;
6
+ scheduledValue: string;
7
+ publishedValue: string;
8
+ }
3
9
  /**
4
10
  * Configuration for a content type defined by the developer.
5
11
  *
@@ -21,6 +27,8 @@ interface ContentTypeConfig {
21
27
  description?: string;
22
28
  /** Zod schema defining the content type's fields. Use .meta({ fieldType: "..." }) for field type overrides. */
23
29
  schema: z.ZodObject<z.ZodRawShape>;
30
+ /** Opt in to scheduled transitions and visibility filtering for content views. */
31
+ publication?: CMSPublicationPolicy;
24
32
  }
25
33
  /**
26
34
  * Content type stored in the database
@@ -55,9 +63,30 @@ type ContentItem = {
55
63
  data: string;
56
64
  /** Optional author ID for tracking who created/modified */
57
65
  authorId?: string;
66
+ /** Optional schedule; only explicitly configured content types execute publication. */
67
+ publishAt?: Date | null;
58
68
  createdAt: Date;
59
69
  updatedAt: Date;
60
70
  };
71
+ /** Immutable snapshot appended after each successful CMS write. */
72
+ type ContentRevision = {
73
+ id: string;
74
+ contentItemId: string;
75
+ /** Unique item/version key protects against concurrent revision numbering. */
76
+ revisionKey: string;
77
+ version: number;
78
+ slug: string;
79
+ data: string;
80
+ publishAt?: Date | null;
81
+ /** Identity that performed the write; absent for trusted jobs. */
82
+ authorId?: string | null;
83
+ createdAt: Date;
84
+ };
85
+ /** Revision transported over HTTP, with dates as ISO strings. */
86
+ type SerializedContentRevision = Omit<ContentRevision, "createdAt" | "publishAt"> & {
87
+ createdAt: string;
88
+ publishAt?: string | null;
89
+ };
61
90
  /**
62
91
  * Content item with its content type joined
63
92
  */
@@ -157,9 +186,10 @@ interface SerializedContentType extends Omit<ContentType, "createdAt" | "updated
157
186
  /**
158
187
  * Serialized content item for API responses (dates as strings)
159
188
  */
160
- interface SerializedContentItem extends Omit<ContentItem, "createdAt" | "updatedAt"> {
189
+ interface SerializedContentItem extends Omit<ContentItem, "createdAt" | "updatedAt" | "publishAt"> {
161
190
  createdAt: string;
162
191
  updatedAt: string;
192
+ publishAt?: string | null;
163
193
  }
164
194
  /**
165
195
  * Serialized content item with parsed data and joined content type
@@ -276,6 +306,7 @@ interface CMSCreateOperationContext extends CMSOperationContextBase<{
276
306
  readonly body: {
277
307
  readonly slug: string;
278
308
  readonly data: Readonly<Record<string, CMSOperationData>>;
309
+ readonly publishAt?: string | null;
279
310
  };
280
311
  }, {
281
312
  contentType: string;
@@ -288,6 +319,7 @@ interface CMSCreateOperationContext extends CMSOperationContextBase<{
288
319
  readonly slug: string;
289
320
  /** Validated JSON-safe request fields, including any inline `_new` relation values. */
290
321
  readonly data: Readonly<Record<string, CMSOperationData>>;
322
+ readonly publishAt?: string | null;
291
323
  };
292
324
  }
293
325
  /** CMS create context after execution. */
@@ -302,6 +334,7 @@ interface CMSUpdateOperationContext extends CMSOperationContextBase<{
302
334
  readonly body: {
303
335
  readonly slug?: string;
304
336
  readonly data?: Readonly<Record<string, CMSOperationData>>;
337
+ readonly publishAt?: string | null;
305
338
  };
306
339
  }, {
307
340
  contentType: string;
@@ -321,6 +354,7 @@ interface CMSUpdateOperationContext extends CMSOperationContextBase<{
321
354
  readonly slug?: string;
322
355
  /** Optional record-field fragment; hooks receive its merged validated result. */
323
356
  readonly data?: Readonly<Record<string, CMSOperationData>>;
357
+ readonly publishAt?: string | null;
324
358
  };
325
359
  }
326
360
  /** CMS update context after execution. */
@@ -376,6 +410,8 @@ interface CMSBackendHooks {
376
410
  onBeforeUpdateContent?: (id: string, data: Readonly<Record<string, CMSOperationData>>, context: CMSUpdateOperationContext) => Promise<void> | void;
377
411
  /** Observes the fully updated record after the atomic update succeeds. */
378
412
  onAfterUpdateContent?: (item: CMSDeepReadonly<SerializedContentItemWithType>, context: CMSUpdateResultContext) => Promise<void> | void;
413
+ /** Runs after a scheduled publication commits; invalidate host caches or rebuild static output here. */
414
+ onAfterPublishContent?: (item: CMSDeepReadonly<SerializedContentItemWithType>, context: CMSUpdateResultContext) => Promise<void> | void;
379
415
  /** Runs after authorization and before the record is deleted. */
380
416
  onBeforeDeleteContent?: (id: string, context: CMSDeleteOperationContext) => Promise<void> | void;
381
417
  /** Observes the deleted record ID after the atomic delete succeeds. */
@@ -403,4 +439,4 @@ interface CMSBackendConfig {
403
439
  maxPageSize?: number;
404
440
  }
405
441
 
406
- export type { CMSBackendConfig, CMSBackendHooks, CMSContentFields, CMSContentItemResult, CMSContentTypeMap, CMSCreateOperationContext, CMSCreateResultContext, CMSDeleteOperationContext, CMSDeleteResultContext, CMSHookContext, CMSOperationData, CMSOperationErrorContext, CMSOperationLifecycleContext, CMSReadOptions, CMSReadView, CMSSelectedData, CMSUpdateOperationContext, CMSUpdateResultContext, ContentItem, ContentItemWithType, ContentRelation, ContentType, ContentTypeConfig, InverseRelation, PaginatedContentItems, RelationConfig, RelationValue, SerializedContentItem, SerializedContentItemContent, SerializedContentItemWithType, SerializedContentType };
442
+ export type { CMSBackendConfig, CMSBackendHooks, CMSContentFields, CMSContentItemResult, CMSContentTypeMap, CMSCreateOperationContext, CMSCreateResultContext, CMSDeleteOperationContext, CMSDeleteResultContext, CMSHookContext, CMSOperationData, CMSOperationErrorContext, CMSOperationLifecycleContext, CMSPublicationPolicy, CMSReadOptions, CMSReadView, CMSSelectedData, CMSUpdateOperationContext, CMSUpdateResultContext, ContentItem, ContentItemWithType, ContentRelation, ContentRevision, ContentType, ContentTypeConfig, InverseRelation, PaginatedContentItems, RelationConfig, RelationValue, SerializedContentItem, SerializedContentItemContent, SerializedContentItemWithType, SerializedContentRevision, SerializedContentType };
package/dist/types.d.ts CHANGED
@@ -1,5 +1,11 @@
1
1
  import { z } from 'zod';
2
2
 
3
+ /** Explicit publication state stored in one top-level content data field. */
4
+ interface CMSPublicationPolicy {
5
+ stateField: string;
6
+ scheduledValue: string;
7
+ publishedValue: string;
8
+ }
3
9
  /**
4
10
  * Configuration for a content type defined by the developer.
5
11
  *
@@ -21,6 +27,8 @@ interface ContentTypeConfig {
21
27
  description?: string;
22
28
  /** Zod schema defining the content type's fields. Use .meta({ fieldType: "..." }) for field type overrides. */
23
29
  schema: z.ZodObject<z.ZodRawShape>;
30
+ /** Opt in to scheduled transitions and visibility filtering for content views. */
31
+ publication?: CMSPublicationPolicy;
24
32
  }
25
33
  /**
26
34
  * Content type stored in the database
@@ -55,9 +63,30 @@ type ContentItem = {
55
63
  data: string;
56
64
  /** Optional author ID for tracking who created/modified */
57
65
  authorId?: string;
66
+ /** Optional schedule; only explicitly configured content types execute publication. */
67
+ publishAt?: Date | null;
58
68
  createdAt: Date;
59
69
  updatedAt: Date;
60
70
  };
71
+ /** Immutable snapshot appended after each successful CMS write. */
72
+ type ContentRevision = {
73
+ id: string;
74
+ contentItemId: string;
75
+ /** Unique item/version key protects against concurrent revision numbering. */
76
+ revisionKey: string;
77
+ version: number;
78
+ slug: string;
79
+ data: string;
80
+ publishAt?: Date | null;
81
+ /** Identity that performed the write; absent for trusted jobs. */
82
+ authorId?: string | null;
83
+ createdAt: Date;
84
+ };
85
+ /** Revision transported over HTTP, with dates as ISO strings. */
86
+ type SerializedContentRevision = Omit<ContentRevision, "createdAt" | "publishAt"> & {
87
+ createdAt: string;
88
+ publishAt?: string | null;
89
+ };
61
90
  /**
62
91
  * Content item with its content type joined
63
92
  */
@@ -157,9 +186,10 @@ interface SerializedContentType extends Omit<ContentType, "createdAt" | "updated
157
186
  /**
158
187
  * Serialized content item for API responses (dates as strings)
159
188
  */
160
- interface SerializedContentItem extends Omit<ContentItem, "createdAt" | "updatedAt"> {
189
+ interface SerializedContentItem extends Omit<ContentItem, "createdAt" | "updatedAt" | "publishAt"> {
161
190
  createdAt: string;
162
191
  updatedAt: string;
192
+ publishAt?: string | null;
163
193
  }
164
194
  /**
165
195
  * Serialized content item with parsed data and joined content type
@@ -276,6 +306,7 @@ interface CMSCreateOperationContext extends CMSOperationContextBase<{
276
306
  readonly body: {
277
307
  readonly slug: string;
278
308
  readonly data: Readonly<Record<string, CMSOperationData>>;
309
+ readonly publishAt?: string | null;
279
310
  };
280
311
  }, {
281
312
  contentType: string;
@@ -288,6 +319,7 @@ interface CMSCreateOperationContext extends CMSOperationContextBase<{
288
319
  readonly slug: string;
289
320
  /** Validated JSON-safe request fields, including any inline `_new` relation values. */
290
321
  readonly data: Readonly<Record<string, CMSOperationData>>;
322
+ readonly publishAt?: string | null;
291
323
  };
292
324
  }
293
325
  /** CMS create context after execution. */
@@ -302,6 +334,7 @@ interface CMSUpdateOperationContext extends CMSOperationContextBase<{
302
334
  readonly body: {
303
335
  readonly slug?: string;
304
336
  readonly data?: Readonly<Record<string, CMSOperationData>>;
337
+ readonly publishAt?: string | null;
305
338
  };
306
339
  }, {
307
340
  contentType: string;
@@ -321,6 +354,7 @@ interface CMSUpdateOperationContext extends CMSOperationContextBase<{
321
354
  readonly slug?: string;
322
355
  /** Optional record-field fragment; hooks receive its merged validated result. */
323
356
  readonly data?: Readonly<Record<string, CMSOperationData>>;
357
+ readonly publishAt?: string | null;
324
358
  };
325
359
  }
326
360
  /** CMS update context after execution. */
@@ -376,6 +410,8 @@ interface CMSBackendHooks {
376
410
  onBeforeUpdateContent?: (id: string, data: Readonly<Record<string, CMSOperationData>>, context: CMSUpdateOperationContext) => Promise<void> | void;
377
411
  /** Observes the fully updated record after the atomic update succeeds. */
378
412
  onAfterUpdateContent?: (item: CMSDeepReadonly<SerializedContentItemWithType>, context: CMSUpdateResultContext) => Promise<void> | void;
413
+ /** Runs after a scheduled publication commits; invalidate host caches or rebuild static output here. */
414
+ onAfterPublishContent?: (item: CMSDeepReadonly<SerializedContentItemWithType>, context: CMSUpdateResultContext) => Promise<void> | void;
379
415
  /** Runs after authorization and before the record is deleted. */
380
416
  onBeforeDeleteContent?: (id: string, context: CMSDeleteOperationContext) => Promise<void> | void;
381
417
  /** Observes the deleted record ID after the atomic delete succeeds. */
@@ -403,4 +439,4 @@ interface CMSBackendConfig {
403
439
  maxPageSize?: number;
404
440
  }
405
441
 
406
- export type { CMSBackendConfig, CMSBackendHooks, CMSContentFields, CMSContentItemResult, CMSContentTypeMap, CMSCreateOperationContext, CMSCreateResultContext, CMSDeleteOperationContext, CMSDeleteResultContext, CMSHookContext, CMSOperationData, CMSOperationErrorContext, CMSOperationLifecycleContext, CMSReadOptions, CMSReadView, CMSSelectedData, CMSUpdateOperationContext, CMSUpdateResultContext, ContentItem, ContentItemWithType, ContentRelation, ContentType, ContentTypeConfig, InverseRelation, PaginatedContentItems, RelationConfig, RelationValue, SerializedContentItem, SerializedContentItemContent, SerializedContentItemWithType, SerializedContentType };
442
+ export type { CMSBackendConfig, CMSBackendHooks, CMSContentFields, CMSContentItemResult, CMSContentTypeMap, CMSCreateOperationContext, CMSCreateResultContext, CMSDeleteOperationContext, CMSDeleteResultContext, CMSHookContext, CMSOperationData, CMSOperationErrorContext, CMSOperationLifecycleContext, CMSPublicationPolicy, CMSReadOptions, CMSReadView, CMSSelectedData, CMSUpdateOperationContext, CMSUpdateResultContext, ContentItem, ContentItemWithType, ContentRelation, ContentRevision, ContentType, ContentTypeConfig, InverseRelation, PaginatedContentItems, RelationConfig, RelationValue, SerializedContentItem, SerializedContentItemContent, SerializedContentItemWithType, SerializedContentRevision, SerializedContentType };
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ const file = require('./fields/file.cjs');
3
4
  const checkbox = require('./fields/checkbox.cjs');
4
5
  const date = require('./fields/date.cjs');
5
6
  const _enum = require('./fields/enum.cjs');
@@ -10,6 +11,7 @@ const _switch = require('./fields/switch.cjs');
10
11
  const textarea = require('./fields/textarea.cjs');
11
12
 
12
13
  const INPUT_COMPONENTS = {
14
+ file: file.default,
13
15
  checkbox: checkbox,
14
16
  date: date,
15
17
  select: _enum,
@@ -1,3 +1,4 @@
1
+ import AutoFormFile from './fields/file.mjs';
1
2
  import AutoFormCheckbox from './fields/checkbox.mjs';
2
3
  import AutoFormDate from './fields/date.mjs';
3
4
  import AutoFormEnum from './fields/enum.mjs';
@@ -8,6 +9,7 @@ import AutoFormSwitch from './fields/switch.mjs';
8
9
  import AutoFormTextarea from './fields/textarea.mjs';
9
10
 
10
11
  const INPUT_COMPONENTS = {
12
+ file: AutoFormFile,
11
13
  checkbox: AutoFormCheckbox,
12
14
  date: AutoFormDate,
13
15
  select: AutoFormEnum,
@@ -0,0 +1,68 @@
1
+ 'use client';
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ const jsxRuntime = require('react/jsx-runtime');
7
+ const React = require('react');
8
+ const reactHookForm = require('react-hook-form');
9
+ const form = require('../../form.cjs');
10
+ const input = require('../../input.cjs');
11
+ const label = require('../common/label.cjs');
12
+ const tooltip = require('../common/tooltip.cjs');
13
+
14
+ const FileUploadStatusContext = React.createContext(() => {
15
+ });
16
+ function AutoFormFile({ field, fieldProps, fieldConfigItem, label: label$1, isRequired }) {
17
+ const [uploading, setUploading] = React.useState(false);
18
+ const [error, setError] = React.useState(null);
19
+ const form$1 = reactHookForm.useFormContext();
20
+ const reportStatus = React.useContext(FileUploadStatusContext);
21
+ React.useEffect(() => () => reportStatus(field.name, null), [field.name, reportStatus]);
22
+ const onUpload = fieldConfigItem.onUpload;
23
+ return /* @__PURE__ */ jsxRuntime.jsxs(form.FormItem, { children: [
24
+ /* @__PURE__ */ jsxRuntime.jsx(label, { label: fieldConfigItem.label || label$1, isRequired }),
25
+ /* @__PURE__ */ jsxRuntime.jsx(form.FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(
26
+ input.Input,
27
+ {
28
+ type: "file",
29
+ name: field.name,
30
+ onBlur: field.onBlur,
31
+ accept: fieldProps.accept,
32
+ disabled: fieldProps.disabled || uploading || !onUpload,
33
+ required: isRequired && !field.value,
34
+ onChange: async (event) => {
35
+ const input = event.currentTarget;
36
+ const file = input.files?.[0];
37
+ if (!file || !onUpload) return;
38
+ setUploading(true);
39
+ reportStatus(field.name, "uploading");
40
+ setError(null);
41
+ form$1.setError(field.name, { type: "upload", message: "Upload in progress" });
42
+ try {
43
+ const url = await onUpload(file);
44
+ if (typeof url !== "string" || !url.trim()) throw new Error("Upload must return a URL string");
45
+ field.onChange(url);
46
+ form$1.clearErrors(field.name);
47
+ reportStatus(field.name, null);
48
+ } catch (error2) {
49
+ const message = error2 instanceof Error ? error2.message : "Upload failed";
50
+ setError(message);
51
+ reportStatus(field.name, "failed");
52
+ form$1.setError(field.name, { type: "upload", message });
53
+ } finally {
54
+ setUploading(false);
55
+ input.value = "";
56
+ }
57
+ }
58
+ }
59
+ ) }),
60
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", role: "status", children: uploading ? "Uploading\u2026" : !onUpload ? "File uploads are not configured." : field.value ? "File uploaded" : "" }),
61
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", className: "text-sm text-destructive", children: error }),
62
+ /* @__PURE__ */ jsxRuntime.jsx(tooltip, { fieldConfigItem }),
63
+ /* @__PURE__ */ jsxRuntime.jsx(form.FormMessage, {})
64
+ ] });
65
+ }
66
+
67
+ exports.FileUploadStatusContext = FileUploadStatusContext;
68
+ exports.default = AutoFormFile;
@@ -0,0 +1,63 @@
1
+ 'use client';
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import { useState, useContext, useEffect, createContext } from 'react';
4
+ import { useFormContext } from 'react-hook-form';
5
+ import { FormItem, FormControl, FormMessage } from '../../form.mjs';
6
+ import { Input } from '../../input.mjs';
7
+ import AutoFormLabel from '../common/label.mjs';
8
+ import AutoFormTooltip from '../common/tooltip.mjs';
9
+
10
+ const FileUploadStatusContext = createContext(() => {
11
+ });
12
+ function AutoFormFile({ field, fieldProps, fieldConfigItem, label, isRequired }) {
13
+ const [uploading, setUploading] = useState(false);
14
+ const [error, setError] = useState(null);
15
+ const form = useFormContext();
16
+ const reportStatus = useContext(FileUploadStatusContext);
17
+ useEffect(() => () => reportStatus(field.name, null), [field.name, reportStatus]);
18
+ const onUpload = fieldConfigItem.onUpload;
19
+ return /* @__PURE__ */ jsxs(FormItem, { children: [
20
+ /* @__PURE__ */ jsx(AutoFormLabel, { label: fieldConfigItem.label || label, isRequired }),
21
+ /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(
22
+ Input,
23
+ {
24
+ type: "file",
25
+ name: field.name,
26
+ onBlur: field.onBlur,
27
+ accept: fieldProps.accept,
28
+ disabled: fieldProps.disabled || uploading || !onUpload,
29
+ required: isRequired && !field.value,
30
+ onChange: async (event) => {
31
+ const input = event.currentTarget;
32
+ const file = input.files?.[0];
33
+ if (!file || !onUpload) return;
34
+ setUploading(true);
35
+ reportStatus(field.name, "uploading");
36
+ setError(null);
37
+ form.setError(field.name, { type: "upload", message: "Upload in progress" });
38
+ try {
39
+ const url = await onUpload(file);
40
+ if (typeof url !== "string" || !url.trim()) throw new Error("Upload must return a URL string");
41
+ field.onChange(url);
42
+ form.clearErrors(field.name);
43
+ reportStatus(field.name, null);
44
+ } catch (error2) {
45
+ const message = error2 instanceof Error ? error2.message : "Upload failed";
46
+ setError(message);
47
+ reportStatus(field.name, "failed");
48
+ form.setError(field.name, { type: "upload", message });
49
+ } finally {
50
+ setUploading(false);
51
+ input.value = "";
52
+ }
53
+ }
54
+ }
55
+ ) }),
56
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", role: "status", children: uploading ? "Uploading\u2026" : !onUpload ? "File uploads are not configured." : field.value ? "File uploaded" : "" }),
57
+ error && /* @__PURE__ */ jsx("p", { role: "alert", className: "text-sm text-destructive", children: error }),
58
+ /* @__PURE__ */ jsx(AutoFormTooltip, { fieldConfigItem }),
59
+ /* @__PURE__ */ jsx(FormMessage, {})
60
+ ] });
61
+ }
62
+
63
+ export { FileUploadStatusContext, AutoFormFile as default };
@@ -1,6 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  const jsxRuntime = require('react/jsx-runtime');
4
+ const schemaConverter = require('../../../lib/schema-converter.cjs');
5
+ const formVisibility = require('../../../lib/form-visibility.cjs');
4
6
  const accordion = require('../../accordion.cjs');
5
7
  const form = require('../../form.cjs');
6
8
  const reactHookForm = require('react-hook-form');
@@ -32,7 +34,8 @@ function AutoFormObject({
32
34
  form: form$1,
33
35
  fieldConfig,
34
36
  path = [],
35
- dependencies: dependencies$1 = []
37
+ dependencies: dependencies$1 = [],
38
+ visibilityValues
36
39
  }) {
37
40
  const { watch } = reactHookForm.useFormContext();
38
41
  if (!schema) {
@@ -56,6 +59,9 @@ function AutoFormObject({
56
59
  return item;
57
60
  };
58
61
  const sortedFieldKeys = helpers.sortFieldsByOrder(fieldConfig, Object.keys(shape));
62
+ const siblingValues = visibilityValues ?? schemaConverter.resolveVisibleSchema({
63
+ properties: Object.fromEntries(Object.keys(shape).map((name) => [name, { showIf: fieldConfig?.[name]?.showIf }]))
64
+ }, path.length ? watch(path.join(".")) ?? {} : watch()).data;
59
65
  return /* @__PURE__ */ jsxRuntime.jsx(accordion.Accordion, { type: "multiple", className: "space-y-5 border-none", children: sortedFieldKeys.map((name) => {
60
66
  let item = shape[name];
61
67
  item = handleIfZodNumber(item);
@@ -68,7 +74,7 @@ function AutoFormObject({
68
74
  isRequired: isRequiredByDependency,
69
75
  overrideOptions
70
76
  } = dependencies(dependencies$1, name, watch);
71
- if (isHidden) {
77
+ if (isHidden || !formVisibility.matchesShowIf(fieldConfig?.[name]?.showIf, siblingValues)) {
72
78
  return null;
73
79
  }
74
80
  if (zodBaseType === "ZodObject") {
@@ -202,6 +208,7 @@ function AutoFormObject({
202
208
  const fieldProps = {
203
209
  ...helpers.zodToHtmlInputProps(item),
204
210
  ...field,
211
+ onChange: zodBaseType === "ZodNumber" && inputType === "number" ? (event) => field.onChange(event.target.value === "" ? void 0 : Number(event.target.value)) : field.onChange,
205
212
  ...safeInputProps,
206
213
  disabled: safeInputProps.disabled || isDisabled,
207
214
  ref: void 0,
@@ -1,4 +1,6 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { resolveVisibleSchema } from '../../../lib/schema-converter.mjs';
3
+ import { matchesShowIf } from '../../../lib/form-visibility.mjs';
2
4
  import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from '../../accordion.mjs';
3
5
  import { FormField } from '../../form.mjs';
4
6
  import { useFormContext } from 'react-hook-form';
@@ -16,7 +18,8 @@ function AutoFormObject({
16
18
  form,
17
19
  fieldConfig,
18
20
  path = [],
19
- dependencies = []
21
+ dependencies = [],
22
+ visibilityValues
20
23
  }) {
21
24
  const { watch } = useFormContext();
22
25
  if (!schema) {
@@ -40,6 +43,9 @@ function AutoFormObject({
40
43
  return item;
41
44
  };
42
45
  const sortedFieldKeys = sortFieldsByOrder(fieldConfig, Object.keys(shape));
46
+ const siblingValues = visibilityValues ?? resolveVisibleSchema({
47
+ properties: Object.fromEntries(Object.keys(shape).map((name) => [name, { showIf: fieldConfig?.[name]?.showIf }]))
48
+ }, path.length ? watch(path.join(".")) ?? {} : watch()).data;
43
49
  return /* @__PURE__ */ jsx(Accordion, { type: "multiple", className: "space-y-5 border-none", children: sortedFieldKeys.map((name) => {
44
50
  let item = shape[name];
45
51
  item = handleIfZodNumber(item);
@@ -52,7 +58,7 @@ function AutoFormObject({
52
58
  isRequired: isRequiredByDependency,
53
59
  overrideOptions
54
60
  } = resolveDependencies(dependencies, name, watch);
55
- if (isHidden) {
61
+ if (isHidden || !matchesShowIf(fieldConfig?.[name]?.showIf, siblingValues)) {
56
62
  return null;
57
63
  }
58
64
  if (zodBaseType === "ZodObject") {
@@ -186,6 +192,7 @@ function AutoFormObject({
186
192
  const fieldProps = {
187
193
  ...zodToHtmlInputProps(item),
188
194
  ...field,
195
+ onChange: zodBaseType === "ZodNumber" && inputType === "number" ? (event) => field.onChange(event.target.value === "" ? void 0 : Number(event.target.value)) : field.onChange,
189
196
  ...safeInputProps,
190
197
  disabled: safeInputProps.disabled || isDisabled,
191
198
  ref: void 0,
@@ -1,9 +1,11 @@
1
1
  'use strict';
2
2
 
3
3
  const jsxRuntime = require('react/jsx-runtime');
4
+ const schemaConverter = require('../../lib/schema-converter.cjs');
4
5
  require('zod');
5
6
 
6
7
  const BUILTIN_FIELD_TYPES = [
8
+ "file",
7
9
  "checkbox",
8
10
  "date",
9
11
  "select",
@@ -24,6 +26,8 @@ function beautifyObjectName(string) {
24
26
  }
25
27
  function getBaseSchema(schema) {
26
28
  if (!schema) return null;
29
+ const display = schemaConverter.getFormDisplaySchema(schema);
30
+ if (display) return display;
27
31
  const def = schema._zod?.def;
28
32
  if (!def) return schema;
29
33
  if (def.innerType) {
@@ -107,6 +111,8 @@ function getDefaultValues(schema, fieldConfig) {
107
111
  }
108
112
  function getObjectFormSchema(schema) {
109
113
  if (!schema) return schema;
114
+ const displaySchema = schemaConverter.getFormDisplaySchema(schema);
115
+ if (displaySchema) return displaySchema;
110
116
  const def = schema._zod?.def;
111
117
  if (!def) return schema;
112
118
  if (def.type === "pipe") {
@@ -176,6 +182,7 @@ function buildFieldConfigFromJsonSchema(jsonSchema, fieldComponents) {
176
182
  if (!properties) return fieldConfig;
177
183
  for (const [key, value] of Object.entries(properties)) {
178
184
  const config = {};
185
+ if (value.showIf) config.showIf = value.showIf;
179
186
  if (value.label) {
180
187
  config.label = value.label;
181
188
  } else if (value.title) {
@@ -218,6 +225,8 @@ function buildFieldConfigFromJsonSchema(jsonSchema, fieldComponents) {
218
225
  "inputProps",
219
226
  "fieldType",
220
227
  "renderParent",
228
+ "showIf",
229
+ "onUpload",
221
230
  "order"
222
231
  ]);
223
232
  if (value.properties) {
@@ -1,7 +1,9 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
+ import { getFormDisplaySchema } from '../../lib/schema-converter.mjs';
2
3
  import 'zod';
3
4
 
4
5
  const BUILTIN_FIELD_TYPES = [
6
+ "file",
5
7
  "checkbox",
6
8
  "date",
7
9
  "select",
@@ -22,6 +24,8 @@ function beautifyObjectName(string) {
22
24
  }
23
25
  function getBaseSchema(schema) {
24
26
  if (!schema) return null;
27
+ const display = getFormDisplaySchema(schema);
28
+ if (display) return display;
25
29
  const def = schema._zod?.def;
26
30
  if (!def) return schema;
27
31
  if (def.innerType) {
@@ -105,6 +109,8 @@ function getDefaultValues(schema, fieldConfig) {
105
109
  }
106
110
  function getObjectFormSchema(schema) {
107
111
  if (!schema) return schema;
112
+ const displaySchema = getFormDisplaySchema(schema);
113
+ if (displaySchema) return displaySchema;
108
114
  const def = schema._zod?.def;
109
115
  if (!def) return schema;
110
116
  if (def.type === "pipe") {
@@ -174,6 +180,7 @@ function buildFieldConfigFromJsonSchema(jsonSchema, fieldComponents) {
174
180
  if (!properties) return fieldConfig;
175
181
  for (const [key, value] of Object.entries(properties)) {
176
182
  const config = {};
183
+ if (value.showIf) config.showIf = value.showIf;
177
184
  if (value.label) {
178
185
  config.label = value.label;
179
186
  } else if (value.title) {
@@ -216,6 +223,8 @@ function buildFieldConfigFromJsonSchema(jsonSchema, fieldComponents) {
216
223
  "inputProps",
217
224
  "fieldType",
218
225
  "renderParent",
226
+ "showIf",
227
+ "onUpload",
219
228
  "order"
220
229
  ]);
221
230
  if (value.properties) {