@ditojs/admin 2.100.0 → 3.1.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/dito-admin.css +1 -1
- package/dist/dito-admin.es.js +3555 -2719
- package/dist/dito-admin.umd.js +5 -6
- package/package.json +84 -46
- package/src/DitoAdmin.js +1 -65
- package/src/DitoComponent.js +1 -1
- package/src/DitoContext.js +51 -0
- package/src/DitoTypeComponent.js +23 -1
- package/src/components/DitoAffixes.vue +6 -3
- package/src/components/DitoButtons.vue +14 -1
- package/src/components/DitoContainer.vue +19 -10
- package/src/components/DitoCreateButton.vue +11 -2
- package/src/components/DitoDialog.vue +21 -2
- package/src/components/DitoForm.vue +152 -84
- package/src/components/DitoLabel.vue +3 -2
- package/src/components/DitoPane.vue +55 -11
- package/src/components/DitoPanel.vue +34 -5
- package/src/components/DitoPanels.vue +2 -1
- package/src/components/DitoRoot.vue +6 -6
- package/src/components/DitoRouterView.vue +27 -0
- package/src/components/DitoSchema.vue +278 -145
- package/src/components/DitoSchemaInlined.vue +1 -1
- package/src/components/DitoTabs.vue +16 -18
- package/src/components/DitoTrail.vue +5 -4
- package/src/components/DitoTreeItem.vue +17 -6
- package/src/components/DitoView.vue +21 -3
- package/src/components/index.js +1 -0
- package/src/mixins/DitoMixin.js +53 -7
- package/src/mixins/ItemMixin.js +3 -6
- package/src/mixins/NumberMixin.js +47 -31
- package/src/mixins/OptionsMixin.js +132 -71
- package/src/mixins/ResourceMixin.js +5 -2
- package/src/mixins/RouteMixin.js +39 -1
- package/src/mixins/SortableMixin.js +0 -13
- package/src/mixins/SourceMixin.js +155 -96
- package/src/mixins/TextMixin.js +1 -1
- package/src/mixins/TypeMixin.js +37 -22
- package/src/mixins/ValidationMixin.js +9 -27
- package/src/mixins/ValidatorMixin.js +5 -7
- package/src/mixins/ValueMixin.js +5 -2
- package/src/types/DitoTypeButton.vue +1 -1
- package/src/types/DitoTypeCheckbox.vue +1 -1
- package/src/types/DitoTypeCheckboxes.vue +1 -1
- package/src/types/DitoTypeCode.vue +8 -1
- package/src/types/DitoTypeColor.vue +20 -34
- package/src/types/DitoTypeComponent.vue +1 -1
- package/src/types/DitoTypeComputed.vue +4 -27
- package/src/types/DitoTypeDate.vue +16 -5
- package/src/types/DitoTypeLabel.vue +1 -4
- package/src/types/DitoTypeList.vue +9 -5
- package/src/types/DitoTypeMarkup.vue +25 -13
- package/src/types/DitoTypeMultiselect.vue +37 -6
- package/src/types/DitoTypeNumber.vue +1 -1
- package/src/types/DitoTypeObject.vue +10 -7
- package/src/types/DitoTypePanel.vue +20 -6
- package/src/types/DitoTypeProgress.vue +1 -1
- package/src/types/DitoTypeRadio.vue +1 -1
- package/src/types/DitoTypeSection.vue +32 -4
- package/src/types/DitoTypeSelect.vue +1 -1
- package/src/types/DitoTypeSlider.vue +1 -1
- package/src/types/DitoTypeSwitch.vue +1 -1
- package/src/types/DitoTypeText.vue +13 -15
- package/src/types/DitoTypeTextarea.vue +1 -1
- package/src/types/DitoTypeTreeList.vue +5 -7
- package/src/types/DitoTypeUpload.vue +1 -2
- package/src/utils/DataSchemaResolver.js +154 -0
- package/src/utils/FormModel.js +615 -0
- package/src/utils/data.js +20 -0
- package/src/utils/filter.js +3 -2
- package/src/utils/options.js +3 -0
- package/src/utils/request.js +70 -0
- package/src/utils/schema/data.js +659 -0
- package/src/utils/schema/lookup.js +250 -0
- package/src/utils/schema/setup.js +354 -0
- package/src/utils/schema/structure.js +172 -0
- package/src/utils/schema/types.js +34 -0
- package/src/utils/schema/validation.js +142 -0
- package/src/utils/units.js +70 -3
- package/types/index.d.ts +174 -59
- package/src/mixins/DataMixin.js +0 -131
- package/src/utils/schema.js +0 -1121
package/types/index.d.ts
CHANGED
|
@@ -52,6 +52,12 @@ export type RequestMethod = <T>(options: {
|
|
|
52
52
|
headers?: Record<string, string> | null
|
|
53
53
|
/** Abort signal to cancel the request. */
|
|
54
54
|
signal?: AbortSignal | null
|
|
55
|
+
/**
|
|
56
|
+
* Milliseconds after which the request is aborted.
|
|
57
|
+
*
|
|
58
|
+
* @defaultValue {@link ApiConfig.timeout}
|
|
59
|
+
*/
|
|
60
|
+
timeout?: number | null
|
|
55
61
|
}) => Promise<RequestMethodResponse<T>>
|
|
56
62
|
|
|
57
63
|
/**
|
|
@@ -170,6 +176,14 @@ export interface ApiConfig {
|
|
|
170
176
|
*/
|
|
171
177
|
durationFactor: number
|
|
172
178
|
}
|
|
179
|
+
/**
|
|
180
|
+
* Milliseconds after which requests are aborted, so that
|
|
181
|
+
* nothing waits for them forever, e.g. submitting forms for
|
|
182
|
+
* pending loads of options. Requests can set their own.
|
|
183
|
+
*
|
|
184
|
+
* @defaultValue `null`, no timeout
|
|
185
|
+
*/
|
|
186
|
+
timeout?: number | null
|
|
173
187
|
/**
|
|
174
188
|
* CORS settings applied to API requests (where
|
|
175
189
|
* {@link ApiConfig.isApiUrl} returns `true`).
|
|
@@ -326,9 +340,15 @@ export interface BaseSchema<$Item>
|
|
|
326
340
|
*/
|
|
327
341
|
default?: OrItemAccessor<$Item>
|
|
328
342
|
/**
|
|
329
|
-
* Computes and sets the field value reactively
|
|
330
|
-
* the
|
|
331
|
-
*
|
|
343
|
+
* Computes and sets the field value reactively, also
|
|
344
|
+
* when the field isn't rendered, unless its `if`
|
|
345
|
+
* evaluates to `false`. If the callback returns
|
|
346
|
+
* `undefined`, the current value is preserved.
|
|
347
|
+
*
|
|
348
|
+
* As it doesn't depend on the field's component, the
|
|
349
|
+
* context's component properties, e.g. `component`
|
|
350
|
+
* and `schemaComponent`, refer to the form, view or
|
|
351
|
+
* dialog that holds the data, not to the field.
|
|
332
352
|
*/
|
|
333
353
|
compute?: ItemAccessor<$Item>
|
|
334
354
|
/**
|
|
@@ -367,19 +387,26 @@ export interface SchemaDitoMixin<$Item> {
|
|
|
367
387
|
* change before value validation occurs. Rule changes do not influence how
|
|
368
388
|
* the component is rendered.
|
|
369
389
|
*/
|
|
370
|
-
rules?:
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
390
|
+
rules?: SchemaRules
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Validation rules shared by all schemas, extended by the individual types.
|
|
395
|
+
*/
|
|
396
|
+
export interface SchemaRules {
|
|
397
|
+
/** Override whether the field is required. */
|
|
398
|
+
required?: boolean
|
|
374
399
|
}
|
|
375
400
|
|
|
376
401
|
/**
|
|
377
402
|
* Return false to mark event as handled and stop it from propagating to parent
|
|
378
403
|
* schemas.
|
|
379
404
|
*/
|
|
405
|
+
// Handlers can be async, as events are awaited, e.g. by buttons that show
|
|
406
|
+
// their progress while their `click` handler runs.
|
|
380
407
|
export type ItemEventHandler<$Item = any> = (
|
|
381
408
|
itemParams: DitoContext<$Item>
|
|
382
|
-
) => void | false
|
|
409
|
+
) => void | false | Promise<void | false>
|
|
383
410
|
|
|
384
411
|
export type OpenEventHandler<$Item = any> = (
|
|
385
412
|
itemParams: DitoContext<$Item> & { open: boolean }
|
|
@@ -565,14 +592,20 @@ export interface SchemaTypeMixin<$Item> extends SchemaFields<$Item> {
|
|
|
565
592
|
* @see {@link SchemaFields.onInitialize} and other `on`-
|
|
566
593
|
* prefixed properties for per-event documentation.
|
|
567
594
|
*/
|
|
568
|
-
events?:
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
595
|
+
events?: BaseSchemaEvents<$Item>
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Grouped event handlers shared by all schemas, extended by the individual
|
|
600
|
+
* types.
|
|
601
|
+
*/
|
|
602
|
+
export interface BaseSchemaEvents<$Item> extends SchemaEvents<$Item> {
|
|
603
|
+
/** @see {@link BaseSchema.onFocus} */
|
|
604
|
+
focus?: ItemEventHandler<$Item>
|
|
605
|
+
/** @see {@link BaseSchema.onBlur} */
|
|
606
|
+
blur?: ItemEventHandler<$Item>
|
|
607
|
+
/** @see {@link BaseSchema.onInput} */
|
|
608
|
+
input?: ItemEventHandler<$Item>
|
|
576
609
|
}
|
|
577
610
|
|
|
578
611
|
export interface SchemaSourceMixin<$Item> {
|
|
@@ -643,9 +676,18 @@ export interface SchemaSourceMixin<$Item> {
|
|
|
643
676
|
/** Buttons for the source. */
|
|
644
677
|
buttons?: Buttons<$Item>
|
|
645
678
|
/**
|
|
646
|
-
*
|
|
679
|
+
* The key under which primitive values are wrapped in objects, so that the
|
|
680
|
+
* source's forms can edit them, e.g. `'value'` for a list of strings.
|
|
647
681
|
*/
|
|
648
|
-
wrapPrimitives?:
|
|
682
|
+
wrapPrimitives?: string
|
|
683
|
+
/**
|
|
684
|
+
* Whether the forms of the source's items directly mutate the source's data
|
|
685
|
+
* instead of editing a copy that is applied when submitting. Forms that
|
|
686
|
+
* mutate data are never dirty.
|
|
687
|
+
*
|
|
688
|
+
* @defaultValue `false`
|
|
689
|
+
*/
|
|
690
|
+
mutate?: boolean
|
|
649
691
|
/**
|
|
650
692
|
* URL path for the source items.
|
|
651
693
|
*/
|
|
@@ -722,7 +764,9 @@ export interface SchemaSourceMixin<$Item> {
|
|
|
722
764
|
deletable?: OrItemAccessor<$Item, {}, boolean | { label: string }>
|
|
723
765
|
/**
|
|
724
766
|
* The column used for the order resulting from dragging around list entries
|
|
725
|
-
* when the `draggable` property of the list schema is set to `true`.
|
|
767
|
+
* when the `draggable` property of the list schema is set to `true`. Items
|
|
768
|
+
* are numbered when the data is loaded, and when they are added, removed or
|
|
769
|
+
* reordered.
|
|
726
770
|
*/
|
|
727
771
|
orderKey?: string
|
|
728
772
|
/**
|
|
@@ -772,6 +816,12 @@ export type SchemaOptions<$Item, $Option = any> =
|
|
|
772
816
|
* receives the `DitoContext` and returns an inner
|
|
773
817
|
* function that is called to fetch the actual data,
|
|
774
818
|
* enabling reactive dependency tracking.
|
|
819
|
+
*
|
|
820
|
+
* The options are loaded independently of the
|
|
821
|
+
* field's component, also for computes, so the
|
|
822
|
+
* context's component properties, e.g. `component`
|
|
823
|
+
* and `schemaComponent`, refer to the form, view or
|
|
824
|
+
* dialog that holds the data, not to the field.
|
|
775
825
|
*/
|
|
776
826
|
data?: OrItemAccessor<
|
|
777
827
|
$Item,
|
|
@@ -919,14 +969,15 @@ export interface SchemaNumberMixin<$Item> {
|
|
|
919
969
|
*/
|
|
920
970
|
step?: OrItemAccessor<$Item, {}, number>
|
|
921
971
|
/**
|
|
922
|
-
* The amount of decimals
|
|
972
|
+
* The maximum amount of decimals allowed, validated on input.
|
|
923
973
|
*/
|
|
924
974
|
decimals?: OrItemAccessor<$Item, {}, number>
|
|
925
975
|
/** Validation rules for numeric constraints. */
|
|
926
|
-
rules?:
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
976
|
+
rules?: SchemaRules &
|
|
977
|
+
Omit<SchemaNumberMixin<$Item>, 'rules'> & {
|
|
978
|
+
/** Restrict the value to whole numbers. */
|
|
979
|
+
integer?: boolean
|
|
980
|
+
}
|
|
930
981
|
}
|
|
931
982
|
|
|
932
983
|
export interface SchemaTextMixin<$Item> {
|
|
@@ -964,7 +1015,7 @@ export interface SchemaDataMixin<$Item> {
|
|
|
964
1015
|
/**
|
|
965
1016
|
* Data source for the component.
|
|
966
1017
|
*/
|
|
967
|
-
data?: OrItemAccessor<$Item, {}, any
|
|
1018
|
+
data?: OrItemAccessor<$Item, {}, Record<string, any>>
|
|
968
1019
|
/**
|
|
969
1020
|
* Path to retrieve data from parent context.
|
|
970
1021
|
*/
|
|
@@ -1128,7 +1179,7 @@ export interface InputSchema<$Item = any>
|
|
|
1128
1179
|
| 'tel'
|
|
1129
1180
|
| 'password'
|
|
1130
1181
|
| 'creditcard'
|
|
1131
|
-
rules?: {
|
|
1182
|
+
rules?: SchemaRules & {
|
|
1132
1183
|
text?: boolean
|
|
1133
1184
|
email?: boolean
|
|
1134
1185
|
url?: boolean
|
|
@@ -1180,7 +1231,7 @@ export interface ButtonSchema<$Item = any>
|
|
|
1180
1231
|
onClick?: ItemEventHandler<$Item>
|
|
1181
1232
|
onSuccess?: ItemEventHandler<$Item>
|
|
1182
1233
|
onError?: ErrorEventHandler<$Item>
|
|
1183
|
-
events?: {
|
|
1234
|
+
events?: BaseSchemaEvents<$Item> & {
|
|
1184
1235
|
click?: ItemEventHandler<$Item>
|
|
1185
1236
|
success?: ItemEventHandler<$Item>
|
|
1186
1237
|
error?: ErrorEventHandler<$Item>
|
|
@@ -1209,8 +1260,9 @@ export interface SwitchSchema<$Item = any> extends BaseSchema<$Item> {
|
|
|
1209
1260
|
}
|
|
1210
1261
|
|
|
1211
1262
|
export interface NumberSchema<$Item = any>
|
|
1263
|
+
// `rules` comes from `SchemaNumberMixin`, which extends `SchemaRules`.
|
|
1212
1264
|
extends SchemaNumberMixin<$Item>,
|
|
1213
|
-
BaseSchema<$Item>,
|
|
1265
|
+
Omit<BaseSchema<$Item>, 'rules'>,
|
|
1214
1266
|
SchemaAffixMixin<$Item> {
|
|
1215
1267
|
/**
|
|
1216
1268
|
* The type of the component.
|
|
@@ -1219,8 +1271,9 @@ export interface NumberSchema<$Item = any>
|
|
|
1219
1271
|
}
|
|
1220
1272
|
|
|
1221
1273
|
export interface SliderSchema<$Item = any>
|
|
1274
|
+
// `rules` comes from `SchemaNumberMixin`, which extends `SchemaRules`.
|
|
1222
1275
|
extends SchemaNumberMixin<$Item>,
|
|
1223
|
-
BaseSchema<$Item> {
|
|
1276
|
+
Omit<BaseSchema<$Item>, 'rules'> {
|
|
1224
1277
|
/**
|
|
1225
1278
|
* The type of the component.
|
|
1226
1279
|
*/
|
|
@@ -1400,9 +1453,8 @@ export interface UploadSchema<$Item = any> extends BaseSchema<$Item> {
|
|
|
1400
1453
|
accept?: OrArrayOf<string>
|
|
1401
1454
|
/**
|
|
1402
1455
|
* The maximum size of the file expressed as number of bytes or as a string
|
|
1403
|
-
* like `'
|
|
1404
|
-
*
|
|
1405
|
-
* @see {@link https://github.com/patrickkettner/filesize-parser/blob/master/test.js String Examples}
|
|
1456
|
+
* like `'200kB'`, `'1MB'`, `'3.2GB'`, etc., using base 10 (1 kB = 1000
|
|
1457
|
+
* bytes). IEC units like `'1MiB'` use base 2 (1 KiB = 1024 bytes).
|
|
1406
1458
|
*/
|
|
1407
1459
|
maxSize?: string | number
|
|
1408
1460
|
/**
|
|
@@ -1502,7 +1554,7 @@ type SectionContent<$Data> = {
|
|
|
1502
1554
|
/**
|
|
1503
1555
|
* A form schema for the section's content. Use this
|
|
1504
1556
|
* instead of `components` to get form-level options
|
|
1505
|
-
* like `label
|
|
1557
|
+
* like `label` and `tabs`.
|
|
1506
1558
|
*/
|
|
1507
1559
|
form?: ResolvableForm<$Data>
|
|
1508
1560
|
/**
|
|
@@ -1679,7 +1731,9 @@ export type ColorFormat =
|
|
|
1679
1731
|
| 'hsl'
|
|
1680
1732
|
| 'hsv'
|
|
1681
1733
|
export interface ColorSchema<$Item = any>
|
|
1682
|
-
|
|
1734
|
+
// `format` is the color format here, not the formatting function of
|
|
1735
|
+
// `BaseSchema`.
|
|
1736
|
+
extends Omit<BaseSchema<$Item>, 'format'>,
|
|
1683
1737
|
SchemaAffixMixin<$Item> {
|
|
1684
1738
|
/**
|
|
1685
1739
|
* The type of the component.
|
|
@@ -1801,7 +1855,7 @@ export interface ListSchema<$Item = { [key: string]: any }>
|
|
|
1801
1855
|
/**
|
|
1802
1856
|
* Grouped event handlers.
|
|
1803
1857
|
*/
|
|
1804
|
-
events?: {
|
|
1858
|
+
events?: BaseSchemaEvents<$Item> & {
|
|
1805
1859
|
/**
|
|
1806
1860
|
* Called when a collapsible inlined list is
|
|
1807
1861
|
* toggled open or closed.
|
|
@@ -1930,7 +1984,12 @@ export type DitoContext<$Item = any> = {
|
|
|
1930
1984
|
sourceComponent: DitoSourceInstance | null
|
|
1931
1985
|
/** The currently focused option in a select. */
|
|
1932
1986
|
option: any
|
|
1933
|
-
/**
|
|
1987
|
+
/**
|
|
1988
|
+
* All available options in a select. In `compute()`, they are
|
|
1989
|
+
* loaded when first read, also when the field isn't rendered,
|
|
1990
|
+
* and are `undefined` while loading; the callback runs again
|
|
1991
|
+
* once they are loaded.
|
|
1992
|
+
*/
|
|
1934
1993
|
options: any
|
|
1935
1994
|
/**
|
|
1936
1995
|
* Whether a pulldown/select is currently open.
|
|
@@ -2062,6 +2121,14 @@ export interface DitoComponentInstanceBase<$Item = any>
|
|
|
2062
2121
|
name: string
|
|
2063
2122
|
/** Full dot-separated path to the current data. */
|
|
2064
2123
|
dataPath: string
|
|
2124
|
+
/**
|
|
2125
|
+
* The path of component names through views, tabs,
|
|
2126
|
+
* panels and forms, with item indices from the data
|
|
2127
|
+
* path, e.g. `main/chapters/0/title`. Unlike
|
|
2128
|
+
* `dataPath`, it tells apart components that display
|
|
2129
|
+
* the same data. Used as the component's DOM id.
|
|
2130
|
+
*/
|
|
2131
|
+
componentPath: string
|
|
2065
2132
|
/** The schema definition for the current component. */
|
|
2066
2133
|
schema: Component
|
|
2067
2134
|
/** The component type from the schema. */
|
|
@@ -2409,6 +2476,36 @@ export interface DitoFormInstance<$Item = any>
|
|
|
2409
2476
|
*/
|
|
2410
2477
|
isCreating: boolean
|
|
2411
2478
|
|
|
2479
|
+
/**
|
|
2480
|
+
* Whether the form's processed data differs from
|
|
2481
|
+
* the data it was loaded, saved or applied with.
|
|
2482
|
+
* Values that are derived when the data is set up,
|
|
2483
|
+
* e.g. defaults and computed values, don't count.
|
|
2484
|
+
* Forms with `mutate: true` aren't dirty
|
|
2485
|
+
* themselves, their changes make the form that
|
|
2486
|
+
* owns the data dirty.
|
|
2487
|
+
*/
|
|
2488
|
+
isDirty: boolean
|
|
2489
|
+
|
|
2490
|
+
/**
|
|
2491
|
+
* Makes clean changes to the data, which don't
|
|
2492
|
+
* make the form dirty, while other changes still
|
|
2493
|
+
* do, e.g. to apply what an action on the server
|
|
2494
|
+
* already saved. `makeChanges()` is called
|
|
2495
|
+
* synchronously, the returned promise resolves
|
|
2496
|
+
* once the values derived from the changes are
|
|
2497
|
+
* clean too.
|
|
2498
|
+
*
|
|
2499
|
+
* @example
|
|
2500
|
+
* ```js
|
|
2501
|
+
* const shopOrder = await request({ method: 'post', url })
|
|
2502
|
+
* formComponent.applyCleanChanges(() => {
|
|
2503
|
+
* item.templateShopOrder = shopOrder
|
|
2504
|
+
* })
|
|
2505
|
+
* ```
|
|
2506
|
+
*/
|
|
2507
|
+
applyCleanChanges(makeChanges: () => void): Promise<void>
|
|
2508
|
+
|
|
2412
2509
|
/**
|
|
2413
2510
|
* Submits the form data to the API. Returns
|
|
2414
2511
|
* `true` on success, `false` if validation
|
|
@@ -2435,7 +2532,9 @@ export interface DitoFormInstance<$Item = any>
|
|
|
2435
2532
|
close(): Promise<void>
|
|
2436
2533
|
|
|
2437
2534
|
/**
|
|
2438
|
-
* Validates all fields in the form
|
|
2535
|
+
* Validates all fields in the form's data, including
|
|
2536
|
+
* fields that aren't rendered, e.g. in collapsed
|
|
2537
|
+
* sections or closed nested forms. Optionally
|
|
2439
2538
|
* filter fields with a match pattern. Returns
|
|
2440
2539
|
* `true` if all matched fields are valid.
|
|
2441
2540
|
*/
|
|
@@ -2497,8 +2596,12 @@ export interface DitoFormInstance<$Item = any>
|
|
|
2497
2596
|
ensureData(): void
|
|
2498
2597
|
/** Clears the loaded data. */
|
|
2499
2598
|
clearData(): void
|
|
2500
|
-
/**
|
|
2501
|
-
|
|
2599
|
+
/**
|
|
2600
|
+
* Sets the component's loaded data directly, and
|
|
2601
|
+
* returns it as the component's reactive data,
|
|
2602
|
+
* which can be modified to update it.
|
|
2603
|
+
*/
|
|
2604
|
+
setData(data: any): any
|
|
2502
2605
|
/**
|
|
2503
2606
|
* Creates a new data object with default values
|
|
2504
2607
|
* from the schema. Optionally sets a `type`
|
|
@@ -2576,13 +2679,17 @@ export interface DitoViewInstance<$Item = any>
|
|
|
2576
2679
|
* a resource.
|
|
2577
2680
|
*/
|
|
2578
2681
|
providesData: boolean
|
|
2579
|
-
/**
|
|
2580
|
-
|
|
2682
|
+
/**
|
|
2683
|
+
* Sets the view's data directly, and returns it
|
|
2684
|
+
* as the view's reactive data.
|
|
2685
|
+
*/
|
|
2686
|
+
setData(data: any): any
|
|
2581
2687
|
|
|
2582
2688
|
// -- Validation (ValidatorMixin) --
|
|
2583
2689
|
|
|
2584
2690
|
/**
|
|
2585
|
-
* Validates all fields in the view
|
|
2691
|
+
* Validates all fields in the view's data,
|
|
2692
|
+
* including fields that aren't rendered.
|
|
2586
2693
|
* Optionally filter fields with a match pattern.
|
|
2587
2694
|
* Returns `true` if all matched fields are valid.
|
|
2588
2695
|
*/
|
|
@@ -2611,9 +2718,12 @@ export interface DitoViewInstance<$Item = any>
|
|
|
2611
2718
|
export interface DitoSchemaInstance<$Item = any>
|
|
2612
2719
|
extends DitoComponentInstanceBase<$Item> {
|
|
2613
2720
|
/**
|
|
2614
|
-
* Validates all fields in the schema
|
|
2721
|
+
* Validates all fields in the schema's data,
|
|
2722
|
+
* including fields that aren't rendered, e.g. in
|
|
2723
|
+
* collapsed sections or closed nested forms.
|
|
2615
2724
|
* Optionally filter fields with a match pattern
|
|
2616
|
-
* (string, string[], RegExp, or function)
|
|
2725
|
+
* (string, string[], RegExp, or function) over
|
|
2726
|
+
* their data paths.
|
|
2617
2727
|
* Returns `true` if all matched fields are
|
|
2618
2728
|
* valid.
|
|
2619
2729
|
*/
|
|
@@ -2717,11 +2827,14 @@ export interface DitoSourceInstance<$Item = any>
|
|
|
2717
2827
|
deleteItem(item: any, index: number): void
|
|
2718
2828
|
/**
|
|
2719
2829
|
* Navigates to a component identified by its
|
|
2720
|
-
* data path.
|
|
2830
|
+
* data path. With `shouldRevealInlinedOnly`, only
|
|
2831
|
+
* components in inlined schemas are revealed,
|
|
2832
|
+
* without navigating to nested forms.
|
|
2721
2833
|
*/
|
|
2722
2834
|
navigateToComponent(
|
|
2723
2835
|
dataPath: string,
|
|
2724
|
-
onComplete?: Function
|
|
2836
|
+
onComplete?: Function,
|
|
2837
|
+
options?: { shouldRevealInlinedOnly?: boolean }
|
|
2725
2838
|
): Promise<boolean>
|
|
2726
2839
|
/**
|
|
2727
2840
|
* Navigates to the route component associated
|
|
@@ -2756,8 +2869,12 @@ export interface DitoSourceInstance<$Item = any>
|
|
|
2756
2869
|
ensureData(): void
|
|
2757
2870
|
/** Clears the loaded data. */
|
|
2758
2871
|
clearData(): void
|
|
2759
|
-
/**
|
|
2760
|
-
|
|
2872
|
+
/**
|
|
2873
|
+
* Sets the component's loaded data directly, and
|
|
2874
|
+
* returns it as the component's reactive data,
|
|
2875
|
+
* which can be modified to update it.
|
|
2876
|
+
*/
|
|
2877
|
+
setData(data: any): any
|
|
2761
2878
|
/**
|
|
2762
2879
|
* Creates a new data object with default values
|
|
2763
2880
|
* from the schema. Optionally sets a `type`
|
|
@@ -2883,7 +3000,7 @@ export interface ObjectSchema<$Item = { [key: string]: any }>
|
|
|
2883
3000
|
/**
|
|
2884
3001
|
* Grouped event handlers.
|
|
2885
3002
|
*/
|
|
2886
|
-
events?: {
|
|
3003
|
+
events?: BaseSchemaEvents<$Item> & {
|
|
2887
3004
|
/**
|
|
2888
3005
|
* Called when a collapsible inlined object is
|
|
2889
3006
|
* toggled open or closed.
|
|
@@ -2953,8 +3070,9 @@ export interface SpacerSchema<$Item = any> extends BaseSchema<$Item> {
|
|
|
2953
3070
|
}
|
|
2954
3071
|
|
|
2955
3072
|
export interface ProgressSchema<$Item = any>
|
|
3073
|
+
// `rules` comes from `SchemaNumberMixin`, which extends `SchemaRules`.
|
|
2956
3074
|
extends SchemaNumberMixin<$Item>,
|
|
2957
|
-
BaseSchema<$Item> {
|
|
3075
|
+
Omit<BaseSchema<$Item>, 'rules'> {
|
|
2958
3076
|
/**
|
|
2959
3077
|
* The type of the component.
|
|
2960
3078
|
*/
|
|
@@ -2993,6 +3111,7 @@ type NonSectionComponent<$Item = any> =
|
|
|
2993
3111
|
export type Component<$Item = any> =
|
|
2994
3112
|
| NonSectionComponent<$Item>
|
|
2995
3113
|
| SectionSchema<$Item>
|
|
3114
|
+
| PanelSchema<$Item>
|
|
2996
3115
|
|
|
2997
3116
|
/**
|
|
2998
3117
|
* Source components (list, object, tree) that contain nested
|
|
@@ -3107,11 +3226,14 @@ export type Components<$Item = any> = 0 extends 1 & $Item
|
|
|
3107
3226
|
? Record<string, Component>
|
|
3108
3227
|
: {
|
|
3109
3228
|
[K in keyof $Item]?: [$Item[K]] extends [never]
|
|
3110
|
-
?
|
|
3229
|
+
? // Sections and panels that share the data of their schema.
|
|
3230
|
+
NonSectionComponent<$Item> | SectionSchema<$Item> | PanelSchema<$Item>
|
|
3111
3231
|
: NonNullable<$Item[K]> extends (infer E)[]
|
|
3112
3232
|
? E extends Record<string, any>
|
|
3113
3233
|
? NonSectionComponent<E>
|
|
3114
|
-
:
|
|
3234
|
+
: // Lists of primitive values edit them wrapped in objects under
|
|
3235
|
+
// the key given by `wrapPrimitives`, see `SchemaSourceMixin`.
|
|
3236
|
+
NonSectionComponent<Record<string, E>>
|
|
3115
3237
|
: NonNullable<$Item[K]> extends Record<string, any>
|
|
3116
3238
|
?
|
|
3117
3239
|
| NonOptionFieldComponent<$Item>
|
|
@@ -3147,13 +3269,6 @@ export interface Form<$Item = any> extends SchemaRoute<$Item> {
|
|
|
3147
3269
|
* The label of the form.
|
|
3148
3270
|
*/
|
|
3149
3271
|
label?: OrItemAccessor<$Item, {}, string | boolean>
|
|
3150
|
-
/**
|
|
3151
|
-
* Whether the form directly mutates the parent data instead
|
|
3152
|
-
* of working on a copy.
|
|
3153
|
-
*
|
|
3154
|
-
* @defaultValue `false`
|
|
3155
|
-
*/
|
|
3156
|
-
mutate?: boolean
|
|
3157
3272
|
/**
|
|
3158
3273
|
* The property name used as the item's unique identifier.
|
|
3159
3274
|
*
|
package/src/mixins/DataMixin.js
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
isObject,
|
|
3
|
-
isFunction,
|
|
4
|
-
isPromise,
|
|
5
|
-
normalizeDataPath,
|
|
6
|
-
getValueAtDataPath
|
|
7
|
-
} from '@ditojs/utils'
|
|
8
|
-
import { markRaw, ref } from 'vue'
|
|
9
|
-
import LoadingMixin from './LoadingMixin.js'
|
|
10
|
-
|
|
11
|
-
// @vue/component
|
|
12
|
-
export default {
|
|
13
|
-
mixins: [LoadingMixin],
|
|
14
|
-
|
|
15
|
-
data() {
|
|
16
|
-
return {
|
|
17
|
-
isLoading: false,
|
|
18
|
-
asyncDataEntries: markRaw({})
|
|
19
|
-
}
|
|
20
|
-
},
|
|
21
|
-
|
|
22
|
-
methods: {
|
|
23
|
-
handleDataSchema(schema, name, loadingOptions) {
|
|
24
|
-
if (!isObject(schema)) {
|
|
25
|
-
schema = { data: schema }
|
|
26
|
-
}
|
|
27
|
-
let { data = undefined, dataPath = null } = schema
|
|
28
|
-
// Create a reactive entry for the async data, if it doesn't exist yet.
|
|
29
|
-
// NOTE: `markRaw()` is used to avoid reactivity on `asyncDataEntries`
|
|
30
|
-
// itself, as reactivity is only desired on `reactiveVersion`, which is
|
|
31
|
-
// used to trigger controlled reevaluation of the computed getter.
|
|
32
|
-
const asyncEntry = (this.asyncDataEntries[name] ??= {
|
|
33
|
-
reactiveVersion: ref(1),
|
|
34
|
-
dependencyFunction: null,
|
|
35
|
-
resolvedData: undefined,
|
|
36
|
-
resolving: false,
|
|
37
|
-
resolved: false
|
|
38
|
-
})
|
|
39
|
-
// If the data callback provided a dependency function when it was called,
|
|
40
|
-
// cal it in every call of `handleDataSchema()` to force Vue to keep track
|
|
41
|
-
// of the async dependencies. Also access `reactiveVersion.value` right
|
|
42
|
-
// away, to ensure that the reactive property is tracked as a dependency:
|
|
43
|
-
asyncEntry.reactiveVersion.value &&
|
|
44
|
-
asyncEntry.dependencyFunction?.(this.context)
|
|
45
|
-
|
|
46
|
-
if (asyncEntry.resolved) {
|
|
47
|
-
// If the data was resolved already, return it and clear the resolved
|
|
48
|
-
// value. This works because Vue caches the result of computed getters
|
|
49
|
-
// and only reevaluates if one of the dependencies changed. This is to
|
|
50
|
-
// ensure that a cached value here doesn't block / override
|
|
51
|
-
// reevaluation when a dependency changes:
|
|
52
|
-
const { resolvedData } = asyncEntry
|
|
53
|
-
asyncEntry.resolvedData = undefined
|
|
54
|
-
asyncEntry.resolved = false
|
|
55
|
-
return resolvedData
|
|
56
|
-
}
|
|
57
|
-
// Avoid calling the data function twice:
|
|
58
|
-
if (asyncEntry.resolving) {
|
|
59
|
-
data = null
|
|
60
|
-
} else if (data) {
|
|
61
|
-
if (isFunction(data)) {
|
|
62
|
-
const result = data(this.context)
|
|
63
|
-
// If the result of the data function is another function, then the
|
|
64
|
-
// first data function is there to track dependencies and the real
|
|
65
|
-
// data loading happens in the function that it returned. Keep track
|
|
66
|
-
// it in `dependencyFunction` so it can be called on each call of
|
|
67
|
-
// `handleDataSchema()` to keep the dependencies intact, and call
|
|
68
|
-
// the function that it returned once to get the actual data:
|
|
69
|
-
if (isFunction(result)) {
|
|
70
|
-
asyncEntry.dependencyFunction = data
|
|
71
|
-
data = result(this.context)
|
|
72
|
-
} else {
|
|
73
|
-
data = result
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
// NOTE: If the data is not a promise, it is resolved already.
|
|
77
|
-
if (isPromise(data)) {
|
|
78
|
-
// If the data is asynchronous, it can't be returned straight away.
|
|
79
|
-
// But we can cheat using computed properties and `resolvedData`,
|
|
80
|
-
// which is going to receive the loaded data asynchronously,
|
|
81
|
-
// triggering a recompute of the computed property that calls
|
|
82
|
-
// `handleDataSchema()`.
|
|
83
|
-
asyncEntry.resolving = true
|
|
84
|
-
this.resolveData(data, loadingOptions)
|
|
85
|
-
.then(data => {
|
|
86
|
-
asyncEntry.resolvedData = data
|
|
87
|
-
asyncEntry.resolving = false
|
|
88
|
-
asyncEntry.resolved = true
|
|
89
|
-
// Trigger reevaluation of the computed getter by increasing the
|
|
90
|
-
// `reactiveVersion` value.
|
|
91
|
-
asyncEntry.reactiveVersion.value++
|
|
92
|
-
})
|
|
93
|
-
.catch(error => {
|
|
94
|
-
console.error(error)
|
|
95
|
-
asyncEntry.resolving = false
|
|
96
|
-
})
|
|
97
|
-
// Clear data until promise is resolved and `resolvedData` is set
|
|
98
|
-
data = null
|
|
99
|
-
}
|
|
100
|
-
} else if (dataPath) {
|
|
101
|
-
data = getValueAtDataPath(
|
|
102
|
-
this.rootData,
|
|
103
|
-
normalizeDataPath(`${this.dataPath}/${dataPath}`)
|
|
104
|
-
)
|
|
105
|
-
}
|
|
106
|
-
return data
|
|
107
|
-
},
|
|
108
|
-
|
|
109
|
-
async resolveData(load, loadingOptions = {}) {
|
|
110
|
-
// Use a timeout to allow already resolved promises to return data without
|
|
111
|
-
// showing a loading indicator.
|
|
112
|
-
let clearLoading = false
|
|
113
|
-
const timer = setTimeout(() => {
|
|
114
|
-
this.setLoading(true, loadingOptions)
|
|
115
|
-
clearLoading = true
|
|
116
|
-
}, 0)
|
|
117
|
-
let data = null
|
|
118
|
-
try {
|
|
119
|
-
data = await (isFunction(load) ? load() : load)
|
|
120
|
-
} catch (error) {
|
|
121
|
-
this.addError(error.message || error)
|
|
122
|
-
}
|
|
123
|
-
if (clearLoading) {
|
|
124
|
-
this.setLoading(false, loadingOptions)
|
|
125
|
-
} else {
|
|
126
|
-
clearTimeout(timer)
|
|
127
|
-
}
|
|
128
|
-
return data
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|