@svadmin/ui 0.70.0 → 0.73.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 (372) hide show
  1. package/README.md +40 -25
  2. package/THIRD_PARTY_NOTICES.md +52 -0
  3. package/dist/actions.js +1 -1
  4. package/dist/app.css +7804 -5188
  5. package/dist/app.theme.css +7738 -5173
  6. package/dist/class-properties.generated.d.ts +1 -0
  7. package/dist/class-properties.generated.js +2 -0
  8. package/dist/classnames.d.ts +8 -0
  9. package/dist/classnames.js +26 -0
  10. package/dist/component-registry.svelte.d.ts +33 -19
  11. package/dist/component-registry.svelte.js +6 -4
  12. package/dist/components/AdminApp.svelte +55 -53
  13. package/dist/components/AdminApp.svelte.d.ts +2 -2
  14. package/dist/components/ApiSettings.svelte +19 -1
  15. package/dist/components/AuditLogDrawer.svelte +14 -3
  16. package/dist/components/AutoForm.svelte +162 -50
  17. package/dist/components/AutoForm.svelte.d.ts +4 -0
  18. package/dist/components/AutoTable.svelte +599 -259
  19. package/dist/components/AutoTable.svelte.d.ts +6 -0
  20. package/dist/components/BoundRecordDetailDrawer.svelte +172 -0
  21. package/dist/components/BoundRecordDetailDrawer.svelte.d.ts +11 -0
  22. package/dist/components/Breadcrumbs.svelte +7 -4
  23. package/dist/components/CancelTaskButton.svelte +9 -5
  24. package/dist/components/ColumnHeaderFilter.svelte +4 -3
  25. package/dist/components/ColumnSettings.svelte +1 -0
  26. package/dist/components/ComboboxField.svelte +118 -36
  27. package/dist/components/ComboboxField.svelte.d.ts +5 -4
  28. package/dist/components/CreatePage.svelte +7 -1
  29. package/dist/components/CreatePage.svelte.d.ts +2 -0
  30. package/dist/components/DateRangeInput.svelte +75 -0
  31. package/dist/components/DateRangeInput.svelte.d.ts +25 -0
  32. package/dist/components/DateTimeInput.svelte +65 -0
  33. package/dist/components/DateTimeInput.svelte.d.ts +19 -0
  34. package/dist/components/DetailDrawer.svelte +4 -0
  35. package/dist/components/DetailDrawer.svelte.d.ts +1 -0
  36. package/dist/components/DevTools.svelte +8 -21
  37. package/dist/components/DraggableGrid.svelte +1 -0
  38. package/dist/components/DraggableHeader.svelte +5 -9
  39. package/dist/components/DraggableHeader.svelte.d.ts +43 -18
  40. package/dist/components/DraggableRowTable.svelte +2 -2
  41. package/dist/components/DynamicFormList.svelte +17 -17
  42. package/dist/components/DynamicFormList.svelte.d.ts +2 -1
  43. package/dist/components/EditPage.svelte +7 -1
  44. package/dist/components/EditPage.svelte.d.ts +2 -0
  45. package/dist/components/EditableTable.svelte +4 -0
  46. package/dist/components/ErrorPage.svelte +3 -1
  47. package/dist/components/FieldDisplay.svelte +14 -0
  48. package/dist/components/FieldDisplay.svelte.d.ts +7 -0
  49. package/dist/components/FieldRenderer.svelte +96 -20
  50. package/dist/components/FileUpload.svelte +250 -0
  51. package/dist/components/FileUpload.svelte.d.ts +32 -0
  52. package/dist/components/FilterBuilder.svelte +236 -268
  53. package/dist/components/FilterBuilder.svelte.d.ts +3 -0
  54. package/dist/components/FilterDropdown.svelte.d.ts +1 -1
  55. package/dist/components/Header.svelte +5 -6
  56. package/dist/components/ImportWizard.svelte +182 -94
  57. package/dist/components/InfiniteList.svelte +22 -8
  58. package/dist/components/InfiniteList.svelte.d.ts +5 -3
  59. package/dist/components/InlineEdit.svelte +114 -44
  60. package/dist/components/JsonSchemaForm.svelte +256 -95
  61. package/dist/components/JsonSchemaForm.svelte.d.ts +12 -1
  62. package/dist/components/Layout.svelte +20 -17
  63. package/dist/components/LazyTaskQueueDrawer.svelte +26 -0
  64. package/dist/components/LazyTaskQueueDrawer.svelte.d.ts +8 -0
  65. package/dist/components/ListPage.svelte +11 -6
  66. package/dist/components/ListPage.svelte.d.ts +2 -0
  67. package/dist/components/LoginPage.svelte +1 -1
  68. package/dist/components/MasterDetailView.svelte +3 -3
  69. package/dist/components/MediaLibraryModal.svelte +5 -2
  70. package/dist/components/MentionsInput.svelte +4 -3
  71. package/dist/components/MoneyInput.svelte +25 -0
  72. package/dist/components/MoneyInput.svelte.d.ts +20 -0
  73. package/dist/components/NavigateToResource.svelte +3 -2
  74. package/dist/components/NumberInput.svelte +25 -0
  75. package/dist/components/NumberInput.svelte.d.ts +19 -0
  76. package/dist/components/NumericInput.svelte +110 -0
  77. package/dist/components/NumericInput.svelte.d.ts +23 -0
  78. package/dist/components/PercentInput.svelte +25 -0
  79. package/dist/components/PercentInput.svelte.d.ts +20 -0
  80. package/dist/components/PermissionMatrix.svelte +4 -3
  81. package/dist/components/ProfilePage.svelte +2 -2
  82. package/dist/components/QuickEditDrawer.svelte +42 -0
  83. package/dist/components/QuickEditDrawer.svelte.d.ts +10 -0
  84. package/dist/components/RecordDetailDrawer.svelte +16 -108
  85. package/dist/components/RecordDetailDrawer.svelte.d.ts +2 -0
  86. package/dist/components/RecordRowActions.svelte +41 -0
  87. package/dist/components/RecordRowActions.svelte.d.ts +14 -0
  88. package/dist/components/ResourceAccessGuard.svelte +7 -5
  89. package/dist/components/ResourceOperationsPage.svelte +25 -19
  90. package/dist/components/ResourceOperationsPage.svelte.d.ts +5 -1
  91. package/dist/components/RetryTaskButton.svelte +9 -5
  92. package/dist/components/RowActions.svelte +5 -3
  93. package/dist/components/SensitiveDataMask.svelte +3 -3
  94. package/dist/components/SettingsPage.svelte +1 -1
  95. package/dist/components/ShowInferencer.svelte +4 -2
  96. package/dist/components/ShowInferencer.svelte.d.ts +2 -0
  97. package/dist/components/ShowPage.svelte +49 -39
  98. package/dist/components/ShowPage.svelte.d.ts +2 -0
  99. package/dist/components/Sidebar.svelte +15 -13
  100. package/dist/components/SplitPaneLayout.svelte +4 -2
  101. package/dist/components/SpreadsheetView.svelte +81 -286
  102. package/dist/components/StepsForm.svelte +166 -49
  103. package/dist/components/StepsForm.svelte.d.ts +1 -0
  104. package/dist/components/SvarAutoTable.svelte +39 -0
  105. package/dist/components/SvarAutoTable.svelte.d.ts +13 -0
  106. package/dist/components/SvarDataGrid.svelte +362 -0
  107. package/dist/components/SvarDataGrid.svelte.d.ts +57 -0
  108. package/dist/components/SvarGridCell.svelte +10 -0
  109. package/dist/components/SvarGridCell.svelte.d.ts +7 -0
  110. package/dist/components/SvarResourceRead.svelte +50 -0
  111. package/dist/components/SvarResourceRead.svelte.d.ts +23 -0
  112. package/dist/components/SvarResourceTable.svelte +63 -0
  113. package/dist/components/SvarResourceTable.svelte.d.ts +42 -0
  114. package/dist/components/SvarResourceTableView.svelte +364 -0
  115. package/dist/components/SvarResourceTableView.svelte.d.ts +4 -0
  116. package/dist/components/TaskDetails.svelte +20 -7
  117. package/dist/components/TaskList.svelte +19 -7
  118. package/dist/components/TaskQueueDrawer.svelte +92 -37
  119. package/dist/components/Toast.svelte +4 -2
  120. package/dist/components/TooltipButton.svelte +1 -1
  121. package/dist/components/TreeSelect.svelte +212 -30
  122. package/dist/components/TreeSelect.svelte.d.ts +3 -1
  123. package/dist/components/ValidatedField.svelte +27 -0
  124. package/dist/components/ValidatedField.svelte.d.ts +35 -0
  125. package/dist/components/account/ImportMembersPage.svelte +2 -2
  126. package/dist/components/account/SecurityLogPage.svelte +3 -1
  127. package/dist/components/account/SettingsEnterprisePage.svelte +7 -5
  128. package/dist/components/account/TeamMembersPage.svelte +1 -1
  129. package/dist/components/auto-table-grid.d.ts +26 -0
  130. package/dist/components/auto-table-grid.js +1 -0
  131. package/dist/components/buttons/CloneButton.svelte +6 -4
  132. package/dist/components/buttons/DeleteButton.svelte +95 -29
  133. package/dist/components/buttons/DeleteButton.svelte.d.ts +2 -0
  134. package/dist/components/buttons/EditButton.svelte +6 -4
  135. package/dist/components/buttons/ExportButton.svelte +22 -4
  136. package/dist/components/buttons/ImportButton.svelte +83 -38
  137. package/dist/components/buttons/ImportButton.svelte.d.ts +6 -10
  138. package/dist/components/buttons/RefreshButton.svelte +48 -8
  139. package/dist/components/buttons/ShowButton.svelte +6 -4
  140. package/dist/components/content/ApiKeyList.svelte +3 -1
  141. package/dist/components/content/ContentPageHeader.svelte +12 -9
  142. package/dist/components/content/ContentPageShell.svelte +8 -9
  143. package/dist/components/content/FileBrowser.svelte +35 -0
  144. package/dist/components/content/FileBrowser.svelte.d.ts +14 -0
  145. package/dist/components/content/FileList.svelte +3 -1
  146. package/dist/components/content/MemberList.svelte +3 -1
  147. package/dist/components/content/MetricBlock.svelte +10 -13
  148. package/dist/components/content/NetworkTable.svelte +6 -4
  149. package/dist/components/content/NetworkTable.svelte.d.ts +1 -0
  150. package/dist/components/content/PageToolbar.svelte +6 -10
  151. package/dist/components/content/SectionHeader.svelte +8 -13
  152. package/dist/components/content/SecurityEventTable.svelte +3 -1
  153. package/dist/components/content/SettingsFieldRow.svelte +9 -23
  154. package/dist/components/content/SettingsGroup.svelte +11 -27
  155. package/dist/components/content/StatusBadge.svelte +3 -8
  156. package/dist/components/content/StatusTabs.svelte +2 -2
  157. package/dist/components/content/WorkspaceLayout.svelte +8 -12
  158. package/dist/components/enterprise/filter-tree.d.ts +48 -0
  159. package/dist/components/enterprise/filter-tree.js +224 -0
  160. package/dist/components/enterprise/json-schema-form.d.ts +39 -0
  161. package/dist/components/enterprise/json-schema-form.js +195 -0
  162. package/dist/components/enterprise/recursive-schema-form.d.ts +30 -0
  163. package/dist/components/enterprise/recursive-schema-form.js +196 -0
  164. package/dist/components/enterprise/spreadsheet-formula.d.ts +12 -0
  165. package/dist/components/enterprise/spreadsheet-formula.js +245 -0
  166. package/dist/components/fieldComponentMap.d.ts +18 -13
  167. package/dist/components/fieldComponentMap.js +100 -47
  168. package/dist/components/fields/AvatarField.svelte +1 -1
  169. package/dist/components/fields/ChoiceField.svelte +16 -0
  170. package/dist/components/fields/ChoiceField.svelte.d.ts +10 -0
  171. package/dist/components/fields/CodeField.svelte +11 -12
  172. package/dist/components/fields/CodeField.svelte.d.ts +1 -1
  173. package/dist/components/fields/DateField.svelte +4 -3
  174. package/dist/components/fields/DateRangeField.svelte +2 -4
  175. package/dist/components/fields/ImageField.svelte +3 -1
  176. package/dist/components/fields/ImagesField.svelte +23 -0
  177. package/dist/components/fields/ImagesField.svelte.d.ts +6 -0
  178. package/dist/components/fields/JsonField.svelte +19 -13
  179. package/dist/components/fields/PasswordField.svelte +5 -0
  180. package/dist/components/fields/PasswordField.svelte.d.ts +6 -0
  181. package/dist/components/fields/date-field-value.d.ts +2 -0
  182. package/dist/components/fields/date-field-value.js +13 -0
  183. package/dist/components/fields/json-value.d.ts +11 -0
  184. package/dist/components/fields/json-value.js +28 -0
  185. package/dist/components/json-schema-form-state.d.ts +37 -0
  186. package/dist/components/json-schema-form-state.js +168 -0
  187. package/dist/components/profile/ActivityTimeline.svelte +2 -2
  188. package/dist/components/record-detail.svelte.d.ts +19 -0
  189. package/dist/components/record-detail.svelte.js +34 -0
  190. package/dist/components/saved-list-views.js +29 -29
  191. package/dist/components/svar-grid-cells.d.ts +14 -0
  192. package/dist/components/svar-grid-cells.js +2 -0
  193. package/dist/components/svar-grid-contract.d.ts +80 -0
  194. package/dist/components/svar-grid-contract.js +159 -0
  195. package/dist/components/svar-grid-interactions.d.ts +54 -0
  196. package/dist/components/svar-grid-interactions.js +174 -0
  197. package/dist/components/svar-grid-loading.d.ts +40 -0
  198. package/dist/components/svar-grid-loading.js +180 -0
  199. package/dist/components/svar-grid-operations.d.ts +37 -0
  200. package/dist/components/svar-grid-operations.js +186 -0
  201. package/dist/components/svar-grid-panes.d.ts +34 -0
  202. package/dist/components/svar-grid-panes.js +66 -0
  203. package/dist/components/svar-grid-resource-loading.d.ts +18 -0
  204. package/dist/components/svar-grid-resource-loading.js +68 -0
  205. package/dist/components/svar-grid-resource-session.svelte.d.ts +29 -0
  206. package/dist/components/svar-grid-resource-session.svelte.js +61 -0
  207. package/dist/components/table-contract.d.ts +13 -0
  208. package/dist/components/table-contract.js +42 -0
  209. package/dist/components/task-utils.js +4 -2
  210. package/dist/components/ui/alert/alert-variants.d.ts +2 -3
  211. package/dist/components/ui/alert/alert-variants.js +1 -2
  212. package/dist/components/ui/alert/alert.svelte +4 -5
  213. package/dist/components/ui/alert/alert.svelte.d.ts +3 -8
  214. package/dist/components/ui/alert/index.js +0 -2
  215. package/dist/components/ui/avatar/avatar-variants.d.ts +2 -3
  216. package/dist/components/ui/avatar/avatar-variants.js +1 -2
  217. package/dist/components/ui/avatar/avatar.svelte +5 -6
  218. package/dist/components/ui/avatar/avatar.svelte.d.ts +3 -8
  219. package/dist/components/ui/badge/badge-variants.d.ts +2 -3
  220. package/dist/components/ui/badge/badge-variants.js +3 -2
  221. package/dist/components/ui/badge/badge.svelte +4 -5
  222. package/dist/components/ui/badge/badge.svelte.d.ts +3 -8
  223. package/dist/components/ui/badge/index.js +0 -2
  224. package/dist/components/ui/button/button-variants.d.ts +2 -3
  225. package/dist/components/ui/button/button-variants.js +5 -3
  226. package/dist/components/ui/button/button.svelte +100 -44
  227. package/dist/components/ui/button/button.svelte.d.ts +8 -12
  228. package/dist/components/ui/button/index.js +0 -2
  229. package/dist/components/ui/command/command-dialog.svelte +3 -1
  230. package/dist/components/ui/command/command-dialog.svelte.d.ts +1 -1
  231. package/dist/components/ui/command/command-group.svelte +4 -2
  232. package/dist/components/ui/command/command-item.svelte +4 -2
  233. package/dist/components/ui/command/command-separator.svelte +3 -1
  234. package/dist/components/ui/command/index.d.ts +5 -5
  235. package/dist/components/ui/input/input.svelte +41 -24
  236. package/dist/components/ui/input/input.svelte.d.ts +5 -4
  237. package/dist/components/ui/sheet/sheet.svelte +9 -3
  238. package/dist/components/ui/sheet/sheet.svelte.d.ts +1 -0
  239. package/dist/components/ui/textarea/textarea.svelte +2 -1
  240. package/dist/components/ui/tooltip/tooltip.svelte +4 -2
  241. package/dist/components.css +3079 -0
  242. package/dist/design-contract.d.ts +13 -0
  243. package/dist/design-contract.js +11 -0
  244. package/dist/design-system.d.ts +15 -0
  245. package/dist/design-system.js +7 -0
  246. package/dist/index.d.ts +15 -1
  247. package/dist/index.js +9 -0
  248. package/dist/inline-value.d.ts +5 -0
  249. package/dist/inline-value.js +24 -0
  250. package/dist/numeric-input.d.ts +2 -0
  251. package/dist/numeric-input.js +9 -0
  252. package/dist/page-chrome.css +12 -49
  253. package/dist/recipes.d.ts +4 -0
  254. package/dist/recipes.js +4 -0
  255. package/dist/rendering/index.d.ts +87 -0
  256. package/dist/rendering/index.js +117 -0
  257. package/dist/styled-system/css/conditions.js +36 -0
  258. package/dist/styled-system/css/css.d.ts +22 -0
  259. package/dist/styled-system/css/css.js +45 -0
  260. package/dist/styled-system/css/cva.d.ts +6 -0
  261. package/dist/styled-system/css/cva.js +87 -0
  262. package/dist/styled-system/css/cx.d.ts +5 -0
  263. package/dist/styled-system/css/cx.js +15 -0
  264. package/dist/styled-system/css/index.d.ts +5 -0
  265. package/dist/styled-system/css/index.js +4 -0
  266. package/dist/styled-system/css/sva.d.ts +4 -0
  267. package/dist/styled-system/css/sva.js +46 -0
  268. package/dist/styled-system/helpers.js +316 -0
  269. package/dist/styled-system/patterns/aspect-ratio.d.ts +20 -0
  270. package/dist/styled-system/patterns/aspect-ratio.js +38 -0
  271. package/dist/styled-system/patterns/bleed.d.ts +21 -0
  272. package/dist/styled-system/patterns/bleed.js +24 -0
  273. package/dist/styled-system/patterns/box.d.ts +20 -0
  274. package/dist/styled-system/patterns/box.js +15 -0
  275. package/dist/styled-system/patterns/center.d.ts +20 -0
  276. package/dist/styled-system/patterns/center.js +21 -0
  277. package/dist/styled-system/patterns/circle.d.ts +20 -0
  278. package/dist/styled-system/patterns/circle.js +25 -0
  279. package/dist/styled-system/patterns/container.d.ts +20 -0
  280. package/dist/styled-system/patterns/container.js +21 -0
  281. package/dist/styled-system/patterns/cq.d.ts +21 -0
  282. package/dist/styled-system/patterns/cq.js +21 -0
  283. package/dist/styled-system/patterns/divider.d.ts +22 -0
  284. package/dist/styled-system/patterns/divider.js +25 -0
  285. package/dist/styled-system/patterns/flex.d.ts +26 -0
  286. package/dist/styled-system/patterns/flex.js +26 -0
  287. package/dist/styled-system/patterns/float.d.ts +23 -0
  288. package/dist/styled-system/patterns/float.js +52 -0
  289. package/dist/styled-system/patterns/grid-item.d.ts +25 -0
  290. package/dist/styled-system/patterns/grid-item.js +25 -0
  291. package/dist/styled-system/patterns/grid.d.ts +24 -0
  292. package/dist/styled-system/patterns/grid.js +27 -0
  293. package/dist/styled-system/patterns/hstack.d.ts +21 -0
  294. package/dist/styled-system/patterns/hstack.js +24 -0
  295. package/dist/styled-system/patterns/index.d.ts +21 -0
  296. package/dist/styled-system/patterns/index.js +20 -0
  297. package/dist/styled-system/patterns/link-overlay.d.ts +20 -0
  298. package/dist/styled-system/patterns/link-overlay.js +24 -0
  299. package/dist/styled-system/patterns/spacer.d.ts +20 -0
  300. package/dist/styled-system/patterns/spacer.js +25 -0
  301. package/dist/styled-system/patterns/square.d.ts +20 -0
  302. package/dist/styled-system/patterns/square.js +24 -0
  303. package/dist/styled-system/patterns/stack.d.ts +23 -0
  304. package/dist/styled-system/patterns/stack.js +24 -0
  305. package/dist/styled-system/patterns/visually-hidden.d.ts +20 -0
  306. package/dist/styled-system/patterns/visually-hidden.js +18 -0
  307. package/dist/styled-system/patterns/vstack.d.ts +21 -0
  308. package/dist/styled-system/patterns/vstack.js +24 -0
  309. package/dist/styled-system/patterns/wrap.d.ts +24 -0
  310. package/dist/styled-system/patterns/wrap.js +25 -0
  311. package/dist/styled-system/recipes/content-header.d.ts +31 -0
  312. package/dist/styled-system/recipes/content-header.js +65 -0
  313. package/dist/styled-system/recipes/content-page.d.ts +34 -0
  314. package/dist/styled-system/recipes/content-page.js +43 -0
  315. package/dist/styled-system/recipes/create-recipe.js +82 -0
  316. package/dist/styled-system/recipes/index.d.ts +17 -0
  317. package/dist/styled-system/recipes/index.js +16 -0
  318. package/dist/styled-system/recipes/metric-block.d.ts +34 -0
  319. package/dist/styled-system/recipes/metric-block.js +76 -0
  320. package/dist/styled-system/recipes/product-list.d.ts +31 -0
  321. package/dist/styled-system/recipes/product-list.js +73 -0
  322. package/dist/styled-system/recipes/product-section.d.ts +31 -0
  323. package/dist/styled-system/recipes/product-section.js +49 -0
  324. package/dist/styled-system/recipes/product-settings-row.d.ts +34 -0
  325. package/dist/styled-system/recipes/product-settings-row.js +58 -0
  326. package/dist/styled-system/recipes/product-settings.d.ts +31 -0
  327. package/dist/styled-system/recipes/product-settings.js +57 -0
  328. package/dist/styled-system/recipes/product-status.d.ts +34 -0
  329. package/dist/styled-system/recipes/product-status.js +45 -0
  330. package/dist/styled-system/recipes/product-toolbar.d.ts +31 -0
  331. package/dist/styled-system/recipes/product-toolbar.js +41 -0
  332. package/dist/styled-system/recipes/product-workspace.d.ts +34 -0
  333. package/dist/styled-system/recipes/product-workspace.js +58 -0
  334. package/dist/styled-system/recipes/surface-metric.d.ts +38 -0
  335. package/dist/styled-system/recipes/surface-metric.js +63 -0
  336. package/dist/styled-system/recipes/surface-table.d.ts +34 -0
  337. package/dist/styled-system/recipes/surface-table.js +62 -0
  338. package/dist/styled-system/recipes/ui-badge.d.ts +31 -0
  339. package/dist/styled-system/recipes/ui-badge.js +38 -0
  340. package/dist/styled-system/recipes/ui-button.d.ts +32 -0
  341. package/dist/styled-system/recipes/ui-button.js +43 -0
  342. package/dist/styled-system/recipes/ui-input.d.ts +31 -0
  343. package/dist/styled-system/recipes/ui-input.js +49 -0
  344. package/dist/styled-system/recipes/ui-textarea.d.ts +31 -0
  345. package/dist/styled-system/recipes/ui-textarea.js +24 -0
  346. package/dist/styled-system/styles.css +1257 -0
  347. package/dist/styled-system/tokens/index.d.ts +9 -0
  348. package/dist/styled-system/tokens/index.js +268 -0
  349. package/dist/styled-system/tokens/tokens.d.ts +36 -0
  350. package/dist/styled-system/types/composition.d.ts +227 -0
  351. package/dist/styled-system/types/conditions.d.ts +236 -0
  352. package/dist/styled-system/types/csstype.d.ts +22570 -0
  353. package/dist/styled-system/types/index.d.ts +6 -0
  354. package/dist/styled-system/types/parts.d.ts +8 -0
  355. package/dist/styled-system/types/pattern.d.ts +78 -0
  356. package/dist/styled-system/types/prop-type.d.ts +223 -0
  357. package/dist/styled-system/types/recipe.d.ts +181 -0
  358. package/dist/styled-system/types/selectors.d.ts +59 -0
  359. package/dist/styled-system/types/static-css.d.ts +56 -0
  360. package/dist/styled-system/types/style-props.d.ts +8088 -0
  361. package/dist/styled-system/types/system-types.d.ts +151 -0
  362. package/dist/styles/aliases.css +49 -0
  363. package/dist/styles/compatibility.epilogue.css +384 -0
  364. package/dist/styles/compatibility.prelude.css +5513 -0
  365. package/dist/styles/conditional-states.css +28 -0
  366. package/dist/styles/conditional-utilities.css +22 -0
  367. package/dist/styles/recipes.css +1262 -0
  368. package/dist/types.d.ts +3 -3
  369. package/dist/utils.d.ts +1 -1
  370. package/dist/utils.js +1 -1
  371. package/package.json +38 -14
  372. package/styles-compatibility.json +12 -0
@@ -1,7 +1,12 @@
1
1
  <script lang="ts">
2
- import { useUpdate } from '@svadmin/core';
2
+ import { useUpdate, useResourceContract, captureAdminContext, captureAuthSession, useCan, HttpError, useTranslation } from '@svadmin/core';
3
3
  import type { FieldDefinition } from '@svadmin/core';
4
- import { Loader2 } from '@lucide/svelte';
4
+ import { definedReactiveOptions } from '@svadmin/core/options';
5
+ import { untrack } from 'svelte';
6
+ import { Check, X, Loader2 } from '@lucide/svelte';
7
+ import { Button } from './ui/button/index.js';
8
+ import FieldDisplay from './FieldDisplay.svelte';
9
+ import { inlineDisplayValue, parseInlineValue } from '../inline-value';
5
10
 
6
11
  interface Props {
7
12
  resourceName: string;
@@ -14,53 +19,103 @@
14
19
 
15
20
  let { resourceName, recordId, field, value, onSave }: Props = $props();
16
21
 
22
+ const context = captureAdminContext();
23
+ const binding = useResourceContract(() => resourceName);
24
+ const i18n = useTranslation();
25
+ const permission = useCan(() => ({ resource: resourceName, action: 'edit', id: recordId }));
26
+ const { mutation } = useUpdate(definedReactiveOptions({
27
+ get resource() { return binding.resource; },
28
+ get id() { return recordId; },
29
+ }));
30
+ const display = $derived(inlineDisplayValue(field.type, value));
31
+ const session = $derived(captureAuthSession(context.authProvider));
32
+ const editable = $derived(session.available && context.getResource(resourceName).canEdit !== false && field.showInEdit !== false &&
33
+ field.key !== 'id' && permission.allowed === true && display !== undefined);
34
+ const scope = $derived({
35
+ contract: binding.resource, id: recordId, field: field.key, type: field.type, editable,
36
+ provider: context.providers?.[binding.dataProviderName], meta: binding.meta,
37
+ tenant: context.tenantCacheKey?.__svadminTenant,
38
+ auth: context.authProvider, session,
39
+ });
17
40
  let editing = $state(false);
18
41
  let editValue = $state('');
19
42
  let inputRef = $state<HTMLInputElement | null>(null);
43
+ let editorRef = $state<HTMLDivElement | null>(null);
20
44
  let saving = $state(false);
21
- let savePending = false;
22
- const displayValue = $derived(String(value ?? ''));
45
+ let failure = $state<'input' | 'request' | null>(null);
46
+ let active: object | undefined;
47
+ let editingScope = $state.raw<typeof scope>();
23
48
  const fieldLabel = $derived(field.label || field.key);
24
49
 
25
- const { mutation } = useUpdate({ get resource() { return resourceName; } });
50
+ $effect(() => {
51
+ void scope;
52
+ editing = false;
53
+ editValue = '';
54
+ saving = false;
55
+ failure = null;
56
+ active = undefined;
57
+ editingScope = undefined;
58
+ });
59
+ $effect(() => () => { active = undefined; });
60
+ $effect(() => {
61
+ const node = inputRef;
62
+ if (editing && node) untrack(() => node.focus());
63
+ });
26
64
 
27
65
  function startEdit() {
28
- if (field.type === 'number' || field.type === 'text' || field.type === 'url' || field.type === 'email') {
29
- editing = true;
30
- editValue = displayValue;
31
- // Focus input on next tick
32
- setTimeout(() => inputRef?.focus(), 0);
33
- }
66
+ if (!editable || !display || saving || !session.isCurrent()) return;
67
+ editingScope = scope;
68
+ failure = null;
69
+ editValue = display.text;
70
+ editing = true;
34
71
  }
35
72
 
36
73
  async function save() {
37
- if (!editing || saving || savePending) return;
38
- const newValue = field.type === 'number' ? (editValue.trim() === '' ? null : (() => { const n = Number(editValue); return isNaN(n) ? value : n; })()) : editValue;
39
- if (newValue === value) {
74
+ if (!editing || saving || !editable || editingScope !== scope || !session.isCurrent()) return;
75
+ let newValue: string | number | null;
76
+ try { newValue = parseInlineValue(field.type, editValue); }
77
+ catch { failure = 'input'; return; }
78
+ if (newValue === display?.value) {
40
79
  editing = false;
41
80
  return;
42
81
  }
43
- savePending = true;
82
+ const current = scope;
83
+ const fieldKey = field.key;
84
+ const callback = onSave;
85
+ const token = {};
86
+ active = token;
44
87
  saving = true;
88
+ failure = null;
89
+ let succeeded = false;
90
+ let savedValue: unknown;
45
91
  try {
46
- await mutation.mutateAsync({
47
- id: recordId,
48
- resource: resourceName,
49
- variables: { [field.key]: newValue },
92
+ const result = await mutation.mutateAsync({
93
+ variables: { [fieldKey]: newValue }, dataProviderName: binding.dataProviderName,
50
94
  });
51
- editing = false;
52
- onSave?.(newValue);
53
- } catch {
54
- // Keep editing on error
95
+ if (active === token && scope === current && current.session.isCurrent()) {
96
+ editing = false;
97
+ succeeded = true;
98
+ savedValue = result.data[fieldKey];
99
+ }
100
+ } catch (error) {
101
+ if (active === token && scope === current && current.session.isCurrent()) {
102
+ failure = error instanceof HttpError && error.code === 'INVALID_RESOURCE_INPUT' ? 'input' : 'request';
103
+ }
55
104
  } finally {
56
- saving = false;
57
- savePending = false;
105
+ if (active === token && scope === current && current.session.isCurrent()) {
106
+ active = undefined;
107
+ saving = false;
108
+ }
58
109
  }
110
+ if (succeeded && scope === current && current.session.isCurrent()) callback?.(savedValue);
59
111
  }
60
112
 
61
113
  function cancel() {
114
+ if (saving) return;
62
115
  editing = false;
63
- editValue = displayValue;
116
+ failure = null;
117
+ editingScope = undefined;
118
+ editValue = display?.text ?? '';
64
119
  }
65
120
 
66
121
  function handleKeydown(e: KeyboardEvent) {
@@ -71,38 +126,53 @@
71
126
  if (e.key === 'Escape') cancel();
72
127
  }
73
128
 
74
- function handleBlur() {
75
- if (!savePending) save();
129
+ function handleBlur(event: FocusEvent) {
130
+ if (event.relatedTarget instanceof Node && editorRef?.contains(event.relatedTarget)) return;
131
+ if (!saving) void save();
76
132
  }
77
133
  </script>
78
134
 
79
- {#if editing}
80
- <div class="svadmin-u-d89972fe17d6 svadmin-u-60fbb7713999 svadmin-u-3960ffc248d9 svadmin-u-6da6a3c3f741">
135
+ {#if editing && editingScope === scope && session.isCurrent()}
136
+ <div bind:this={editorRef} class="svadmin-u-d89972fe17d6 svadmin-u-60fbb7713999 svadmin-u-3960ffc248d9 svadmin-u-6da6a3c3f741">
81
137
  <input
82
138
  bind:this={inputRef}
83
- type={field.type === 'number' ? 'number' : 'text'}
139
+ type="text"
140
+ inputmode={field.type === 'number' ? 'decimal' : field.type === 'email' ? 'email' : field.type === 'url' ? 'url' : 'text'}
84
141
  bind:value={editValue}
85
142
  onkeydown={handleKeydown}
86
143
  onblur={handleBlur}
87
144
  disabled={saving}
88
145
  aria-label={fieldLabel}
89
- class="svadmin-u-d0a52b312f7d svadmin-u-6da6a3c3f741 svadmin-u-07389a777c1f svadmin-u-ca6bcd4b6f3f svadmin-u-e6f9e383a762 svadmin-u-d5eab218aa34 svadmin-u-fc7473ca09eb svadmin-u-df37b1fd9495 svadmin-u-3daca9af0861 svadmin-u-f42e9fee68a1 svadmin-u-608dd26cd5ba svadmin-u-1a5f9520d7fa svadmin-u-0fe7d7d814d0 svadmin-u-d463b664011d"
146
+ aria-invalid={failure !== null}
147
+ class="svadmin-u-d0a52b312f7d svadmin-u-7e0b7cdf1a94 svadmin-u-36e579c0b41c svadmin-u-07389a777c1f svadmin-u-ca6bcd4b6f3f svadmin-u-e6f9e383a762 svadmin-u-d5eab218aa34 svadmin-u-fc7473ca09eb svadmin-u-df37b1fd9495 svadmin-u-3daca9af0861 svadmin-u-f42e9fee68a1 svadmin-u-608dd26cd5ba svadmin-u-1a5f9520d7fa svadmin-u-0fe7d7d814d0 svadmin-u-d463b664011d"
90
148
  />
91
- {#if saving}
92
- <span class="svadmin-u-da4dbfbc4fdc svadmin-u-7b2d63937d23 svadmin-u-60fbb7713999 svadmin-u-3960ffc248d9 svadmin-u-a4326536b8f5" role="status" aria-label="Saving...">
93
- <Loader2 class="svadmin-u-783b0d9d1e2c svadmin-u-afbdd13a380e svadmin-u-bfa603190748" aria-hidden="true" />
94
- </span>
95
- {/if}
149
+ <Button type="button" variant="ghost" size="icon-sm" disabled={saving} title={i18n.t('common.save')}
150
+ aria-label={i18n.t('common.save')} aria-busy={saving} onclick={save}>
151
+ {#if saving}
152
+ <Loader2 class="svadmin-u-11e59c6d5f6b svadmin-u-dc7972ebf3f3 svadmin-u-afbdd13a380e" role="status" aria-label="Saving..." />
153
+ {:else}
154
+ <Check class="svadmin-u-11e59c6d5f6b svadmin-u-dc7972ebf3f3" />
155
+ {/if}
156
+ </Button>
157
+ <Button type="button" variant="ghost" size="icon-sm" disabled={saving} title={i18n.t('common.cancel')}
158
+ aria-label={i18n.t('common.cancel')} onclick={cancel}>
159
+ <X class="svadmin-u-11e59c6d5f6b svadmin-u-dc7972ebf3f3" />
160
+ </Button>
96
161
  </div>
97
- {:else}
98
- <span
162
+ {#if failure}
163
+ <p role="alert">{i18n.t(failure === 'input' ? 'validation.invalidFormat' : 'common.operationFailed')}</p>
164
+ {/if}
165
+ {:else if editable && display}
166
+ <button type="button"
99
167
  class="svadmin-u-52083e7da442 svadmin-u-3960ffc248d9 svadmin-u-34516836730d svadmin-u-07389a777c1f svadmin-u-45d828117213 svadmin-u-465609a240a8 svadmin-u-76610325273f svadmin-u-fc7473ca09eb svadmin-u-d4108abe6359 svadmin-u-2a6233dc87a9 svadmin-u-f10f771f87e9 svadmin-u-793c80e97ffb svadmin-u-9c1295a6914a svadmin-u-ce4edccf4cbb svadmin-u-ceb69a6b0e5f"
100
168
  ondblclick={startEdit}
101
- title={`Double-click to edit ${fieldLabel}`}
102
- role="button"
103
- tabindex="0"
169
+ onclick={startEdit}
170
+ title={`${i18n.t('common.edit')} ${fieldLabel}`}
171
+ aria-label={`${i18n.t('common.edit')} ${fieldLabel}`}
104
172
  onkeydown={(e) => { if (e.key === 'Enter' || e.key === 'F2') { e.preventDefault(); startEdit(); } }}
105
173
  >
106
- {value != null && value !== '' ? String(value) : '—'}
107
- </span>
174
+ {display.text || '—'}
175
+ </button>
176
+ {:else}
177
+ <FieldDisplay type={field.type} {value} options={field.options} resourceName={field.resource} />
108
178
  {/if}
@@ -1,13 +1,32 @@
1
1
  <script lang="ts">
2
+ import { useTranslation } from '@svadmin/core/i18n';
2
3
  import { Button } from './ui/button/index.js';
3
- import { Loader2 } from '@lucide/svelte';
4
+ import { Loader2, Plus, Trash2 } from '@lucide/svelte';
4
5
  import { cn } from '../utils.js';
6
+ import { onDestroy, untrack } from 'svelte';
7
+ import {
8
+ initializeSchemaForm, schemaFormArrayItem, schemaFormEnumIndex,
9
+ schemaFormEnumValue, schemaFormSnapshot, writeSchemaFormPath,
10
+ type JsonSchemaFormSchema,
11
+ } from './json-schema-form-state.js';
12
+
13
+ import { readRecursiveSchemaForm, validateRecursiveSchemaForm, schemaFormPointer } from './enterprise/recursive-schema-form.js';
14
+ import { parseSchemaNumber, type SchemaFormIssue } from './enterprise/json-schema-form.js';
15
+ type JsonSchema = JsonSchemaFormSchema;
5
16
 
6
17
  interface Props {
7
- schema: Record<string, unknown>;
18
+ schema: JsonSchema;
8
19
  value?: Record<string, unknown>;
9
20
  onsubmit?: (data: Record<string, unknown>) => void | Promise<void>;
10
21
  submitText?: string;
22
+ disabled?: boolean;
23
+ readonly?: boolean;
24
+ /** 只决定此实例文案;不修改全局语言。 */
25
+ locale?: string;
26
+ onerror?: (error: unknown) => void;
27
+ onvalidationerror?: (issues: SchemaFormIssue[]) => void;
28
+ /** Use a unique stable prefix when several schema forms share a page. */
29
+ idPrefix?: string;
11
30
  class?: string;
12
31
  }
13
32
 
@@ -16,134 +35,276 @@
16
35
  value = $bindable({}),
17
36
  onsubmit,
18
37
  submitText = 'Submit Form',
38
+ disabled = false,
39
+ readonly = false,
40
+ locale,
41
+ onerror,
42
+ onvalidationerror,
43
+ idPrefix,
19
44
  class: className = '',
20
45
  }: Props = $props();
21
46
 
47
+ const i18n = useTranslation();
48
+ const instanceId = $props.id();
49
+ const prefix = $derived(idPrefix ?? `json-form-${instanceId}`);
50
+ const isZh = $derived((locale ?? i18n.locale).startsWith('zh'));
51
+ const labels = $derived(isZh ? {
52
+ add: '添加项目', remove: '删除', empty: '暂无项目',
53
+ failed: '提交未完成,请检查状态后重试。', invalid: '请检查表单输入。',
54
+ } : {
55
+ add: 'Add item', remove: 'Remove item', empty: 'No items',
56
+ failed: 'Submission did not complete. Check its status before retrying.', invalid: 'Check the form input.',
57
+ });
58
+ const model = $derived(readRecursiveSchemaForm(schema));
59
+ let validationIssues = $state<SchemaFormIssue[]>([]);
60
+ let parseIssues = $state<SchemaFormIssue[]>([]);
61
+ let internalValue: Record<string, unknown> | undefined;
22
62
  let isSubmitting = $state(false);
23
-
24
- interface FieldMeta {
25
- key: string;
26
- title: string;
27
- description?: string;
28
- type: string;
29
- enum?: Array<string | number>;
30
- required?: boolean;
31
- default?: unknown;
32
- }
33
-
34
- const properties = $derived.by<FieldMeta[]>(() => {
35
- const propsObj = (schema.properties ?? {}) as Record<string, Record<string, unknown>>;
36
- const requiredKeys = Array.isArray(schema.required) ? (schema.required as string[]) : [];
37
-
38
- return Object.entries(propsObj).map(([key, propDef]) => ({
39
- key,
40
- title: String(propDef.title ?? key),
41
- description: propDef.description ? String(propDef.description) : undefined,
42
- type: String(propDef.type ?? 'string'),
43
- enum: Array.isArray(propDef.enum) ? (propDef.enum as Array<string | number>) : undefined,
44
- required: requiredKeys.includes(key),
45
- default: propDef.default,
46
- }));
63
+ let failure = $state<'invalid' | 'failed' | null>(null);
64
+ let formElement: HTMLFormElement | undefined;
65
+ let destroyed = false;
66
+ let authorityRevision = 0;
67
+ let identity: readonly unknown[] = [];
68
+ const prepared = $derived.by(() => {
69
+ try {
70
+ if (model.issues.length) return { ok: false as const };
71
+ return { ok: true as const, value: initializeSchemaForm(schema, value) };
72
+ }
73
+ catch { return { ok: false as const }; }
74
+ });
75
+ const locked = $derived(disabled || readonly || isSubmitting || !prepared.ok);
76
+ // 按键是否存在初始化,不能每次输入都用 ?? 把清空的默认值补回来。
77
+ $effect.pre(() => {
78
+ if (prepared.ok && prepared.value !== value) value = prepared.value;
79
+ });
80
+ $effect.pre(() => {
81
+ const next = [schema, value, disabled, readonly, onsubmit];
82
+ untrack(() => {
83
+ if (next.some((part, index) => part !== identity[index])) {
84
+ authorityRevision += 1;
85
+ failure = null;
86
+ validationIssues = [];
87
+ if (schema !== identity[0] || value !== internalValue) parseIssues = [];
88
+ internalValue = undefined;
89
+ }
90
+ identity = next;
91
+ });
47
92
  });
93
+ onDestroy(() => { destroyed = true; });
48
94
 
49
- async function handleSubmit(e: SubmitEvent) {
50
- e.preventDefault();
95
+ function editable(): boolean {
96
+ return !destroyed && !disabled && !readonly && !isSubmitting && prepared.ok
97
+ && !formElement?.closest('fieldset[disabled]');
98
+ }
99
+ function nodeType(node: JsonSchema): string | undefined {
100
+ return Array.isArray(node.type) ? node.type.find(type => type !== 'null') : node.type;
101
+ }
102
+ function choices(node: JsonSchema): JsonSchema['enum'] {
103
+ return node.enum ?? (Object.hasOwn(node, 'const') ? [node.const ?? null] : undefined);
104
+ }
105
+ function pathReadonly(path: readonly string[]): boolean {
106
+ let node: JsonSchema | undefined = schema;
107
+ if (node.readOnly) return true;
108
+ for (const key of path) {
109
+ node = node && (nodeType(node) === 'array' ? node.items : node.properties?.[key]);
110
+ if (node?.readOnly) return true;
111
+ }
112
+ return false;
113
+ }
114
+ function invalid(issues: SchemaFormIssue[]): void {
115
+ failure = 'invalid';
116
+ validationIssues = issues;
117
+ try { onvalidationerror?.(issues); } catch { /* Observers do not authorize submission. */ }
118
+ }
119
+ function fieldInvalid(path: readonly string[]): boolean {
120
+ return [...validationIssues, ...parseIssues].some(issue => issue.path === schemaFormPointer(path));
121
+ }
122
+ function writeNumber(path: string[], input: HTMLInputElement): void {
123
+ if (!editable() || pathReadonly(path)) return;
124
+ const pointer = schemaFormPointer(path);
125
+ parseIssues = parseIssues.filter(issue => issue.path !== pointer);
126
+ try {
127
+ if (input.validity.badInput) throw new Error('Invalid numeric input');
128
+ writePath(path, parseSchemaNumber(input.value));
129
+ } catch {
130
+ parseIssues = [...parseIssues, { path: pointer, code: 'invalid-value' }];
131
+ invalid(parseIssues);
132
+ }
133
+ }
134
+ function readPath(path: string[]): unknown {
135
+ return path.reduce<unknown>((current, key) => (
136
+ current && typeof current === 'object' && Object.hasOwn(current, key)
137
+ ? (current as Record<string, unknown>)[key] : undefined
138
+ ), prepared.ok ? prepared.value : {});
139
+ }
140
+ function writePath(path: string[], nextValue: unknown): boolean {
141
+ if (!editable() || !prepared.ok || pathReadonly(path)) return false;
142
+ try {
143
+ value = writeSchemaFormPath(prepared.value, path, nextValue);
144
+ // Capture the actual bindable value after Svelte wraps it, not its raw source.
145
+ internalValue = value;
146
+ failure = null;
147
+ validationIssues = [];
148
+ return true;
149
+ }
150
+ catch { failure = 'invalid'; return false; }
151
+ }
152
+ function choose(path: string[], raw: string, choices: JsonSchema['enum']): void {
153
+ if (!editable()) return;
154
+ try { writePath(path, schemaFormEnumValue(choices ?? [], raw)); }
155
+ catch { failure = 'invalid'; }
156
+ }
157
+ function addArrayItem(path: string[], itemSchema: JsonSchema): void {
158
+ if (!editable()) return;
159
+ const current = readPath(path);
160
+ try { writePath(path, [...(Array.isArray(current) ? current : []), schemaFormArrayItem(itemSchema)]); }
161
+ catch { failure = 'invalid'; }
162
+ }
163
+ function removeArrayItem(path: string[], index: number): void {
164
+ if (!editable()) return;
165
+ const current = readPath(path);
166
+ if (!Array.isArray(current) || !Number.isSafeInteger(index) || index < 0 || index >= current.length) return;
167
+ const prefix = schemaFormPointer(path) + '/';
168
+ const nextIssues = parseIssues.flatMap(issue => {
169
+ if (!issue.path.startsWith(prefix)) return [issue];
170
+ const tail = issue.path.slice(prefix.length);
171
+ const separator = tail.indexOf('/');
172
+ const segment = separator < 0 ? tail : tail.slice(0, separator);
173
+ if (!/^(0|[1-9][0-9]*)$/u.test(segment)) return [issue];
174
+ const itemIndex = Number(segment);
175
+ if (itemIndex === index) return [];
176
+ if (itemIndex < index) return [issue];
177
+ return [{ ...issue, path: prefix + String(itemIndex - 1) + (separator < 0 ? '' : tail.slice(separator)) }];
178
+ });
179
+ // Retire only the removed item's error and shift surviving descendants with their
180
+ // array item. A rejected readonly/disabled write must not clear any error.
181
+ if (writePath(path, current.filter((_, itemIndex) => itemIndex !== index))) parseIssues = nextIssues;
182
+ }
183
+ async function handleSubmit(event: SubmitEvent): Promise<void> {
184
+ event.preventDefault();
185
+ // 同步置锁,防止同一帧的双击/重入 submit;遵循宿主 fieldset 的预览禁用状态;权限仍需服务端校验。
186
+ if (!editable() || !prepared.ok || !onsubmit) return;
187
+ const problems = [...parseIssues, ...validateRecursiveSchemaForm(model, prepared.value)];
188
+ if (problems.length) { invalid(problems); return; }
189
+ if (formElement && !formElement.checkValidity()) { invalid([{ path: '', code: 'invalid-value' }]); return; }
190
+ let payload: Record<string, unknown>;
191
+ try { payload = schemaFormSnapshot(prepared.value); }
192
+ catch { invalid([{ path: '', code: 'invalid-value' }]); return; }
193
+ const currentValue = value, currentSchema = schema, handler = onsubmit, revision = authorityRevision;
194
+ const fingerprint = JSON.stringify(payload);
195
+ failure = null;
51
196
  isSubmitting = true;
52
197
  try {
53
- await onsubmit?.(value);
198
+ await handler(payload);
199
+ } catch (error) {
200
+ // 回调只能拿到副本;被替换/卸载实例的失败不能污染新的表单上下文。
201
+ if (!destroyed && revision === authorityRevision && !disabled && !readonly && currentValue === value && currentSchema === schema && handler === onsubmit) {
202
+ try {
203
+ if (JSON.stringify(schemaFormSnapshot(prepared.ok ? prepared.value : value)) === fingerprint) {
204
+ failure = 'failed';
205
+ try { onerror?.(error); } catch { /* 错误观察者不改变提交状态。 */ }
206
+ }
207
+ } catch { /* 新上下文不再是可比较的 JSON 草稿,不发布旧错误。 */ }
208
+ }
54
209
  } finally {
55
- isSubmitting = false;
210
+ if (!destroyed) isSubmitting = false;
56
211
  }
57
212
  }
58
213
 
59
- function updateValue(key: string, val: unknown) {
60
- value = {
61
- ...value,
62
- [key]: val,
63
- };
64
- }
65
214
  </script>
66
215
 
67
216
  <form
217
+ novalidate
218
+ data-testid="json-schema-form"
219
+ bind:this={formElement}
220
+ aria-busy={isSubmitting}
68
221
  onsubmit={handleSubmit}
69
222
  class={cn('svadmin-u-3e7ce58d64fa svadmin-u-a217b4eaa918 svadmin-u-ca6bcd4b6f3f svadmin-u-18049387f0af svadmin-u-cd0ad9a56558 svadmin-u-0478c89a150f svadmin-u-cef5b893cf23 svadmin-u-359090c2d529', className)}
70
223
  >
71
224
  {#if schema.title}
72
225
  <div class="svadmin-u-f4cc511ff0c1 svadmin-u-65fdbade2025 svadmin-u-05faf5c801ff">
73
226
  <h3 class="svadmin-u-fc7473ca09eb svadmin-u-e83a7042bc91 svadmin-u-d4108abe6359">{schema.title}</h3>
74
- {#if schema.description}
75
- <p class="svadmin-u-359090c2d529 svadmin-u-bfa603190748 svadmin-u-15e1b1f444fe">{schema.description}</p>
76
- {/if}
227
+ {#if schema.description}<p class="svadmin-u-359090c2d529 svadmin-u-bfa603190748 svadmin-u-15e1b1f444fe">{schema.description}</p>{/if}
77
228
  </div>
78
229
  {/if}
79
230
 
80
- <div class="svadmin-u-9c6cdfa2ba3d">
81
- {#each properties as field (field.key)}
231
+ {#if !prepared.ok || failure}
232
+ <p role="alert" data-testid="schema-form-errors">{labels[!prepared.ok ? 'invalid' : failure ?? 'invalid']}</p>
233
+ {/if}
234
+
235
+ {#snippet renderField(node: JsonSchema, path: string[], title: string, required = false)}
236
+ {@const current = readPath(path)}
237
+ {@const options = choices(node)}
238
+ {@const type = nodeType(node)}
239
+ {@const fieldLocked = locked || pathReadonly(path)}
240
+ {@const id = `${prefix}_${path.map(encodeURIComponent).join('/')}`}
241
+ {#if type === 'object' || node.properties}
242
+ <fieldset class="svadmin-u-da7c36cd8867 svadmin-u-421ac2be5045">
243
+ <legend class="svadmin-u-0214b4b355d1 svadmin-u-2689f3958069">{title}</legend>
244
+ {#if node.description}<p class="svadmin-u-d058ca6de60f svadmin-u-bfa603190748">{node.description}</p>{/if}
245
+ <div class="svadmin-u-9c6cdfa2ba3d">
246
+ {#each Object.entries(node.properties ?? {}) as [key, child] (key)}
247
+ {@render renderField(child, [...path, key], child.title ?? key, node.required?.includes(key) ?? false)}
248
+ {/each}
249
+ </div>
250
+ </fieldset>
251
+ {:else if type === 'array'}
252
+ {@const items = Array.isArray(current) ? current : []}
253
+ <fieldset class="svadmin-u-da7c36cd8867 svadmin-u-421ac2be5045">
254
+ <legend class="svadmin-u-0214b4b355d1 svadmin-u-2689f3958069">{title}</legend>
255
+ {#if node.description}<p class="svadmin-u-d058ca6de60f svadmin-u-bfa603190748">{node.description}</p>{/if}
256
+ {#each items as _, index (index)}
257
+ {@render renderField(node.items ?? { type: 'string' }, [...path, String(index)], `${title} ${index + 1}`, true)}
258
+ <Button type="button" disabled={fieldLocked} variant="ghost" size="sm" onclick={() => removeArrayItem(path, index)}>
259
+ <Trash2 class="svadmin-u-7fc7f732bf7e svadmin-u-bf600f8e029c" /> {labels.remove}
260
+ </Button>
261
+ {:else}
262
+ <span class="svadmin-u-bfa603190748">{labels.empty}</span>
263
+ {/each}
264
+ <Button type="button" disabled={fieldLocked} variant="outline" size="sm" onclick={() => addArrayItem(path, node.items ?? { type: 'string' })}>
265
+ <Plus class="svadmin-u-7fc7f732bf7e svadmin-u-bf600f8e029c" /> {labels.add}
266
+ </Button>
267
+ </fieldset>
268
+ {:else}
82
269
  <div class="svadmin-u-da7c36cd8867">
83
- <label for="json_field_{field.key}" class="svadmin-u-0214b4b355d1 svadmin-u-2689f3958069 svadmin-u-d4108abe6359">
84
- {field.title}
85
- {#if field.required}
86
- <span class="svadmin-u-811148b13d1e">*</span>
87
- {/if}
270
+ <label for={id} class="svadmin-u-0214b4b355d1 svadmin-u-2689f3958069 svadmin-u-d4108abe6359">
271
+ {title}{#if required}<span class="svadmin-u-811148b13d1e">*</span>{/if}
88
272
  </label>
89
-
90
- {#if field.description}
91
- <p class="svadmin-u-d058ca6de60f svadmin-u-bfa603190748">{field.description}</p>
92
- {/if}
93
-
94
- {#if field.enum}
95
- <select
96
- id="json_field_{field.key}"
97
- required={field.required}
98
- value={String(value[field.key] ?? field.default ?? '')}
99
- onchange={(e) => updateValue(field.key, e.currentTarget.value)}
100
- class="svadmin-u-ed8a5df7b2fb svadmin-u-6da6a3c3f741 svadmin-u-421ac2be5045 svadmin-u-ca6bcd4b6f3f svadmin-u-e5795dad4d22 svadmin-u-e6f9e383a762 svadmin-u-d5eab218aa34 svadmin-u-359090c2d529 svadmin-u-f10f771f87e9 svadmin-u-3e94a98e1466 svadmin-u-9c1295a6914a"
101
- >
102
- <option value="">Select an option...</option>
103
- {#each field.enum as option (option)}
104
- <option value={String(option)}>{option}</option>
105
- {/each}
273
+ {#if node.description}<p class="svadmin-u-d058ca6de60f svadmin-u-bfa603190748">{node.description}</p>{/if}
274
+ {#if options}
275
+ <select id={id} name={path.join('.')} aria-invalid={fieldInvalid(path)} disabled={fieldLocked} required={required} value={schemaFormEnumIndex(options, current)} onchange={(event) => choose(path, event.currentTarget.value, options)} class="svadmin-u-ed8a5df7b2fb svadmin-u-6da6a3c3f741 svadmin-u-421ac2be5045 svadmin-u-ca6bcd4b6f3f svadmin-u-e5795dad4d22 svadmin-u-e6f9e383a762 svadmin-u-d5eab218aa34 svadmin-u-359090c2d529">
276
+ <option value="">{i18n.t('common.selectOption')}</option>
277
+ {#each options as option, optionIndex (optionIndex)}<option value={String(optionIndex)}>{String(option)}</option>{/each}
106
278
  </select>
107
- {:else if field.type === 'boolean'}
108
- <div class="svadmin-u-60fbb7713999 svadmin-u-3960ffc248d9 svadmin-u-77a2a20e90d4 svadmin-u-6b7d6e21ccbd">
109
- <input
110
- id="json_field_{field.key}"
111
- type="checkbox"
112
- checked={Boolean(value[field.key] ?? field.default)}
113
- onchange={(e) => updateValue(field.key, e.currentTarget.checked)}
114
- class="svadmin-u-11e59c6d5f6b svadmin-u-dc7972ebf3f3 svadmin-u-07389a777c1f svadmin-u-18049387f0af svadmin-u-20aaf08a7ed1 svadmin-u-4df2b13689a4 svadmin-u-34516836730d"
115
- />
116
- <span class="svadmin-u-359090c2d529 svadmin-u-bfa603190748">{field.title}</span>
117
- </div>
118
- {:else if field.type === 'number' || field.type === 'integer'}
119
- <input
120
- id="json_field_{field.key}"
121
- type="number"
122
- required={field.required}
123
- value={Number(value[field.key] ?? field.default ?? 0)}
124
- oninput={(e) => updateValue(field.key, Number(e.currentTarget.value))}
125
- class="svadmin-u-ed8a5df7b2fb svadmin-u-6da6a3c3f741 svadmin-u-421ac2be5045 svadmin-u-ca6bcd4b6f3f svadmin-u-e5795dad4d22 svadmin-u-e6f9e383a762 svadmin-u-d5eab218aa34 svadmin-u-359090c2d529 svadmin-u-f10f771f87e9 svadmin-u-3e94a98e1466 svadmin-u-9c1295a6914a"
126
- />
279
+ {:else if type === 'boolean'}
280
+ <input id={id} name={path.join('.')} aria-invalid={fieldInvalid(path)} disabled={fieldLocked} type="checkbox" checked={Boolean(current)} onchange={(event) => writePath(path, event.currentTarget.checked)} />
281
+ {:else if type === 'number' || type === 'integer'}
282
+ <input id={id} name={path.join('.')} aria-invalid={fieldInvalid(path)} disabled={fieldLocked} type="number" step={type === 'integer' ? 1 : 'any'} required={required} value={current === undefined ? '' : String(current)} oninput={(event) => writeNumber(path, event.currentTarget)} class="svadmin-u-ed8a5df7b2fb svadmin-u-6da6a3c3f741 svadmin-u-421ac2be5045 svadmin-u-ca6bcd4b6f3f svadmin-u-e5795dad4d22 svadmin-u-e6f9e383a762 svadmin-u-d5eab218aa34 svadmin-u-359090c2d529" />
127
283
  {:else}
128
- <input
129
- id="json_field_{field.key}"
130
- type="text"
131
- required={field.required}
132
- value={String(value[field.key] ?? field.default ?? '')}
133
- oninput={(e) => updateValue(field.key, e.currentTarget.value)}
134
- class="svadmin-u-ed8a5df7b2fb svadmin-u-6da6a3c3f741 svadmin-u-421ac2be5045 svadmin-u-ca6bcd4b6f3f svadmin-u-e5795dad4d22 svadmin-u-e6f9e383a762 svadmin-u-d5eab218aa34 svadmin-u-359090c2d529 svadmin-u-f10f771f87e9 svadmin-u-3e94a98e1466 svadmin-u-9c1295a6914a"
135
- />
284
+ <input id={id} name={path.join('.')} aria-invalid={fieldInvalid(path)} disabled={fieldLocked} type="text" required={required} value={String(current ?? '')} oninput={(event) => writePath(path, event.currentTarget.value)} class="svadmin-u-ed8a5df7b2fb svadmin-u-6da6a3c3f741 svadmin-u-421ac2be5045 svadmin-u-ca6bcd4b6f3f svadmin-u-e5795dad4d22 svadmin-u-e6f9e383a762 svadmin-u-d5eab218aa34 svadmin-u-359090c2d529" />
136
285
  {/if}
137
286
  </div>
287
+ {/if}
288
+ {/snippet}
289
+
290
+ <fieldset class="schema-form-fields svadmin-u-3e7ce58d64fa" disabled={locked}>
291
+ {#if prepared.ok}
292
+ <div class="svadmin-u-9c6cdfa2ba3d">
293
+ {#each Object.entries(schema.properties ?? {}) as [key, node] (key)}
294
+ {@render renderField(node, [key], node.title ?? key, schema.required?.includes(key) ?? false)}
138
295
  {/each}
139
296
  </div>
140
297
 
298
+ {/if}
141
299
  <div class="svadmin-u-173fa8f06789 svadmin-u-b950dda299d3 svadmin-u-05faf5c801ff svadmin-u-60fbb7713999 svadmin-u-77c08e015d14">
142
- <Button type="submit" size="sm" disabled={isSubmitting} class="svadmin-u-44ee8ba0a421 svadmin-u-25effcb585ab">
143
- {#if isSubmitting}
144
- <Loader2 class="svadmin-u-7fc7f732bf7e svadmin-u-bf600f8e029c svadmin-u-afbdd13a380e" />
145
- {/if}
300
+ <Button type="submit" size="sm" disabled={locked} class="svadmin-u-44ee8ba0a421 svadmin-u-25effcb585ab">
301
+ {#if isSubmitting}<Loader2 class="svadmin-u-7fc7f732bf7e svadmin-u-bf600f8e029c svadmin-u-afbdd13a380e" />{/if}
146
302
  {submitText}
147
303
  </Button>
148
304
  </div>
305
+ </fieldset>
149
306
  </form>
307
+
308
+ <style>
309
+ .schema-form-fields { min-width: 0; margin: 0; padding: 0; border: 0; }
310
+ </style>
@@ -1,8 +1,19 @@
1
+ import { type JsonSchemaFormSchema } from './json-schema-form-state.js';
2
+ import { type SchemaFormIssue } from './enterprise/json-schema-form.js';
3
+ type JsonSchema = JsonSchemaFormSchema;
1
4
  interface Props {
2
- schema: Record<string, unknown>;
5
+ schema: JsonSchema;
3
6
  value?: Record<string, unknown>;
4
7
  onsubmit?: (data: Record<string, unknown>) => void | Promise<void>;
5
8
  submitText?: string;
9
+ disabled?: boolean;
10
+ readonly?: boolean;
11
+ /** 只决定此实例文案;不修改全局语言。 */
12
+ locale?: string;
13
+ onerror?: (error: unknown) => void;
14
+ onvalidationerror?: (issues: SchemaFormIssue[]) => void;
15
+ /** Use a unique stable prefix when several schema forms share a page. */
16
+ idPrefix?: string;
6
17
  class?: string;
7
18
  }
8
19
  declare const JsonSchemaForm: import("svelte").Component<Props, {}, "value">;