@globalbrain/sefirot 2.2.1 → 2.4.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/lib/components/SButton.vue +0 -1
- package/lib/components/SButtonGroup.vue +17 -17
- package/lib/components/SDropdownSectionFilter.vue +5 -5
- package/lib/components/SIcon.vue +2 -2
- package/lib/components/SInputBase.vue +4 -5
- package/lib/components/SInputCheckbox.vue +23 -23
- package/lib/components/SInputCheckboxes.vue +23 -23
- package/lib/components/SInputDate.vue +55 -132
- package/lib/components/SInputDropdown.vue +3 -3
- package/lib/components/SInputFile.vue +1 -1
- package/lib/components/SInputSelect.vue +48 -48
- package/lib/components/SInputSwitch.vue +68 -142
- package/lib/components/SInputSwitches.vue +51 -58
- package/lib/components/SInputText.vue +1 -1
- package/lib/components/SInputTextarea.vue +24 -24
- package/lib/components/SLink.vue +14 -14
- package/lib/components/SMarkdown.vue +3 -3
- package/lib/components/SMount.vue +1 -1
- package/lib/components/SSheetFooterAction.vue +1 -1
- package/lib/components/SSpinner.vue +28 -12
- package/lib/components/SStep.vue +15 -15
- package/lib/components/SSteps.vue +16 -16
- package/lib/components/STable.vue +2 -2
- package/lib/components/STableCellAvatar.vue +1 -1
- package/lib/components/STableCellAvatars.vue +1 -1
- package/lib/components/STableCellDay.vue +1 -1
- package/lib/components/STableColumn.vue +4 -4
- package/lib/components/STooltip.vue +17 -17
- package/lib/composables/Data.ts +108 -0
- package/lib/composables/Form.ts +12 -12
- package/lib/composables/Grid.ts +3 -3
- package/lib/composables/Markdown.ts +2 -2
- package/lib/composables/Tooltip.ts +2 -1
- package/lib/composables/Validation.ts +2 -2
- package/lib/support/Day.ts +1 -1
- package/lib/support/Utils.ts +4 -0
- package/lib/validation/rules/email.ts +1 -1
- package/lib/validation/rules/hms.ts +1 -1
- package/lib/validation/rules/maxLength.ts +1 -1
- package/lib/validation/rules/maxValue.ts +1 -1
- package/lib/validation/rules/minLength.ts +1 -1
- package/lib/validation/rules/minValue.ts +1 -1
- package/lib/validation/rules/required.ts +1 -1
- package/lib/validation/rules/requiredHms.ts +1 -1
- package/lib/validation/rules/requiredIf.ts +1 -1
- package/lib/validation/rules/requiredYmd.ts +1 -1
- package/lib/validation/rules/url.ts +1 -1
- package/lib/validation/rules/ymd.ts +1 -1
- package/lib/validation/validators/requiredYmd.ts +1 -1
- package/package.json +12 -15
|
@@ -1,21 +1,5 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="SButtonGroup" :class="classes">
|
|
3
|
-
<button
|
|
4
|
-
v-for="item in items"
|
|
5
|
-
:key="item.value"
|
|
6
|
-
class="button"
|
|
7
|
-
:class="getButtonClasses(item)"
|
|
8
|
-
@click="handleClick(item.value)"
|
|
9
|
-
>
|
|
10
|
-
<span class="content">
|
|
11
|
-
{{ item.label }}
|
|
12
|
-
</span>
|
|
13
|
-
</button>
|
|
14
|
-
</div>
|
|
15
|
-
</template>
|
|
16
|
-
|
|
17
1
|
<script setup lang="ts">
|
|
18
|
-
import {
|
|
2
|
+
import { PropType, computed } from 'vue'
|
|
19
3
|
|
|
20
4
|
export interface ButtonGroupItem {
|
|
21
5
|
label: string
|
|
@@ -48,6 +32,22 @@ function handleClick(value: string) {
|
|
|
48
32
|
}
|
|
49
33
|
</script>
|
|
50
34
|
|
|
35
|
+
<template>
|
|
36
|
+
<div class="SButtonGroup" :class="classes">
|
|
37
|
+
<button
|
|
38
|
+
v-for="item in items"
|
|
39
|
+
:key="item.value"
|
|
40
|
+
class="button"
|
|
41
|
+
:class="getButtonClasses(item)"
|
|
42
|
+
@click="handleClick(item.value)"
|
|
43
|
+
>
|
|
44
|
+
<span class="content">
|
|
45
|
+
{{ item.label }}
|
|
46
|
+
</span>
|
|
47
|
+
</button>
|
|
48
|
+
</div>
|
|
49
|
+
</template>
|
|
50
|
+
|
|
51
51
|
<style lang="postcss" scoped>
|
|
52
52
|
.SButtonGroup {
|
|
53
53
|
display: flex;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import IconCheck from '@iconify-icons/ph/check'
|
|
3
|
-
import
|
|
3
|
+
import { MaybeRef } from '@vueuse/core'
|
|
4
4
|
import Fuse from 'fuse.js'
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { computed, onMounted, ref, unref } from 'vue'
|
|
6
|
+
import { DropdownSectionFilterOption, DropdownSectionFilterSelectedValue } from '../composables/Dropdown'
|
|
7
7
|
import { isArray } from '../support/Utils'
|
|
8
8
|
import SDropdownSectionFilterItem from './SDropdownSectionFilterItem.vue'
|
|
9
9
|
import SIcon from './SIcon.vue'
|
|
@@ -25,7 +25,7 @@ const fuse = computed(() => {
|
|
|
25
25
|
const filteredOptions = computed(() => {
|
|
26
26
|
return !props.search || !query.value
|
|
27
27
|
? unref(props.options)
|
|
28
|
-
: fuse.value.search(query.value).map(
|
|
28
|
+
: fuse.value.search(query.value).map(r => r.item)
|
|
29
29
|
})
|
|
30
30
|
|
|
31
31
|
onMounted(() => {
|
|
@@ -36,7 +36,7 @@ function isActive(value: string | number | boolean) {
|
|
|
36
36
|
const selected = unref(props.selected)
|
|
37
37
|
|
|
38
38
|
return isArray(selected)
|
|
39
|
-
? selected.
|
|
39
|
+
? selected.includes(value)
|
|
40
40
|
: selected === value
|
|
41
41
|
}
|
|
42
42
|
|
package/lib/components/SIcon.vue
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { Icon, IconifyIcon } from '@iconify/vue/dist/offline'
|
|
3
|
-
import
|
|
3
|
+
import { DefineComponent } from 'vue'
|
|
4
4
|
|
|
5
5
|
defineProps<{
|
|
6
6
|
icon: IconifyIcon | DefineComponent
|
|
@@ -8,6 +8,6 @@ defineProps<{
|
|
|
8
8
|
</script>
|
|
9
9
|
|
|
10
10
|
<template>
|
|
11
|
-
<Icon v-if="typeof icon
|
|
11
|
+
<Icon v-if="typeof icon.body === 'string'" :icon="icon as IconifyIcon" />
|
|
12
12
|
<component v-else :is="icon" />
|
|
13
13
|
</template>
|
|
@@ -3,10 +3,10 @@ import { computed, unref } from 'vue'
|
|
|
3
3
|
import { Validatable } from '../composables/Validation'
|
|
4
4
|
|
|
5
5
|
const props = defineProps<{
|
|
6
|
-
name?: string
|
|
7
|
-
note?: string
|
|
8
|
-
label?: string
|
|
9
|
-
help?: string
|
|
6
|
+
name?: string
|
|
7
|
+
note?: string
|
|
8
|
+
label?: string
|
|
9
|
+
help?: string
|
|
10
10
|
hideError?: boolean
|
|
11
11
|
validation?: Validatable
|
|
12
12
|
}>()
|
|
@@ -98,7 +98,6 @@ const showError = computed(() => {
|
|
|
98
98
|
|
|
99
99
|
.help {
|
|
100
100
|
position: relative;
|
|
101
|
-
word-break: break-all;
|
|
102
101
|
}
|
|
103
102
|
|
|
104
103
|
.help-error {
|
|
@@ -1,26 +1,3 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<SInputBase
|
|
3
|
-
class="SInputCheckbox"
|
|
4
|
-
:class="[size]"
|
|
5
|
-
:label="label"
|
|
6
|
-
:note="note"
|
|
7
|
-
:help="help"
|
|
8
|
-
:validation="validation"
|
|
9
|
-
>
|
|
10
|
-
<div class="container">
|
|
11
|
-
<div class="input" :class="{ on: modelValue }" role="button" @click="emitChange">
|
|
12
|
-
<div class="box">
|
|
13
|
-
<div class="check">
|
|
14
|
-
<SIcon :icon="IconCheck" class="check-icon" />
|
|
15
|
-
</div>
|
|
16
|
-
</div>
|
|
17
|
-
|
|
18
|
-
<p class="text">{{ text }}</p>
|
|
19
|
-
</div>
|
|
20
|
-
</div>
|
|
21
|
-
</SInputBase>
|
|
22
|
-
</template>
|
|
23
|
-
|
|
24
1
|
<script setup lang="ts">
|
|
25
2
|
import IconCheck from '@iconify-icons/ph/check'
|
|
26
3
|
import { PropType } from 'vue'
|
|
@@ -47,6 +24,29 @@ function emitChange() {
|
|
|
47
24
|
}
|
|
48
25
|
</script>
|
|
49
26
|
|
|
27
|
+
<template>
|
|
28
|
+
<SInputBase
|
|
29
|
+
class="SInputCheckbox"
|
|
30
|
+
:class="[size]"
|
|
31
|
+
:label="label"
|
|
32
|
+
:note="note"
|
|
33
|
+
:help="help"
|
|
34
|
+
:validation="validation"
|
|
35
|
+
>
|
|
36
|
+
<div class="container">
|
|
37
|
+
<div class="input" :class="{ on: modelValue }" role="button" @click="emitChange">
|
|
38
|
+
<div class="box">
|
|
39
|
+
<div class="check">
|
|
40
|
+
<SIcon :icon="IconCheck" class="check-icon" />
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<p class="text">{{ text }}</p>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</SInputBase>
|
|
48
|
+
</template>
|
|
49
|
+
|
|
50
50
|
<style lang="postcss" scoped>
|
|
51
51
|
.container {
|
|
52
52
|
display: flex;
|
|
@@ -1,26 +1,3 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<SInputBase
|
|
3
|
-
class="SInputCheckboxes"
|
|
4
|
-
:class="[size]"
|
|
5
|
-
:name="name"
|
|
6
|
-
:label="label"
|
|
7
|
-
:note="note"
|
|
8
|
-
:help="help"
|
|
9
|
-
>
|
|
10
|
-
<div class="container">
|
|
11
|
-
<div class="row">
|
|
12
|
-
<div v-for="option in options" :key="option.value" class="col">
|
|
13
|
-
<SInputCheckbox
|
|
14
|
-
:text="option.label"
|
|
15
|
-
:model-value="isChecked(option.value)"
|
|
16
|
-
@update:model-value="handleChange(option.value)"
|
|
17
|
-
/>
|
|
18
|
-
</div>
|
|
19
|
-
</div>
|
|
20
|
-
</div>
|
|
21
|
-
</SInputBase>
|
|
22
|
-
</template>
|
|
23
|
-
|
|
24
1
|
<script setup lang="ts">
|
|
25
2
|
import { PropType } from 'vue'
|
|
26
3
|
import SInputBase from './SInputBase.vue'
|
|
@@ -58,6 +35,29 @@ function handleChange(value: unknown): void {
|
|
|
58
35
|
}
|
|
59
36
|
</script>
|
|
60
37
|
|
|
38
|
+
<template>
|
|
39
|
+
<SInputBase
|
|
40
|
+
class="SInputCheckboxes"
|
|
41
|
+
:class="[size]"
|
|
42
|
+
:name="name"
|
|
43
|
+
:label="label"
|
|
44
|
+
:note="note"
|
|
45
|
+
:help="help"
|
|
46
|
+
>
|
|
47
|
+
<div class="container">
|
|
48
|
+
<div class="row">
|
|
49
|
+
<div v-for="option in options" :key="option.value" class="col">
|
|
50
|
+
<SInputCheckbox
|
|
51
|
+
:text="option.label"
|
|
52
|
+
:model-value="isChecked(option.value)"
|
|
53
|
+
@update:model-value="handleChange(option.value)"
|
|
54
|
+
/>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</SInputBase>
|
|
59
|
+
</template>
|
|
60
|
+
|
|
61
61
|
<style lang="postcss" scoped>
|
|
62
62
|
.container {
|
|
63
63
|
display: flex;
|
|
@@ -1,30 +1,67 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { DatePicker } from 'v-calendar'
|
|
3
|
+
import { computed } from 'vue'
|
|
4
|
+
import { Validatable } from '../composables/Validation'
|
|
5
|
+
import { Day, day } from '../support/Day'
|
|
6
|
+
import SInputBase from './SInputBase.vue'
|
|
7
|
+
|
|
8
|
+
const props = defineProps<{
|
|
9
|
+
name?: string
|
|
10
|
+
label?: string
|
|
11
|
+
note?: string
|
|
12
|
+
help?: string
|
|
13
|
+
hideError?: boolean
|
|
14
|
+
modelValue: Day | null
|
|
15
|
+
validation?: Validatable
|
|
16
|
+
}>()
|
|
17
|
+
|
|
18
|
+
const emit = defineEmits<{
|
|
19
|
+
(e: 'update:modelValue', value: Day | null): void
|
|
20
|
+
}>()
|
|
21
|
+
|
|
22
|
+
const value = computed(() => {
|
|
23
|
+
return props.modelValue
|
|
24
|
+
? props.modelValue.format('YYYY-MM-DD')
|
|
25
|
+
: null
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
function emitInput(date?: string) {
|
|
29
|
+
emit('update:modelValue', date ? day(date) : null)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function emitBlur(e: FocusEvent) {
|
|
33
|
+
setTimeout(() => {
|
|
34
|
+
props.validation && props.validation.$touch()
|
|
35
|
+
}, 100)
|
|
36
|
+
}
|
|
37
|
+
</script>
|
|
38
|
+
|
|
1
39
|
<template>
|
|
2
40
|
<SInputBase
|
|
3
|
-
class="SInputDate"
|
|
4
|
-
:class="classes"
|
|
41
|
+
class="SInputDate small"
|
|
5
42
|
:name="name"
|
|
6
43
|
:label="label"
|
|
7
44
|
:note="note"
|
|
8
45
|
:help="help"
|
|
46
|
+
:hide-error="hideError"
|
|
9
47
|
:validation="validation"
|
|
10
48
|
>
|
|
11
49
|
<div class="container">
|
|
12
50
|
<DatePicker
|
|
13
51
|
v-slot="{ inputValue, inputEvents }"
|
|
14
|
-
:value="modelValue"
|
|
15
52
|
color="blue"
|
|
16
53
|
is-dark
|
|
17
54
|
:masks="{ input: 'YYYY-MM-DD' }"
|
|
18
55
|
:model-config="{ type: 'string', mask: 'YYYY-MM-DD' }"
|
|
19
56
|
:popover="{ placement: 'bottom', visibility: 'click' }"
|
|
20
|
-
|
|
57
|
+
:model-value="value"
|
|
58
|
+
@update:model-value="emitInput"
|
|
21
59
|
>
|
|
22
60
|
<input
|
|
23
61
|
:id="name"
|
|
24
62
|
class="input"
|
|
25
63
|
type="text"
|
|
26
|
-
|
|
27
|
-
:disabled="disabled"
|
|
64
|
+
placeholder="YYYY-MM-DD"
|
|
28
65
|
:value="inputValue"
|
|
29
66
|
autocomplete="off"
|
|
30
67
|
v-on="inputEvents"
|
|
@@ -35,78 +72,7 @@
|
|
|
35
72
|
</SInputBase>
|
|
36
73
|
</template>
|
|
37
74
|
|
|
38
|
-
<script setup lang="ts">
|
|
39
|
-
import { DatePicker } from 'v-calendar'
|
|
40
|
-
import { PropType, computed } from 'vue'
|
|
41
|
-
import { Validation } from '../composables/Validation'
|
|
42
|
-
import SInputBase from './SInputBase.vue'
|
|
43
|
-
|
|
44
|
-
type Size = 'medium' | 'mini'
|
|
45
|
-
type Mode = 'filled' | 'outlined'
|
|
46
|
-
|
|
47
|
-
const props = defineProps({
|
|
48
|
-
size: { type: String as PropType<Size>, default: 'medium' },
|
|
49
|
-
mode: { type: String as PropType<Mode>, default: 'filled' },
|
|
50
|
-
name: { type: String, default: null },
|
|
51
|
-
label: { type: String, default: null },
|
|
52
|
-
note: { type: String, default: null },
|
|
53
|
-
help: { type: String, default: null },
|
|
54
|
-
placeholder: { type: String, default: 'YYYY-MM-DD' },
|
|
55
|
-
disabled: { type: Boolean, default: false },
|
|
56
|
-
modelValue: { type: String, default: null },
|
|
57
|
-
validation: { type: Object as PropType<Validation>, default: null }
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
const emit = defineEmits(['update:modelValue', 'blur'])
|
|
61
|
-
|
|
62
|
-
const classes = computed(() => [
|
|
63
|
-
props.size,
|
|
64
|
-
props.mode,
|
|
65
|
-
{
|
|
66
|
-
disabled: props.disabled
|
|
67
|
-
}
|
|
68
|
-
])
|
|
69
|
-
|
|
70
|
-
function emitInput(date: string | null) {
|
|
71
|
-
emit('update:modelValue', date)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function emitBlur(e: FocusEvent) {
|
|
75
|
-
setTimeout(() => {
|
|
76
|
-
props.validation && props.validation.$touch()
|
|
77
|
-
|
|
78
|
-
emit('blur', (e.target as HTMLInputElement).value)
|
|
79
|
-
}, 100)
|
|
80
|
-
}
|
|
81
|
-
</script>
|
|
82
|
-
|
|
83
75
|
<style lang="postcss" scoped>
|
|
84
|
-
.SInputDate.mini {
|
|
85
|
-
.input {
|
|
86
|
-
padding: 3px 12px;
|
|
87
|
-
width: 100%;
|
|
88
|
-
line-height: 24px;
|
|
89
|
-
font-size: 14px;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
.container {
|
|
93
|
-
height: 32px;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
.SInputDate.medium {
|
|
98
|
-
.input {
|
|
99
|
-
padding: 11px 16px;
|
|
100
|
-
width: 100%;
|
|
101
|
-
line-height: 24px;
|
|
102
|
-
font-size: 16px;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
.container {
|
|
106
|
-
height: 48px;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
76
|
.SInputDate.has-error {
|
|
111
77
|
.input {
|
|
112
78
|
border-color: var(--c-danger);
|
|
@@ -117,66 +83,23 @@ function emitBlur(e: FocusEvent) {
|
|
|
117
83
|
}
|
|
118
84
|
}
|
|
119
85
|
|
|
120
|
-
.SInputDate.filled {
|
|
121
|
-
.input {
|
|
122
|
-
background-color: var(--input-filled-bg);
|
|
123
|
-
|
|
124
|
-
&:hover {
|
|
125
|
-
border-color: var(--input-focus-border);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
&:focus {
|
|
129
|
-
border-color: var(--input-focus-border);
|
|
130
|
-
background-color: var(--input-filled-bg-focus);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
&.disabled .input {
|
|
135
|
-
background-color: var(--input-filled-bg-disabled);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
.SInputDate.outlined {
|
|
140
|
-
.input {
|
|
141
|
-
border-color: var(--input-outlined-border);
|
|
142
|
-
background-color: transparent;
|
|
143
|
-
|
|
144
|
-
&:hover {
|
|
145
|
-
border-color: var(--input-focus-border);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
&:focus {
|
|
149
|
-
border-color: var(--input-focus-border);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
&.disabled .input:hover {
|
|
154
|
-
border-color: var(--input-outlined-border);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
&.disabled .input {
|
|
158
|
-
background-color: var(--input-outlined-bg-disabled);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
.SInputDate.disabled {
|
|
163
|
-
.input:hover {
|
|
164
|
-
cursor: not-allowed;
|
|
165
|
-
border-color: transparent;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
|
|
170
86
|
.input {
|
|
171
87
|
display: block;
|
|
172
|
-
border: 1px solid
|
|
173
|
-
border-radius:
|
|
88
|
+
border: 1px solid var(--c-divider);
|
|
89
|
+
border-radius: 6px;
|
|
90
|
+
padding: 5px 12px;
|
|
174
91
|
width: 100%;
|
|
175
|
-
|
|
176
|
-
|
|
92
|
+
max-width: 144px;
|
|
93
|
+
height: 40px;
|
|
94
|
+
letter-spacing: 0;
|
|
95
|
+
line-height: 24px;
|
|
96
|
+
font-size: 16px;
|
|
97
|
+
background-color: var(--c-bg);
|
|
98
|
+
transition: border-color 0.25s, background-color 0.25s;
|
|
177
99
|
|
|
178
100
|
&::placeholder {
|
|
179
|
-
|
|
101
|
+
font-weight: 500;
|
|
102
|
+
color: var(--c-text-3);
|
|
180
103
|
}
|
|
181
104
|
}
|
|
182
105
|
</style>
|
|
@@ -3,7 +3,7 @@ import IconCaretDown from '@iconify-icons/ph/caret-down'
|
|
|
3
3
|
import IconCaretUp from '@iconify-icons/ph/caret-up'
|
|
4
4
|
import xor from 'lodash-es/xor'
|
|
5
5
|
import { computed } from 'vue'
|
|
6
|
-
import
|
|
6
|
+
import { DropdownSectionFilter } from '../composables/Dropdown'
|
|
7
7
|
import { useFlyout } from '../composables/Flyout'
|
|
8
8
|
import { Validatable } from '../composables/Validation'
|
|
9
9
|
import { isArray } from '../support/Utils'
|
|
@@ -71,10 +71,10 @@ const dropdownOptions = computed<DropdownSectionFilter[]>(() => [{
|
|
|
71
71
|
|
|
72
72
|
const selected = computed(() => {
|
|
73
73
|
if (isArray(props.modelValue)) {
|
|
74
|
-
return props.options.filter(
|
|
74
|
+
return props.options.filter(o => (props.modelValue as ArrayValue).includes(o.value))
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
const item = props.options.find(
|
|
77
|
+
const item = props.options.find(o => o.value === props.modelValue)
|
|
78
78
|
|
|
79
79
|
return item ? [item] : []
|
|
80
80
|
})
|
|
@@ -1,54 +1,7 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<SInputBase
|
|
3
|
-
class="SInputSelect"
|
|
4
|
-
:class="classes"
|
|
5
|
-
:label="label"
|
|
6
|
-
:note="note"
|
|
7
|
-
:help="help"
|
|
8
|
-
:error-message="errorMessage ?? true"
|
|
9
|
-
:validation="validation"
|
|
10
|
-
>
|
|
11
|
-
<div class="box" :class="{ focus: isFocused }">
|
|
12
|
-
<select
|
|
13
|
-
class="select"
|
|
14
|
-
:class="{ 'is-not-selected': isNotSelected }"
|
|
15
|
-
:disabled="disabled"
|
|
16
|
-
@focus="focus"
|
|
17
|
-
@blur="blur"
|
|
18
|
-
@change="emitChange"
|
|
19
|
-
>
|
|
20
|
-
<option
|
|
21
|
-
v-if="placeholder || nullable"
|
|
22
|
-
:value="JSON.stringify({ value: null })"
|
|
23
|
-
:selected="isNotSelected"
|
|
24
|
-
:disabled="!nullable"
|
|
25
|
-
>
|
|
26
|
-
{{ placeholder || 'Please select' }}
|
|
27
|
-
</option>
|
|
28
|
-
|
|
29
|
-
<option
|
|
30
|
-
v-for="(option, index) in options"
|
|
31
|
-
:key="index"
|
|
32
|
-
:style="{ display: option.disabled ? 'none' : undefined }"
|
|
33
|
-
:value="JSON.stringify(option)"
|
|
34
|
-
:selected="isSelectedOption(option)"
|
|
35
|
-
>
|
|
36
|
-
{{ option.label }}
|
|
37
|
-
</option>
|
|
38
|
-
</select>
|
|
39
|
-
|
|
40
|
-
<div class="icon" role="button">
|
|
41
|
-
<SIcon :icon="IconCaretUp" class="icon-svg up" />
|
|
42
|
-
<SIcon :icon="IconCaretDown" class="icon-svg down" />
|
|
43
|
-
</div>
|
|
44
|
-
</div>
|
|
45
|
-
</SInputBase>
|
|
46
|
-
</template>
|
|
47
|
-
|
|
48
1
|
<script setup lang="ts">
|
|
49
2
|
import IconCaretDown from '@iconify-icons/ph/caret-down'
|
|
50
3
|
import IconCaretUp from '@iconify-icons/ph/caret-up'
|
|
51
|
-
import { PropType,
|
|
4
|
+
import { PropType, computed, ref } from 'vue'
|
|
52
5
|
import { Validatable } from '../composables/Validation'
|
|
53
6
|
import SIcon from './SIcon.vue'
|
|
54
7
|
import SInputBase from './SInputBase.vue'
|
|
@@ -109,6 +62,53 @@ function emitChange(e: any): void {
|
|
|
109
62
|
}
|
|
110
63
|
</script>
|
|
111
64
|
|
|
65
|
+
<template>
|
|
66
|
+
<SInputBase
|
|
67
|
+
class="SInputSelect"
|
|
68
|
+
:class="classes"
|
|
69
|
+
:label="label"
|
|
70
|
+
:note="note"
|
|
71
|
+
:help="help"
|
|
72
|
+
:error-message="errorMessage ?? true"
|
|
73
|
+
:validation="validation"
|
|
74
|
+
>
|
|
75
|
+
<div class="box" :class="{ focus: isFocused }">
|
|
76
|
+
<select
|
|
77
|
+
class="select"
|
|
78
|
+
:class="{ 'is-not-selected': isNotSelected }"
|
|
79
|
+
:disabled="disabled"
|
|
80
|
+
@focus="focus"
|
|
81
|
+
@blur="blur"
|
|
82
|
+
@change="emitChange"
|
|
83
|
+
>
|
|
84
|
+
<Option
|
|
85
|
+
v-if="placeholder || nullable"
|
|
86
|
+
:value="JSON.stringify({ value: null })"
|
|
87
|
+
:selected="isNotSelected"
|
|
88
|
+
:disabled="!nullable"
|
|
89
|
+
>
|
|
90
|
+
{{ placeholder || 'Please select' }}
|
|
91
|
+
</Option>
|
|
92
|
+
|
|
93
|
+
<Option
|
|
94
|
+
v-for="(option, index) in options"
|
|
95
|
+
:key="index"
|
|
96
|
+
:style="{ display: option.disabled ? 'none' : undefined }"
|
|
97
|
+
:value="JSON.stringify(option)"
|
|
98
|
+
:selected="isSelectedOption(option)"
|
|
99
|
+
>
|
|
100
|
+
{{ option.label }}
|
|
101
|
+
</Option>
|
|
102
|
+
</select>
|
|
103
|
+
|
|
104
|
+
<div class="icon" role="button">
|
|
105
|
+
<SIcon :icon="IconCaretUp" class="icon-svg up" />
|
|
106
|
+
<SIcon :icon="IconCaretDown" class="icon-svg down" />
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
</SInputBase>
|
|
110
|
+
</template>
|
|
111
|
+
|
|
112
112
|
<style scoped lang="postcss">
|
|
113
113
|
.SInputSelect.mini {
|
|
114
114
|
.box {
|