@antify/ui 4.1.32 → 4.1.34
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/calendar/AntDatePicker.vue +24 -4
- package/dist/components/calendar/__stories/AntDatePicker.stories.d.ts +1 -0
- package/dist/components/calendar/__stories/AntDatePicker.stories.js +75 -1
- package/dist/components/calendar/__stories/AntDatePicker.stories.mjs +74 -0
- package/dist/components/inputs/AntNumberInput.vue +154 -47
- package/dist/components/inputs/Elements/AntBaseInput.vue +18 -2
- package/dist/components/inputs/__stories/AntNumberInput.stories.d.ts +3 -0
- package/dist/components/inputs/__stories/AntNumberInput.stories.js +120 -21
- package/dist/components/inputs/__stories/AntNumberInput.stories.mjs +121 -20
- package/package.json +1 -1
|
@@ -35,11 +35,16 @@ const props = withDefaults(defineProps<{
|
|
|
35
35
|
date: string;
|
|
36
36
|
color: string;
|
|
37
37
|
}[];
|
|
38
|
+
/**
|
|
39
|
+
* Color token used for the week number column (e.g., 'base-200', 'primary-500').
|
|
40
|
+
*/
|
|
41
|
+
weekNumberColor?: string;
|
|
38
42
|
}>(), {
|
|
39
43
|
showWeekend: false,
|
|
40
44
|
showWeekNumbers: false,
|
|
41
45
|
skeleton: false,
|
|
42
46
|
specialDays: () => [],
|
|
47
|
+
weekNumberColor: 'base-200',
|
|
43
48
|
});
|
|
44
49
|
const emit = defineEmits([
|
|
45
50
|
'select',
|
|
@@ -134,6 +139,18 @@ const getColorNumber = (color: string) => {
|
|
|
134
139
|
return match ? parseInt(match[0], 10) : null;
|
|
135
140
|
};
|
|
136
141
|
|
|
142
|
+
const getContrastTextColor = (colorToken: string) => {
|
|
143
|
+
const match = colorToken.match(/(\d+)/);
|
|
144
|
+
const weight = match ? parseInt(match[0], 10) : 0;
|
|
145
|
+
|
|
146
|
+
return weight < 500 ? 'var(--color-for-white-bg-font)' : '#fff';
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const weekNumberStyles = computed(() => ({
|
|
150
|
+
backgroundColor: `var(--color-${props.weekNumberColor})`,
|
|
151
|
+
color: getContrastTextColor(props.weekNumberColor),
|
|
152
|
+
}));
|
|
153
|
+
|
|
137
154
|
watch(() => props.modelValue, (val) => {
|
|
138
155
|
const date = new Date(val);
|
|
139
156
|
currentMonthIndex.value = date.getMonth();
|
|
@@ -179,9 +196,11 @@ onMounted(() => {
|
|
|
179
196
|
}"
|
|
180
197
|
>
|
|
181
198
|
<div
|
|
182
|
-
v-for="day in weekDays"
|
|
183
|
-
:key="day"
|
|
184
|
-
class="text-
|
|
199
|
+
v-for="(day, index) in weekDays"
|
|
200
|
+
:key="`${day}-${index}`"
|
|
201
|
+
class="text-center flex items-center justify-center rounded-md"
|
|
202
|
+
:class="[!(showWeekNumbers && index === 0) ? 'text-for-white-bg-font' : '']"
|
|
203
|
+
:style="showWeekNumbers && index === 0 ? weekNumberStyles : {}"
|
|
185
204
|
>
|
|
186
205
|
<AntSkeleton
|
|
187
206
|
:visible="skeleton"
|
|
@@ -200,7 +219,8 @@ onMounted(() => {
|
|
|
200
219
|
>
|
|
201
220
|
<div
|
|
202
221
|
v-if="showWeekNumbers"
|
|
203
|
-
class="flex
|
|
222
|
+
class="flex font-semibold rounded-md transition-colors"
|
|
223
|
+
:style="weekNumberStyles"
|
|
204
224
|
>
|
|
205
225
|
<AntSkeleton
|
|
206
226
|
:visible="skeleton"
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
module.exports = exports.Summary = exports.Docs = void 0;
|
|
6
|
+
module.exports = exports.WeekNumberStyling = exports.Summary = exports.Docs = void 0;
|
|
7
7
|
var _AntDatePicker = _interopRequireDefault(require("../AntDatePicker.vue"));
|
|
8
8
|
var _AntDateSwitcher = _interopRequireDefault(require("../AntDateSwitcher.vue"));
|
|
9
9
|
var _vue = require("vue");
|
|
@@ -31,6 +31,21 @@ const meta = {
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
},
|
|
34
|
+
weekNumberColor: {
|
|
35
|
+
control: "text",
|
|
36
|
+
description: "Color token e.g. 'base-200', 'primary-500'. Automatically calculates contrast text color.",
|
|
37
|
+
table: {
|
|
38
|
+
type: {
|
|
39
|
+
summary: "string"
|
|
40
|
+
},
|
|
41
|
+
defaultValue: {
|
|
42
|
+
summary: "base-200"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
showWeekNumbers: {
|
|
47
|
+
control: "boolean"
|
|
48
|
+
},
|
|
34
49
|
onSelect: {
|
|
35
50
|
action: "select"
|
|
36
51
|
}
|
|
@@ -66,6 +81,65 @@ const Docs = exports.Docs = {
|
|
|
66
81
|
}]
|
|
67
82
|
}
|
|
68
83
|
};
|
|
84
|
+
const WeekNumberStyling = exports.WeekNumberStyling = {
|
|
85
|
+
render: args => ({
|
|
86
|
+
components: {
|
|
87
|
+
AntCalendar: _AntDatePicker.default,
|
|
88
|
+
AntFormGroup: _AntFormGroup.default,
|
|
89
|
+
AntFormGroupLabel: _AntFormGroupLabel.default
|
|
90
|
+
},
|
|
91
|
+
setup() {
|
|
92
|
+
const value = (0, _vue.ref)((/* @__PURE__ */new Date("2026-01-01")).getTime());
|
|
93
|
+
return {
|
|
94
|
+
value,
|
|
95
|
+
args
|
|
96
|
+
};
|
|
97
|
+
},
|
|
98
|
+
template: `
|
|
99
|
+
<AntFormGroup class="p-4 flex gap-4 w-fit">
|
|
100
|
+
<AntFormGroupLabel>Week Number Styling (Presets)</AntFormGroupLabel>
|
|
101
|
+
|
|
102
|
+
<AntFormGroup class="grid grid-cols-4 gap-10">
|
|
103
|
+
<div class="flex flex-col w-64 gap-2">
|
|
104
|
+
<span class="text-sm font-medium text-for-white-bg-font">1. Default (Base 200)</span>
|
|
105
|
+
<AntCalendar
|
|
106
|
+
v-model="value"
|
|
107
|
+
:show-week-numbers="true"
|
|
108
|
+
/>
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
<div class="flex flex-col w-64 gap-2">
|
|
112
|
+
<span class="text-sm font-medium text-for-white-bg-font">2. Primary 900</span>
|
|
113
|
+
<AntCalendar
|
|
114
|
+
v-model="value"
|
|
115
|
+
:show-week-numbers="true"
|
|
116
|
+
week-number-color="primary-900"
|
|
117
|
+
/>
|
|
118
|
+
</div>
|
|
119
|
+
|
|
120
|
+
<div class="flex flex-col w-64 gap-2">
|
|
121
|
+
<span class="text-sm font-medium text-for-white-bg-font">3. Info 100</span>
|
|
122
|
+
<AntCalendar
|
|
123
|
+
v-model="value"
|
|
124
|
+
:show-week-numbers="true"
|
|
125
|
+
week-number-color="info-100"
|
|
126
|
+
/>
|
|
127
|
+
</div>
|
|
128
|
+
|
|
129
|
+
<div class="flex flex-col w-64 gap-2">
|
|
130
|
+
<span class="text-sm font-medium text-for-white-bg-font">4. Success 500</span>
|
|
131
|
+
<AntCalendar
|
|
132
|
+
v-model="value"
|
|
133
|
+
:show-week-numbers="true"
|
|
134
|
+
week-number-color="success-500"
|
|
135
|
+
/>
|
|
136
|
+
</div>
|
|
137
|
+
|
|
138
|
+
</AntFormGroup>
|
|
139
|
+
</AntFormGroup>
|
|
140
|
+
`
|
|
141
|
+
})
|
|
142
|
+
};
|
|
69
143
|
const Summary = exports.Summary = {
|
|
70
144
|
parameters: {
|
|
71
145
|
chromatic: {
|
|
@@ -29,6 +29,21 @@ const meta = {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
},
|
|
32
|
+
weekNumberColor: {
|
|
33
|
+
control: "text",
|
|
34
|
+
description: "Color token e.g. 'base-200', 'primary-500'. Automatically calculates contrast text color.",
|
|
35
|
+
table: {
|
|
36
|
+
type: {
|
|
37
|
+
summary: "string"
|
|
38
|
+
},
|
|
39
|
+
defaultValue: {
|
|
40
|
+
summary: "base-200"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
showWeekNumbers: {
|
|
45
|
+
control: "boolean"
|
|
46
|
+
},
|
|
32
47
|
onSelect: {
|
|
33
48
|
action: "select"
|
|
34
49
|
}
|
|
@@ -66,6 +81,65 @@ export const Docs = {
|
|
|
66
81
|
]
|
|
67
82
|
}
|
|
68
83
|
};
|
|
84
|
+
export const WeekNumberStyling = {
|
|
85
|
+
render: (args) => ({
|
|
86
|
+
components: {
|
|
87
|
+
AntCalendar,
|
|
88
|
+
AntFormGroup,
|
|
89
|
+
AntFormGroupLabel
|
|
90
|
+
},
|
|
91
|
+
setup() {
|
|
92
|
+
const value = ref((/* @__PURE__ */ new Date("2026-01-01")).getTime());
|
|
93
|
+
return {
|
|
94
|
+
value,
|
|
95
|
+
args
|
|
96
|
+
};
|
|
97
|
+
},
|
|
98
|
+
template: `
|
|
99
|
+
<AntFormGroup class="p-4 flex gap-4 w-fit">
|
|
100
|
+
<AntFormGroupLabel>Week Number Styling (Presets)</AntFormGroupLabel>
|
|
101
|
+
|
|
102
|
+
<AntFormGroup class="grid grid-cols-4 gap-10">
|
|
103
|
+
<div class="flex flex-col w-64 gap-2">
|
|
104
|
+
<span class="text-sm font-medium text-for-white-bg-font">1. Default (Base 200)</span>
|
|
105
|
+
<AntCalendar
|
|
106
|
+
v-model="value"
|
|
107
|
+
:show-week-numbers="true"
|
|
108
|
+
/>
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
<div class="flex flex-col w-64 gap-2">
|
|
112
|
+
<span class="text-sm font-medium text-for-white-bg-font">2. Primary 900</span>
|
|
113
|
+
<AntCalendar
|
|
114
|
+
v-model="value"
|
|
115
|
+
:show-week-numbers="true"
|
|
116
|
+
week-number-color="primary-900"
|
|
117
|
+
/>
|
|
118
|
+
</div>
|
|
119
|
+
|
|
120
|
+
<div class="flex flex-col w-64 gap-2">
|
|
121
|
+
<span class="text-sm font-medium text-for-white-bg-font">3. Info 100</span>
|
|
122
|
+
<AntCalendar
|
|
123
|
+
v-model="value"
|
|
124
|
+
:show-week-numbers="true"
|
|
125
|
+
week-number-color="info-100"
|
|
126
|
+
/>
|
|
127
|
+
</div>
|
|
128
|
+
|
|
129
|
+
<div class="flex flex-col w-64 gap-2">
|
|
130
|
+
<span class="text-sm font-medium text-for-white-bg-font">4. Success 500</span>
|
|
131
|
+
<AntCalendar
|
|
132
|
+
v-model="value"
|
|
133
|
+
:show-week-numbers="true"
|
|
134
|
+
week-number-color="success-500"
|
|
135
|
+
/>
|
|
136
|
+
</div>
|
|
137
|
+
|
|
138
|
+
</AntFormGroup>
|
|
139
|
+
</AntFormGroup>
|
|
140
|
+
`
|
|
141
|
+
})
|
|
142
|
+
};
|
|
69
143
|
export const Summary = {
|
|
70
144
|
parameters: {
|
|
71
145
|
chromatic: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import {
|
|
3
|
-
computed, onMounted,
|
|
3
|
+
computed, onMounted, nextTick, ref, useId,
|
|
4
4
|
} from 'vue';
|
|
5
5
|
import AntButton from '../AntButton.vue';
|
|
6
6
|
import AntField from '../forms/AntField.vue';
|
|
@@ -58,6 +58,7 @@ const props = withDefaults(defineProps<{
|
|
|
58
58
|
messages?: string[];
|
|
59
59
|
indicators?: boolean;
|
|
60
60
|
inputRef?: HTMLInputElement | null;
|
|
61
|
+
selectAllOnFocus?: boolean;
|
|
61
62
|
}>(), {
|
|
62
63
|
state: InputState.base,
|
|
63
64
|
disabled: false,
|
|
@@ -69,95 +70,197 @@ const props = withDefaults(defineProps<{
|
|
|
69
70
|
messages: () => [],
|
|
70
71
|
indicators: false,
|
|
71
72
|
inputRef: null,
|
|
73
|
+
selectAllOnFocus: false,
|
|
72
74
|
});
|
|
73
75
|
const emit = defineEmits([
|
|
74
76
|
'update:modelValue',
|
|
75
77
|
'update:inputRef',
|
|
76
78
|
'validate',
|
|
79
|
+
'focus',
|
|
80
|
+
'blur',
|
|
77
81
|
]);
|
|
78
82
|
|
|
83
|
+
const id = useId();
|
|
84
|
+
const _inputRef = useVModel(props, 'inputRef', emit);
|
|
85
|
+
const isFocused = ref(false);
|
|
86
|
+
|
|
79
87
|
const _modelValue = computed({
|
|
80
88
|
get: () => {
|
|
81
|
-
if(
|
|
82
|
-
return
|
|
89
|
+
if (props.modelValue === null || props.modelValue === undefined || props.modelValue === '') {
|
|
90
|
+
return null;
|
|
83
91
|
}
|
|
84
92
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
93
|
+
if (isFocused.value) {
|
|
94
|
+
return props.modelValue.toString();
|
|
95
|
+
}
|
|
88
96
|
|
|
89
|
-
|
|
97
|
+
const bigValue = new Big(props.modelValue);
|
|
98
|
+
const isInteger = bigValue.mod(1).eq(0);
|
|
99
|
+
|
|
100
|
+
if (isInteger) {
|
|
101
|
+
return props.modelValue.toString();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const dp = getPrecision();
|
|
105
|
+
|
|
106
|
+
return bigValue.toFixed(dp);
|
|
90
107
|
},
|
|
91
|
-
set: (val: string) => {
|
|
92
|
-
|
|
108
|
+
set: (val: string | number | null) => {
|
|
109
|
+
if (val === '' || val === null || val === undefined) {
|
|
110
|
+
emit('update:modelValue', null);
|
|
111
|
+
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const num = Number(val);
|
|
116
|
+
if (!isNaN(num)) {
|
|
117
|
+
emit('update:modelValue', num);
|
|
118
|
+
}
|
|
93
119
|
},
|
|
94
120
|
});
|
|
95
|
-
|
|
121
|
+
|
|
122
|
+
function onInputFocus(e: FocusEvent) {
|
|
123
|
+
isFocused.value = true;
|
|
124
|
+
|
|
125
|
+
const el = e.target as HTMLInputElement;
|
|
126
|
+
|
|
127
|
+
if (el && props.selectAllOnFocus && el.value !== '') {
|
|
128
|
+
const originalType = el.type;
|
|
129
|
+
el.type = 'text';
|
|
130
|
+
|
|
131
|
+
setTimeout(() => {
|
|
132
|
+
el.setSelectionRange(0, el.value.length);
|
|
133
|
+
el.type = originalType;
|
|
134
|
+
}, 0);
|
|
135
|
+
}
|
|
136
|
+
emit('focus', e);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function getPrecision() {
|
|
140
|
+
const modelDecimalPlaces = getDecimalPlaces(props.modelValue || 0);
|
|
141
|
+
const stepDecimalPlaces = getDecimalPlaces(props.steps);
|
|
142
|
+
|
|
143
|
+
return Math.max(modelDecimalPlaces, stepDecimalPlaces);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function subtract() {
|
|
147
|
+
const dp = getPrecision();
|
|
148
|
+
|
|
149
|
+
const current = props.modelValue !== null ? new Big(props.modelValue) : new Big(props.max || 0);
|
|
150
|
+
let result = current.sub(props.steps);
|
|
151
|
+
|
|
152
|
+
if (props.min !== undefined && result.lt(props.min)) {
|
|
153
|
+
result = new Big(props.min);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
emit('update:modelValue', Number(result.toFixed(dp)));
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function add() {
|
|
160
|
+
const dp = getPrecision();
|
|
161
|
+
|
|
162
|
+
const current = props.modelValue !== null ? new Big(props.modelValue) : new Big(props.min || 0);
|
|
163
|
+
let result = current.add(props.steps);
|
|
164
|
+
|
|
165
|
+
if (props.max !== undefined && result.gt(props.max)) {
|
|
166
|
+
result = new Big(props.max);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
emit('update:modelValue', Number(result.toFixed(dp)));
|
|
170
|
+
}
|
|
96
171
|
|
|
97
172
|
const isPrevButtonDisabled = computed(() => {
|
|
98
|
-
if (props.disabled) {
|
|
173
|
+
if (props.disabled || props.readonly) {
|
|
99
174
|
return true;
|
|
100
175
|
}
|
|
101
176
|
|
|
102
|
-
if (
|
|
177
|
+
if (props.modelValue === null) {
|
|
103
178
|
return false;
|
|
104
179
|
}
|
|
105
180
|
|
|
106
|
-
return props.min !== undefined ? Number(
|
|
181
|
+
return props.min !== undefined ? Number(props.modelValue) <= props.min : false;
|
|
107
182
|
});
|
|
183
|
+
|
|
108
184
|
const isNextButtonDisabled = computed(() => {
|
|
109
|
-
if (props.disabled) {
|
|
185
|
+
if (props.disabled || props.readonly) {
|
|
110
186
|
return true;
|
|
111
187
|
}
|
|
112
188
|
|
|
113
|
-
if (
|
|
189
|
+
if (props.modelValue === null) {
|
|
114
190
|
return false;
|
|
115
191
|
}
|
|
116
192
|
|
|
117
|
-
return props.max !== undefined ? Number(
|
|
193
|
+
return props.max !== undefined ? Number(props.modelValue) >= props.max : false;
|
|
118
194
|
});
|
|
119
195
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
handleEnumValidation(props.state, InputState, 'state');
|
|
123
|
-
});
|
|
196
|
+
function onButtonBlur(e: FocusEvent) {
|
|
197
|
+
isFocused.value = false;
|
|
124
198
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
199
|
+
if (props.modelValue !== null) {
|
|
200
|
+
let finalValue = props.modelValue;
|
|
201
|
+
const dp = getPrecision();
|
|
202
|
+
|
|
203
|
+
if (props.max !== undefined && finalValue > props.max) {
|
|
204
|
+
finalValue = props.max;
|
|
205
|
+
}
|
|
206
|
+
if (props.min !== undefined && finalValue < props.min) {
|
|
207
|
+
finalValue = props.min;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const roundedValue = Number(new Big(finalValue).toFixed(dp));
|
|
211
|
+
|
|
212
|
+
emit('update:modelValue', roundedValue);
|
|
213
|
+
|
|
214
|
+
if (_inputRef.value) {
|
|
215
|
+
_inputRef.value.value = roundedValue.toString();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
emit('validate', roundedValue);
|
|
136
219
|
}
|
|
220
|
+
|
|
221
|
+
emit('blur', e);
|
|
137
222
|
}
|
|
138
223
|
|
|
139
|
-
function
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
224
|
+
function onKeyDown(e: KeyboardEvent) {
|
|
225
|
+
if (e.ctrlKey || e.metaKey) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const allowedKeys = [
|
|
230
|
+
'Backspace',
|
|
231
|
+
'Delete',
|
|
232
|
+
'Tab',
|
|
233
|
+
'Escape',
|
|
234
|
+
'Enter',
|
|
235
|
+
'ArrowLeft',
|
|
236
|
+
'ArrowRight',
|
|
237
|
+
'ArrowUp',
|
|
238
|
+
'ArrowDown',
|
|
239
|
+
'Home',
|
|
240
|
+
'End',
|
|
241
|
+
];
|
|
242
|
+
|
|
243
|
+
if (allowedKeys.includes(e.key)) {
|
|
244
|
+
return;
|
|
150
245
|
}
|
|
151
|
-
}
|
|
152
246
|
|
|
153
|
-
|
|
154
|
-
|
|
247
|
+
if (!/^[0-9.-]$/.test(e.key)) {
|
|
248
|
+
e.preventDefault();
|
|
249
|
+
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
155
252
|
}
|
|
253
|
+
|
|
254
|
+
onMounted(() => {
|
|
255
|
+
handleEnumValidation(props.size, Size, 'size');
|
|
256
|
+
handleEnumValidation(props.state, InputState, 'state');
|
|
257
|
+
});
|
|
156
258
|
</script>
|
|
157
259
|
|
|
158
260
|
<template>
|
|
159
261
|
<AntField
|
|
160
262
|
:label="label"
|
|
263
|
+
:label-for="id"
|
|
161
264
|
:size="size"
|
|
162
265
|
:skeleton="skeleton"
|
|
163
266
|
:description="description"
|
|
@@ -185,7 +288,8 @@ function onButtonBlur() {
|
|
|
185
288
|
/>
|
|
186
289
|
|
|
187
290
|
<AntBaseInput
|
|
188
|
-
|
|
291
|
+
:id="id"
|
|
292
|
+
v-model="_modelValue"
|
|
189
293
|
v-model:input-ref="_inputRef"
|
|
190
294
|
:type="BaseInputType.number"
|
|
191
295
|
:grouped="indicators ? Grouped.center : Grouped.none"
|
|
@@ -193,6 +297,7 @@ function onButtonBlur() {
|
|
|
193
297
|
:state="state"
|
|
194
298
|
:size="size"
|
|
195
299
|
:skeleton="skeleton"
|
|
300
|
+
:step="steps"
|
|
196
301
|
:min="min"
|
|
197
302
|
:max="max"
|
|
198
303
|
:disabled="disabled"
|
|
@@ -200,7 +305,9 @@ function onButtonBlur() {
|
|
|
200
305
|
:placeholder="placeholder || label"
|
|
201
306
|
:show-icon="false"
|
|
202
307
|
v-bind="$attrs"
|
|
203
|
-
@
|
|
308
|
+
@focus="onInputFocus"
|
|
309
|
+
@blur="onButtonBlur"
|
|
310
|
+
@keydown="onKeyDown"
|
|
204
311
|
/>
|
|
205
312
|
|
|
206
313
|
<AntButton
|
|
@@ -61,6 +61,7 @@ const props = withDefaults(defineProps<{
|
|
|
61
61
|
inputRef?: null | HTMLInputElement;
|
|
62
62
|
min?: string | number;
|
|
63
63
|
max?: string | number;
|
|
64
|
+
step?: string | number;
|
|
64
65
|
}>(), {
|
|
65
66
|
state: InputState.base,
|
|
66
67
|
disabled: false,
|
|
@@ -73,6 +74,7 @@ const props = withDefaults(defineProps<{
|
|
|
73
74
|
default: false,
|
|
74
75
|
nullable: false,
|
|
75
76
|
inputRef: null,
|
|
77
|
+
step: 1,
|
|
76
78
|
});
|
|
77
79
|
const slot = useSlots();
|
|
78
80
|
const hasInputState = computed(() => props.skeleton || props.disabled);
|
|
@@ -161,13 +163,26 @@ const icon = computed(() => icons[props.state]);
|
|
|
161
163
|
const _modelValue = computed<string | number | null>({
|
|
162
164
|
get: () => props.modelValue,
|
|
163
165
|
set: (val: string | number | null) => {
|
|
164
|
-
if (props.type === BaseInputType.number
|
|
165
|
-
|
|
166
|
+
if (props.type === BaseInputType.number) {
|
|
167
|
+
if (val === '' || val === null || val === undefined) {
|
|
168
|
+
emit('update:modelValue', null);
|
|
169
|
+
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const num = Number(val);
|
|
174
|
+
|
|
175
|
+
if (!isNaN(num)) {
|
|
176
|
+
emit('update:modelValue', num);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return;
|
|
166
180
|
}
|
|
167
181
|
|
|
168
182
|
emit('update:modelValue', val);
|
|
169
183
|
},
|
|
170
184
|
});
|
|
185
|
+
|
|
171
186
|
const inputIconSize = computed(() => {
|
|
172
187
|
if (props.size === Size.xs || props.size === Size.xs2) {
|
|
173
188
|
return IconSize.xs;
|
|
@@ -270,6 +285,7 @@ function onClickClearIcon() {
|
|
|
270
285
|
:min="min"
|
|
271
286
|
:max="max"
|
|
272
287
|
title=""
|
|
288
|
+
:step="step"
|
|
273
289
|
v-bind="$attrs"
|
|
274
290
|
:data-e2e-state="state"
|
|
275
291
|
@blur="onBlur"
|
|
@@ -4,5 +4,8 @@ declare const meta: Meta<typeof AntNumberInput>;
|
|
|
4
4
|
export default meta;
|
|
5
5
|
type Story = StoryObj<typeof AntNumberInput>;
|
|
6
6
|
export declare const Docs: Story;
|
|
7
|
+
export declare const SelectAllOnFocus: Story;
|
|
8
|
+
export declare const PrecisionAndSteps: Story;
|
|
9
|
+
export declare const Limits: Story;
|
|
7
10
|
export declare const WithIndicators: Story;
|
|
8
11
|
export declare const Summary: Story;
|
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
module.exports = exports.WithIndicators = exports.Summary = exports.Docs = void 0;
|
|
6
|
+
module.exports = exports.WithIndicators = exports.Summary = exports.SelectAllOnFocus = exports.PrecisionAndSteps = exports.Limits = exports.Docs = void 0;
|
|
7
7
|
var _Size = require("../../../enums/Size.enum");
|
|
8
8
|
var _AntNumberInput = _interopRequireDefault(require("../AntNumberInput.vue"));
|
|
9
9
|
var _State = require("../../../enums/State.enum");
|
|
10
10
|
var _vue = require("vue");
|
|
11
11
|
var _AntFormGroup = _interopRequireDefault(require("../../forms/AntFormGroup.vue"));
|
|
12
12
|
var _AntFormGroupLabel = _interopRequireDefault(require("../../forms/AntFormGroupLabel.vue"));
|
|
13
|
+
var _test = require("@storybook/test");
|
|
13
14
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
15
|
const meta = {
|
|
15
16
|
title: "Inputs/Number Input",
|
|
@@ -47,11 +48,19 @@ const meta = {
|
|
|
47
48
|
}
|
|
48
49
|
}
|
|
49
50
|
},
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
steps: {
|
|
52
|
+
control: {
|
|
53
|
+
type: "number"
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
min: {
|
|
57
|
+
control: {
|
|
58
|
+
type: "number"
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
max: {
|
|
62
|
+
control: {
|
|
63
|
+
type: "number"
|
|
55
64
|
}
|
|
56
65
|
}
|
|
57
66
|
}
|
|
@@ -67,20 +76,17 @@ const Docs = exports.Docs = {
|
|
|
67
76
|
args
|
|
68
77
|
};
|
|
69
78
|
},
|
|
70
|
-
template:
|
|
71
|
-
<AntNumberInput
|
|
72
|
-
v-bind="args"
|
|
73
|
-
v-model="args.modelValue"
|
|
74
|
-
/>`
|
|
79
|
+
template: '<AntNumberInput v-bind="args" v-model="args.modelValue" />'
|
|
75
80
|
}),
|
|
76
81
|
args: {
|
|
77
82
|
modelValue: null,
|
|
78
83
|
steps: 1,
|
|
79
|
-
label: "
|
|
80
|
-
description: "
|
|
84
|
+
label: "Standard Number Input",
|
|
85
|
+
description: "Basic usage with manual entry or indicators",
|
|
86
|
+
onValidate: (0, _test.fn)()
|
|
81
87
|
}
|
|
82
88
|
};
|
|
83
|
-
const
|
|
89
|
+
const SelectAllOnFocus = exports.SelectAllOnFocus = {
|
|
84
90
|
render: args => ({
|
|
85
91
|
components: {
|
|
86
92
|
AntNumberInput: _AntNumberInput.default,
|
|
@@ -88,19 +94,112 @@ const WithIndicators = exports.WithIndicators = {
|
|
|
88
94
|
AntFormGroupLabel: _AntFormGroupLabel.default
|
|
89
95
|
},
|
|
90
96
|
setup() {
|
|
97
|
+
const val = (0, _vue.ref)(999.99);
|
|
91
98
|
return {
|
|
92
|
-
args
|
|
99
|
+
args,
|
|
100
|
+
val
|
|
93
101
|
};
|
|
94
102
|
},
|
|
95
103
|
template: `
|
|
96
|
-
<AntFormGroup>
|
|
97
|
-
<
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
104
|
+
<AntFormGroup class="w-80">
|
|
105
|
+
<AntFormGroupLabel>Select All on Focus</AntFormGroupLabel>
|
|
106
|
+
<AntNumberInput
|
|
107
|
+
v-bind="args"
|
|
108
|
+
v-model="val"
|
|
109
|
+
:selectAllOnFocus="true"
|
|
110
|
+
label="Price"
|
|
111
|
+
description="Click to select the entire number for quick replacement"
|
|
112
|
+
/>
|
|
113
|
+
</AntFormGroup>
|
|
114
|
+
`
|
|
115
|
+
})
|
|
116
|
+
};
|
|
117
|
+
const PrecisionAndSteps = exports.PrecisionAndSteps = {
|
|
118
|
+
render: args => ({
|
|
119
|
+
components: {
|
|
120
|
+
AntNumberInput: _AntNumberInput.default,
|
|
121
|
+
AntFormGroup: _AntFormGroup.default,
|
|
122
|
+
AntFormGroupLabel: _AntFormGroupLabel.default
|
|
123
|
+
},
|
|
124
|
+
setup() {
|
|
125
|
+
const intVal = (0, _vue.ref)(null);
|
|
126
|
+
const floatVal = (0, _vue.ref)(0.5);
|
|
127
|
+
return {
|
|
128
|
+
args,
|
|
129
|
+
intVal,
|
|
130
|
+
floatVal
|
|
131
|
+
};
|
|
132
|
+
},
|
|
133
|
+
template: `
|
|
134
|
+
<AntFormGroup direction="row">
|
|
135
|
+
<AntFormGroup>
|
|
136
|
+
<AntFormGroupLabel>Integer (Step 1)</AntFormGroupLabel>
|
|
137
|
+
<AntNumberInput v-bind="args" :steps="1" v-model="intVal" />
|
|
138
|
+
</AntFormGroup>
|
|
139
|
+
|
|
140
|
+
<AntFormGroup>
|
|
141
|
+
<AntFormGroupLabel>Currency Style (Step 0.01)</AntFormGroupLabel>
|
|
142
|
+
<AntNumberInput v-bind="args" :steps="0.01" v-model="floatVal" indicators />
|
|
143
|
+
</AntFormGroup>
|
|
144
|
+
|
|
145
|
+
<AntFormGroup>
|
|
146
|
+
<AntFormGroupLabel>High Precision (Step 0.0005)</AntFormGroupLabel>
|
|
147
|
+
<AntNumberInput v-bind="args" :steps="0.0005" v-model="floatVal" indicators />
|
|
102
148
|
</AntFormGroup>
|
|
103
149
|
</AntFormGroup>`
|
|
150
|
+
})
|
|
151
|
+
};
|
|
152
|
+
const Limits = exports.Limits = {
|
|
153
|
+
render: args => ({
|
|
154
|
+
components: {
|
|
155
|
+
AntNumberInput: _AntNumberInput.default,
|
|
156
|
+
AntFormGroup: _AntFormGroup.default,
|
|
157
|
+
AntFormGroupLabel: _AntFormGroupLabel.default
|
|
158
|
+
},
|
|
159
|
+
setup() {
|
|
160
|
+
const limitedVal = (0, _vue.ref)(5);
|
|
161
|
+
return {
|
|
162
|
+
args,
|
|
163
|
+
limitedVal
|
|
164
|
+
};
|
|
165
|
+
},
|
|
166
|
+
template: `
|
|
167
|
+
<AntFormGroup class="w-96">
|
|
168
|
+
<AntFormGroupLabel>Min: {{ args.min }} | Max: {{ args.max }}</AntFormGroupLabel>
|
|
169
|
+
<AntNumberInput
|
|
170
|
+
v-bind="args"
|
|
171
|
+
v-model="limitedVal"
|
|
172
|
+
label="Try to exceed limits"
|
|
173
|
+
/>
|
|
174
|
+
</AntFormGroup>`
|
|
175
|
+
}),
|
|
176
|
+
args: {
|
|
177
|
+
min: 0,
|
|
178
|
+
max: 10,
|
|
179
|
+
indicators: true,
|
|
180
|
+
limiter: true
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
const WithIndicators = exports.WithIndicators = {
|
|
184
|
+
render: args => ({
|
|
185
|
+
components: {
|
|
186
|
+
AntNumberInput: _AntNumberInput.default,
|
|
187
|
+
AntFormGroup: _AntFormGroup.default
|
|
188
|
+
},
|
|
189
|
+
setup() {
|
|
190
|
+
const val1 = (0, _vue.ref)(null);
|
|
191
|
+
const val2 = (0, _vue.ref)(null);
|
|
192
|
+
return {
|
|
193
|
+
args,
|
|
194
|
+
val1,
|
|
195
|
+
val2
|
|
196
|
+
};
|
|
197
|
+
},
|
|
198
|
+
template: `
|
|
199
|
+
<AntFormGroup direction="column">
|
|
200
|
+
<AntNumberInput v-bind="args" v-model="val1" label="Step 1" :steps="1"/>
|
|
201
|
+
<AntNumberInput v-bind="args" v-model="val2" label="Step 0.0001" :steps="0.0001"/>
|
|
202
|
+
</AntFormGroup>`
|
|
104
203
|
}),
|
|
105
204
|
args: {
|
|
106
205
|
...Docs.args,
|
|
@@ -10,6 +10,9 @@ import {
|
|
|
10
10
|
} from "vue";
|
|
11
11
|
import AntFormGroup from "../../forms/AntFormGroup.vue";
|
|
12
12
|
import AntFormGroupLabel from "../../forms/AntFormGroupLabel.vue";
|
|
13
|
+
import {
|
|
14
|
+
fn
|
|
15
|
+
} from "@storybook/test";
|
|
13
16
|
const meta = {
|
|
14
17
|
title: "Inputs/Number Input",
|
|
15
18
|
component: AntNumberInput,
|
|
@@ -46,11 +49,19 @@ const meta = {
|
|
|
46
49
|
}
|
|
47
50
|
}
|
|
48
51
|
},
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
steps: {
|
|
53
|
+
control: {
|
|
54
|
+
type: "number"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
min: {
|
|
58
|
+
control: {
|
|
59
|
+
type: "number"
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
max: {
|
|
63
|
+
control: {
|
|
64
|
+
type: "number"
|
|
54
65
|
}
|
|
55
66
|
}
|
|
56
67
|
}
|
|
@@ -66,20 +77,17 @@ export const Docs = {
|
|
|
66
77
|
args
|
|
67
78
|
};
|
|
68
79
|
},
|
|
69
|
-
template:
|
|
70
|
-
<AntNumberInput
|
|
71
|
-
v-bind="args"
|
|
72
|
-
v-model="args.modelValue"
|
|
73
|
-
/>`
|
|
80
|
+
template: '<AntNumberInput v-bind="args" v-model="args.modelValue" />'
|
|
74
81
|
}),
|
|
75
82
|
args: {
|
|
76
83
|
modelValue: null,
|
|
77
84
|
steps: 1,
|
|
78
|
-
label: "
|
|
79
|
-
description: "
|
|
85
|
+
label: "Standard Number Input",
|
|
86
|
+
description: "Basic usage with manual entry or indicators",
|
|
87
|
+
onValidate: fn()
|
|
80
88
|
}
|
|
81
89
|
};
|
|
82
|
-
export const
|
|
90
|
+
export const SelectAllOnFocus = {
|
|
83
91
|
render: (args) => ({
|
|
84
92
|
components: {
|
|
85
93
|
AntNumberInput,
|
|
@@ -87,18 +95,111 @@ export const WithIndicators = {
|
|
|
87
95
|
AntFormGroupLabel
|
|
88
96
|
},
|
|
89
97
|
setup() {
|
|
98
|
+
const val = ref(999.99);
|
|
90
99
|
return {
|
|
91
|
-
args
|
|
100
|
+
args,
|
|
101
|
+
val
|
|
92
102
|
};
|
|
93
103
|
},
|
|
94
104
|
template: `
|
|
95
|
-
<AntFormGroup>
|
|
96
|
-
<
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
105
|
+
<AntFormGroup class="w-80">
|
|
106
|
+
<AntFormGroupLabel>Select All on Focus</AntFormGroupLabel>
|
|
107
|
+
<AntNumberInput
|
|
108
|
+
v-bind="args"
|
|
109
|
+
v-model="val"
|
|
110
|
+
:selectAllOnFocus="true"
|
|
111
|
+
label="Price"
|
|
112
|
+
description="Click to select the entire number for quick replacement"
|
|
113
|
+
/>
|
|
114
|
+
</AntFormGroup>
|
|
115
|
+
`
|
|
116
|
+
})
|
|
117
|
+
};
|
|
118
|
+
export const PrecisionAndSteps = {
|
|
119
|
+
render: (args) => ({
|
|
120
|
+
components: {
|
|
121
|
+
AntNumberInput,
|
|
122
|
+
AntFormGroup,
|
|
123
|
+
AntFormGroupLabel
|
|
124
|
+
},
|
|
125
|
+
setup() {
|
|
126
|
+
const intVal = ref(null);
|
|
127
|
+
const floatVal = ref(0.5);
|
|
128
|
+
return {
|
|
129
|
+
args,
|
|
130
|
+
intVal,
|
|
131
|
+
floatVal
|
|
132
|
+
};
|
|
133
|
+
},
|
|
134
|
+
template: `
|
|
135
|
+
<AntFormGroup direction="row">
|
|
136
|
+
<AntFormGroup>
|
|
137
|
+
<AntFormGroupLabel>Integer (Step 1)</AntFormGroupLabel>
|
|
138
|
+
<AntNumberInput v-bind="args" :steps="1" v-model="intVal" />
|
|
139
|
+
</AntFormGroup>
|
|
140
|
+
|
|
141
|
+
<AntFormGroup>
|
|
142
|
+
<AntFormGroupLabel>Currency Style (Step 0.01)</AntFormGroupLabel>
|
|
143
|
+
<AntNumberInput v-bind="args" :steps="0.01" v-model="floatVal" indicators />
|
|
101
144
|
</AntFormGroup>
|
|
145
|
+
|
|
146
|
+
<AntFormGroup>
|
|
147
|
+
<AntFormGroupLabel>High Precision (Step 0.0005)</AntFormGroupLabel>
|
|
148
|
+
<AntNumberInput v-bind="args" :steps="0.0005" v-model="floatVal" indicators />
|
|
149
|
+
</AntFormGroup>
|
|
150
|
+
</AntFormGroup>`
|
|
151
|
+
})
|
|
152
|
+
};
|
|
153
|
+
export const Limits = {
|
|
154
|
+
render: (args) => ({
|
|
155
|
+
components: {
|
|
156
|
+
AntNumberInput,
|
|
157
|
+
AntFormGroup,
|
|
158
|
+
AntFormGroupLabel
|
|
159
|
+
},
|
|
160
|
+
setup() {
|
|
161
|
+
const limitedVal = ref(5);
|
|
162
|
+
return {
|
|
163
|
+
args,
|
|
164
|
+
limitedVal
|
|
165
|
+
};
|
|
166
|
+
},
|
|
167
|
+
template: `
|
|
168
|
+
<AntFormGroup class="w-96">
|
|
169
|
+
<AntFormGroupLabel>Min: {{ args.min }} | Max: {{ args.max }}</AntFormGroupLabel>
|
|
170
|
+
<AntNumberInput
|
|
171
|
+
v-bind="args"
|
|
172
|
+
v-model="limitedVal"
|
|
173
|
+
label="Try to exceed limits"
|
|
174
|
+
/>
|
|
175
|
+
</AntFormGroup>`
|
|
176
|
+
}),
|
|
177
|
+
args: {
|
|
178
|
+
min: 0,
|
|
179
|
+
max: 10,
|
|
180
|
+
indicators: true,
|
|
181
|
+
limiter: true
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
export const WithIndicators = {
|
|
185
|
+
render: (args) => ({
|
|
186
|
+
components: {
|
|
187
|
+
AntNumberInput,
|
|
188
|
+
AntFormGroup
|
|
189
|
+
},
|
|
190
|
+
setup() {
|
|
191
|
+
const val1 = ref(null);
|
|
192
|
+
const val2 = ref(null);
|
|
193
|
+
return {
|
|
194
|
+
args,
|
|
195
|
+
val1,
|
|
196
|
+
val2
|
|
197
|
+
};
|
|
198
|
+
},
|
|
199
|
+
template: `
|
|
200
|
+
<AntFormGroup direction="column">
|
|
201
|
+
<AntNumberInput v-bind="args" v-model="val1" label="Step 1" :steps="1"/>
|
|
202
|
+
<AntNumberInput v-bind="args" v-model="val2" label="Step 0.0001" :steps="0.0001"/>
|
|
102
203
|
</AntFormGroup>`
|
|
103
204
|
}),
|
|
104
205
|
args: {
|