@radio-garden/ditojs-admin 2.85.2-0.5067ad799

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 (153) hide show
  1. package/README.md +180 -0
  2. package/dist/dito-admin.css +1 -0
  3. package/dist/dito-admin.es.js +12106 -0
  4. package/dist/dito-admin.umd.js +7 -0
  5. package/package.json +96 -0
  6. package/src/DitoAdmin.js +293 -0
  7. package/src/DitoComponent.js +34 -0
  8. package/src/DitoContext.js +318 -0
  9. package/src/DitoTypeComponent.js +42 -0
  10. package/src/DitoUser.js +12 -0
  11. package/src/appState.js +12 -0
  12. package/src/components/DitoAccount.vue +60 -0
  13. package/src/components/DitoAffix.vue +68 -0
  14. package/src/components/DitoAffixes.vue +200 -0
  15. package/src/components/DitoButtons.vue +80 -0
  16. package/src/components/DitoClipboard.vue +186 -0
  17. package/src/components/DitoContainer.vue +374 -0
  18. package/src/components/DitoCreateButton.vue +146 -0
  19. package/src/components/DitoDialog.vue +242 -0
  20. package/src/components/DitoDraggable.vue +117 -0
  21. package/src/components/DitoEditButtons.vue +135 -0
  22. package/src/components/DitoErrors.vue +83 -0
  23. package/src/components/DitoForm.vue +521 -0
  24. package/src/components/DitoFormInner.vue +26 -0
  25. package/src/components/DitoFormNested.vue +17 -0
  26. package/src/components/DitoHeader.vue +84 -0
  27. package/src/components/DitoLabel.vue +200 -0
  28. package/src/components/DitoMenu.vue +186 -0
  29. package/src/components/DitoNavigation.vue +40 -0
  30. package/src/components/DitoNotifications.vue +170 -0
  31. package/src/components/DitoPagination.vue +42 -0
  32. package/src/components/DitoPane.vue +334 -0
  33. package/src/components/DitoPanel.vue +256 -0
  34. package/src/components/DitoPanels.vue +61 -0
  35. package/src/components/DitoRoot.vue +524 -0
  36. package/src/components/DitoSchema.vue +846 -0
  37. package/src/components/DitoSchemaInlined.vue +97 -0
  38. package/src/components/DitoScopes.vue +76 -0
  39. package/src/components/DitoSidebar.vue +50 -0
  40. package/src/components/DitoSpinner.vue +95 -0
  41. package/src/components/DitoTableCell.vue +64 -0
  42. package/src/components/DitoTableHead.vue +121 -0
  43. package/src/components/DitoTabs.vue +103 -0
  44. package/src/components/DitoTrail.vue +124 -0
  45. package/src/components/DitoTreeItem.vue +420 -0
  46. package/src/components/DitoUploadFile.vue +199 -0
  47. package/src/components/DitoVNode.vue +14 -0
  48. package/src/components/DitoView.vue +143 -0
  49. package/src/components/index.js +42 -0
  50. package/src/directives/resize.js +83 -0
  51. package/src/index.js +1 -0
  52. package/src/mixins/ContextMixin.js +68 -0
  53. package/src/mixins/DataMixin.js +131 -0
  54. package/src/mixins/DitoMixin.js +591 -0
  55. package/src/mixins/DomMixin.js +29 -0
  56. package/src/mixins/EmitterMixin.js +158 -0
  57. package/src/mixins/ItemMixin.js +144 -0
  58. package/src/mixins/LoadingMixin.js +23 -0
  59. package/src/mixins/NumberMixin.js +118 -0
  60. package/src/mixins/OptionsMixin.js +304 -0
  61. package/src/mixins/PulldownMixin.js +63 -0
  62. package/src/mixins/ResourceMixin.js +398 -0
  63. package/src/mixins/RouteMixin.js +190 -0
  64. package/src/mixins/SchemaParentMixin.js +33 -0
  65. package/src/mixins/SortableMixin.js +49 -0
  66. package/src/mixins/SourceMixin.js +734 -0
  67. package/src/mixins/TextMixin.js +26 -0
  68. package/src/mixins/TypeMixin.js +280 -0
  69. package/src/mixins/ValidationMixin.js +119 -0
  70. package/src/mixins/ValidatorMixin.js +57 -0
  71. package/src/mixins/ValueMixin.js +31 -0
  72. package/src/styles/_base.scss +17 -0
  73. package/src/styles/_button.scss +191 -0
  74. package/src/styles/_imports.scss +3 -0
  75. package/src/styles/_info.scss +19 -0
  76. package/src/styles/_layout.scss +19 -0
  77. package/src/styles/_pulldown.scss +38 -0
  78. package/src/styles/_scroll.scss +13 -0
  79. package/src/styles/_settings.scss +88 -0
  80. package/src/styles/_table.scss +223 -0
  81. package/src/styles/_tippy.scss +45 -0
  82. package/src/styles/style.scss +9 -0
  83. package/src/types/DitoTypeButton.vue +143 -0
  84. package/src/types/DitoTypeCheckbox.vue +27 -0
  85. package/src/types/DitoTypeCheckboxes.vue +65 -0
  86. package/src/types/DitoTypeCode.vue +199 -0
  87. package/src/types/DitoTypeColor.vue +272 -0
  88. package/src/types/DitoTypeComponent.vue +31 -0
  89. package/src/types/DitoTypeComputed.vue +50 -0
  90. package/src/types/DitoTypeDate.vue +99 -0
  91. package/src/types/DitoTypeLabel.vue +23 -0
  92. package/src/types/DitoTypeList.vue +364 -0
  93. package/src/types/DitoTypeMarkup.vue +700 -0
  94. package/src/types/DitoTypeMultiselect.vue +522 -0
  95. package/src/types/DitoTypeNumber.vue +66 -0
  96. package/src/types/DitoTypeObject.vue +136 -0
  97. package/src/types/DitoTypePanel.vue +18 -0
  98. package/src/types/DitoTypeProgress.vue +40 -0
  99. package/src/types/DitoTypeRadio.vue +45 -0
  100. package/src/types/DitoTypeSection.vue +80 -0
  101. package/src/types/DitoTypeSelect.vue +133 -0
  102. package/src/types/DitoTypeSlider.vue +66 -0
  103. package/src/types/DitoTypeSpacer.vue +11 -0
  104. package/src/types/DitoTypeSwitch.vue +40 -0
  105. package/src/types/DitoTypeText.vue +101 -0
  106. package/src/types/DitoTypeTextarea.vue +48 -0
  107. package/src/types/DitoTypeTreeList.vue +193 -0
  108. package/src/types/DitoTypeUpload.vue +503 -0
  109. package/src/types/index.js +30 -0
  110. package/src/utils/SchemaGraph.js +147 -0
  111. package/src/utils/accessor.js +75 -0
  112. package/src/utils/agent.js +47 -0
  113. package/src/utils/data.js +92 -0
  114. package/src/utils/filter.js +266 -0
  115. package/src/utils/math.js +14 -0
  116. package/src/utils/options.js +48 -0
  117. package/src/utils/path.js +5 -0
  118. package/src/utils/resource.js +44 -0
  119. package/src/utils/route.js +53 -0
  120. package/src/utils/schema.js +1121 -0
  121. package/src/utils/type.js +81 -0
  122. package/src/utils/uid.js +15 -0
  123. package/src/utils/units.js +5 -0
  124. package/src/validators/_creditcard.js +6 -0
  125. package/src/validators/_decimals.js +11 -0
  126. package/src/validators/_domain.js +6 -0
  127. package/src/validators/_email.js +6 -0
  128. package/src/validators/_hostname.js +6 -0
  129. package/src/validators/_integer.js +6 -0
  130. package/src/validators/_max.js +6 -0
  131. package/src/validators/_min.js +6 -0
  132. package/src/validators/_password.js +5 -0
  133. package/src/validators/_range.js +6 -0
  134. package/src/validators/_required.js +9 -0
  135. package/src/validators/_url.js +6 -0
  136. package/src/validators/index.js +12 -0
  137. package/src/verbs.js +17 -0
  138. package/types/index.d.ts +3298 -0
  139. package/types/tests/admin.test-d.ts +27 -0
  140. package/types/tests/component-buttons.test-d.ts +44 -0
  141. package/types/tests/component-list.test-d.ts +159 -0
  142. package/types/tests/component-misc.test-d.ts +137 -0
  143. package/types/tests/component-object.test-d.ts +69 -0
  144. package/types/tests/component-section.test-d.ts +174 -0
  145. package/types/tests/component-select.test-d.ts +107 -0
  146. package/types/tests/components.test-d.ts +81 -0
  147. package/types/tests/context.test-d.ts +31 -0
  148. package/types/tests/fixtures.ts +24 -0
  149. package/types/tests/form.test-d.ts +109 -0
  150. package/types/tests/instance.test-d.ts +20 -0
  151. package/types/tests/schema-features.test-d.ts +402 -0
  152. package/types/tests/variance.test-d.ts +125 -0
  153. package/types/tests/view.test-d.ts +146 -0
@@ -0,0 +1,97 @@
1
+ <template lang="pug">
2
+ DitoSchema.dito-schema-inlined(
3
+ :schema="schema"
4
+ :dataPath="dataPath"
5
+ :data="data"
6
+ :meta="meta"
7
+ :store="store"
8
+ :label="isCompact ? null : label"
9
+ :info="info"
10
+ :padding="padding ?? 'inlined'"
11
+ :inlined="true"
12
+ :disabled="disabled"
13
+ :compact="isCompact"
14
+ :collapsed="collapsed"
15
+ :collapsible="collapsible"
16
+ :generateLabels="!isCompact"
17
+ :labelNode="labelNode"
18
+ :accumulatedBasis="accumulatedBasis"
19
+ )
20
+ //- Render dito-edit-buttons for inlined schemas separately from all
21
+ //- others in `TypeList` as a scope, for better handling of layout.
22
+ template(#edit-buttons)
23
+ DitoEditButtons(
24
+ v-if="deletable || draggable || editable"
25
+ :schema="schema"
26
+ :dataPath="dataPath"
27
+ :data="data"
28
+ :meta="meta"
29
+ :store="store"
30
+ :disabled="disabled"
31
+ :deletable="deletable"
32
+ :draggable="draggable"
33
+ :editable="editable"
34
+ :editPath="editPath"
35
+ @delete="$emit('delete')"
36
+ )
37
+ </template>
38
+
39
+ <script>
40
+ import DitoComponent from '../DitoComponent.js'
41
+ import { isCompact } from '../utils/schema.js'
42
+ // @vue/component
43
+ export default DitoComponent.component('DitoSchemaInlined', {
44
+ emits: ['delete'],
45
+
46
+ props: {
47
+ schema: { type: Object, required: true },
48
+ dataPath: { type: String, required: true },
49
+ data: { type: Object, required: true },
50
+ meta: { type: Object, required: true },
51
+ store: { type: Object, required: true },
52
+ label: { type: [String, Object], default: null },
53
+ info: { type: String, default: null },
54
+ padding: { type: String, default: null },
55
+ disabled: { type: Boolean, required: true },
56
+ collapsed: { type: Boolean, default: false },
57
+ collapsible: { type: Boolean, default: false },
58
+ draggable: { type: Boolean, default: false },
59
+ editable: { type: Boolean, default: false },
60
+ deletable: { type: Boolean, default: false },
61
+ editPath: { type: String, default: null },
62
+ labelNode: { type: HTMLElement, default: null },
63
+ accumulatedBasis: { type: Number, default: null }
64
+ },
65
+
66
+ computed: {
67
+ isCompact() {
68
+ return isCompact(this.schema)
69
+ },
70
+
71
+ hasLabel() {
72
+ return !this.isCompact && !!this.label
73
+ }
74
+ }
75
+ })
76
+ </script>
77
+
78
+ <style lang="scss">
79
+ @import '../styles/_imports';
80
+
81
+ .dito-schema-inlined {
82
+ // Use grid layout for two reasons: For `TransitionHeight` to work smoothly,
83
+ // and to align the header above the content when the header is not teleported
84
+ // outside of the schema.
85
+ display: grid;
86
+ grid-template-rows: min-content;
87
+ grid-template-columns: 100%;
88
+
89
+ &:not(:hover, .dito-schema--open) {
90
+ > .dito-schema-header {
91
+ > .dito-clipboard {
92
+ display: none;
93
+ }
94
+ }
95
+ }
96
+ }
97
+ </style>
@@ -0,0 +1,76 @@
1
+ <template lang="pug">
2
+ .dito-scopes
3
+ RouterLink(
4
+ v-for="(scope, key) in scopes"
5
+ :key="key"
6
+ v-slot="{ navigate }"
7
+ :to="getScopeLink(scope)"
8
+ custom
9
+ )
10
+ button.dito-button(
11
+ type="button"
12
+ :class="{ 'dito-button--selected': scope.name === query.scope }"
13
+ :title="scope.hint || getLabel(scope)"
14
+ @click="navigate"
15
+ ) {{ getLabel(scope) }}
16
+ </template>
17
+
18
+ <script>
19
+ import DitoComponent from '../DitoComponent.js'
20
+
21
+ // @vue/component
22
+ export default DitoComponent.component('DitoScopes', {
23
+ props: {
24
+ query: { type: Object, required: true },
25
+ scopes: { type: Object, required: true }
26
+ },
27
+
28
+ methods: {
29
+ getScopeLink(scope) {
30
+ const query = { ...this.query, scope: scope.name }
31
+ if (query.page) {
32
+ query.page = 0
33
+ }
34
+ return this.getQueryLink(query)
35
+ }
36
+ }
37
+ })
38
+ </script>
39
+
40
+ <style lang="scss">
41
+ @import '../styles/_imports';
42
+
43
+ .dito-scopes {
44
+ white-space: nowrap;
45
+ display: flex;
46
+
47
+ .dito-button {
48
+ @include ellipsis;
49
+
50
+ border-radius: 0;
51
+ // A bit more than the width of ellipsis, to prevent replacing short words
52
+ // with ellipsis.
53
+ min-width: 3em;
54
+ flex: 0 1 auto;
55
+
56
+ &:first-child {
57
+ border-top-left-radius: 1em;
58
+ border-bottom-left-radius: 1em;
59
+ padding-left: 1em;
60
+ }
61
+
62
+ &:last-child {
63
+ border-top-right-radius: 1em;
64
+ border-bottom-right-radius: 1em;
65
+ padding-right: 1em;
66
+ }
67
+
68
+ & + .dito-button {
69
+ margin-left: -1px;
70
+ } // Don't cover the focused border of buttons:
71
+ &:focus {
72
+ z-index: 1;
73
+ }
74
+ }
75
+ }
76
+ </style>
@@ -0,0 +1,50 @@
1
+ <template lang="pug">
2
+ aside.dito-sidebar.dito-scroll-parent(
3
+ v-resize="onResizeSidebar"
4
+ :class="classes"
5
+ )
6
+ nav.dito-header
7
+ slot
8
+ .dito-sidebar__teleport.dito-scroll
9
+ </template>
10
+
11
+ <script>
12
+ import DitoComponent from '../DitoComponent.js'
13
+
14
+ // @vue/component
15
+ export default DitoComponent.component('DitoSidebar', {
16
+ data() {
17
+ return {
18
+ sidebarWidth: 0
19
+ }
20
+ },
21
+
22
+ computed: {
23
+ classes() {
24
+ const prefix = 'dito-sidebar'
25
+ // NOTE: Keep synced with $sidebar-max-width in SCSS:
26
+ const sidebarWidth = 360
27
+ return {
28
+ [`${prefix}--width-99`]: this.sidebarWidth < sidebarWidth,
29
+ [`${prefix}--width-60`]: this.sidebarWidth <= sidebarWidth * 0.6
30
+ }
31
+ }
32
+ },
33
+
34
+ methods: {
35
+ onResizeSidebar({ contentRect: { width } }) {
36
+ this.sidebarWidth = width
37
+ }
38
+ }
39
+ })
40
+ </script>
41
+
42
+ <style lang="scss">
43
+ @import '../styles/_imports';
44
+
45
+ .dito-sidebar {
46
+ flex: 0 1 $sidebar-max-width;
47
+ max-width: $sidebar-max-width;
48
+ min-width: $sidebar-min-width;
49
+ }
50
+ </style>
@@ -0,0 +1,95 @@
1
+ <template lang="pug">
2
+ .dito-spinner(
3
+ v-show="loading"
4
+ :style="{ '--color': color, '--size': size, '--margin': margin }"
5
+ )
6
+ .dito-spinner__pulse.dito-spinner__pulse1
7
+ .dito-spinner__pulse.dito-spinner__pulse2
8
+ .dito-spinner__pulse.dito-spinner__pulse3
9
+ </template>
10
+
11
+ <script>
12
+ import DitoComponent from '../DitoComponent.js'
13
+
14
+ // @vue/component
15
+ export default DitoComponent.component('DitoSpinner', {
16
+ props: {
17
+ loading: {
18
+ type: Boolean,
19
+ default: true
20
+ },
21
+ color: {
22
+ type: String,
23
+ default: null
24
+ },
25
+ size: {
26
+ type: String,
27
+ default: null
28
+ },
29
+ margin: {
30
+ type: String,
31
+ default: null
32
+ }
33
+ }
34
+ })
35
+ </script>
36
+
37
+ <style lang="scss">
38
+ .dito-spinner {
39
+ --color: #999999;
40
+ --size: 8px;
41
+ --margin: 2px;
42
+
43
+ display: flex;
44
+ align-items: center;
45
+
46
+ &__pulse {
47
+ display: inline-block;
48
+ background: var(--color);
49
+ width: var(--size);
50
+ height: var(--size);
51
+ margin: var(--margin);
52
+ border-radius: 100%;
53
+ animation: dito-spinner-pulse 0.75s cubic-bezier(0.2, 0.68, 0.18, 1.08) 0s
54
+ infinite both;
55
+ }
56
+
57
+ &__pulse1 {
58
+ animation-delay: 0.12s;
59
+ }
60
+
61
+ &__pulse2 {
62
+ animation-delay: 0.24s;
63
+ }
64
+
65
+ &__pulse3 {
66
+ animation-delay: 0.36s;
67
+ }
68
+ }
69
+
70
+ @keyframes dito-spinner-pulse {
71
+ 0%,
72
+ 80% {
73
+ transform: scale(1);
74
+ opacity: 1;
75
+ }
76
+
77
+ 45% {
78
+ transform: scale(0.1);
79
+ opacity: 0.7;
80
+ }
81
+ }
82
+
83
+ @keyframes dito-spinner-pulse {
84
+ 0%,
85
+ 80% {
86
+ transform: scale(1);
87
+ opacity: 1;
88
+ }
89
+
90
+ 45% {
91
+ transform: scale(0.1);
92
+ opacity: 0.7;
93
+ }
94
+ }
95
+ </style>
@@ -0,0 +1,64 @@
1
+ <template lang="pug">
2
+ td(
3
+ :class="cell.class"
4
+ :style="cell.style"
5
+ )
6
+ //- TODO: Implement inlined components in cell mode!
7
+ component(
8
+ v-if="cell.component"
9
+ :is="cell.component"
10
+ :schema="schema"
11
+ :dataPath="dataPath"
12
+ :data="data"
13
+ :meta="meta"
14
+ :store="store"
15
+ :nested="nested"
16
+ :disabled="disabled"
17
+ )
18
+ span(
19
+ v-else
20
+ v-html="renderCell(data)"
21
+ )
22
+ </template>
23
+
24
+ <script>
25
+ import DitoComponent from '../DitoComponent.js'
26
+ import DitoContext from '../DitoContext.js'
27
+ import ContextMixin from '../mixins/ContextMixin.js'
28
+ import { appendDataPath } from '../utils/data.js'
29
+ import { escapeHtml } from '@ditojs/utils'
30
+
31
+ // @vue/component
32
+ export default DitoComponent.component('DitoTableCell', {
33
+ mixins: [ContextMixin],
34
+
35
+ props: {
36
+ cell: { type: Object, required: true },
37
+ schema: { type: Object, required: true },
38
+ dataPath: { type: String, required: true },
39
+ data: { type: Object, required: true },
40
+ meta: { type: Object, required: true },
41
+ store: { type: Object, required: true },
42
+ nested: { type: Boolean, default: true },
43
+ disabled: { type: Boolean, default: false }
44
+ },
45
+
46
+ methods: {
47
+ renderCell(item) {
48
+ const { name, render } = this.cell
49
+ const value = item[name]
50
+ return render
51
+ ? render.call(
52
+ this,
53
+ new DitoContext(this, {
54
+ name,
55
+ value,
56
+ data: item,
57
+ dataPath: appendDataPath(this.dataPath, name)
58
+ })
59
+ )
60
+ : escapeHtml(value)
61
+ }
62
+ }
63
+ })
64
+ </script>
@@ -0,0 +1,121 @@
1
+ <template lang="pug">
2
+ thead.dito-table-head
3
+ tr
4
+ template(
5
+ v-for="column in columns"
6
+ )
7
+ th(
8
+ v-if="shouldRenderSchema(column)"
9
+ :class="getColumnClass(column)"
10
+ )
11
+ RouterLink(
12
+ v-if="column.sortable"
13
+ v-slot="{ navigate }"
14
+ :to="getSortLink(column)"
15
+ custom
16
+ )
17
+ button.dito-button(
18
+ type="button"
19
+ :class="getSortClass(column)"
20
+ @click="navigate"
21
+ )
22
+ .dito-button__order-arrows
23
+ span {{ getLabel(column) }}
24
+ span(
25
+ v-else
26
+ ) {{ getLabel(column) }}
27
+ th(
28
+ v-if="hasEditButtons"
29
+ )
30
+ //- Empty <span> is needed for styling, see _table.scss
31
+ span
32
+ </template>
33
+
34
+ <script>
35
+ import DitoComponent from '../DitoComponent.js'
36
+ import { hyphenate } from '@ditojs/utils'
37
+
38
+ // @vue/component
39
+ export default DitoComponent.component('DitoTableHead', {
40
+ props: {
41
+ query: { type: Object, required: true },
42
+ columns: { type: Object, required: true },
43
+ hasEditButtons: { type: Boolean, required: true }
44
+ },
45
+
46
+ computed: {
47
+ sort() {
48
+ const order = (this.query.order || '').split(/\s+/)
49
+ return {
50
+ name: order[0],
51
+ order: order[1]
52
+ }
53
+ }
54
+ },
55
+
56
+ methods: {
57
+ getColumnClass(column) {
58
+ return `dito-column--${hyphenate(column.name)}`
59
+ },
60
+
61
+ getSortClass(column) {
62
+ return this.sort.name === column.name
63
+ ? `dito-button--selected dito-button--order-${this.sort.order}`
64
+ : null
65
+ },
66
+
67
+ getSortLink(column) {
68
+ // Toggle order if the same column is clicked again.
69
+ const order =
70
+ this.sort.name === column.name && this.sort.order === 'asc'
71
+ ? 'desc'
72
+ : 'asc'
73
+ return this.getQueryLink({
74
+ ...this.query,
75
+ order: `${column.name} ${order}`
76
+ })
77
+ }
78
+ }
79
+ })
80
+ </script>
81
+
82
+ <style lang="scss">
83
+ @import '../styles/_imports';
84
+
85
+ .dito-table-head {
86
+ @include user-select(none);
87
+
88
+ tr {
89
+ th {
90
+ padding: 0;
91
+ font-weight: normal;
92
+ text-align: left;
93
+ white-space: nowrap;
94
+
95
+ .dito-button {
96
+ // Convention: Nested spans handle padding, see below
97
+ display: block; // Override default inline-flex positioning.
98
+ padding: 0;
99
+ width: 100%;
100
+ text-align: inherit;
101
+ border-radius: 0;
102
+ }
103
+
104
+ span {
105
+ display: inline-block;
106
+ // Convention: Nested spans handle padding
107
+ padding: $input-padding;
108
+
109
+ &:empty::after {
110
+ // Prevent empty <th> from collapsing
111
+ content: '\200b'; // zero-width space;
112
+ }
113
+ }
114
+
115
+ > span {
116
+ display: block;
117
+ }
118
+ }
119
+ }
120
+ }
121
+ </style>
@@ -0,0 +1,103 @@
1
+ <template lang="pug">
2
+ .dito-tabs
3
+ template(
4
+ v-for="(tabSchema, key) in tabs"
5
+ )
6
+ a.dito-tabs__link(
7
+ v-if="shouldRenderSchema(tabSchema)"
8
+ :key="key"
9
+ :class="{ 'dito-tabs__link--active': modelValue === key }"
10
+ @click="$emit('update:modelValue', key)"
11
+ ) {{ getLabel(tabSchema, key) }}
12
+ </template>
13
+
14
+ <script>
15
+ import DitoComponent from '../DitoComponent.js'
16
+
17
+ // @vue/component
18
+ export default DitoComponent.component('DitoTabs', {
19
+ emits: ['update:modelValue'],
20
+ props: {
21
+ tabs: { type: Object, default: null },
22
+ modelValue: { type: String, default: null }
23
+ }
24
+ })
25
+ </script>
26
+
27
+ <style lang="scss">
28
+ @use 'sass:color';
29
+ @import '../styles/_imports';
30
+
31
+ .dito-tabs {
32
+ display: flex;
33
+
34
+ &__link {
35
+ @include user-select(none);
36
+
37
+ display: block;
38
+ white-space: nowrap;
39
+
40
+ &:hover {
41
+ background: $color-white;
42
+ }
43
+
44
+ // When in main header:
45
+ .dito-header & {
46
+ background: $color-light;
47
+ padding: $tab-padding-ver $tab-padding-hor;
48
+ margin-left: $tab-margin;
49
+ border-top-left-radius: $tab-radius;
50
+ border-top-right-radius: $tab-radius;
51
+
52
+ &:active {
53
+ background: $color-lightest;
54
+ }
55
+
56
+ &--active {
57
+ background: $color-lightest;
58
+ }
59
+ }
60
+
61
+ // When inside a inline schema:
62
+ .dito-schema-inlined &,
63
+ .dito-label & {
64
+ background: $color-lighter;
65
+ border: $border-style;
66
+ padding: $input-padding;
67
+ margin-left: -$border-width;
68
+ white-space: nowrap;
69
+
70
+ &:first-child {
71
+ border-top-left-radius: $tab-radius;
72
+ border-bottom-left-radius: $tab-radius;
73
+ }
74
+
75
+ &:last-child {
76
+ border-top-right-radius: $tab-radius;
77
+ border-bottom-right-radius: $tab-radius;
78
+ }
79
+
80
+ &:active {
81
+ background: $color-lighter;
82
+ }
83
+
84
+ &--active {
85
+ background: $color-active;
86
+ border-color: color.adjust($color-active, $lightness: -10%);
87
+ color: $color-white;
88
+ z-index: 1;
89
+ }
90
+ }
91
+ }
92
+
93
+ .dito-schema & {
94
+ // Push clipboard to the right in the flex layout, see:
95
+ // https://codepen.io/tholex/pen/hveBx/
96
+ margin-left: auto;
97
+
98
+ &:last-child {
99
+ margin-right: auto;
100
+ }
101
+ }
102
+ }
103
+ </style>