@antify/ui 4.2.1 → 4.2.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.
- package/dist/components/inputs/AntCheckbox.vue +33 -3
- package/dist/components/inputs/AntCheckboxGroup.vue +149 -1
- package/dist/components/inputs/AntRadio.vue +35 -41
- package/dist/components/inputs/AntRadioGroup.vue +135 -1
- package/dist/components/inputs/__stories/AntCheckboxGroup.stories.d.ts +3 -0
- package/dist/components/inputs/__stories/AntCheckboxGroup.stories.js +360 -15
- package/dist/components/inputs/__stories/AntCheckboxGroup.stories.mjs +369 -19
- package/dist/components/inputs/__stories/AntRadioGroup.stories.d.ts +2 -0
- package/dist/components/inputs/__stories/AntRadioGroup.stories.js +231 -20
- package/dist/components/inputs/__stories/AntRadioGroup.stories.mjs +232 -20
- package/dist/enums/LayoutVariant.enum.d.ts +5 -0
- package/dist/enums/LayoutVariant.enum.js +12 -0
- package/dist/enums/LayoutVariant.enum.mjs +6 -0
- package/dist/enums/index.d.ts +1 -0
- package/dist/enums/index.js +11 -0
- package/dist/enums/index.mjs +1 -0
- package/package.json +1 -1
|
@@ -65,6 +65,7 @@ const props =
|
|
|
65
65
|
});
|
|
66
66
|
const _modelValue = useVModel(props, 'modelValue', emit);
|
|
67
67
|
const delayedValue = ref(_modelValue.value);
|
|
68
|
+
const inputRef = ref<HTMLInputElement | null>(null);
|
|
68
69
|
const hasInputState = computed(() => props.skeleton || props.readonly || props.disabled);
|
|
69
70
|
const inputClasses = computed(() => {
|
|
70
71
|
const focusColorVariant: Record<InputState, string> = {
|
|
@@ -106,7 +107,7 @@ const inputClasses = computed(() => {
|
|
|
106
107
|
};
|
|
107
108
|
});
|
|
108
109
|
const contentClasses = computed(() => ({
|
|
109
|
-
'text-for-white-bg-font': true,
|
|
110
|
+
'text-for-white-bg-font w-fit': true,
|
|
110
111
|
'cursor-pointer': !hasInputState.value,
|
|
111
112
|
'cursor-not-allowed opacity-50': props.disabled,
|
|
112
113
|
'text-sm': props.size === Size.lg || props.size === Size.md || props.size === Size.sm,
|
|
@@ -119,6 +120,20 @@ const itemSize = computed(() => {
|
|
|
119
120
|
return IconSize.sm;
|
|
120
121
|
}
|
|
121
122
|
});
|
|
123
|
+
const gapSize = computed(() => {
|
|
124
|
+
switch (props.size) {
|
|
125
|
+
case Size.lg:
|
|
126
|
+
return 'gap-2.5';
|
|
127
|
+
case Size.md:
|
|
128
|
+
return 'gap-2';
|
|
129
|
+
case Size.sm:
|
|
130
|
+
return 'gap-1.5';
|
|
131
|
+
case Size.xs:
|
|
132
|
+
return 'gap-1.5';
|
|
133
|
+
default:
|
|
134
|
+
return 'gap-1';
|
|
135
|
+
}
|
|
136
|
+
});
|
|
122
137
|
const iconColor = computed(() => {
|
|
123
138
|
switch (props.state) {
|
|
124
139
|
case InputState.base:
|
|
@@ -167,6 +182,12 @@ function onBlur(e: FocusEvent) {
|
|
|
167
182
|
emit('blur', e);
|
|
168
183
|
}
|
|
169
184
|
|
|
185
|
+
const onClickContent = () => {
|
|
186
|
+
if (inputRef.value && !props.disabled && !props.readonly) {
|
|
187
|
+
inputRef.value.focus();
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
|
|
170
191
|
onMounted(() => {
|
|
171
192
|
handleEnumValidation(props.size, Size, 'size');
|
|
172
193
|
handleEnumValidation(props.state, InputState, 'state');
|
|
@@ -187,8 +208,12 @@ onMounted(() => {
|
|
|
187
208
|
:size="size"
|
|
188
209
|
:expanded="false"
|
|
189
210
|
:messages="messages"
|
|
211
|
+
@mousedown.prevent="onClickContent"
|
|
190
212
|
>
|
|
191
|
-
<div
|
|
213
|
+
<div
|
|
214
|
+
class="flex"
|
|
215
|
+
:class="gapSize"
|
|
216
|
+
>
|
|
192
217
|
<div
|
|
193
218
|
class="relative flex"
|
|
194
219
|
:class="{
|
|
@@ -199,8 +224,10 @@ onMounted(() => {
|
|
|
199
224
|
<AntSkeleton
|
|
200
225
|
:visible="skeleton"
|
|
201
226
|
rounded
|
|
227
|
+
@click.prevent
|
|
202
228
|
>
|
|
203
229
|
<input
|
|
230
|
+
ref="inputRef"
|
|
204
231
|
v-model="_modelValue"
|
|
205
232
|
:class="inputClasses"
|
|
206
233
|
type="checkbox"
|
|
@@ -223,7 +250,10 @@ onMounted(() => {
|
|
|
223
250
|
</AntSkeleton>
|
|
224
251
|
</div>
|
|
225
252
|
|
|
226
|
-
<span
|
|
253
|
+
<span
|
|
254
|
+
:class="contentClasses"
|
|
255
|
+
@mousedown.prevent="onClickContent"
|
|
256
|
+
>
|
|
227
257
|
<AntSkeleton
|
|
228
258
|
:visible="skeleton"
|
|
229
259
|
rounded
|
|
@@ -13,8 +13,9 @@ import {
|
|
|
13
13
|
Direction,
|
|
14
14
|
} from '../../enums/Direction.enum';
|
|
15
15
|
import {
|
|
16
|
-
InputState, Size,
|
|
16
|
+
InputState, LayoutVariant, Size,
|
|
17
17
|
} from '../../enums';
|
|
18
|
+
import AntSkeleton from '../AntSkeleton.vue';
|
|
18
19
|
|
|
19
20
|
const emit = defineEmits([
|
|
20
21
|
'update:modelValue',
|
|
@@ -30,6 +31,7 @@ const props = withDefaults(
|
|
|
30
31
|
direction?: Direction;
|
|
31
32
|
state?: InputState;
|
|
32
33
|
size?: Size;
|
|
34
|
+
layoutVariant?: LayoutVariant;
|
|
33
35
|
skeleton?: boolean;
|
|
34
36
|
readonly?: boolean;
|
|
35
37
|
disabled?: boolean;
|
|
@@ -48,8 +50,10 @@ const props = withDefaults(
|
|
|
48
50
|
activeColorClass?: string;
|
|
49
51
|
}>(),
|
|
50
52
|
{
|
|
53
|
+
checkboxes: () => [],
|
|
51
54
|
direction: Direction.column,
|
|
52
55
|
state: InputState.base,
|
|
56
|
+
layoutVariant: LayoutVariant.default,
|
|
53
57
|
size: Size.md,
|
|
54
58
|
skeleton: false,
|
|
55
59
|
readonly: false,
|
|
@@ -60,12 +64,67 @@ const props = withDefaults(
|
|
|
60
64
|
activeColorClass: 'text-primary-500',
|
|
61
65
|
},
|
|
62
66
|
);
|
|
67
|
+
|
|
63
68
|
const containerClasses = computed(() => ({
|
|
64
69
|
'flex gap-2.5': true,
|
|
65
70
|
'flex-row': props.direction === Direction.row,
|
|
66
71
|
'flex-col': props.direction === Direction.column,
|
|
67
72
|
}));
|
|
73
|
+
const blockContainerClasses = computed(() => ({
|
|
74
|
+
'flex flex-col gap-px rounded-md border overflow-hidden': true,
|
|
75
|
+
'bg-base-300 border-base-300': props.state === InputState.base,
|
|
76
|
+
'bg-info-500 border-info-500': props.state === InputState.info,
|
|
77
|
+
'bg-success-500 border-success-500': props.state === InputState.success,
|
|
78
|
+
'bg-warning-500 border-warning-500': props.state === InputState.warning,
|
|
79
|
+
'bg-danger-500 border-danger-500': props.state === InputState.danger,
|
|
80
|
+
'cursor-not-allowed': props.disabled,
|
|
81
|
+
}));
|
|
82
|
+
const blockItemClasses = computed(() => ({
|
|
83
|
+
'p-2.5': props.size === Size.lg,
|
|
84
|
+
'p-2': props.size === Size.md,
|
|
85
|
+
'p-1.5': props.size === Size.sm || props.size === Size.xs,
|
|
86
|
+
'p-1': props.size === Size.xs2,
|
|
87
|
+
}));
|
|
88
|
+
const tabContainerClasses = computed(() => ({
|
|
89
|
+
'flex rounded-md overflow-hidden': true,
|
|
90
|
+
'cursor-not-allowed': props.disabled,
|
|
91
|
+
}));
|
|
92
|
+
const tabItemClasses = computed(() => ({
|
|
93
|
+
'flex justify-center grow transition-colors': true,
|
|
94
|
+
'text-sm': props.size === Size.lg || props.size === Size.md || props.size === Size.sm,
|
|
95
|
+
'text-xs': props.size === Size.xs || props.size === Size.xs2,
|
|
96
|
+
'p-2.5': props.size === Size.lg,
|
|
97
|
+
'p-2': props.size === Size.md,
|
|
98
|
+
'p-1.5': props.size === Size.sm || props.size === Size.xs,
|
|
99
|
+
'p-1': props.size === Size.xs2,
|
|
100
|
+
}));
|
|
101
|
+
const getTabItemColorClasses = (checkbox: AntCheckboxType, index: number) => {
|
|
102
|
+
const borderClasses = {
|
|
103
|
+
'border-base-300': props.modelValue?.includes(checkbox.value) || (!props.modelValue?.includes(checkbox.value) && props.state === InputState.base),
|
|
104
|
+
'border-info-500': !props.modelValue?.includes(checkbox.value) && props.state === InputState.info,
|
|
105
|
+
'border-success-500': !props.modelValue?.includes(checkbox.value) && props.state === InputState.success,
|
|
106
|
+
'border-warning-500': !props.modelValue?.includes(checkbox.value) && props.state === InputState.warning,
|
|
107
|
+
'border-danger-500': !props.modelValue?.includes(checkbox.value) && props.state === InputState.danger,
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
...borderClasses,
|
|
112
|
+
'border-y': true,
|
|
113
|
+
'border-l': index !== props.checkboxes.length - 1,
|
|
114
|
+
'border-x': index === props.checkboxes.length - 1,
|
|
115
|
+
'rounded-l-md': index === 0,
|
|
116
|
+
'rounded-r-md': index === props.checkboxes.length - 1,
|
|
117
|
+
'opacity-50': props.disabled || checkbox.disabled,
|
|
118
|
+
'bg-white text-for-white-bg-font': !props.modelValue?.includes(checkbox.value),
|
|
119
|
+
'!bg-primary-500 text-primary-500-font': !props.skeleton && props.modelValue?.includes(checkbox.value) && props.state === InputState.base,
|
|
120
|
+
'!bg-info-500 text-info-500-font': !props.skeleton && props.modelValue?.includes(checkbox.value) && props.state === InputState.info,
|
|
121
|
+
'!bg-success-500 text-success-500-font': !props.skeleton && props.modelValue?.includes(checkbox.value) && props.state === InputState.success,
|
|
122
|
+
'!bg-warning-500 text-warning-500-font': !props.skeleton && props.modelValue?.includes(checkbox.value) && props.state === InputState.warning,
|
|
123
|
+
'!bg-danger-500 text-danger-500-font': !props.skeleton && props.modelValue?.includes(checkbox.value) && props.state === InputState.danger,
|
|
124
|
+
};
|
|
125
|
+
};
|
|
68
126
|
const containerRef = ref<null | HTMLElement>(null);
|
|
127
|
+
const checkboxRef = ref<Array<InstanceType<typeof AntCheckbox>>>([]);
|
|
69
128
|
|
|
70
129
|
watch(() => props.modelValue, (val) => {
|
|
71
130
|
if ([
|
|
@@ -115,6 +174,34 @@ function onBlurCheckbox() {
|
|
|
115
174
|
}, 100);
|
|
116
175
|
}
|
|
117
176
|
|
|
177
|
+
const onClickBlockItem = (checkbox: AntCheckboxType, index: number) => {
|
|
178
|
+
if (props.skeleton || props.disabled || props.readonly || checkbox.disabled || checkbox.readonly) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
updateValue(checkbox.value);
|
|
183
|
+
|
|
184
|
+
setTimeout(() => {
|
|
185
|
+
const checkboxComponent = checkboxRef.value[index];
|
|
186
|
+
|
|
187
|
+
if (checkboxComponent && checkboxComponent.$el) {
|
|
188
|
+
const input = checkboxComponent.$el.querySelector('input[type="checkbox"]');
|
|
189
|
+
|
|
190
|
+
if (input) {
|
|
191
|
+
input.focus();
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
const onClickTabItem = (checkbox: AntCheckboxType) => {
|
|
198
|
+
if (props.skeleton || props.disabled || props.readonly || checkbox.disabled || checkbox.readonly) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
updateValue(checkbox.value);
|
|
203
|
+
};
|
|
204
|
+
|
|
118
205
|
onMounted(() => {
|
|
119
206
|
if (!props.skeleton && props.modelValue !== null) {
|
|
120
207
|
emit('validate', props.modelValue);
|
|
@@ -134,6 +221,7 @@ onMounted(() => {
|
|
|
134
221
|
label-for="noop"
|
|
135
222
|
>
|
|
136
223
|
<div
|
|
224
|
+
v-if="layoutVariant === LayoutVariant.default"
|
|
137
225
|
ref="containerRef"
|
|
138
226
|
:class="containerClasses"
|
|
139
227
|
>
|
|
@@ -155,5 +243,65 @@ onMounted(() => {
|
|
|
155
243
|
{{ checkbox.label }}
|
|
156
244
|
</AntCheckbox>
|
|
157
245
|
</div>
|
|
246
|
+
|
|
247
|
+
<div
|
|
248
|
+
v-if="layoutVariant === LayoutVariant.block"
|
|
249
|
+
ref="containerRef"
|
|
250
|
+
:class="blockContainerClasses"
|
|
251
|
+
>
|
|
252
|
+
<div
|
|
253
|
+
v-for="(checkbox, index) in checkboxes"
|
|
254
|
+
:key="`checkbox-widget_${checkbox.value}-${index}`"
|
|
255
|
+
:class="{
|
|
256
|
+
...blockItemClasses,
|
|
257
|
+
'cursor-not-allowed': props.disabled || checkbox.disabled,
|
|
258
|
+
'cursor-pointer hover:bg-base-50': !props.skeleton && !props.disabled && !props.readonly && !checkbox.disabled && !checkbox.readonly,
|
|
259
|
+
'bg-base-100': !skeleton && modelValue?.includes(checkbox.value),
|
|
260
|
+
'bg-white': skeleton || !modelValue?.includes(checkbox.value),
|
|
261
|
+
}"
|
|
262
|
+
@click="onClickBlockItem(checkbox, index)"
|
|
263
|
+
>
|
|
264
|
+
<AntCheckbox
|
|
265
|
+
:ref="el => checkboxRef[index] = el"
|
|
266
|
+
:model-value="modelValue !== null ? modelValue?.indexOf(checkbox.value) !== -1 : null"
|
|
267
|
+
:skeleton="skeleton"
|
|
268
|
+
:disabled="disabled || checkbox.disabled"
|
|
269
|
+
:readonly="readonly || checkbox.readonly"
|
|
270
|
+
:state="state"
|
|
271
|
+
:size="size"
|
|
272
|
+
@update:model-value="updateValue(checkbox.value)"
|
|
273
|
+
@blur="() => onBlurCheckbox()"
|
|
274
|
+
@click.stop
|
|
275
|
+
>
|
|
276
|
+
{{ checkbox.label }}
|
|
277
|
+
</AntCheckbox>
|
|
278
|
+
</div>
|
|
279
|
+
</div>
|
|
280
|
+
|
|
281
|
+
<div
|
|
282
|
+
v-if="layoutVariant === LayoutVariant.tab"
|
|
283
|
+
:class="tabContainerClasses"
|
|
284
|
+
>
|
|
285
|
+
<div
|
|
286
|
+
v-for="(checkbox, index) in checkboxes"
|
|
287
|
+
:key="`checkbox-widget_${checkbox.value}-${index}`"
|
|
288
|
+
:class="{
|
|
289
|
+
...tabItemClasses,
|
|
290
|
+
...getTabItemColorClasses(checkbox, index),
|
|
291
|
+
'cursor-not-allowed': props.disabled || checkbox.disabled,
|
|
292
|
+
'cursor-pointer hover:bg-base-50': !props.skeleton && !props.disabled && !props.readonly && !checkbox.disabled && !checkbox.readonly,
|
|
293
|
+
'bg-base-100': !skeleton && modelValue?.includes(checkbox.value),
|
|
294
|
+
'bg-white': skeleton || !modelValue?.includes(checkbox.value),
|
|
295
|
+
}"
|
|
296
|
+
@click="onClickTabItem(checkbox)"
|
|
297
|
+
>
|
|
298
|
+
<AntSkeleton
|
|
299
|
+
:visible="skeleton"
|
|
300
|
+
rounded
|
|
301
|
+
>
|
|
302
|
+
{{ checkbox.label }}
|
|
303
|
+
</AntSkeleton>
|
|
304
|
+
</div>
|
|
305
|
+
</div>
|
|
158
306
|
</AntField>
|
|
159
307
|
</template>
|
|
@@ -107,13 +107,6 @@ const gapSize = computed(() => {
|
|
|
107
107
|
return 'gap-1';
|
|
108
108
|
}
|
|
109
109
|
});
|
|
110
|
-
const valueSize = computed(() => {
|
|
111
|
-
if (props.size === Size.xs || props.size === Size.xs2) {
|
|
112
|
-
return 'h-4';
|
|
113
|
-
} else {
|
|
114
|
-
return 'h-5';
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
110
|
const innerRadioClass = computed(() => (
|
|
118
111
|
{
|
|
119
112
|
'bg-primary-500': props.state === InputState.base,
|
|
@@ -177,50 +170,51 @@ onMounted(() => {
|
|
|
177
170
|
data-e2e="radio"
|
|
178
171
|
>
|
|
179
172
|
<div
|
|
180
|
-
class="flex
|
|
173
|
+
class="flex"
|
|
181
174
|
:class="gapSize"
|
|
182
175
|
>
|
|
183
|
-
<div
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
/>
|
|
191
|
-
</Transition>
|
|
192
|
-
</div>
|
|
193
|
-
|
|
194
|
-
<input
|
|
195
|
-
v-model="_modelValue"
|
|
196
|
-
:value="value.value"
|
|
197
|
-
:class="inputClasses"
|
|
198
|
-
type="radio"
|
|
199
|
-
:aria-checked="isActive"
|
|
200
|
-
:disabled="disabled || readonly"
|
|
201
|
-
@blur="onBlur"
|
|
202
|
-
>
|
|
203
|
-
|
|
176
|
+
<div
|
|
177
|
+
class="relative flex"
|
|
178
|
+
:class="{
|
|
179
|
+
'h-5 w-5': size === Size.lg || size === Size.md || size === Size.sm,
|
|
180
|
+
'h-4 w-4': size === Size.xs || size === Size.xs2,
|
|
181
|
+
}"
|
|
182
|
+
>
|
|
204
183
|
<AntSkeleton
|
|
205
184
|
:visible="skeleton"
|
|
206
|
-
absolute
|
|
207
185
|
rounded-full
|
|
208
|
-
|
|
186
|
+
@click.prevent
|
|
187
|
+
>
|
|
188
|
+
<div class="absolute flex items-center justify-center w-full h-full">
|
|
189
|
+
<Transition name="fade-radio">
|
|
190
|
+
<div
|
|
191
|
+
v-if="isActive"
|
|
192
|
+
class="rounded-full transition-all"
|
|
193
|
+
:class="innerRadioClass"
|
|
194
|
+
/>
|
|
195
|
+
</Transition>
|
|
196
|
+
</div>
|
|
197
|
+
|
|
198
|
+
<input
|
|
199
|
+
v-model="_modelValue"
|
|
200
|
+
:value="value.value"
|
|
201
|
+
:class="inputClasses"
|
|
202
|
+
type="radio"
|
|
203
|
+
:aria-checked="isActive"
|
|
204
|
+
:disabled="disabled || readonly"
|
|
205
|
+
@blur="onBlur"
|
|
206
|
+
>
|
|
207
|
+
</AntSkeleton>
|
|
209
208
|
</div>
|
|
210
209
|
|
|
211
|
-
<
|
|
212
|
-
|
|
213
|
-
|
|
210
|
+
<AntSkeleton
|
|
211
|
+
:visible="skeleton"
|
|
212
|
+
rounded
|
|
214
213
|
>
|
|
215
214
|
<span :class="valueClass">
|
|
216
|
-
|
|
217
|
-
:visible="skeleton"
|
|
218
|
-
rounded
|
|
219
|
-
>
|
|
220
|
-
{{ value.label }}
|
|
221
|
-
</AntSkeleton>
|
|
215
|
+
{{ value.label }}
|
|
222
216
|
</span>
|
|
223
|
-
</
|
|
217
|
+
</AntSkeleton>
|
|
224
218
|
</div>
|
|
225
219
|
</AntField>
|
|
226
220
|
</template>
|
|
@@ -6,11 +6,12 @@ import {
|
|
|
6
6
|
import {
|
|
7
7
|
AntField,
|
|
8
8
|
} from './Elements';
|
|
9
|
+
import AntSkeleton from '../AntSkeleton.vue';
|
|
9
10
|
import {
|
|
10
11
|
type AntRadioTypes,
|
|
11
12
|
} from './__types/AntRadio.types';
|
|
12
13
|
import {
|
|
13
|
-
InputState, Size,
|
|
14
|
+
InputState, LayoutVariant, Size,
|
|
14
15
|
} from '../../enums';
|
|
15
16
|
import {
|
|
16
17
|
computed, onMounted, ref, watch,
|
|
@@ -35,6 +36,7 @@ const props = withDefaults(defineProps<{
|
|
|
35
36
|
direction?: Direction;
|
|
36
37
|
state?: InputState;
|
|
37
38
|
size?: Size;
|
|
39
|
+
layoutVariant?: LayoutVariant;
|
|
38
40
|
skeleton?: boolean;
|
|
39
41
|
disabled?: boolean;
|
|
40
42
|
readonly?: boolean;
|
|
@@ -42,6 +44,7 @@ const props = withDefaults(defineProps<{
|
|
|
42
44
|
}>(), {
|
|
43
45
|
direction: Direction.column,
|
|
44
46
|
state: InputState.base,
|
|
47
|
+
layoutVariant: LayoutVariant.default,
|
|
45
48
|
size: Size.md,
|
|
46
49
|
skeleton: false,
|
|
47
50
|
disabled: false,
|
|
@@ -49,6 +52,7 @@ const props = withDefaults(defineProps<{
|
|
|
49
52
|
messages: () => [],
|
|
50
53
|
});
|
|
51
54
|
const _modelValue = useVModel(props, 'modelValue', emit);
|
|
55
|
+
const radioRef = ref<Array<InstanceType<typeof AntRadio>>>([]);
|
|
52
56
|
const containerClasses = computed(() => ({
|
|
53
57
|
'flex justify-start': true,
|
|
54
58
|
'flex-row': props.direction === Direction.row,
|
|
@@ -58,6 +62,50 @@ const containerClasses = computed(() => ({
|
|
|
58
62
|
'gap-1.5': props.size === Size.sm || props.size === Size.xs,
|
|
59
63
|
'gap-1': props.size === Size.xs2,
|
|
60
64
|
}));
|
|
65
|
+
const blockContainerClasses = computed(() => ({
|
|
66
|
+
'flex flex-col gap-px rounded-md border overflow-hidden': true,
|
|
67
|
+
'bg-base-300 border-base-300': props.state === InputState.base,
|
|
68
|
+
'bg-info-500 border-info-500': props.state === InputState.info,
|
|
69
|
+
'bg-success-500 border-success-500': props.state === InputState.success,
|
|
70
|
+
'bg-warning-500 border-warning-500': props.state === InputState.warning,
|
|
71
|
+
'bg-danger-500 border-danger-500': props.state === InputState.danger,
|
|
72
|
+
'cursor-not-allowed': props.disabled,
|
|
73
|
+
}));
|
|
74
|
+
const blockItemClasses = computed(() => ({
|
|
75
|
+
'p-2.5': props.size === Size.lg,
|
|
76
|
+
'p-2': props.size === Size.md,
|
|
77
|
+
'p-1.5': props.size === Size.sm || props.size === Size.xs,
|
|
78
|
+
'p-1': props.size === Size.xs2,
|
|
79
|
+
}));
|
|
80
|
+
const tabContainerClasses = computed(() => ({
|
|
81
|
+
'flex gap-px rounded-md border overflow-hidden': true,
|
|
82
|
+
'bg-base-300 border-base-300': props.state === InputState.base,
|
|
83
|
+
'bg-info-500 border-info-500': props.state === InputState.info,
|
|
84
|
+
'bg-success-500 border-success-500': props.state === InputState.success,
|
|
85
|
+
'bg-warning-500 border-warning-500': props.state === InputState.warning,
|
|
86
|
+
'bg-danger-500 border-danger-500': props.state === InputState.danger,
|
|
87
|
+
'cursor-not-allowed': props.disabled,
|
|
88
|
+
}));
|
|
89
|
+
const tabItemClasses = computed(() => ({
|
|
90
|
+
'flex justify-center grow transition-colors': true,
|
|
91
|
+
'text-sm': props.size === Size.lg || props.size === Size.md || props.size === Size.sm,
|
|
92
|
+
'text-xs': props.size === Size.xs || props.size === Size.xs2,
|
|
93
|
+
'p-2.5': props.size === Size.lg,
|
|
94
|
+
'p-2': props.size === Size.md,
|
|
95
|
+
'p-1.5': props.size === Size.sm || props.size === Size.xs,
|
|
96
|
+
'p-1': props.size === Size.xs2,
|
|
97
|
+
}));
|
|
98
|
+
const getTabItemColorClasses = (radio: AntRadioTypes) => {
|
|
99
|
+
return {
|
|
100
|
+
'opacity-50': props.disabled || radio.disabled,
|
|
101
|
+
'bg-white text-for-white-bg-font': radio.value !== _modelValue.value,
|
|
102
|
+
'!bg-primary-500 text-primary-500-font': !props.skeleton && radio.value === _modelValue.value && props.state === InputState.base,
|
|
103
|
+
'!bg-info-500 text-info-500-font': !props.skeleton && radio.value === _modelValue.value && props.state === InputState.info,
|
|
104
|
+
'!bg-success-500 text-success-500-font': !props.skeleton && radio.value === _modelValue.value && props.state === InputState.success,
|
|
105
|
+
'!bg-warning-500 text-warning-500-font': !props.skeleton && radio.value === _modelValue.value && props.state === InputState.warning,
|
|
106
|
+
'!bg-danger-500 text-danger-500-font': !props.skeleton && radio.value === _modelValue.value && props.state === InputState.danger,
|
|
107
|
+
};
|
|
108
|
+
};
|
|
61
109
|
const containerRef = ref<null | HTMLElement>(null);
|
|
62
110
|
const fieldSize = computed(() => {
|
|
63
111
|
switch (props.size) {
|
|
@@ -107,6 +155,34 @@ function onBlurRadio() {
|
|
|
107
155
|
}, 100);
|
|
108
156
|
}
|
|
109
157
|
|
|
158
|
+
const onClickBlockItem = (radio: AntRadioTypes, index: number) => {
|
|
159
|
+
if (props.skeleton || props.disabled || props.readonly || radio.disabled || radio.readonly) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
_modelValue.value = radio.value;
|
|
164
|
+
|
|
165
|
+
setTimeout(() => {
|
|
166
|
+
const radioComponent = radioRef.value[index];
|
|
167
|
+
|
|
168
|
+
if (radioComponent && radioComponent.$el) {
|
|
169
|
+
const input = radioComponent.$el.querySelector('input[type="radio"]');
|
|
170
|
+
|
|
171
|
+
if (input) {
|
|
172
|
+
input.focus();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
const onClickTabItem = (radio: AntRadioTypes) => {
|
|
179
|
+
if (props.skeleton || props.disabled || props.readonly || radio.disabled || radio.readonly) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
_modelValue.value = radio.value;
|
|
184
|
+
};
|
|
185
|
+
|
|
110
186
|
onMounted(() => {
|
|
111
187
|
handleEnumValidation(props.size, Size, 'size');
|
|
112
188
|
handleEnumValidation(props.state, InputState, 'state');
|
|
@@ -133,6 +209,7 @@ onMounted(() => {
|
|
|
133
209
|
data-e2e="radio-group"
|
|
134
210
|
>
|
|
135
211
|
<div
|
|
212
|
+
v-if="layoutVariant === LayoutVariant.default"
|
|
136
213
|
ref="containerRef"
|
|
137
214
|
:class="containerClasses"
|
|
138
215
|
>
|
|
@@ -149,5 +226,62 @@ onMounted(() => {
|
|
|
149
226
|
@blur="onBlurRadio"
|
|
150
227
|
/>
|
|
151
228
|
</div>
|
|
229
|
+
|
|
230
|
+
<div
|
|
231
|
+
v-if="layoutVariant === LayoutVariant.block"
|
|
232
|
+
ref="containerRef"
|
|
233
|
+
:class="blockContainerClasses"
|
|
234
|
+
>
|
|
235
|
+
<div
|
|
236
|
+
v-for="(radio, index) in radioButtons"
|
|
237
|
+
:key="`radio-button-widget_${radio.value}-${index}`"
|
|
238
|
+
:class="{
|
|
239
|
+
...blockItemClasses,
|
|
240
|
+
'cursor-not-allowed': props.disabled || radio.disabled,
|
|
241
|
+
'cursor-pointer hover:bg-base-50': !props.skeleton && !props.disabled && !props.readonly && !radio.disabled && !radio.readonly,
|
|
242
|
+
'bg-base-100': !skeleton && _modelValue === radio.value,
|
|
243
|
+
'bg-white': skeleton || _modelValue !== radio.value,
|
|
244
|
+
}"
|
|
245
|
+
@click="onClickBlockItem(radio, index)"
|
|
246
|
+
>
|
|
247
|
+
<AntRadio
|
|
248
|
+
:ref="el => radioRef[index] = el"
|
|
249
|
+
v-model="_modelValue"
|
|
250
|
+
:value="radio"
|
|
251
|
+
:skeleton="skeleton"
|
|
252
|
+
:disabled="disabled || radio.disabled"
|
|
253
|
+
:readonly="readonly || radio.readonly"
|
|
254
|
+
:state="radio.state || state"
|
|
255
|
+
:size="size"
|
|
256
|
+
@blur="onBlurRadio"
|
|
257
|
+
/>
|
|
258
|
+
</div>
|
|
259
|
+
</div>
|
|
260
|
+
|
|
261
|
+
<div
|
|
262
|
+
v-if="layoutVariant === LayoutVariant.tab"
|
|
263
|
+
:class="tabContainerClasses"
|
|
264
|
+
>
|
|
265
|
+
<div
|
|
266
|
+
v-for="(radio, index) in radioButtons"
|
|
267
|
+
:key="`radio-button-widget_${radio.value}-${index}`"
|
|
268
|
+
:class="{
|
|
269
|
+
...tabItemClasses,
|
|
270
|
+
...getTabItemColorClasses(radio),
|
|
271
|
+
'cursor-not-allowed': props.disabled || radio.disabled,
|
|
272
|
+
'cursor-pointer hover:bg-base-50': !props.skeleton && !props.disabled && !props.readonly && !radio.disabled && !radio.readonly,
|
|
273
|
+
'bg-base-100': !skeleton && _modelValue === radio.value,
|
|
274
|
+
'bg-white': skeleton || _modelValue !== radio.value,
|
|
275
|
+
}"
|
|
276
|
+
@click="onClickTabItem(radio)"
|
|
277
|
+
>
|
|
278
|
+
<AntSkeleton
|
|
279
|
+
:visible="skeleton"
|
|
280
|
+
rounded
|
|
281
|
+
>
|
|
282
|
+
{{ radio.label }}
|
|
283
|
+
</AntSkeleton>
|
|
284
|
+
</div>
|
|
285
|
+
</div>
|
|
152
286
|
</AntField>
|
|
153
287
|
</template>
|
|
@@ -5,3 +5,6 @@ export default meta;
|
|
|
5
5
|
type Story = StoryObj<typeof AntCheckboxGroup>;
|
|
6
6
|
export declare const Docs: Story;
|
|
7
7
|
export declare const WithLongContent: Story;
|
|
8
|
+
export declare const BlockVariant: Story;
|
|
9
|
+
export declare const TabVariant: Story;
|
|
10
|
+
export declare const summary: Story;
|