@svadmin/ui 0.88.1 → 0.92.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.
- package/dist/app.css +4 -0
- package/dist/app.theme.css +4 -0
- package/dist/component-registry.svelte.d.ts +2 -2
- package/dist/components/AboutSettings.svelte +23 -4
- package/dist/components/AdminApp.svelte +6 -4
- package/dist/components/AdminApp.svelte.d.ts +3 -3
- package/dist/components/ApiSettings.svelte +43 -27
- package/dist/components/ApprovalActionCard.svelte +8 -9
- package/dist/components/ApprovalCenter.svelte +24 -5
- package/dist/components/AuditLogViewer.svelte +2 -2
- package/dist/components/AutoComplete.svelte +610 -0
- package/dist/components/AutoComplete.svelte.d.ts +25 -0
- package/dist/components/AutoForm.svelte +265 -18
- package/dist/components/AutoForm.svelte.d.ts +19 -2
- package/dist/components/AutoTable.svelte +141 -36
- package/dist/components/AutoTable.svelte.d.ts +8 -0
- package/dist/components/BatchActionBar.svelte +42 -14
- package/dist/components/BatchActionBar.svelte.d.ts +5 -0
- package/dist/components/BoundRecordDetailDrawer.svelte +5 -3
- package/dist/components/CancelTaskButton.svelte +14 -1
- package/dist/components/Cascader.svelte +412 -53
- package/dist/components/Cascader.svelte.d.ts +7 -1
- package/dist/components/ColorPicker.svelte +1 -1
- package/dist/components/ColorPicker.svelte.d.ts +1 -1
- package/dist/components/ComboboxField.svelte +270 -34
- package/dist/components/ComboboxField.svelte.d.ts +4 -0
- package/dist/components/CommandPalette.svelte +4 -4
- package/dist/components/DashboardView.svelte +73 -7
- package/dist/components/DashboardView.svelte.d.ts +3 -1
- package/dist/components/DateRangeInput.svelte +8 -1
- package/dist/components/DetailWorkspaceAsyncSection.svelte +107 -0
- package/dist/components/DetailWorkspaceAsyncSection.svelte.d.ts +36 -0
- package/dist/components/DetailWorkspaceSections.svelte +233 -0
- package/dist/components/DetailWorkspaceSections.svelte.d.ts +9 -0
- package/dist/components/DrawerForm.svelte +78 -9
- package/dist/components/DrawerForm.svelte.d.ts +3 -3
- package/dist/components/ErrorBoundary.svelte +1 -1
- package/dist/components/ErrorComponent.svelte +19 -6
- package/dist/components/ErrorComponent.svelte.d.ts +1 -0
- package/dist/components/ErrorSummary.svelte +9 -4
- package/dist/components/FieldRenderer.svelte +203 -90
- package/dist/components/FieldRenderer.svelte.d.ts +16 -1
- package/dist/components/FileUpload.svelte +116 -51
- package/dist/components/FileUpload.svelte.d.ts +7 -27
- package/dist/components/FileUploadField.svelte +170 -0
- package/dist/components/FileUploadField.svelte.d.ts +21 -0
- package/dist/components/FilterBuilder.svelte +13 -7
- package/dist/components/FilterCollectionInput.svelte +9 -7
- package/dist/components/FilterCollectionInput.svelte.d.ts +3 -0
- package/dist/components/ForgotPasswordPage.svelte +1 -1
- package/dist/components/Header.svelte +1 -1
- package/dist/components/ImportWizard.svelte +197 -28
- package/dist/components/ImportWizard.svelte.d.ts +5 -1
- package/dist/components/InferencerPanel.svelte +4 -2
- package/dist/components/InfiniteList.svelte +52 -9
- package/dist/components/JsonSchemaForm.svelte +237 -42
- package/dist/components/JsonSchemaForm.svelte.d.ts +10 -3
- package/dist/components/KanbanBoard.svelte +43 -7
- package/dist/components/KanbanBoard.svelte.d.ts +2 -2
- package/dist/components/Layout.svelte +1 -1
- package/dist/components/LoginPage.svelte +1 -1
- package/dist/components/MetricStrip.svelte +8 -3
- package/dist/components/MetricStrip.svelte.d.ts +1 -0
- package/dist/components/ModalForm.svelte +85 -9
- package/dist/components/ModalForm.svelte.d.ts +3 -3
- package/dist/components/MoneyInput.svelte +5 -3
- package/dist/components/MoneyInput.svelte.d.ts +4 -2
- package/dist/components/MultiTabKeepAlive.svelte +502 -43
- package/dist/components/MultiTabKeepAlive.svelte.d.ts +40 -6
- package/dist/components/NotificationsSettings.svelte +10 -10
- package/dist/components/NumberInput.svelte +5 -3
- package/dist/components/NumberInput.svelte.d.ts +4 -2
- package/dist/components/NumericInput.svelte +277 -25
- package/dist/components/NumericInput.svelte.d.ts +3 -1
- package/dist/components/PercentInput.svelte +5 -3
- package/dist/components/PercentInput.svelte.d.ts +4 -2
- package/dist/components/PermissionMatrix.svelte +44 -8
- package/dist/components/PermissionMatrix.svelte.d.ts +1 -0
- package/dist/components/ProfilePage.svelte +38 -13
- package/dist/components/RadioGroup.svelte +203 -4
- package/dist/components/RadioGroup.svelte.d.ts +1 -1
- package/dist/components/Rate.svelte +3 -3
- package/dist/components/Rate.svelte.d.ts +2 -2
- package/dist/components/RecordDetailDrawer.svelte +1 -1
- package/dist/components/RecordDetailDrawer.svelte.d.ts +1 -1
- package/dist/components/RegisterPage.svelte +1 -1
- package/dist/components/RelationPicker.svelte +39 -11
- package/dist/components/ResourceAccessGuard.svelte +7 -2
- package/dist/components/RetryTaskButton.svelte +14 -1
- package/dist/components/RolesSettings.svelte +74 -28
- package/dist/components/SecuritySettings.svelte +66 -51
- package/dist/components/SegmentedControl.svelte +4 -2
- package/dist/components/SegmentedControl.svelte.d.ts +1 -1
- package/dist/components/Sidebar.svelte +1 -1
- package/dist/components/StepsForm.svelte +62 -10
- package/dist/components/StepsForm.svelte.d.ts +4 -2
- package/dist/components/SvadminLogo.svelte +1 -0
- package/dist/components/SvarDataGrid.svelte +42 -24
- package/dist/components/SvarDataGrid.svelte.d.ts +10 -10
- package/dist/components/SvarResourceRead.svelte +2 -0
- package/dist/components/SvarResourceTableView.svelte +4 -2
- package/dist/components/TagsInput.svelte +3 -3
- package/dist/components/TagsInput.svelte.d.ts +2 -2
- package/dist/components/TaskDetails.svelte +22 -16
- package/dist/components/TaskDetails.svelte.d.ts +1 -1
- package/dist/components/TaskList.svelte +57 -15
- package/dist/components/TaskQueueDrawer.svelte +54 -34
- package/dist/components/Toast.svelte +13 -2
- package/dist/components/Transfer.svelte +67 -5
- package/dist/components/Transfer.svelte.d.ts +4 -0
- package/dist/components/TreeSelect.svelte +337 -77
- package/dist/components/TreeSelect.svelte.d.ts +4 -0
- package/dist/components/TreeTable.svelte +6 -1
- package/dist/components/TwoFactorAuthPage.svelte +8 -4
- package/dist/components/UpdatePasswordPage.svelte +1 -1
- package/dist/components/VersionDiffViewer.svelte +9 -7
- package/dist/components/account/CompanyProfilePage.svelte +13 -12
- package/dist/components/account/MemberDirectory.svelte +14 -10
- package/dist/components/account/SettingsEnterprisePage.svelte +18 -18
- package/dist/components/content/AuditTimeline.svelte +8 -6
- package/dist/components/content/DataState.svelte +1 -1
- package/dist/components/content/FileList.svelte +44 -13
- package/dist/components/content/FileList.svelte.d.ts +4 -2
- package/dist/components/content/FileListRow.svelte +87 -0
- package/dist/components/content/FileListRow.svelte.d.ts +11 -0
- package/dist/components/content/ImportDropzone.svelte +109 -12
- package/dist/components/content/ImportDropzone.svelte.d.ts +1 -0
- package/dist/components/content/IntegrationCard.svelte +3 -3
- package/dist/components/content/IntegrationCard.svelte.d.ts +2 -0
- package/dist/components/content/MediaThumbnail.svelte +6 -2
- package/dist/components/detail-workspace.d.ts +60 -0
- package/dist/components/detail-workspace.js +3 -0
- package/dist/components/enterprise/json-schema-form.d.ts +1 -1
- package/dist/components/enterprise/recursive-schema-form.d.ts +15 -1
- package/dist/components/enterprise/recursive-schema-form.js +288 -14
- package/dist/components/enterprise/schema-form-references.d.ts +14 -0
- package/dist/components/enterprise/schema-form-references.js +316 -0
- package/dist/components/fields/ArrayField.svelte +178 -14
- package/dist/components/fields/ArrayField.svelte.d.ts +17 -3
- package/dist/components/fields/array-field-metadata.d.ts +4 -0
- package/dist/components/fields/array-field-metadata.js +36 -0
- package/dist/components/file-upload-reference.d.ts +11 -0
- package/dist/components/file-upload-reference.js +50 -0
- package/dist/components/file-upload-types.d.ts +32 -0
- package/dist/components/file-upload-types.js +1 -0
- package/dist/components/form-contract.upload-type-fixture.svelte +108 -0
- package/dist/components/form-contract.upload-type-fixture.svelte.d.ts +18 -0
- package/dist/components/json-schema-form-state.d.ts +19 -0
- package/dist/components/list-deletion.svelte.js +6 -1
- package/dist/components/list-state.svelte.d.ts +12 -1
- package/dist/components/list-state.svelte.js +56 -16
- package/dist/components/numeric-format.d.ts +44 -0
- package/dist/components/numeric-format.js +198 -0
- package/dist/components/record-detail.svelte.js +2 -0
- package/dist/components/saved-list-views.d.ts +9 -2
- package/dist/components/saved-list-views.js +42 -11
- package/dist/components/saved-list-views.svelte.d.ts +3 -0
- package/dist/components/saved-list-views.svelte.js +56 -7
- package/dist/components/task-action.svelte.d.ts +1 -0
- package/dist/components/task-action.svelte.js +55 -3
- package/dist/components/task-utils.d.ts +1 -0
- package/dist/components/task-utils.js +18 -0
- package/dist/components/ui/input/input.svelte +1 -1
- package/dist/components/ui/input/input.svelte.d.ts +1 -1
- package/dist/components/ui/sheet/sheet.svelte +4 -1
- package/dist/components/version-history.d.ts +14 -0
- package/dist/components/version-history.js +32 -0
- package/dist/components/workspace-tab-state.d.ts +78 -0
- package/dist/components/workspace-tab-state.js +587 -0
- package/dist/index.d.ts +13 -1
- package/dist/index.js +4 -0
- package/package.json +5 -5
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
import DateTimeInput from './DateTimeInput.svelte';
|
|
25
25
|
import DateRangeInput, { type DateRangeInputValue } from './DateRangeInput.svelte';
|
|
26
26
|
import FileUpload from './FileUpload.svelte';
|
|
27
|
+
import type { UploadCancelHandler, UploadHandler } from './file-upload-types.js';
|
|
28
|
+
import FileUploadField from './FileUploadField.svelte';
|
|
27
29
|
import ColorPicker from './ColorPicker.svelte';
|
|
28
30
|
import Rate from './Rate.svelte';
|
|
29
31
|
import TagsInput from './TagsInput.svelte';
|
|
@@ -36,23 +38,51 @@
|
|
|
36
38
|
import type { Snippet } from 'svelte';
|
|
37
39
|
import { getRichTextEditor } from '../editor-config.svelte.js';
|
|
38
40
|
import { numericInputValue } from '../numeric-input.js';
|
|
41
|
+
import type { NumericInputLocale } from './numeric-format.js';
|
|
39
42
|
|
|
40
43
|
type FieldOption = NonNullable<FieldDefinition['options']>[number];
|
|
41
44
|
const i18n = useTranslation();
|
|
42
45
|
|
|
43
|
-
let {
|
|
46
|
+
let {
|
|
47
|
+
field, value, onchange, disabled, invalid = false, errorId, id, children, nativeSubmit = true,
|
|
48
|
+
upload, cancelUpload, onUploadStateChange, fileReferenceMode = false, fileScopeKey,
|
|
49
|
+
} = $props<{
|
|
44
50
|
field: FieldDefinition;
|
|
45
51
|
value: unknown;
|
|
46
52
|
onchange: (val: unknown) => void;
|
|
47
53
|
disabled?: boolean;
|
|
48
54
|
invalid?: boolean;
|
|
49
|
-
errorId?: string;
|
|
55
|
+
errorId?: string | undefined;
|
|
56
|
+
id?: string;
|
|
50
57
|
children?: Snippet;
|
|
58
|
+
/** 嵌套数组的可序列化值由外层 JSON 提交;原始文件保留原生通道。 */
|
|
59
|
+
nativeSubmit?: boolean;
|
|
60
|
+
/** 开启异步上传后,字段值只保存可序列化引用,不再接收 File。 */
|
|
61
|
+
upload?: UploadHandler;
|
|
62
|
+
cancelUpload?: UploadCancelHandler;
|
|
63
|
+
onUploadStateChange?: (state: { busy: boolean; unresolved: boolean }) => void;
|
|
64
|
+
/** AutoForm 的 JSON 文件模式;独立 FieldRenderer 默认保留原生 multipart。 */
|
|
65
|
+
fileReferenceMode?: boolean;
|
|
66
|
+
/** 记录/上传作用域或 reset 变化时只重挂载文件字段。 */
|
|
67
|
+
fileScopeKey?: string | number | object;
|
|
51
68
|
}>();
|
|
52
69
|
|
|
70
|
+
const instanceId = $props.id();
|
|
71
|
+
const controlId = $derived(id ?? (children ? field.key : `${instanceId}-control`));
|
|
72
|
+
const labelId = $derived(children ? `label-${controlId}` : `${instanceId}-label`);
|
|
73
|
+
const labelTarget = $derived(!children && field.type === 'daterange' ? `${controlId}-start` : controlId);
|
|
74
|
+
const descriptionId = $derived(`${instanceId}-description`);
|
|
75
|
+
const describedBy = $derived([field.description ? descriptionId : undefined, errorId].filter(Boolean).join(' ') || undefined);
|
|
76
|
+
const nativeFieldName = $derived(nativeSubmit ? field.key : undefined);
|
|
77
|
+
const nativeArrayName = $derived(nativeSubmit ? `${field.key}[]` : undefined);
|
|
78
|
+
|
|
53
79
|
// Typed accessors
|
|
54
80
|
const strVal = $derived((value as string) ?? '');
|
|
55
81
|
const numVal = $derived(numericInputValue(value));
|
|
82
|
+
// FieldDefinition.locale is intentionally a runtime string. Pass it through so
|
|
83
|
+
// NumericInput can render an explicit unsupported-locale state instead of
|
|
84
|
+
// silently switching the field back to the default number path.
|
|
85
|
+
const numericLocale = $derived(field.locale as NumericInputLocale | undefined);
|
|
56
86
|
const boolVal = $derived((value as boolean) ?? false);
|
|
57
87
|
const tagsVal = $derived((value as string[]) ?? []);
|
|
58
88
|
const multiVal = $derived((value as (string | number)[]) ?? []);
|
|
@@ -90,18 +120,21 @@
|
|
|
90
120
|
}
|
|
91
121
|
}
|
|
92
122
|
|
|
93
|
-
// Images management
|
|
123
|
+
// Images management:禁用态保留回显,但所有入口都不能改值。
|
|
94
124
|
function addImage() {
|
|
125
|
+
if (disabled) return;
|
|
95
126
|
onchange([...imagesVal, '']);
|
|
96
127
|
}
|
|
97
128
|
|
|
98
129
|
function updateImage(index: number, url: string) {
|
|
130
|
+
if (disabled) return;
|
|
99
131
|
const next = [...imagesVal];
|
|
100
132
|
next[index] = url;
|
|
101
133
|
onchange(next);
|
|
102
134
|
}
|
|
103
135
|
|
|
104
136
|
function removeImage(index: number) {
|
|
137
|
+
if (disabled) return;
|
|
105
138
|
onchange(imagesVal.filter((_: string, i: number) => i !== index));
|
|
106
139
|
}
|
|
107
140
|
</script>
|
|
@@ -111,162 +144,182 @@
|
|
|
111
144
|
data-svadmin-field
|
|
112
145
|
data-svadmin-field-key={field.key}
|
|
113
146
|
>
|
|
114
|
-
<Label for
|
|
147
|
+
<Label {...definedOptions({ for: !children && (['array', 'transfer'].includes(field.type) || field.type === 'richtext' && getRichTextEditor()) ? undefined : labelTarget })} id={labelId} data-svadmin-field-label>
|
|
115
148
|
{field.label}
|
|
116
149
|
{#if field.required}
|
|
117
150
|
<span class="svadmin-u-811148b13d1e">*</span>
|
|
118
151
|
{/if}
|
|
119
152
|
</Label>
|
|
153
|
+
{#if field.description}
|
|
154
|
+
<p id={descriptionId} data-svadmin-field-description class="svadmin-u-359090c2d529 svadmin-u-bfa603190748">{field.description}</p>
|
|
155
|
+
{/if}
|
|
120
156
|
|
|
121
157
|
{#if children}
|
|
122
158
|
{@render children()}
|
|
123
159
|
|
|
124
160
|
{:else if field.type === 'array'}
|
|
125
|
-
|
|
126
|
-
|
|
161
|
+
{#if nativeSubmit}
|
|
162
|
+
<input type="hidden" name={field.key} value={JSON.stringify(Array.isArray(value) ? value : [])} {disabled} />
|
|
163
|
+
{/if}
|
|
164
|
+
<ArrayField
|
|
165
|
+
{field}
|
|
166
|
+
{value}
|
|
167
|
+
{onchange}
|
|
168
|
+
{...definedOptions({ disabled })}
|
|
169
|
+
labelledby={labelId}
|
|
170
|
+
{...definedOptions({ describedby: describedBy })}
|
|
171
|
+
invalid={invalid}
|
|
172
|
+
nativeSubmit={false}
|
|
173
|
+
{fileReferenceMode}
|
|
174
|
+
{...definedOptions({ upload, cancelUpload, onUploadStateChange, fileScopeKey })}
|
|
175
|
+
/>
|
|
127
176
|
|
|
128
177
|
{:else if field.type === 'text' || field.type === 'image'}
|
|
129
178
|
<Input
|
|
130
|
-
id={
|
|
131
|
-
name={
|
|
179
|
+
id={controlId}
|
|
180
|
+
name={nativeFieldName}
|
|
132
181
|
type="text"
|
|
133
182
|
value={strVal}
|
|
134
183
|
oninput={(e) => onchange((e.target as HTMLInputElement).value)}
|
|
135
184
|
required={field.required}
|
|
136
185
|
aria-invalid={invalid || undefined}
|
|
137
|
-
aria-describedby={
|
|
186
|
+
aria-describedby={describedBy}
|
|
138
187
|
{disabled}
|
|
139
188
|
placeholder={i18n.t('field.enterValue', { label: field.label })}
|
|
140
189
|
/>
|
|
141
190
|
|
|
142
191
|
{:else if field.type === 'email'}
|
|
143
192
|
<Input
|
|
144
|
-
id={
|
|
145
|
-
name={
|
|
193
|
+
id={controlId}
|
|
194
|
+
name={nativeFieldName}
|
|
146
195
|
type="email"
|
|
147
196
|
value={strVal}
|
|
148
197
|
oninput={(e) => onchange((e.target as HTMLInputElement).value)}
|
|
149
198
|
required={field.required}
|
|
150
199
|
aria-invalid={invalid || undefined}
|
|
151
|
-
aria-describedby={
|
|
200
|
+
aria-describedby={describedBy}
|
|
152
201
|
{disabled}
|
|
153
202
|
placeholder="name@example.com"
|
|
154
203
|
/>
|
|
155
204
|
|
|
156
205
|
{:else if field.type === 'url'}
|
|
157
206
|
<Input
|
|
158
|
-
id={
|
|
159
|
-
name={
|
|
207
|
+
id={controlId}
|
|
208
|
+
name={nativeFieldName}
|
|
160
209
|
type="url"
|
|
161
210
|
value={strVal}
|
|
162
211
|
oninput={(e) => onchange((e.target as HTMLInputElement).value)}
|
|
163
212
|
required={field.required}
|
|
164
213
|
aria-invalid={invalid || undefined}
|
|
165
|
-
aria-describedby={
|
|
214
|
+
aria-describedby={describedBy}
|
|
166
215
|
{disabled}
|
|
167
216
|
placeholder="https://"
|
|
168
217
|
/>
|
|
169
218
|
|
|
170
219
|
{:else if field.type === 'phone'}
|
|
171
220
|
<Input
|
|
172
|
-
id={
|
|
173
|
-
name={
|
|
221
|
+
id={controlId}
|
|
222
|
+
name={nativeFieldName}
|
|
174
223
|
type="tel"
|
|
175
224
|
value={strVal}
|
|
176
225
|
oninput={(e) => onchange((e.target as HTMLInputElement).value)}
|
|
177
226
|
required={field.required}
|
|
178
227
|
aria-invalid={invalid || undefined}
|
|
179
|
-
aria-describedby={
|
|
228
|
+
aria-describedby={describedBy}
|
|
180
229
|
{disabled}
|
|
181
230
|
placeholder="+1 (555) 000-0000"
|
|
182
231
|
/>
|
|
183
232
|
|
|
184
233
|
{:else if field.type === 'color'}
|
|
185
234
|
<ColorPicker
|
|
186
|
-
id={
|
|
187
|
-
name={field.key}
|
|
235
|
+
id={controlId}
|
|
188
236
|
value={strVal}
|
|
189
237
|
onchange={onchange}
|
|
190
238
|
required={field.required}
|
|
191
239
|
invalid={invalid}
|
|
192
|
-
describedby={errorId}
|
|
193
240
|
ariaLabel={field.label}
|
|
194
241
|
{disabled}
|
|
242
|
+
{...definedOptions({ name: nativeFieldName, describedby: describedBy })}
|
|
195
243
|
/>
|
|
196
244
|
|
|
197
245
|
{:else if field.type === 'number'}
|
|
198
246
|
<NumberInput
|
|
199
|
-
id={
|
|
200
|
-
name={
|
|
247
|
+
id={controlId}
|
|
248
|
+
name={nativeFieldName}
|
|
201
249
|
value={numVal}
|
|
202
250
|
min={field.min}
|
|
203
251
|
max={field.max}
|
|
204
252
|
step={field.step}
|
|
205
253
|
precision={field.precision}
|
|
254
|
+
locale={numericLocale}
|
|
206
255
|
onchange={onchange}
|
|
207
256
|
required={field.required}
|
|
208
257
|
invalid={invalid}
|
|
209
|
-
describedby={
|
|
258
|
+
describedby={describedBy}
|
|
210
259
|
{disabled}
|
|
211
260
|
/>
|
|
212
261
|
|
|
213
262
|
{:else if field.type === 'currency'}
|
|
214
263
|
<MoneyInput
|
|
215
|
-
id={
|
|
216
|
-
name={
|
|
264
|
+
id={controlId}
|
|
265
|
+
name={nativeFieldName}
|
|
217
266
|
value={numVal}
|
|
218
267
|
currency={field.currency ?? 'USD'}
|
|
219
268
|
min={field.min}
|
|
220
269
|
max={field.max}
|
|
221
270
|
step={field.step}
|
|
222
271
|
precision={field.precision ?? 2}
|
|
272
|
+
locale={numericLocale}
|
|
223
273
|
onchange={onchange}
|
|
224
274
|
required={field.required}
|
|
225
275
|
invalid={invalid}
|
|
226
|
-
describedby={
|
|
276
|
+
describedby={describedBy}
|
|
227
277
|
{disabled}
|
|
228
278
|
/>
|
|
229
279
|
|
|
230
280
|
{:else if field.type === 'percent'}
|
|
231
281
|
<PercentInput
|
|
232
|
-
id={
|
|
233
|
-
name={
|
|
282
|
+
id={controlId}
|
|
283
|
+
name={nativeFieldName}
|
|
234
284
|
value={numVal}
|
|
235
285
|
scale={field.scale ?? '100'}
|
|
236
286
|
min={field.min}
|
|
237
287
|
max={field.max}
|
|
238
288
|
step={field.step}
|
|
239
289
|
precision={field.precision ?? 1}
|
|
290
|
+
locale={numericLocale}
|
|
240
291
|
onchange={onchange}
|
|
241
292
|
required={field.required}
|
|
242
293
|
invalid={invalid}
|
|
243
|
-
describedby={
|
|
294
|
+
describedby={describedBy}
|
|
244
295
|
{disabled}
|
|
245
296
|
/>
|
|
246
297
|
|
|
247
298
|
{:else if field.type === 'richtext'}
|
|
248
299
|
{@const EditorComp = getRichTextEditor()}
|
|
249
300
|
{#if EditorComp}
|
|
250
|
-
<input type="hidden" name={
|
|
301
|
+
<input type="hidden" name={nativeFieldName} value={strVal} {disabled} />
|
|
251
302
|
<EditorComp
|
|
252
|
-
id={
|
|
303
|
+
id={controlId}
|
|
253
304
|
value={strVal}
|
|
254
305
|
placeholder={i18n.t('field.enterValue', { label: field.label })}
|
|
255
306
|
preset="full"
|
|
256
|
-
onchange={(html: string) => onchange(html)}
|
|
307
|
+
onchange={(html: string) => { if (!disabled) onchange(html); }}
|
|
308
|
+
aria-labelledby={labelId}
|
|
309
|
+
aria-required={field.required || undefined}
|
|
257
310
|
aria-invalid={invalid || undefined}
|
|
258
|
-
aria-describedby={
|
|
311
|
+
aria-describedby={describedBy}
|
|
259
312
|
{disabled}
|
|
260
313
|
/>
|
|
261
314
|
{:else}
|
|
262
315
|
<Textarea
|
|
263
|
-
id={
|
|
264
|
-
name={
|
|
316
|
+
id={controlId}
|
|
317
|
+
name={nativeFieldName}
|
|
265
318
|
value={strVal}
|
|
266
319
|
oninput={(e) => onchange((e.target as HTMLTextAreaElement).value)}
|
|
267
320
|
required={field.required}
|
|
268
321
|
aria-invalid={invalid || undefined}
|
|
269
|
-
aria-describedby={
|
|
322
|
+
aria-describedby={describedBy}
|
|
270
323
|
{disabled}
|
|
271
324
|
rows={10}
|
|
272
325
|
placeholder={i18n.t('field.enterValue', { label: field.label })}
|
|
@@ -276,13 +329,13 @@
|
|
|
276
329
|
|
|
277
330
|
{:else if field.type === 'textarea'}
|
|
278
331
|
<Textarea
|
|
279
|
-
id={
|
|
280
|
-
name={
|
|
332
|
+
id={controlId}
|
|
333
|
+
name={nativeFieldName}
|
|
281
334
|
value={strVal}
|
|
282
335
|
oninput={(e) => onchange((e.target as HTMLTextAreaElement).value)}
|
|
283
336
|
required={field.required}
|
|
284
337
|
aria-invalid={invalid || undefined}
|
|
285
|
-
aria-describedby={
|
|
338
|
+
aria-describedby={describedBy}
|
|
286
339
|
{disabled}
|
|
287
340
|
rows={4}
|
|
288
341
|
placeholder={i18n.t('field.enterValue', { label: field.label })}
|
|
@@ -290,7 +343,18 @@
|
|
|
290
343
|
/>
|
|
291
344
|
|
|
292
345
|
{:else if field.type === 'tree-select' || field.type === 'treeselect'}
|
|
346
|
+
{#if field.multiple}
|
|
347
|
+
{#each multiVal as selectedValue, _i (selectedValue)}
|
|
348
|
+
<input type="hidden" name={nativeArrayName} value={String(selectedValue)} {disabled} />
|
|
349
|
+
{/each}
|
|
350
|
+
{:else}
|
|
351
|
+
<input type="hidden" name={nativeFieldName} value={value == null ? '' : String(value)} {disabled} />
|
|
352
|
+
{/if}
|
|
293
353
|
<TreeSelect
|
|
354
|
+
id={controlId}
|
|
355
|
+
ariaLabel={field.label}
|
|
356
|
+
{...definedOptions({ describedby: describedBy })}
|
|
357
|
+
invalid={invalid}
|
|
294
358
|
options={(field.treeOptions ?? field.options ?? []) as TreeSelectOption[]}
|
|
295
359
|
{...definedOptions({ "value": value as string | number | (string | number)[] | undefined })}
|
|
296
360
|
multiple={field.multiple}
|
|
@@ -300,7 +364,12 @@
|
|
|
300
364
|
/>
|
|
301
365
|
|
|
302
366
|
{:else if field.type === 'cascader'}
|
|
367
|
+
<input type="hidden" name={nativeFieldName} value={JSON.stringify(Array.isArray(value) ? value : [])} {disabled} />
|
|
303
368
|
<Cascader
|
|
369
|
+
id={controlId}
|
|
370
|
+
ariaLabel={field.label}
|
|
371
|
+
{...definedOptions({ describedby: describedBy })}
|
|
372
|
+
invalid={invalid}
|
|
304
373
|
options={(field.cascaderOptions ?? field.options ?? []) as CascaderOption[]}
|
|
305
374
|
value={value as (string | number)[]}
|
|
306
375
|
separator={field.separator}
|
|
@@ -311,7 +380,14 @@
|
|
|
311
380
|
/>
|
|
312
381
|
|
|
313
382
|
{:else if field.type === 'transfer'}
|
|
383
|
+
{#each multiVal as selectedValue, _i (selectedValue)}
|
|
384
|
+
<input type="hidden" name={nativeArrayName} value={String(selectedValue)} {disabled} />
|
|
385
|
+
{/each}
|
|
314
386
|
<Transfer
|
|
387
|
+
id={controlId}
|
|
388
|
+
labelledby={labelId}
|
|
389
|
+
{...definedOptions({ describedby: describedBy })}
|
|
390
|
+
invalid={invalid}
|
|
315
391
|
dataSource={(field.transferData ?? field.options?.map((o: { label: string; value: string | number }) => ({ key: o.value, title: o.label })) ?? []) as TransferItem[]}
|
|
316
392
|
targetKeys={(value as (string | number)[]) ?? []}
|
|
317
393
|
disabled={disabled}
|
|
@@ -321,13 +397,13 @@
|
|
|
321
397
|
{:else if field.type === 'relation' && field.resource}
|
|
322
398
|
{#if field.multiple}
|
|
323
399
|
{#each multiVal as selectedValue, _i (selectedValue)}
|
|
324
|
-
<input type="hidden" name={
|
|
400
|
+
<input type="hidden" name={nativeFieldName} value={String(selectedValue)} {disabled} />
|
|
325
401
|
{/each}
|
|
326
402
|
{:else}
|
|
327
|
-
<input type="hidden" name={
|
|
403
|
+
<input type="hidden" name={nativeFieldName} value={value == null ? '' : String(value)} {disabled} />
|
|
328
404
|
{/if}
|
|
329
405
|
<ComboboxField
|
|
330
|
-
id={
|
|
406
|
+
id={controlId}
|
|
331
407
|
resource={field.resource}
|
|
332
408
|
value={field.multiple ? multiVal : value as string | number | null}
|
|
333
409
|
onchange={(v) => onchange(v)}
|
|
@@ -336,22 +412,22 @@
|
|
|
336
412
|
multiple={field.multiple}
|
|
337
413
|
placeholder={i18n.t('field.selectPlaceholder')}
|
|
338
414
|
aria-invalid={invalid || undefined}
|
|
339
|
-
aria-describedby={
|
|
415
|
+
aria-describedby={describedBy}
|
|
340
416
|
{disabled}
|
|
341
417
|
/>
|
|
342
418
|
|
|
343
419
|
{:else if field.type === 'select'}
|
|
344
|
-
<input type="hidden" name={
|
|
420
|
+
<input type="hidden" name={nativeFieldName} value={value == null ? '' : String(value)} {disabled} />
|
|
345
421
|
{#if (field.options?.length ?? 0) > 8}
|
|
346
422
|
<select
|
|
347
|
-
id={
|
|
423
|
+
id={controlId}
|
|
348
424
|
data-slot="select"
|
|
349
425
|
class="svadmin-u-60fbb7713999 svadmin-u-426b8b75185b svadmin-u-6da6a3c3f741 svadmin-u-3960ffc248d9 svadmin-u-8ef2268efbbc svadmin-u-421ac2be5045 svadmin-u-ca6bcd4b6f3f svadmin-u-e5795dad4d22 svadmin-u-e6f9e383a762 svadmin-u-0e17f2bd9074 svadmin-u-03b4dd7f172b svadmin-u-fc7473ca09eb svadmin-u-582e6ef4b245 svadmin-u-9c24ab70af61 svadmin-u-55d048ebfb1c svadmin-u-608dd26cd5ba svadmin-u-80b9d0ae125f svadmin-u-6b22a22a9752 svadmin-u-5f533b3a7de7 svadmin-u-b29d8adbad2e"
|
|
350
426
|
value={selectToken}
|
|
351
427
|
onchange={changeSelect}
|
|
352
428
|
required={field.required}
|
|
353
429
|
aria-invalid={invalid || undefined}
|
|
354
|
-
aria-describedby={
|
|
430
|
+
aria-describedby={describedBy}
|
|
355
431
|
disabled={disabled}
|
|
356
432
|
>
|
|
357
433
|
<option value="">{i18n.t('field.selectPlaceholder')}</option>
|
|
@@ -361,12 +437,12 @@
|
|
|
361
437
|
</select>
|
|
362
438
|
{:else}
|
|
363
439
|
<Select
|
|
364
|
-
id={
|
|
440
|
+
id={controlId}
|
|
365
441
|
value={selectToken}
|
|
366
442
|
onchange={changeSelect}
|
|
367
443
|
required={field.required}
|
|
368
444
|
aria-invalid={invalid || undefined}
|
|
369
|
-
aria-describedby={
|
|
445
|
+
aria-describedby={describedBy}
|
|
370
446
|
{disabled}
|
|
371
447
|
>
|
|
372
448
|
<option value="">{i18n.t('field.selectPlaceholder')}</option>
|
|
@@ -378,23 +454,23 @@
|
|
|
378
454
|
|
|
379
455
|
{:else if field.type === 'multiselect'}
|
|
380
456
|
{#each multiVal as selectedValue, selectedIndex (`${selectedValue}-${selectedIndex}`)}
|
|
381
|
-
<input type="hidden" name={
|
|
457
|
+
<input type="hidden" name={nativeArrayName} value={String(selectedValue)} {disabled} />
|
|
382
458
|
{/each}
|
|
383
459
|
<div
|
|
384
460
|
class="svadmin-u-6f7e013d6499 svadmin-u-5f22e64f2282 svadmin-u-ca6bcd4b6f3f svadmin-u-e5795dad4d22 svadmin-u-eb6e8b881acd svadmin-u-558f64349245 svadmin-u-92bf82f493b1"
|
|
385
461
|
role="group"
|
|
386
|
-
aria-labelledby=
|
|
387
|
-
aria-describedby={
|
|
462
|
+
aria-labelledby={labelId}
|
|
463
|
+
aria-describedby={describedBy}
|
|
388
464
|
data-invalid={invalid || undefined}
|
|
389
465
|
>
|
|
390
466
|
{#each field.options ?? [] as opt, _i (_i)}
|
|
391
467
|
<label class="svadmin-u-60fbb7713999 svadmin-u-3960ffc248d9 svadmin-u-77a2a20e90d4 svadmin-u-fc7473ca09eb svadmin-u-34516836730d svadmin-u-39f703dbe296 svadmin-u-07389a777c1f svadmin-u-d8e0e382c67b svadmin-u-465609a240a8 svadmin-u-ceb69a6b0e5f">
|
|
392
468
|
<Checkbox
|
|
393
|
-
id={`${
|
|
469
|
+
id={`${controlId}-option-${_i}`}
|
|
394
470
|
checked={multiVal.includes(opt.value)}
|
|
395
471
|
onCheckedChange={() => toggleMulti(opt.value)}
|
|
396
472
|
aria-invalid={invalid || undefined}
|
|
397
|
-
aria-describedby={
|
|
473
|
+
aria-describedby={describedBy}
|
|
398
474
|
disabled={disabled || opt.disabled}
|
|
399
475
|
/>
|
|
400
476
|
{opt.label}
|
|
@@ -417,14 +493,14 @@
|
|
|
417
493
|
{/if}
|
|
418
494
|
|
|
419
495
|
{:else if field.type === 'boolean'}
|
|
420
|
-
<input type="hidden" name={
|
|
496
|
+
<input type="hidden" name={nativeFieldName} value={String(boolVal)} {disabled} />
|
|
421
497
|
<div class="svadmin-u-60fbb7713999 svadmin-u-3960ffc248d9 svadmin-u-77a2a20e90d4 svadmin-u-6b7d6e21ccbd">
|
|
422
498
|
<Switch
|
|
423
|
-
id={
|
|
499
|
+
id={controlId}
|
|
424
500
|
checked={boolVal}
|
|
425
501
|
onCheckedChange={(v) => onchange(v)}
|
|
426
502
|
aria-invalid={invalid || undefined}
|
|
427
|
-
aria-describedby={
|
|
503
|
+
aria-describedby={describedBy}
|
|
428
504
|
disabled={disabled}
|
|
429
505
|
/>
|
|
430
506
|
<span class="svadmin-u-fc7473ca09eb svadmin-u-bfa603190748">{boolVal ? i18n.t('common.yes') : i18n.t('common.no')}</span>
|
|
@@ -432,21 +508,20 @@
|
|
|
432
508
|
|
|
433
509
|
{:else if field.type === 'tags'}
|
|
434
510
|
<TagsInput
|
|
435
|
-
name={`${field.key}[]`}
|
|
436
511
|
value={tagsVal}
|
|
437
512
|
onchange={onchange}
|
|
438
513
|
placeholder={i18n.t('field.tagsPlaceholder')}
|
|
439
514
|
required={field.required}
|
|
440
515
|
invalid={invalid}
|
|
441
|
-
describedby={errorId}
|
|
442
516
|
ariaLabel={field.label}
|
|
443
517
|
{disabled}
|
|
518
|
+
{...definedOptions({ name: nativeArrayName, describedby: describedBy })}
|
|
444
519
|
/>
|
|
445
520
|
|
|
446
521
|
{:else if field.type === 'date' || field.type === 'time' || field.type === 'datetime'}
|
|
447
522
|
<DateTimeInput
|
|
448
|
-
id={
|
|
449
|
-
name={
|
|
523
|
+
id={controlId}
|
|
524
|
+
name={nativeFieldName}
|
|
450
525
|
mode={field.type}
|
|
451
526
|
min={field.dateInput?.min}
|
|
452
527
|
max={field.dateInput?.max}
|
|
@@ -459,13 +534,13 @@
|
|
|
459
534
|
onchange={(next) => onchange(next)}
|
|
460
535
|
required={field.required}
|
|
461
536
|
invalid={invalid}
|
|
462
|
-
describedby={
|
|
537
|
+
describedby={describedBy}
|
|
463
538
|
{disabled}
|
|
464
539
|
/>
|
|
465
540
|
|
|
466
541
|
{:else if field.type === 'daterange'}
|
|
467
542
|
<DateRangeInput
|
|
468
|
-
startId={`${
|
|
543
|
+
startId={`${controlId}-start`}
|
|
469
544
|
mode={field.dateInput?.rangeMode ?? 'date'}
|
|
470
545
|
valueMode={field.dateInput?.valueMode}
|
|
471
546
|
timeZone={field.dateInput?.timeZone}
|
|
@@ -475,78 +550,116 @@
|
|
|
475
550
|
step={field.dateInput?.step}
|
|
476
551
|
disabledDate={field.dateInput?.disabledDate}
|
|
477
552
|
presets={field.dateInput?.presets}
|
|
478
|
-
endId={`${
|
|
553
|
+
endId={`${controlId}-end`}
|
|
479
554
|
startAriaLabel={`${field.label} ${i18n.t('common.startDate')}`}
|
|
480
555
|
endAriaLabel={`${field.label} ${i18n.t('common.endDate')}`}
|
|
481
|
-
startName={`${field.key}.start`}
|
|
482
|
-
endName={`${field.key}.end`}
|
|
483
556
|
value={value as DateRangeInputValue | null}
|
|
484
557
|
onchange={(next) => onchange(next)}
|
|
485
558
|
required={field.required}
|
|
486
559
|
invalid={invalid}
|
|
487
|
-
describedby={errorId}
|
|
488
560
|
{disabled}
|
|
561
|
+
{...definedOptions({
|
|
562
|
+
startName: nativeSubmit ? `${field.key}.start` : undefined,
|
|
563
|
+
endName: nativeSubmit ? `${field.key}.end` : undefined,
|
|
564
|
+
describedby: describedBy,
|
|
565
|
+
})}
|
|
489
566
|
/>
|
|
490
567
|
|
|
491
568
|
{:else if field.type === 'rate' || field.type === 'rating'}
|
|
492
569
|
<Rate
|
|
493
|
-
name={
|
|
570
|
+
name={nativeFieldName}
|
|
494
571
|
value={numVal ?? 0}
|
|
495
572
|
onchange={onchange}
|
|
496
573
|
required={field.required}
|
|
497
574
|
invalid={invalid}
|
|
498
|
-
describedby={errorId}
|
|
499
575
|
ariaLabel={field.label}
|
|
500
576
|
{disabled}
|
|
577
|
+
{...definedOptions({ describedby: describedBy })}
|
|
501
578
|
/>
|
|
502
579
|
|
|
503
580
|
{:else if field.type === 'file'}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
581
|
+
{#if fileReferenceMode || upload}
|
|
582
|
+
<!-- AutoForm 显式 JSON 文件模式:只写入可序列化引用。 -->
|
|
583
|
+
{#key fileScopeKey}
|
|
584
|
+
<FileUploadField
|
|
585
|
+
id={controlId}
|
|
586
|
+
{field}
|
|
587
|
+
{value}
|
|
588
|
+
{onchange}
|
|
589
|
+
{invalid}
|
|
590
|
+
{...definedOptions({ describedby: describedBy })}
|
|
591
|
+
{...definedOptions({ disabled, upload, cancelUpload, onUploadStateChange })}
|
|
592
|
+
/>
|
|
593
|
+
{/key}
|
|
594
|
+
{:else}
|
|
595
|
+
<!-- 独立 FieldRenderer 保留原生 multipart 字段名与 File 值。 -->
|
|
596
|
+
<FileUpload
|
|
597
|
+
id={controlId}
|
|
598
|
+
name={field.key}
|
|
599
|
+
multiple={field.multiple}
|
|
600
|
+
required={field.required && !value}
|
|
601
|
+
disabled={disabled}
|
|
602
|
+
ariaLabel={field.label}
|
|
603
|
+
invalid={invalid}
|
|
604
|
+
{...definedOptions({ describedby: describedBy })}
|
|
605
|
+
accept={field.accept}
|
|
606
|
+
maxSize={field.maxSize}
|
|
607
|
+
onChange={(items) => onchange(field.multiple ? items.map(item => item.file) : items[0]?.file ?? null)}
|
|
608
|
+
/>
|
|
609
|
+
{/if}
|
|
514
610
|
|
|
515
611
|
{:else if field.type === 'images'}
|
|
516
612
|
{#each imagesVal as url, imageIndex (imageIndex)}
|
|
517
|
-
<input type="hidden" name={
|
|
613
|
+
<input type="hidden" name={nativeArrayName} value={url} {disabled} />
|
|
518
614
|
{/each}
|
|
519
615
|
<div class="svadmin-u-6f7e013d6499">
|
|
520
616
|
{#each imagesVal as url, i (i)}
|
|
521
617
|
<div class="svadmin-u-60fbb7713999 svadmin-u-3960ffc248d9 svadmin-u-77a2a20e90d4">
|
|
522
618
|
<Input
|
|
523
|
-
id={i === 0 ?
|
|
619
|
+
id={i === 0 ? controlId : undefined}
|
|
524
620
|
type="text"
|
|
525
621
|
value={url}
|
|
526
622
|
oninput={(e) => updateImage(i, (e.target as HTMLInputElement).value)}
|
|
527
623
|
placeholder="https://example.com/image.jpg"
|
|
528
624
|
class="svadmin-u-36e579c0b41c"
|
|
529
625
|
aria-invalid={invalid || undefined}
|
|
530
|
-
aria-describedby={
|
|
626
|
+
aria-describedby={describedBy}
|
|
531
627
|
{disabled}
|
|
532
628
|
/>
|
|
533
629
|
{#if url}
|
|
534
630
|
<div class="svadmin-u-665f07fe73cc svadmin-u-012fbd121f37"><MediaThumbnail src={url} alt="preview" size="full" fit="cover" showOverlay={false} /></div>
|
|
535
631
|
{/if}
|
|
536
|
-
<TooltipButton
|
|
632
|
+
<TooltipButton
|
|
633
|
+
tooltip={i18n.t('common.removeImage')}
|
|
634
|
+
variant="ghost"
|
|
635
|
+
size="icon"
|
|
636
|
+
class="svadmin-u-ed8a5df7b2fb svadmin-u-2bbcfc3b5179 svadmin-u-012fbd121f37"
|
|
637
|
+
aria-describedby={describedBy}
|
|
638
|
+
aria-invalid={invalid || undefined}
|
|
639
|
+
{disabled}
|
|
640
|
+
onclick={() => removeImage(i)}
|
|
641
|
+
>
|
|
537
642
|
<X class="svadmin-u-7fc7f732bf7e svadmin-u-bf600f8e029c" />
|
|
538
643
|
</TooltipButton>
|
|
539
644
|
</div>
|
|
540
645
|
{/each}
|
|
541
|
-
<Button
|
|
646
|
+
<Button
|
|
647
|
+
variant="outline"
|
|
648
|
+
size="sm"
|
|
649
|
+
type="button"
|
|
650
|
+
aria-describedby={describedBy}
|
|
651
|
+
aria-invalid={invalid || undefined}
|
|
652
|
+
{disabled}
|
|
653
|
+
onclick={addImage}
|
|
654
|
+
>
|
|
542
655
|
<Plus class="svadmin-u-7fc7f732bf7e svadmin-u-bf600f8e029c svadmin-u-618162408e7a" /> {i18n.t('field.addImage')}
|
|
543
656
|
</Button>
|
|
544
657
|
</div>
|
|
545
658
|
|
|
546
659
|
{:else if field.type === 'json'}
|
|
547
660
|
<Textarea
|
|
548
|
-
id={
|
|
549
|
-
name={
|
|
661
|
+
id={controlId}
|
|
662
|
+
name={nativeFieldName}
|
|
550
663
|
value={jsonEditText}
|
|
551
664
|
onfocus={() => { jsonEditing = true; }}
|
|
552
665
|
onblur={() => {
|
|
@@ -564,20 +677,20 @@
|
|
|
564
677
|
}}
|
|
565
678
|
{disabled}
|
|
566
679
|
aria-invalid={invalid || undefined}
|
|
567
|
-
aria-describedby={
|
|
680
|
+
aria-describedby={describedBy}
|
|
568
681
|
rows={6}
|
|
569
682
|
class="svadmin-u-5bd7b080992c svadmin-u-0e65706bcccd svadmin-u-359090c2d529"
|
|
570
683
|
/>
|
|
571
684
|
|
|
572
685
|
{:else}
|
|
573
686
|
<Input
|
|
574
|
-
id={
|
|
575
|
-
name={
|
|
687
|
+
id={controlId}
|
|
688
|
+
name={nativeFieldName}
|
|
576
689
|
type="text"
|
|
577
690
|
value={strVal}
|
|
578
691
|
oninput={(e) => onchange((e.target as HTMLInputElement).value)}
|
|
579
692
|
aria-invalid={invalid || undefined}
|
|
580
|
-
aria-describedby={
|
|
693
|
+
aria-describedby={describedBy}
|
|
581
694
|
{disabled}
|
|
582
695
|
/>
|
|
583
696
|
{/if}
|