@box/metadata-template-editor 1.19.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 (215) hide show
  1. package/LICENSE +379 -0
  2. package/README.md +57 -0
  3. package/dist/chunks/metadata-field-configurator.module.js +17 -0
  4. package/dist/chunks/types.js +34 -0
  5. package/dist/esm/index.js +34 -0
  6. package/dist/esm/lib/components/field-selector/field-selector.js +39 -0
  7. package/dist/esm/lib/components/field-selector/index.js +4 -0
  8. package/dist/esm/lib/components/field-selector/messages.js +14 -0
  9. package/dist/esm/lib/components/field-type-dropdown/field-type-dropdown.js +47 -0
  10. package/dist/esm/lib/components/field-type-dropdown/index.js +4 -0
  11. package/dist/esm/lib/components/field-type-dropdown/messages.js +14 -0
  12. package/dist/esm/lib/components/field-type-tiles/field-type-tiles.js +40 -0
  13. package/dist/esm/lib/components/field-type-tiles/index.js +4 -0
  14. package/dist/esm/lib/components/field-type-tiles/messages.js +14 -0
  15. package/dist/esm/lib/components/metadata-field-configurator/components/confirmation-modal/confirmation-modal.js +46 -0
  16. package/dist/esm/lib/components/metadata-field-configurator/components/confirmation-modal/messages.js +18 -0
  17. package/dist/esm/lib/components/metadata-field-configurator/components/field-action-slot/field-action-slot.js +80 -0
  18. package/dist/esm/lib/components/metadata-field-configurator/components/field-context-menu/field-context-menu.js +115 -0
  19. package/dist/esm/lib/components/metadata-field-configurator/components/field-edit-content/field-edit-content.js +101 -0
  20. package/dist/esm/lib/components/metadata-field-configurator/components/levels-chain/chip.js +33 -0
  21. package/dist/esm/lib/components/metadata-field-configurator/components/levels-chain/index.js +4 -0
  22. package/dist/esm/lib/components/metadata-field-configurator/components/levels-chain/levels-chain.js +118 -0
  23. package/dist/esm/lib/components/metadata-field-configurator/components/levels-chain/utils.js +34 -0
  24. package/dist/esm/lib/components/metadata-field-configurator/components/type-specific-configuration/dropdown/__mocks__/getInitialValues.js +33 -0
  25. package/dist/esm/lib/components/metadata-field-configurator/components/type-specific-configuration/dropdown/dropdown-default-values.js +15 -0
  26. package/dist/esm/lib/components/metadata-field-configurator/components/type-specific-configuration/dropdown/dropdown-field-configuration.js +66 -0
  27. package/dist/esm/lib/components/metadata-field-configurator/components/type-specific-configuration/dropdown/sortable-option-list.js +294 -0
  28. package/dist/esm/lib/components/metadata-field-configurator/components/type-specific-configuration/index.js +6 -0
  29. package/dist/esm/lib/components/metadata-field-configurator/components/type-specific-configuration/taxonomy/taxonomy-default-values.js +15 -0
  30. package/dist/esm/lib/components/metadata-field-configurator/components/type-specific-configuration/taxonomy/taxonomy-field-configuration.js +149 -0
  31. package/dist/esm/lib/components/metadata-field-configurator/components/type-specific-configuration/taxonomy/taxonomy-field-configurator-initial-state.js +54 -0
  32. package/dist/esm/lib/components/metadata-field-configurator/components/type-specific-configuration/taxonomy/taxonomy-selector-messages.js +38 -0
  33. package/dist/esm/lib/components/metadata-field-configurator/components/type-specific-configuration/taxonomy/taxonomy-selector.js +103 -0
  34. package/dist/esm/lib/components/metadata-field-configurator/components/type-specific-configuration/taxonomy/useTaxonomySelect.js +19 -0
  35. package/dist/esm/lib/components/metadata-field-configurator/components/type-specific-configuration/taxonomy/utils.js +4 -0
  36. package/dist/esm/lib/components/metadata-field-configurator/context/field-configurator-context.js +68 -0
  37. package/dist/esm/lib/components/metadata-field-configurator/context/field-extensions-context.js +9 -0
  38. package/dist/esm/lib/components/metadata-field-configurator/context/taxonomy-options-context.js +23 -0
  39. package/dist/esm/lib/components/metadata-field-configurator/hooks/useFieldConfiguratorBehavior.js +119 -0
  40. package/dist/esm/lib/components/metadata-field-configurator/hooks/useFieldValidation.js +68 -0
  41. package/dist/esm/lib/components/metadata-field-configurator/hooks/useTaxonomyFetch.js +27 -0
  42. package/dist/esm/lib/components/metadata-field-configurator/hooks/useTemplateFieldSchema.js +44 -0
  43. package/dist/esm/lib/components/metadata-field-configurator/index.js +11 -0
  44. package/dist/esm/lib/components/metadata-field-configurator/messages/configurator-messages.js +136 -0
  45. package/dist/esm/lib/components/metadata-field-configurator/messages/dropdown-messages.js +38 -0
  46. package/dist/esm/lib/components/metadata-field-configurator/messages/levels-chain-messages.js +18 -0
  47. package/dist/esm/lib/components/metadata-field-configurator/messages/taxonomy-messages.js +38 -0
  48. package/dist/esm/lib/components/metadata-field-configurator/metadata-field-configurator.js +154 -0
  49. package/dist/esm/lib/components/metadata-field-configurator/utils.js +53 -0
  50. package/dist/esm/lib/components/metadata-field-list/index.js +5 -0
  51. package/dist/esm/lib/components/metadata-field-list/metadata-field-list.js +279 -0
  52. package/dist/esm/lib/components/metadata-template-editor-form/metadata-template-editor-form.js +137 -0
  53. package/dist/esm/lib/components/metadata-template-editor-modal/index.js +4 -0
  54. package/dist/esm/lib/components/metadata-template-editor-modal/metadata-template-editor-modal.js +103 -0
  55. package/dist/esm/lib/hooks/useMetadataTemplateFormSchema.js +16 -0
  56. package/dist/esm/lib/hooks/useTemplateNameSchema.js +12 -0
  57. package/dist/esm/lib/index.js +14 -0
  58. package/dist/esm/lib/messages.js +118 -0
  59. package/dist/esm/lib/metadata-template-editor.js +179 -0
  60. package/dist/esm/lib/utils/constants.js +8 -0
  61. package/dist/esm/lib/utils/field-options/field-type-icon.js +34 -0
  62. package/dist/esm/lib/utils/field-options/index.js +9 -0
  63. package/dist/esm/lib/utils/field-options/messages.js +48 -0
  64. package/dist/esm/lib/utils/field-options/useFieldOptions.js +19 -0
  65. package/dist/esm/lib/utils/key-generation.js +29 -0
  66. package/dist/esm/lib/utils/template-type-conversion/convertLocalConfiguratorToTemplateField.js +78 -0
  67. package/dist/esm/lib/utils/template-type-conversion/convertTemplateFieldToLocalConfigurator.js +90 -0
  68. package/dist/esm/lib/utils/template-type-conversion/generateJSONPatchTemplateOperations.js +179 -0
  69. package/dist/esm/lib/utils/template-type-conversion/mapFieldsWithUniqueKeys.js +14 -0
  70. package/dist/i18n/bn-IN.js +108 -0
  71. package/dist/i18n/bn-IN.properties +196 -0
  72. package/dist/i18n/da-DK.js +108 -0
  73. package/dist/i18n/da-DK.properties +196 -0
  74. package/dist/i18n/de-DE.js +108 -0
  75. package/dist/i18n/de-DE.properties +196 -0
  76. package/dist/i18n/en-AU.js +108 -0
  77. package/dist/i18n/en-AU.properties +196 -0
  78. package/dist/i18n/en-CA.js +108 -0
  79. package/dist/i18n/en-CA.properties +196 -0
  80. package/dist/i18n/en-GB.js +108 -0
  81. package/dist/i18n/en-GB.properties +196 -0
  82. package/dist/i18n/en-US.js +108 -0
  83. package/dist/i18n/en-US.properties +212 -0
  84. package/dist/i18n/en-x-pseudo.js +108 -0
  85. package/dist/i18n/en-x-pseudo.properties +196 -0
  86. package/dist/i18n/es-419.js +108 -0
  87. package/dist/i18n/es-419.properties +196 -0
  88. package/dist/i18n/es-ES.js +108 -0
  89. package/dist/i18n/es-ES.properties +196 -0
  90. package/dist/i18n/fi-FI.js +108 -0
  91. package/dist/i18n/fi-FI.properties +196 -0
  92. package/dist/i18n/fr-CA.js +108 -0
  93. package/dist/i18n/fr-CA.properties +196 -0
  94. package/dist/i18n/fr-FR.js +108 -0
  95. package/dist/i18n/fr-FR.properties +196 -0
  96. package/dist/i18n/hi-IN.js +108 -0
  97. package/dist/i18n/hi-IN.properties +196 -0
  98. package/dist/i18n/it-IT.js +108 -0
  99. package/dist/i18n/it-IT.properties +196 -0
  100. package/dist/i18n/ja-JP.js +108 -0
  101. package/dist/i18n/ja-JP.properties +196 -0
  102. package/dist/i18n/json/src/lib/components/field-selector/messages.json +1 -0
  103. package/dist/i18n/json/src/lib/components/field-type-dropdown/messages.json +1 -0
  104. package/dist/i18n/json/src/lib/components/field-type-tiles/messages.json +1 -0
  105. package/dist/i18n/json/src/lib/components/metadata-field-configurator/components/confirmation-modal/messages.json +1 -0
  106. package/dist/i18n/json/src/lib/components/metadata-field-configurator/components/type-specific-configuration/taxonomy/taxonomy-selector-messages.json +1 -0
  107. package/dist/i18n/json/src/lib/components/metadata-field-configurator/messages/configurator-messages.json +1 -0
  108. package/dist/i18n/json/src/lib/components/metadata-field-configurator/messages/dropdown-messages.json +1 -0
  109. package/dist/i18n/json/src/lib/components/metadata-field-configurator/messages/levels-chain-messages.json +1 -0
  110. package/dist/i18n/json/src/lib/components/metadata-field-configurator/messages/taxonomy-messages.json +1 -0
  111. package/dist/i18n/json/src/lib/messages.json +1 -0
  112. package/dist/i18n/json/src/lib/utils/field-options/messages.json +1 -0
  113. package/dist/i18n/ko-KR.js +108 -0
  114. package/dist/i18n/ko-KR.properties +196 -0
  115. package/dist/i18n/nb-NO.js +108 -0
  116. package/dist/i18n/nb-NO.properties +196 -0
  117. package/dist/i18n/nl-NL.js +108 -0
  118. package/dist/i18n/nl-NL.properties +196 -0
  119. package/dist/i18n/pl-PL.js +108 -0
  120. package/dist/i18n/pl-PL.properties +196 -0
  121. package/dist/i18n/pt-BR.js +108 -0
  122. package/dist/i18n/pt-BR.properties +196 -0
  123. package/dist/i18n/ru-RU.js +108 -0
  124. package/dist/i18n/ru-RU.properties +196 -0
  125. package/dist/i18n/sv-SE.js +108 -0
  126. package/dist/i18n/sv-SE.properties +196 -0
  127. package/dist/i18n/tr-TR.js +108 -0
  128. package/dist/i18n/tr-TR.properties +196 -0
  129. package/dist/i18n/zh-CN.js +108 -0
  130. package/dist/i18n/zh-CN.properties +196 -0
  131. package/dist/i18n/zh-TW.js +108 -0
  132. package/dist/i18n/zh-TW.properties +196 -0
  133. package/dist/styles/chip.css +1 -0
  134. package/dist/styles/dropdown-field-configuration.css +1 -0
  135. package/dist/styles/field-context-menu.css +1 -0
  136. package/dist/styles/field-selector.css +1 -0
  137. package/dist/styles/field-type-dropdown.css +1 -0
  138. package/dist/styles/levels-chain.css +1 -0
  139. package/dist/styles/metadata-field-configurator.css +1 -0
  140. package/dist/styles/metadata-field-list.css +1 -0
  141. package/dist/styles/metadata-template-editor-form.css +1 -0
  142. package/dist/styles/metadata-template-editor-modal.css +1 -0
  143. package/dist/styles/metadata-template-editor.css +1 -0
  144. package/dist/styles/sortable-option-list.css +1 -0
  145. package/dist/styles/taxonomy-field-configuration.css +1 -0
  146. package/dist/styles/taxonomy-field-configurator-initial-state.css +1 -0
  147. package/dist/styles/taxonomy-selector.css +1 -0
  148. package/dist/types/index.d.ts +8 -0
  149. package/dist/types/lib/components/field-selector/field-selector.d.ts +16 -0
  150. package/dist/types/lib/components/field-selector/index.d.ts +1 -0
  151. package/dist/types/lib/components/field-selector/messages.d.ts +13 -0
  152. package/dist/types/lib/components/field-type-dropdown/field-type-dropdown.d.ts +15 -0
  153. package/dist/types/lib/components/field-type-dropdown/index.d.ts +2 -0
  154. package/dist/types/lib/components/field-type-dropdown/messages.d.ts +12 -0
  155. package/dist/types/lib/components/field-type-tiles/field-type-tiles.d.ts +12 -0
  156. package/dist/types/lib/components/field-type-tiles/index.d.ts +2 -0
  157. package/dist/types/lib/components/field-type-tiles/messages.d.ts +12 -0
  158. package/dist/types/lib/components/metadata-field-configurator/components/confirmation-modal/confirmation-modal.d.ts +31 -0
  159. package/dist/types/lib/components/metadata-field-configurator/components/confirmation-modal/messages.d.ts +18 -0
  160. package/dist/types/lib/components/metadata-field-configurator/components/field-action-slot/field-action-slot.d.ts +30 -0
  161. package/dist/types/lib/components/metadata-field-configurator/components/field-context-menu/field-context-menu.d.ts +23 -0
  162. package/dist/types/lib/components/metadata-field-configurator/components/field-edit-content/field-edit-content.d.ts +20 -0
  163. package/dist/types/lib/components/metadata-field-configurator/components/levels-chain/chip.d.ts +17 -0
  164. package/dist/types/lib/components/metadata-field-configurator/components/levels-chain/index.d.ts +1 -0
  165. package/dist/types/lib/components/metadata-field-configurator/components/levels-chain/levels-chain.d.ts +31 -0
  166. package/dist/types/lib/components/metadata-field-configurator/components/levels-chain/utils.d.ts +10 -0
  167. package/dist/types/lib/components/metadata-field-configurator/components/type-specific-configuration/dropdown/__mocks__/getInitialValues.d.ts +2 -0
  168. package/dist/types/lib/components/metadata-field-configurator/components/type-specific-configuration/dropdown/dropdown-default-values.d.ts +2 -0
  169. package/dist/types/lib/components/metadata-field-configurator/components/type-specific-configuration/dropdown/dropdown-field-configuration.d.ts +1 -0
  170. package/dist/types/lib/components/metadata-field-configurator/components/type-specific-configuration/dropdown/sortable-option-list.d.ts +6 -0
  171. package/dist/types/lib/components/metadata-field-configurator/components/type-specific-configuration/index.d.ts +2 -0
  172. package/dist/types/lib/components/metadata-field-configurator/components/type-specific-configuration/taxonomy/taxonomy-default-values.d.ts +2 -0
  173. package/dist/types/lib/components/metadata-field-configurator/components/type-specific-configuration/taxonomy/taxonomy-field-configuration.d.ts +1 -0
  174. package/dist/types/lib/components/metadata-field-configurator/components/type-specific-configuration/taxonomy/taxonomy-field-configurator-initial-state.d.ts +1 -0
  175. package/dist/types/lib/components/metadata-field-configurator/components/type-specific-configuration/taxonomy/taxonomy-selector-messages.d.ts +43 -0
  176. package/dist/types/lib/components/metadata-field-configurator/components/type-specific-configuration/taxonomy/taxonomy-selector.d.ts +12 -0
  177. package/dist/types/lib/components/metadata-field-configurator/components/type-specific-configuration/taxonomy/useTaxonomySelect.d.ts +5 -0
  178. package/dist/types/lib/components/metadata-field-configurator/components/type-specific-configuration/taxonomy/utils.d.ts +2 -0
  179. package/dist/types/lib/components/metadata-field-configurator/context/field-configurator-context.d.ts +57 -0
  180. package/dist/types/lib/components/metadata-field-configurator/context/field-extensions-context.d.ts +52 -0
  181. package/dist/types/lib/components/metadata-field-configurator/context/taxonomy-options-context.d.ts +21 -0
  182. package/dist/types/lib/components/metadata-field-configurator/hooks/useFieldConfiguratorBehavior.d.ts +57 -0
  183. package/dist/types/lib/components/metadata-field-configurator/hooks/useFieldValidation.d.ts +27 -0
  184. package/dist/types/lib/components/metadata-field-configurator/hooks/useTaxonomyFetch.d.ts +19 -0
  185. package/dist/types/lib/components/metadata-field-configurator/hooks/useTemplateFieldSchema.d.ts +15 -0
  186. package/dist/types/lib/components/metadata-field-configurator/index.d.ts +6 -0
  187. package/dist/types/lib/components/metadata-field-configurator/messages/configurator-messages.d.ts +164 -0
  188. package/dist/types/lib/components/metadata-field-configurator/messages/dropdown-messages.d.ts +43 -0
  189. package/dist/types/lib/components/metadata-field-configurator/messages/levels-chain-messages.d.ts +18 -0
  190. package/dist/types/lib/components/metadata-field-configurator/messages/taxonomy-messages.d.ts +43 -0
  191. package/dist/types/lib/components/metadata-field-configurator/metadata-field-configurator.d.ts +191 -0
  192. package/dist/types/lib/components/metadata-field-configurator/stories/story-fixtures.d.ts +5 -0
  193. package/dist/types/lib/components/metadata-field-configurator/utils.d.ts +24 -0
  194. package/dist/types/lib/components/metadata-field-list/index.d.ts +2 -0
  195. package/dist/types/lib/components/metadata-field-list/metadata-field-list.d.ts +109 -0
  196. package/dist/types/lib/components/metadata-template-editor-form/metadata-template-editor-form.d.ts +20 -0
  197. package/dist/types/lib/components/metadata-template-editor-modal/index.d.ts +1 -0
  198. package/dist/types/lib/components/metadata-template-editor-modal/metadata-template-editor-modal.d.ts +56 -0
  199. package/dist/types/lib/hooks/useMetadataTemplateFormSchema.d.ts +17 -0
  200. package/dist/types/lib/hooks/useTemplateNameSchema.d.ts +2 -0
  201. package/dist/types/lib/index.d.ts +7 -0
  202. package/dist/types/lib/messages.d.ts +143 -0
  203. package/dist/types/lib/metadata-template-editor.d.ts +290 -0
  204. package/dist/types/lib/types.d.ts +311 -0
  205. package/dist/types/lib/utils/constants.d.ts +9 -0
  206. package/dist/types/lib/utils/field-options/field-type-icon.d.ts +6 -0
  207. package/dist/types/lib/utils/field-options/index.d.ts +4 -0
  208. package/dist/types/lib/utils/field-options/messages.d.ts +60 -0
  209. package/dist/types/lib/utils/field-options/useFieldOptions.d.ts +34 -0
  210. package/dist/types/lib/utils/key-generation.d.ts +24 -0
  211. package/dist/types/lib/utils/template-type-conversion/convertLocalConfiguratorToTemplateField.d.ts +25 -0
  212. package/dist/types/lib/utils/template-type-conversion/convertTemplateFieldToLocalConfigurator.d.ts +8 -0
  213. package/dist/types/lib/utils/template-type-conversion/generateJSONPatchTemplateOperations.d.ts +16 -0
  214. package/dist/types/lib/utils/template-type-conversion/mapFieldsWithUniqueKeys.d.ts +8 -0
  215. package/package.json +61 -0
@@ -0,0 +1,290 @@
1
+ import { MetadataTemplateCreateBody, MetadataTemplateEditorMode, MetadataTemplatePatchItem, MetadataTemplateApiResponse } from './types';
2
+ import { MetadataFieldListProps } from './components/metadata-field-list';
3
+ import { FieldConfiguratorExtension } from './components/metadata-field-configurator/context/field-extensions-context';
4
+ type MetadataTemplateEditorCommonProps = {
5
+ /** Called when the user dismisses the form without saving. */
6
+ onCancel?: () => void;
7
+ /**
8
+ * Fired whenever the form's dirty state changes.
9
+ * Useful for parent components (e.g. a modal footer) that need to reflect
10
+ * whether the user has made any unsaved changes.
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
15
+ *
16
+ * <MetadataTemplateEditor
17
+ * onDirtyStateChange={setHasUnsavedChanges}
18
+ * // ...
19
+ * />
20
+ * {hasUnsavedChanges && <Banner>You have unsaved changes.</Banner>}
21
+ * ```
22
+ */
23
+ onDirtyStateChange?: (isDirty: boolean) => void;
24
+ /**
25
+ * Called when the API save fails — i.e. when `onCreateTemplate` or `onEditTemplate`
26
+ * throws.
27
+ *
28
+ * The editor catches that error to show its own error notification and then
29
+ * re-throws into Formik (which only uses it to clear `isSubmitting`). Because
30
+ * Formik swallows the re-throw, there is no way to observe the error outside
31
+ * the editor _unless_ this callback is provided.
32
+ *
33
+ * Use it to update external state, log to analytics, or trigger UI outside
34
+ * the editor without having to wrap your own callback with try-catch.
35
+ *
36
+ * @example
37
+ * ```tsx
38
+ * <MetadataTemplateEditor
39
+ * onCreateTemplate={async body => { await api.createTemplate(body); }}
40
+ * onSubmitError={err => analytics.track('template_save_failed', { err })}
41
+ * />
42
+ * ```
43
+ */
44
+ onSubmitError?: (error: unknown) => void;
45
+ /**
46
+ * Fired whenever the form-level validation state changes.
47
+ *
48
+ * Receives `true` when all fields and the template name satisfy the Yup schema,
49
+ * and `false` once any validation error is present. The editor enables Formik's
50
+ * `validateOnMount`, so the first validation pass runs after the form mounts (Yup
51
+ * is asynchronous — there can be a short window before the first callback).
52
+ *
53
+ * Most useful when `hideActions={true}` and the host renders its own submit button
54
+ * outside the form — the host can gate that button on this value.
55
+ *
56
+ * @example
57
+ * ```tsx
58
+ * const [isFormValid, setIsFormValid] = useState(true);
59
+ *
60
+ * <MetadataTemplateEditor
61
+ * hideActions
62
+ * formId="my-form"
63
+ * onValidationChange={setIsFormValid}
64
+ * // ...
65
+ * />
66
+ * <button form="my-form" type="submit" disabled={!isFormValid}>Save</button>
67
+ * ```
68
+ */
69
+ onValidationChange?: (isValid: boolean) => void;
70
+ /**
71
+ * Fired once the template data has been fetched and the form is populated.
72
+ * Only called in edit mode.
73
+ *
74
+ * @example
75
+ * ```tsx
76
+ * // Reflect the loaded template name in a parent heading
77
+ * const [templateName, setTemplateName] = useState('');
78
+ *
79
+ * <h2>{templateName || 'Loading…'}</h2>
80
+ * <MetadataTemplateEditor
81
+ * mode={MetadataTemplateEditorMode.Edit}
82
+ * fetchTemplate={() => api.getTemplate(templateKey)}
83
+ * onEditTemplate={handleEdit}
84
+ * onTemplateLoad={t => setTemplateName(t.displayName)}
85
+ * />
86
+ * ```
87
+ */
88
+ onTemplateLoad?: (template: MetadataTemplateApiResponse) => void;
89
+ /**
90
+ * Static taxonomy options forwarded to each field configurator.
91
+ * Use `fetchTaxonomies` instead for lazy loading with built-in loading/error/retry handling.
92
+ */
93
+ taxonomyOptions?: MetadataFieldListProps['taxonomyOptions'];
94
+ /**
95
+ * Async function called to fetch the available taxonomy options.
96
+ *
97
+ * The shared feature calls this automatically the first time the user opens the taxonomy selector
98
+ * on any field. Results are cached per-field for the lifetime of the component — the implementing
99
+ * team does not need to manage loading state, error handling, or retry logic.
100
+ *
101
+ * Mutually exclusive with `taxonomyOptions`.
102
+ *
103
+ * @example
104
+ * ```tsx
105
+ * <MetadataTemplateEditor
106
+ * fetchTaxonomies={() => api.getTaxonomies(namespaceId)}
107
+ * onCreateTemplate={handleCreate}
108
+ * />
109
+ * ```
110
+ */
111
+ fetchTaxonomies?: MetadataFieldListProps['fetchTaxonomies'];
112
+ /**
113
+ * HTML `id` applied to the `<form>` element.
114
+ * Useful when submit/cancel buttons are rendered outside the form DOM subtree
115
+ * (e.g. inside a modal footer) and need to be associated via the `form` attribute.
116
+ */
117
+ formId?: string;
118
+ /**
119
+ * When `true`, the built-in Cancel / Save action bar is not rendered.
120
+ * Use this together with `formId` when the parent (e.g. a modal) owns the actions.
121
+ */
122
+ hideActions?: boolean;
123
+ /**
124
+ * Domain-specific extensions injected into every field configurator in this editor.
125
+ *
126
+ * When provided, a tab switcher appears in each field's accordion header next to the
127
+ * context menu. The first tab always shows the built-in Edit UI; each additional tab
128
+ * renders the corresponding extension's content with the current field data.
129
+ *
130
+ * Can also be passed at a lower level via `MetadataFieldList` or `MetadataFieldConfigurator`
131
+ * directly — the nearest provider in the tree wins.
132
+ *
133
+ * @example
134
+ * ```tsx
135
+ * <MetadataTemplateEditor
136
+ * mode="edit"
137
+ * fieldExtensions={[
138
+ * {
139
+ * icon: MyIcon,
140
+ * label: 'My settings',
141
+ * renderContent: field => <MyFieldPanel field={field} />,
142
+ * },
143
+ * ]}
144
+ * />
145
+ * ```
146
+ */
147
+ fieldExtensions?: FieldConfiguratorExtension[];
148
+ };
149
+ /**
150
+ * Create mode: no pre-existing values.
151
+ */
152
+ type CreateModeProps = {
153
+ /** Discriminates the union; must be `MetadataTemplateEditorMode.Create` for the create flow. */
154
+ mode: MetadataTemplateEditorMode.Create;
155
+ /**
156
+ * The namespace the new template will be created in.
157
+ * Included verbatim in the create request body — the editor does not render
158
+ * it as a visible field.
159
+ *
160
+ * @example `"enterprise"` · `"global"` · `"myOrg"`
161
+ */
162
+ namespace: string;
163
+ /**
164
+ * Called when the user saves a **new** template and the form passes all validation.
165
+ * Receives the API-ready create payload with fields converted from the internal
166
+ * configurator shape. `await` this if you need `isSubmitting` to remain `true`
167
+ * during the API call.
168
+ */
169
+ onCreateTemplate: (body: MetadataTemplateCreateBody) => Promise<void> | void;
170
+ onEditTemplate?: never;
171
+ fetchTemplate?: never;
172
+ };
173
+ /**
174
+ * Edit mode: the form fetches its own data and the Save button is only enabled
175
+ * when there are unsaved changes (`formik.dirty`).
176
+ */
177
+ type EditModeProps = {
178
+ /** Discriminates the union; must be `MetadataTemplateEditorMode.Edit` for the edit flow. */
179
+ mode: MetadataTemplateEditorMode.Edit;
180
+ /**
181
+ * Called when the user saves changes to an **existing** template and the form
182
+ * passes all validation. Receives the array of JSON Patch operations that
183
+ * describe only the changes made since the template was loaded.
184
+ * `await` this if you need `isSubmitting` to remain `true` during the API call.
185
+ */
186
+ onEditTemplate: (patchItems: MetadataTemplatePatchItem[]) => Promise<void> | void;
187
+ onCreateTemplate?: never;
188
+ /**
189
+ * Called once (and re-called whenever the reference changes) to fetch the
190
+ * existing template data. The editor handles loading state and field conversion
191
+ * internally — the host does not need to manage either.
192
+ *
193
+ * Provide a stable reference (e.g. via `useCallback`) to avoid unnecessary
194
+ * re-fetches; a new reference triggers a fresh fetch.
195
+ */
196
+ fetchTemplate: () => Promise<MetadataTemplateApiResponse>;
197
+ /** Namespace is read from the fetched template in edit mode — do not pass it from the host. */
198
+ namespace?: never;
199
+ };
200
+ export type MetadataTemplateEditorProps = MetadataTemplateEditorCommonProps & (CreateModeProps | EditModeProps);
201
+ /**
202
+ * Imperative handle exposed by `MetadataTemplateEditor` via `ref`.
203
+ *
204
+ * Allows a parent (e.g. `MetadataTemplateEditorModal`) to delegate its own
205
+ * cancel / close triggers to the editor so that the "unsaved changes" guard
206
+ * and the `ConfirmationModal` live in exactly one place.
207
+ *
208
+ * @example
209
+ * ```tsx
210
+ * const editorRef = useRef<MetadataTemplateEditorHandle>(null);
211
+ *
212
+ * // Delegate the modal's footer Cancel and shell close to the editor:
213
+ * <MetadataTemplateEditorModal … /> // internally calls editorRef.current.requestClose()
214
+ *
215
+ * // Or wire it up manually:
216
+ * <button onClick={() => editorRef.current?.requestClose()}>Cancel</button>
217
+ * <MetadataTemplateEditor ref={editorRef} … />
218
+ * ```
219
+ */
220
+ export type MetadataTemplateEditorHandle = {
221
+ /**
222
+ * Triggers the editor's cancel flow from outside the component.
223
+ * If the form is dirty, opens the "unsaved changes" confirmation modal.
224
+ * Otherwise calls `onCancel` immediately.
225
+ */
226
+ requestClose: () => void;
227
+ };
228
+ /**
229
+ * Full metadata template creation / editing form.
230
+ *
231
+ * - Formik owns `displayName`, `templateKey`, and the `fields` array.
232
+ * - Each `MetadataFieldConfigurator` (rendered via `MetadataFieldList`) runs
233
+ * its own internal Yup validation for real-time feedback — no error threading
234
+ * is required from this form down to the fields.
235
+ * - `useMetadataTemplateFormSchema` embeds the same per-field schema here so Formik
236
+ * can gate submission if any field is invalid, even if the user hasn't interacted
237
+ * with it yet.
238
+ * - Empty state shows `FieldTypeTiles`; once fields exist, shows `MetadataFieldList`
239
+ * with a `FieldTypeDropdown` "Add field" button below.
240
+ * - Pass `mode={MetadataTemplateEditorMode.Edit}` to enable **edit mode**: the form
241
+ * fetches its own data via `fetchTemplate` and the Save button is only enabled when
242
+ * there are unsaved changes.
243
+ *
244
+ * @example
245
+ * ```tsx
246
+ * // Minimal create flow
247
+ * <MetadataTemplateEditor
248
+ * mode={MetadataTemplateEditorMode.Create}
249
+ * namespace="enterprise"
250
+ * onCreateTemplate={async body => { await api.createTemplate(body); }}
251
+ * onCancel={() => navigate(-1)}
252
+ * />
253
+ *
254
+ * // Minimal edit flow
255
+ * <MetadataTemplateEditor
256
+ * mode={MetadataTemplateEditorMode.Edit}
257
+ * fetchTemplate={useCallback(() => api.getTemplate(templateKey), [templateKey])}
258
+ * onEditTemplate={async patches => { await api.updateTemplate(patches); }}
259
+ * onCancel={() => navigate(-1)}
260
+ * />
261
+ * ```
262
+ *
263
+ * @example
264
+ * ```tsx
265
+ * // External submit button with full observer callbacks
266
+ * const [isFormValid, setIsFormValid] = useState(true);
267
+ * const [isDirty, setIsDirty] = useState(false);
268
+ *
269
+ * <MetadataTemplateEditor
270
+ * mode={MetadataTemplateEditorMode.Edit}
271
+ * fetchTemplate={() => api.getTemplate(templateKey)}
272
+ * onEditTemplate={async patches => { await api.updateTemplate(patches); }}
273
+ * onTemplateLoad={t => setPageTitle(t.displayName)}
274
+ * onDirtyStateChange={setIsDirty}
275
+ * onValidationChange={setIsFormValid}
276
+ * onSubmitError={err => logger.error('save failed', err)}
277
+ * hideActions
278
+ * formId="template-form"
279
+ * />
280
+ * <button
281
+ * form="template-form"
282
+ * type="submit"
283
+ * disabled={!isFormValid || !isDirty}
284
+ * >
285
+ * Save
286
+ * </button>
287
+ * ```
288
+ */
289
+ export declare const MetadataTemplateEditor: import('react').ForwardRefExoticComponent<MetadataTemplateEditorProps & import('react').RefAttributes<MetadataTemplateEditorHandle>>;
290
+ export default MetadataTemplateEditor;
@@ -0,0 +1,311 @@
1
+ /**
2
+ * Discriminates between creating a new template and editing an existing one.
3
+ * Pass as the `mode` prop on `MetadataTemplateEditor` / `MetadataTemplateEditorModal`.
4
+ */
5
+ export declare enum MetadataTemplateEditorMode {
6
+ Create = "create",
7
+ Edit = "edit"
8
+ }
9
+ /**
10
+ * Types of fields that can be defined in a metadata template:
11
+ * - Text - plain text field
12
+ * - Number - numeric field
13
+ * - Date - date field
14
+ * - Dropdown - field with a dropdown list
15
+ * - Taxonomy - taxonomy field (e.g. key-value pairs)
16
+ */
17
+ export declare enum FieldType {
18
+ Text = "text",
19
+ Number = "number",
20
+ Date = "date",
21
+ Dropdown = "dropdown",
22
+ Taxonomy = "taxonomy"
23
+ }
24
+ /**
25
+ * Basic set of properties for every field.
26
+ */
27
+ export interface BasicField {
28
+ /**
29
+ * Stable UI identity generated client-side (lodash `uniqueId`).
30
+ * Used by dnd-kit item IDs, Accordion item values, and DOM element IDs.
31
+ * Never sent to the backend — use `key` for the persisted field identifier.
32
+ */
33
+ id: string;
34
+ key: string;
35
+ type: FieldType;
36
+ name: string;
37
+ description?: string;
38
+ hidden: boolean;
39
+ dropdown: DropdownField['dropdown'];
40
+ taxonomy: TaxonomyField['taxonomy'];
41
+ isFieldNew: boolean;
42
+ isFieldReadOnly: boolean;
43
+ }
44
+ /**
45
+ * Describes possible data for any field. It branches based on the `type` property.
46
+ */
47
+ export type FieldData = (BasicField & {
48
+ type: FieldType.Text | FieldType.Number | FieldType.Date;
49
+ }) | (BasicField & DropdownField & {
50
+ type: FieldType.Dropdown;
51
+ }) | (BasicField & TaxonomyField & {
52
+ type: FieldType.Taxonomy;
53
+ });
54
+ /**
55
+ * Represents a dropdown field with a non-empty array of options.
56
+ */
57
+ export interface DropdownField {
58
+ dropdown: {
59
+ options: DropdownFieldOption[];
60
+ allowMultipleSelections: boolean;
61
+ isAllowMultipleSelectionsEnabled: boolean;
62
+ };
63
+ }
64
+ /**
65
+ * Represents options for dropdown field type.
66
+ */
67
+ export interface DropdownFieldOption {
68
+ id: string;
69
+ key: string;
70
+ isNew: boolean;
71
+ }
72
+ /**
73
+ * Represents a taxonomy field.
74
+ */
75
+ export interface TaxonomyField {
76
+ taxonomy: {
77
+ availableTaxonomies: TaxonomyOption[];
78
+ allowMultipleSelections: boolean;
79
+ selection: TaxonomySelection;
80
+ selectedLevels: number[];
81
+ taxonomyKey: string;
82
+ taxonomySearchValue: string;
83
+ namespace: string;
84
+ };
85
+ }
86
+ /**
87
+ * Represents a taxonomy option.
88
+ */
89
+ export interface TaxonomyOption {
90
+ id: string;
91
+ label: string;
92
+ levels: TaxonomyLevel[];
93
+ selected: boolean;
94
+ taxonomyKey: string;
95
+ namespace: string;
96
+ }
97
+ /**
98
+ * Represents a taxonomy level.
99
+ */
100
+ export interface TaxonomyLevel {
101
+ name: string;
102
+ level: number;
103
+ }
104
+ /**
105
+ * Represents the selection mode for a taxonomy field.
106
+ */
107
+ export declare enum TaxonomySelection {
108
+ RequireSpecific = "requireSpecific",
109
+ AllowAny = "allowAny"
110
+ }
111
+ /**
112
+ * Represents the type of a field in a metadata template API response.
113
+ */
114
+ export declare enum ApiMetadataTemplateFieldType {
115
+ Float = "float",
116
+ Taxonomy = "taxonomy",
117
+ MultiSelect = "multiSelect",
118
+ Date = "date",
119
+ String = "string",
120
+ Enum = "enum"
121
+ }
122
+ export type ApiDropdownFieldOption = {
123
+ key: string;
124
+ };
125
+ export type ApiMetadataTemplateFieldBase = {
126
+ key: string;
127
+ displayName: string;
128
+ description?: string;
129
+ isHidden: boolean;
130
+ };
131
+ export type ApiMetadataTemplateTextField = {
132
+ type: ApiMetadataTemplateFieldType.String;
133
+ };
134
+ export type ApiMetadataTemplateNumberField = {
135
+ type: ApiMetadataTemplateFieldType.Float;
136
+ };
137
+ export type ApiMetadataTemplateDateField = {
138
+ type: ApiMetadataTemplateFieldType.Date;
139
+ };
140
+ export type ApiMetadataTemplateTaxonomyField = {
141
+ type: ApiMetadataTemplateFieldType.Taxonomy;
142
+ taxonomyKey: string;
143
+ optionsRules: {
144
+ selectableLevels: number[];
145
+ multiSelect: boolean;
146
+ };
147
+ namespace: string;
148
+ };
149
+ export type ApiMetadataTemplateDropdownField = {
150
+ type: ApiMetadataTemplateFieldType.Enum | ApiMetadataTemplateFieldType.MultiSelect;
151
+ options: ApiDropdownFieldOption[];
152
+ };
153
+ export type ApiMetadataTemplateField = ApiMetadataTemplateFieldBase & (ApiMetadataTemplateTextField | ApiMetadataTemplateNumberField | ApiMetadataTemplateDateField | ApiMetadataTemplateTaxonomyField | ApiMetadataTemplateDropdownField);
154
+ type MetadataTemplateBase = {
155
+ namespace: string;
156
+ templateKey: string;
157
+ displayName: string;
158
+ };
159
+ export type MetadataTemplateApiResponse = MetadataTemplateBase & {
160
+ fields: ApiMetadataTemplateField[];
161
+ isHidden: boolean;
162
+ };
163
+ export type MetadataTemplateEditorFormValues = MetadataTemplateBase & {
164
+ /**
165
+ this is a parameter after type conversion from api (MetadataTemplateField)
166
+ for easier handling in the field editor
167
+ */
168
+ fields: FieldData[];
169
+ /**
170
+ * This visibility property parameter is different from the API response's `isHidden`
171
+ because there is a param name mismatch between get and put/post endpoints (`isHidden` vs `hidden`)
172
+ */
173
+ hidden: boolean;
174
+ };
175
+ /**
176
+ * A template field as expected by the create (POST) endpoint.
177
+ * Uses `hidden` (not `isHidden`) because of the param name mismatch between GET and POST endpoints.
178
+ */
179
+ export type MetadataTemplateFieldCreateBody = Omit<ApiMetadataTemplateFieldBase, 'isHidden'> & {
180
+ hidden: boolean;
181
+ } & (ApiMetadataTemplateTextField | ApiMetadataTemplateNumberField | ApiMetadataTemplateDateField | ApiMetadataTemplateTaxonomyField | ApiMetadataTemplateDropdownField);
182
+ /**
183
+ * The full request body sent to the create (POST) endpoint.
184
+ * Fields are in the converted API-ready shape (with `hidden` instead of `isHidden`).
185
+ */
186
+ export type MetadataTemplateCreateBody = MetadataTemplateBase & {
187
+ hidden: boolean;
188
+ fields: MetadataTemplateFieldCreateBody[];
189
+ };
190
+ export declare enum TemplateOperations {
191
+ EditTemplate = "editTemplate"
192
+ }
193
+ export declare enum FieldOperations {
194
+ AddField = "addField",
195
+ ReorderFields = "reorderFields",
196
+ EditField = "editField",
197
+ RemoveField = "removeField"
198
+ }
199
+ export declare enum EnumOperations {
200
+ AddEnumOption = "addEnumOption",
201
+ ReorderEnumOptions = "reorderEnumOptions",
202
+ EditEnumOption = "editEnumOption",
203
+ RemoveEnumOption = "removeEnumOption"
204
+ }
205
+ export declare enum MultiSelectOperations {
206
+ AddMultiSelectOption = "addMultiSelectOption",
207
+ ReorderMultiSelectOptions = "reorderMultiSelectOptions",
208
+ EditMultiSelectOption = "editMultiSelectOption",
209
+ RemoveMultiSelectOption = "removeMultiSelectOption"
210
+ }
211
+ export declare const AllOps: {
212
+ readonly AddMultiSelectOption: MultiSelectOperations.AddMultiSelectOption;
213
+ readonly ReorderMultiSelectOptions: MultiSelectOperations.ReorderMultiSelectOptions;
214
+ readonly EditMultiSelectOption: MultiSelectOperations.EditMultiSelectOption;
215
+ readonly RemoveMultiSelectOption: MultiSelectOperations.RemoveMultiSelectOption;
216
+ readonly AddEnumOption: EnumOperations.AddEnumOption;
217
+ readonly ReorderEnumOptions: EnumOperations.ReorderEnumOptions;
218
+ readonly EditEnumOption: EnumOperations.EditEnumOption;
219
+ readonly RemoveEnumOption: EnumOperations.RemoveEnumOption;
220
+ readonly AddField: FieldOperations.AddField;
221
+ readonly ReorderFields: FieldOperations.ReorderFields;
222
+ readonly EditField: FieldOperations.EditField;
223
+ readonly RemoveField: FieldOperations.RemoveField;
224
+ readonly EditTemplate: TemplateOperations.EditTemplate;
225
+ };
226
+ export type ValidOperations = (typeof AllOps)[keyof typeof AllOps];
227
+ interface BaseOperation {
228
+ op: ValidOperations;
229
+ }
230
+ interface EditTemplateOperation extends BaseOperation {
231
+ op: TemplateOperations.EditTemplate;
232
+ data: {
233
+ displayName?: string;
234
+ hidden?: boolean;
235
+ };
236
+ }
237
+ interface AddFieldOperation extends BaseOperation {
238
+ op: FieldOperations.AddField;
239
+ fieldKey?: string;
240
+ data: ApiMetadataTemplateField;
241
+ }
242
+ interface ReorderFieldsOperation extends BaseOperation {
243
+ op: FieldOperations.ReorderFields;
244
+ fieldKeys: string[];
245
+ }
246
+ export interface EditFieldOperation extends BaseOperation {
247
+ op: FieldOperations.EditField;
248
+ fieldKey: string;
249
+ data: {
250
+ displayName?: string;
251
+ description?: string;
252
+ hidden?: boolean;
253
+ };
254
+ }
255
+ interface RemoveFieldOperation extends BaseOperation {
256
+ op: FieldOperations.RemoveField;
257
+ fieldKey: string;
258
+ }
259
+ interface AddEnumOptionOperation extends BaseOperation {
260
+ op: EnumOperations.AddEnumOption;
261
+ fieldKey: string;
262
+ data: {
263
+ key: string;
264
+ };
265
+ }
266
+ interface ReorderEnumOptionsOperation extends BaseOperation {
267
+ op: EnumOperations.ReorderEnumOptions;
268
+ fieldKey: string;
269
+ enumOptionKeys: string[];
270
+ }
271
+ interface EditEnumOptionOperation extends BaseOperation {
272
+ op: EnumOperations.EditEnumOption;
273
+ fieldKey: string;
274
+ enumOptionKey: string;
275
+ data: {
276
+ key: string;
277
+ };
278
+ }
279
+ interface RemoveEnumOptionOperation extends BaseOperation {
280
+ op: EnumOperations.RemoveEnumOption;
281
+ fieldKey: string;
282
+ enumOptionKey: string;
283
+ }
284
+ interface AddMultiSelectOptionOperation extends BaseOperation {
285
+ op: MultiSelectOperations.AddMultiSelectOption;
286
+ fieldKey: string;
287
+ data: {
288
+ key: string;
289
+ };
290
+ }
291
+ interface ReorderMultiSelectOptionsOperation extends BaseOperation {
292
+ op: MultiSelectOperations.ReorderMultiSelectOptions;
293
+ fieldKey: string;
294
+ multiSelectOptionKeys: string[];
295
+ }
296
+ interface EditMultiSelectOptionOperation extends BaseOperation {
297
+ op: MultiSelectOperations.EditMultiSelectOption;
298
+ fieldKey: string;
299
+ multiSelectOptionKey: string;
300
+ data: {
301
+ key: string;
302
+ };
303
+ }
304
+ interface RemoveMultiSelectOptionOperation extends BaseOperation {
305
+ op: MultiSelectOperations.RemoveMultiSelectOption;
306
+ fieldKey: string;
307
+ multiSelectOptionKey: string;
308
+ }
309
+ export type MetadataTemplatePatchItem = EditTemplateOperation | AddFieldOperation | ReorderFieldsOperation | EditFieldOperation | RemoveFieldOperation | AddEnumOptionOperation | ReorderEnumOptionsOperation | EditEnumOptionOperation | RemoveEnumOptionOperation | AddMultiSelectOptionOperation | ReorderMultiSelectOptionsOperation | EditMultiSelectOptionOperation | RemoveMultiSelectOptionOperation;
310
+ export type TemplateUpdateRequestBody = MetadataTemplatePatchItem[];
311
+ export {};
@@ -0,0 +1,9 @@
1
+ /** Max length for a metadata template field name (display name). */
2
+ export declare const METADATA_TEMPLATE_FIELD_NAME_MAX_LENGTH = 4096;
3
+ /** Max length for a metadata template field key. */
4
+ export declare const METADATA_TEMPLATE_FIELD_KEY_MAX_LENGTH = 256;
5
+ /** Max length for a metadata template key. */
6
+ export declare const METADATA_TEMPLATE_KEY_MAX_LENGTH = 64;
7
+ /** Max length for a metadata template name (display name). */
8
+ export declare const METADATA_TEMPLATE_NAME_MAX_LENGTH = 4096;
9
+ export declare const CONFLICT_HTTP_STATUS = 409;
@@ -0,0 +1,6 @@
1
+ import { default as React } from 'react';
2
+ import { FieldType } from '../../types';
3
+ /**
4
+ * Returns an icon component based on the provided field type.
5
+ */
6
+ export declare const FieldTypeIcon: (type: FieldType) => (props: React.SVGProps<SVGSVGElement>) => React.JSX.Element;
@@ -0,0 +1,4 @@
1
+ export { FieldTypeIcon } from './field-type-icon';
2
+ export { fieldTypeDescriptionMessages, fieldTypesTitleMessages } from './messages';
3
+ export { useFieldOptions } from './useFieldOptions';
4
+ export type { FieldOptionType, FieldOptionTypes } from './useFieldOptions';
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Field type labels for metadata template editor.
3
+ */
4
+ export declare const fieldTypesTitleMessages: {
5
+ text: {
6
+ defaultMessage: string;
7
+ description: string;
8
+ id: string;
9
+ };
10
+ number: {
11
+ defaultMessage: string;
12
+ description: string;
13
+ id: string;
14
+ };
15
+ date: {
16
+ defaultMessage: string;
17
+ description: string;
18
+ id: string;
19
+ };
20
+ dropdown: {
21
+ defaultMessage: string;
22
+ description: string;
23
+ id: string;
24
+ };
25
+ taxonomy: {
26
+ defaultMessage: string;
27
+ description: string;
28
+ id: string;
29
+ };
30
+ };
31
+ /**
32
+ * Detailed descriptions for each metadata field type.
33
+ */
34
+ export declare const fieldTypeDescriptionMessages: {
35
+ text: {
36
+ defaultMessage: string;
37
+ description: string;
38
+ id: string;
39
+ };
40
+ number: {
41
+ defaultMessage: string;
42
+ description: string;
43
+ id: string;
44
+ };
45
+ date: {
46
+ defaultMessage: string;
47
+ description: string;
48
+ id: string;
49
+ };
50
+ dropdown: {
51
+ defaultMessage: string;
52
+ description: string;
53
+ id: string;
54
+ };
55
+ taxonomy: {
56
+ defaultMessage: string;
57
+ description: string;
58
+ id: string;
59
+ };
60
+ };