@ditojs/admin 2.7.4 → 2.8.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.es.js +1769 -1705
- 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 +26 -11
- package/src/components/DitoDialog.vue +14 -3
- package/src/components/DitoEditButtons.vue +20 -9
- package/src/components/DitoForm.vue +17 -12
- package/src/components/DitoHeader.vue +22 -6
- package/src/components/DitoLabel.vue +39 -22
- package/src/components/DitoPane.vue +43 -35
- package/src/components/DitoRoot.vue +1 -2
- package/src/components/DitoSchema.vue +137 -165
- package/src/components/DitoSchemaInlined.vue +17 -13
- 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 +8 -7
- package/src/mixins/ItemMixin.js +5 -1
- package/src/mixins/TypeMixin.js +5 -0
- package/src/styles/_button.scss +13 -12
- package/src/styles/_settings.scss +2 -2
- package/src/types/DitoTypeList.vue +12 -9
- package/src/types/DitoTypeMultiselect.vue +3 -4
- package/src/types/DitoTypeObject.vue +9 -6
- package/src/types/DitoTypePanel.vue +1 -1
- package/src/types/DitoTypeSection.vue +38 -10
- package/src/types/DitoTypeSelect.vue +3 -2
- 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.
|
|
@@ -221,51 +225,55 @@ export default DitoComponent.component('DitoPane', {
|
|
|
221
225
|
flex-flow: row wrap;
|
|
222
226
|
align-items: flex-start;
|
|
223
227
|
align-content: flex-start;
|
|
224
|
-
padding: $content-padding;
|
|
225
228
|
// 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`,
|
|
229
|
+
margin: -$form-spacing-half;
|
|
230
|
+
// Use `flex: 0%` for all `.dito-pane` except `.dito-pane__main`,
|
|
229
231
|
// so that the `.dito-buttons-main` can be moved all the way to the bottom.
|
|
230
232
|
flex: 0%;
|
|
231
233
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
margin: 0;
|
|
234
|
+
&__main {
|
|
235
|
+
flex: 100%;
|
|
235
236
|
}
|
|
236
237
|
|
|
237
238
|
.dito-scroll > & {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
239
|
+
// A root-level pane inside a scroll view. Clear negative margin from above.
|
|
240
|
+
margin: 0;
|
|
241
|
+
// Move the negative margin used to remove the padding added by
|
|
242
|
+
// `.dito-container` inside `.dito-pane` to the padding:
|
|
243
|
+
padding: $content-padding - $form-spacing-half;
|
|
242
244
|
|
|
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;
|
|
245
|
+
&#{$self}--single {
|
|
246
|
+
padding: $content-padding;
|
|
250
247
|
}
|
|
251
|
-
}
|
|
252
248
|
|
|
253
|
-
|
|
254
|
-
|
|
249
|
+
&:has(> .dito-container--label-vertical:first-of-type) {
|
|
250
|
+
// Reduce top spacing when the first row has labels.
|
|
251
|
+
margin-top: -$form-spacing-half;
|
|
252
|
+
}
|
|
255
253
|
}
|
|
256
254
|
|
|
257
|
-
.dito-
|
|
258
|
-
|
|
259
|
-
|
|
255
|
+
// Display a ruler between tabbed components and towards the .dito-buttons
|
|
256
|
+
&__tab + &__main {
|
|
257
|
+
&::before {
|
|
258
|
+
// Use a pseudo element to display a ruler with proper margins
|
|
259
|
+
display: block;
|
|
260
|
+
content: '';
|
|
261
|
+
width: 100%;
|
|
262
|
+
border-bottom: $border-style;
|
|
263
|
+
// Add removed $form-spacing-half again to the ruler
|
|
264
|
+
margin: (-$content-padding + $form-spacing-half) $form-spacing-half
|
|
265
|
+
$form-spacing-half;
|
|
266
|
+
}
|
|
260
267
|
}
|
|
261
268
|
|
|
262
|
-
.dito-
|
|
263
|
-
//
|
|
264
|
-
margin:
|
|
265
|
-
|
|
269
|
+
&__main + .dito-buttons-main {
|
|
270
|
+
// Needed forms with sticky main buttons.
|
|
271
|
+
margin: $content-padding;
|
|
272
|
+
margin-bottom: 0;
|
|
266
273
|
}
|
|
267
274
|
|
|
268
275
|
.dito-break {
|
|
276
|
+
display: block;
|
|
269
277
|
flex: 100%;
|
|
270
278
|
height: 0;
|
|
271
279
|
}
|
|
@@ -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,62 @@ 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
|
+
DitoPane.dito-pane__tab(
|
|
57
|
+
v-for="(tabSchema, tab) in tabs"
|
|
58
|
+
v-show="selectedTab === tab"
|
|
59
|
+
ref="tabs"
|
|
60
|
+
:key="tab"
|
|
61
|
+
:tab="tab"
|
|
62
|
+
:schema="tabSchema"
|
|
63
|
+
:dataPath="dataPath"
|
|
64
|
+
:data="data"
|
|
65
|
+
:meta="meta"
|
|
66
|
+
:store="store"
|
|
67
|
+
:single="!inlined && !hasMainPane"
|
|
68
|
+
:disabled="disabled"
|
|
69
|
+
:generateLabels="generateLabels"
|
|
70
|
+
:accumulatedBasis="accumulatedBasis"
|
|
71
|
+
)
|
|
72
|
+
DitoPane.dito-pane__main(
|
|
73
|
+
v-if="hasMainPane"
|
|
75
74
|
ref="components"
|
|
76
75
|
:schema="schema"
|
|
77
76
|
:dataPath="dataPath"
|
|
@@ -83,17 +82,14 @@ slot(name="before")
|
|
|
83
82
|
:generateLabels="generateLabels"
|
|
84
83
|
:accumulatedBasis="accumulatedBasis"
|
|
85
84
|
)
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
v-if="inlined"
|
|
85
|
+
slot(
|
|
86
|
+
v-if="!inlined && isPopulated"
|
|
87
|
+
name="buttons"
|
|
88
|
+
)
|
|
89
|
+
slot(
|
|
90
|
+
v-if="inlined && !hasHeader"
|
|
91
|
+
name="edit-buttons"
|
|
92
92
|
)
|
|
93
|
-
slot(
|
|
94
|
-
v-if="!hasLabel"
|
|
95
|
-
name="edit-buttons"
|
|
96
|
-
)
|
|
97
93
|
slot(name="after")
|
|
98
94
|
</template>
|
|
99
95
|
|
|
@@ -103,6 +99,7 @@ import {
|
|
|
103
99
|
isArray,
|
|
104
100
|
isFunction,
|
|
105
101
|
isRegExp,
|
|
102
|
+
equals,
|
|
106
103
|
parseDataPath,
|
|
107
104
|
normalizeDataPath,
|
|
108
105
|
labelize
|
|
@@ -148,8 +145,8 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
148
145
|
collapsible: { type: Boolean, default: false },
|
|
149
146
|
scrollable: { type: Boolean, default: false },
|
|
150
147
|
hasOwnData: { type: Boolean, default: false },
|
|
151
|
-
headerInMenu: { type: Boolean, default: false },
|
|
152
148
|
generateLabels: { type: Boolean, default: false },
|
|
149
|
+
labelNode: { type: HTMLElement, default: null },
|
|
153
150
|
accumulatedBasis: { type: Number, default: 1 }
|
|
154
151
|
},
|
|
155
152
|
|
|
@@ -190,25 +187,25 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
190
187
|
return getNamedSchemas(this.schema.tabs)
|
|
191
188
|
},
|
|
192
189
|
|
|
193
|
-
selectedTab
|
|
194
|
-
|
|
190
|
+
selectedTab: {
|
|
191
|
+
get() {
|
|
192
|
+
return this.currentTab || this.defaultTab || null
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
set(selectedTab) {
|
|
196
|
+
this.currentTab = selectedTab
|
|
197
|
+
}
|
|
195
198
|
},
|
|
196
199
|
|
|
197
200
|
defaultTab() {
|
|
198
201
|
let first = null
|
|
199
202
|
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
|
|
203
|
+
const tabs = Object.values(this.tabs).filter(this.shouldRenderSchema)
|
|
204
|
+
for (const { name, defaultTab } of tabs) {
|
|
205
|
+
if (isFunction(defaultTab) ? defaultTab(this.context) : defaultTab) {
|
|
206
|
+
return name
|
|
211
207
|
}
|
|
208
|
+
first ??= name
|
|
212
209
|
}
|
|
213
210
|
}
|
|
214
211
|
return first
|
|
@@ -218,6 +215,16 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
218
215
|
return this.schema?.clipboard
|
|
219
216
|
},
|
|
220
217
|
|
|
218
|
+
hasHeader() {
|
|
219
|
+
return this.hasLabel || this.hasTabs || !!this.clipboard
|
|
220
|
+
},
|
|
221
|
+
|
|
222
|
+
headerTeleport() {
|
|
223
|
+
return this.isRootSchema
|
|
224
|
+
? '.dito-header__teleport'
|
|
225
|
+
: this.labelNode
|
|
226
|
+
},
|
|
227
|
+
|
|
221
228
|
parentData() {
|
|
222
229
|
const data = getParentItem(this.rootData, this.dataPath, false)
|
|
223
230
|
return data !== this.data ? data : null
|
|
@@ -266,6 +273,11 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
266
273
|
)
|
|
267
274
|
},
|
|
268
275
|
|
|
276
|
+
isRootSchema() {
|
|
277
|
+
// Section schemas can share the root dataPath but they are inlined.
|
|
278
|
+
return this.dataPath === '' && !this.inlined
|
|
279
|
+
},
|
|
280
|
+
|
|
269
281
|
isDirty() {
|
|
270
282
|
return this.someComponent(it => it.isDirty)
|
|
271
283
|
},
|
|
@@ -295,7 +307,11 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
295
307
|
},
|
|
296
308
|
|
|
297
309
|
hasTabs() {
|
|
298
|
-
return
|
|
310
|
+
return !!this.tabs
|
|
311
|
+
},
|
|
312
|
+
|
|
313
|
+
hasMainTabs() {
|
|
314
|
+
return this.hasTabs && this.isRootSchema
|
|
299
315
|
},
|
|
300
316
|
|
|
301
317
|
hasMainPane() {
|
|
@@ -348,27 +364,21 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
348
364
|
// Remember the current path to know if tab changes should still be
|
|
349
365
|
// handled, but remove the trailing `/create` or `/:id` from it so that
|
|
350
366
|
// tabs informs that stay open after creation still work.
|
|
351
|
-
if (this.
|
|
367
|
+
if (this.hasMainTabs) {
|
|
352
368
|
this.currentTab = hash?.slice(1) || null
|
|
353
|
-
if (this.hasErrors) {
|
|
354
|
-
this.repositionErrors()
|
|
355
|
-
}
|
|
356
369
|
}
|
|
357
370
|
}
|
|
358
371
|
},
|
|
359
372
|
|
|
360
373
|
'selectedTab'(selectedTab) {
|
|
361
|
-
if (this.
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
if (tab) {
|
|
370
|
-
this.$router.replace({ hash: `#${tab}` })
|
|
371
|
-
}
|
|
374
|
+
if (this.hasMainTabs) {
|
|
375
|
+
const tab = this.shouldRenderSchema(this.tabs[selectedTab])
|
|
376
|
+
? selectedTab
|
|
377
|
+
: this.defaultTab
|
|
378
|
+
this.$router.replace({ hash: tab ? `#${tab}` : null })
|
|
379
|
+
}
|
|
380
|
+
if (this.hasErrors) {
|
|
381
|
+
this.repositionErrors()
|
|
372
382
|
}
|
|
373
383
|
}
|
|
374
384
|
},
|
|
@@ -441,11 +451,8 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
441
451
|
return this.isPopulated && this.components.every(callback)
|
|
442
452
|
},
|
|
443
453
|
|
|
444
|
-
|
|
445
|
-
this.emitEvent('
|
|
446
|
-
// TODO: Actually expose this on DitoContext?
|
|
447
|
-
context: { expand }
|
|
448
|
-
})
|
|
454
|
+
onOpen(open) {
|
|
455
|
+
this.emitEvent('open', { context: { open } })
|
|
449
456
|
// Prevent closing the schema with invalid data, since the in-component
|
|
450
457
|
// validation will not be executed once it's closed.
|
|
451
458
|
|
|
@@ -453,8 +460,8 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
453
460
|
// processing, and use `showValidationErrors()` for the resulting errors,
|
|
454
461
|
// then remove this requirement, since we can validate closed forms and
|
|
455
462
|
// schemas then.
|
|
456
|
-
if (!this.opened ||
|
|
457
|
-
this.opened =
|
|
463
|
+
if (!this.opened || open || this.validateAll()) {
|
|
464
|
+
this.opened = open
|
|
458
465
|
}
|
|
459
466
|
},
|
|
460
467
|
|
|
@@ -630,9 +637,12 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
630
637
|
for (const name in data) {
|
|
631
638
|
if (name in this.data) {
|
|
632
639
|
// eslint-disable-next-line vue/no-mutating-props
|
|
633
|
-
this.data[name]
|
|
634
|
-
|
|
635
|
-
|
|
640
|
+
if (!equals(this.data[name], data[name])) {
|
|
641
|
+
// eslint-disable-next-line vue/no-mutating-props
|
|
642
|
+
this.data[name] = data[name]
|
|
643
|
+
for (const component of this.getComponentsByName(name)) {
|
|
644
|
+
component.markDirty()
|
|
645
|
+
}
|
|
636
646
|
}
|
|
637
647
|
}
|
|
638
648
|
}
|
|
@@ -733,10 +743,22 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
733
743
|
|
|
734
744
|
.dito-schema {
|
|
735
745
|
box-sizing: border-box;
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
746
|
+
|
|
747
|
+
> .dito-schema-header + .dito-schema-content > .dito-pane {
|
|
748
|
+
margin-top: $form-spacing-half;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
&:has(> .dito-schema-content + .dito-edit-buttons) {
|
|
752
|
+
// Display the edit buttons to the right of the schema:
|
|
753
|
+
display: flex;
|
|
754
|
+
flex-direction: row;
|
|
755
|
+
align-items: stretch;
|
|
756
|
+
|
|
757
|
+
> .dito-edit-buttons {
|
|
758
|
+
flex: 1 0 0%;
|
|
759
|
+
margin-left: $form-spacing;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
740
762
|
|
|
741
763
|
> .dito-schema-content {
|
|
742
764
|
flex: 0 1 100%;
|
|
@@ -751,37 +773,6 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
751
773
|
> *:only-child {
|
|
752
774
|
grid-row-end: none;
|
|
753
775
|
}
|
|
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
776
|
}
|
|
786
777
|
}
|
|
787
778
|
|
|
@@ -789,41 +780,22 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
789
780
|
display: flex;
|
|
790
781
|
justify-content: space-between;
|
|
791
782
|
|
|
792
|
-
.dito-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
align-self: flex-end;
|
|
783
|
+
.dito-header & {
|
|
784
|
+
// When teleported into main header.
|
|
785
|
+
align-items: flex-end;
|
|
796
786
|
}
|
|
797
787
|
|
|
798
|
-
.dito-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
788
|
+
.dito-label & {
|
|
789
|
+
// When teleported into container label.
|
|
790
|
+
flex: 1;
|
|
791
|
+
}
|
|
802
792
|
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
}
|
|
793
|
+
> .dito-label {
|
|
794
|
+
margin-bottom: 0;
|
|
806
795
|
}
|
|
807
796
|
|
|
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
|
-
}
|
|
797
|
+
> .dito-buttons {
|
|
798
|
+
margin-left: var(--button-margin, 0);
|
|
827
799
|
}
|
|
828
800
|
}
|
|
829
801
|
</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
|
|
@@ -19,15 +20,16 @@ DitoSchema.dito-schema-inlined(
|
|
|
19
20
|
template(#edit-buttons)
|
|
20
21
|
DitoEditButtons(
|
|
21
22
|
v-if="deletable || draggable || editable"
|
|
22
|
-
:deletable="deletable"
|
|
23
|
-
:draggable="draggable"
|
|
24
|
-
:editable="editable"
|
|
25
|
-
:editPath="editPath"
|
|
26
23
|
:schema="schema"
|
|
27
24
|
:dataPath="dataPath"
|
|
28
25
|
:data="data"
|
|
29
26
|
:meta="meta"
|
|
30
27
|
:store="store"
|
|
28
|
+
:disabled="disabled"
|
|
29
|
+
:deletable="deletable"
|
|
30
|
+
:draggable="draggable"
|
|
31
|
+
:editable="editable"
|
|
32
|
+
:editPath="editPath"
|
|
31
33
|
@delete="$emit('delete')"
|
|
32
34
|
)
|
|
33
35
|
</template>
|
|
@@ -53,6 +55,7 @@ export default DitoComponent.component('DitoSchemaInlined', {
|
|
|
53
55
|
editable: { type: Boolean, default: false },
|
|
54
56
|
deletable: { type: Boolean, default: false },
|
|
55
57
|
editPath: { type: String, default: null },
|
|
58
|
+
labelNode: { type: HTMLElement, default: null },
|
|
56
59
|
accumulatedBasis: { type: Number, default: null }
|
|
57
60
|
},
|
|
58
61
|
|
|
@@ -72,25 +75,26 @@ export default DitoComponent.component('DitoSchemaInlined', {
|
|
|
72
75
|
@import '../styles/_imports';
|
|
73
76
|
|
|
74
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
|
+
|
|
75
85
|
> .dito-schema-content {
|
|
76
86
|
> .dito-schema-header {
|
|
77
|
-
|
|
78
|
-
|
|
87
|
+
justify-content: space-between;
|
|
88
|
+
position: relative;
|
|
79
89
|
|
|
80
90
|
.dito-label {
|
|
81
|
-
// Add removed $form-spacing again.
|
|
82
|
-
margin: $form-spacing;
|
|
83
91
|
width: 100%;
|
|
84
|
-
|
|
92
|
+
margin: 0;
|
|
85
93
|
// Prevent collapsing to min-height when alone in
|
|
86
94
|
// .dito-schema-content, due to grid-template-rows: min-content
|
|
87
95
|
min-height: $input-height;
|
|
88
96
|
}
|
|
89
97
|
}
|
|
90
|
-
|
|
91
|
-
> .dito-pane {
|
|
92
|
-
padding: 0;
|
|
93
|
-
}
|
|
94
98
|
}
|
|
95
99
|
}
|
|
96
100
|
</style>
|