@bethinkpl/design-system 43.0.0 → 44.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/design-system.css +1 -1
  2. package/dist/design-system.js +11664 -11121
  3. package/dist/design-system.js.map +1 -1
  4. package/dist/lib/js/components/Form/PinInputField/PinInputField.consts.d.ts +14 -0
  5. package/dist/lib/js/components/Form/PinInputField/PinInputField.types.d.ts +12 -0
  6. package/dist/lib/js/components/Form/PinInputField/PinInputField.utils.d.ts +2 -0
  7. package/dist/lib/js/components/Form/PinInputField/PinInputField.vue.d.ts +91 -0
  8. package/dist/lib/js/components/Form/PinInputField/index.d.ts +5 -0
  9. package/dist/lib/js/components/Form/PinInputField/usePinInputFieldWithinForm.d.ts +8 -0
  10. package/dist/lib/js/components/Form/TextAreaField/TextAreaField.types.d.ts +9 -0
  11. package/dist/lib/js/components/Form/TextAreaField/TextAreaField.vue.d.ts +76 -0
  12. package/dist/lib/js/components/Form/TextAreaField/TextAreaFieldAutosized.vue.d.ts +6 -0
  13. package/dist/lib/js/components/Form/TextAreaField/index.d.ts +4 -0
  14. package/dist/lib/js/components/LabelValue/LabelValueItem/LabelValueItem.vue.d.ts +12 -1
  15. package/dist/lib/js/components/Toast/Toast.consts.d.ts +11 -9
  16. package/dist/lib/js/components/Toast/Toast.vue.d.ts +51 -433
  17. package/dist/lib/js/{components/Form/InputField/useInputFieldWithinForm.d.ts → composables/useTextFieldWithinForm.d.ts} +1 -1
  18. package/dist/lib/js/index.d.ts +4 -0
  19. package/lib/js/components/Form/CheckboxGroupField/CheckboxGroupField.spec.ts +15 -0
  20. package/lib/js/components/Form/CheckboxGroupField/CheckboxGroupField.vue +5 -2
  21. package/lib/js/components/Form/Form.stories.ts +23 -2
  22. package/lib/js/components/Form/InputField/InputField.spec.ts +11 -1
  23. package/lib/js/components/Form/InputField/InputField.vue +7 -4
  24. package/lib/js/components/Form/PinInputField/PinInputField.consts.ts +18 -0
  25. package/lib/js/components/Form/PinInputField/PinInputField.spec.ts +394 -0
  26. package/lib/js/components/Form/PinInputField/PinInputField.stories.ts +124 -0
  27. package/lib/js/components/Form/PinInputField/PinInputField.types.ts +42 -0
  28. package/lib/js/components/Form/PinInputField/PinInputField.utils.ts +5 -0
  29. package/lib/js/components/Form/PinInputField/PinInputField.vue +211 -0
  30. package/lib/js/components/Form/PinInputField/index.ts +6 -0
  31. package/lib/js/components/Form/PinInputField/usePinInputFieldWithinForm.ts +29 -0
  32. package/lib/js/components/Form/SelectField/SelectField.stories.ts +0 -5
  33. package/lib/js/components/Form/SelectField/useSelectFieldWithinForm.ts +1 -1
  34. package/lib/js/components/Form/TextAreaField/TextAreaField.spec.ts +341 -0
  35. package/lib/js/components/Form/TextAreaField/TextAreaField.stories.ts +99 -0
  36. package/lib/js/components/Form/TextAreaField/TextAreaField.types.ts +23 -0
  37. package/lib/js/components/Form/TextAreaField/TextAreaField.vue +190 -0
  38. package/lib/js/components/Form/TextAreaField/TextAreaFieldAutosized.vue +19 -0
  39. package/lib/js/components/Form/TextAreaField/index.ts +5 -0
  40. package/lib/js/components/LabelValue/LabelValueItem/LabelValueItem.spec.ts +26 -0
  41. package/lib/js/components/LabelValue/LabelValueItem/LabelValueItem.stories.ts +16 -3
  42. package/lib/js/components/LabelValue/LabelValueItem/LabelValueItem.vue +5 -0
  43. package/lib/js/components/LoadingBar/LoadingBar.spec.ts +84 -0
  44. package/lib/js/components/LoadingBar/LoadingBar.vue +30 -19
  45. package/lib/js/components/Toast/Toast.consts.ts +4 -2
  46. package/lib/js/components/Toast/Toast.spec.ts +177 -0
  47. package/lib/js/components/Toast/Toast.stories.ts +65 -31
  48. package/lib/js/components/Toast/Toast.vue +176 -195
  49. package/lib/js/{components/Form/InputField/useInputFieldWithinForm.ts → composables/useTextFieldWithinForm.ts} +7 -2
  50. package/lib/js/index.ts +4 -0
  51. package/package.json +1 -1
@@ -1,439 +1,57 @@
1
1
  import { ToastColors, ToastPositions, ToastSizes } from './Toast.consts';
2
- import { PropType } from 'vue';
2
+ import { IconItem } from '../Icons/Icon';
3
3
 
4
- declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
5
- size: {
6
- type: PropType<ToastSizes>;
7
- default: "medium";
8
- };
9
- position: {
10
- type: PropType<ToastPositions>;
11
- default: string;
12
- };
13
- boundariesSelector: {
14
- type: PropType<string | HTMLElement>;
15
- default: null;
16
- };
17
- color: {
18
- type: PropType<ToastColors>;
19
- default: string;
20
- };
21
- footerPrimaryButtonText: {
22
- type: StringConstructor;
23
- default: string;
24
- };
25
- footerPrimaryButtonIcon: {
26
- type: ObjectConstructor;
27
- default: null;
28
- validator(footerPrimaryButtonIcon: any): boolean;
29
- };
30
- footerSecondaryButtonText: {
31
- type: StringConstructor;
32
- default: string;
33
- };
34
- footerSecondaryButtonIcon: {
35
- type: ObjectConstructor;
36
- default: null;
37
- validator(footerSecondaryButtonIcon: any): boolean;
38
- };
39
- isDisappearing: {
40
- type: BooleanConstructor;
41
- default: boolean;
42
- };
43
- disappearingTimeout: {
44
- type: StringConstructor;
45
- default: string;
46
- validator(disappearingTimeout: string): boolean;
47
- };
48
- }>, {}, {
49
- boundariesSelectorElement: null;
50
- boundariesSelectorElementResizeObserver: null;
51
- styles: {};
52
- BUTTON_COLORS: Readonly<{
53
- readonly PRIMARY: "primary";
54
- readonly NEUTRAL: "neutral";
55
- readonly DANGER: "danger";
56
- readonly SUCCESS: "success";
57
- readonly INVERTED: "inverted";
58
- readonly MAGIC: "magic";
59
- }>;
60
- BUTTON_RADIUSES: Readonly<{
61
- readonly CAPSULE: "capsule";
62
- readonly ROUNDED: "rounded";
63
- }>;
64
- BUTTON_TYPES: Readonly<{
65
- readonly FILLED: "filled";
66
- readonly OUTLINED: "outlined";
67
- readonly TEXT: "text";
68
- }>;
69
- TOAST_SIZES: Readonly<{
70
- readonly SMALL: "small";
71
- readonly MEDIUM: "medium";
72
- }>;
73
- TOAST_POSITIONS: Readonly<{
74
- LEFT: string;
75
- CENTER: string;
76
- RIGHT: string;
77
- }>;
78
- }, {
79
- buttonPrimaryColor(): "neutral" | "primary";
80
- buttonSecondaryColor(): "danger" | "neutral";
81
- toastPosition(): string;
82
- toastSize(): string;
83
- }, {
84
- calculateStyles(): void;
85
- setBoundariesSelectorElement(): void;
86
- }, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
87
- close: () => true;
88
- 'primary-button-click': () => true;
89
- 'secondary-button-click': () => true;
90
- }, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
91
- size: {
92
- type: PropType<ToastSizes>;
93
- default: "medium";
94
- };
95
- position: {
96
- type: PropType<ToastPositions>;
97
- default: string;
98
- };
99
- boundariesSelector: {
100
- type: PropType<string | HTMLElement>;
101
- default: null;
102
- };
103
- color: {
104
- type: PropType<ToastColors>;
105
- default: string;
106
- };
107
- footerPrimaryButtonText: {
108
- type: StringConstructor;
109
- default: string;
110
- };
111
- footerPrimaryButtonIcon: {
112
- type: ObjectConstructor;
113
- default: null;
114
- validator(footerPrimaryButtonIcon: any): boolean;
115
- };
116
- footerSecondaryButtonText: {
117
- type: StringConstructor;
118
- default: string;
119
- };
120
- footerSecondaryButtonIcon: {
121
- type: ObjectConstructor;
122
- default: null;
123
- validator(footerSecondaryButtonIcon: any): boolean;
124
- };
125
- isDisappearing: {
126
- type: BooleanConstructor;
127
- default: boolean;
128
- };
129
- disappearingTimeout: {
130
- type: StringConstructor;
131
- default: string;
132
- validator(disappearingTimeout: string): boolean;
133
- };
134
- }>> & Readonly<{
4
+ declare function __VLS_template(): Readonly<{
5
+ content?: () => any;
6
+ }> & {
7
+ content?: () => any;
8
+ };
9
+ declare const __VLS_component: import('vue').DefineComponent<import('vue').ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
10
+ title?: string;
11
+ size?: ToastSizes;
12
+ position?: ToastPositions;
13
+ color?: ToastColors;
14
+ footerPrimaryButtonText?: string;
15
+ footerPrimaryButtonIcon?: IconItem | null;
16
+ footerSecondaryButtonText?: string;
17
+ footerSecondaryButtonIcon?: IconItem | null;
18
+ isDisappearing?: boolean;
19
+ disappearingTimeout?: string;
20
+ isClosable?: boolean;
21
+ }>>, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
22
+ close: () => void;
23
+ "secondary-button-click": () => void;
24
+ "primary-button-click": () => void;
25
+ }, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
26
+ title?: string;
27
+ size?: ToastSizes;
28
+ position?: ToastPositions;
29
+ color?: ToastColors;
30
+ footerPrimaryButtonText?: string;
31
+ footerPrimaryButtonIcon?: IconItem | null;
32
+ footerSecondaryButtonText?: string;
33
+ footerSecondaryButtonIcon?: IconItem | null;
34
+ isDisappearing?: boolean;
35
+ disappearingTimeout?: string;
36
+ isClosable?: boolean;
37
+ }>>> & Readonly<{
135
38
  onClose?: (() => any) | undefined;
136
39
  "onSecondary-button-click"?: (() => any) | undefined;
137
40
  "onPrimary-button-click"?: (() => any) | undefined;
138
- }>, {
139
- size: ToastSizes;
140
- color: string;
141
- footerPrimaryButtonText: string;
142
- footerPrimaryButtonIcon: Record<string, any>;
143
- footerSecondaryButtonText: string;
144
- footerSecondaryButtonIcon: Record<string, any>;
145
- position: string;
146
- boundariesSelector: string | HTMLElement;
147
- isDisappearing: boolean;
148
- disappearingTimeout: string;
149
- }, {}, {
150
- DsButton: {
151
- new (...args: any[]): import('vue').CreateComponentPublicInstanceWithMixins<Readonly<import('vue').ExtractPropTypes<{
152
- size: {
153
- type: PropType<string>;
154
- };
155
- type: {
156
- type: PropType<string>;
157
- };
158
- color: {
159
- type: PropType<string | null>;
160
- };
161
- radius: {
162
- type: PropType<string>;
163
- };
164
- state: {
165
- type: PropType<string>;
166
- };
167
- iconLeft: import('../Icons/Icon').IconItem | null;
168
- iconRight: import('../Icons/Icon').IconItem | null;
169
- elevation: {
170
- type: PropType<string>;
171
- };
172
- as: {
173
- type: PropType<"a" | "button" | "span" | "router-link" | "nuxt-link">;
174
- };
175
- }>> & Readonly<{}>, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, import('vue').PublicProps, {}, true, {}, {}, import('vue').GlobalComponents, import('vue').GlobalDirectives, string, {}, any, import('vue').ComponentProvideOptions, {
176
- P: {};
177
- B: {};
178
- D: {};
179
- C: {};
180
- M: {};
181
- Defaults: {};
182
- }, Readonly<import('vue').ExtractPropTypes<{
183
- size: {
184
- type: PropType<string>;
185
- };
186
- type: {
187
- type: PropType<string>;
188
- };
189
- color: {
190
- type: PropType<string | null>;
191
- };
192
- radius: {
193
- type: PropType<string>;
194
- };
195
- state: {
196
- type: PropType<string>;
197
- };
198
- iconLeft: import('../Icons/Icon').IconItem | null;
199
- iconRight: import('../Icons/Icon').IconItem | null;
200
- elevation: {
201
- type: PropType<string>;
202
- };
203
- as: {
204
- type: PropType<"a" | "button" | "span" | "router-link" | "nuxt-link">;
205
- };
206
- }>> & Readonly<{}>, {}, {}, {}, {}, {}>;
207
- __isFragment?: never;
208
- __isTeleport?: never;
209
- __isSuspense?: never;
210
- } & import('vue').ComponentOptionsBase<Readonly<import('vue').ExtractPropTypes<{
211
- size: {
212
- type: PropType<string>;
213
- };
214
- type: {
215
- type: PropType<string>;
216
- };
217
- color: {
218
- type: PropType<string | null>;
219
- };
220
- radius: {
221
- type: PropType<string>;
222
- };
223
- state: {
224
- type: PropType<string>;
225
- };
226
- iconLeft: import('../Icons/Icon').IconItem | null;
227
- iconRight: import('../Icons/Icon').IconItem | null;
228
- elevation: {
229
- type: PropType<string>;
230
- };
231
- as: {
232
- type: PropType<"a" | "button" | "span" | "router-link" | "nuxt-link">;
233
- };
234
- }>> & Readonly<{}>, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, {}, {}, string, {}, import('vue').GlobalComponents, import('vue').GlobalDirectives, string, import('vue').ComponentProvideOptions> & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps & (new () => {
235
- $slots: {
236
- default?(_: {}): any;
237
- };
238
- });
239
- DsCard: {
240
- new (...args: any[]): import('vue').CreateComponentPublicInstanceWithMixins<Readonly<import('vue').ExtractPropTypes<{
241
- contentHasPadding: {
242
- type: PropType<boolean>;
243
- };
244
- headerHasPadding: {
245
- type: PropType<boolean>;
246
- };
247
- footerHasPadding: {
248
- type: PropType<boolean>;
249
- };
250
- paddingSize: {
251
- type: PropType<import('../Cards/Card').CardPaddingSize>;
252
- };
253
- dividerUnderHeader: {
254
- type: PropType<boolean>;
255
- };
256
- hasRibbon: {
257
- type: PropType<boolean>;
258
- };
259
- elevation: {
260
- type: PropType<import('../Cards/Card').CardElevation>;
261
- };
262
- radius: {
263
- type: PropType<import('../Cards/Card').CardRadius>;
264
- };
265
- backgroundColor: {
266
- type: PropType<import('../Cards/Card').CardBackgroundColor>;
267
- };
268
- isFlat: {
269
- type: PropType<boolean>;
270
- };
271
- ribbonPosition: {
272
- type: PropType<import('../Cards/Card').CardRibbonPositions>;
273
- };
274
- ribbonSize: {
275
- type: PropType<import('../Cards/Card').CardRibbonSizes>;
276
- };
277
- ribbonColor: {
278
- type: PropType<import('../Cards/Card').CardRibbonColors>;
279
- };
280
- hasRibbonRadius: {
281
- type: PropType<boolean>;
282
- };
283
- hasLoadingBar: {
284
- type: PropType<boolean>;
285
- };
286
- loadingBarColor: {
287
- type: PropType<string>;
288
- };
289
- loadingBarTime: {
290
- type: PropType<string>;
291
- };
292
- isContentScrollable: {
293
- type: PropType<boolean>;
294
- };
295
- hasRadius: {
296
- type: PropType<import('../../utils/type.utils').RemovedProp<"renamed to radius">>;
297
- };
298
- }>> & Readonly<{}>, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, import('vue').PublicProps, {}, true, {}, {}, import('vue').GlobalComponents, import('vue').GlobalDirectives, string, {}, any, import('vue').ComponentProvideOptions, {
299
- P: {};
300
- B: {};
301
- D: {};
302
- C: {};
303
- M: {};
304
- Defaults: {};
305
- }, Readonly<import('vue').ExtractPropTypes<{
306
- contentHasPadding: {
307
- type: PropType<boolean>;
308
- };
309
- headerHasPadding: {
310
- type: PropType<boolean>;
311
- };
312
- footerHasPadding: {
313
- type: PropType<boolean>;
314
- };
315
- paddingSize: {
316
- type: PropType<import('../Cards/Card').CardPaddingSize>;
317
- };
318
- dividerUnderHeader: {
319
- type: PropType<boolean>;
320
- };
321
- hasRibbon: {
322
- type: PropType<boolean>;
323
- };
324
- elevation: {
325
- type: PropType<import('../Cards/Card').CardElevation>;
326
- };
327
- radius: {
328
- type: PropType<import('../Cards/Card').CardRadius>;
329
- };
330
- backgroundColor: {
331
- type: PropType<import('../Cards/Card').CardBackgroundColor>;
332
- };
333
- isFlat: {
334
- type: PropType<boolean>;
335
- };
336
- ribbonPosition: {
337
- type: PropType<import('../Cards/Card').CardRibbonPositions>;
338
- };
339
- ribbonSize: {
340
- type: PropType<import('../Cards/Card').CardRibbonSizes>;
341
- };
342
- ribbonColor: {
343
- type: PropType<import('../Cards/Card').CardRibbonColors>;
344
- };
345
- hasRibbonRadius: {
346
- type: PropType<boolean>;
347
- };
348
- hasLoadingBar: {
349
- type: PropType<boolean>;
350
- };
351
- loadingBarColor: {
352
- type: PropType<string>;
353
- };
354
- loadingBarTime: {
355
- type: PropType<string>;
356
- };
357
- isContentScrollable: {
358
- type: PropType<boolean>;
359
- };
360
- hasRadius: {
361
- type: PropType<import('../../utils/type.utils').RemovedProp<"renamed to radius">>;
362
- };
363
- }>> & Readonly<{}>, {}, {}, {}, {}, {}>;
364
- __isFragment?: never;
365
- __isTeleport?: never;
366
- __isSuspense?: never;
367
- } & import('vue').ComponentOptionsBase<Readonly<import('vue').ExtractPropTypes<{
368
- contentHasPadding: {
369
- type: PropType<boolean>;
370
- };
371
- headerHasPadding: {
372
- type: PropType<boolean>;
373
- };
374
- footerHasPadding: {
375
- type: PropType<boolean>;
376
- };
377
- paddingSize: {
378
- type: PropType<import('../Cards/Card').CardPaddingSize>;
379
- };
380
- dividerUnderHeader: {
381
- type: PropType<boolean>;
382
- };
383
- hasRibbon: {
384
- type: PropType<boolean>;
385
- };
386
- elevation: {
387
- type: PropType<import('../Cards/Card').CardElevation>;
388
- };
389
- radius: {
390
- type: PropType<import('../Cards/Card').CardRadius>;
391
- };
392
- backgroundColor: {
393
- type: PropType<import('../Cards/Card').CardBackgroundColor>;
394
- };
395
- isFlat: {
396
- type: PropType<boolean>;
397
- };
398
- ribbonPosition: {
399
- type: PropType<import('../Cards/Card').CardRibbonPositions>;
400
- };
401
- ribbonSize: {
402
- type: PropType<import('../Cards/Card').CardRibbonSizes>;
403
- };
404
- ribbonColor: {
405
- type: PropType<import('../Cards/Card').CardRibbonColors>;
406
- };
407
- hasRibbonRadius: {
408
- type: PropType<boolean>;
409
- };
410
- hasLoadingBar: {
411
- type: PropType<boolean>;
412
- };
413
- loadingBarColor: {
414
- type: PropType<string>;
415
- };
416
- loadingBarTime: {
417
- type: PropType<string>;
418
- };
419
- isContentScrollable: {
420
- type: PropType<boolean>;
421
- };
422
- hasRadius: {
423
- type: PropType<import('../../utils/type.utils').RemovedProp<"renamed to radius">>;
424
- };
425
- }>> & Readonly<{}>, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, {}, {}, string, {}, import('vue').GlobalComponents, import('vue').GlobalDirectives, string, import('vue').ComponentProvideOptions> & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps & (new () => {
426
- $slots: Readonly<{
427
- header?: () => any;
428
- content?: () => any;
429
- footer?: () => any;
430
- experimentalContent?: () => any;
431
- }> & {
432
- header?: () => any;
433
- content?: () => any;
434
- footer?: () => any;
435
- experimentalContent?: () => any;
436
- };
437
- });
438
- }, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
41
+ }>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
42
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, ReturnType<typeof __VLS_template>>;
439
43
  export default _default;
44
+ type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
45
+ type __VLS_TypePropsToRuntimeProps<T> = {
46
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
47
+ type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
48
+ } : {
49
+ type: import('vue').PropType<T[K]>;
50
+ required: true;
51
+ };
52
+ };
53
+ type __VLS_WithTemplateSlots<T, S> = T & {
54
+ new (): {
55
+ $slots: S;
56
+ };
57
+ };
@@ -1,6 +1,6 @@
1
1
  import { MaybeRefOrGetter, Ref } from 'vue';
2
2
 
3
- export declare function useInputFieldWithinForm(name: MaybeRefOrGetter<string | undefined>, modelValue: Ref<string | undefined>): {
3
+ export declare function useTextFieldWithinForm(name: MaybeRefOrGetter<string | undefined>, modelValue: Ref<string | undefined>): {
4
4
  onBlur: (event: Event) => void;
5
5
  onInput: () => void;
6
6
  value: Ref<string | undefined, string | undefined>;
@@ -53,11 +53,15 @@ export { default as NumberInCircle } from './components/NumberInCircle';
53
53
  export { default as DsNumberInCircle } from './components/NumberInCircle';
54
54
  export * from './components/NumberInCircle/NumberInCircle.consts';
55
55
  export { default as DsPasswordField } from './components/Form/PasswordField';
56
+ export { default as DsPinInputField } from './components/Form/PinInputField';
57
+ export * from './components/Form/PinInputField';
56
58
  export { default as DsSelectField } from './components/Form/SelectField';
57
59
  export * from './components/Form/SelectField';
58
60
  export { default as TabItem } from './components/TabItem';
59
61
  export { default as DsTabItem } from './components/TabItem';
60
62
  export * from './components/TabItem/TabItem.consts';
63
+ export { default as DsTextAreaField } from './components/Form/TextAreaField';
64
+ export * from './components/Form/TextAreaField';
61
65
  export { default as Tile } from './components/Tile';
62
66
  export { default as DsTile } from './components/Tile';
63
67
  export * from './components/Tile/Tile.consts';
@@ -104,6 +104,21 @@ describe('CheckboxGroupField', () => {
104
104
  );
105
105
  });
106
106
 
107
+ it('sets aria-describedby only when a message is rendered', () => {
108
+ const wrapper = mount(CheckboxGroupField, {
109
+ props: {
110
+ label: 'Test Label',
111
+ },
112
+ slots: {
113
+ field: '<div>Content</div>',
114
+ },
115
+ });
116
+
117
+ expect(
118
+ wrapper.find('.ds-checkboxGroupField').attributes('aria-describedby'),
119
+ ).toBeUndefined();
120
+ });
121
+
107
122
  describe('vee-validate integration', () => {
108
123
  it('integrates with vee-validate form context and reflects initial values', async () => {
109
124
  // eslint-disable-next-line vue/one-component-per-file
@@ -5,7 +5,7 @@
5
5
  v-model="value"
6
6
  class="ds-checkboxGroupField"
7
7
  role="group"
8
- :aria-describedby="messageId"
8
+ :aria-describedby="hasMessage ? messageId : undefined"
9
9
  :aria-labelledby="labelId"
10
10
  :disabled="formFieldProps.state === FORM_FIELD_STATES.DISABLED"
11
11
  loop
@@ -64,7 +64,7 @@ const {
64
64
  ...rest
65
65
  } = defineProps<CheckboxGroupFieldProps>();
66
66
 
67
- defineSlots<CheckboxGroupFieldSlots>();
67
+ const slots = defineSlots<CheckboxGroupFieldSlots>();
68
68
 
69
69
  const modelValue = defineModel<Array<string>>({
70
70
  default: [],
@@ -77,6 +77,9 @@ const formFieldProps = computed<FormFieldProps>(() => {
77
77
  return extractFormFieldProps(rest, errors.value);
78
78
  });
79
79
 
80
+ // Avoids pointing `aria-describedby` at a message element that is never rendered.
81
+ const hasMessage = computed(() => !!(formFieldProps.value.messageText || slots.message));
82
+
80
83
  const mappedState = computed(() => {
81
84
  const stateMap: Record<FormFieldState, CheckboxState> = {
82
85
  [FORM_FIELD_STATES.DEFAULT]: CHECKBOX_STATES.DEFAULT,
@@ -7,6 +7,8 @@ import { toTypedSchema } from '@vee-validate/zod';
7
7
  import { array, object, string } from 'zod';
8
8
  import CheckboxGroupField from './CheckboxGroupField/CheckboxGroupField.vue';
9
9
  import SelectField from './SelectField';
10
+ import TextAreaField from './TextAreaField';
11
+ import PinInputField from './PinInputField';
10
12
  import Button from '../Buttons/Button';
11
13
 
12
14
  export default {
@@ -15,13 +17,23 @@ export default {
15
17
  } as Meta<any>;
16
18
 
17
19
  export const SimpleForm = () => ({
18
- components: { InputField, CheckboxGroupField, Checkbox, SelectField, Button },
20
+ components: {
21
+ InputField,
22
+ CheckboxGroupField,
23
+ Checkbox,
24
+ SelectField,
25
+ TextAreaField,
26
+ PinInputField,
27
+ Button,
28
+ },
19
29
  setup: () => {
20
30
  const { handleSubmit } = useForm({
21
31
  initialValues: {
22
32
  fullName: '',
23
33
  country: '',
24
34
  newsletterTopics: [],
35
+ notes: '',
36
+ code: '',
25
37
  },
26
38
  validationSchema: toTypedSchema(
27
39
  object({
@@ -31,6 +43,8 @@ export const SimpleForm = () => ({
31
43
  1,
32
44
  'Wybierz przynajmniej jeden temat newslettera',
33
45
  ),
46
+ notes: string().max(500, 'Maksymalnie 500 znaków'),
47
+ code: string().length(6, 'Kod ma 6 cyfr'),
34
48
  }),
35
49
  ),
36
50
  });
@@ -54,7 +68,7 @@ export const SimpleForm = () => ({
54
68
  };
55
69
  },
56
70
  template: `
57
- <form @submit.prevent="onSubmit" style="display: flex; flex-direction: column; gap: 16px; max-width: 400px;">
71
+ <form novalidate @submit.prevent="onSubmit" style="display: flex; flex-direction: column; gap: 16px; max-width: 400px;">
58
72
  <InputField label="Imię i nazwisko" name="fullName" />
59
73
  <SelectField
60
74
  label="Kraj"
@@ -70,6 +84,13 @@ export const SimpleForm = () => ({
70
84
  <Checkbox value="sports">Sport</Checkbox>
71
85
  </template>
72
86
  </CheckboxGroupField>
87
+ <TextAreaField
88
+ label="Uwagi"
89
+ name="notes"
90
+ is-autoresizing
91
+ :input-props="{ rows: 4, maxlength: 500, placeholder: 'Coś jeszcze?' }"
92
+ />
93
+ <PinInputField label="Kod z e-maila" name="code" />
73
94
  <Button as="button">
74
95
  Wyślij
75
96
  </Button>
@@ -87,6 +87,16 @@ describe('InputField', () => {
87
87
  expect(wrapper.find(`#${messageId}`).exists()).toBe(true);
88
88
  });
89
89
 
90
+ it('should set aria-describedby only when a message is rendered', () => {
91
+ const wrapper = setup({
92
+ props: {
93
+ label: 'Label',
94
+ },
95
+ });
96
+
97
+ expect(wrapper.find('input').attributes('aria-describedby')).toBeUndefined();
98
+ });
99
+
90
100
  it('should pass inputProps to the input element', () => {
91
101
  const inputProps = {
92
102
  placeholder: 'Enter text',
@@ -252,7 +262,7 @@ describe('InputField', () => {
252
262
  }).toThrowError();
253
263
  });
254
264
 
255
- it('overrides state and message on vee-validate form error', async () => {
265
+ it('should keep an explicit state and message over a vee-validate error', async () => {
256
266
  const { wrapper, errorsRef } = setupWithForm({
257
267
  state: FORM_FIELD_STATES.SUCCESS,
258
268
  messageText: 'Success message',