@ditojs/admin 2.1.1 → 2.1.2
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 +1525 -1489
- package/dist/dito-admin.umd.js +4 -4
- package/dist/style.css +1 -1
- package/package.json +3 -3
- package/src/DitoContext.js +7 -3
- package/src/components/DitoPane.vue +4 -4
- package/src/components/DitoSchema.vue +6 -6
- package/src/components/DitoView.vue +1 -4
- package/src/mixins/OptionsMixin.js +2 -0
- package/src/types/DitoTypeMultiselect.vue +214 -181
- package/src/types/DitoTypeText.vue +3 -1
- package/src/utils/filter.js +2 -0
- package/src/utils/schema.js +109 -79
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ditojs/admin",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.2",
|
|
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,7 +33,7 @@
|
|
|
33
33
|
"not ie_mob > 0"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@ditojs/ui": "^2.1.
|
|
36
|
+
"@ditojs/ui": "^2.1.2",
|
|
37
37
|
"@ditojs/utils": "^2.1.1",
|
|
38
38
|
"@kyvg/vue3-notification": "^2.9.0",
|
|
39
39
|
"@lk77/vue3-color": "^3.0.6",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"vite": "^4.2.1"
|
|
83
83
|
},
|
|
84
84
|
"types": "types",
|
|
85
|
-
"gitHead": "
|
|
85
|
+
"gitHead": "90bf14abf59293794f94d47c8866d9e85dd49ac8",
|
|
86
86
|
"scripts": {
|
|
87
87
|
"build": "vite build",
|
|
88
88
|
"watch": "yarn build --mode 'development' --watch",
|
package/src/DitoContext.js
CHANGED
|
@@ -67,6 +67,10 @@ export default class DitoContext {
|
|
|
67
67
|
return get(this, 'nested', true)
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
get schema() {
|
|
71
|
+
return get(this, 'schema', null)
|
|
72
|
+
}
|
|
73
|
+
|
|
70
74
|
get value() {
|
|
71
75
|
return get(this, 'value', undefined)
|
|
72
76
|
}
|
|
@@ -154,9 +158,9 @@ export default class DitoContext {
|
|
|
154
158
|
return get(this, 'formLabel', null)
|
|
155
159
|
}
|
|
156
160
|
|
|
157
|
-
//
|
|
158
|
-
//
|
|
159
|
-
//
|
|
161
|
+
// NOTE: Like 'options', the associated component doesn't always exist, e.g.
|
|
162
|
+
// in nested forms during `processData()`. But `schema` is guaranteed to
|
|
163
|
+
// always be available.
|
|
160
164
|
get component() {
|
|
161
165
|
return get(this, 'component', null)
|
|
162
166
|
}
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
<script>
|
|
38
38
|
import DitoComponent from '../DitoComponent.js'
|
|
39
39
|
import { appendDataPath } from '../utils/data.js'
|
|
40
|
-
import {
|
|
40
|
+
import { getAllPanelEntries, isNested } from '../utils/schema.js'
|
|
41
41
|
|
|
42
42
|
// @vue/component
|
|
43
43
|
export default DitoComponent.component('DitoPane', {
|
|
@@ -95,12 +95,12 @@ export default DitoComponent.component('DitoPane', {
|
|
|
95
95
|
)
|
|
96
96
|
},
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
panelEntries() {
|
|
99
99
|
// Gather all panel schemas from all component schemas, by finding those
|
|
100
|
-
// that want to provide a panel. See `
|
|
100
|
+
// that want to provide a panel. See `getAllPanelEntries()` for details.
|
|
101
101
|
return this.componentSchemas.flatMap(
|
|
102
102
|
({ schema, nestedDataPath: dataPath }) =>
|
|
103
|
-
|
|
103
|
+
getAllPanelEntries(
|
|
104
104
|
schema,
|
|
105
105
|
dataPath,
|
|
106
106
|
this.schemaComponent,
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
v-else-if="isPopulated"
|
|
76
76
|
)
|
|
77
77
|
DitoPanels(
|
|
78
|
-
:panels="
|
|
78
|
+
:panels="panelEntries"
|
|
79
79
|
:data="data"
|
|
80
80
|
:meta="meta"
|
|
81
81
|
:store="store"
|
|
@@ -99,7 +99,7 @@ import ItemMixin from '../mixins/ItemMixin.js'
|
|
|
99
99
|
import { appendDataPath, getParentItem } from '../utils/data.js'
|
|
100
100
|
import {
|
|
101
101
|
getNamedSchemas,
|
|
102
|
-
|
|
102
|
+
getPanelEntries,
|
|
103
103
|
setDefaultValues,
|
|
104
104
|
processData
|
|
105
105
|
} from '../utils/schema.js'
|
|
@@ -164,12 +164,12 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
164
164
|
return this.hasOwnData ? null : this.parentComponent.schemaComponent
|
|
165
165
|
},
|
|
166
166
|
|
|
167
|
-
|
|
168
|
-
const
|
|
167
|
+
panelEntries() {
|
|
168
|
+
const panelEntries = getPanelEntries(this.schema.panels, '')
|
|
169
169
|
for (const pane of this.panes) {
|
|
170
|
-
|
|
170
|
+
panelEntries.push(...pane.panelEntries)
|
|
171
171
|
}
|
|
172
|
-
return
|
|
172
|
+
return panelEntries
|
|
173
173
|
},
|
|
174
174
|
|
|
175
175
|
tabs() {
|
|
@@ -93,10 +93,7 @@ export default DitoComponent.component('DitoView', {
|
|
|
93
93
|
},
|
|
94
94
|
|
|
95
95
|
providesData() {
|
|
96
|
-
return someSchemaComponent(
|
|
97
|
-
this.viewSchema,
|
|
98
|
-
component => hasResource(component)
|
|
99
|
-
)
|
|
96
|
+
return someSchemaComponent(this.viewSchema, hasResource)
|
|
100
97
|
}
|
|
101
98
|
},
|
|
102
99
|
|
|
@@ -100,6 +100,7 @@ export default {
|
|
|
100
100
|
default: null
|
|
101
101
|
}),
|
|
102
102
|
|
|
103
|
+
// TODO: Rename to `options.labelKey` / `optionLabelKey`?
|
|
103
104
|
optionLabel: getSchemaAccessor('options.label', {
|
|
104
105
|
type: [String, Function],
|
|
105
106
|
default: null,
|
|
@@ -114,6 +115,7 @@ export default {
|
|
|
114
115
|
}
|
|
115
116
|
}),
|
|
116
117
|
|
|
118
|
+
// TODO: Rename to `options.valueKey` / `optionValueKey`?
|
|
117
119
|
optionValue: getSchemaAccessor('options.value', {
|
|
118
120
|
type: [String, Function],
|
|
119
121
|
default: null,
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
VueMultiselect(
|
|
9
9
|
ref="element"
|
|
10
10
|
v-model="selectedOptions"
|
|
11
|
+
:class="{ 'multiselect--show-highlight': showHighlight }"
|
|
11
12
|
:showLabels="false"
|
|
12
13
|
:placeholder="placeholder"
|
|
13
14
|
tagPlaceholder="Press enter to add new tag"
|
|
@@ -45,6 +46,7 @@ import TypeMixin from '../mixins/TypeMixin.js'
|
|
|
45
46
|
import OptionsMixin from '../mixins/OptionsMixin.js'
|
|
46
47
|
import VueMultiselect from 'vue-multiselect'
|
|
47
48
|
import { getSchemaAccessor } from '../utils/accessor.js'
|
|
49
|
+
import { isBoolean } from '@ditojs/utils'
|
|
48
50
|
|
|
49
51
|
// @vue/component
|
|
50
52
|
export default DitoTypeComponent.register('multiselect', {
|
|
@@ -53,6 +55,7 @@ export default DitoTypeComponent.register('multiselect', {
|
|
|
53
55
|
|
|
54
56
|
data() {
|
|
55
57
|
return {
|
|
58
|
+
isMounted: false,
|
|
56
59
|
searchedOptions: null,
|
|
57
60
|
populate: false
|
|
58
61
|
}
|
|
@@ -71,8 +74,8 @@ export default DitoTypeComponent.register('multiselect', {
|
|
|
71
74
|
)
|
|
72
75
|
)
|
|
73
76
|
// Filter out options that we couldn't match.
|
|
74
|
-
// TODO:
|
|
75
|
-
.filter(
|
|
77
|
+
// TODO: Should we display an error instead?
|
|
78
|
+
.filter(Boolean)
|
|
76
79
|
: this.selectedOption
|
|
77
80
|
},
|
|
78
81
|
|
|
@@ -111,20 +114,26 @@ export default DitoTypeComponent.register('multiselect', {
|
|
|
111
114
|
}),
|
|
112
115
|
|
|
113
116
|
placeholder() {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
placeholder
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
117
|
+
let { placeholder, searchable, taggable } = this.schema
|
|
118
|
+
if (isBoolean(placeholder)) {
|
|
119
|
+
placeholder = placeholder ? undefined : null
|
|
120
|
+
}
|
|
121
|
+
return placeholder === undefined
|
|
122
|
+
? searchable && taggable
|
|
123
|
+
? `Search or add a ${this.label}`
|
|
124
|
+
: searchable
|
|
125
|
+
? `Select or search ${this.label}`
|
|
126
|
+
: undefined
|
|
127
|
+
: placeholder
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
showHighlight() {
|
|
131
|
+
return this.isMounted && this.$refs.element.pointerDirty
|
|
124
132
|
}
|
|
125
133
|
},
|
|
126
134
|
|
|
127
135
|
mounted() {
|
|
136
|
+
this.isMounted = true
|
|
128
137
|
if (this.autofocus) {
|
|
129
138
|
// vue-multiselect doesn't support the autofocus attribute. We need to
|
|
130
139
|
// handle it here.
|
|
@@ -211,224 +220,248 @@ $tag-line-height: 1em;
|
|
|
211
220
|
.dito-multiselect {
|
|
212
221
|
position: relative;
|
|
213
222
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
min-height: inherit;
|
|
217
|
-
color: $color-black;
|
|
223
|
+
&.dito-multiselect-single {
|
|
224
|
+
--input-width: 100%;
|
|
218
225
|
}
|
|
219
226
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
overflow: auto;
|
|
223
|
-
min-height: inherit;
|
|
224
|
-
padding: 0 $spinner-width 0 0;
|
|
225
|
-
// So tags can float on multiple lines and have proper margins:
|
|
226
|
-
padding-bottom: $tag-margin;
|
|
227
|
+
&.dito-multiselect-multiple {
|
|
228
|
+
--input-width: auto;
|
|
227
229
|
}
|
|
228
230
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
padding: $tag-padding $tag-icon-width $tag-padding 0.8em;
|
|
234
|
-
line-height: $tag-line-height;
|
|
235
|
-
height: calc($input-height - 2 * $tag-padding);
|
|
231
|
+
&.dito-has-errors {
|
|
232
|
+
&__tags {
|
|
233
|
+
border-color: $color-error;
|
|
234
|
+
}
|
|
236
235
|
}
|
|
237
236
|
|
|
238
|
-
.
|
|
239
|
-
|
|
240
|
-
line-height: 0;
|
|
237
|
+
.dito-button-clear {
|
|
238
|
+
width: $spinner-width;
|
|
241
239
|
}
|
|
242
240
|
|
|
243
|
-
.
|
|
244
|
-
|
|
245
|
-
|
|
241
|
+
.multiselect {
|
|
242
|
+
$self: last-selector(&);
|
|
243
|
+
|
|
246
244
|
font-size: inherit;
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
margin: 0 0 1px 0;
|
|
250
|
-
// Sadly, vue-select sets style="padding: ...;" in addition to using
|
|
251
|
-
// classes, so `!important` is necessary:
|
|
252
|
-
padding: $input-padding !important;
|
|
253
|
-
// So input can float next to tags and have proper margins with
|
|
254
|
-
// .multiselect__tags:
|
|
255
|
-
padding-bottom: 0 !important;
|
|
256
|
-
background: none;
|
|
257
|
-
}
|
|
245
|
+
min-height: inherit;
|
|
246
|
+
color: $color-black;
|
|
258
247
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
248
|
+
&--active {
|
|
249
|
+
#{$self}__placeholder {
|
|
250
|
+
// Don't use `display: none` to hide place-holder, as the layout would
|
|
251
|
+
// collapse.
|
|
252
|
+
display: inline-block;
|
|
253
|
+
visibility: hidden;
|
|
254
|
+
}
|
|
263
255
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
}
|
|
271
|
-
}
|
|
256
|
+
#{$self}__single,
|
|
257
|
+
#{$self}__input {
|
|
258
|
+
// Sadly, vue-select sets `style="width"` in addition to using classes
|
|
259
|
+
// so `!important` is necessary:
|
|
260
|
+
width: var(--input-width) !important;
|
|
261
|
+
}
|
|
272
262
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
right: $border-width;
|
|
279
|
-
bottom: $border-width;
|
|
280
|
-
height: inherit;
|
|
281
|
-
border-radius: $border-radius;
|
|
282
|
-
}
|
|
263
|
+
#{$self}__tags {
|
|
264
|
+
border-color: $color-active;
|
|
265
|
+
border-bottom-left-radius: 0;
|
|
266
|
+
border-bottom-right-radius: 0;
|
|
267
|
+
}
|
|
283
268
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
269
|
+
#{$self}__content-wrapper {
|
|
270
|
+
border: $border-width solid $color-active;
|
|
271
|
+
border-top-color: $border-color;
|
|
272
|
+
margin: -1px 0 0;
|
|
273
|
+
border-top-left-radius: 0;
|
|
274
|
+
border-top-right-radius: 0;
|
|
275
|
+
}
|
|
287
276
|
|
|
288
|
-
|
|
289
|
-
|
|
277
|
+
&#{$self}--above {
|
|
278
|
+
#{$self}__tags {
|
|
279
|
+
border-radius: $border-radius;
|
|
280
|
+
border-top-left-radius: 0;
|
|
281
|
+
border-top-right-radius: 0;
|
|
282
|
+
}
|
|
290
283
|
|
|
291
|
-
|
|
292
|
-
|
|
284
|
+
#{$self}__content-wrapper {
|
|
285
|
+
border: $border-width solid $color-active;
|
|
286
|
+
border-bottom-color: $border-color;
|
|
287
|
+
margin: 0 0 -1px;
|
|
288
|
+
border-radius: $border-radius;
|
|
289
|
+
border-bottom-left-radius: 0;
|
|
290
|
+
border-bottom-right-radius: 0;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
293
|
}
|
|
294
|
-
}
|
|
295
294
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
//
|
|
302
|
-
|
|
303
|
-
border-top-color: $color-active;
|
|
304
|
-
inset: 0;
|
|
305
|
-
margin: auto;
|
|
295
|
+
&__tags {
|
|
296
|
+
font-size: inherit;
|
|
297
|
+
overflow: auto;
|
|
298
|
+
min-height: inherit;
|
|
299
|
+
padding: 0 $spinner-width 0 0;
|
|
300
|
+
// So tags can float on multiple lines and have proper margins:
|
|
301
|
+
padding-bottom: $tag-margin;
|
|
306
302
|
}
|
|
307
|
-
}
|
|
308
303
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
&::after {
|
|
316
|
-
// Instruction text for options
|
|
317
|
-
padding: $input-padding;
|
|
304
|
+
&__tag {
|
|
305
|
+
float: left;
|
|
306
|
+
margin: $tag-margin 0 0 $tag-margin;
|
|
307
|
+
border-radius: 1em;
|
|
308
|
+
padding: $tag-padding $tag-icon-width $tag-padding 0.8em;
|
|
318
309
|
line-height: $tag-line-height;
|
|
310
|
+
height: calc($input-height - 2 * $tag-padding);
|
|
319
311
|
}
|
|
320
|
-
}
|
|
321
312
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
position: absolute;
|
|
326
|
-
background: transparent;
|
|
327
|
-
color: $color-white;
|
|
313
|
+
&__tags-wrap {
|
|
314
|
+
overflow: auto;
|
|
315
|
+
line-height: 0;
|
|
328
316
|
}
|
|
329
|
-
}
|
|
330
317
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
318
|
+
&__single,
|
|
319
|
+
&__placeholder,
|
|
320
|
+
&__input {
|
|
321
|
+
font-size: inherit;
|
|
322
|
+
line-height: inherit;
|
|
323
|
+
min-height: 0;
|
|
324
|
+
margin: 0 0 1px 0;
|
|
325
|
+
// Sadly, vue-select sets style="padding: ...;" in addition to using
|
|
326
|
+
// classes, so `!important` is necessary:
|
|
327
|
+
padding: $input-padding !important;
|
|
328
|
+
// So input can float next to tags and have proper margins with
|
|
329
|
+
// &__tags:
|
|
330
|
+
padding-bottom: 0 !important;
|
|
331
|
+
background: none;
|
|
332
|
+
}
|
|
335
333
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
margin: 0;
|
|
334
|
+
&__placeholder,
|
|
335
|
+
&__input::placeholder {
|
|
336
|
+
color: $color-placeholder;
|
|
337
|
+
}
|
|
341
338
|
|
|
342
|
-
|
|
343
|
-
|
|
339
|
+
&__placeholder {
|
|
340
|
+
&::after {
|
|
341
|
+
// Enforce actual line-height for positioning.
|
|
342
|
+
content: '\200b';
|
|
343
|
+
}
|
|
344
|
+
}
|
|
344
345
|
|
|
345
|
-
|
|
346
|
-
|
|
346
|
+
&__select,
|
|
347
|
+
&__spinner {
|
|
348
|
+
padding: 0;
|
|
349
|
+
// $border-width to prevent masking border with &__spinner
|
|
350
|
+
top: $border-width;
|
|
351
|
+
right: $border-width;
|
|
352
|
+
bottom: $border-width;
|
|
353
|
+
height: inherit;
|
|
354
|
+
border-radius: $border-radius;
|
|
347
355
|
}
|
|
348
356
|
|
|
349
|
-
|
|
350
|
-
|
|
357
|
+
&__select {
|
|
358
|
+
width: 0;
|
|
359
|
+
margin-right: calc($select-arrow-width / 2);
|
|
360
|
+
|
|
361
|
+
&::before {
|
|
362
|
+
@include arrow($select-arrow-size);
|
|
363
|
+
|
|
364
|
+
bottom: $select-arrow-bottom;
|
|
365
|
+
right: calc(-1 * $select-arrow-size / 2);
|
|
366
|
+
}
|
|
351
367
|
}
|
|
352
|
-
}
|
|
353
368
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
color: $color-text;
|
|
357
|
-
font-weight: normal;
|
|
369
|
+
&__spinner {
|
|
370
|
+
width: $spinner-width;
|
|
358
371
|
|
|
359
|
-
|
|
360
|
-
|
|
372
|
+
&::before,
|
|
373
|
+
&::after {
|
|
374
|
+
// Change the width of the loading spinner
|
|
375
|
+
border-width: 3px;
|
|
376
|
+
border-top-color: $color-active;
|
|
377
|
+
inset: 0;
|
|
378
|
+
margin: auto;
|
|
379
|
+
}
|
|
361
380
|
}
|
|
362
|
-
}
|
|
363
381
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
background: $color-active;
|
|
367
|
-
color: $color-text-inverted;
|
|
368
|
-
}
|
|
382
|
+
&__option {
|
|
383
|
+
$option: last-selector(&);
|
|
369
384
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
}
|
|
385
|
+
min-height: unset;
|
|
386
|
+
height: unset;
|
|
387
|
+
line-height: $tag-line-height;
|
|
388
|
+
padding: $input-padding;
|
|
375
389
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
390
|
+
&::after {
|
|
391
|
+
// Instruction text for options
|
|
392
|
+
padding: $input-padding;
|
|
393
|
+
line-height: $tag-line-height;
|
|
394
|
+
}
|
|
379
395
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
396
|
+
// Only show the highlight once the pulldown has received mouse or
|
|
397
|
+
// keyboard interaction, in which case `&--show-highlight` will be set,
|
|
398
|
+
// which is controlled by `pointerDirty` in vue-multiselect.
|
|
399
|
+
// Until then, clear the highlight style, but only if it isn't also
|
|
400
|
+
// disabled or selected, in which case we want to keep the style.
|
|
401
|
+
@at-root #{$self}:not(#{$self}--show-highlight)
|
|
402
|
+
#{$option}:not(#{$option}--disabled):not(#{$option}--selected) {
|
|
403
|
+
color: $color-text;
|
|
404
|
+
background: transparent;
|
|
405
|
+
}
|
|
383
406
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
407
|
+
&--highlight {
|
|
408
|
+
&::after {
|
|
409
|
+
display: block;
|
|
410
|
+
position: absolute;
|
|
411
|
+
background: transparent;
|
|
412
|
+
color: $color-white;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
@at-root #{$self}#{$self}--show-highlight #{last-selector(&)} {
|
|
416
|
+
color: $color-text-inverted;
|
|
417
|
+
background: $color-active;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
&--selected {
|
|
422
|
+
font-weight: normal;
|
|
423
|
+
color: $color-text;
|
|
424
|
+
background: $color-highlight;
|
|
425
|
+
|
|
426
|
+
&#{$option}--highlight {
|
|
427
|
+
color: $color-text-inverted;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
391
430
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
431
|
+
&--disabled {
|
|
432
|
+
background: none;
|
|
433
|
+
color: $color-disabled;
|
|
434
|
+
}
|
|
396
435
|
}
|
|
397
436
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
margin: -1px 0 0;
|
|
402
|
-
border-top-left-radius: 0;
|
|
403
|
-
border-top-right-radius: 0;
|
|
437
|
+
&__tag {
|
|
438
|
+
color: $color-text-inverted;
|
|
439
|
+
background: $color-active;
|
|
404
440
|
}
|
|
405
441
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
442
|
+
&__tag-icon {
|
|
443
|
+
background: none;
|
|
444
|
+
border-radius: 1em;
|
|
445
|
+
width: $tag-icon-width;
|
|
446
|
+
margin: 0;
|
|
447
|
+
|
|
448
|
+
&::after {
|
|
449
|
+
@extend %icon-clear;
|
|
450
|
+
|
|
451
|
+
font-size: 0.9em;
|
|
452
|
+
color: $color-text-inverted;
|
|
411
453
|
}
|
|
412
454
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
border-bottom-color: $border-color;
|
|
416
|
-
margin: 0 0 -1px;
|
|
417
|
-
border-radius: $border-radius;
|
|
418
|
-
border-bottom-left-radius: 0;
|
|
419
|
-
border-bottom-right-radius: 0;
|
|
455
|
+
&:hover::after {
|
|
456
|
+
color: $color-text;
|
|
420
457
|
}
|
|
421
458
|
}
|
|
422
|
-
}
|
|
423
459
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
border
|
|
460
|
+
&__tags,
|
|
461
|
+
&__content-wrapper {
|
|
462
|
+
border: $border-style;
|
|
463
|
+
border-radius: $border-radius;
|
|
427
464
|
}
|
|
428
465
|
}
|
|
429
|
-
|
|
430
|
-
.dito-button-clear {
|
|
431
|
-
width: $spinner-width;
|
|
432
|
-
}
|
|
433
466
|
}
|
|
434
467
|
</style>
|
|
@@ -46,9 +46,11 @@ export default DitoTypeComponent.register(
|
|
|
46
46
|
|
|
47
47
|
inputValue: {
|
|
48
48
|
get() {
|
|
49
|
-
return
|
|
49
|
+
return (
|
|
50
|
+
this.type === 'password' &&
|
|
50
51
|
this.value === undefined &&
|
|
51
52
|
!this.focused
|
|
53
|
+
)
|
|
52
54
|
? maskedPassword
|
|
53
55
|
: this.value
|
|
54
56
|
},
|
package/src/utils/filter.js
CHANGED
|
@@ -63,6 +63,7 @@ export const filterComponents = {
|
|
|
63
63
|
|
|
64
64
|
export function getFiltersPanel(filters, dataPath, proxy) {
|
|
65
65
|
const panel = {
|
|
66
|
+
type: 'panel',
|
|
66
67
|
label: 'Filters',
|
|
67
68
|
name: '$filters',
|
|
68
69
|
target: dataPath,
|
|
@@ -125,6 +126,7 @@ function getFiltersComponents(filters) {
|
|
|
125
126
|
? filterComponents[type]?.(filter)
|
|
126
127
|
: filter.components
|
|
127
128
|
if (components) {
|
|
129
|
+
form.type = 'form'
|
|
128
130
|
form.components = {}
|
|
129
131
|
// Convert labels to placeholders:
|
|
130
132
|
for (const [key, component] of Object.entries(components)) {
|