@globalbrain/sefirot 0.70.1 → 2.0.0-draft.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.
Files changed (174) hide show
  1. package/CHANGELOG.md +4 -802
  2. package/README.md +1 -1
  3. package/lib/assets/styles/bootstrap.css +1 -2
  4. package/lib/assets/styles/variables.css +14 -47
  5. package/lib/components/SAvatar.vue +9 -18
  6. package/lib/components/SButton.vue +35 -48
  7. package/lib/components/SDialog.vue +16 -34
  8. package/lib/components/SDropdown.vue +36 -55
  9. package/lib/components/SDropdownItem.vue +27 -39
  10. package/lib/components/SDropdownItemText.vue +4 -9
  11. package/lib/components/SDropdownItemUser.vue +4 -12
  12. package/lib/components/SInputBase.vue +33 -45
  13. package/lib/components/SInputCheckbox.vue +19 -35
  14. package/lib/components/SInputDropdown.vue +109 -171
  15. package/lib/components/SInputDropdownItem.vue +26 -32
  16. package/lib/components/SInputDropdownItemText.vue +6 -11
  17. package/lib/components/SInputDropdownItemTextTag.vue +10 -17
  18. package/lib/components/SInputDropdownItemUser.vue +5 -13
  19. package/lib/components/SInputDropdownItemUserTag.vue +9 -16
  20. package/lib/components/SInputFile.vue +38 -53
  21. package/lib/components/SInputHMS.vue +91 -114
  22. package/lib/components/SInputNumber.vue +27 -106
  23. package/lib/components/SInputRadio.vue +23 -33
  24. package/lib/components/SInputRadios.vue +37 -47
  25. package/lib/components/SInputText.vue +59 -633
  26. package/lib/components/SInputTextarea.vue +54 -113
  27. package/lib/components/SInputYMD.vue +94 -105
  28. package/lib/components/SLink.vue +16 -52
  29. package/lib/components/SModal.vue +53 -90
  30. package/lib/components/SPortalModals.vue +37 -53
  31. package/lib/components/SPortalSnackbars.vue +9 -24
  32. package/lib/components/SSheet.vue +10 -23
  33. package/lib/components/SSheetFooter.vue +0 -2
  34. package/lib/components/SSheetFooterAction.vue +9 -14
  35. package/lib/components/SSheetFooterActions.vue +1 -3
  36. package/lib/components/SSheetHeader.vue +9 -24
  37. package/lib/components/SSheetHeaderTitle.vue +1 -3
  38. package/lib/components/SSheetMedium.vue +13 -25
  39. package/lib/components/SSnackbar.vue +18 -28
  40. package/lib/components/icons/SIconSend.vue +5 -0
  41. package/lib/composables/Dialog.ts +9 -17
  42. package/lib/composables/Dropdown.ts +1 -1
  43. package/lib/composables/{Menu.ts → Flyout.ts} +11 -4
  44. package/lib/composables/Form.ts +42 -44
  45. package/lib/composables/Modal.ts +9 -9
  46. package/lib/composables/Snackbar.ts +18 -0
  47. package/lib/composables/Validation.ts +28 -0
  48. package/lib/mixins/Sheet.ts +3 -3
  49. package/lib/store/Sefirot.ts +8 -13
  50. package/lib/store/dialog/index.ts +20 -10
  51. package/lib/store/modal/index.ts +11 -13
  52. package/lib/store/snackbars/index.ts +3 -4
  53. package/lib/support/{Util.ts → Utils.ts} +0 -2
  54. package/lib/types/Utils.ts +0 -7
  55. package/lib/types/vue-shims.d.ts +7 -0
  56. package/lib/validation/rules/checked.ts +6 -10
  57. package/lib/validation/rules/fileExtension.ts +9 -9
  58. package/lib/validation/rules/hms.ts +9 -9
  59. package/lib/validation/rules/index.ts +10 -74
  60. package/lib/validation/rules/maxLength.ts +10 -9
  61. package/lib/validation/rules/minLength.ts +12 -0
  62. package/lib/validation/rules/required.ts +2 -10
  63. package/lib/validation/rules/requiredHms.ts +11 -0
  64. package/lib/validation/rules/requiredIf.ts +3 -11
  65. package/lib/validation/rules/requiredYmd.ts +11 -0
  66. package/lib/validation/rules/ymd.ts +11 -0
  67. package/lib/validation/validators/checked.ts +1 -1
  68. package/lib/validation/validators/fileExtension.ts +1 -1
  69. package/lib/validation/validators/hms.ts +5 -5
  70. package/lib/validation/validators/requiredHms.ts +17 -0
  71. package/lib/validation/validators/requiredYmd.ts +7 -0
  72. package/lib/validation/validators/ymd.ts +41 -0
  73. package/package.json +45 -50
  74. package/lib/components/SAction.vue +0 -37
  75. package/lib/components/SActionAvatar.vue +0 -25
  76. package/lib/components/SActionButton.vue +0 -40
  77. package/lib/components/SActionPill.vue +0 -35
  78. package/lib/components/SActionSwitch.vue +0 -37
  79. package/lib/components/SAlert.vue +0 -145
  80. package/lib/components/SButtonGroup.vue +0 -160
  81. package/lib/components/SCard.vue +0 -111
  82. package/lib/components/SCardFooter.vue +0 -74
  83. package/lib/components/SCardHeader.vue +0 -213
  84. package/lib/components/SGrid.vue +0 -237
  85. package/lib/components/SGridActionLink.vue +0 -53
  86. package/lib/components/SGridActionMulti.vue +0 -139
  87. package/lib/components/SGridActionSingle.vue +0 -64
  88. package/lib/components/SHeader.vue +0 -180
  89. package/lib/components/SInputCheckboxes.vue +0 -83
  90. package/lib/components/SInputDate.vue +0 -192
  91. package/lib/components/SInputDay.vue +0 -87
  92. package/lib/components/SInputMonth.vue +0 -86
  93. package/lib/components/SInputSelect.vue +0 -282
  94. package/lib/components/SInputSwitch.vue +0 -212
  95. package/lib/components/SInputSwitches.vue +0 -108
  96. package/lib/components/SInputTime.vue +0 -255
  97. package/lib/components/SInputYear.vue +0 -60
  98. package/lib/components/SMarkdown.vue +0 -56
  99. package/lib/components/SPlaceholderBlank.vue +0 -113
  100. package/lib/components/SPlaceholderImage.vue +0 -83
  101. package/lib/components/SPortalScreens.vue +0 -62
  102. package/lib/components/SProgressBar.vue +0 -89
  103. package/lib/components/SResponsive.vue +0 -46
  104. package/lib/components/SScreen.vue +0 -81
  105. package/lib/components/SStep.vue +0 -107
  106. package/lib/components/SSteps.vue +0 -75
  107. package/lib/components/STag.vue +0 -67
  108. package/lib/components/STooltip.vue +0 -134
  109. package/lib/components/SWindow.vue +0 -158
  110. package/lib/composables/Action.ts +0 -141
  111. package/lib/composables/Alert.ts +0 -50
  112. package/lib/composables/Card.ts +0 -46
  113. package/lib/composables/FormValidation.ts +0 -150
  114. package/lib/composables/Header.ts +0 -72
  115. package/lib/composables/InputDropdown.ts +0 -6
  116. package/lib/composables/Markdown.ts +0 -138
  117. package/lib/composables/Router.ts +0 -20
  118. package/lib/composables/Step.ts +0 -7
  119. package/lib/composables/Store.ts +0 -9
  120. package/lib/composables/Tag.ts +0 -32
  121. package/lib/composables/Tooltip.ts +0 -91
  122. package/lib/composables/Utils.ts +0 -115
  123. package/lib/composables/markdown/LinkPlugin.ts +0 -45
  124. package/lib/compositions/useForm.ts +0 -17
  125. package/lib/compositions/useResizeObserver.ts +0 -25
  126. package/lib/compositions/useTime.ts +0 -26
  127. package/lib/store/alert/index.ts +0 -32
  128. package/lib/store/screen/index.ts +0 -46
  129. package/lib/types/v-calendar.d.ts +0 -5
  130. package/lib/validation/Validation.ts +0 -151
  131. package/lib/validation/rules/day.ts +0 -11
  132. package/lib/validation/rules/email.ts +0 -11
  133. package/lib/validation/rules/every.ts +0 -38
  134. package/lib/validation/rules/include.ts +0 -11
  135. package/lib/validation/rules/includeSome.ts +0 -11
  136. package/lib/validation/rules/integer.ts +0 -11
  137. package/lib/validation/rules/maxValue.ts +0 -11
  138. package/lib/validation/rules/minValue.ts +0 -11
  139. package/lib/validation/rules/month.ts +0 -11
  140. package/lib/validation/rules/not.ts +0 -10
  141. package/lib/validation/rules/regex.ts +0 -11
  142. package/lib/validation/rules/requiredHMS.ts +0 -11
  143. package/lib/validation/rules/requiredMonthDate.ts +0 -11
  144. package/lib/validation/rules/requiredYearMonth.ts +0 -11
  145. package/lib/validation/rules/requiredYearMonthDate.ts +0 -11
  146. package/lib/validation/rules/rule.ts +0 -5
  147. package/lib/validation/rules/sameAs.ts +0 -11
  148. package/lib/validation/rules/url.ts +0 -11
  149. package/lib/validation/rules/validateIf.ts +0 -27
  150. package/lib/validation/rules/year.ts +0 -11
  151. package/lib/validation/rules/yearMonth.ts +0 -11
  152. package/lib/validation/rules/yearMonthDate.ts +0 -11
  153. package/lib/validation/validators/day.ts +0 -29
  154. package/lib/validation/validators/email.ts +0 -5
  155. package/lib/validation/validators/include.ts +0 -5
  156. package/lib/validation/validators/includeSome.ts +0 -5
  157. package/lib/validation/validators/index.ts +0 -51
  158. package/lib/validation/validators/integer.ts +0 -6
  159. package/lib/validation/validators/maxLength.ts +0 -3
  160. package/lib/validation/validators/maxValue.ts +0 -3
  161. package/lib/validation/validators/minValue.ts +0 -3
  162. package/lib/validation/validators/month.ts +0 -3
  163. package/lib/validation/validators/monthDate.ts +0 -20
  164. package/lib/validation/validators/regex.ts +0 -3
  165. package/lib/validation/validators/required.ts +0 -27
  166. package/lib/validation/validators/requiredHMS.ts +0 -17
  167. package/lib/validation/validators/requiredMonthDate.ts +0 -8
  168. package/lib/validation/validators/requiredYearMonth.ts +0 -8
  169. package/lib/validation/validators/requiredYearMonthDate.ts +0 -9
  170. package/lib/validation/validators/sameAs.ts +0 -5
  171. package/lib/validation/validators/url.ts +0 -5
  172. package/lib/validation/validators/year.ts +0 -3
  173. package/lib/validation/validators/yearMonth.ts +0 -20
  174. package/lib/validation/validators/yearMonthDate.ts +0 -21
@@ -8,61 +8,49 @@
8
8
 
9
9
  <div class="help">
10
10
  <slot name="before-help" />
11
- <p v-if="showError" :key="errorMsg" class="help-error">{{ errorMsg }}</p>
11
+ <p v-if="showError" class="help-error">{{ errorMsg }}</p>
12
12
  <p v-if="help" class="help-text">{{ help }}</p>
13
13
  </div>
14
14
  </div>
15
15
  </template>
16
16
 
17
- <script lang="ts">
18
- import { PropType, defineComponent, computed } from '@vue/composition-api'
19
- import { Validation } from '../validation/Validation'
20
-
21
- export default defineComponent({
22
- props: {
23
- name: { type: String, default: null },
24
- note: { type: String, default: null },
25
- label: { type: String, default: null },
26
- help: { type: String, default: null },
27
- errorMessage: { type: Boolean, default: true },
28
- validation: { type: Object as PropType<Validation>, default: null }
29
- },
30
-
31
- setup(props) {
32
- const hasError = computed(() => {
33
- if (!props.validation) {
34
- return false
35
- }
36
-
37
- return props.validation.$isDirty.value && !props.validation.$isValid.value
38
- })
39
-
40
- const errorMsg = computed(() => {
41
- if (!props.validation) {
42
- return null
43
- }
44
-
45
- const errors = props.validation.$errors.value
46
-
47
- return errors.length > 0 ? errors[0][1] : null
48
- })
49
-
50
- const showError = computed(() => {
51
- return props.errorMessage && hasError.value && errorMsg.value
52
- })
53
-
54
- return {
55
- hasError,
56
- errorMsg,
57
- showError
58
- }
17
+ <script setup lang="ts">
18
+ import { PropType, computed } from 'vue'
19
+ import { Validatable } from '../composables/Validation'
20
+
21
+ const props = defineProps({
22
+ name: { type: String, default: null },
23
+ note: { type: String, default: null },
24
+ label: { type: String, default: null },
25
+ help: { type: String, default: null },
26
+ errorMessage: { type: Boolean, default: true },
27
+ validation: { type: Object as PropType<Validatable>, default: null }
28
+ })
29
+
30
+ const hasError = computed(() => {
31
+ if (!props.validation) {
32
+ return false
59
33
  }
34
+
35
+ return props.validation.$dirty && props.validation.$invalid
36
+ })
37
+
38
+ const errorMsg = computed(() => {
39
+ if (!props.validation) {
40
+ return null
41
+ }
42
+
43
+ const errors = props.validation.$errors
44
+
45
+ return errors.length > 0 ? errors[0].$message : null
46
+ })
47
+
48
+ const showError = computed(() => {
49
+ return props.errorMessage && hasError.value && errorMsg.value
60
50
  })
61
51
  </script>
62
52
 
63
53
  <style lang="postcss" scoped>
64
- @import "@/assets/styles/variables";
65
-
66
54
  .SInputBase.mini {
67
55
  .label {
68
56
  padding-bottom: 6px;
@@ -1,14 +1,14 @@
1
1
  <template>
2
2
  <SInputBase
3
3
  class="SInputCheckbox"
4
- :name="name"
4
+ :class="[size]"
5
5
  :label="label"
6
6
  :note="note"
7
7
  :help="help"
8
8
  :validation="validation"
9
9
  >
10
10
  <div class="container">
11
- <div class="input" :class="{ on: value }" role="button" @click="emitChange">
11
+ <div class="input" :class="{ on: modelValue }" role="button" @click="emitChange">
12
12
  <div class="box">
13
13
  <div class="check">
14
14
  <SIconCheck class="check-icon" />
@@ -21,48 +21,32 @@
21
21
  </SInputBase>
22
22
  </template>
23
23
 
24
- <script lang="ts">
25
- import { PropType, defineComponent } from '@vue/composition-api'
26
- import { Validation } from '../validation/Validation'
24
+ <script setup lang="ts">
25
+ import { PropType } from 'vue'
26
+ import { Validatable } from '../composables/Validation'
27
27
  import SIconCheck from './icons/SIconCheck.vue'
28
28
  import SInputBase from './SInputBase.vue'
29
29
 
30
- export default defineComponent({
31
- components: {
32
- SIconCheck,
33
- SInputBase
34
- },
30
+ type Size = 'mini' | 'small' | 'medium'
35
31
 
36
- model: {
37
- prop: 'value',
38
- event: 'change'
39
- },
40
-
41
- props: {
42
- name: { type: String, default: null },
43
- label: { type: String, default: null },
44
- note: { type: String, default: null },
45
- help: { type: String, default: null },
46
- text: { type: String, required: true },
47
- value: { type: Boolean, required: true },
48
- validation: { type: Object as PropType<Validation>, default: null }
49
- },
32
+ const props = defineProps({
33
+ size: { type: String as PropType<Size>, default: 'small' },
34
+ label: { type: String, default: null },
35
+ note: { type: String, default: null },
36
+ help: { type: String, default: null },
37
+ text: { type: String, required: true },
38
+ modelValue: { type: Boolean, required: true },
39
+ validation: { type: Object as PropType<Validatable>, default: null }
40
+ })
50
41
 
51
- setup(props, { emit }) {
52
- function emitChange() {
53
- emit('change', !props.value)
54
- }
42
+ const emit = defineEmits(['update:modelValue'])
55
43
 
56
- return {
57
- emitChange
58
- }
59
- }
60
- })
44
+ function emitChange() {
45
+ emit('update:modelValue', !props.modelValue)
46
+ }
61
47
  </script>
62
48
 
63
49
  <style lang="postcss" scoped>
64
- @import "@/assets/styles/variables";
65
-
66
50
  .container {
67
51
  display: flex;
68
52
  }
@@ -2,7 +2,6 @@
2
2
  <SInputBase
3
3
  class="SInputDropdown"
4
4
  :class="classes"
5
- :name="name"
6
5
  :label="label"
7
6
  :note="note"
8
7
  :help="help"
@@ -42,10 +41,10 @@
42
41
  </SInputBase>
43
42
  </template>
44
43
 
45
- <script lang="ts">
46
- import { PropType, defineComponent, computed, nextTick } from '@vue/composition-api'
47
- import { isNullish, isArray, isEqual } from '../support/Util'
48
- import { useMenu } from '../composables/Menu'
44
+ <script setup lang="ts">
45
+ import { PropType, computed, nextTick } from 'vue'
46
+ import { isNullish, isArray, isEqual } from '../support/Utils'
47
+ import { useFlyout } from '../composables/Flyout'
49
48
  import { Search, Item, UseDropdownSearchOptions, useDropdown } from '../composables/Dropdown'
50
49
  import SIconChevronUp from './icons/SIconChevronUp.vue'
51
50
  import SIconChevronDown from './icons/SIconChevronDown.vue'
@@ -54,152 +53,119 @@ import SInputBase from './SInputBase.vue'
54
53
  import SInputDropdownItem from './SInputDropdownItem.vue'
55
54
 
56
55
  type Size = 'mini' | 'small' | 'medium'
57
- type Mode = 'outlined' | 'filled'
58
56
  type Value = string | number | boolean | unknown[]
59
57
 
60
- export default defineComponent({
61
- components: {
62
- SIconChevronUp,
63
- SIconChevronDown,
64
- SDropdown,
65
- SInputBase,
66
- SInputDropdownItem
67
- },
68
-
69
- model: {
70
- prop: 'value',
71
- event: 'change'
72
- },
73
-
74
- props: {
75
- size: { type: String as PropType<Size>, default: 'small' },
76
- mode: { type: String as PropType<Mode>, default: 'outlined' },
77
- name: { type: String, default: null },
78
- label: { type: String, default: null },
79
- note: { type: String, default: null },
80
- help: { type: String, default: null },
81
- placeholder: { type: String, default: null },
82
- search: { type: [Boolean, Object] as PropType<boolean | Search>, default: false },
83
- options: { type: Array as PropType<Item[]>, required: true },
84
- nullable: { type: Boolean, default: true },
85
- closeOnClick: { type: Boolean, default: false },
86
- disabled: { type: Boolean, default: false },
87
- validation: { type: Object, default: null },
88
- value: { type: [String, Number, Boolean, Array, Object] as PropType<Value>, default: null }
89
- },
90
-
91
- setup(props, { emit }) {
92
- const { container, isOpen, open, close } = useMenu()
93
-
94
- const classes = computed(() => [
95
- props.size,
96
- props.mode,
97
- { disabled: props.disabled }
98
- ])
99
-
100
- const enabledItems = computed(() => {
101
- return props.options.filter(option => !option.disabled)
102
- })
103
-
104
- const dropdownOptions = useDropdown({
105
- search: createDropdownSearchOptions(),
106
- items: enabledItems,
107
- closeOnClick: props.closeOnClick,
108
- selected: computed(() => props.value),
109
- callback: handleCallback
110
- })
111
-
112
- const selected = computed(() => {
113
- return isArray(props.value)
114
- ? props.options.filter(o => (props.value as unknown[]).includes(o.value))
115
- : props.options.find(o => isEqual(o.value, props.value))
116
- })
117
-
118
- const hasSelected = computed(() => {
119
- return isArray(selected.value)
120
- ? selected.value.length > 0
121
- : !isNullish(selected.value) && selected.value.value !== ''
122
- })
123
-
124
- function createDropdownSearchOptions(): UseDropdownSearchOptions | undefined {
125
- if (props.search === false) {
126
- return undefined
127
- }
128
-
129
- if (props.search === true) {
130
- return {
131
- placeholder: 'Search items',
132
- missing: 'No items found.'
133
- }
134
- }
135
-
136
- return props.search
137
- }
58
+ const props = defineProps({
59
+ size: { type: String as PropType<Size>, default: 'small' },
60
+ label: { type: String, default: null },
61
+ note: { type: String, default: null },
62
+ help: { type: String, default: null },
63
+ placeholder: { type: String, default: null },
64
+ search: { type: [Boolean, Object] as PropType<boolean | Search>, default: false },
65
+ options: { type: Array as PropType<Item[]>, required: true },
66
+ nullable: { type: Boolean, default: true },
67
+ closeOnClick: { type: Boolean, default: false },
68
+ disabled: { type: Boolean, default: false },
69
+ modelValue: { type: [String, Number, Boolean, Array, Object] as PropType<Value>, default: null },
70
+ validation: { type: Object as PropType<any>, default: null }
71
+ })
138
72
 
139
- async function handleOpen(): Promise<void> {
140
- if (!props.disabled) {
141
- open()
73
+ const emit = defineEmits(['update:modelValue'])
142
74
 
143
- await nextTick()
75
+ const { container, isOpen, open, close } = useFlyout()
144
76
 
145
- const el = document.querySelector<HTMLInputElement>('.SInputDropdown .SDropdown .search .SInputText input')
77
+ const classes = computed(() => [
78
+ props.size,
79
+ { disabled: props.disabled }
80
+ ])
146
81
 
147
- el && el.focus()
148
- }
149
- }
82
+ const enabledItems = computed(() => {
83
+ return props.options.filter(option => !option.disabled)
84
+ })
150
85
 
151
- function handleCallback(item: Item): void {
152
- props.validation && props.validation.$touch()
86
+ const dropdownOptions = useDropdown({
87
+ search: createDropdownSearchOptions(),
88
+ items: enabledItems,
89
+ closeOnClick: props.closeOnClick,
90
+ selected: computed(() => props.modelValue),
91
+ callback: handleCallback
92
+ })
153
93
 
154
- isArray(props.value) ? handleArray(item.value) : handlePrimitive(item.value)
155
- }
94
+ const selected = computed(() => {
95
+ return isArray(props.modelValue)
96
+ ? props.options.filter(o => (props.modelValue as unknown[]).includes(o.value))
97
+ : props.options.find(o => isEqual(o.value, props.modelValue))
98
+ })
156
99
 
157
- function handlePrimitive(value: unknown): void {
158
- if (!isEqual(props.value, value)) {
159
- emit('change', value)
100
+ const hasSelected = computed(() => {
101
+ return isArray(selected.value)
102
+ ? selected.value.length > 0
103
+ : !isNullish(selected.value) && selected.value.value !== ''
104
+ })
160
105
 
161
- return
162
- }
106
+ function createDropdownSearchOptions(): UseDropdownSearchOptions | undefined {
107
+ if (props.search === false) {
108
+ return undefined
109
+ }
163
110
 
164
- if (props.nullable) {
165
- emit('change', null)
166
- }
111
+ if (props.search === true) {
112
+ return {
113
+ placeholder: 'Search items',
114
+ missing: 'No items found.'
167
115
  }
116
+ }
168
117
 
169
- function handleArray(value: unknown[]): void {
170
- const difference = getDifference(props.value as unknown[], value)
118
+ return props.search
119
+ }
171
120
 
172
- if (!props.nullable && difference.length === 0) {
173
- return
174
- }
121
+ async function handleOpen(): Promise<void> {
122
+ if (!props.disabled) {
123
+ open()
175
124
 
176
- emit('change', difference)
177
- }
125
+ await nextTick()
178
126
 
179
- function getDifference(source: unknown[], value: unknown[]): unknown[] {
180
- return source
181
- .filter(item => !isEqual(item, value))
182
- .concat(source.includes(value) ? [] : [value])
183
- }
127
+ const el = document.querySelector<HTMLInputElement>('.SInputDropdown .SDropdown .search .SInputText input')
184
128
 
185
- return {
186
- classes,
187
- container,
188
- isOpen,
189
- close,
190
- dropdownOptions,
191
- selected,
192
- hasSelected,
193
- handleOpen,
194
- handleCallback
195
- }
129
+ el && el.focus()
196
130
  }
197
- })
131
+ }
132
+
133
+ function handleCallback(item: Item): void {
134
+ props.validation && props.validation.$touch()
135
+
136
+ isArray(props.modelValue) ? handleArray(item.value) : handlePrimitive(item.value)
137
+ }
138
+
139
+ function handlePrimitive(value: unknown): void {
140
+ if (!isEqual(props.modelValue, value)) {
141
+ emit('update:modelValue', value)
142
+
143
+ return
144
+ }
145
+
146
+ if (props.nullable) {
147
+ emit('update:modelValue', null)
148
+ }
149
+ }
150
+
151
+ function handleArray(value: unknown[]): void {
152
+ const difference = getDifference(props.modelValue as unknown[], value)
153
+
154
+ if (!props.nullable && difference.length === 0) {
155
+ return
156
+ }
157
+
158
+ emit('update:modelValue', difference)
159
+ }
160
+
161
+ function getDifference(source: unknown[], value: unknown[]): unknown[] {
162
+ return source
163
+ .filter(item => !isEqual(item, value))
164
+ .concat(source.includes(value) ? [] : [value])
165
+ }
198
166
  </script>
199
167
 
200
168
  <style lang="postcss" scoped>
201
- @import "@/assets/styles/variables";
202
-
203
169
  .SInputDropdown.mini {
204
170
  .SInputDropdown-box {
205
171
  min-height: 32px;
@@ -251,53 +217,15 @@ export default defineComponent({
251
217
  }
252
218
  }
253
219
 
254
- .SInputDropdown.outlined {
255
- .SInputDropdown-box {
256
- border-color: var(--input-outlined-border);
257
-
258
- &:hover {
259
- border-color: var(--input-focus-border);
260
- }
261
-
262
- &:focus:not(:focus-visible) {
263
- border-color: var(--input-focus-border);
264
- outline: 0;
265
- }
266
- }
267
-
268
- &.disabled .SInputDropdown-box {
269
- background-color: var(--input-outlined-bg-disabled);
270
- cursor: not-allowed;
271
-
272
- &:hover { border-color: var(--input-outlined-border); }
273
- &:focus:not(:focus-visible) { border-color: var(--input-outlined-border); }
274
- }
275
- }
276
-
277
- .SInputDropdown.filled {
220
+ .SInputDropdown.disabled {
278
221
  .SInputDropdown-box {
279
- background-color: var(--input-filled-bg);
280
-
281
- &:hover {
282
- border-color: var(--input-focus-border);
283
- }
284
-
285
- &:focus:not(:focus-visible) {
286
- border-color: var(--input-focus-border);
287
- outline: 0;
288
- }
289
- }
290
-
291
- &.disabled .SInputDropdown-box {
292
- background-color: var(--input-outlined-bg-disabled);
222
+ background-color: var(--input-disabled-bg);
293
223
  cursor: not-allowed;
294
224
 
295
225
  &:hover { border-color: var(--input-outlined-border); }
296
226
  &:focus:not(:focus-visible) { border-color: var(--input-outlined-border); }
297
227
  }
298
- }
299
228
 
300
- .SInputDropdown.disabled {
301
229
  .SInputDropdown-box-icon {
302
230
  cursor: not-allowed;
303
231
  }
@@ -315,12 +243,22 @@ export default defineComponent({
315
243
 
316
244
  .SInputDropdown-box {
317
245
  position: relative;
318
- border: 1px solid transparent;
246
+ border: 1px solid var(--input-border);
319
247
  border-radius: 4px;
320
248
  width: 100%;
321
249
  color: var(--input-text);
322
250
  cursor: pointer;
323
251
  transition: border-color .25s, background-color .25s;
252
+
253
+ &:hover {
254
+ border-color: var(--input-focus-border);
255
+ }
256
+
257
+ &:focus {
258
+ border-color: var(--input-focus-border);
259
+ outline: 0;
260
+ }
261
+
324
262
  }
325
263
 
326
264
  .SInputDropdown-box-placeholder {
@@ -3,7 +3,7 @@
3
3
  <div v-for="(i, index) in arrayItem" :key="index" class="item">
4
4
  <component
5
5
  :is="component(i)"
6
- :mute="i.value === null"
6
+ :mute="shouldMute(i)"
7
7
  :item="i"
8
8
  :disabled="disabled"
9
9
  @remove="$emit('remove', i)"
@@ -12,51 +12,45 @@
12
12
  </div>
13
13
  </template>
14
14
 
15
- <script lang="ts">
16
- import { PropType, defineComponent, computed } from '@vue/composition-api'
17
- import { isArray } from '../support/Util'
18
- import { Item } from '../composables/Dropdown'
15
+ <script setup lang="ts">
16
+ import { PropType, computed } from 'vue'
17
+ import { isArray } from '../support/Utils'
19
18
  import SInputDropdownItemText from './SInputDropdownItemText.vue'
20
19
  import SInputDropdownItemTextTag from './SInputDropdownItemTextTag.vue'
21
20
  import SInputDropdownItemUser from './SInputDropdownItemUser.vue'
22
21
  import SInputDropdownItemUserTag from './SInputDropdownItemUserTag.vue'
23
22
 
24
- export default defineComponent({
25
- props: {
26
- item: { type: [Object, Array] as PropType<Item | Item[]>, required: true },
27
- disabled: { type: Boolean, default: false }
28
- },
29
-
30
- setup(props) {
31
- const isItemArray = computed(() => isArray(props.item))
23
+ const props = defineProps({
24
+ item: { type: [Object, Array] as PropType<any>, default: null },
25
+ disabled: { type: Boolean, default: false }
26
+ })
32
27
 
33
- const arrayItem = computed(() => {
34
- return isArray(props.item) ? props.item : [props.item]
35
- })
28
+ defineEmits(['remove'])
36
29
 
37
- function component(item: Item) {
38
- if (item.type === 'text') {
39
- return isItemArray.value ? SInputDropdownItemTextTag : SInputDropdownItemText
40
- }
30
+ const isItemArray = computed(() => isArray(props.item))
41
31
 
42
- if (item.type === 'user') {
43
- return isItemArray.value ? SInputDropdownItemUserTag : SInputDropdownItemUser
44
- }
32
+ const arrayItem = computed(() => {
33
+ return isArray(props.item) ? props.item : [props.item]
34
+ })
45
35
 
46
- throw new Error('Invalid item type.')
47
- }
36
+ function component(item: any): any {
37
+ if (item.type === 'text') {
38
+ return isItemArray.value ? SInputDropdownItemTextTag : SInputDropdownItemText
39
+ }
48
40
 
49
- return {
50
- arrayItem,
51
- component
52
- }
41
+ if (item.type === 'user') {
42
+ return isItemArray.value ? SInputDropdownItemUserTag : SInputDropdownItemUser
53
43
  }
54
- })
44
+
45
+ throw new Error('Invalid item type.')
46
+ }
47
+
48
+ function shouldMute(item: any) {
49
+ return item.value === null
50
+ }
55
51
  </script>
56
52
 
57
53
  <style lang="postcss" scoped>
58
- @import "@/assets/styles/variables";
59
-
60
54
  .SInputDropdownItem {
61
55
  display: flex;
62
56
  flex-wrap: wrap;
@@ -4,22 +4,17 @@
4
4
  </div>
5
5
  </template>
6
6
 
7
- <script lang="ts">
8
- import { PropType, defineComponent } from '@vue/composition-api'
9
- import { Item } from '../composables/Dropdown'
7
+ <script setup lang="ts">
8
+ import { PropType } from 'vue'
10
9
 
11
- export default defineComponent({
12
- props: {
13
- mute: { type: Boolean, default: false },
14
- item: { type: Object as PropType<Item>, required: true },
15
- disabled: { type: Boolean, default: false }
16
- }
10
+ const props = defineProps({
11
+ mute: { type: Boolean, default: false },
12
+ item: { type: Object as PropType<any>, required: true },
13
+ disabled: { type: Boolean, default: false }
17
14
  })
18
15
  </script>
19
16
 
20
17
  <style lang="postcss" scoped>
21
- @import "@/assets/styles/variables";
22
-
23
18
  .SInputDropdownItemText.mute .text {
24
19
  color: var(--input-placeholder);
25
20
  }