@svadmin/ui 0.69.1 → 0.72.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 (158) hide show
  1. package/dist/actions.js +1 -1
  2. package/dist/app.css +102 -63
  3. package/dist/app.theme.css +102 -63
  4. package/dist/component-registry.svelte.d.ts +33 -19
  5. package/dist/component-registry.svelte.js +6 -4
  6. package/dist/components/AdminApp.svelte +55 -53
  7. package/dist/components/AdminApp.svelte.d.ts +2 -2
  8. package/dist/components/ApiSettings.svelte +19 -1
  9. package/dist/components/AuditLogDrawer.svelte +14 -3
  10. package/dist/components/AutoForm.svelte +146 -48
  11. package/dist/components/AutoForm.svelte.d.ts +2 -0
  12. package/dist/components/AutoTable.svelte +358 -258
  13. package/dist/components/AutoTable.svelte.d.ts +1 -0
  14. package/dist/components/BoundRecordDetailDrawer.svelte +166 -0
  15. package/dist/components/BoundRecordDetailDrawer.svelte.d.ts +9 -0
  16. package/dist/components/Breadcrumbs.svelte +7 -4
  17. package/dist/components/CancelTaskButton.svelte +9 -5
  18. package/dist/components/ColumnHeaderFilter.svelte +4 -3
  19. package/dist/components/ColumnSettings.svelte +1 -0
  20. package/dist/components/ComboboxField.svelte +90 -30
  21. package/dist/components/ComboboxField.svelte.d.ts +2 -2
  22. package/dist/components/CreatePage.svelte +3 -1
  23. package/dist/components/DetailDrawer.svelte +4 -0
  24. package/dist/components/DetailDrawer.svelte.d.ts +1 -0
  25. package/dist/components/DevTools.svelte +1 -1
  26. package/dist/components/DraggableGrid.svelte +1 -0
  27. package/dist/components/DraggableHeader.svelte +5 -9
  28. package/dist/components/DraggableHeader.svelte.d.ts +43 -18
  29. package/dist/components/DraggableRowTable.svelte +2 -2
  30. package/dist/components/DynamicFormList.svelte +17 -17
  31. package/dist/components/DynamicFormList.svelte.d.ts +2 -1
  32. package/dist/components/EditPage.svelte +3 -1
  33. package/dist/components/EditableTable.svelte +4 -0
  34. package/dist/components/ErrorPage.svelte +3 -1
  35. package/dist/components/FieldDisplay.svelte +14 -0
  36. package/dist/components/FieldDisplay.svelte.d.ts +7 -0
  37. package/dist/components/FieldRenderer.svelte +9 -5
  38. package/dist/components/FilterBuilder.svelte +19 -8
  39. package/dist/components/FilterDropdown.svelte.d.ts +1 -1
  40. package/dist/components/Header.svelte +5 -6
  41. package/dist/components/ImportWizard.svelte +3 -2
  42. package/dist/components/InfiniteList.svelte +22 -8
  43. package/dist/components/InfiniteList.svelte.d.ts +5 -3
  44. package/dist/components/InlineEdit.svelte +114 -44
  45. package/dist/components/JsonSchemaForm.svelte +19 -14
  46. package/dist/components/Layout.svelte +19 -15
  47. package/dist/components/LazyTaskQueueDrawer.svelte +26 -0
  48. package/dist/components/LazyTaskQueueDrawer.svelte.d.ts +8 -0
  49. package/dist/components/ListPage.svelte +7 -6
  50. package/dist/components/MasterDetailView.svelte +3 -3
  51. package/dist/components/MediaLibraryModal.svelte +5 -2
  52. package/dist/components/MentionsInput.svelte +4 -3
  53. package/dist/components/NavigateToResource.svelte +3 -2
  54. package/dist/components/PermissionMatrix.svelte +4 -3
  55. package/dist/components/ProfilePage.svelte +2 -2
  56. package/dist/components/QuickEditDrawer.svelte +39 -0
  57. package/dist/components/QuickEditDrawer.svelte.d.ts +8 -0
  58. package/dist/components/RecordDetailDrawer.svelte +14 -108
  59. package/dist/components/RecordRowActions.svelte +41 -0
  60. package/dist/components/RecordRowActions.svelte.d.ts +14 -0
  61. package/dist/components/ResourceAccessGuard.svelte +7 -5
  62. package/dist/components/RetryTaskButton.svelte +9 -5
  63. package/dist/components/RowActions.svelte +5 -3
  64. package/dist/components/SensitiveDataMask.svelte +3 -3
  65. package/dist/components/SettingsPage.svelte +1 -1
  66. package/dist/components/ShowPage.svelte +44 -38
  67. package/dist/components/Sidebar.svelte +10 -8
  68. package/dist/components/SplitPaneLayout.svelte +4 -2
  69. package/dist/components/StepsForm.svelte +161 -44
  70. package/dist/components/StepsForm.svelte.d.ts +1 -0
  71. package/dist/components/TaskDetails.svelte +20 -7
  72. package/dist/components/TaskList.svelte +19 -7
  73. package/dist/components/TaskQueueDrawer.svelte +21 -22
  74. package/dist/components/Toast.svelte +4 -2
  75. package/dist/components/TooltipButton.svelte +1 -1
  76. package/dist/components/TreeSelect.svelte +4 -2
  77. package/dist/components/ValidatedField.svelte +27 -0
  78. package/dist/components/ValidatedField.svelte.d.ts +35 -0
  79. package/dist/components/account/ImportMembersPage.svelte +2 -2
  80. package/dist/components/account/SecurityLogPage.svelte +3 -1
  81. package/dist/components/account/SettingsEnterprisePage.svelte +7 -5
  82. package/dist/components/account/TeamMembersPage.svelte +1 -1
  83. package/dist/components/buttons/CloneButton.svelte +6 -4
  84. package/dist/components/buttons/DeleteButton.svelte +95 -29
  85. package/dist/components/buttons/DeleteButton.svelte.d.ts +2 -0
  86. package/dist/components/buttons/EditButton.svelte +6 -4
  87. package/dist/components/buttons/ExportButton.svelte +22 -4
  88. package/dist/components/buttons/ImportButton.svelte +83 -38
  89. package/dist/components/buttons/ImportButton.svelte.d.ts +6 -10
  90. package/dist/components/buttons/RefreshButton.svelte +48 -8
  91. package/dist/components/buttons/ShowButton.svelte +6 -4
  92. package/dist/components/content/ApiKeyList.svelte +3 -1
  93. package/dist/components/content/ContentPageShell.svelte +3 -1
  94. package/dist/components/content/FileList.svelte +3 -1
  95. package/dist/components/content/MemberList.svelte +3 -1
  96. package/dist/components/content/NetworkTable.svelte +3 -1
  97. package/dist/components/content/SecurityEventTable.svelte +3 -1
  98. package/dist/components/content/StatusTabs.svelte +2 -2
  99. package/dist/components/fieldComponentMap.d.ts +18 -13
  100. package/dist/components/fieldComponentMap.js +95 -47
  101. package/dist/components/fields/AvatarField.svelte +1 -1
  102. package/dist/components/fields/ChoiceField.svelte +16 -0
  103. package/dist/components/fields/ChoiceField.svelte.d.ts +10 -0
  104. package/dist/components/fields/CodeField.svelte +11 -12
  105. package/dist/components/fields/CodeField.svelte.d.ts +1 -1
  106. package/dist/components/fields/DateRangeField.svelte +2 -4
  107. package/dist/components/fields/ImageField.svelte +3 -1
  108. package/dist/components/fields/ImagesField.svelte +23 -0
  109. package/dist/components/fields/ImagesField.svelte.d.ts +6 -0
  110. package/dist/components/fields/JsonField.svelte +19 -13
  111. package/dist/components/fields/PasswordField.svelte +5 -0
  112. package/dist/components/fields/PasswordField.svelte.d.ts +6 -0
  113. package/dist/components/fields/json-value.d.ts +11 -0
  114. package/dist/components/fields/json-value.js +28 -0
  115. package/dist/components/profile/ActivityTimeline.svelte +2 -2
  116. package/dist/components/record-detail.svelte.d.ts +16 -0
  117. package/dist/components/record-detail.svelte.js +28 -0
  118. package/dist/components/saved-list-views.js +29 -29
  119. package/dist/components/table-contract.d.ts +13 -0
  120. package/dist/components/table-contract.js +42 -0
  121. package/dist/components/task-utils.js +4 -2
  122. package/dist/components/ui/alert/alert-variants.d.ts +2 -3
  123. package/dist/components/ui/alert/alert-variants.js +1 -2
  124. package/dist/components/ui/alert/alert.svelte +4 -5
  125. package/dist/components/ui/alert/alert.svelte.d.ts +3 -8
  126. package/dist/components/ui/alert/index.js +0 -2
  127. package/dist/components/ui/avatar/avatar-variants.d.ts +2 -3
  128. package/dist/components/ui/avatar/avatar-variants.js +1 -2
  129. package/dist/components/ui/avatar/avatar.svelte +5 -6
  130. package/dist/components/ui/avatar/avatar.svelte.d.ts +3 -8
  131. package/dist/components/ui/badge/badge-variants.d.ts +2 -3
  132. package/dist/components/ui/badge/badge-variants.js +1 -2
  133. package/dist/components/ui/badge/badge.svelte +4 -5
  134. package/dist/components/ui/badge/badge.svelte.d.ts +3 -8
  135. package/dist/components/ui/badge/index.js +0 -2
  136. package/dist/components/ui/button/button-variants.d.ts +2 -3
  137. package/dist/components/ui/button/button-variants.js +1 -2
  138. package/dist/components/ui/button/button.svelte +100 -44
  139. package/dist/components/ui/button/button.svelte.d.ts +8 -12
  140. package/dist/components/ui/button/index.js +0 -2
  141. package/dist/components/ui/command/command-dialog.svelte +3 -1
  142. package/dist/components/ui/command/command-dialog.svelte.d.ts +1 -1
  143. package/dist/components/ui/command/command-group.svelte +4 -2
  144. package/dist/components/ui/command/command-item.svelte +4 -2
  145. package/dist/components/ui/command/command-separator.svelte +3 -1
  146. package/dist/components/ui/command/index.d.ts +5 -5
  147. package/dist/components/ui/input/input.svelte +40 -20
  148. package/dist/components/ui/input/input.svelte.d.ts +5 -4
  149. package/dist/components/ui/sheet/sheet.svelte +9 -3
  150. package/dist/components/ui/sheet/sheet.svelte.d.ts +1 -0
  151. package/dist/components/ui/tooltip/tooltip.svelte +4 -2
  152. package/dist/index.d.ts +1 -1
  153. package/dist/inline-value.d.ts +5 -0
  154. package/dist/inline-value.js +24 -0
  155. package/dist/numeric-input.d.ts +2 -0
  156. package/dist/numeric-input.js +9 -0
  157. package/dist/types.d.ts +3 -3
  158. package/package.json +11 -5
@@ -1,5 +1,9 @@
1
1
  <script lang="ts">
2
- import { useForm, getResource, deriveValidator, useNavigation } from '@svadmin/core';
2
+ import { definedReactiveOptions } from '@svadmin/core/options';
3
+
4
+ import { definedOptions } from '@svadmin/core/options';
5
+
6
+ import { captureAdminContext, captureAuthSession, useResourceContract, getContractFormFields, deriveValidator, useNavigation, useCan, useForm } from '@svadmin/core';
3
7
  import { slide } from 'svelte/transition';
4
8
  import type { FieldDefinition } from '@svadmin/core';
5
9
  import { useTranslation } from '@svadmin/core/i18n';
@@ -29,6 +33,8 @@
29
33
  formActions?: Snippet<[{ isLoading: boolean; onSubmit: () => void }]>;
30
34
  headerContent?: Snippet;
31
35
  onSuccess?: () => void;
36
+ redirect?: 'list' | false;
37
+ onCancel?: () => void;
32
38
  onNavigationGuardReady?: (guard: (fn: () => void) => void) => void;
33
39
  }
34
40
 
@@ -43,20 +49,39 @@
43
49
  formActions,
44
50
  headerContent,
45
51
  onSuccess,
52
+ redirect = 'list',
53
+ onCancel,
46
54
  onNavigationGuardReady,
47
55
  }: Props = $props();
48
56
  const navigation = useNavigation();
57
+ const context = captureAdminContext();
58
+ const binding = useResourceContract(() => resourceName);
49
59
  const isReadonly = $derived(mode === 'show');
50
60
  const isCompact = $derived(density === 'compact');
51
61
 
52
62
  // ─── Resource metadata ────────────────────────────────────────────
53
- const resource = $derived(getResource(resourceName));
63
+ const resource = $derived(context.getResource(resourceName));
54
64
  const primaryKey = $derived(resource.primaryKey ?? 'id');
65
+ const contractFields = $derived(getContractFormFields(binding.resource, mode));
66
+ const readPermission = useCan(() => definedOptions({
67
+ resource: resourceName, action: mode === 'edit' ? 'edit' : 'show', id,
68
+ queryOptions: { enabled: mode !== 'create' },
69
+ }));
70
+ const createPermission = useCan(() => ({
71
+ resource: resourceName, action: 'create', queryOptions: { enabled: mode === 'create' || mode === 'clone' },
72
+ }));
73
+ const permissionPending = $derived(mode === 'create' ? createPermission.isLoading
74
+ : readPermission.isLoading || (mode === 'clone' && createPermission.isLoading));
75
+ const allowed = $derived(mode === 'create' ? resource.canCreate !== false && createPermission.allowed
76
+ : mode === 'edit' ? resource.canEdit !== false && readPermission.allowed
77
+ : mode === 'show' ? resource.canShow !== false && readPermission.allowed
78
+ : resource.canCreate !== false && resource.canShow !== false && readPermission.allowed && createPermission.allowed);
55
79
 
56
80
  const formFields = $derived(resource.fields.filter(f => {
57
81
  if (f.key === primaryKey) return false;
82
+ if (!contractFields.includes(f.key)) return false;
58
83
  if (f.showInForm === false) return false;
59
- if (mode === 'create' && f.showInCreate === false) return false;
84
+ if ((mode === 'create' || mode === 'clone') && f.showInCreate === false) return false;
60
85
  if (mode === 'edit' && f.showInEdit === false) return false;
61
86
  if (mode === 'show' && f.showInShow === false) return false;
62
87
  return true;
@@ -117,19 +142,42 @@
117
142
  const validator = $derived(deriveValidator(formFields, { translate: i18n.t }));
118
143
 
119
144
  // ─── useForm: single source of truth for values, errors, tainted ──
120
- const form = useForm({
121
- get resource() { return resourceName; },
145
+ const form = useForm(definedReactiveOptions({
146
+ get resource() { return binding.resource; },
122
147
  get action() { return mode; },
123
148
  get id() { return id; },
124
149
  get defaultValues() { return defaults; },
125
- redirect: 'list',
150
+ get enabled() { return allowed; },
151
+ get dataProviderName() { return binding.dataProviderName; },
152
+ get redirect() { return redirect; },
126
153
  warnWhenUnsavedChanges: true,
127
154
  get validate() { return validator; },
128
- });
155
+ get onMutationSuccess() {
156
+ const callback = onSuccess;
157
+ return callback ? () => callback() : undefined;
158
+ },
159
+ }));
129
160
 
130
161
  // ─── Submission error (non-field, e.g. network error) ─────────────
131
162
  let submitError = $state<string | null>(null);
132
163
  let formElement = $state.raw<HTMLFormElement>();
164
+ const scope = $derived({
165
+ contract: binding.resource, id, mode, allowed,
166
+ provider: context.providers?.[binding.dataProviderName], meta: binding.meta,
167
+ tenant: context.tenantCacheKey?.__svadminTenant, auth: context.authProvider,
168
+ session: captureAuthSession(context.authProvider),
169
+ });
170
+ let mounted = true;
171
+ const currentScope = (origin: typeof scope) => mounted && scope === origin && origin.session.isCurrent();
172
+ let submission: object | undefined;
173
+ $effect(() => {
174
+ void scope;
175
+ submission = undefined;
176
+ submitError = null;
177
+ confirmOpen = false;
178
+ pendingNavigation = null;
179
+ });
180
+ $effect(() => () => { mounted = false; submission = undefined; });
133
181
 
134
182
  function fieldErrorId(fieldKey: string): string {
135
183
  return `${resourceName}-${fieldKey}-error`;
@@ -140,19 +188,42 @@
140
188
  firstInvalid?.focus();
141
189
  }
142
190
 
143
- async function handleSubmit() {
144
- submitError = null;
145
- try {
146
- await form.submit();
147
- if (Object.keys(form.errors).length > 0) {
148
- queueMicrotask(focusFirstInvalidField);
149
- return;
191
+ const handleSubmit = $derived.by(() => {
192
+ const current = scope;
193
+ return async () => {
194
+ if (!currentScope(current) || !allowed || isReadonly || !form.ready || form.submitting || submission) return;
195
+ const token = {};
196
+ submission = token;
197
+ submitError = null;
198
+ try {
199
+ await form.submit();
200
+ } catch {
201
+ if (submission === token && currentScope(current)) {
202
+ submitError = i18n.t('common.operationFailed');
203
+ queueMicrotask(() => {
204
+ if (currentScope(current)) focusFirstInvalidField();
205
+ });
206
+ }
207
+ } finally {
208
+ if (submission === token) submission = undefined;
150
209
  }
151
- onSuccess?.();
152
- } catch (e) {
153
- submitError = e instanceof Error ? e.message : i18n.t('common.operationFailed');
154
- }
155
- }
210
+ };
211
+ });
212
+ const submitEvent = $derived.by(() => {
213
+ const submit = handleSubmit;
214
+ return (event: Event) => { event.preventDefault(); void submit(); };
215
+ });
216
+ const fieldChange = $derived.by(() => {
217
+ const origin = scope;
218
+ return (key: string) => (value: unknown) => {
219
+ if (currentScope(origin)) form.setFieldValue(key, value);
220
+ };
221
+ });
222
+ const retry = $derived.by(() => {
223
+ const origin = scope;
224
+ const refetch = form.query.refetch;
225
+ return () => { if (currentScope(origin)) void refetch().catch(() => {}); };
226
+ });
156
227
 
157
228
  const pageTitle = $derived(
158
229
  mode === 'create'
@@ -166,29 +237,49 @@
166
237
  let confirmOpen = $state(false);
167
238
  let pendingNavigation: (() => void) | null = null;
168
239
 
169
- function guardNavigate(fn: () => void) {
170
- if (form.isTainted()) {
171
- pendingNavigation = fn;
172
- confirmOpen = true;
173
- } else {
174
- fn();
175
- }
176
- }
240
+ const guardNavigate = $derived.by(() => {
241
+ const origin = scope;
242
+ return (fn: () => void) => {
243
+ if (!currentScope(origin)) return;
244
+ if (form.submitting) return;
245
+ if (form.isTainted()) {
246
+ pendingNavigation = () => { if (currentScope(origin)) fn(); };
247
+ confirmOpen = true;
248
+ } else {
249
+ fn();
250
+ }
251
+ };
252
+ });
253
+ const back = $derived.by(() => {
254
+ const guard = guardNavigate;
255
+ const name = resourceName;
256
+ const cancel = onCancel;
257
+ return () => guard(() => cancel ? cancel() : navigation.list(name));
258
+ });
177
259
 
178
260
  $effect(() => {
179
261
  onNavigationGuardReady?.(guardNavigate);
180
262
  });
181
263
 
182
- function confirmNavigate() {
183
- confirmOpen = false;
184
- pendingNavigation?.();
185
- pendingNavigation = null;
186
- }
264
+ const confirmNavigate = $derived.by(() => {
265
+ const origin = scope;
266
+ return () => {
267
+ if (!currentScope(origin)) return;
268
+ confirmOpen = false;
269
+ const navigate = pendingNavigation;
270
+ pendingNavigation = null;
271
+ navigate?.();
272
+ };
273
+ });
187
274
 
188
- function cancelNavigate() {
189
- confirmOpen = false;
190
- pendingNavigation = null;
191
- }
275
+ const cancelNavigate = $derived.by(() => {
276
+ const origin = scope;
277
+ return () => {
278
+ if (!currentScope(origin)) return;
279
+ confirmOpen = false;
280
+ pendingNavigation = null;
281
+ };
282
+ });
192
283
  </script>
193
284
 
194
285
  <div class={isCompact ? 'svadmin-u-3e7ce58d64fa' : 'svadmin-u-b3542e058833'}>
@@ -196,7 +287,7 @@
196
287
  <div class="svadmin-u-60fbb7713999 svadmin-u-3960ffc248d9 svadmin-u-0c3bc98565dd">
197
288
  <TooltipButton
198
289
  tooltip={i18n.t('common.back')}
199
- onclick={() => guardNavigate(() => navigation.list(resourceName))}
290
+ onclick={back}
200
291
  >
201
292
  <ArrowLeft class="svadmin-u-cd0d9c512cdc svadmin-u-72470489ff4e" aria-hidden="true" />
202
293
  </TooltipButton>
@@ -210,7 +301,7 @@
210
301
  </div>
211
302
  {/if}
212
303
 
213
- {#if form.loading}
304
+ {#if form.loading || permissionPending}
214
305
  <div class="svadmin-u-cf3893e36c22 svadmin-u-b3542e058833">
215
306
  <div class="svadmin-u-5f22e64f2282 svadmin-u-438b2237b8d6 svadmin-u-3daca9af0861 svadmin-u-a10fdd7667ee svadmin-u-0478c89a150f svadmin-u-b43b4c086d9a">
216
307
  {#each Array(4) as _, _i (_i)}
@@ -221,8 +312,15 @@
221
312
  {/each}
222
313
  </div>
223
314
  </div>
224
- {:else}
225
- <form bind:this={formElement} onsubmit={(e: Event) => { e.preventDefault(); handleSubmit(); }} class="svadmin-u-cf3893e36c22 svadmin-u-b3542e058833" novalidate>
315
+ {:else if !allowed}
316
+ <p role="alert">{i18n.t('common.operationFailed')}</p>
317
+ {:else if !form.ready && form.error}
318
+ <p role="alert">{i18n.t('common.operationFailed')}</p>
319
+ <Button type="button" variant="outline" onclick={retry}>
320
+ {i18n.t('common.retry')}
321
+ </Button>
322
+ {:else if form.ready}
323
+ <form bind:this={formElement} onsubmit={submitEvent} class="svadmin-u-cf3893e36c22 svadmin-u-b3542e058833" novalidate>
226
324
  {#if submitError}
227
325
  <div transition:slide={{ duration: 300, axis: 'y' }} class="svadmin-shake">
228
326
  <Alert.Root variant="destructive">
@@ -245,15 +343,15 @@
245
343
  {#each group.fields as field (field.key)}
246
344
  <div class={cn(columns > 1 && isFullWidthField(field) && 'svadmin-u-2c955d1b45df', !!form.errors[field.key] && 'svadmin-u-ee1a5af3aa10')}>
247
345
  {#if fieldRenderer}
248
- {@render fieldRenderer({ field, value: form.values[field.key], onchange: (val: unknown) => form.setFieldValue(field.key, val) })}
346
+ {@render fieldRenderer({ field, value: form.values[field.key], onchange: fieldChange(field.key) })}
249
347
  {:else}
250
348
  <FieldRenderer
251
349
  {field}
252
350
  value={form.values[field.key]}
253
- onchange={(val: unknown) => form.setFieldValue(field.key, val)}
351
+ onchange={fieldChange(field.key)}
254
352
  {density}
255
353
  invalid={!!form.errors[field.key]}
256
- errorId={form.errors[field.key] ? fieldErrorId(field.key) : undefined}
354
+ {...definedOptions({ "errorId": form.errors[field.key] ? fieldErrorId(field.key) : undefined })}
257
355
  disabled={isReadonly}
258
356
  />
259
357
  {/if}
@@ -273,15 +371,15 @@
273
371
  {#each formFields as field (field.key)}
274
372
  <div class={cn(columns > 1 && isFullWidthField(field) && 'svadmin-u-2c955d1b45df', !!form.errors[field.key] && 'svadmin-u-ee1a5af3aa10')}>
275
373
  {#if fieldRenderer}
276
- {@render fieldRenderer({ field, value: form.values[field.key], onchange: (val: unknown) => form.setFieldValue(field.key, val) })}
374
+ {@render fieldRenderer({ field, value: form.values[field.key], onchange: fieldChange(field.key) })}
277
375
  {:else}
278
376
  <FieldRenderer
279
377
  {field}
280
378
  value={form.values[field.key]}
281
- onchange={(val: unknown) => form.setFieldValue(field.key, val)}
379
+ onchange={fieldChange(field.key)}
282
380
  {density}
283
381
  invalid={!!form.errors[field.key]}
284
- errorId={form.errors[field.key] ? fieldErrorId(field.key) : undefined}
382
+ {...definedOptions({ "errorId": form.errors[field.key] ? fieldErrorId(field.key) : undefined })}
285
383
  disabled={isReadonly}
286
384
  />
287
385
  {/if}
@@ -296,7 +394,7 @@
296
394
  {/if}
297
395
 
298
396
  <div class="svadmin-u-60fbb7713999 svadmin-u-3960ffc248d9 svadmin-u-1004c0c3954c">
299
- {#if formActions}
397
+ {#if formActions && !isReadonly}
300
398
  {@render formActions({ isLoading: form.submitting, onSubmit: handleSubmit })}
301
399
  {:else if !isReadonly}
302
400
  <Button type="submit" size={isCompact ? 'sm' : 'default'} disabled={form.submitting}>
@@ -311,7 +409,7 @@
311
409
  type="button"
312
410
  variant="outline"
313
411
  size={isCompact ? 'sm' : 'default'}
314
- onclick={() => guardNavigate(() => navigation.list(resourceName))}
412
+ onclick={back}
315
413
  >
316
414
  {i18n.t('common.cancel')}
317
415
  </Button>
@@ -18,6 +18,8 @@ interface Props {
18
18
  }]>;
19
19
  headerContent?: Snippet;
20
20
  onSuccess?: () => void;
21
+ redirect?: 'list' | false;
22
+ onCancel?: () => void;
21
23
  onNavigationGuardReady?: (guard: (fn: () => void) => void) => void;
22
24
  }
23
25
  declare const AutoForm: import("svelte").Component<Props, {}, "">;