@ditojs/admin 2.0.5 → 2.1.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.
- package/dist/dito-admin.es.js +1511 -1435
- package/dist/dito-admin.umd.js +4 -4
- package/dist/style.css +1 -1
- package/package.json +31 -31
- package/src/DitoAdmin.js +66 -31
- package/src/DitoComponent.js +4 -1
- package/src/DitoContext.js +13 -5
- package/src/{TypeComponent.js → DitoTypeComponent.js} +8 -5
- package/src/components/DitoAccount.vue +20 -19
- package/src/components/DitoButtons.vue +14 -12
- package/src/components/DitoClipboard.vue +16 -8
- package/src/components/DitoContainer.vue +56 -43
- package/src/components/DitoCreateButton.vue +20 -15
- package/src/components/DitoDialog.vue +69 -48
- package/src/components/DitoEditButtons.vue +16 -14
- package/src/components/DitoElement.vue +2 -3
- package/src/components/DitoErrors.vue +18 -13
- package/src/components/DitoForm.vue +41 -24
- package/src/components/DitoFormNested.vue +12 -10
- package/src/components/DitoHeader.vue +103 -69
- package/src/components/DitoLabel.vue +108 -81
- package/src/components/DitoMenu.vue +52 -36
- package/src/components/DitoPagination.vue +9 -7
- package/src/components/DitoPane.vue +53 -45
- package/src/components/DitoPanel.vue +62 -42
- package/src/components/DitoPanels.vue +11 -10
- package/src/components/DitoRoot.vue +57 -46
- package/src/components/DitoSchema.vue +179 -131
- package/src/components/DitoSchemaInlined.vue +39 -28
- package/src/components/DitoScopes.vue +41 -31
- package/src/components/DitoSpinner.vue +31 -40
- package/src/components/DitoTableCell.vue +9 -9
- package/src/components/DitoTableHead.vue +52 -37
- package/src/components/DitoTabs.vue +39 -29
- package/src/components/DitoTreeItem.vue +140 -86
- package/src/components/DitoVNode.vue +1 -1
- package/src/components/DitoView.vue +13 -11
- package/src/mixins/DataMixin.js +11 -9
- package/src/mixins/DitoMixin.js +47 -25
- package/src/mixins/EmitterMixin.js +2 -1
- package/src/mixins/ItemMixin.js +15 -10
- package/src/mixins/LoadingMixin.js +2 -1
- package/src/mixins/NumberMixin.js +15 -10
- package/src/mixins/OptionsMixin.js +24 -12
- package/src/mixins/ResourceMixin.js +42 -34
- package/src/mixins/RouteMixin.js +8 -8
- package/src/mixins/SortableMixin.js +1 -1
- package/src/mixins/SourceMixin.js +68 -34
- package/src/mixins/TypeMixin.js +5 -4
- package/src/mixins/ValidationMixin.js +3 -0
- package/src/styles/_base.scss +17 -0
- package/src/styles/_button.scss +212 -0
- package/src/styles/_imports.scss +2 -0
- package/src/styles/_layout.scss +22 -0
- package/src/styles/_notifications.scss +54 -0
- package/src/styles/_pulldown.scss +39 -0
- package/src/styles/_scroll.scss +15 -0
- package/src/styles/_settings.scss +68 -0
- package/src/styles/_sortable.scss +13 -0
- package/src/styles/_table.scss +224 -0
- package/src/styles/style.scss +9 -0
- package/src/types/DitoTypeButton.vue +72 -0
- package/src/types/{TypeCheckbox.vue → DitoTypeCheckbox.vue} +12 -11
- package/src/types/{TypeCheckboxes.vue → DitoTypeCheckboxes.vue} +21 -15
- package/src/types/{TypeCode.vue → DitoTypeCode.vue} +46 -34
- package/src/types/{TypeColor.vue → DitoTypeColor.vue} +71 -52
- package/src/types/{TypeComponent.vue → DitoTypeComponent.vue} +2 -2
- package/src/types/DitoTypeComputed.vue +54 -0
- package/src/types/DitoTypeDate.vue +64 -0
- package/src/types/DitoTypeLabel.vue +23 -0
- package/src/types/{TypeList.vue → DitoTypeList.vue} +83 -61
- package/src/types/{TypeMarkup.vue → DitoTypeMarkup.vue} +172 -122
- package/src/types/DitoTypeMultiselect.vue +434 -0
- package/src/types/DitoTypeNumber.vue +46 -0
- package/src/types/{TypeObject.vue → DitoTypeObject.vue} +41 -26
- package/src/types/{TypePanel.vue → DitoTypePanel.vue} +2 -2
- package/src/types/{TypeProgress.vue → DitoTypeProgress.vue} +4 -6
- package/src/types/{TypeRadio.vue → DitoTypeRadio.vue} +17 -13
- package/src/types/{TypeSection.vue → DitoTypeSection.vue} +17 -17
- package/src/types/{TypeSelect.vue → DitoTypeSelect.vue} +39 -35
- package/src/types/{TypeSlider.vue → DitoTypeSlider.vue} +29 -23
- package/src/types/{TypeSwitch.vue → DitoTypeSwitch.vue} +15 -13
- package/src/types/DitoTypeText.vue +77 -0
- package/src/types/{TypeTextarea.vue → DitoTypeTextarea.vue} +17 -14
- package/src/types/DitoTypeTreeList.vue +191 -0
- package/src/types/{TypeUpload.vue → DitoTypeUpload.vue} +92 -65
- package/src/types/index.js +26 -26
- package/src/utils/SchemaGraph.js +21 -13
- package/src/utils/accessor.js +17 -9
- package/src/utils/data.js +4 -1
- package/src/utils/filter.js +8 -10
- package/src/utils/options.js +3 -3
- package/src/utils/resource.js +12 -10
- package/src/utils/schema.js +190 -125
- package/src/utils/type.js +31 -20
- package/src/validations/_decimals.js +1 -2
- package/types/index.d.ts +27 -23
- package/src/styles/_base.sass +0 -15
- package/src/styles/_button.sass +0 -127
- package/src/styles/_imports.sass +0 -2
- package/src/styles/_layout.sass +0 -13
- package/src/styles/_notifications.sass +0 -33
- package/src/styles/_pulldown.sass +0 -26
- package/src/styles/_scroll.sass +0 -13
- package/src/styles/_settings.sass +0 -55
- package/src/styles/_sortable.sass +0 -9
- package/src/styles/_table.sass +0 -153
- package/src/styles/style.sass +0 -10
- package/src/types/TypeButton.vue +0 -73
- package/src/types/TypeComputed.vue +0 -53
- package/src/types/TypeDate.vue +0 -64
- package/src/types/TypeLabel.vue +0 -19
- package/src/types/TypeMultiselect.vue +0 -376
- package/src/types/TypeNumber.vue +0 -44
- package/src/types/TypeText.vue +0 -67
- package/src/types/TypeTreeList.vue +0 -164
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
<template lang="pug">
|
|
2
|
-
//- TODO: Find a better way to trigger evaluation of `value` that dose not
|
|
3
|
-
//- involve actually rendering it when the component is not visible.
|
|
4
|
-
input.dito-text.dito-input(
|
|
5
|
-
ref="element"
|
|
6
|
-
:id="dataPath"
|
|
7
|
-
:name="name"
|
|
8
|
-
type="text"
|
|
9
|
-
:value="value"
|
|
10
|
-
:disabled="disabled"
|
|
11
|
-
:readonly="true"
|
|
12
|
-
)
|
|
13
|
-
</template>
|
|
14
|
-
|
|
15
|
-
<script>
|
|
16
|
-
import TypeComponent from '../TypeComponent.js'
|
|
17
|
-
import TypeMixin from '../mixins/TypeMixin.js'
|
|
18
|
-
import DataMixin from '../mixins/DataMixin.js'
|
|
19
|
-
|
|
20
|
-
export default TypeComponent.register([
|
|
21
|
-
'computed', 'data', 'hidden'
|
|
22
|
-
],
|
|
23
|
-
// @vue/component
|
|
24
|
-
{
|
|
25
|
-
mixins: [DataMixin],
|
|
26
|
-
|
|
27
|
-
defaultValue: () => undefined, // Callback to override `defaultValue: null`
|
|
28
|
-
defaultVisible: false,
|
|
29
|
-
|
|
30
|
-
computed: {
|
|
31
|
-
value: {
|
|
32
|
-
get() {
|
|
33
|
-
const { schema } = this
|
|
34
|
-
if (schema.data || schema.dataPath) {
|
|
35
|
-
const value = this.handleDataSchema(schema, 'schema', {
|
|
36
|
-
// Modifying `this.data` below triggers another call of the `value`
|
|
37
|
-
// getter, so use a value of 2 for `resolveCounter` to return the
|
|
38
|
-
// resolved data twice.
|
|
39
|
-
resolveCounter: 2
|
|
40
|
-
})
|
|
41
|
-
// eslint-disable-next-line vue/no-mutating-props
|
|
42
|
-
this.data[this.name] = value
|
|
43
|
-
}
|
|
44
|
-
return TypeMixin.computed.value.get.call(this)
|
|
45
|
-
},
|
|
46
|
-
|
|
47
|
-
set(value) {
|
|
48
|
-
TypeMixin.computed.value.set.call(this, value)
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
})
|
|
53
|
-
</script>
|
package/src/types/TypeDate.vue
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
<template lang="pug">
|
|
2
|
-
.dito-date
|
|
3
|
-
component(
|
|
4
|
-
:is="getComponent(type)"
|
|
5
|
-
ref="element"
|
|
6
|
-
:id="dataPath"
|
|
7
|
-
:locale="locale"
|
|
8
|
-
:dateFormat="{ ...api.formats.date, ...dateFormat }"
|
|
9
|
-
v-model="dateValue"
|
|
10
|
-
v-bind="attributes"
|
|
11
|
-
)
|
|
12
|
-
</template>
|
|
13
|
-
|
|
14
|
-
<script>
|
|
15
|
-
import TypeComponent from '../TypeComponent.js'
|
|
16
|
-
import { getSchemaAccessor } from '../utils/accessor.js'
|
|
17
|
-
import { DatePicker, TimePicker, DateTimePicker } from '@ditojs/ui/src'
|
|
18
|
-
import { isDate } from '@ditojs/utils'
|
|
19
|
-
|
|
20
|
-
export default TypeComponent.register([
|
|
21
|
-
'date', 'datetime', 'time'
|
|
22
|
-
],
|
|
23
|
-
// @vue/component
|
|
24
|
-
{
|
|
25
|
-
components: { DatePicker, TimePicker, DateTimePicker },
|
|
26
|
-
// TODO: This is only here so we get placeholder added. Come up with a better
|
|
27
|
-
// way to support attributes per component (a list of actually supported
|
|
28
|
-
// attributes)
|
|
29
|
-
nativeField: true,
|
|
30
|
-
textField: true,
|
|
31
|
-
|
|
32
|
-
computed: {
|
|
33
|
-
dateValue: {
|
|
34
|
-
get() {
|
|
35
|
-
const { value } = this
|
|
36
|
-
return value ? new Date(value) : value
|
|
37
|
-
},
|
|
38
|
-
|
|
39
|
-
set(value) {
|
|
40
|
-
this.value = value
|
|
41
|
-
}
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
dateFormat: getSchemaAccessor('dateFormat', {
|
|
45
|
-
type: Object,
|
|
46
|
-
default: null
|
|
47
|
-
})
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
methods: {
|
|
51
|
-
getComponent(type) {
|
|
52
|
-
return {
|
|
53
|
-
date: 'date-picker',
|
|
54
|
-
time: 'time-picker',
|
|
55
|
-
datetime: 'date-time-picker'
|
|
56
|
-
}[type]
|
|
57
|
-
}
|
|
58
|
-
},
|
|
59
|
-
|
|
60
|
-
processValue(schema, value) {
|
|
61
|
-
return isDate(value) ? value.toISOString() : value
|
|
62
|
-
}
|
|
63
|
-
})
|
|
64
|
-
</script>
|
package/src/types/TypeLabel.vue
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
<template lang="pug">
|
|
2
|
-
dito-label.dito-label-component(:label="value" :dataPath="dataPath")
|
|
3
|
-
</template>
|
|
4
|
-
|
|
5
|
-
<style lang="sass">
|
|
6
|
-
.dito-label-component
|
|
7
|
-
display: flex
|
|
8
|
-
height: 2em
|
|
9
|
-
</style>
|
|
10
|
-
|
|
11
|
-
<script>
|
|
12
|
-
import TypeComponent from '../TypeComponent.js'
|
|
13
|
-
|
|
14
|
-
// @vue/component
|
|
15
|
-
export default TypeComponent.register('label', {
|
|
16
|
-
excludeValue: true,
|
|
17
|
-
generateLabel: false
|
|
18
|
-
})
|
|
19
|
-
</script>
|
|
@@ -1,376 +0,0 @@
|
|
|
1
|
-
<template lang="pug">
|
|
2
|
-
.dito-multiselect(
|
|
3
|
-
:class=`{
|
|
4
|
-
'dito-multiselect-single': !multiple,
|
|
5
|
-
'dito-multiselect-multiple': multiple
|
|
6
|
-
}`
|
|
7
|
-
)
|
|
8
|
-
vue-multiselect(
|
|
9
|
-
ref="element"
|
|
10
|
-
:show-labels="false"
|
|
11
|
-
:placeholder="placeholder"
|
|
12
|
-
tag-placeholder="Press enter to add new tag",
|
|
13
|
-
:options="populate && activeOptions || []"
|
|
14
|
-
:custom-label="getLabelForOption"
|
|
15
|
-
:track-by="optionValue"
|
|
16
|
-
:group-label="groupByLabel"
|
|
17
|
-
:group-values="groupByOptions"
|
|
18
|
-
:multiple="multiple"
|
|
19
|
-
:taggable="taggable"
|
|
20
|
-
:searchable="searchable"
|
|
21
|
-
:internal-search="!searchFilter"
|
|
22
|
-
:preserve-search="!!searchFilter"
|
|
23
|
-
:clear-on-select="!searchFilter"
|
|
24
|
-
:close-on-select="!stayOpen"
|
|
25
|
-
:loading="isLoading"
|
|
26
|
-
@open="onOpen"
|
|
27
|
-
@close="onClose"
|
|
28
|
-
@tag="onAddTag"
|
|
29
|
-
@search-change="onSearchChange"
|
|
30
|
-
v-model="selectedOptions"
|
|
31
|
-
v-bind="attributes"
|
|
32
|
-
)
|
|
33
|
-
button.dito-button-clear.dito-button-overlay(
|
|
34
|
-
type="button"
|
|
35
|
-
v-if="showClearButton"
|
|
36
|
-
@click="clear"
|
|
37
|
-
:disabled="disabled"
|
|
38
|
-
)
|
|
39
|
-
</template>
|
|
40
|
-
|
|
41
|
-
<style lang="sass">
|
|
42
|
-
@import '../styles/_imports'
|
|
43
|
-
@import 'vue-multiselect/dist/vue-multiselect.css'
|
|
44
|
-
|
|
45
|
-
$spinner-width: $select-arrow-width
|
|
46
|
-
$tag-icon-width: 1.8em
|
|
47
|
-
$tag-margin: 2px
|
|
48
|
-
$tag-padding: 3px
|
|
49
|
-
$tag-line-height: 1.1em
|
|
50
|
-
|
|
51
|
-
.dito-multiselect
|
|
52
|
-
position: relative
|
|
53
|
-
|
|
54
|
-
.multiselect
|
|
55
|
-
font-size: inherit
|
|
56
|
-
min-height: inherit
|
|
57
|
-
color: $color-black
|
|
58
|
-
|
|
59
|
-
.multiselect__tags
|
|
60
|
-
font-size: inherit
|
|
61
|
-
overflow: auto
|
|
62
|
-
min-height: inherit
|
|
63
|
-
padding: 0 $spinner-width 0 0
|
|
64
|
-
// So tags can float on multiple lines and have proper margins:
|
|
65
|
-
padding-bottom: $tag-margin
|
|
66
|
-
|
|
67
|
-
.multiselect__tag
|
|
68
|
-
float: left
|
|
69
|
-
margin: $tag-margin 0 0 $tag-margin
|
|
70
|
-
border-radius: 1em
|
|
71
|
-
padding: $tag-padding $tag-icon-width $tag-padding 0.8em
|
|
72
|
-
line-height: $tag-line-height
|
|
73
|
-
|
|
74
|
-
.multiselect__tags-wrap
|
|
75
|
-
overflow: auto
|
|
76
|
-
line-height: 0
|
|
77
|
-
|
|
78
|
-
.multiselect__single,
|
|
79
|
-
.multiselect__placeholder,
|
|
80
|
-
.multiselect__input
|
|
81
|
-
font-size: inherit
|
|
82
|
-
line-height: inherit
|
|
83
|
-
min-height: 0
|
|
84
|
-
margin: 0 0 1px 0
|
|
85
|
-
// Sadly, vue-select sets style="padding: ...;" in addition to using
|
|
86
|
-
// classes, so `!important` is necessary:
|
|
87
|
-
padding: $input-padding !important
|
|
88
|
-
// So input can float next to tags and have proper margins with
|
|
89
|
-
// .multiselect__tags:
|
|
90
|
-
padding-bottom: 0 !important
|
|
91
|
-
background: none
|
|
92
|
-
|
|
93
|
-
.multiselect__placeholder,
|
|
94
|
-
.multiselect__input::placeholder
|
|
95
|
-
color: $color-placeholder
|
|
96
|
-
|
|
97
|
-
.multiselect--active
|
|
98
|
-
.multiselect__placeholder
|
|
99
|
-
// Don't use `display: none` to hide place-holder, as the layout would
|
|
100
|
-
// collapse.
|
|
101
|
-
display: inline-block
|
|
102
|
-
visibility: hidden
|
|
103
|
-
|
|
104
|
-
.multiselect__select,
|
|
105
|
-
.multiselect__spinner
|
|
106
|
-
padding: 0
|
|
107
|
-
// $border-width to prevent masking border with .multiselect__spinner
|
|
108
|
-
top: $border-width
|
|
109
|
-
right: $border-width
|
|
110
|
-
bottom: $border-width
|
|
111
|
-
height: inherit
|
|
112
|
-
border-radius: $border-radius
|
|
113
|
-
|
|
114
|
-
.multiselect__select
|
|
115
|
-
width: 0
|
|
116
|
-
margin-right: calc($select-arrow-width / 2)
|
|
117
|
-
&::before
|
|
118
|
-
+arrow($select-arrow-size)
|
|
119
|
-
bottom: $select-arrow-bottom
|
|
120
|
-
right: calc(-1 * $select-arrow-size / 2)
|
|
121
|
-
|
|
122
|
-
.multiselect__spinner
|
|
123
|
-
width: $spinner-width
|
|
124
|
-
&::before,
|
|
125
|
-
&::after
|
|
126
|
-
// Change the width of the loading spinner
|
|
127
|
-
border-width: 3px
|
|
128
|
-
border-top-color: $color-active
|
|
129
|
-
inset: 0
|
|
130
|
-
margin: auto
|
|
131
|
-
|
|
132
|
-
.multiselect__option
|
|
133
|
-
min-height: unset
|
|
134
|
-
height: unset
|
|
135
|
-
line-height: $tag-line-height
|
|
136
|
-
padding: $input-padding
|
|
137
|
-
&::after
|
|
138
|
-
// Instruction text for options
|
|
139
|
-
padding: $input-padding
|
|
140
|
-
line-height: $tag-line-height
|
|
141
|
-
.multiselect__option--highlight
|
|
142
|
-
&::after
|
|
143
|
-
display: block
|
|
144
|
-
position: absolute
|
|
145
|
-
background: transparent
|
|
146
|
-
color: $color-white
|
|
147
|
-
.multiselect__option--disabled
|
|
148
|
-
background: none
|
|
149
|
-
color: $color-disabled
|
|
150
|
-
|
|
151
|
-
.multiselect__tag-icon
|
|
152
|
-
background: none
|
|
153
|
-
border-radius: 1em
|
|
154
|
-
font-weight: inherit
|
|
155
|
-
line-height: 1.4em
|
|
156
|
-
width: $tag-icon-width
|
|
157
|
-
&::after
|
|
158
|
-
color: $color-text-inverted
|
|
159
|
-
font-size: 1.3em
|
|
160
|
-
&:hover::after
|
|
161
|
-
color: $color-text
|
|
162
|
-
|
|
163
|
-
.multiselect__option--selected
|
|
164
|
-
background: $color-highlight
|
|
165
|
-
color: $color-text
|
|
166
|
-
font-weight: normal
|
|
167
|
-
&.multiselect__option--highlight
|
|
168
|
-
color: $color-text-inverted
|
|
169
|
-
|
|
170
|
-
.multiselect__tag,
|
|
171
|
-
.multiselect__option--highlight
|
|
172
|
-
background: $color-active
|
|
173
|
-
color: $color-text-inverted
|
|
174
|
-
|
|
175
|
-
.multiselect__tags,
|
|
176
|
-
.multiselect__content-wrapper
|
|
177
|
-
border: $border-style
|
|
178
|
-
border-radius: $border-radius
|
|
179
|
-
|
|
180
|
-
&.dito-multiselect-single
|
|
181
|
-
--input-width: 100%
|
|
182
|
-
&.dito-multiselect-multiple
|
|
183
|
-
--input-width: auto
|
|
184
|
-
|
|
185
|
-
.multiselect--active
|
|
186
|
-
.multiselect__single,
|
|
187
|
-
.multiselect__input
|
|
188
|
-
// Sadly, vue-select sets `style="width"` in addition to using classes
|
|
189
|
-
// so `!important` is necessary:
|
|
190
|
-
width: var(--input-width) !important
|
|
191
|
-
|
|
192
|
-
.multiselect__tags
|
|
193
|
-
border-color: $color-active
|
|
194
|
-
border-bottom-left-radius: 0
|
|
195
|
-
border-bottom-right-radius: 0
|
|
196
|
-
|
|
197
|
-
.multiselect__content-wrapper
|
|
198
|
-
border: $border-width solid $color-active
|
|
199
|
-
border-top-color: $border-color
|
|
200
|
-
margin: -1px 0 0
|
|
201
|
-
border-top-left-radius: 0
|
|
202
|
-
border-top-right-radius: 0
|
|
203
|
-
|
|
204
|
-
&.multiselect--above
|
|
205
|
-
.multiselect__tags
|
|
206
|
-
border-radius: $border-radius
|
|
207
|
-
border-top-left-radius: 0
|
|
208
|
-
border-top-right-radius: 0
|
|
209
|
-
.multiselect__content-wrapper
|
|
210
|
-
border: $border-width solid $color-active
|
|
211
|
-
border-bottom-color: $border-color
|
|
212
|
-
margin: 0 0 -1px
|
|
213
|
-
border-radius: $border-radius
|
|
214
|
-
border-bottom-left-radius: 0
|
|
215
|
-
border-bottom-right-radius: 0
|
|
216
|
-
|
|
217
|
-
&.dito-has-errors
|
|
218
|
-
.multiselect__tags
|
|
219
|
-
border-color: $color-error
|
|
220
|
-
|
|
221
|
-
.dito-button-clear
|
|
222
|
-
width: $spinner-width
|
|
223
|
-
</style>
|
|
224
|
-
|
|
225
|
-
<script>
|
|
226
|
-
import TypeComponent from '../TypeComponent.js'
|
|
227
|
-
import DitoContext from '../DitoContext.js'
|
|
228
|
-
import TypeMixin from '../mixins/TypeMixin.js'
|
|
229
|
-
import OptionsMixin from '../mixins/OptionsMixin.js'
|
|
230
|
-
import VueMultiselect from 'vue-multiselect'
|
|
231
|
-
import { getSchemaAccessor } from '../utils/accessor.js'
|
|
232
|
-
|
|
233
|
-
// @vue/component
|
|
234
|
-
export default TypeComponent.register('multiselect', {
|
|
235
|
-
components: { VueMultiselect },
|
|
236
|
-
mixins: [OptionsMixin],
|
|
237
|
-
|
|
238
|
-
data() {
|
|
239
|
-
return {
|
|
240
|
-
searchedOptions: null,
|
|
241
|
-
populate: false
|
|
242
|
-
}
|
|
243
|
-
},
|
|
244
|
-
|
|
245
|
-
computed: {
|
|
246
|
-
selectedOptions: {
|
|
247
|
-
get() {
|
|
248
|
-
return this.multiple
|
|
249
|
-
? (this.selectedValue || [])
|
|
250
|
-
.map(
|
|
251
|
-
// If an option cannot be found, we may be in taggable mode and
|
|
252
|
-
// can add it.
|
|
253
|
-
value => this.getOptionForValue(value) || this.addTagOption(value)
|
|
254
|
-
)
|
|
255
|
-
// Filter out options that we couldn't match.
|
|
256
|
-
// TODO: We really should display an error instead
|
|
257
|
-
.filter(value => value)
|
|
258
|
-
: this.selectedOption
|
|
259
|
-
},
|
|
260
|
-
|
|
261
|
-
set(option) {
|
|
262
|
-
// Convert value to options object, since vue-multiselect can't map that
|
|
263
|
-
// itself unfortunately. `track-by` is used for :key mapping it seems.
|
|
264
|
-
this.selectedValue = this.multiple
|
|
265
|
-
? (option || []).map(value => this.getValueForOption(value))
|
|
266
|
-
: this.getValueForOption(option)
|
|
267
|
-
this.onChange()
|
|
268
|
-
}
|
|
269
|
-
},
|
|
270
|
-
|
|
271
|
-
activeOptions() {
|
|
272
|
-
return this.searchedOptions || this.options
|
|
273
|
-
},
|
|
274
|
-
|
|
275
|
-
multiple: getSchemaAccessor('multiple', {
|
|
276
|
-
type: Boolean,
|
|
277
|
-
default: false
|
|
278
|
-
}),
|
|
279
|
-
|
|
280
|
-
searchable: getSchemaAccessor('searchable', {
|
|
281
|
-
type: Boolean,
|
|
282
|
-
default: false
|
|
283
|
-
}),
|
|
284
|
-
|
|
285
|
-
taggable: getSchemaAccessor('taggable', {
|
|
286
|
-
type: Boolean,
|
|
287
|
-
default: false
|
|
288
|
-
}),
|
|
289
|
-
|
|
290
|
-
stayOpen: getSchemaAccessor('stayOpen', {
|
|
291
|
-
type: Boolean,
|
|
292
|
-
default: false
|
|
293
|
-
}),
|
|
294
|
-
|
|
295
|
-
placeholder() {
|
|
296
|
-
const { placeholder, searchable, taggable } = this.schema
|
|
297
|
-
return placeholder || (
|
|
298
|
-
searchable && taggable ? `Search or add a ${this.label}`
|
|
299
|
-
: searchable ? `Select or search ${this.label}`
|
|
300
|
-
: undefined
|
|
301
|
-
)
|
|
302
|
-
}
|
|
303
|
-
},
|
|
304
|
-
|
|
305
|
-
mounted() {
|
|
306
|
-
if (this.autofocus) {
|
|
307
|
-
// vue-multiselect doesn't support the autofocus attribute. We need to
|
|
308
|
-
// handle it here.
|
|
309
|
-
this.focus()
|
|
310
|
-
}
|
|
311
|
-
},
|
|
312
|
-
|
|
313
|
-
methods: {
|
|
314
|
-
addTagOption(tag) {
|
|
315
|
-
if (this.taggable) {
|
|
316
|
-
const { optionLabel, optionValue } = this
|
|
317
|
-
const option = optionLabel && optionValue
|
|
318
|
-
? {
|
|
319
|
-
[optionLabel]: tag,
|
|
320
|
-
// TODO: Define a simple schema option to convert the tag value to
|
|
321
|
-
// something else, e.g. `toTag: tag => underscore(tag)`
|
|
322
|
-
[optionValue]: tag
|
|
323
|
-
}
|
|
324
|
-
: tag
|
|
325
|
-
this.options.push(option)
|
|
326
|
-
return option
|
|
327
|
-
}
|
|
328
|
-
},
|
|
329
|
-
|
|
330
|
-
focusElement() {
|
|
331
|
-
this.$refs.element.activate()
|
|
332
|
-
},
|
|
333
|
-
|
|
334
|
-
onOpen() {
|
|
335
|
-
this.populate = true
|
|
336
|
-
},
|
|
337
|
-
|
|
338
|
-
onClose() {
|
|
339
|
-
// Since we don't fire blur events while the multiselect is open (see
|
|
340
|
-
// below), we need to do it here, when it's actually closed.
|
|
341
|
-
if (this.focused) {
|
|
342
|
-
this.onBlur()
|
|
343
|
-
}
|
|
344
|
-
},
|
|
345
|
-
|
|
346
|
-
onBlur() {
|
|
347
|
-
if (!this.$refs.element.isOpen) {
|
|
348
|
-
TypeMixin.methods.onBlur.call(this)
|
|
349
|
-
}
|
|
350
|
-
},
|
|
351
|
-
|
|
352
|
-
onAddTag(tag) {
|
|
353
|
-
const option = this.addTagOption(tag)
|
|
354
|
-
if (option) {
|
|
355
|
-
this.value.push(this.getValueForOption(option))
|
|
356
|
-
}
|
|
357
|
-
},
|
|
358
|
-
|
|
359
|
-
async onSearchChange(query) {
|
|
360
|
-
if (this.searchFilter) {
|
|
361
|
-
if (query) {
|
|
362
|
-
// Set `searchedOptions` to an empty array, before it will be
|
|
363
|
-
// populated asynchronously with the actual results.
|
|
364
|
-
this.searchedOptions = []
|
|
365
|
-
this.searchedOptions = await this.resolveData(
|
|
366
|
-
() => this.searchFilter(new DitoContext(this, { query }))
|
|
367
|
-
)
|
|
368
|
-
} else {
|
|
369
|
-
// Clear `searchedOptions` when the query is cleared.
|
|
370
|
-
this.searchedOptions = null
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
})
|
|
376
|
-
</script>
|
package/src/types/TypeNumber.vue
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
<template lang="pug">
|
|
2
|
-
input-field.dito-number(
|
|
3
|
-
ref="element"
|
|
4
|
-
:id="dataPath"
|
|
5
|
-
type="number"
|
|
6
|
-
v-model="inputValue"
|
|
7
|
-
v-bind="attributes"
|
|
8
|
-
:min="min"
|
|
9
|
-
:max="max"
|
|
10
|
-
:step="stepValue"
|
|
11
|
-
)
|
|
12
|
-
</template>
|
|
13
|
-
|
|
14
|
-
<style lang="sass">
|
|
15
|
-
// Only show spin buttons if the number component defines a step size.
|
|
16
|
-
input[type="number"]:not([step])
|
|
17
|
-
&::-webkit-inner-spin-button,
|
|
18
|
-
&::-webkit-outer-spin-button
|
|
19
|
-
-webkit-appearance: none
|
|
20
|
-
margin: 0
|
|
21
|
-
</style>
|
|
22
|
-
|
|
23
|
-
<script>
|
|
24
|
-
import TypeComponent from '../TypeComponent.js'
|
|
25
|
-
import NumberMixin from '../mixins/NumberMixin.js'
|
|
26
|
-
import { InputField } from '@ditojs/ui/src'
|
|
27
|
-
|
|
28
|
-
export default TypeComponent.register([
|
|
29
|
-
'number', 'integer'
|
|
30
|
-
],
|
|
31
|
-
// @vue/component
|
|
32
|
-
{
|
|
33
|
-
components: { InputField },
|
|
34
|
-
mixins: [NumberMixin],
|
|
35
|
-
nativeField: true,
|
|
36
|
-
textField: true,
|
|
37
|
-
|
|
38
|
-
computed: {
|
|
39
|
-
isInteger() {
|
|
40
|
-
return this.type === 'integer'
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
})
|
|
44
|
-
</script>
|
package/src/types/TypeText.vue
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
<template lang="pug">
|
|
2
|
-
input-field.dito-text(
|
|
3
|
-
ref="element"
|
|
4
|
-
:id="dataPath"
|
|
5
|
-
:type="inputType"
|
|
6
|
-
v-model="inputValue"
|
|
7
|
-
v-bind="attributes"
|
|
8
|
-
)
|
|
9
|
-
</template>
|
|
10
|
-
|
|
11
|
-
<script>
|
|
12
|
-
import TypeComponent from '../TypeComponent.js'
|
|
13
|
-
import { InputField } from '@ditojs/ui/src'
|
|
14
|
-
|
|
15
|
-
const maskedPassword = '****************'
|
|
16
|
-
|
|
17
|
-
export default TypeComponent.register([
|
|
18
|
-
'text', 'email', 'url', 'hostname', 'domain', 'tel', 'password', 'creditcard'
|
|
19
|
-
],
|
|
20
|
-
// @vue/component
|
|
21
|
-
{
|
|
22
|
-
components: { InputField },
|
|
23
|
-
nativeField: true,
|
|
24
|
-
textField: true,
|
|
25
|
-
ignoreMissingValue: schema => schema.type === 'password',
|
|
26
|
-
|
|
27
|
-
computed: {
|
|
28
|
-
inputType() {
|
|
29
|
-
return {
|
|
30
|
-
creditcard: 'text',
|
|
31
|
-
hostname: 'text',
|
|
32
|
-
domain: 'text'
|
|
33
|
-
}[this.type] || this.type
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
inputValue: {
|
|
37
|
-
get() {
|
|
38
|
-
return (
|
|
39
|
-
this.type === 'password' &&
|
|
40
|
-
this.value === undefined &&
|
|
41
|
-
!this.focused
|
|
42
|
-
)
|
|
43
|
-
? maskedPassword
|
|
44
|
-
: this.value
|
|
45
|
-
},
|
|
46
|
-
|
|
47
|
-
set(value) {
|
|
48
|
-
this.value = value
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
|
|
53
|
-
methods: {
|
|
54
|
-
getValidations() {
|
|
55
|
-
const rule = {
|
|
56
|
-
email: 'email',
|
|
57
|
-
url: 'url',
|
|
58
|
-
hostname: 'hostname',
|
|
59
|
-
domain: 'domain',
|
|
60
|
-
password: 'password',
|
|
61
|
-
creditcard: 'creditcard'
|
|
62
|
-
}[this.type]
|
|
63
|
-
return rule ? { [rule]: true } : {}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
})
|
|
67
|
-
</script>
|