@globalbrain/sefirot 2.0.0-draft.8 → 2.0.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.
Files changed (97) hide show
  1. package/README.md +6 -6
  2. package/lib/components/SAvatar.vue +17 -17
  3. package/lib/components/SButton.vue +512 -267
  4. package/lib/components/SButtonGroup.vue +149 -0
  5. package/lib/components/SDropdown.vue +26 -150
  6. package/lib/components/SDropdownSection.vue +48 -0
  7. package/lib/components/SDropdownSectionFilter.vue +189 -0
  8. package/lib/components/SDropdownSectionFilterItem.vue +21 -0
  9. package/lib/components/SDropdownSectionFilterItemAvatar.vue +31 -0
  10. package/lib/components/SDropdownSectionFilterItemText.vue +20 -0
  11. package/lib/components/SDropdownSectionMenu.vue +39 -0
  12. package/lib/components/SIcon.vue +13 -0
  13. package/lib/components/SInputBase.vue +31 -31
  14. package/lib/components/SInputCheckbox.vue +1 -1
  15. package/lib/components/SInputCheckboxes.vue +74 -0
  16. package/lib/components/SInputDate.vue +182 -0
  17. package/lib/components/SInputDropdown.vue +158 -157
  18. package/lib/components/SInputDropdownItem.vue +46 -48
  19. package/lib/components/{SInputDropdownItemUserTag.vue → SInputDropdownItemAvatar.vue} +43 -44
  20. package/lib/components/SInputDropdownItemText.vue +79 -16
  21. package/lib/components/SInputFile.vue +55 -60
  22. package/lib/components/SInputHMS.vue +120 -110
  23. package/lib/components/SInputNumber.vue +38 -9
  24. package/lib/components/SInputRadio.vue +39 -36
  25. package/lib/components/SInputRadios.vue +40 -53
  26. package/lib/components/SInputSelect.vue +3 -3
  27. package/lib/components/SInputSwitch.vue +193 -0
  28. package/lib/components/SInputSwitches.vue +88 -0
  29. package/lib/components/SInputText.vue +206 -62
  30. package/lib/components/SInputTextarea.vue +46 -32
  31. package/lib/components/SInputYMD.vue +123 -126
  32. package/lib/components/SMarkdown.vue +52 -0
  33. package/lib/components/SModal.vue +25 -63
  34. package/lib/components/SMount.vue +19 -0
  35. package/lib/components/SSheet.vue +49 -55
  36. package/lib/components/SSheetFooter.vue +1 -1
  37. package/lib/components/SSheetFooterAction.vue +24 -17
  38. package/lib/components/SSheetFooterActions.vue +1 -4
  39. package/lib/components/SSheetForm.vue +15 -0
  40. package/lib/components/SSheetMedium.vue +8 -10
  41. package/lib/components/SSheetTitle.vue +7 -14
  42. package/lib/components/SSnackbar.vue +55 -45
  43. package/lib/components/{SPortalSnackbars.vue → SSnackbars.vue} +17 -20
  44. package/lib/components/SStep.vue +106 -0
  45. package/lib/components/SSteps.vue +59 -0
  46. package/lib/components/STable.vue +241 -0
  47. package/lib/components/STableCell.vue +82 -0
  48. package/lib/components/STableCellAvatar.vue +69 -0
  49. package/lib/components/STableCellAvatars.vue +93 -0
  50. package/lib/components/STableCellDay.vue +40 -0
  51. package/lib/components/STableCellPill.vue +84 -0
  52. package/lib/components/STableCellText.vue +102 -0
  53. package/lib/components/STableColumn.vue +255 -0
  54. package/lib/components/STableFooter.vue +115 -0
  55. package/lib/components/STableHeader.vue +74 -0
  56. package/lib/components/STableItem.vue +38 -0
  57. package/lib/components/STooltip.vue +112 -0
  58. package/lib/composables/Dropdown.ts +40 -99
  59. package/lib/composables/Form.ts +21 -18
  60. package/lib/composables/Grid.ts +117 -0
  61. package/lib/composables/Markdown.ts +138 -0
  62. package/lib/composables/Step.ts +7 -0
  63. package/lib/composables/Table.ts +103 -0
  64. package/lib/composables/Tooltip.ts +91 -0
  65. package/lib/composables/Validation.ts +5 -9
  66. package/lib/composables/markdown/LinkPlugin.ts +45 -0
  67. package/lib/mixins/Sheet.ts +5 -3
  68. package/lib/stores/Snackbars.ts +48 -0
  69. package/lib/{assets/styles → styles}/base.css +0 -0
  70. package/lib/{assets/styles → styles}/bootstrap.css +1 -0
  71. package/lib/{assets/styles → styles}/variables.css +55 -48
  72. package/lib/support/Day.ts +8 -0
  73. package/lib/support/Num.ts +3 -0
  74. package/lib/support/Time.ts +5 -2
  75. package/lib/support/Utils.ts +4 -3
  76. package/lib/types/shims.d.ts +3 -0
  77. package/lib/validation/validators/requiredYmd.ts +1 -1
  78. package/lib/validation/validators/ymd.ts +4 -4
  79. package/package.json +57 -37
  80. package/CHANGELOG.md +0 -47
  81. package/lib/.DS_Store +0 -0
  82. package/lib/components/.DS_Store +0 -0
  83. package/lib/components/SDialog.vue +0 -140
  84. package/lib/components/SDropdownItem.vue +0 -78
  85. package/lib/components/SDropdownItemText.vue +0 -22
  86. package/lib/components/SDropdownItemUser.vue +0 -40
  87. package/lib/components/SInputDropdownItemTextTag.vue +0 -94
  88. package/lib/components/SInputDropdownItemUser.vue +0 -41
  89. package/lib/components/SPortalModals.vue +0 -74
  90. package/lib/components/icons/.DS_Store +0 -0
  91. package/lib/composables/Dialog.ts +0 -38
  92. package/lib/composables/Modal.ts +0 -34
  93. package/lib/composables/Snackbar.ts +0 -18
  94. package/lib/store/Sefirot.ts +0 -17
  95. package/lib/store/dialog/index.ts +0 -42
  96. package/lib/store/modal/index.ts +0 -61
  97. package/lib/store/snackbars/index.ts +0 -70
@@ -1,146 +1,100 @@
1
- <template>
2
- <SInputBase
3
- class="SInputDropdown"
4
- :class="classes"
5
- :label="label"
6
- :note="note"
7
- :help="help"
8
- :validation="validation"
9
- >
10
- <div ref="container" class="SInputDropdown-container">
11
- <div
12
- class="SInputDropdown-box"
13
- role="button"
14
- tabindex="0"
15
- @click="handleOpen"
16
- @keydown.down.prevent
17
- @keyup.enter="handleOpen"
18
- @keyup.down="handleOpen"
19
- >
20
- <div class="SInputDropdown-box-content">
21
- <SInputDropdownItem
22
- v-if="hasSelected"
23
- :item="selected"
24
- :disabled="disabled"
25
- @remove="handleCallback"
26
- />
27
-
28
- <span v-else class="SInputDropdown-box-placeholder">{{ placeholder }}</span>
29
- </div>
30
-
31
- <div class="SInputDropdown-box-icon">
32
- <SIconChevronUp class="SInputDropdown-box-icon-svg up" />
33
- <SIconChevronDown class="SInputDropdown-box-icon-svg down" />
34
- </div>
35
- </div>
36
-
37
- <div v-if="isOpen" class="SInputDropdown-dropdown">
38
- <SDropdown :options="dropdownOptions" @close="close" />
39
- </div>
40
- </div>
41
- </SInputBase>
42
- </template>
43
-
44
1
  <script setup lang="ts">
45
- import { PropType, computed, nextTick } from 'vue'
46
- import { isNullish, isArray, isEqual } from '../support/Utils'
2
+ import xor from 'lodash-es/xor'
3
+ import { computed } from 'vue'
4
+ import type { DropdownSectionFilter } from '../composables/Dropdown'
47
5
  import { useFlyout } from '../composables/Flyout'
48
- import { Search, Item, UseDropdownSearchOptions, useDropdown } from '../composables/Dropdown'
49
- import SIconChevronUp from './icons/SIconChevronUp.vue'
50
- import SIconChevronDown from './icons/SIconChevronDown.vue'
6
+ import { Validatable } from '../composables/Validation'
7
+ import { isArray } from '../support/Utils'
51
8
  import SDropdown from './SDropdown.vue'
52
9
  import SInputBase from './SInputBase.vue'
53
10
  import SInputDropdownItem from './SInputDropdownItem.vue'
11
+ import SIconChevronDown from './icons/SIconChevronDown.vue'
12
+ import SIconChevronUp from './icons/SIconChevronUp.vue'
54
13
 
55
- type Size = 'mini' | 'small' | 'medium'
56
- type Value = string | number | boolean | unknown[]
57
-
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
- })
14
+ export type Size = 'mini' | 'small' | 'medium'
15
+ export type PrimitiveValue = string | number | boolean | null
16
+ export type ArrayValue = (string | number | boolean)[]
17
+ export type OptionValue = string | number | boolean
18
+
19
+ export type Option = OptionText | OptionAvatar
72
20
 
73
- const emit = defineEmits(['update:modelValue'])
21
+ export interface OptionBase {
22
+ type?: 'text' | 'avatar'
23
+ value: OptionValue
24
+ }
25
+
26
+ export interface OptionText extends OptionBase {
27
+ type?: 'text'
28
+ label: string
29
+ }
74
30
 
75
- const { container, isOpen, open, close } = useFlyout()
31
+ export interface OptionAvatar extends OptionBase {
32
+ type: 'avatar'
33
+ label: string
34
+ image?: string | null
35
+ }
36
+
37
+ const props = defineProps<{
38
+ size?: Size
39
+ label?: string
40
+ note?: string
41
+ help?: string
42
+ placeholder?: string
43
+ noSearch?: boolean
44
+ nullable?: boolean
45
+ closeOnClick?: boolean
46
+ options: Option[]
47
+ disabled?: boolean
48
+ modelValue: PrimitiveValue | ArrayValue
49
+ validation?: Validatable
50
+ }>()
51
+
52
+ const emit = defineEmits<{
53
+ (e: 'update:modelValue', value: PrimitiveValue | ArrayValue): void
54
+ }>()
55
+
56
+ const { container, isOpen, open } = useFlyout()
76
57
 
77
58
  const classes = computed(() => [
78
- props.size,
59
+ props.size ?? 'small',
79
60
  { disabled: props.disabled }
80
61
  ])
81
62
 
82
- const enabledItems = computed(() => {
83
- return props.options.filter(option => !option.disabled)
84
- })
85
-
86
- const dropdownOptions = useDropdown({
87
- search: createDropdownSearchOptions(),
88
- items: enabledItems,
89
- closeOnClick: props.closeOnClick,
90
- selected: computed(() => props.modelValue),
91
- callback: handleCallback
92
- })
63
+ const dropdownOptions = computed<DropdownSectionFilter[]>(() => [{
64
+ type: 'filter',
65
+ search: props.noSearch === undefined ? true : !props.noSearch,
66
+ selected: props.modelValue,
67
+ options: props.options,
68
+ onClick: handleSelect
69
+ }])
93
70
 
94
71
  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
- })
99
-
100
- const hasSelected = computed(() => {
101
- return isArray(selected.value)
102
- ? selected.value.length > 0
103
- : !isNullish(selected.value) && selected.value.value !== ''
104
- })
105
-
106
- function createDropdownSearchOptions(): UseDropdownSearchOptions | undefined {
107
- if (props.search === false) {
108
- return undefined
109
- }
110
-
111
- if (props.search === true) {
112
- return {
113
- placeholder: 'Search items',
114
- missing: 'No items found.'
115
- }
72
+ if (isArray(props.modelValue)) {
73
+ return props.options.filter((o) => (props.modelValue as ArrayValue).includes(o.value))
116
74
  }
117
75
 
118
- return props.search
119
- }
76
+ const item = props.options.find((o) => o.value === props.modelValue)
120
77
 
121
- async function handleOpen(): Promise<void> {
122
- if (!props.disabled) {
123
- open()
124
-
125
- await nextTick()
78
+ return item ? [item] : []
79
+ })
126
80
 
127
- const el = document.querySelector<HTMLInputElement>('.SInputDropdown .SDropdown .search .SInputText input')
81
+ const hasSelected = computed(() => {
82
+ return selected.value.length > 0
83
+ })
128
84
 
129
- el && el.focus()
130
- }
85
+ async function handleOpen() {
86
+ !props.disabled && open()
131
87
  }
132
88
 
133
- function handleCallback(item: Item): void {
134
- props.validation && props.validation.$touch()
89
+ function handleSelect(value: OptionValue) {
90
+ props.validation?.$touch()
135
91
 
136
- isArray(props.modelValue) ? handleArray(item.value) : handlePrimitive(item.value)
92
+ isArray(props.modelValue) ? handleArray(value) : handlePrimitive(value)
137
93
  }
138
94
 
139
- function handlePrimitive(value: unknown): void {
140
- if (!isEqual(props.modelValue, value)) {
141
- emit('update:modelValue', value)
142
-
143
- return
95
+ function handlePrimitive(value: OptionValue) {
96
+ if (value !== props.modelValue) {
97
+ return emit('update:modelValue', value)
144
98
  }
145
99
 
146
100
  if (props.nullable) {
@@ -148,8 +102,8 @@ function handlePrimitive(value: unknown): void {
148
102
  }
149
103
  }
150
104
 
151
- function handleArray(value: unknown[]): void {
152
- const difference = getDifference(props.modelValue as unknown[], value)
105
+ function handleArray(value: OptionValue) {
106
+ const difference = xor(props.modelValue as ArrayValue, [value])
153
107
 
154
108
  if (!props.nullable && difference.length === 0) {
155
109
  return
@@ -157,76 +111,113 @@ function handleArray(value: unknown[]): void {
157
111
 
158
112
  emit('update:modelValue', difference)
159
113
  }
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
- }
166
114
  </script>
167
115
 
116
+ <template>
117
+ <SInputBase
118
+ class="SInputDropdown"
119
+ :class="classes"
120
+ :label="label"
121
+ :note="note"
122
+ :help="help"
123
+ :validation="validation"
124
+ >
125
+ <div class="container" ref="container">
126
+ <div
127
+ class="box"
128
+ role="button"
129
+ tabindex="0"
130
+ @click="handleOpen"
131
+ @keydown.down.prevent
132
+ @keyup.enter="handleOpen"
133
+ @keyup.down="handleOpen"
134
+ >
135
+ <div class="box-content">
136
+ <SInputDropdownItem
137
+ v-if="hasSelected"
138
+ :items="selected"
139
+ :disabled="disabled ?? false"
140
+ @remove="handleSelect"
141
+ />
142
+
143
+ <div v-else class="box-placeholder">{{ placeholder }}</div>
144
+ </div>
145
+
146
+ <div class="box-icon">
147
+ <SIconChevronUp class="box-icon-svg up" />
148
+ <SIconChevronDown class="box-icon-svg down" />
149
+ </div>
150
+ </div>
151
+
152
+ <div v-if="isOpen" class="dropdown">
153
+ <SDropdown :sections="dropdownOptions" />
154
+ </div>
155
+ </div>
156
+ </SInputBase>
157
+ </template>
158
+
168
159
  <style lang="postcss" scoped>
169
160
  .SInputDropdown.mini {
170
- .SInputDropdown-box {
161
+ .box {
171
162
  min-height: 32px;
172
163
  }
173
164
 
174
- .SInputDropdown-box-content {
165
+ .box-content {
175
166
  padding: 3px 30px 3px 12px;
176
167
  line-height: 24px;
177
168
  font-size: 14px;
178
169
  }
179
170
 
180
- .SInputDropdown-box-icon {
171
+ .box-icon {
181
172
  top: 3px;
182
173
  right: 8px;
183
174
  }
184
175
  }
185
176
 
186
177
  .SInputDropdown.small {
187
- .SInputDropdown-box {
178
+ .box {
188
179
  min-height: 40px;
189
180
  }
190
181
 
191
- .SInputDropdown-box-content {
192
- padding: 7px 30px 7px 12px;
182
+ .box-content {
183
+ padding: 5px 30px 5px 8px;
193
184
  line-height: 24px;
194
- font-size: 14px;
185
+ font-size: 16px;
195
186
  }
196
187
 
197
- .SInputDropdown-box-icon {
188
+ .box-icon {
198
189
  top: 7px;
199
190
  right: 8px;
200
191
  }
201
192
  }
202
193
 
203
194
  .SInputDropdown.medium {
204
- .SInputDropdown-box {
195
+ .box {
205
196
  height: 48px;
206
197
  }
207
198
 
208
- .SInputDropdown-box-content {
199
+ .box-content {
209
200
  padding: 11px 44px 11px 16px;
210
201
  line-height: 24px;
211
202
  font-size: 16px;
212
203
  }
213
204
 
214
- .SInputDropdown-box-icon {
205
+ .box-icon {
215
206
  top: 11px;
216
207
  right: 12px;
217
208
  }
218
209
  }
219
210
 
220
211
  .SInputDropdown.disabled {
221
- .SInputDropdown-box {
222
- background-color: var(--input-disabled-bg);
212
+ .box {
213
+ background-color: var(--c-bg);
223
214
  cursor: not-allowed;
224
215
 
225
- &:hover { border-color: var(--input-outlined-border); }
226
- &:focus:not(:focus-visible) { border-color: var(--input-outlined-border); }
216
+ &:hover { border-color: var(--c-divider); }
217
+ &:focus:not(:focus-visible) { border-color: var(--c-divider); }
227
218
  }
228
219
 
229
- .SInputDropdown-box-icon {
220
+ .box-icon {
230
221
  cursor: not-allowed;
231
222
  }
232
223
  }
@@ -237,53 +228,63 @@ function getDifference(source: unknown[], value: unknown[]): unknown[] {
237
228
  }
238
229
  }
239
230
 
240
- .SInputDropdown-container {
231
+ .container {
241
232
  position: relative;
242
233
  }
243
234
 
244
- .SInputDropdown-box {
235
+ .box {
245
236
  position: relative;
246
- border: 1px solid var(--input-border);
247
- border-radius: 4px;
237
+ border: 1px solid var(--c-divider);
238
+ border-radius: 6px;
248
239
  width: 100%;
249
240
  color: var(--input-text);
241
+ background-color: var(--c-bg);
250
242
  cursor: pointer;
251
243
  transition: border-color .25s, background-color .25s;
252
244
 
253
245
  &:hover {
254
- border-color: var(--input-focus-border);
246
+ border-color: var(--c-black);
255
247
  }
256
248
 
257
- &:focus {
258
- border-color: var(--input-focus-border);
259
- outline: 0;
249
+ &:focus,
250
+ &:hover.focus {
251
+ border-color: var(--c-info);
260
252
  }
261
253
 
254
+ .dark &:hover {
255
+ border-color: var(--c-gray);
256
+ }
257
+
258
+ .dark &:focus,
259
+ .dark &:hover:focus {
260
+ border-color: var(--c-info);
261
+ }
262
262
  }
263
263
 
264
- .SInputDropdown-box-placeholder {
264
+ .box-placeholder {
265
+ padding: 2px 4px;
265
266
  font-weight: 500;
266
- color: var(--input-placeholder);
267
+ color: var(--c-text-3);
267
268
  }
268
269
 
269
- .SInputDropdown-box-icon {
270
+ .box-icon {
270
271
  position: absolute;
271
272
  z-index: 10;
272
273
  cursor: pointer;
273
274
  }
274
275
 
275
- .SInputDropdown-box-icon-svg {
276
+ .box-icon-svg {
276
277
  display: block;
277
278
  width: 14px;
278
279
  height: 14px;
279
- fill: var(--input-placeholder);
280
+ fill: var(--c-text-2);
280
281
  }
281
282
 
282
- .SInputDropdown-box-icon-svg.up {
283
+ .box-icon-svg.up {
283
284
  margin-bottom: -4px;
284
285
  }
285
286
 
286
- .SInputDropdown-dropdown {
287
+ .dropdown {
287
288
  position: absolute;
288
289
  top: calc(100% + 8px);
289
290
  left: 0;
@@ -1,63 +1,61 @@
1
- <template>
2
- <div class="SInputDropdownItem">
3
- <div v-for="(i, index) in arrayItem" :key="index" class="item">
4
- <component
5
- :is="component(i)"
6
- :mute="shouldMute(i)"
7
- :item="i"
8
- :disabled="disabled"
9
- @remove="$emit('remove', i)"
10
- />
11
- </div>
12
- </div>
13
- </template>
14
-
15
1
  <script setup lang="ts">
16
- import { PropType, computed } from 'vue'
17
- import { isArray } from '../support/Utils'
2
+ import SInputDropdownItemAvatar from './SInputDropdownItemAvatar.vue'
18
3
  import SInputDropdownItemText from './SInputDropdownItemText.vue'
19
- import SInputDropdownItemTextTag from './SInputDropdownItemTextTag.vue'
20
- import SInputDropdownItemUser from './SInputDropdownItemUser.vue'
21
- import SInputDropdownItemUserTag from './SInputDropdownItemUserTag.vue'
22
-
23
- const props = defineProps({
24
- item: { type: [Object, Array] as PropType<any>, default: null },
25
- disabled: { type: Boolean, default: false }
26
- })
27
-
28
- defineEmits(['remove'])
29
-
30
- const isItemArray = computed(() => isArray(props.item))
31
4
 
32
- const arrayItem = computed(() => {
33
- return isArray(props.item) ? props.item : [props.item]
34
- })
5
+ export type Item = ItemText | ItemAvatar
35
6
 
36
- function component(item: any): any {
37
- if (item.type === 'text') {
38
- return isItemArray.value ? SInputDropdownItemTextTag : SInputDropdownItemText
39
- }
40
-
41
- if (item.type === 'user') {
42
- return isItemArray.value ? SInputDropdownItemUserTag : SInputDropdownItemUser
43
- }
7
+ export interface ItemBase {
8
+ type?: 'text' | 'avatar'
9
+ value: string | number | boolean
10
+ }
44
11
 
45
- throw new Error('Invalid item type.')
12
+ export interface ItemText extends ItemBase {
13
+ type?: 'text'
14
+ label: string
46
15
  }
47
16
 
48
- function shouldMute(item: any) {
49
- return item.value === null
17
+ export interface ItemAvatar extends ItemBase {
18
+ type: 'avatar'
19
+ label: string
20
+ image?: string | null
50
21
  }
22
+
23
+ defineProps<{
24
+ items: Item[]
25
+ disabled: boolean
26
+ }>()
27
+
28
+ defineEmits<{
29
+ (e: 'remove', value: string | number | boolean): void
30
+ }>()
51
31
  </script>
52
32
 
53
- <style lang="postcss" scoped>
33
+ <template>
34
+ <div class="SInputDropdownItem">
35
+ <div v-for="(item, index) in items" :key="index" class="item">
36
+ <SInputDropdownItemText
37
+ v-if="item.type === 'text' || item.type === undefined"
38
+ :label="item.label"
39
+ :value="item.value"
40
+ :disabled="disabled"
41
+ @remove="(v) => $emit('remove', v)"
42
+ />
43
+ <SInputDropdownItemAvatar
44
+ v-if="item.type === 'avatar'"
45
+ :label="item.label"
46
+ :image="item.image"
47
+ :value="item.value"
48
+ :disabled="disabled"
49
+ @remove="(v) => $emit('remove', v)"
50
+ />
51
+ </div>
52
+ </div>
53
+ </template>
54
+
55
+ <style scoped lang="postcss">
54
56
  .SInputDropdownItem {
55
57
  display: flex;
56
58
  flex-wrap: wrap;
57
- margin: -2px -8px;
58
- }
59
-
60
- .item {
61
- padding: 2px;
59
+ gap: 4px;
62
60
  }
63
61
  </style>
@@ -1,14 +1,29 @@
1
+ <script setup lang="ts">
2
+ import SAvatar from './SAvatar.vue'
3
+ import SIconX from './icons/SIconX.vue'
4
+
5
+ defineProps<{
6
+ label: string
7
+ image?: string | null
8
+ value: string | number | boolean
9
+ disabled: boolean
10
+ }>()
11
+
12
+ defineEmits<{
13
+ (e: 'remove', value: string | number | boolean): void
14
+ }>()
15
+ </script>
16
+
1
17
  <template>
2
- <div class="SInputDropdownItemUserTag" :class="{ disabled }">
18
+ <div class="SInputDropdownItemAvatar" :class="{ disabled }">
3
19
  <div class="user">
4
20
  <div class="avatar">
5
- <SAvatar size="nano" :avatar="item.avatar" :name="item.name" />
21
+ <SAvatar size="nano" :avatar="image" :name="label" />
6
22
  </div>
7
-
8
- <p class="name">{{ item.name }}</p>
23
+ <p class="name">{{ label }}</p>
9
24
  </div>
10
25
 
11
- <div v-if="!disabled" class="remove" role="button" @click="$emit('remove')">
26
+ <div v-if="!disabled" class="remove" role="button" @click="$emit('remove', value)">
12
27
  <div class="remove-box">
13
28
  <SIconX class="remove-icon" />
14
29
  </div>
@@ -16,49 +31,34 @@
16
31
  </div>
17
32
  </template>
18
33
 
19
- <script setup lang="ts">
20
- import { PropType } from 'vue'
21
- import { UserItem } from '../composables/Dropdown'
22
- import SIconX from './icons/SIconX.vue'
23
- import SAvatar from './SAvatar.vue'
24
-
25
- defineProps({
26
- item: { type: Object as PropType<UserItem>, required: true },
27
- disabled: { type: Boolean, default: false }
28
- })
29
-
30
- defineEmits(['remove'])
31
- </script>
32
-
33
34
  <style lang="postcss" scoped>
34
- .SInputDropdownItemUserTag {
35
+ .SInputDropdownItemAvatar {
35
36
  display: flex;
36
- border-radius: 12px;
37
- padding: 0 0 0 0;
38
- background-color: var(--c-white-mute);
37
+ border: 1px solid var(--c-divider-light);
38
+ border-radius: 14px;
39
+ padding: 0;
40
+ background-color: var(--c-bg-mute);
39
41
  }
40
42
 
41
- .SInputDropdownItemUserTag.disabled {
43
+ .SInputDropdownItemUserAvatar.disabled {
42
44
  padding: 0 10px 0 0;
43
45
  background-color: var(--c-gray-light-4);
44
46
  }
45
47
 
46
- .dark .SInputDropdownItemUserTag {
47
- background-color: var(--c-black-mute);
48
- }
49
-
50
48
  .user {
51
49
  display: flex;
52
50
  }
53
51
 
54
52
  .avatar {
55
- padding: 2px 0 0 2px;
53
+ padding: 3px 0 0 3px;
56
54
  }
57
55
 
58
56
  .name {
59
- padding-left: 6px;
57
+ margin: 0 0 0 8px;
58
+ line-height: 26px;
60
59
  font-size: 12px;
61
60
  font-weight: 500;
61
+ white-space: nowrap;
62
62
  }
63
63
 
64
64
  .remove {
@@ -66,19 +66,8 @@ defineEmits(['remove'])
66
66
  justify-content: center;
67
67
  align-items: center;
68
68
  margin-left: 2px;
69
- width: 24px;
70
- height: 24px;
71
-
72
- &:hover .remove-box {
73
- color: var(--c-text-1);
74
- background-color: var(--c-gray-light-4)
75
- }
76
- }
77
-
78
- .dark .remove {
79
- &:hover .remove-box {
80
- background-color: var(--c-gray-dark-2)
81
- }
69
+ width: 26px;
70
+ height: 26px;
82
71
  }
83
72
 
84
73
  .remove-box {
@@ -89,7 +78,17 @@ defineEmits(['remove'])
89
78
  width: 20px;
90
79
  height: 20px;
91
80
  color: var(--c-text-2);
92
- transition: color .25s, background-color .25s;
81
+ transition: color 0.25s, background-color 0.25s;
82
+
83
+ .remove:hover & {
84
+ color: var(--c-text-1);
85
+ background-color: var(--c-gray-light-3)
86
+ }
87
+
88
+ .dark .remove:hover & {
89
+ color: var(--c-text-1);
90
+ background-color: var(--c-gray-dark-3)
91
+ }
93
92
  }
94
93
 
95
94
  .remove-icon {