@globalbrain/sefirot 4.30.1 → 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.
- package/client.d.ts +5 -0
- package/config/nuxt.d.ts +1 -0
- package/config/nuxt.js +8 -5
- package/config/vite.js +4 -13
- package/lib/components/SActionList.vue +2 -2
- package/lib/components/SActionMenu.vue +43 -7
- package/lib/components/SAvatar.vue +1 -1
- package/lib/components/SAvatarStack.vue +12 -12
- package/lib/components/SButton.vue +5 -7
- package/lib/components/SCard.vue +2 -2
- package/lib/components/SChartBar.vue +37 -12
- package/lib/components/SChartPie.vue +13 -7
- package/lib/components/SControlActionBarCollapse.vue +2 -4
- package/lib/components/SControlInputSearch.vue +7 -2
- package/lib/components/SDataListItem.vue +1 -3
- package/lib/components/SDescAvatar.vue +1 -1
- package/lib/components/SDescDay.vue +2 -2
- package/lib/components/SDescFile.vue +2 -4
- package/lib/components/SDescItem.vue +2 -1
- package/lib/components/SDescLabel.vue +1 -1
- package/lib/components/SDescLink.vue +2 -7
- package/lib/components/SDescPill.vue +2 -4
- package/lib/components/SDescText.vue +3 -3
- package/lib/components/SDropdown.vue +1 -1
- package/lib/components/SDropdownSectionFilter.vue +11 -11
- package/lib/components/SFragment.vue +1 -1
- package/lib/components/SInputAddon.vue +13 -11
- package/lib/components/SInputBase.vue +11 -11
- package/lib/components/SInputCheckbox.vue +6 -3
- package/lib/components/SInputCheckboxes.vue +7 -3
- package/lib/components/SInputDate.vue +3 -5
- package/lib/components/SInputDropdown.vue +26 -28
- package/lib/components/SInputDropdownItem.vue +21 -11
- package/lib/components/SInputFile.vue +9 -6
- package/lib/components/SInputFileUpload.vue +9 -11
- package/lib/components/SInputFileUploadItem.vue +8 -4
- package/lib/components/SInputHMS.vue +3 -1
- package/lib/components/SInputImage.vue +4 -2
- package/lib/components/SInputNumber.vue +9 -10
- package/lib/components/SInputRadio.vue +3 -2
- package/lib/components/SInputRadios.vue +6 -5
- package/lib/components/SInputSegments.vue +5 -7
- package/lib/components/SInputSegmentsOption.vue +1 -2
- package/lib/components/SInputSelect.vue +6 -4
- package/lib/components/SInputSwitch.vue +4 -1
- package/lib/components/SInputSwitches.vue +5 -3
- package/lib/components/SInputText.vue +16 -16
- package/lib/components/SInputTextarea.vue +7 -3
- package/lib/components/SInputYMD.vue +3 -1
- package/lib/components/SLink.vue +2 -2
- package/lib/components/SLocalNav.vue +1 -1
- package/lib/components/SLocalNavActions.vue +1 -1
- package/lib/components/SLocalNavMenu.vue +2 -2
- package/lib/components/SLoginPagePasswordDialog.vue +2 -2
- package/lib/components/SM.vue +1 -1
- package/lib/components/SMFade.vue +1 -1
- package/lib/components/SMarkdown.vue +3 -2
- package/lib/components/SModal.vue +2 -2
- package/lib/components/SSnackbar.vue +2 -2
- package/lib/components/SSteps.vue +6 -6
- package/lib/components/STable.vue +70 -27
- package/lib/components/STableCell.vue +14 -17
- package/lib/components/STableCellAvatars.vue +1 -1
- package/lib/components/STableCellDay.vue +12 -5
- package/lib/components/STableCellNumber.vue +2 -3
- package/lib/components/STableCellPath.vue +2 -2
- package/lib/components/STableCellText.vue +2 -3
- package/lib/components/STableColumn.vue +38 -16
- package/lib/components/STableFooter.vue +10 -2
- package/lib/components/STableHeader.vue +0 -1
- package/lib/components/STableHeaderMenu.vue +4 -4
- package/lib/components/STableHeaderMenuItem.vue +1 -1
- package/lib/components/STooltip.vue +3 -3
- package/lib/composables/Api.ts +1 -1
- package/lib/composables/App.ts +13 -11
- package/lib/composables/Dropdown.ts +10 -1
- package/lib/composables/Error.ts +37 -37
- package/lib/composables/Grid.ts +1 -4
- package/lib/composables/Image.ts +2 -3
- package/lib/composables/Lang.ts +8 -16
- package/lib/composables/Markdown.ts +1 -1
- package/lib/composables/Table.ts +0 -2
- package/lib/composables/Theme.ts +1 -13
- package/lib/composables/Utils.ts +11 -4
- package/lib/composables/Validation.ts +1 -4
- package/lib/http/Http.ts +23 -17
- package/lib/styles/variables-deprecated.css +0 -1
- package/lib/styles/variables.css +16 -16
- package/lib/support/Chart.ts +0 -1
- package/lib/support/DateRange.ts +1 -1
- package/lib/support/Day.ts +12 -65
- package/lib/support/File.ts +7 -16
- package/lib/support/Utils.ts +7 -40
- package/lib/validation/Rule.ts +6 -21
- package/lib/validation/rules/decimal.ts +3 -3
- package/lib/validation/rules/email.ts +1 -1
- package/lib/validation/rules/index.ts +1 -1
- package/lib/validation/rules/negativeInteger.ts +1 -1
- package/lib/validation/rules/positiveInteger.ts +1 -1
- package/lib/validation/rules/requiredHms.ts +2 -2
- package/lib/validation/rules/requiredIf.ts +1 -4
- package/lib/validation/rules/requiredYmd.ts +2 -2
- package/lib/validation/rules/slackChannelName.ts +4 -1
- package/lib/validation/rules/zeroOrNegativeInteger.ts +1 -1
- package/lib/validation/rules/zeroOrPositiveInteger.ts +1 -1
- package/lib/validation/validators/after.ts +1 -5
- package/lib/validation/validators/afterOrEqual.ts +1 -5
- package/lib/validation/validators/before.ts +1 -4
- package/lib/validation/validators/beforeOrEqual.ts +1 -5
- package/lib/validation/validators/decimal.ts +7 -9
- package/lib/validation/validators/email.ts +4 -8
- package/lib/validation/validators/fileExtension.ts +7 -15
- package/lib/validation/validators/hms.ts +26 -15
- package/lib/validation/validators/index.ts +0 -2
- package/lib/validation/validators/maxFileSize.ts +3 -13
- package/lib/validation/validators/maxLength.ts +1 -7
- package/lib/validation/validators/maxTotalFileSize.ts +3 -26
- package/lib/validation/validators/maxValue.ts +2 -6
- package/lib/validation/validators/minLength.ts +1 -7
- package/lib/validation/validators/minValue.ts +2 -6
- package/lib/validation/validators/month.ts +1 -7
- package/lib/validation/validators/negativeInteger.ts +1 -7
- package/lib/validation/validators/positiveInteger.ts +1 -7
- package/lib/validation/validators/required.ts +5 -28
- package/lib/validation/validators/requiredHmsIf.ts +11 -13
- package/lib/validation/validators/requiredIf.ts +5 -11
- package/lib/validation/validators/requiredYmdIf.ts +11 -13
- package/lib/validation/validators/slackChannelName.ts +11 -11
- package/lib/validation/validators/url.ts +7 -5
- package/lib/validation/validators/ymd.ts +36 -30
- package/package.json +44 -42
- package/lib/composables/Http.ts +0 -18
- package/lib/validation/validators/requiredHms.ts +0 -9
- package/lib/validation/validators/requiredYmd.ts +0 -9
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
useManualDropdownPosition
|
|
8
8
|
} from '../composables/Dropdown'
|
|
9
9
|
import { useFlyout } from '../composables/Flyout'
|
|
10
|
-
import { isString } from '../support/Utils'
|
|
11
10
|
import SDropdown from './SDropdown.vue'
|
|
12
11
|
|
|
13
12
|
const props = withDefaults(defineProps<{
|
|
@@ -15,7 +14,7 @@ const props = withDefaults(defineProps<{
|
|
|
15
14
|
clickable?: boolean
|
|
16
15
|
dropdown?: DropdownSection[]
|
|
17
16
|
dropdownCaret?: boolean
|
|
18
|
-
|
|
17
|
+
dropdownPosition?: 'top' | 'bottom'
|
|
19
18
|
disabled?: boolean
|
|
20
19
|
}>(), {
|
|
21
20
|
clickable: true,
|
|
@@ -42,21 +41,24 @@ const selectedOptionLabel = computed(() => {
|
|
|
42
41
|
})
|
|
43
42
|
|
|
44
43
|
const { isOpen, open } = useFlyout(container)
|
|
45
|
-
const { position, update: updatePosition } = useManualDropdownPosition(
|
|
44
|
+
const { position, update: updatePosition } = useManualDropdownPosition(
|
|
45
|
+
container,
|
|
46
|
+
() => props.dropdownPosition
|
|
47
|
+
)
|
|
46
48
|
|
|
47
|
-
function
|
|
49
|
+
function onFocus() {
|
|
48
50
|
if (!props.disabled) {
|
|
49
51
|
isFocused.value = true
|
|
50
52
|
}
|
|
51
53
|
}
|
|
52
54
|
|
|
53
|
-
function
|
|
55
|
+
function onBlur() {
|
|
54
56
|
if (!props.disabled) {
|
|
55
57
|
isFocused.value = false
|
|
56
58
|
}
|
|
57
59
|
}
|
|
58
60
|
|
|
59
|
-
function
|
|
61
|
+
function onClickButton() {
|
|
60
62
|
if (!props.disabled) {
|
|
61
63
|
emit('click')
|
|
62
64
|
|
|
@@ -69,19 +71,19 @@ function handleClickButton() {
|
|
|
69
71
|
</script>
|
|
70
72
|
|
|
71
73
|
<template>
|
|
72
|
-
<div class="SInputAddon" :class="classes"
|
|
74
|
+
<div ref="container" class="SInputAddon" :class="classes" @click.stop>
|
|
73
75
|
<component
|
|
74
76
|
:is="clickable ? 'button' : 'div'"
|
|
75
77
|
class="action"
|
|
76
78
|
:disabled="clickable ? props.disabled : null"
|
|
77
|
-
@focus="
|
|
78
|
-
@blur="
|
|
79
|
-
@click="
|
|
79
|
+
@focus="onFocus"
|
|
80
|
+
@blur="onBlur"
|
|
81
|
+
@click="onClickButton"
|
|
80
82
|
>
|
|
81
83
|
<span class="action-label">
|
|
82
84
|
<component
|
|
83
|
-
v-if="props.label && !isString(props.label)"
|
|
84
85
|
:is="props.label"
|
|
86
|
+
v-if="props.label && (typeof props.label !== 'string')"
|
|
85
87
|
class="action-icon"
|
|
86
88
|
/>
|
|
87
89
|
<span v-else>
|
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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="
|
|
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
|
|
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="
|
|
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(
|
|
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:
|
|
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
|
|
103
|
+
async function onOpen() {
|
|
101
104
|
if (!props.disabled) {
|
|
102
105
|
updatePosition()
|
|
103
106
|
open()
|
|
104
107
|
}
|
|
105
108
|
}
|
|
106
109
|
|
|
107
|
-
function
|
|
110
|
+
function onSelect(value: OptionValue) {
|
|
108
111
|
props.validation?.$touch()
|
|
109
112
|
|
|
110
|
-
Array.isArray(model.value)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
-
|
|
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
|
|
145
|
+
<div ref="container" class="container">
|
|
148
146
|
<div
|
|
149
147
|
class="box"
|
|
150
148
|
role="button"
|
|
151
149
|
tabindex="0"
|
|
152
|
-
@click="
|
|
150
|
+
@click="onOpen"
|
|
153
151
|
@keydown.down.prevent
|
|
154
|
-
@keyup.enter="
|
|
155
|
-
@keyup.down="
|
|
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="
|
|
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="
|
|
42
|
-
<div v-if="
|
|
43
|
-
<div class="many-text-value">{{
|
|
44
|
-
<button v-if="removable" class="many-text-close" @click.stop="
|
|
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="
|
|
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="
|
|
51
|
-
<div class="many-avatar-name">{{
|
|
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="
|
|
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="
|
|
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
|
|
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(() =>
|
|
44
|
-
|
|
45
|
-
|
|
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
|
|
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"
|
|
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"
|
|
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">
|
|
68
|
-
|
|
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
|
|
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
|
|
52
|
+
return props.modelValue !== undefined
|
|
53
53
|
? props.modelValue
|
|
54
|
-
: props.value !== undefined
|
|
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?:
|
|
10
|
-
unitAfter?:
|
|
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
|
|
31
|
+
return props.modelValue !== undefined
|
|
33
32
|
? props.modelValue
|
|
34
|
-
: props.value !== undefined
|
|
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 (
|
|
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
|
|
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
|
|
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>
|