@antify/ui 4.1.37 → 4.1.38

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.
@@ -0,0 +1,289 @@
1
+ import AntCountryInput from "../AntCountryInput.vue";
2
+ import AntField from "../../../components/forms/AntField.vue";
3
+ import {
4
+ ref
5
+ } from "vue";
6
+ import {
7
+ InputState,
8
+ Size,
9
+ Grouped
10
+ } from "../../../enums/index.mjs";
11
+ import {
12
+ COUNTRIES,
13
+ CountryValueKey,
14
+ Locale
15
+ } from "../../../constants/countries.mjs";
16
+ const meta = {
17
+ title: "Inputs/Country Input",
18
+ component: AntCountryInput,
19
+ parameters: {
20
+ controls: {
21
+ sort: "requiredFirst"
22
+ }
23
+ },
24
+ argTypes: {
25
+ state: {
26
+ control: "select",
27
+ options: Object.values(InputState)
28
+ },
29
+ size: {
30
+ control: "select",
31
+ options: Object.values(Size)
32
+ },
33
+ grouped: {
34
+ control: {
35
+ type: "select"
36
+ },
37
+ options: Object.values(Grouped),
38
+ description: "Where is this fields position in a group"
39
+ },
40
+ locale: {
41
+ control: {
42
+ type: "select"
43
+ },
44
+ options: Object.values(Locale),
45
+ description: "Language for country labels"
46
+ },
47
+ optionValueKey: {
48
+ control: {
49
+ type: "select"
50
+ },
51
+ options: Object.values(CountryValueKey)
52
+ },
53
+ countries: {
54
+ table: {
55
+ disable: true
56
+ }
57
+ }
58
+ }
59
+ };
60
+ export default meta;
61
+ const MainRender = (args) => ({
62
+ components: {
63
+ AntCountryInput
64
+ },
65
+ setup() {
66
+ const modelValue = ref(args.modelValue);
67
+ return {
68
+ args,
69
+ modelValue
70
+ };
71
+ },
72
+ template: `
73
+ <div>
74
+ <AntCountryInput v-bind="args" v-model="modelValue" />
75
+
76
+ <div class="mt-2 text-md text-base-400">
77
+ Selected Value ({{ args.optionValueKey || 'default' }}):
78
+ <span class="text-blue-500 font-bold">{{ modelValue === null ? 'null' : modelValue }}</span>
79
+ </div>
80
+ </div>
81
+ `
82
+ });
83
+ export const Docs = {
84
+ render: MainRender,
85
+ args: {
86
+ modelValue: null,
87
+ searchable: true,
88
+ countries: COUNTRIES
89
+ }
90
+ };
91
+ export const ValueKeyNumericCode = {
92
+ render: MainRender,
93
+ args: {
94
+ ...Docs.args,
95
+ label: "Value as Numeric Code",
96
+ description: "Using the numericCode field from the data as the model value.",
97
+ optionValueKey: CountryValueKey.numericCode,
98
+ countries: COUNTRIES
99
+ }
100
+ };
101
+ export const DefaultCountry = {
102
+ render: MainRender,
103
+ args: {
104
+ ...Docs.args,
105
+ label: "Default Country Logic",
106
+ description: 'Preselects Germany (DE) by providing modelValue: "DE" to the component.',
107
+ modelValue: "DE"
108
+ }
109
+ };
110
+ export const DefaultByNumericCode = {
111
+ render: MainRender,
112
+ args: {
113
+ ...Docs.args,
114
+ label: "Default by Numeric Code",
115
+ description: "Using numericCode: 33 (France) as the default value.",
116
+ optionValueKey: CountryValueKey.numericCode,
117
+ modelValue: 33
118
+ }
119
+ };
120
+ export const Localization = {
121
+ render: (args) => ({
122
+ components: {
123
+ AntCountryInput
124
+ },
125
+ setup() {
126
+ const modelValue = ref("DE");
127
+ return {
128
+ args,
129
+ modelValue
130
+ };
131
+ },
132
+ template: `
133
+ <div class="flex flex-col gap-4">
134
+ <div>
135
+ <p class="text-xs text-base-400 mb-1">Current Locale: <b>{{ args.locale }}</b></p>
136
+ <AntCountryInput v-bind="args" v-model="modelValue" />
137
+ </div>
138
+
139
+ <div class="p-4 border border-dashed border-base-300 rounded-md bg-base-50">
140
+ <p class="text-sm italic text-base-500">
141
+ Try switching the <b>locale</b> control in the panel below to see labels change between
142
+ "Germany" (EN) and "Deutschland" (DE).
143
+ </p>
144
+ </div>
145
+ </div>
146
+ `
147
+ }),
148
+ args: {
149
+ ...Docs.args,
150
+ label: "Localized Selector",
151
+ locale: Locale.de,
152
+ searchPlaceholder: "Land suchen...",
153
+ description: "The labels and search logic adapt based on the provided locale."
154
+ }
155
+ };
156
+ export const WithoutSearch = {
157
+ render: MainRender,
158
+ args: {
159
+ ...Docs.args,
160
+ label: "No Search Field",
161
+ searchable: false
162
+ }
163
+ };
164
+ export const WithoutFlags = {
165
+ render: MainRender,
166
+ args: {
167
+ ...Docs.args,
168
+ label: "No Flags Mode",
169
+ showFlags: false
170
+ }
171
+ };
172
+ export const GroupedMode = {
173
+ render: (args) => ({
174
+ components: {
175
+ AntCountryInput,
176
+ AntField
177
+ },
178
+ setup() {
179
+ const modelValue = ref(args.modelValue);
180
+ return {
181
+ args,
182
+ modelValue
183
+ };
184
+ },
185
+ template: `
186
+ <div>
187
+ <AntField
188
+ :label="args.label"
189
+ :description="args.description"
190
+ :size="args.size"
191
+ :state="args.state"
192
+ >
193
+ <div class="flex items-center">
194
+ <AntCountryInput
195
+ v-bind="args"
196
+ v-model="modelValue"
197
+ class="w-fit flex-shrink-0"
198
+ />
199
+
200
+ <div
201
+ class="flex-grow border border-l-0 p-2 text-sm text-base-400 bg-base-50 border-base-300 rounded-r-md h-[36px] flex items-center"
202
+ >
203
+ Input area...
204
+ </div>
205
+ </div>
206
+ </AntField>
207
+
208
+ <div class="mt-2 text-md text-base-400">
209
+ Value: {{ modelValue || null }}
210
+ </div>
211
+ </div>
212
+ `
213
+ }),
214
+ args: {
215
+ ...Docs.args,
216
+ label: "Grouped Mode (Phone Input Style)",
217
+ description: "When isGrouped is true, label and description must be provided by a parent AntField.",
218
+ isGrouped: true,
219
+ grouped: Grouped.left,
220
+ modelValue: "DE",
221
+ countries: COUNTRIES
222
+ }
223
+ };
224
+ export const GermanEmptyState = {
225
+ render: MainRender,
226
+ args: {
227
+ ...Docs.args,
228
+ label: "German Empty State",
229
+ description: 'Custom empty state message: "Keine L\xE4nder gefunden". Open the dropdown to see it.',
230
+ searchPlaceholder: "Land suchen...",
231
+ emptyStateMessage: "Keine L\xE4nder gefunden",
232
+ countries: []
233
+ }
234
+ };
235
+ export const Skeleton = {
236
+ render: MainRender,
237
+ args: {
238
+ ...Docs.args,
239
+ skeleton: true
240
+ }
241
+ };
242
+ export const summary = {
243
+ parameters: {
244
+ chromatic: {
245
+ disableSnapshot: false
246
+ }
247
+ },
248
+ render: (args) => ({
249
+ components: {
250
+ AntCountryInput
251
+ },
252
+ setup() {
253
+ const val = ref("DE");
254
+ return {
255
+ args,
256
+ val,
257
+ InputState,
258
+ Size,
259
+ COUNTRIES
260
+ };
261
+ },
262
+ template: `
263
+ <div class="p-4 flex flex-col gap-6">
264
+ <div class="flex flex-wrap gap-4">
265
+ <AntCountryInput v-bind="args" v-model="val" :countries="COUNTRIES" :state="InputState.base" label="Base" class="w-64"/>
266
+ <AntCountryInput v-bind="args" v-model="val" :countries="COUNTRIES" :state="InputState.info" label="Info" class="w-64"/>
267
+ <AntCountryInput v-bind="args" v-model="val" :countries="COUNTRIES" :state="InputState.success" label="Success" class="w-64"/>
268
+ <AntCountryInput v-bind="args" v-model="val" :countries="COUNTRIES" :state="InputState.warning" label="Warning" class="w-64"/>
269
+ <AntCountryInput v-bind="args" v-model="val" :countries="COUNTRIES" :state="InputState.danger" label="Danger" class="w-64"/>
270
+ </div>
271
+
272
+ <div class="flex items-end gap-4">
273
+ <AntCountryInput v-bind="args" v-model="val" :countries="COUNTRIES" :size="Size.sm" label="Small" class="w-64"/>
274
+ <AntCountryInput v-bind="args" v-model="val" :countries="COUNTRIES" :size="Size.md" label="Medium" class="w-64"/>
275
+ <AntCountryInput v-bind="args" v-model="val" :countries="COUNTRIES" :size="Size.lg" label="Large" class="w-64"/>
276
+ </div>
277
+
278
+ <div class="flex gap-4">
279
+ <AntCountryInput v-bind="args" :countries="COUNTRIES" model-value="FR" disabled label="Disabled" class="w-64" />
280
+ <AntCountryInput v-bind="args" :countries="COUNTRIES" model-value="FR" readonly label="Readonly" class="w-64" />
281
+ <AntCountryInput v-bind="args" :countries="COUNTRIES" model-value="FR" skeleton label="Skeleton" class="w-64" />
282
+ </div>
283
+ </div>
284
+ `
285
+ }),
286
+ args: {
287
+ searchPlaceholder: "Search..."
288
+ }
289
+ };
@@ -0,0 +1,7 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3';
2
+ import AntPhoneNumberInput from '../AntPhoneNumberInput.vue';
3
+ declare const meta: Meta<typeof AntPhoneNumberInput>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof AntPhoneNumberInput>;
6
+ export declare const Default: Story;
7
+ export declare const summary: Story;
@@ -0,0 +1,303 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.summary = exports.default = exports.Default = void 0;
7
+ var _AntPhoneNumberInput = _interopRequireDefault(require("../AntPhoneNumberInput.vue"));
8
+ var _enums = require("../../../enums");
9
+ var _vue = require("vue");
10
+ var _countries = require("../../../constants/countries");
11
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
+ const meta = {
13
+ title: "Inputs/Phone Number Input",
14
+ component: _AntPhoneNumberInput.default,
15
+ parameters: {
16
+ docs: {
17
+ description: {
18
+ component: "Komponente zur Eingabe der Telefonnummer mit Auswahl von Land und L\xE4ndervorwahl."
19
+ }
20
+ }
21
+ },
22
+ argTypes: {
23
+ size: {
24
+ control: {
25
+ type: "select"
26
+ },
27
+ options: Object.values(_enums.Size)
28
+ },
29
+ state: {
30
+ control: {
31
+ type: "select"
32
+ },
33
+ options: Object.values(_enums.InputState)
34
+ },
35
+ onValidate: {
36
+ action: "validate"
37
+ },
38
+ nullable: {
39
+ control: "boolean",
40
+ description: "Shows the clear icon in the input field."
41
+ },
42
+ locale: {
43
+ control: {
44
+ type: "select"
45
+ },
46
+ options: Object.values(_countries.Locale),
47
+ description: "Language for country names translation"
48
+ },
49
+ countryValueKey: {
50
+ control: {
51
+ type: "select"
52
+ },
53
+ options: Object.values(_countries.CountryValueKey)
54
+ },
55
+ countries: {
56
+ table: {
57
+ disable: true
58
+ }
59
+ }
60
+ }
61
+ };
62
+ module.exports = meta;
63
+ const Default = exports.Default = {
64
+ render: args => ({
65
+ components: {
66
+ AntPhoneNumberInput: _AntPhoneNumberInput.default
67
+ },
68
+ setup() {
69
+ const phoneDefault = (0, _vue.ref)(null);
70
+ const countryDefault = (0, _vue.ref)("DE");
71
+ const phoneNumericDefault = (0, _vue.ref)(null);
72
+ const countryNumericDefault = (0, _vue.ref)(49);
73
+ const phone1 = (0, _vue.ref)(null);
74
+ const country1 = (0, _vue.ref)(null);
75
+ const phone2 = (0, _vue.ref)(null);
76
+ const country2 = (0, _vue.ref)(null);
77
+ const phone3 = (0, _vue.ref)(null);
78
+ const country3 = (0, _vue.ref)(null);
79
+ const phone4 = (0, _vue.ref)("123456");
80
+ const country4 = (0, _vue.ref)("DE");
81
+ const phonePaste = (0, _vue.ref)(null);
82
+ const countryPaste = (0, _vue.ref)(null);
83
+ const copyToClipboard = async text => {
84
+ await navigator.clipboard?.writeText(text).catch(err => {
85
+ console.warn("Copy failed", err);
86
+ });
87
+ };
88
+ return {
89
+ args,
90
+ phoneDefault,
91
+ countryDefault,
92
+ phoneNumericDefault,
93
+ countryNumericDefault,
94
+ phone1,
95
+ country1,
96
+ phone2,
97
+ country2,
98
+ phone3,
99
+ country3,
100
+ phone4,
101
+ country4,
102
+ phonePaste,
103
+ countryPaste,
104
+ copyToClipboard
105
+ };
106
+ },
107
+ template: `
108
+ <div class="grid grid-cols-2 gap-x-12 gap-y-12">
109
+ <div>
110
+ <h3 class="mb-2 text-sm font-bold text-for-white-bg-font uppercase tracking-wider">Default Country Prop</h3>
111
+ <p class="mb-2 text-xs text-base-400 italic text-wrap">
112
+ Initial values are null. Component selects Germany via <b>default-country-value="DE"</b> using the default "value" key.
113
+ </p>
114
+ <AntPhoneNumberInput
115
+ v-bind="args"
116
+ v-model="phoneDefault"
117
+ :locale="args.locale"
118
+ country-value-key="value"
119
+ v-model:country-value="countryDefault"
120
+ placeholder="Initialized with DE"
121
+ />
122
+ <div class="mt-2 text-md text-for-white-bg-font">
123
+ Data: {{ countryDefault || 'null' }} | {{ phoneDefault || 'null' }}
124
+ </div>
125
+ </div>
126
+
127
+ <div>
128
+ <h3 class="mb-2 text-sm font-bold text-for-white-bg-font uppercase tracking-wider">Default by Numeric Code (49)</h3>
129
+ <p class="mb-2 text-xs text-base-400 italic text-wrap">
130
+ Initial values are null. Component selects Germany via <b>numericCode: 49</b>. We tell the component to use "numericCode" as the value key.
131
+ </p>
132
+ <AntPhoneNumberInput
133
+ v-bind="args"
134
+ v-model="phoneNumericDefault"
135
+ v-model:country-value="countryNumericDefault"
136
+ country-value-key="numericCode"
137
+ placeholder="Initialized with 49"
138
+ />
139
+ <div class="mt-2 text-md text-for-white-bg-font">
140
+ Data: {{ countryNumericDefault || 'null' }} | {{ phoneNumericDefault || 'null' }}
141
+ </div>
142
+ </div>
143
+
144
+ <div>
145
+ <h3 class="mb-2 text-sm font-bold text-for-white-bg-font uppercase tracking-wider">Auto-detect Country on Paste</h3>
146
+ <p class="mb-2 text-xs text-base-400 italic text-wrap">
147
+ Click a number to copy, then paste it (Ctrl+V) into the input to see auto-detection in action.
148
+ </p>
149
+
150
+ <div class="flex gap-2 mb-4">
151
+ <button
152
+ v-for="num in ['+4915211111111', '+3715211111111', '+3725211111111']"
153
+ @click="copyToClipboard(num)"
154
+ class="px-2 py-1 text-xs bg-white border border-base-300 rounded hover:bg-base-100 transition-colors text-for-white-bg-font"
155
+ title="Click to copy"
156
+ >
157
+ {{ num }}
158
+ </button>
159
+ </div>
160
+
161
+ <AntPhoneNumberInput
162
+ v-bind="args"
163
+ v-model="phonePaste"
164
+ v-model:country-value="countryPaste"
165
+ placeholder="Paste a number starting with +..."
166
+ />
167
+
168
+ <div class="mt-2 text-md text-for-white-bg-font">
169
+ Data: {{ countryPaste || 'null' }} | {{ phonePaste || 'null' }}
170
+ </div>
171
+ </div>
172
+
173
+ <div>
174
+ <h3 class="mb-2 text-sm font-bold text-for-white-bg-font uppercase tracking-wider">Keep Country on Clear</h3>
175
+ <p class="mb-2 text-xs text-base-400 italic text-wrap">
176
+ Try clicking the "X" icon. The phone number will be null, but the country (DE) will remain selected.
177
+ </p>
178
+ <AntPhoneNumberInput
179
+ v-bind="args"
180
+ v-model="phone4"
181
+ v-model:country-value="country4"
182
+ :nullable="true"
183
+ country-value-key="value"
184
+ />
185
+ <div class="mt-2 text-md text-for-white-bg-font">
186
+ Data: {{ country4 || 'null' }} | {{ phone4 || 'null' }}
187
+ </div>
188
+ </div>
189
+
190
+ <div>
191
+ <h3 class="mb-2 text-sm font-bold text-for-white-bg-font uppercase tracking-wider">With Search (Default)</h3>
192
+ <AntPhoneNumberInput
193
+ v-bind="args"
194
+ v-model="phone1"
195
+ v-model:country-value="country1"
196
+ />
197
+ <div class="mt-2 text-md text-for-white-bg-font">
198
+ Data: {{ country1 || 'null' }} | {{ phone1 || 'null' }}
199
+ </div>
200
+ </div>
201
+
202
+ <div>
203
+ <h3 class="mb-2 text-sm font-bold text-for-white-bg-font uppercase tracking-wider">Without Search</h3>
204
+ <AntPhoneNumberInput
205
+ v-bind="args"
206
+ v-model="phone2"
207
+ v-model:country-value="country2"
208
+ :searchable="false"
209
+ />
210
+ <div class="mt-2 text-md text-for-white-bg-font">
211
+ Data: {{ country2 || 'null' }} | {{ phone2 || 'null' }}
212
+ </div>
213
+ </div>
214
+
215
+ <div>
216
+ <h3 class="mb-2 text-sm font-bold text-for-white-bg-font uppercase tracking-wider">Numeric Code Output</h3>
217
+ <AntPhoneNumberInput
218
+ v-bind="args"
219
+ v-model="phone3"
220
+ v-model:country-value="country3"
221
+ country-value-key="numericCode"
222
+ country-placeholder="Select for numeric output"
223
+ />
224
+ <div class="mt-2 text-md text-for-white-bg-font">
225
+ Data: {{ country3 || 'null' }} | {{ phone3 || 'null' }}
226
+ </div>
227
+ </div>
228
+ </div>
229
+ `
230
+ }),
231
+ args: {
232
+ label: "Phone Number",
233
+ description: "Enter your mobile phone number",
234
+ placeholder: "Enter digits",
235
+ countryPlaceholder: "Select your country",
236
+ countries: _countries.COUNTRIES,
237
+ size: _enums.Size.md,
238
+ state: _enums.InputState.base,
239
+ nullable: true,
240
+ locale: _countries.Locale.de
241
+ }
242
+ };
243
+ const summary = exports.summary = {
244
+ parameters: {
245
+ chromatic: {
246
+ disableSnapshot: false
247
+ }
248
+ },
249
+ render: args => ({
250
+ components: {
251
+ AntPhoneNumberInput: _AntPhoneNumberInput.default
252
+ },
253
+ setup() {
254
+ const phone = (0, _vue.ref)(null);
255
+ const country = (0, _vue.ref)("+49");
256
+ return {
257
+ args,
258
+ phone,
259
+ country,
260
+ InputState: _enums.InputState,
261
+ Size: _enums.Size,
262
+ COUNTRIES: _countries.COUNTRIES
263
+ };
264
+ },
265
+ template: `
266
+ <div class="flex flex-col gap-4">
267
+ <div class="flex flex-col gap-4">
268
+ <h2 class="text-xl font-bold border-b pb-2 text-base-700">Phone Number Input States</h2>
269
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
270
+ <AntPhoneNumberInput v-bind="args" v-model="phone" v-model:country-value="country" :state="InputState.base" label="Base State" />
271
+ <AntPhoneNumberInput v-bind="args" v-model="phone" v-model:country-value="country" :state="InputState.info" label="Info State" :messages="['Bitte geben Sie Ihre Mobilnummer ein']" />
272
+ <AntPhoneNumberInput v-bind="args" v-model="phone" v-model:country-value="country" :state="InputState.success" label="Success State" />
273
+ <AntPhoneNumberInput v-bind="args" v-model="phone" v-model:country-value="country" :state="InputState.warning" label="Warning State" :messages="['Pr\xFCfen Sie die Vorwahl']" />
274
+ <AntPhoneNumberInput v-bind="args" v-model="phone" v-model:country-value="country" :state="InputState.danger" label="Danger State" :messages="['Ung\xFCltige Telefonnummer']" />
275
+ </div>
276
+ </div>
277
+
278
+ <div class="flex flex-col gap-4">
279
+ <h2 class="text-xl font-bold border-b pb-2 text-base-700">Sizes</h2>
280
+ <div class="flex flex-col gap-4">
281
+ <AntPhoneNumberInput v-bind="args" v-model="phone" v-model:country-value="country" :size="Size.sm" label="Small (sm)" />
282
+ <AntPhoneNumberInput v-bind="args" v-model="phone" v-model:country-value="country" :size="Size.md" label="Medium (md)" />
283
+ <AntPhoneNumberInput v-bind="args" v-model="phone" v-model:country-value="country" :size="Size.lg" label="Large (lg)" />
284
+ </div>
285
+ </div>
286
+
287
+ <div class="flex flex-col gap-4">
288
+ <h2 class="text-xl font-bold border-b pb-2 text-base-700">Special Modes</h2>
289
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-8">
290
+ <AntPhoneNumberInput v-bind="args" v-model="phone" country-value="DE" model-value="1512345678" disabled label="Disabled" />
291
+ <AntPhoneNumberInput v-bind="args" v-model="phone" country-value="DE" model-value="1512345678" readonly label="Readonly" />
292
+ <AntPhoneNumberInput v-bind="args" v-model="phone" country-value="DE" skeleton label="Skeleton" />
293
+ </div>
294
+ </div>
295
+ </div>
296
+ `
297
+ }),
298
+ args: {
299
+ countries: _countries.COUNTRIES,
300
+ countryPlaceholder: "Land w\xE4hlen",
301
+ searchPlaceholder: "Suchen..."
302
+ }
303
+ };