@globalbrain/sefirot 4.31.0 → 4.32.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 (131) hide show
  1. package/client.d.ts +5 -0
  2. package/config/nuxt.d.ts +1 -0
  3. package/config/nuxt.js +1 -1
  4. package/config/vite.js +3 -2
  5. package/lib/components/SActionList.vue +2 -2
  6. package/lib/components/SActionMenu.vue +4 -4
  7. package/lib/components/SAvatar.vue +1 -1
  8. package/lib/components/SAvatarStack.vue +12 -12
  9. package/lib/components/SButton.vue +5 -7
  10. package/lib/components/SCard.vue +2 -2
  11. package/lib/components/SChartBar.vue +37 -12
  12. package/lib/components/SChartPie.vue +13 -7
  13. package/lib/components/SControlActionBarCollapse.vue +2 -4
  14. package/lib/components/SControlInputSearch.vue +7 -2
  15. package/lib/components/SDataListItem.vue +1 -3
  16. package/lib/components/SDescAvatar.vue +1 -1
  17. package/lib/components/SDescDay.vue +2 -2
  18. package/lib/components/SDescFile.vue +2 -4
  19. package/lib/components/SDescItem.vue +2 -1
  20. package/lib/components/SDescLabel.vue +1 -1
  21. package/lib/components/SDescLink.vue +2 -7
  22. package/lib/components/SDescPill.vue +2 -4
  23. package/lib/components/SDescText.vue +2 -2
  24. package/lib/components/SDropdown.vue +1 -1
  25. package/lib/components/SDropdownSectionFilter.vue +11 -11
  26. package/lib/components/SFragment.vue +1 -1
  27. package/lib/components/SInputAddon.vue +13 -11
  28. package/lib/components/SInputBase.vue +11 -11
  29. package/lib/components/SInputCheckbox.vue +6 -3
  30. package/lib/components/SInputCheckboxes.vue +7 -3
  31. package/lib/components/SInputDate.vue +3 -5
  32. package/lib/components/SInputDropdown.vue +26 -28
  33. package/lib/components/SInputDropdownItem.vue +21 -11
  34. package/lib/components/SInputFile.vue +9 -6
  35. package/lib/components/SInputFileUpload.vue +9 -11
  36. package/lib/components/SInputFileUploadItem.vue +8 -4
  37. package/lib/components/SInputHMS.vue +3 -1
  38. package/lib/components/SInputImage.vue +4 -2
  39. package/lib/components/SInputNumber.vue +9 -10
  40. package/lib/components/SInputRadio.vue +3 -2
  41. package/lib/components/SInputRadios.vue +6 -5
  42. package/lib/components/SInputSegments.vue +5 -7
  43. package/lib/components/SInputSegmentsOption.vue +1 -2
  44. package/lib/components/SInputSelect.vue +6 -4
  45. package/lib/components/SInputSwitch.vue +4 -1
  46. package/lib/components/SInputSwitches.vue +5 -3
  47. package/lib/components/SInputText.vue +16 -16
  48. package/lib/components/SInputTextarea.vue +7 -3
  49. package/lib/components/SInputYMD.vue +3 -1
  50. package/lib/components/SLink.vue +2 -2
  51. package/lib/components/SLocalNav.vue +1 -1
  52. package/lib/components/SLocalNavActions.vue +1 -1
  53. package/lib/components/SLocalNavMenu.vue +2 -2
  54. package/lib/components/SLoginPagePasswordDialog.vue +2 -2
  55. package/lib/components/SM.vue +1 -1
  56. package/lib/components/SMFade.vue +1 -1
  57. package/lib/components/SMarkdown.vue +3 -2
  58. package/lib/components/SModal.vue +2 -2
  59. package/lib/components/SSnackbar.vue +2 -2
  60. package/lib/components/SSteps.vue +6 -6
  61. package/lib/components/STable.vue +70 -27
  62. package/lib/components/STableCell.vue +14 -17
  63. package/lib/components/STableCellAvatars.vue +1 -1
  64. package/lib/components/STableCellDay.vue +12 -5
  65. package/lib/components/STableCellNumber.vue +2 -3
  66. package/lib/components/STableCellPath.vue +2 -2
  67. package/lib/components/STableCellText.vue +2 -3
  68. package/lib/components/STableColumn.vue +38 -16
  69. package/lib/components/STableFooter.vue +10 -2
  70. package/lib/components/STableHeader.vue +0 -1
  71. package/lib/components/STableHeaderMenu.vue +4 -4
  72. package/lib/components/STableHeaderMenuItem.vue +1 -1
  73. package/lib/components/STooltip.vue +3 -3
  74. package/lib/composables/Dropdown.ts +10 -1
  75. package/lib/composables/Error.ts +37 -37
  76. package/lib/composables/Grid.ts +1 -4
  77. package/lib/composables/Image.ts +2 -3
  78. package/lib/composables/Lang.ts +1 -1
  79. package/lib/composables/Markdown.ts +1 -1
  80. package/lib/composables/Table.ts +0 -2
  81. package/lib/composables/Theme.ts +1 -1
  82. package/lib/composables/Utils.ts +11 -4
  83. package/lib/composables/Validation.ts +1 -4
  84. package/lib/http/Http.ts +23 -17
  85. package/lib/styles/variables-deprecated.css +0 -1
  86. package/lib/styles/variables.css +16 -16
  87. package/lib/support/Chart.ts +0 -1
  88. package/lib/support/DateRange.ts +1 -1
  89. package/lib/support/Day.ts +12 -65
  90. package/lib/support/File.ts +7 -16
  91. package/lib/support/Utils.ts +7 -40
  92. package/lib/validation/Rule.ts +6 -21
  93. package/lib/validation/rules/decimal.ts +3 -3
  94. package/lib/validation/rules/email.ts +1 -1
  95. package/lib/validation/rules/index.ts +1 -1
  96. package/lib/validation/rules/negativeInteger.ts +1 -1
  97. package/lib/validation/rules/positiveInteger.ts +1 -1
  98. package/lib/validation/rules/requiredHms.ts +2 -2
  99. package/lib/validation/rules/requiredIf.ts +1 -4
  100. package/lib/validation/rules/requiredYmd.ts +2 -2
  101. package/lib/validation/rules/slackChannelName.ts +4 -1
  102. package/lib/validation/rules/zeroOrNegativeInteger.ts +1 -1
  103. package/lib/validation/rules/zeroOrPositiveInteger.ts +1 -1
  104. package/lib/validation/validators/after.ts +1 -5
  105. package/lib/validation/validators/afterOrEqual.ts +1 -5
  106. package/lib/validation/validators/before.ts +1 -4
  107. package/lib/validation/validators/beforeOrEqual.ts +1 -5
  108. package/lib/validation/validators/decimal.ts +7 -9
  109. package/lib/validation/validators/email.ts +4 -8
  110. package/lib/validation/validators/fileExtension.ts +7 -15
  111. package/lib/validation/validators/hms.ts +26 -15
  112. package/lib/validation/validators/index.ts +0 -2
  113. package/lib/validation/validators/maxFileSize.ts +3 -13
  114. package/lib/validation/validators/maxLength.ts +1 -7
  115. package/lib/validation/validators/maxTotalFileSize.ts +3 -26
  116. package/lib/validation/validators/maxValue.ts +2 -6
  117. package/lib/validation/validators/minLength.ts +1 -7
  118. package/lib/validation/validators/minValue.ts +2 -6
  119. package/lib/validation/validators/month.ts +1 -7
  120. package/lib/validation/validators/negativeInteger.ts +1 -7
  121. package/lib/validation/validators/positiveInteger.ts +1 -7
  122. package/lib/validation/validators/required.ts +5 -28
  123. package/lib/validation/validators/requiredHmsIf.ts +11 -13
  124. package/lib/validation/validators/requiredIf.ts +5 -11
  125. package/lib/validation/validators/requiredYmdIf.ts +11 -13
  126. package/lib/validation/validators/slackChannelName.ts +11 -11
  127. package/lib/validation/validators/url.ts +7 -5
  128. package/lib/validation/validators/ymd.ts +36 -30
  129. package/package.json +38 -38
  130. package/lib/validation/validators/requiredHms.ts +0 -9
  131. package/lib/validation/validators/requiredYmd.ts +0 -9
@@ -27,16 +27,6 @@ const props = defineProps<Props>()
27
27
 
28
28
  const slots = useSlots()
29
29
 
30
- const classes = computed(() => [
31
- props.size ?? 'small',
32
- { 'has-error': error.value?.has },
33
- { 'has-warning': props.warning }
34
- ])
35
-
36
- const hasInfo = computed(() => {
37
- return slots.info || props.info
38
- })
39
-
40
30
  const error = computed(() => {
41
31
  if (!props.validation) {
42
32
  return null
@@ -53,6 +43,16 @@ const error = computed(() => {
53
43
  }
54
44
  })
55
45
 
46
+ const classes = computed(() => [
47
+ props.size ?? 'small',
48
+ { 'has-error': error.value?.has },
49
+ { 'has-warning': props.warning }
50
+ ])
51
+
52
+ const hasInfo = computed(() => {
53
+ return slots.info || props.info
54
+ })
55
+
56
56
  function isDirtyAndInvalid(validation: Validatable) {
57
57
  return validation.$dirty && validation.$invalid
58
58
  }
@@ -79,7 +79,7 @@ function getErrorMsg(validation: Validatable) {
79
79
  <span class="label-note" :class="{ 'has-info': hasInfo }">{{ note }}</span>
80
80
 
81
81
  <span v-if="checkIcon || checkText" class="check" :class="checkColor || 'neutral'">
82
- <component v-if="checkIcon" :is="checkIcon" class="check-icon" />
82
+ <component :is="checkIcon" v-if="checkIcon" class="check-icon" />
83
83
  <span v-if="checkText" class="check-text">{{ checkText }}</span>
84
84
  </span>
85
85
  </label>
@@ -44,7 +44,9 @@ const isIndeterminate = computed(() => {
44
44
  const _value = computed(() => {
45
45
  return props.modelValue !== undefined
46
46
  ? props.modelValue === true
47
- : props.value !== undefined ? props.value === true : false
47
+ : props.value !== undefined
48
+ ? props.value === true
49
+ : false
48
50
  })
49
51
 
50
52
  function onClick() {
@@ -68,14 +70,15 @@ function onClick() {
68
70
  :check-text
69
71
  :check-color
70
72
  :validation
73
+ :hide-error
71
74
  >
72
75
  <div class="container">
73
76
  <div
74
77
  class="input"
75
78
  :class="{ on: _value || isIndeterminate }"
76
79
  role="button"
77
- @click="onClick"
78
80
  :aria-disabled="disabled"
81
+ @click="onClick"
79
82
  >
80
83
  <div class="box">
81
84
  <div class="check">
@@ -141,7 +144,7 @@ function onClick() {
141
144
  height: 16px;
142
145
  opacity: 0;
143
146
  transform: scale(0);
144
- transition: opacity .25s, transform .1s;
147
+ transition: opacity 0.25s, transform 0.1s;
145
148
  }
146
149
 
147
150
  .check-icon {
@@ -43,14 +43,16 @@ const emit = defineEmits<{
43
43
  const _value = computed(() => {
44
44
  return props.modelValue !== undefined
45
45
  ? props.modelValue
46
- : props.value !== undefined ? props.value : []
46
+ : props.value !== undefined
47
+ ? props.value
48
+ : []
47
49
  })
48
50
 
49
51
  function isChecked(value: Value): boolean {
50
52
  return _value.value.includes(value)
51
53
  }
52
54
 
53
- function handleChange(value: Value): void {
55
+ function onChange(value: Value): void {
54
56
  const distinct = _value.value
55
57
  .filter((v) => v !== value)
56
58
  .concat(_value.value.includes(value) ? [] : [value])
@@ -77,6 +79,8 @@ function handleChange(value: Value): void {
77
79
  :check-icon
78
80
  :check-text
79
81
  :check-color
82
+ :validation
83
+ :hide-error
80
84
  >
81
85
  <div class="container">
82
86
  <div class="row">
@@ -86,7 +90,7 @@ function handleChange(value: Value): void {
86
90
  :text="option.label"
87
91
  :disabled="option.disabled ?? disabled"
88
92
  :model-value="isChecked(option.value)"
89
- @update:model-value="handleChange(option.value)"
93
+ @update:model-value="onChange(option.value)"
90
94
  />
91
95
  </div>
92
96
  </div>
@@ -34,16 +34,14 @@ const classes = computed(() => [
34
34
  ])
35
35
 
36
36
  const value = computed(() => {
37
- return props.modelValue
38
- ? props.modelValue.format('YYYY-MM-DD')
39
- : null
37
+ return props.modelValue ? day(props.modelValue).format('YYYY-MM-DD') : null
40
38
  })
41
39
 
42
40
  function emitInput(date?: string) {
43
41
  emit('update:model-value', date ? day(date) : null)
44
42
  }
45
43
 
46
- function emitBlur() {
44
+ function onBlur() {
47
45
  setTimeout(() => {
48
46
  props.validation && props.validation.$touch()
49
47
  }, 100)
@@ -88,7 +86,7 @@ function emitBlur() {
88
86
  :disabled
89
87
  :tabindex
90
88
  v-on="disabled ? {} : inputEvents"
91
- @blur="emitBlur"
89
+ @blur="onBlur"
92
90
  >
93
91
  </DatePicker>
94
92
  </div>
@@ -59,8 +59,11 @@ const { t } = useTrans({
59
59
 
60
60
  const container = ref<HTMLDivElement>()
61
61
 
62
- const { isOpen, open } = useFlyout(container)
63
- const { inset, update: updatePosition } = useManualDropdownPosition(container, () => props.position)
62
+ const { isOpen, open, close } = useFlyout(container)
63
+ const { inset, update: updatePosition } = useManualDropdownPosition(
64
+ container,
65
+ () => props.position
66
+ )
64
67
 
65
68
  const classes = computed(() => [
66
69
  props.size ?? 'small',
@@ -72,7 +75,7 @@ const dropdownOptions = computed<DropdownSectionFilter[]>(() => [{
72
75
  search: props.noSearch === undefined ? true : !props.noSearch,
73
76
  selected: model.value,
74
77
  options: props.options,
75
- onClick: handleSelect
78
+ onClick: onSelect
76
79
  }])
77
80
 
78
81
  const selected = computed(() => {
@@ -97,35 +100,30 @@ const removable = computed(() => {
97
100
  return !!props.nullable
98
101
  })
99
102
 
100
- async function handleOpen() {
103
+ async function onOpen() {
101
104
  if (!props.disabled) {
102
105
  updatePosition()
103
106
  open()
104
107
  }
105
108
  }
106
109
 
107
- function handleSelect(value: OptionValue) {
110
+ function onSelect(value: OptionValue) {
108
111
  props.validation?.$touch()
109
112
 
110
- Array.isArray(model.value) ? handleArray(value) : handlePrimitive(value)
111
- }
112
-
113
- function handlePrimitive(value: OptionValue) {
114
- if (value !== model.value) {
115
- model.value = value
116
- } else if (props.nullable) {
117
- model.value = null
118
- }
119
- }
120
-
121
- function handleArray(value: OptionValue) {
122
- const difference = xor(model.value as ArrayValue, [value])
123
-
124
- if (!props.nullable && difference.length === 0) {
125
- return
113
+ if (Array.isArray(model.value)) {
114
+ const toggled = xor(model.value, [value])
115
+ if (toggled.length !== 0 || props.nullable) {
116
+ model.value = toggled
117
+ }
118
+ } else {
119
+ if (value !== model.value) {
120
+ model.value = value
121
+ } else if (props.nullable) {
122
+ model.value = null
123
+ }
126
124
  }
127
125
 
128
- model.value = difference
126
+ props.closeOnClick && close()
129
127
  }
130
128
  </script>
131
129
 
@@ -144,15 +142,15 @@ function handleArray(value: OptionValue) {
144
142
  :validation
145
143
  :hide-error
146
144
  >
147
- <div class="container" ref="container">
145
+ <div ref="container" class="container">
148
146
  <div
149
147
  class="box"
150
148
  role="button"
151
149
  tabindex="0"
152
- @click="handleOpen"
150
+ @click="onOpen"
153
151
  @keydown.down.prevent
154
- @keyup.enter="handleOpen"
155
- @keyup.down="handleOpen"
152
+ @keyup.enter="onOpen"
153
+ @keyup.down="onOpen"
156
154
  >
157
155
  <div class="box-content">
158
156
  <SInputDropdownItem
@@ -161,7 +159,7 @@ function handleArray(value: OptionValue) {
161
159
  :size="size ?? 'small'"
162
160
  :removable
163
161
  :disabled="disabled ?? false"
164
- @remove="handleSelect"
162
+ @remove="onSelect"
165
163
  />
166
164
 
167
165
  <div v-else class="box-placeholder">{{ placeholder ?? t.ph }}</div>
@@ -197,7 +195,7 @@ function handleArray(value: OptionValue) {
197
195
  border-radius: 6px;
198
196
  width: 100%;
199
197
  color: var(--input-text);
200
- background-color: var(--input-bg-color);;
198
+ background-color: var(--input-bg-color);
201
199
  cursor: pointer;
202
200
  transition: border-color 0.25s, background-color 0.25s;
203
201
 
@@ -23,34 +23,40 @@ export interface ItemAvatar extends ItemBase {
23
23
  image?: string | null
24
24
  }
25
25
 
26
- defineProps<{
26
+ const props = defineProps<{
27
27
  item: Item | Item[]
28
28
  size: Size
29
29
  removable: boolean
30
30
  disabled: boolean
31
31
  }>()
32
32
 
33
- defineEmits<{
33
+ const emit = defineEmits<{
34
34
  remove: [value: any]
35
35
  }>()
36
+
37
+ function emitRemove(value: any) {
38
+ if (!props.disabled) {
39
+ emit('remove', value)
40
+ }
41
+ }
36
42
  </script>
37
43
 
38
44
  <template>
39
45
  <div class="SInputDropdownItem" :class="[size, { disabled }]">
40
46
  <div v-if="Array.isArray(item)" class="many">
41
- <template v-for="i, index in item" :key="index">
42
- <div v-if="i.type === undefined || i.type === 'text'" class="many-text">
43
- <div class="many-text-value">{{ i.label }}</div>
44
- <button v-if="removable" class="many-text-close" @click.stop="$emit('remove', i.value)">
47
+ <template v-for="(el, i) in item" :key="i">
48
+ <div v-if="el.type === undefined || el.type === 'text'" class="many-text">
49
+ <div class="many-text-value">{{ el.label }}</div>
50
+ <button v-if="removable" class="many-text-close" @click.stop="emitRemove(el.value)">
45
51
  <IconX class="many-text-close-icon" />
46
52
  </button>
47
53
  </div>
48
- <div v-else-if="i.type === 'avatar'" class="many-avatar">
54
+ <div v-else-if="el.type === 'avatar'" class="many-avatar">
49
55
  <div class="many-avatar-body">
50
- <div class="many-avatar-image"><SAvatar size="fill" :avatar="i.image" /></div>
51
- <div class="many-avatar-name">{{ i.label }}</div>
56
+ <div class="many-avatar-image"><SAvatar size="fill" :avatar="el.image" /></div>
57
+ <div class="many-avatar-name">{{ el.label }}</div>
52
58
  </div>
53
- <button v-if="removable" class="many-avatar-close" @click.stop="$emit('remove', i.value)">
59
+ <button v-if="removable" class="many-avatar-close" @click.stop="emitRemove(el.value)">
54
60
  <IconX class="many-avatar-close-icon" />
55
61
  </button>
56
62
  </div>
@@ -64,7 +70,7 @@ defineEmits<{
64
70
  <div class="one-avatar-image"><SAvatar size="fill" :avatar="item.image" /></div>
65
71
  <div class="one-avatar-name">{{ item.label }}</div>
66
72
  </div>
67
- <button v-if="removable" class="one-close" @click.stop="$emit('remove', item.value)">
73
+ <button v-if="removable" class="one-close" @click.stop="emitRemove(item.value)">
68
74
  <IconX class="one-close-icon" />
69
75
  </button>
70
76
  </div>
@@ -317,4 +323,8 @@ defineEmits<{
317
323
  padding-left: 12px;
318
324
  }
319
325
  }
326
+
327
+ .disabled {
328
+ pointer-events: none;
329
+ }
320
330
  </style>
@@ -33,17 +33,20 @@ const emit = defineEmits<{
33
33
  const _value = computed(() => {
34
34
  return props.modelValue !== undefined
35
35
  ? props.modelValue
36
- : props.value !== undefined ? props.value : null
36
+ : props.value !== undefined
37
+ ? props.value
38
+ : null
37
39
  })
38
40
 
39
41
  const input = ref<HTMLInputElement | null>(null)
40
42
 
41
43
  const classes = computed(() => [props.size ?? 'small'])
42
44
 
43
- const fileName = computed(() => Array.isArray(_value.value)
44
- ? _value.value.map((file) => file.name).join(', ')
45
- : _value.value?.name ?? ''
46
- )
45
+ const fileName = computed(() => {
46
+ return Array.isArray(_value.value)
47
+ ? _value.value.map((file) => file.name).join(', ')
48
+ : (_value.value?.name ?? '')
49
+ })
47
50
 
48
51
  function open() {
49
52
  input.value!.click()
@@ -243,6 +246,6 @@ function onChange(e: Event) {
243
246
 
244
247
  .placeholder {
245
248
  font-weight: 500;
246
- color: var(--input-placeholder-color)
249
+ color: var(--input-placeholder-color);
247
250
  }
248
251
  </style>
@@ -46,7 +46,6 @@ const props = withDefaults(defineProps<{
46
46
  placeholder?: string
47
47
  emptyText?: string
48
48
  accept?: string
49
- multiple?: boolean
50
49
  checkIcon?: Component
51
50
  checkText?: string
52
51
  checkColor?: Color
@@ -70,7 +69,7 @@ const { t } = useTrans({
70
69
  en: {
71
70
  button_text: 'Choose File',
72
71
  empty_text: 'No file selected',
73
- selected_files: (c: number) => c === 1 ? `${c} file` : `${c} files`
72
+ selected_files: (c: number) => (c === 1 ? `${c} file` : `${c} files`)
74
73
  },
75
74
  ja: {
76
75
  button_text: 'ファイルを選択',
@@ -81,15 +80,14 @@ const { t } = useTrans({
81
80
 
82
81
  const dropZoneEl = ref<HTMLDivElement | null>(null)
83
82
 
84
- const { isOverDropZone } = useDropZone(dropZoneEl, {
85
- multiple: true,
86
- onDrop: (files) => onDrop(files)
87
- })
83
+ const { isOverDropZone } = useDropZone(dropZoneEl, { onDrop })
88
84
 
89
85
  const _value = computed(() => {
90
86
  return props.modelValue !== undefined
91
87
  ? props.modelValue
92
- : props.value !== undefined ? props.value : [] as ModelValue<T>[]
88
+ : props.value !== undefined
89
+ ? props.value
90
+ : ([] as ModelValue<T>[])
93
91
  })
94
92
 
95
93
  const input = ref<HTMLInputElement | null>(null)
@@ -105,7 +103,7 @@ const totalFileCountText = computed(() => {
105
103
  })
106
104
 
107
105
  const totalFileSizeText = computed(() => {
108
- const files = _value.value.map((file) => file instanceof File ? file : file.file)
106
+ const files = _value.value.map((file) => (file instanceof File ? file : file.file))
109
107
  return formatSize(files)
110
108
  })
111
109
 
@@ -150,7 +148,7 @@ function append(files: File[]) {
150
148
  }
151
149
 
152
150
  function toFileObjects(files: File[]) {
153
- return files.map((file) => ({ file } as ModelValue<T>))
151
+ return files.map((file) => ({ file }) as ModelValue<T>)
154
152
  }
155
153
  </script>
156
154
 
@@ -178,7 +176,7 @@ function toFileObjects(files: File[]) {
178
176
  @change="onChange"
179
177
  >
180
178
  <SCard :mode="hasError ? 'danger' : undefined">
181
- <SCardBlock v-if="droppable" class="drop-zone" ref="dropZoneEl" @click="open">
179
+ <SCardBlock v-if="droppable" ref="dropZoneEl" class="drop-zone" @click="open">
182
180
  <div class="drop-zone-box">
183
181
  <STrans lang="en">
184
182
  <div class="drop-zone-text">
@@ -211,7 +209,7 @@ function toFileObjects(files: File[]) {
211
209
  </SCardBlock>
212
210
  <template v-if="_value.length">
213
211
  <SInputFileUploadItem
214
- v-for="file, i in _value"
212
+ v-for="(file, i) in _value"
215
213
  :key="i"
216
214
  :file
217
215
  :rules
@@ -40,7 +40,7 @@ const _file = computed(() => ({
40
40
  file: props.file instanceof File ? props.file : props.file.file,
41
41
  size: formatSize(props.file instanceof File ? props.file : props.file.file),
42
42
  indicatorState: props.file instanceof File ? null : props.file.indicatorState,
43
- canRemove: props.file instanceof File ? true : props.file.canRemove ?? true,
43
+ canRemove: props.file instanceof File ? true : (props.file.canRemove ?? true),
44
44
  action: props.file instanceof File ? null : props.file.action,
45
45
  errorMessage: props.file instanceof File ? null : props.file.errorMessage
46
46
  }))
@@ -60,12 +60,16 @@ validation.value.$touch()
60
60
  <div class="name-label">
61
61
  <div class="name-icon">
62
62
  <IconFileText v-if="_file.indicatorState == null" class="name-icon-svg" />
63
- <SIndicator size="fill" v-else :state="_file.indicatorState" />
63
+ <SIndicator v-else size="fill" :state="_file.indicatorState" />
64
64
  </div>
65
65
  <p class="name-text">{{ _file.name }}</p>
66
66
  </div>
67
- <p v-if="_file.errorMessage" class="error">{{ _file.errorMessage }}</p>
68
- <p v-else-if="validation.$errors.length" class="error">{{ validation.$errors[0]?.$message }}</p>
67
+ <p v-if="_file.errorMessage" class="error">
68
+ {{ _file.errorMessage }}
69
+ </p>
70
+ <p v-else-if="validation.$errors.length" class="error">
71
+ {{ validation.$errors[0]?.$message }}
72
+ </p>
69
73
  </div>
70
74
  <div v-if="_file.action" class="action">
71
75
  <SButton
@@ -37,7 +37,9 @@ const emit = defineEmits<{
37
37
  const _value = computed(() => {
38
38
  return props.modelValue !== undefined
39
39
  ? props.modelValue
40
- : props.value !== undefined ? props.value : null
40
+ : props.value !== undefined
41
+ ? props.value
42
+ : null
41
43
  })
42
44
 
43
45
  const padPlaceholder = computed(() => {
@@ -49,9 +49,11 @@ const emit = defineEmits<{
49
49
  const fileInput = ref<HTMLInputElement | null>(null)
50
50
 
51
51
  const _value = computed(() => {
52
- return (props.modelValue !== undefined)
52
+ return props.modelValue !== undefined
53
53
  ? props.modelValue
54
- : props.value !== undefined ? props.value : null
54
+ : props.value !== undefined
55
+ ? props.value
56
+ : null
55
57
  })
56
58
 
57
59
  const { src: imageSrc } = useImageSrcFromFile(_value)
@@ -1,13 +1,12 @@
1
1
  <script setup lang="ts">
2
- import { computed } from 'vue'
3
- import { isString } from '../support/Utils'
2
+ import { type Component, computed } from 'vue'
4
3
  import { type Props as BaseProps } from './SInputBase.vue'
5
4
  import SInputText from './SInputText.vue'
6
5
 
7
6
  export interface Props extends BaseProps {
8
7
  placeholder?: string
9
- unitBefore?: any
10
- unitAfter?: any
8
+ unitBefore?: Component | string
9
+ unitAfter?: Component | string
11
10
  textColor?: TextColor | ((value: number | null) => TextColor)
12
11
  separator?: boolean
13
12
  align?: Align
@@ -29,9 +28,11 @@ const emit = defineEmits<{
29
28
  }>()
30
29
 
31
30
  const _value = computed(() => {
32
- return (props.modelValue !== undefined)
31
+ return props.modelValue !== undefined
33
32
  ? props.modelValue
34
- : props.value !== undefined ? props.value : null
33
+ : props.value !== undefined
34
+ ? props.value
35
+ : null
35
36
  })
36
37
 
37
38
  const _textColor = computed(() => {
@@ -39,7 +40,7 @@ const _textColor = computed(() => {
39
40
  return 'neutral'
40
41
  }
41
42
 
42
- if (isString(props.textColor)) {
43
+ if (typeof props.textColor === 'string') {
43
44
  return props.textColor
44
45
  }
45
46
 
@@ -61,9 +62,7 @@ const displayValue = computed(() => {
61
62
  return props.displayValue
62
63
  }
63
64
 
64
- return (!props.separator || valueWithSeparator.value == null)
65
- ? null
66
- : valueWithSeparator.value
65
+ return !props.separator || valueWithSeparator.value == null ? null : valueWithSeparator.value
67
66
  })
68
67
 
69
68
  function emitUpdate(value: string | null) {
@@ -45,6 +45,7 @@ function onClick() {
45
45
  class="SInputRadio"
46
46
  :class="classes"
47
47
  :size
48
+ :name
48
49
  :label
49
50
  :note
50
51
  :info
@@ -60,14 +61,14 @@ function onClick() {
60
61
  class="input"
61
62
  :class="{ on: props.modelValue }"
62
63
  role="button"
63
- @click="onClick"
64
64
  :aria-disabled="disabled"
65
+ @click="onClick"
65
66
  >
66
67
  <div class="box">
67
68
  <div class="check" />
68
69
  </div>
69
70
 
70
- <p class="text" v-if="text">{{ text }}</p>
71
+ <p v-if="text" class="text">{{ text }}</p>
71
72
  </div>
72
73
  </div>
73
74
  <template v-if="$slots.info" #info><slot name="info" /></template>
@@ -13,9 +13,7 @@ import SInputRadio from './SInputRadio.vue'
13
13
 
14
14
  export type { Color, Size }
15
15
 
16
- export interface Option<
17
- ValueType extends string | number | boolean = string | number | boolean
18
- > {
16
+ export interface Option<ValueType extends string | number | boolean = string | number | boolean> {
19
17
  label: string
20
18
  value: ValueType
21
19
  disabled?: boolean
@@ -53,7 +51,9 @@ const emit = defineEmits<{
53
51
  const _value = computed(() => {
54
52
  return props.modelValue !== undefined
55
53
  ? props.modelValue
56
- : props.value !== undefined ? props.value : null
54
+ : props.value !== undefined
55
+ ? props.value
56
+ : null
57
57
  })
58
58
 
59
59
  function isChecked(value: ValueType) {
@@ -88,6 +88,7 @@ function onChange(value: ValueType) {
88
88
  class="SInputRadios"
89
89
  :class="[size ?? 'small']"
90
90
  :size
91
+ :name
91
92
  :label
92
93
  :note
93
94
  :info
@@ -100,7 +101,7 @@ function onChange(value: ValueType) {
100
101
  >
101
102
  <div class="container">
102
103
  <div class="row">
103
- <div v-for="(option, index) in options" :key="index" class="col">
104
+ <div v-for="(option, i) in options" :key="i" class="col">
104
105
  <SInputRadio
105
106
  size="sm"
106
107
  :text="option.label"
@@ -38,9 +38,7 @@ const emit = defineEmits<{
38
38
  }>()
39
39
 
40
40
  const _value = computed(() => {
41
- const v = props.modelValue !== undefined
42
- ? props.modelValue
43
- : props.value
41
+ const v = props.modelValue !== undefined ? props.modelValue : props.value
44
42
 
45
43
  if (v === undefined) {
46
44
  throw new Error('[sefirot] SInputSegments: `value` or `modelValue` is required.')
@@ -60,6 +58,7 @@ function onSelect(value: T) {
60
58
  class="SInputSegments"
61
59
  :class="[size ?? 'small', { block }]"
62
60
  :size
61
+ :name
63
62
  :label
64
63
  :note
65
64
  :info
@@ -72,14 +71,13 @@ function onSelect(value: T) {
72
71
  >
73
72
  <div class="box">
74
73
  <SInputSegmentsOption
75
- v-for="option, index in options"
76
- :key="index"
74
+ v-for="(option, i) in options"
75
+ :key="i"
77
76
  :size="size ?? 'small'"
78
77
  :label="option.label"
79
- :value="option.value"
80
78
  :mode="option.mode ?? 'default'"
81
79
  :active="_value === option.value"
82
- :disabled="disabled ? true : option.disabled ?? false"
80
+ :disabled="disabled ? true : (option.disabled ?? false)"
83
81
  @click="onSelect(option.value)"
84
82
  />
85
83
  </div>
@@ -1,4 +1,4 @@
1
- <script setup lang="ts" generic="T extends string | number | boolean">
1
+ <script setup lang="ts">
2
2
  import { type Size } from './SInputBase.vue'
3
3
 
4
4
  export type { Size }
@@ -7,7 +7,6 @@ export type Mode = 'default' | 'mute' | 'neutral' | 'info' | 'success' | 'warnin
7
7
  const props = defineProps<{
8
8
  size: Size
9
9
  label: string
10
- value: T
11
10
  mode: Mode
12
11
  active: boolean
13
12
  disabled: boolean