@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.
Files changed (37) hide show
  1. package/dist/dito-admin.es.js +1417 -1376
  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 +21 -1
  10. package/src/components/DitoDialog.vue +5 -0
  11. package/src/components/DitoEditButtons.vue +35 -25
  12. package/src/components/DitoElement.vue +2 -2
  13. package/src/components/DitoForm.vue +9 -4
  14. package/src/components/DitoHeader.vue +22 -6
  15. package/src/components/DitoLabel.vue +41 -23
  16. package/src/components/DitoPane.vue +47 -35
  17. package/src/components/DitoRoot.vue +1 -2
  18. package/src/components/DitoSchema.vue +139 -165
  19. package/src/components/DitoSchemaInlined.vue +12 -9
  20. package/src/components/DitoTabs.vue +65 -23
  21. package/src/components/DitoTreeItem.vue +1 -1
  22. package/src/components/DitoView.vue +0 -1
  23. package/src/mixins/DitoMixin.js +6 -5
  24. package/src/mixins/ItemMixin.js +5 -1
  25. package/src/mixins/TypeMixin.js +14 -30
  26. package/src/styles/_button.scss +13 -12
  27. package/src/styles/_settings.scss +2 -2
  28. package/src/types/DitoTypeList.vue +1 -1
  29. package/src/types/DitoTypeMultiselect.vue +2 -3
  30. package/src/types/DitoTypeObject.vue +6 -4
  31. package/src/types/DitoTypePanel.vue +1 -1
  32. package/src/types/DitoTypeSection.vue +38 -10
  33. package/src/types/DitoTypeSelect.vue +2 -1
  34. package/src/types/DitoTypeUpload.vue +2 -2
  35. package/src/utils/options.js +1 -1
  36. package/src/utils/schema.js +8 -6
  37. 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.
@@ -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: (-$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`,
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
- &--single {
233
- // Clear negative margin from above.
234
- margin: 0;
235
+ &__main {
236
+ flex: 100%;
235
237
  }
236
238
 
237
239
  .dito-scroll > & {
238
- &,
239
- .dito-container {
240
- min-width: min-content;
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
- &: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;
246
+ &#{$self}--single {
247
+ padding: $content-padding;
250
248
  }
251
- }
252
249
 
253
- &.dito-pane-main {
254
- flex: 100%;
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-schema-header + & {
258
- // Clear top-margin if the components are preceded by a schema header.
259
- margin-top: 0;
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-container--omit-padding > & {
263
- // Clear margins set above again if parent is omitting padding.
264
- margin: 0;
265
- max-width: unset;
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
- .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
+ 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
- slot(
87
- v-if="!inlined && isPopulated"
88
- name="buttons"
89
- )
90
- template(
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
- return this.currentTab || this.defaultTab?.name || null
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
- 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
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 !this.inlined && !!this.tabs
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.hasTabs) {
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.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
- }
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
- onExpand(expand) {
445
- this.emitEvent('expand', {
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 || expand || this.validateAll()) {
457
- this.opened = expand
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] = data[name]
634
- for (const component of this.getComponentsByName(name)) {
635
- component.markDirty()
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
- // To display edit buttons next to schema:
737
- display: flex;
738
- align-items: stretch;
739
- min-height: 100%;
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-tabs,
793
- .dito-clipboard {
794
- display: flex;
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-clipboard {
799
- &:only-child {
800
- margin-left: auto;
801
- }
790
+ .dito-label & {
791
+ // When teleported into container label.
792
+ flex: 1;
793
+ }
802
794
 
803
- .dito-button {
804
- margin: 0 0 $tab-margin $tab-margin;
805
- }
795
+ > .dito-label {
796
+ margin-bottom: 0;
806
797
  }
807
798
 
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
- }
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
- // Change spacing so .dito-label covers the full .dito-schema-header.
79
- margin: -$form-spacing;
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
- box-sizing: content-box;
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>