@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.
Files changed (36) hide show
  1. package/dist/dito-admin.es.js +1769 -1705
  2. package/dist/dito-admin.umd.js +5 -5
  3. package/dist/style.css +1 -1
  4. package/package.json +5 -5
  5. package/src/DitoContext.js +4 -0
  6. package/src/DitoTypeComponent.js +1 -1
  7. package/src/components/DitoClipboard.vue +22 -0
  8. package/src/components/DitoContainer.vue +7 -12
  9. package/src/components/DitoCreateButton.vue +26 -11
  10. package/src/components/DitoDialog.vue +14 -3
  11. package/src/components/DitoEditButtons.vue +20 -9
  12. package/src/components/DitoForm.vue +17 -12
  13. package/src/components/DitoHeader.vue +22 -6
  14. package/src/components/DitoLabel.vue +39 -22
  15. package/src/components/DitoPane.vue +43 -35
  16. package/src/components/DitoRoot.vue +1 -2
  17. package/src/components/DitoSchema.vue +137 -165
  18. package/src/components/DitoSchemaInlined.vue +17 -13
  19. package/src/components/DitoTabs.vue +65 -23
  20. package/src/components/DitoTreeItem.vue +1 -1
  21. package/src/components/DitoView.vue +0 -1
  22. package/src/mixins/DitoMixin.js +8 -7
  23. package/src/mixins/ItemMixin.js +5 -1
  24. package/src/mixins/TypeMixin.js +5 -0
  25. package/src/styles/_button.scss +13 -12
  26. package/src/styles/_settings.scss +2 -2
  27. package/src/types/DitoTypeList.vue +12 -9
  28. package/src/types/DitoTypeMultiselect.vue +3 -4
  29. package/src/types/DitoTypeObject.vue +9 -6
  30. package/src/types/DitoTypePanel.vue +1 -1
  31. package/src/types/DitoTypeSection.vue +38 -10
  32. package/src/types/DitoTypeSelect.vue +3 -2
  33. package/src/types/DitoTypeUpload.vue +2 -2
  34. package/src/utils/options.js +1 -1
  35. package/src/utils/schema.js +8 -6
  36. 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: nested ? this.getChildStore(name) : this.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 > 3 &&
153
- position.node.querySelector(':scope > .dito-label')
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: (-$form-spacing) (-$form-spacing-half);
227
- max-width: calc(var(--max-content-width) + $form-spacing);
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
- &--single {
233
- // Clear negative margin from above.
234
- margin: 0;
234
+ &__main {
235
+ flex: 100%;
235
236
  }
236
237
 
237
238
  .dito-scroll > & {
238
- &,
239
- .dito-container {
240
- min-width: min-content;
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
- &:not(#{$self}--single) {
244
- // Root-level panes inside scroll views need to move the negative margin
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
- &.dito-pane-main {
254
- flex: 100%;
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-schema-header + & {
258
- // Clear top-margin if the components are preceded by a schema header.
259
- margin-top: 0;
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-container--omit-padding > & {
263
- // Clear margins set above again if parent is omitting padding.
264
- margin: 0;
265
- max-width: unset;
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
- .dito-schema-content(
18
- ref="content"
19
- :class="{ 'dito-scroll': scrollable }"
18
+ Teleport(
19
+ v-if="hasHeader"
20
+ :to="headerTeleport"
21
+ :disabled="!headerTeleport"
20
22
  )
21
- Teleport(
22
- v-if="hasLabel || hasTabs || clipboard"
23
- to=".dito-header__teleport"
24
- :disabled="!headerInMenu"
25
- )
26
- .dito-schema-header(
27
- :class="{ 'dito-schema-header--menu': headerInMenu }"
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="tabs"
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
- template(
54
- v-if="hasTabs"
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
- TransitionHeight(:enabled="inlined")
73
- DitoPane.dito-pane-main(
74
- v-if="hasMainPane && opened"
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
- slot(
87
- v-if="!inlined && isPopulated"
88
- name="buttons"
89
- )
90
- template(
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
- return this.currentTab || this.defaultTab?.name || null
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
- for (const tab of Object.values(this.tabs)) {
201
- const { defaultTab } = tab
202
- if (
203
- isFunction(defaultTab)
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 !this.inlined && !!this.tabs
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.hasTabs) {
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.hasTabs) {
362
- let tab = null
363
- if (selectedTab !== this.currentTab) {
364
- // Any tab change needs to be reflected in the router also.
365
- tab = selectedTab
366
- } else if (!this.shouldRenderSchema(this.tabs[selectedTab])) {
367
- tab = this.defaultTab?.name
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
- onExpand(expand) {
445
- this.emitEvent('expand', {
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 || expand || this.validateAll()) {
457
- this.opened = expand
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] = data[name]
634
- for (const component of this.getComponentsByName(name)) {
635
- component.markDirty()
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
- // To display edit buttons next to schema:
737
- display: flex;
738
- align-items: stretch;
739
- min-height: 100%;
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-tabs,
793
- .dito-clipboard {
794
- display: flex;
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-clipboard {
799
- &:only-child {
800
- margin-left: auto;
801
- }
788
+ .dito-label & {
789
+ // When teleported into container label.
790
+ flex: 1;
791
+ }
802
792
 
803
- .dito-button {
804
- margin: 0 0 $tab-margin $tab-margin;
805
- }
793
+ > .dito-label {
794
+ margin-bottom: 0;
806
795
  }
807
796
 
808
- &--menu {
809
- // Align the tabs on top of to the header menu.
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
- // Change spacing so .dito-label covers the full .dito-schema-header.
78
- margin: -$form-spacing;
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
- box-sizing: content-box;
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>