@ditojs/admin 2.2.16 → 2.3.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 +1372 -1318
- package/dist/dito-admin.umd.js +4 -4
- package/dist/style.css +1 -1
- package/package.json +5 -5
- package/src/components/DitoContainer.vue +36 -22
- package/src/components/DitoEditButtons.vue +13 -11
- package/src/components/DitoForm.vue +3 -2
- package/src/components/DitoLabel.vue +5 -3
- package/src/components/DitoPanel.vue +3 -3
- package/src/components/DitoRoot.vue +10 -1
- package/src/mixins/OptionsMixin.js +20 -2
- package/src/mixins/TypeMixin.js +2 -6
- package/src/styles/_button.scss +5 -5
- package/src/styles/_info.scss +3 -0
- package/src/types/DitoTypeButton.vue +8 -6
- package/src/types/DitoTypeList.vue +4 -2
- package/src/types/DitoTypeMultiselect.vue +54 -31
- package/src/types/DitoTypeSelect.vue +58 -37
- package/src/utils/schema.js +13 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ditojs/admin",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Dito.js Admin is a schema based admin interface for Dito.js Server, featuring auto-generated views and forms and built with Vue.js",
|
|
6
6
|
"repository": "https://github.com/ditojs/dito/tree/master/packages/admin",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"not ie_mob > 0"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@ditojs/ui": "^2.
|
|
37
|
-
"@ditojs/utils": "^2.
|
|
36
|
+
"@ditojs/ui": "^2.3.1",
|
|
37
|
+
"@ditojs/utils": "^2.3.0",
|
|
38
38
|
"@kyvg/vue3-notification": "^2.9.0",
|
|
39
39
|
"@lk77/vue3-color": "^3.0.6",
|
|
40
40
|
"@tiptap/core": "^2.0.3",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"vue-upload-component": "^3.1.8"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
|
-
"@ditojs/build": "^2.
|
|
77
|
+
"@ditojs/build": "^2.3.0",
|
|
78
78
|
"@vitejs/plugin-vue": "^4.1.0",
|
|
79
79
|
"@vue/compiler-sfc": "^3.2.47",
|
|
80
80
|
"pug": "^3.0.2",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"vite": "^4.3.1"
|
|
84
84
|
},
|
|
85
85
|
"types": "types",
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "1b5f5121a2e8e6d3741f0bb2b81d38c2343810d6",
|
|
87
87
|
"scripts": {
|
|
88
88
|
"build": "vite build",
|
|
89
89
|
"watch": "yarn build --mode 'development' --watch",
|
|
@@ -131,6 +131,32 @@ export default DitoComponent.component('DitoContainer', {
|
|
|
131
131
|
}
|
|
132
132
|
}),
|
|
133
133
|
|
|
134
|
+
flexGrow() {
|
|
135
|
+
// Interpret '>50%' as '50%, flex-grow: 1`
|
|
136
|
+
return (
|
|
137
|
+
this.widthOperator === '>' ||
|
|
138
|
+
this.width === 'fill'
|
|
139
|
+
)
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
flexShrink() {
|
|
143
|
+
// Interpret '<50%' as '50%, flex-shrink: 1`
|
|
144
|
+
return this.widthOperator === '<'
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
flexBasis() {
|
|
148
|
+
const width = this.width
|
|
149
|
+
// 'auto' = no fitting:
|
|
150
|
+
const basis = [null, 'auto', 'fill'].includes(width)
|
|
151
|
+
? 'auto'
|
|
152
|
+
: /%$/.test(width)
|
|
153
|
+
? parseFloat(width) // percentage
|
|
154
|
+
: /[a-z]/.test(width)
|
|
155
|
+
? width // native units
|
|
156
|
+
: parseFraction(width) * 100 // fraction
|
|
157
|
+
return isNumber(basis) ? `${basis}%` : basis
|
|
158
|
+
},
|
|
159
|
+
|
|
134
160
|
containerClass() {
|
|
135
161
|
const { class: containerClass } = this.schema
|
|
136
162
|
const prefix = 'dito-container'
|
|
@@ -150,39 +176,27 @@ export default DitoComponent.component('DitoContainer', {
|
|
|
150
176
|
}
|
|
151
177
|
},
|
|
152
178
|
|
|
153
|
-
componentBasis() {
|
|
154
|
-
const width = this.width
|
|
155
|
-
// 'auto' = no fitting:
|
|
156
|
-
const basis = [null, 'auto', 'fill'].includes(width)
|
|
157
|
-
? 'auto'
|
|
158
|
-
: /%$/.test(width)
|
|
159
|
-
? parseFloat(width) // percentage
|
|
160
|
-
: /[a-z]/.test(width)
|
|
161
|
-
? width // native units
|
|
162
|
-
: parseFraction(width) * 100 // fraction
|
|
163
|
-
return isNumber(basis) ? `${basis}%` : basis
|
|
164
|
-
},
|
|
165
|
-
|
|
166
179
|
containerStyle() {
|
|
167
|
-
// Interpret '>50%' as '50%, flex-grow: 1`
|
|
168
|
-
const grow = (
|
|
169
|
-
this.widthOperator === '>' ||
|
|
170
|
-
this.width === 'fill'
|
|
171
|
-
)
|
|
172
|
-
// Interpret '<50%' as '50%, flex-shrink: 1`
|
|
173
|
-
const shrink = this.widthOperator === '<'
|
|
174
180
|
return {
|
|
175
|
-
flex: `${
|
|
181
|
+
flex: `${
|
|
182
|
+
this.flexGrow ? 1 : 0
|
|
183
|
+
} ${
|
|
184
|
+
this.flexShrink ? 1 : 0
|
|
185
|
+
} ${
|
|
186
|
+
this.flexBasis
|
|
187
|
+
}`
|
|
176
188
|
}
|
|
177
189
|
},
|
|
178
190
|
|
|
179
191
|
componentClass() {
|
|
180
|
-
const basisIsAuto = this.
|
|
192
|
+
const basisIsAuto = this.flexBasis === 'auto'
|
|
181
193
|
return {
|
|
182
194
|
// TODO: BEM?
|
|
183
195
|
'dito-single': this.single,
|
|
184
196
|
'dito-disabled': this.componentDisabled,
|
|
185
197
|
'dito-width-fill': !basisIsAuto || this.width === 'fill',
|
|
198
|
+
'dito-width-grow': this.flexGrow,
|
|
199
|
+
'dito-width-shrink': this.flexShrink,
|
|
186
200
|
'dito-has-errors': !!this.errors
|
|
187
201
|
}
|
|
188
202
|
}
|
|
@@ -10,23 +10,25 @@ DitoButtons.dito-edit-buttons.dito-buttons-round(
|
|
|
10
10
|
)
|
|
11
11
|
//- Firefox doesn't like <button> here, so use <a> instead:
|
|
12
12
|
a.dito-button(
|
|
13
|
-
v-if="
|
|
13
|
+
v-if="hasDraggable"
|
|
14
14
|
v-bind="getButtonAttributes(verbs.drag)"
|
|
15
15
|
)
|
|
16
16
|
RouterLink.dito-button(
|
|
17
|
-
v-if="
|
|
18
|
-
:
|
|
17
|
+
v-if="hasEditable"
|
|
18
|
+
:class="{ 'dito-disabled': !editPath }"
|
|
19
|
+
:to="editPath ? { path: editPath } : {}"
|
|
19
20
|
v-bind="getButtonAttributes(verbs.edit)"
|
|
20
21
|
)
|
|
21
22
|
DitoCreateButton(
|
|
22
|
-
v-if="
|
|
23
|
+
v-if="hasCreatable"
|
|
24
|
+
:class="{ 'dito-disabled': !createPath }"
|
|
23
25
|
:schema="schema"
|
|
24
26
|
:path="createPath"
|
|
25
27
|
:verb="verbs.create"
|
|
26
28
|
:text="createButtonText"
|
|
27
29
|
)
|
|
28
30
|
button.dito-button(
|
|
29
|
-
v-if="
|
|
31
|
+
v-if="hasDeletable"
|
|
30
32
|
type="button"
|
|
31
33
|
v-bind="getButtonAttributes(verbs.delete)"
|
|
32
34
|
@click="$emit('delete')"
|
|
@@ -61,19 +63,19 @@ export default DitoComponent.component('DitoEditButtons', {
|
|
|
61
63
|
return this.getLabel(this.schema.form)
|
|
62
64
|
},
|
|
63
65
|
|
|
64
|
-
|
|
66
|
+
hasDraggable() {
|
|
65
67
|
return this.hasOption('draggable')
|
|
66
68
|
},
|
|
67
69
|
|
|
68
|
-
|
|
69
|
-
return this.hasOption('editable')
|
|
70
|
+
hasEditable() {
|
|
71
|
+
return this.hasOption('editable')
|
|
70
72
|
},
|
|
71
73
|
|
|
72
|
-
|
|
73
|
-
return this.hasOption('creatable')
|
|
74
|
+
hasCreatable() {
|
|
75
|
+
return this.hasOption('creatable')
|
|
74
76
|
},
|
|
75
77
|
|
|
76
|
-
|
|
78
|
+
hasDeletable() {
|
|
77
79
|
return this.hasOption('deletable')
|
|
78
80
|
},
|
|
79
81
|
|
|
@@ -289,8 +289,9 @@ export default DitoComponent.component('DitoForm', {
|
|
|
289
289
|
if (
|
|
290
290
|
param &&
|
|
291
291
|
this.providesData &&
|
|
292
|
-
from.
|
|
293
|
-
|
|
292
|
+
from.matched[0].path === to.matched[0].path && // Staying on same form?
|
|
293
|
+
from.params[param] !== 'create' && // But haven't been creating?
|
|
294
|
+
to.params[param] !== from.params[param] // Going to a different entity?
|
|
294
295
|
) {
|
|
295
296
|
this.loadData(true)
|
|
296
297
|
}
|
|
@@ -28,8 +28,7 @@ component.dito-label(
|
|
|
28
28
|
)
|
|
29
29
|
.dito-info(
|
|
30
30
|
v-if="info"
|
|
31
|
-
:data-
|
|
32
|
-
data-tippy-theme="info"
|
|
31
|
+
:data-info="info"
|
|
33
32
|
)
|
|
34
33
|
slot(name="edit-buttons")
|
|
35
34
|
</template>
|
|
@@ -118,8 +117,11 @@ export default DitoComponent.component('DitoLabel', {
|
|
|
118
117
|
.dito-label-suffix {
|
|
119
118
|
@include user-select(none);
|
|
120
119
|
@include ellipsis;
|
|
120
|
+
}
|
|
121
121
|
|
|
122
|
-
|
|
122
|
+
.dito-label-prefix + label,
|
|
123
|
+
label + .dito-label-suffix {
|
|
124
|
+
&::before {
|
|
123
125
|
content: '\a0'; //
|
|
124
126
|
}
|
|
125
127
|
}
|
|
@@ -224,10 +224,10 @@ export default DitoComponent.component('DitoPanel', {
|
|
|
224
224
|
> .dito-schema-content {
|
|
225
225
|
> .dito-pane {
|
|
226
226
|
padding: $form-spacing-half $form-spacing;
|
|
227
|
-
}
|
|
228
227
|
|
|
229
|
-
|
|
230
|
-
|
|
228
|
+
> .dito-container {
|
|
229
|
+
padding: $form-spacing-half;
|
|
230
|
+
}
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
.dito-object {
|
|
@@ -92,7 +92,16 @@ export default DitoComponent.component('DitoRoot', {
|
|
|
92
92
|
|
|
93
93
|
async mounted() {
|
|
94
94
|
tippyDelegate(this.$el, {
|
|
95
|
-
target: '
|
|
95
|
+
target: '.dito-info',
|
|
96
|
+
onCreate(instance) {
|
|
97
|
+
instance.setContent(instance.reference.dataset.info)
|
|
98
|
+
instance.setProps({
|
|
99
|
+
theme: 'info',
|
|
100
|
+
interactive: true,
|
|
101
|
+
animation: 'shift-away-subtle',
|
|
102
|
+
delay: 250
|
|
103
|
+
})
|
|
104
|
+
}
|
|
96
105
|
})
|
|
97
106
|
// Clear the label marked as active on all mouse and keyboard events, except
|
|
98
107
|
// the ones that DitoLabel itself intercepts.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import DitoContext from '../DitoContext.js'
|
|
2
2
|
import DataMixin from './DataMixin.js'
|
|
3
|
+
import { hasViewSchema, getViewEditPath } from '../utils/schema.js'
|
|
3
4
|
import { getSchemaAccessor } from '../utils/accessor.js'
|
|
4
5
|
import { setTemporaryId, isReference } from '../utils/data.js'
|
|
5
6
|
import {
|
|
@@ -145,6 +146,23 @@ export default {
|
|
|
145
146
|
}
|
|
146
147
|
}),
|
|
147
148
|
|
|
149
|
+
editable: getSchemaAccessor('editable', {
|
|
150
|
+
type: Boolean,
|
|
151
|
+
default: false,
|
|
152
|
+
get(editable) {
|
|
153
|
+
return (
|
|
154
|
+
editable &&
|
|
155
|
+
hasViewSchema(this.schema, this.context)
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
|
+
}),
|
|
159
|
+
|
|
160
|
+
editPath() {
|
|
161
|
+
return this.editable && this.selectedValue
|
|
162
|
+
? getViewEditPath(this.schema, this.selectedValue, this.context)
|
|
163
|
+
: null
|
|
164
|
+
},
|
|
165
|
+
|
|
148
166
|
groupByLabel() {
|
|
149
167
|
return this.groupBy ? 'label' : null
|
|
150
168
|
},
|
|
@@ -227,7 +245,7 @@ export default {
|
|
|
227
245
|
return isString(optionValue)
|
|
228
246
|
? option?.[optionValue]
|
|
229
247
|
: isFunction(optionValue)
|
|
230
|
-
? optionValue
|
|
248
|
+
? optionValue(new DitoContext(this, { option }))
|
|
231
249
|
: option
|
|
232
250
|
},
|
|
233
251
|
|
|
@@ -236,7 +254,7 @@ export default {
|
|
|
236
254
|
return isString(optionLabel)
|
|
237
255
|
? option?.[optionLabel]
|
|
238
256
|
: isFunction(optionLabel)
|
|
239
|
-
? optionLabel
|
|
257
|
+
? optionLabel(new DitoContext(this, { option }))
|
|
240
258
|
: labelize(`${option}`)
|
|
241
259
|
}
|
|
242
260
|
},
|
package/src/mixins/TypeMixin.js
CHANGED
|
@@ -55,19 +55,15 @@ export default {
|
|
|
55
55
|
{ component: this }
|
|
56
56
|
)
|
|
57
57
|
const { format } = this.schema
|
|
58
|
-
// `schema.format` is only ever called in the life-cycle
|
|
59
|
-
// of the component and thus it's ok to bind it to `this`
|
|
60
58
|
return format
|
|
61
|
-
? format
|
|
59
|
+
? format(new DitoContext(this, { value }))
|
|
62
60
|
: value
|
|
63
61
|
},
|
|
64
62
|
|
|
65
63
|
set(value) {
|
|
66
64
|
const { parse } = this.schema
|
|
67
|
-
// `schema.parse` is only ever called in the life-cycle
|
|
68
|
-
// of the component and thus it's ok to bind it to `this`
|
|
69
65
|
this.parsedValue = parse
|
|
70
|
-
? parse
|
|
66
|
+
? parse(new DitoContext(this, { value }))
|
|
71
67
|
: value
|
|
72
68
|
// eslint-disable-next-line vue/no-mutating-props
|
|
73
69
|
this.data[this.name] = this.parsedValue
|
package/src/styles/_button.scss
CHANGED
|
@@ -191,18 +191,18 @@
|
|
|
191
191
|
cursor: pointer;
|
|
192
192
|
|
|
193
193
|
&.dito-button-clear {
|
|
194
|
+
$self: &;
|
|
195
|
+
|
|
194
196
|
width: $input-height;
|
|
195
197
|
z-index: 1;
|
|
196
198
|
background: $color-white;
|
|
197
199
|
display: none;
|
|
198
200
|
|
|
199
|
-
$button-clear: &;
|
|
200
|
-
|
|
201
201
|
@at-root .dito-component:hover {
|
|
202
202
|
// Support two levels of nesting inside .dito-component, used by TypeColor
|
|
203
|
-
& > #{$
|
|
204
|
-
& > * > #{$
|
|
205
|
-
& > * > * > #{$
|
|
203
|
+
& > #{$self},
|
|
204
|
+
& > * > #{$self},
|
|
205
|
+
& > * > * > #{$self} {
|
|
206
206
|
display: block;
|
|
207
207
|
}
|
|
208
208
|
}
|
package/src/styles/_info.scss
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
@import 'tippy.js/animations/shift-away-subtle.css';
|
|
2
|
+
|
|
1
3
|
.dito-info {
|
|
2
4
|
--size: calc(1em * var(--line-height));
|
|
3
5
|
|
|
@@ -21,6 +23,7 @@
|
|
|
21
23
|
.tippy-box[data-theme~='info'] {
|
|
22
24
|
background-color: $color-active;
|
|
23
25
|
color: $color-white;
|
|
26
|
+
filter: drop-shadow(0 2px 4px $color-shadow);
|
|
24
27
|
|
|
25
28
|
> .tippy-arrow::before {
|
|
26
29
|
color: $color-active;
|
|
@@ -14,8 +14,7 @@ button.dito-button(
|
|
|
14
14
|
span {{ text }}
|
|
15
15
|
.dito-info(
|
|
16
16
|
v-if="!label && info"
|
|
17
|
-
:data-
|
|
18
|
-
data-tippy-theme="info"
|
|
17
|
+
:data-info="info"
|
|
19
18
|
)
|
|
20
19
|
template(
|
|
21
20
|
v-else
|
|
@@ -97,19 +96,22 @@ export default DitoTypeComponent.register(
|
|
|
97
96
|
@import '../styles/_imports';
|
|
98
97
|
|
|
99
98
|
.dito-button {
|
|
100
|
-
|
|
99
|
+
$self: &;
|
|
101
100
|
|
|
102
101
|
&__text {
|
|
103
102
|
position: relative;
|
|
104
|
-
width: 100%;
|
|
105
103
|
min-width: min-content;
|
|
106
104
|
height: calc(1em * var(--line-height));
|
|
107
105
|
|
|
108
106
|
span {
|
|
109
107
|
@include ellipsis;
|
|
110
108
|
|
|
111
|
-
|
|
112
|
-
|
|
109
|
+
#{$self}:not(.dito-width-grow) & {
|
|
110
|
+
// Use `position: absolute` to prevent the text from growing over the
|
|
111
|
+
// button's width, which would cause the button to grow as well.
|
|
112
|
+
position: absolute;
|
|
113
|
+
inset: 0;
|
|
114
|
+
}
|
|
113
115
|
}
|
|
114
116
|
}
|
|
115
117
|
}
|
|
@@ -251,9 +251,11 @@ export default DitoTypeComponent.register('list', {
|
|
|
251
251
|
|
|
252
252
|
getEditPath(item, index) {
|
|
253
253
|
if (this.editable) {
|
|
254
|
-
const path = getViewEditPath(this.schema, this.context) || this.path
|
|
255
254
|
const id = this.getItemId(this.schema, item, index)
|
|
256
|
-
return
|
|
255
|
+
return (
|
|
256
|
+
getViewEditPath(this.schema, id, this.context) ||
|
|
257
|
+
`${this.path}/${id}`
|
|
258
|
+
)
|
|
257
259
|
}
|
|
258
260
|
return null
|
|
259
261
|
},
|
|
@@ -5,37 +5,48 @@
|
|
|
5
5
|
'dito-multiselect-multiple': multiple
|
|
6
6
|
}`
|
|
7
7
|
)
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
8
|
+
.dito-multiselect__inner
|
|
9
|
+
VueMultiselect(
|
|
10
|
+
ref="element"
|
|
11
|
+
v-model="selectedOptions"
|
|
12
|
+
:class="{ 'multiselect--show-highlight': showHighlight }"
|
|
13
|
+
:showLabels="false"
|
|
14
|
+
:placeholder="placeholder"
|
|
15
|
+
tagPlaceholder="Press enter to add new tag"
|
|
16
|
+
:options="populate && activeOptions || []"
|
|
17
|
+
:customLabel="getLabelForOption"
|
|
18
|
+
:trackBy="optionValue"
|
|
19
|
+
:groupLabel="groupByLabel"
|
|
20
|
+
:groupValues="groupByOptions"
|
|
21
|
+
:multiple="multiple"
|
|
22
|
+
:taggable="taggable"
|
|
23
|
+
:searchable="searchable"
|
|
24
|
+
:internalSearch="!searchFilter"
|
|
25
|
+
:preserveSearch="!!searchFilter"
|
|
26
|
+
:clearOnSelect="!searchFilter"
|
|
27
|
+
:closeOnSelect="!stayOpen"
|
|
28
|
+
:loading="isLoading"
|
|
29
|
+
v-bind="attributes"
|
|
30
|
+
@open="onOpen"
|
|
31
|
+
@close="onClose"
|
|
32
|
+
@tag="onAddTag"
|
|
33
|
+
@search-change="onSearchChange"
|
|
34
|
+
)
|
|
35
|
+
button.dito-button-clear.dito-button-overlay(
|
|
36
|
+
v-if="showClearButton"
|
|
37
|
+
type="button"
|
|
38
|
+
:disabled="disabled"
|
|
39
|
+
@click="clear"
|
|
40
|
+
)
|
|
41
|
+
DitoEditButtons(
|
|
42
|
+
v-if="editable"
|
|
43
|
+
:editable="editable"
|
|
44
|
+
:editPath="editPath"
|
|
45
|
+
:schema="schema"
|
|
46
|
+
:dataPath="dataPath"
|
|
47
|
+
:data="data"
|
|
48
|
+
:meta="meta"
|
|
49
|
+
:store="store"
|
|
39
50
|
)
|
|
40
51
|
</template>
|
|
41
52
|
|
|
@@ -218,12 +229,20 @@ $tag-padding: 3px;
|
|
|
218
229
|
$tag-line-height: 1em;
|
|
219
230
|
|
|
220
231
|
.dito-multiselect {
|
|
232
|
+
display: inline-flex;
|
|
221
233
|
position: relative;
|
|
222
234
|
|
|
235
|
+
&__inner {
|
|
236
|
+
flex: 1;
|
|
237
|
+
position: relative;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// TODO: BEM
|
|
223
241
|
&.dito-multiselect-single {
|
|
224
242
|
--input-width: 100%;
|
|
225
243
|
}
|
|
226
244
|
|
|
245
|
+
// TODO: BEM
|
|
227
246
|
&.dito-multiselect-multiple {
|
|
228
247
|
--input-width: auto;
|
|
229
248
|
}
|
|
@@ -234,6 +253,10 @@ $tag-line-height: 1em;
|
|
|
234
253
|
}
|
|
235
254
|
}
|
|
236
255
|
|
|
256
|
+
.dito-edit-buttons {
|
|
257
|
+
margin-left: $form-spacing-half;
|
|
258
|
+
}
|
|
259
|
+
|
|
237
260
|
.dito-button-clear {
|
|
238
261
|
width: $spinner-width;
|
|
239
262
|
}
|
|
@@ -1,40 +1,51 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
2
|
//- Nesting is needed to make an arrow appear over the select item:
|
|
3
3
|
.dito-select
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
template(
|
|
13
|
-
v-if="populate"
|
|
4
|
+
.dito-select__inner
|
|
5
|
+
select(
|
|
6
|
+
:id="dataPath"
|
|
7
|
+
ref="element"
|
|
8
|
+
v-model="selectedValue"
|
|
9
|
+
v-bind="attributes"
|
|
10
|
+
@mousedown="populate = true"
|
|
11
|
+
@focus="populate = true"
|
|
14
12
|
)
|
|
15
13
|
template(
|
|
16
|
-
v-
|
|
14
|
+
v-if="populate"
|
|
17
15
|
)
|
|
18
|
-
|
|
19
|
-
v-
|
|
20
|
-
:label="option[groupByLabel]"
|
|
16
|
+
template(
|
|
17
|
+
v-for="option in options"
|
|
21
18
|
)
|
|
19
|
+
optgroup(
|
|
20
|
+
v-if="groupBy"
|
|
21
|
+
:label="option[groupByLabel]"
|
|
22
|
+
)
|
|
23
|
+
option(
|
|
24
|
+
v-for="opt in option[groupByOptions]"
|
|
25
|
+
:value="getValueForOption(opt)"
|
|
26
|
+
) {{ getLabelForOption(opt) }}
|
|
22
27
|
option(
|
|
23
|
-
v-
|
|
24
|
-
:value="getValueForOption(
|
|
25
|
-
) {{ getLabelForOption(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
) {{ getLabelForOption(
|
|
30
|
-
|
|
31
|
-
v-
|
|
28
|
+
v-else
|
|
29
|
+
:value="getValueForOption(option)"
|
|
30
|
+
) {{ getLabelForOption(option) }}
|
|
31
|
+
template(
|
|
32
|
+
v-else-if="selectedOption"
|
|
33
|
+
)
|
|
34
|
+
option(:value="selectedValue") {{ getLabelForOption(selectedOption) }}
|
|
35
|
+
button.dito-button-clear.dito-button-overlay(
|
|
36
|
+
v-if="showClearButton"
|
|
37
|
+
:disabled="disabled"
|
|
38
|
+
@click="clear"
|
|
32
39
|
)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
:
|
|
37
|
-
|
|
40
|
+
DitoEditButtons(
|
|
41
|
+
v-if="editable"
|
|
42
|
+
:editable="editable"
|
|
43
|
+
:editPath="editPath"
|
|
44
|
+
:schema="schema"
|
|
45
|
+
:dataPath="dataPath"
|
|
46
|
+
:data="data"
|
|
47
|
+
:meta="meta"
|
|
48
|
+
:store="store"
|
|
38
49
|
)
|
|
39
50
|
</template>
|
|
40
51
|
|
|
@@ -65,12 +76,30 @@ export default DitoTypeComponent.register('select', {
|
|
|
65
76
|
$select-arrow-right: calc(($select-arrow-width - $select-arrow-size) / 2);
|
|
66
77
|
|
|
67
78
|
.dito-select {
|
|
68
|
-
display: inline-
|
|
79
|
+
display: inline-flex;
|
|
69
80
|
position: relative;
|
|
70
81
|
|
|
71
82
|
select {
|
|
72
83
|
padding-right: $select-arrow-width;
|
|
73
84
|
}
|
|
85
|
+
|
|
86
|
+
&__inner {
|
|
87
|
+
flex: 1;
|
|
88
|
+
position: relative;
|
|
89
|
+
|
|
90
|
+
&::after {
|
|
91
|
+
position: absolute;
|
|
92
|
+
@include arrow($select-arrow-size);
|
|
93
|
+
|
|
94
|
+
bottom: $select-arrow-bottom;
|
|
95
|
+
right: calc(#{$select-arrow-right} + #{$border-width});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.dito-edit-buttons {
|
|
100
|
+
margin-left: $form-spacing-half;
|
|
101
|
+
}
|
|
102
|
+
|
|
74
103
|
// Handle .dito-width-fill separately due to required nesting of select:
|
|
75
104
|
&.dito-width-fill {
|
|
76
105
|
select {
|
|
@@ -78,14 +107,6 @@ $select-arrow-right: calc(($select-arrow-width - $select-arrow-size) / 2);
|
|
|
78
107
|
}
|
|
79
108
|
}
|
|
80
109
|
|
|
81
|
-
&::after {
|
|
82
|
-
position: absolute;
|
|
83
|
-
@include arrow($select-arrow-size);
|
|
84
|
-
|
|
85
|
-
bottom: $select-arrow-bottom;
|
|
86
|
-
right: calc(#{$select-arrow-right} + #{$border-width});
|
|
87
|
-
}
|
|
88
|
-
|
|
89
110
|
&.dito-disabled::after {
|
|
90
111
|
border-color: $border-color;
|
|
91
112
|
}
|