@ditojs/admin 2.7.5 → 2.8.1
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.es.js +1417 -1376
- package/dist/dito-admin.umd.js +5 -5
- package/dist/style.css +1 -1
- package/package.json +5 -5
- package/src/DitoContext.js +4 -0
- package/src/DitoTypeComponent.js +1 -1
- package/src/components/DitoClipboard.vue +22 -0
- package/src/components/DitoContainer.vue +7 -12
- package/src/components/DitoCreateButton.vue +21 -1
- package/src/components/DitoDialog.vue +5 -0
- package/src/components/DitoEditButtons.vue +35 -25
- package/src/components/DitoElement.vue +2 -2
- package/src/components/DitoForm.vue +9 -4
- package/src/components/DitoHeader.vue +22 -6
- package/src/components/DitoLabel.vue +41 -23
- package/src/components/DitoPane.vue +47 -35
- package/src/components/DitoRoot.vue +1 -2
- package/src/components/DitoSchema.vue +139 -165
- package/src/components/DitoSchemaInlined.vue +12 -9
- package/src/components/DitoTabs.vue +65 -23
- package/src/components/DitoTreeItem.vue +1 -1
- package/src/components/DitoView.vue +0 -1
- package/src/mixins/DitoMixin.js +6 -5
- package/src/mixins/ItemMixin.js +5 -1
- package/src/mixins/TypeMixin.js +14 -30
- package/src/styles/_button.scss +13 -12
- package/src/styles/_settings.scss +2 -2
- package/src/types/DitoTypeList.vue +1 -1
- package/src/types/DitoTypeMultiselect.vue +2 -3
- package/src/types/DitoTypeObject.vue +6 -4
- package/src/types/DitoTypePanel.vue +1 -1
- package/src/types/DitoTypeSection.vue +38 -10
- package/src/types/DitoTypeSelect.vue +2 -1
- package/src/types/DitoTypeUpload.vue +2 -2
- package/src/utils/options.js +1 -1
- package/src/utils/schema.js +8 -6
- package/types/index.d.ts +1 -1
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
<template lang="pug">
|
|
3
3
|
.dito-pane(
|
|
4
4
|
v-if="isPopulated && componentSchemas.length > 0"
|
|
5
|
-
v-show="visible"
|
|
6
5
|
:class=`{
|
|
7
6
|
'dito-pane--single': isSingleComponent
|
|
8
7
|
}`
|
|
@@ -16,7 +15,9 @@
|
|
|
16
15
|
store
|
|
17
16
|
}, index in componentSchemas`
|
|
18
17
|
)
|
|
19
|
-
.dito-break
|
|
18
|
+
// -Use <span> for .dito-break so we can use `.dito-container:first-of-type`
|
|
19
|
+
// selector.
|
|
20
|
+
span.dito-break(
|
|
20
21
|
v-if="schema.break === 'before'"
|
|
21
22
|
)
|
|
22
23
|
DitoContainer(
|
|
@@ -35,7 +36,7 @@
|
|
|
35
36
|
:verticalLabels="isInLabeledRow(index)"
|
|
36
37
|
:accumulatedBasis="accumulatedBasis"
|
|
37
38
|
)
|
|
38
|
-
.dito-break(
|
|
39
|
+
span.dito-break(
|
|
39
40
|
v-if="schema.break === 'after'"
|
|
40
41
|
)
|
|
41
42
|
</template>
|
|
@@ -61,7 +62,6 @@ export default DitoComponent.component('DitoPane', {
|
|
|
61
62
|
store: { type: Object, required: true },
|
|
62
63
|
tab: { type: String, default: null },
|
|
63
64
|
single: { type: Boolean, default: false },
|
|
64
|
-
visible: { type: Boolean, default: true },
|
|
65
65
|
disabled: { type: Boolean, default: false },
|
|
66
66
|
generateLabels: { type: Boolean, default: false },
|
|
67
67
|
accumulatedBasis: { type: Number, default: null }
|
|
@@ -102,7 +102,7 @@ export default DitoComponent.component('DitoPane', {
|
|
|
102
102
|
: this.dataPath,
|
|
103
103
|
nestedDataPath,
|
|
104
104
|
nested,
|
|
105
|
-
store:
|
|
105
|
+
store: this.getChildStore(name)
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
)
|
|
@@ -149,8 +149,12 @@ export default DitoComponent.component('DitoPane', {
|
|
|
149
149
|
for (const index of row) {
|
|
150
150
|
const position = this.positions[index]
|
|
151
151
|
if (
|
|
152
|
-
position?.height >
|
|
153
|
-
|
|
152
|
+
position?.height > 2 && (
|
|
153
|
+
position.node.matches(':has(> .dito-label)') ||
|
|
154
|
+
position.node
|
|
155
|
+
.closest('.dito-container')
|
|
156
|
+
.matches('.dito-container--label-vertical')
|
|
157
|
+
)
|
|
154
158
|
) {
|
|
155
159
|
// TODO: Handle nested schemas, e.g. 'section' or 'object' and
|
|
156
160
|
// detect labels there too.
|
|
@@ -215,57 +219,65 @@ export default DitoComponent.component('DitoPane', {
|
|
|
215
219
|
|
|
216
220
|
.dito-pane {
|
|
217
221
|
$self: &;
|
|
222
|
+
$root-padding: $content-padding - $form-spacing-half;
|
|
218
223
|
|
|
219
224
|
display: flex;
|
|
220
225
|
position: relative;
|
|
221
226
|
flex-flow: row wrap;
|
|
222
227
|
align-items: flex-start;
|
|
223
228
|
align-content: flex-start;
|
|
224
|
-
padding: $content-padding;
|
|
225
229
|
// Remove the padding added by `.dito-container` inside `.dito-pane`:
|
|
226
|
-
margin:
|
|
227
|
-
|
|
228
|
-
// Use `flex: 0%` for all `.dito-pane` except `.dito-pane-main`,
|
|
230
|
+
margin: -$form-spacing-half;
|
|
231
|
+
// Use `flex: 0%` for all `.dito-pane` except `.dito-pane__main`,
|
|
229
232
|
// so that the `.dito-buttons-main` can be moved all the way to the bottom.
|
|
230
233
|
flex: 0%;
|
|
231
234
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
margin: 0;
|
|
235
|
+
&__main {
|
|
236
|
+
flex: 100%;
|
|
235
237
|
}
|
|
236
238
|
|
|
237
239
|
.dito-scroll > & {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
240
|
+
// A root-level pane inside a scroll view. Clear negative margin from above.
|
|
241
|
+
margin: 0;
|
|
242
|
+
// Move the negative margin used to remove the padding added by
|
|
243
|
+
// `.dito-container` inside `.dito-pane` to the padding:
|
|
244
|
+
padding: $root-padding;
|
|
242
245
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
// used to remove the padding added by `.dito-container` inside
|
|
246
|
-
// `.dito-pane` to the padding:
|
|
247
|
-
padding: ($content-padding - $form-spacing)
|
|
248
|
-
($content-padding - $form-spacing-half);
|
|
249
|
-
margin: 0;
|
|
246
|
+
&#{$self}--single {
|
|
247
|
+
padding: $content-padding;
|
|
250
248
|
}
|
|
251
|
-
}
|
|
252
249
|
|
|
253
|
-
|
|
254
|
-
|
|
250
|
+
&:has(> .dito-container--label-vertical:first-of-type) {
|
|
251
|
+
// Reduce top spacing when the first row has labels.
|
|
252
|
+
margin-top: -$form-spacing-half;
|
|
253
|
+
}
|
|
255
254
|
}
|
|
256
255
|
|
|
257
|
-
.dito-
|
|
258
|
-
|
|
259
|
-
|
|
256
|
+
// Display a ruler between tabbed components and towards the .dito-buttons
|
|
257
|
+
&__tab + &__main {
|
|
258
|
+
&::before {
|
|
259
|
+
// Use a pseudo element to display a ruler with proper margins
|
|
260
|
+
display: block;
|
|
261
|
+
content: '';
|
|
262
|
+
width: 100%;
|
|
263
|
+
border-bottom: $border-style;
|
|
264
|
+
// Shift ruler up by $root-padding to exclude removed $form-spacing-half.
|
|
265
|
+
margin: (-$root-padding) $form-spacing-half $root-padding;
|
|
266
|
+
padding: $form-spacing-half;
|
|
267
|
+
}
|
|
260
268
|
}
|
|
261
269
|
|
|
262
|
-
.dito-
|
|
263
|
-
//
|
|
264
|
-
margin:
|
|
265
|
-
|
|
270
|
+
&__main + .dito-buttons-main {
|
|
271
|
+
// Needed forms with sticky main buttons.
|
|
272
|
+
margin: $content-padding;
|
|
273
|
+
margin-bottom: 0;
|
|
266
274
|
}
|
|
267
275
|
|
|
268
276
|
.dito-break {
|
|
277
|
+
// `.dito-break` is rendered as <span> so we can use the
|
|
278
|
+
// `.dito-container:first-of-type` selector to match the first container
|
|
279
|
+
// even if it has a break before it.
|
|
280
|
+
display: block;
|
|
269
281
|
flex: 100%;
|
|
270
282
|
height: 0;
|
|
271
283
|
}
|
|
@@ -37,8 +37,6 @@
|
|
|
37
37
|
)
|
|
38
38
|
span Login
|
|
39
39
|
.dito-fill
|
|
40
|
-
.dito-header
|
|
41
|
-
span
|
|
42
40
|
</template>
|
|
43
41
|
|
|
44
42
|
<script>
|
|
@@ -478,6 +476,7 @@ function addRoutes(router, routes) {
|
|
|
478
476
|
flex: 0 1 var(--max-page-width);
|
|
479
477
|
background: $content-color-background;
|
|
480
478
|
max-width: var(--max-page-width);
|
|
479
|
+
overflow: visible; // For .dito-header full-width background.
|
|
481
480
|
// For the `@container` rule in `.dito-container` to work:
|
|
482
481
|
container-type: inline-size;
|
|
483
482
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
2
|
slot(name="before")
|
|
3
3
|
.dito-schema(
|
|
4
|
+
:class="{ 'dito-scroll-parent': scrollable, 'dito-schema--open': opened }"
|
|
4
5
|
v-bind="$attrs"
|
|
5
6
|
)
|
|
6
7
|
Teleport(
|
|
@@ -14,64 +15,64 @@ slot(name="before")
|
|
|
14
15
|
:store="store"
|
|
15
16
|
:disabled="disabled"
|
|
16
17
|
)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
:
|
|
18
|
+
Teleport(
|
|
19
|
+
v-if="hasHeader"
|
|
20
|
+
:to="headerTeleport"
|
|
21
|
+
:disabled="!headerTeleport"
|
|
20
22
|
)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
:
|
|
23
|
+
.dito-schema-header
|
|
24
|
+
DitoLabel(
|
|
25
|
+
v-if="hasLabel"
|
|
26
|
+
:label="label"
|
|
27
|
+
:dataPath="dataPath"
|
|
28
|
+
:collapsible="collapsible"
|
|
29
|
+
:collapsed="!opened"
|
|
30
|
+
@open="onOpen"
|
|
31
|
+
)
|
|
32
|
+
Transition(
|
|
33
|
+
v-if="tabs"
|
|
34
|
+
name="dito-fade"
|
|
28
35
|
)
|
|
29
|
-
DitoLabel(
|
|
30
|
-
v-if="hasLabel"
|
|
31
|
-
:label="label"
|
|
32
|
-
:dataPath="dataPath"
|
|
33
|
-
:collapsible="collapsible"
|
|
34
|
-
:collapsed="!opened"
|
|
35
|
-
@expand="onExpand"
|
|
36
|
-
)
|
|
37
|
-
//- Pass edit-buttons through to dito-label's own edit-buttons slot:
|
|
38
|
-
template(
|
|
39
|
-
v-if="inlined"
|
|
40
|
-
#edit-buttons
|
|
41
|
-
)
|
|
42
|
-
slot(name="edit-buttons")
|
|
43
36
|
DitoTabs(
|
|
44
|
-
v-if="
|
|
37
|
+
v-if="opened"
|
|
38
|
+
v-model="selectedTab"
|
|
45
39
|
:tabs="tabs"
|
|
46
|
-
:selectedTab="selectedTab"
|
|
47
|
-
)
|
|
48
|
-
DitoClipboard(
|
|
49
|
-
:clipboard="clipboard"
|
|
50
|
-
:dataPath="dataPath"
|
|
51
|
-
:data="data"
|
|
52
40
|
)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
)
|
|
56
|
-
DitoPane.dito-pane-tab(
|
|
57
|
-
v-for="(tabSchema, tab) in tabs"
|
|
58
|
-
ref="tabs"
|
|
59
|
-
:key="tab"
|
|
60
|
-
:visible="selectedTab === tab"
|
|
61
|
-
:tab="tab"
|
|
62
|
-
:schema="tabSchema"
|
|
41
|
+
DitoClipboard(
|
|
42
|
+
:clipboard="clipboard"
|
|
63
43
|
:dataPath="dataPath"
|
|
64
44
|
:data="data"
|
|
65
|
-
:meta="meta"
|
|
66
|
-
:store="store"
|
|
67
|
-
:single="!inlined && !hasMainPane"
|
|
68
|
-
:disabled="disabled"
|
|
69
|
-
:generateLabels="generateLabels"
|
|
70
|
-
:accumulatedBasis="accumulatedBasis"
|
|
71
45
|
)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
46
|
+
slot(name="edit-buttons")
|
|
47
|
+
TransitionHeight(:enabled="inlined")
|
|
48
|
+
.dito-schema-content(
|
|
49
|
+
v-if="opened"
|
|
50
|
+
ref="content"
|
|
51
|
+
:class="{ 'dito-scroll': scrollable }"
|
|
52
|
+
)
|
|
53
|
+
template(
|
|
54
|
+
v-if="hasTabs"
|
|
55
|
+
)
|
|
56
|
+
template(
|
|
57
|
+
v-for="(tabSchema, tab) in tabs"
|
|
58
|
+
)
|
|
59
|
+
DitoPane.dito-pane__tab(
|
|
60
|
+
v-if="selectedTab === tab"
|
|
61
|
+
ref="tabs"
|
|
62
|
+
:key="tab"
|
|
63
|
+
:tab="tab"
|
|
64
|
+
:schema="tabSchema"
|
|
65
|
+
:dataPath="dataPath"
|
|
66
|
+
:data="data"
|
|
67
|
+
:meta="meta"
|
|
68
|
+
:store="store"
|
|
69
|
+
:single="!inlined && !hasMainPane"
|
|
70
|
+
:disabled="disabled"
|
|
71
|
+
:generateLabels="generateLabels"
|
|
72
|
+
:accumulatedBasis="accumulatedBasis"
|
|
73
|
+
)
|
|
74
|
+
DitoPane.dito-pane__main(
|
|
75
|
+
v-if="hasMainPane"
|
|
75
76
|
ref="components"
|
|
76
77
|
:schema="schema"
|
|
77
78
|
:dataPath="dataPath"
|
|
@@ -83,17 +84,14 @@ slot(name="before")
|
|
|
83
84
|
:generateLabels="generateLabels"
|
|
84
85
|
:accumulatedBasis="accumulatedBasis"
|
|
85
86
|
)
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
v-if="inlined"
|
|
87
|
+
slot(
|
|
88
|
+
v-if="!inlined && isPopulated"
|
|
89
|
+
name="buttons"
|
|
90
|
+
)
|
|
91
|
+
slot(
|
|
92
|
+
v-if="inlined && !hasHeader"
|
|
93
|
+
name="edit-buttons"
|
|
92
94
|
)
|
|
93
|
-
slot(
|
|
94
|
-
v-if="!hasLabel"
|
|
95
|
-
name="edit-buttons"
|
|
96
|
-
)
|
|
97
95
|
slot(name="after")
|
|
98
96
|
</template>
|
|
99
97
|
|
|
@@ -103,6 +101,7 @@ import {
|
|
|
103
101
|
isArray,
|
|
104
102
|
isFunction,
|
|
105
103
|
isRegExp,
|
|
104
|
+
equals,
|
|
106
105
|
parseDataPath,
|
|
107
106
|
normalizeDataPath,
|
|
108
107
|
labelize
|
|
@@ -148,8 +147,8 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
148
147
|
collapsible: { type: Boolean, default: false },
|
|
149
148
|
scrollable: { type: Boolean, default: false },
|
|
150
149
|
hasOwnData: { type: Boolean, default: false },
|
|
151
|
-
headerInMenu: { type: Boolean, default: false },
|
|
152
150
|
generateLabels: { type: Boolean, default: false },
|
|
151
|
+
labelNode: { type: HTMLElement, default: null },
|
|
153
152
|
accumulatedBasis: { type: Number, default: 1 }
|
|
154
153
|
},
|
|
155
154
|
|
|
@@ -190,25 +189,25 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
190
189
|
return getNamedSchemas(this.schema.tabs)
|
|
191
190
|
},
|
|
192
191
|
|
|
193
|
-
selectedTab
|
|
194
|
-
|
|
192
|
+
selectedTab: {
|
|
193
|
+
get() {
|
|
194
|
+
return this.currentTab || this.defaultTab || null
|
|
195
|
+
},
|
|
196
|
+
|
|
197
|
+
set(selectedTab) {
|
|
198
|
+
this.currentTab = selectedTab
|
|
199
|
+
}
|
|
195
200
|
},
|
|
196
201
|
|
|
197
202
|
defaultTab() {
|
|
198
203
|
let first = null
|
|
199
204
|
if (this.tabs) {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
if (
|
|
203
|
-
|
|
204
|
-
? defaultTab(this.context)
|
|
205
|
-
: defaultTab
|
|
206
|
-
) {
|
|
207
|
-
return tab
|
|
208
|
-
}
|
|
209
|
-
if (!first) {
|
|
210
|
-
first = tab
|
|
205
|
+
const tabs = Object.values(this.tabs).filter(this.shouldRenderSchema)
|
|
206
|
+
for (const { name, defaultTab } of tabs) {
|
|
207
|
+
if (isFunction(defaultTab) ? defaultTab(this.context) : defaultTab) {
|
|
208
|
+
return name
|
|
211
209
|
}
|
|
210
|
+
first ??= name
|
|
212
211
|
}
|
|
213
212
|
}
|
|
214
213
|
return first
|
|
@@ -218,6 +217,16 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
218
217
|
return this.schema?.clipboard
|
|
219
218
|
},
|
|
220
219
|
|
|
220
|
+
hasHeader() {
|
|
221
|
+
return this.hasLabel || this.hasTabs || !!this.clipboard
|
|
222
|
+
},
|
|
223
|
+
|
|
224
|
+
headerTeleport() {
|
|
225
|
+
return this.isRootSchema
|
|
226
|
+
? '.dito-header__teleport'
|
|
227
|
+
: this.labelNode
|
|
228
|
+
},
|
|
229
|
+
|
|
221
230
|
parentData() {
|
|
222
231
|
const data = getParentItem(this.rootData, this.dataPath, false)
|
|
223
232
|
return data !== this.data ? data : null
|
|
@@ -266,6 +275,11 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
266
275
|
)
|
|
267
276
|
},
|
|
268
277
|
|
|
278
|
+
isRootSchema() {
|
|
279
|
+
// Section schemas can share the root dataPath but they are inlined.
|
|
280
|
+
return this.dataPath === '' && !this.inlined
|
|
281
|
+
},
|
|
282
|
+
|
|
269
283
|
isDirty() {
|
|
270
284
|
return this.someComponent(it => it.isDirty)
|
|
271
285
|
},
|
|
@@ -295,7 +309,11 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
295
309
|
},
|
|
296
310
|
|
|
297
311
|
hasTabs() {
|
|
298
|
-
return
|
|
312
|
+
return !!this.tabs
|
|
313
|
+
},
|
|
314
|
+
|
|
315
|
+
hasMainTabs() {
|
|
316
|
+
return this.hasTabs && this.isRootSchema
|
|
299
317
|
},
|
|
300
318
|
|
|
301
319
|
hasMainPane() {
|
|
@@ -348,27 +366,21 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
348
366
|
// Remember the current path to know if tab changes should still be
|
|
349
367
|
// handled, but remove the trailing `/create` or `/:id` from it so that
|
|
350
368
|
// tabs informs that stay open after creation still work.
|
|
351
|
-
if (this.
|
|
369
|
+
if (this.hasMainTabs) {
|
|
352
370
|
this.currentTab = hash?.slice(1) || null
|
|
353
|
-
if (this.hasErrors) {
|
|
354
|
-
this.repositionErrors()
|
|
355
|
-
}
|
|
356
371
|
}
|
|
357
372
|
}
|
|
358
373
|
},
|
|
359
374
|
|
|
360
375
|
'selectedTab'(selectedTab) {
|
|
361
|
-
if (this.
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
if (tab) {
|
|
370
|
-
this.$router.replace({ hash: `#${tab}` })
|
|
371
|
-
}
|
|
376
|
+
if (this.hasMainTabs) {
|
|
377
|
+
const tab = this.shouldRenderSchema(this.tabs[selectedTab])
|
|
378
|
+
? selectedTab
|
|
379
|
+
: this.defaultTab
|
|
380
|
+
this.$router.replace({ hash: tab ? `#${tab}` : null })
|
|
381
|
+
}
|
|
382
|
+
if (this.hasErrors) {
|
|
383
|
+
this.repositionErrors()
|
|
372
384
|
}
|
|
373
385
|
}
|
|
374
386
|
},
|
|
@@ -441,11 +453,8 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
441
453
|
return this.isPopulated && this.components.every(callback)
|
|
442
454
|
},
|
|
443
455
|
|
|
444
|
-
|
|
445
|
-
this.emitEvent('
|
|
446
|
-
// TODO: Actually expose this on DitoContext?
|
|
447
|
-
context: { expand }
|
|
448
|
-
})
|
|
456
|
+
onOpen(open) {
|
|
457
|
+
this.emitEvent('open', { context: { open } })
|
|
449
458
|
// Prevent closing the schema with invalid data, since the in-component
|
|
450
459
|
// validation will not be executed once it's closed.
|
|
451
460
|
|
|
@@ -453,8 +462,8 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
453
462
|
// processing, and use `showValidationErrors()` for the resulting errors,
|
|
454
463
|
// then remove this requirement, since we can validate closed forms and
|
|
455
464
|
// schemas then.
|
|
456
|
-
if (!this.opened ||
|
|
457
|
-
this.opened =
|
|
465
|
+
if (!this.opened || open || this.validateAll()) {
|
|
466
|
+
this.opened = open
|
|
458
467
|
}
|
|
459
468
|
},
|
|
460
469
|
|
|
@@ -630,9 +639,12 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
630
639
|
for (const name in data) {
|
|
631
640
|
if (name in this.data) {
|
|
632
641
|
// eslint-disable-next-line vue/no-mutating-props
|
|
633
|
-
this.data[name]
|
|
634
|
-
|
|
635
|
-
|
|
642
|
+
if (!equals(this.data[name], data[name])) {
|
|
643
|
+
// eslint-disable-next-line vue/no-mutating-props
|
|
644
|
+
this.data[name] = data[name]
|
|
645
|
+
for (const component of this.getComponentsByName(name)) {
|
|
646
|
+
component.markDirty()
|
|
647
|
+
}
|
|
636
648
|
}
|
|
637
649
|
}
|
|
638
650
|
}
|
|
@@ -733,10 +745,22 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
733
745
|
|
|
734
746
|
.dito-schema {
|
|
735
747
|
box-sizing: border-box;
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
748
|
+
|
|
749
|
+
> .dito-schema-header + .dito-schema-content > .dito-pane {
|
|
750
|
+
margin-top: $form-spacing-half;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
&:has(> .dito-schema-content + .dito-edit-buttons) {
|
|
754
|
+
// Display the edit buttons to the right of the schema:
|
|
755
|
+
display: flex;
|
|
756
|
+
flex-direction: row;
|
|
757
|
+
align-items: stretch;
|
|
758
|
+
|
|
759
|
+
> .dito-edit-buttons {
|
|
760
|
+
flex: 1 0 0%;
|
|
761
|
+
margin-left: $form-spacing;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
740
764
|
|
|
741
765
|
> .dito-schema-content {
|
|
742
766
|
flex: 0 1 100%;
|
|
@@ -751,37 +775,6 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
751
775
|
> *:only-child {
|
|
752
776
|
grid-row-end: none;
|
|
753
777
|
}
|
|
754
|
-
|
|
755
|
-
&.dito-scroll:has(.dito-pane:last-child)::after {
|
|
756
|
-
// Eat up negative margin of the last child to prevent overscroll.
|
|
757
|
-
content: '';
|
|
758
|
-
}
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
> .dito-buttons {
|
|
762
|
-
flex: 1 1 0%;
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
> .dito-buttons {
|
|
766
|
-
margin-left: $form-spacing;
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
// Display a ruler between tabbed components and towards the .dito-buttons
|
|
770
|
-
.dito-pane-tab + .dito-pane-main {
|
|
771
|
-
&::before {
|
|
772
|
-
// Use a pseudo element to display a ruler with proper margins
|
|
773
|
-
display: block;
|
|
774
|
-
content: '';
|
|
775
|
-
width: 100%;
|
|
776
|
-
border-bottom: $border-style;
|
|
777
|
-
// Add removed $form-spacing again to the ruler
|
|
778
|
-
margin: $content-padding $form-spacing-half $form-spacing-half;
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
|
|
782
|
-
.dito-pane-main + .dito-buttons-main {
|
|
783
|
-
// Needed forms with sticky main buttons.
|
|
784
|
-
margin-bottom: 0;
|
|
785
778
|
}
|
|
786
779
|
}
|
|
787
780
|
|
|
@@ -789,41 +782,22 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
789
782
|
display: flex;
|
|
790
783
|
justify-content: space-between;
|
|
791
784
|
|
|
792
|
-
.dito-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
align-self: flex-end;
|
|
785
|
+
.dito-header & {
|
|
786
|
+
// When teleported into main header.
|
|
787
|
+
align-items: flex-end;
|
|
796
788
|
}
|
|
797
789
|
|
|
798
|
-
.dito-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
790
|
+
.dito-label & {
|
|
791
|
+
// When teleported into container label.
|
|
792
|
+
flex: 1;
|
|
793
|
+
}
|
|
802
794
|
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
}
|
|
795
|
+
> .dito-label {
|
|
796
|
+
margin-bottom: 0;
|
|
806
797
|
}
|
|
807
798
|
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
position: absolute;
|
|
811
|
-
height: $header-height;
|
|
812
|
-
padding: 0 $header-padding-hor;
|
|
813
|
-
top: 0;
|
|
814
|
-
left: 0;
|
|
815
|
-
right: 0;
|
|
816
|
-
z-index: $z-index-header;
|
|
817
|
-
// Turn off pointer events so that DitoTrail keeps receiving events...
|
|
818
|
-
pointer-events: none;
|
|
819
|
-
// ...but allow interaction with the tabs and buttons (e.g. clipboard)
|
|
820
|
-
// layered on top of DitoTrail.
|
|
821
|
-
.dito-tabs,
|
|
822
|
-
.dito-buttons {
|
|
823
|
-
pointer-events: auto;
|
|
824
|
-
line-height: $header-line-height;
|
|
825
|
-
font-size: $header-font-size;
|
|
826
|
-
}
|
|
799
|
+
> .dito-buttons {
|
|
800
|
+
margin-left: var(--button-margin, 0);
|
|
827
801
|
}
|
|
828
802
|
}
|
|
829
803
|
</style>
|
|
@@ -12,6 +12,7 @@ DitoSchema.dito-schema-inlined(
|
|
|
12
12
|
:collapsed="collapsed"
|
|
13
13
|
:collapsible="collapsible"
|
|
14
14
|
:generateLabels="!isCompact"
|
|
15
|
+
:labelNode="labelNode"
|
|
15
16
|
:accumulatedBasis="accumulatedBasis"
|
|
16
17
|
)
|
|
17
18
|
//- Render dito-edit-buttons for inlined schemas separately from all
|
|
@@ -54,6 +55,7 @@ export default DitoComponent.component('DitoSchemaInlined', {
|
|
|
54
55
|
editable: { type: Boolean, default: false },
|
|
55
56
|
deletable: { type: Boolean, default: false },
|
|
56
57
|
editPath: { type: String, default: null },
|
|
58
|
+
labelNode: { type: HTMLElement, default: null },
|
|
57
59
|
accumulatedBasis: { type: Number, default: null }
|
|
58
60
|
},
|
|
59
61
|
|
|
@@ -73,25 +75,26 @@ export default DitoComponent.component('DitoSchemaInlined', {
|
|
|
73
75
|
@import '../styles/_imports';
|
|
74
76
|
|
|
75
77
|
.dito-schema-inlined {
|
|
78
|
+
// Use grid layout for two reasons: For `TransitionHeight` to work smoothly,
|
|
79
|
+
// and to align the header above the content when the header is not teleported
|
|
80
|
+
// outside of the schema.
|
|
81
|
+
display: grid;
|
|
82
|
+
grid-template-rows: min-content;
|
|
83
|
+
grid-template-columns: 100%;
|
|
84
|
+
|
|
76
85
|
> .dito-schema-content {
|
|
77
86
|
> .dito-schema-header {
|
|
78
|
-
|
|
79
|
-
|
|
87
|
+
justify-content: space-between;
|
|
88
|
+
position: relative;
|
|
80
89
|
|
|
81
90
|
.dito-label {
|
|
82
|
-
// Add removed $form-spacing again.
|
|
83
|
-
margin: $form-spacing;
|
|
84
91
|
width: 100%;
|
|
85
|
-
|
|
92
|
+
margin: 0;
|
|
86
93
|
// Prevent collapsing to min-height when alone in
|
|
87
94
|
// .dito-schema-content, due to grid-template-rows: min-content
|
|
88
95
|
min-height: $input-height;
|
|
89
96
|
}
|
|
90
97
|
}
|
|
91
|
-
|
|
92
|
-
> .dito-pane {
|
|
93
|
-
padding: 0;
|
|
94
|
-
}
|
|
95
98
|
}
|
|
96
99
|
}
|
|
97
100
|
</style>
|