vueless 1.3.7-beta.1 → 1.3.7-beta.3

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 (33) hide show
  1. package/components.d.ts +1 -0
  2. package/components.ts +1 -0
  3. package/constants.d.ts +2 -0
  4. package/constants.js +2 -0
  5. package/package.json +2 -2
  6. package/ui.container-col/UCol.vue +0 -1
  7. package/ui.container-collapsible/UCollapsible.vue +190 -0
  8. package/ui.container-collapsible/config.ts +45 -0
  9. package/ui.container-collapsible/constants.ts +1 -0
  10. package/ui.container-collapsible/storybook/docs.mdx +17 -0
  11. package/ui.container-collapsible/storybook/stories.ts +261 -0
  12. package/ui.container-collapsible/tests/UCollapsible.test.ts +571 -0
  13. package/ui.container-collapsible/types.ts +57 -0
  14. package/ui.dropdown/UDropdown.vue +324 -0
  15. package/ui.dropdown/config.ts +27 -0
  16. package/ui.dropdown/constants.ts +1 -0
  17. package/ui.dropdown/storybook/docs.mdx +17 -0
  18. package/ui.dropdown/storybook/stories.ts +286 -0
  19. package/ui.dropdown/tests/UDropdown.test.ts +631 -0
  20. package/ui.dropdown/types.ts +127 -0
  21. package/ui.dropdown-badge/UDropdownBadge.vue +119 -227
  22. package/ui.dropdown-badge/config.ts +18 -15
  23. package/ui.dropdown-badge/tests/UDropdownBadge.test.ts +201 -67
  24. package/ui.dropdown-button/UDropdownButton.vue +121 -226
  25. package/ui.dropdown-button/config.ts +32 -28
  26. package/ui.dropdown-button/tests/UDropdownButton.test.ts +189 -73
  27. package/ui.dropdown-link/UDropdownLink.vue +123 -233
  28. package/ui.dropdown-link/config.ts +15 -18
  29. package/ui.dropdown-link/tests/UDropdownLink.test.ts +190 -71
  30. package/ui.form-listbox/UListbox.vue +2 -3
  31. package/ui.form-listbox/config.ts +2 -2
  32. package/ui.form-select/config.ts +1 -1
  33. package/utils/node/helper.js +6 -5
@@ -15,10 +15,8 @@ describe("UDropdownButton.vue", () => {
15
15
  { value: 3, label: "Option 3" },
16
16
  ];
17
17
 
18
- // Props tests
19
18
  describe("Props", () => {
20
- // Label prop
21
- it("renders the correct label text", () => {
19
+ it("Label – renders the correct label text", () => {
22
20
  const label = "Dropdown Button";
23
21
 
24
22
  const component = mount(UDropdownButton, {
@@ -31,8 +29,7 @@ describe("UDropdownButton.vue", () => {
31
29
  expect(component.findComponent(UButton).props("label")).toBe(label);
32
30
  });
33
31
 
34
- // ModelValue prop
35
- it("selects the correct option based on modelValue", async () => {
32
+ it("ModelValue – selects the correct option based on modelValue", async () => {
36
33
  const modelValue = 2;
37
34
 
38
35
  const component = mount(UDropdownButton, {
@@ -48,8 +45,7 @@ describe("UDropdownButton.vue", () => {
48
45
  expect(component.findComponent(UButton).props("label")).toBe(selectedOption?.label);
49
46
  });
50
47
 
51
- // Multiple prop with modelValue
52
- it("handles multiple selections correctly", async () => {
48
+ it("Multiple handles multiple selections correctly", async () => {
53
49
  const modelValue = [1, 3];
54
50
 
55
51
  const component = mount(UDropdownButton, {
@@ -67,8 +63,7 @@ describe("UDropdownButton.vue", () => {
67
63
  expect(component.findComponent(UButton).props("label")).toBe(expectedLabel);
68
64
  });
69
65
 
70
- // LabelDisplayCount prop
71
- it("limits displayed labels based on labelDisplayCount", async () => {
66
+ it("LabelDisplayCount – limits displayed labels based on labelDisplayCount", async () => {
72
67
  const modelValue = [1, 2, 3];
73
68
  const labelDisplayCount = 1;
74
69
 
@@ -87,8 +82,7 @@ describe("UDropdownButton.vue", () => {
87
82
  expect(component.findComponent(UButton).props("label")).toBe(expectedLabel);
88
83
  });
89
84
 
90
- // LabelDisplayCount prop with single value
91
- it("correctly displays label when labelDisplayCount is 1 and only one value is selected", async () => {
85
+ it("LabelDisplayCount displays label correctly with single value", async () => {
92
86
  const modelValue = [1];
93
87
  const labelDisplayCount = 1;
94
88
 
@@ -107,8 +101,7 @@ describe("UDropdownButton.vue", () => {
107
101
  expect(component.findComponent(UButton).props("label")).toBe(expectedLabel);
108
102
  });
109
103
 
110
- // Variant prop
111
- it("applies the correct variant class", async () => {
104
+ it("Variant – applies the correct variant class", async () => {
112
105
  const variants = ["solid", "outlined", "subtle", "soft", "ghost"];
113
106
 
114
107
  variants.forEach((variant) => {
@@ -123,8 +116,7 @@ describe("UDropdownButton.vue", () => {
123
116
  });
124
117
  });
125
118
 
126
- // Color prop
127
- it("applies the correct color class", async () => {
119
+ it("Color – applies the correct color class", async () => {
128
120
  const colors = [
129
121
  "primary",
130
122
  "secondary",
@@ -149,8 +141,7 @@ describe("UDropdownButton.vue", () => {
149
141
  });
150
142
  });
151
143
 
152
- // Size prop
153
- it("applies the correct size class", async () => {
144
+ it("Size – applies the correct size class", async () => {
154
145
  const sizes = ["2xs", "xs", "sm", "md", "lg", "xl"];
155
146
 
156
147
  sizes.forEach((size) => {
@@ -165,8 +156,7 @@ describe("UDropdownButton.vue", () => {
165
156
  });
166
157
  });
167
158
 
168
- // Round prop
169
- it("applies round class when round prop is true", () => {
159
+ it("Round – applies round class when round prop is true", () => {
170
160
  const round = true;
171
161
 
172
162
  const component = mount(UDropdownButton, {
@@ -179,8 +169,7 @@ describe("UDropdownButton.vue", () => {
179
169
  expect(component.findComponent(UButton).props("round")).toBe(round);
180
170
  });
181
171
 
182
- // Square prop
183
- it("applies square class when square prop is true", () => {
172
+ it("Square – applies square class when square prop is true", () => {
184
173
  const square = true;
185
174
 
186
175
  const component = mount(UDropdownButton, {
@@ -193,8 +182,7 @@ describe("UDropdownButton.vue", () => {
193
182
  expect(component.findComponent(UButton).props("square")).toBe(square);
194
183
  });
195
184
 
196
- // Disabled prop
197
- it("applies disabled attribute when disabled prop is true", () => {
185
+ it("Disabled – applies disabled attribute when disabled prop is true", () => {
198
186
  const disabled = true;
199
187
 
200
188
  const component = mount(UDropdownButton, {
@@ -207,8 +195,7 @@ describe("UDropdownButton.vue", () => {
207
195
  expect(component.findComponent(UButton).props("disabled")).toBe(disabled);
208
196
  });
209
197
 
210
- // Block prop
211
- it("applies class when prop is true", () => {
198
+ it("Block – applies class when prop is true", () => {
212
199
  const block = true;
213
200
  const expectedClass = "w-full";
214
201
 
@@ -223,8 +210,7 @@ describe("UDropdownButton.vue", () => {
223
210
  expect(component.findComponent(UButton).attributes("class")).toContain(expectedClass);
224
211
  });
225
212
 
226
- // ToggleIcon prop (boolean: true)
227
- it("shows default toggle icon when toggleIcon is true", () => {
213
+ it("ToggleIcon shows default toggle icon when toggleIcon is true", () => {
228
214
  const toggleIcon = true;
229
215
 
230
216
  const component = mount(UDropdownButton, {
@@ -240,8 +226,7 @@ describe("UDropdownButton.vue", () => {
240
226
  expect(iconComponent.props("name")).toBe("keyboard_arrow_down");
241
227
  });
242
228
 
243
- // ToggleIcon prop (boolean: false)
244
- it("shows default toggle icon when toggleIcon is false", () => {
229
+ it("ToggleIcon shows default toggle icon when toggleIcon is false", () => {
245
230
  const toggleIcon = false;
246
231
 
247
232
  const component = mount(UDropdownButton, {
@@ -256,8 +241,7 @@ describe("UDropdownButton.vue", () => {
256
241
  expect(iconComponent.exists()).toBe(false);
257
242
  });
258
243
 
259
- // ToggleIcon prop (string)
260
- it("shows custom toggle icon when toggleIcon is a string", () => {
244
+ it("ToggleIcon shows custom toggle icon when toggleIcon is a string", () => {
261
245
  const toggleIcon = "custom_icon";
262
246
 
263
247
  const component = mount(UDropdownButton, {
@@ -273,8 +257,7 @@ describe("UDropdownButton.vue", () => {
273
257
  expect(iconComponent.props("name")).toBe(toggleIcon);
274
258
  });
275
259
 
276
- // ID prop
277
- it("applies the correct id attribute", () => {
260
+ it("ID – applies the correct id attribute", () => {
278
261
  const id = "test-dropdown-id";
279
262
 
280
263
  const component = mount(UDropdownButton, {
@@ -284,11 +267,10 @@ describe("UDropdownButton.vue", () => {
284
267
  },
285
268
  });
286
269
 
287
- expect(component.findComponent(UButton).props("id")).toBe(id);
270
+ expect(component.attributes("id")).toBe(id);
288
271
  });
289
272
 
290
- // DataTest prop
291
- it("applies the correct data-test attribute", () => {
273
+ it("DataTest – applies the correct data-test attribute", () => {
292
274
  const dataTest = "test-dropdown";
293
275
 
294
276
  const component = mount(UDropdownButton, {
@@ -301,8 +283,7 @@ describe("UDropdownButton.vue", () => {
301
283
  expect(component.findComponent(UButton).attributes("data-test")).toBe(dataTest);
302
284
  });
303
285
 
304
- // OptionsLimit prop
305
- it("passes optionsLimit prop to UListbox component", async () => {
286
+ it("OptionsLimit – passes optionsLimit prop to UListbox component", async () => {
306
287
  const optionsLimit = 2;
307
288
 
308
289
  const component = mount(UDropdownButton, {
@@ -335,8 +316,7 @@ describe("UDropdownButton.vue", () => {
335
316
  expect(options[0].text()).toBe("Option 2");
336
317
  });
337
318
 
338
- // VisibleOptions prop
339
- it("passes visibleOptions prop to UListbox component", async () => {
319
+ it("VisibleOptions – passes visibleOptions prop to UListbox component", async () => {
340
320
  const visibleOptions = 5;
341
321
 
342
322
  const component = mount(UDropdownButton, {
@@ -351,8 +331,7 @@ describe("UDropdownButton.vue", () => {
351
331
  expect(component.findComponent(UListbox).props("visibleOptions")).toBe(visibleOptions);
352
332
  });
353
333
 
354
- // GroupLabelKey prop
355
- it("passes groupLabelKey prop to UListbox component", async () => {
334
+ it("GroupLabelKey – passes groupLabelKey prop to UListbox component", async () => {
356
335
  const groupLabelKey = "category";
357
336
  const groupedOptions = [
358
337
  { groupLabel: "Group 1", category: "group1" },
@@ -373,8 +352,7 @@ describe("UDropdownButton.vue", () => {
373
352
  expect(component.findComponent(UListbox).props("groupLabelKey")).toBe(groupLabelKey);
374
353
  });
375
354
 
376
- // CloseOnSelect prop
377
- it("keeps dropdown open when closeOnSelect is false", async () => {
355
+ it("CloseOnSelect – keeps dropdown open when closeOnSelect is false", async () => {
378
356
  const component = mount(UDropdownButton, {
379
357
  props: {
380
358
  options: defaultOptions,
@@ -391,12 +369,100 @@ describe("UDropdownButton.vue", () => {
391
369
 
392
370
  expect(component.findComponent(UListbox).exists()).toBe(true);
393
371
  });
372
+
373
+ it("XPosition – passes xPosition prop to dropdown", () => {
374
+ const component = mount(UDropdownButton, {
375
+ props: {
376
+ xPosition: "right",
377
+ options: defaultOptions,
378
+ },
379
+ });
380
+
381
+ const dropdown = component.findComponent({ name: "UDropdown" });
382
+
383
+ expect(dropdown.props("xPosition")).toBe("right");
384
+ });
385
+
386
+ it("YPosition – passes yPosition prop to dropdown", () => {
387
+ const component = mount(UDropdownButton, {
388
+ props: {
389
+ yPosition: "top",
390
+ options: defaultOptions,
391
+ },
392
+ });
393
+
394
+ const dropdown = component.findComponent({ name: "UDropdown" });
395
+
396
+ expect(dropdown.props("yPosition")).toBe("top");
397
+ });
398
+
399
+ it("LabelKey – uses custom label key for options", async () => {
400
+ const customOptions = [
401
+ { id: 1, name: "First" },
402
+ { id: 2, name: "Second" },
403
+ ];
404
+
405
+ const component = mount(UDropdownButton, {
406
+ props: {
407
+ options: customOptions,
408
+ labelKey: "name",
409
+ valueKey: "id",
410
+ },
411
+ });
412
+
413
+ const dropdown = component.findComponent({ name: "UDropdown" });
414
+
415
+ expect(dropdown.props("labelKey")).toBe("name");
416
+ });
417
+
418
+ it("ValueKey – uses custom value key for options", async () => {
419
+ const customOptions = [
420
+ { id: 1, name: "First" },
421
+ { id: 2, name: "Second" },
422
+ ];
423
+
424
+ const component = mount(UDropdownButton, {
425
+ props: {
426
+ options: customOptions,
427
+ labelKey: "name",
428
+ valueKey: "id",
429
+ },
430
+ });
431
+
432
+ const dropdown = component.findComponent({ name: "UDropdown" });
433
+
434
+ expect(dropdown.props("valueKey")).toBe("id");
435
+ });
436
+
437
+ it("GroupValueKey – passes groupValueKey prop to dropdown", () => {
438
+ const component = mount(UDropdownButton, {
439
+ props: {
440
+ groupValueKey: "items",
441
+ options: defaultOptions,
442
+ },
443
+ });
444
+
445
+ const dropdown = component.findComponent({ name: "UDropdown" });
446
+
447
+ expect(dropdown.props("groupValueKey")).toBe("items");
448
+ });
449
+
450
+ it("Searchable – passes searchable prop to dropdown", () => {
451
+ const component = mount(UDropdownButton, {
452
+ props: {
453
+ searchable: true,
454
+ options: defaultOptions,
455
+ },
456
+ });
457
+
458
+ const dropdown = component.findComponent({ name: "UDropdown" });
459
+
460
+ expect(dropdown.props("searchable")).toBe(true);
461
+ });
394
462
  });
395
463
 
396
- // Slots tests
397
464
  describe("Slots", () => {
398
- // Default slot
399
- it("renders content from default slot", () => {
465
+ it("Default – renders content from default slot", () => {
400
466
  const slotContent = "Custom Content";
401
467
  const label = "Dropdown Button";
402
468
 
@@ -413,8 +479,7 @@ describe("UDropdownButton.vue", () => {
413
479
  expect(component.text()).toContain(slotContent);
414
480
  });
415
481
 
416
- // Left slot
417
- it("renders content from left slot", () => {
482
+ it("Left – renders content from left slot", () => {
418
483
  const label = "Dropdown Button";
419
484
  const slotText = "Left";
420
485
  const slotClass = "left-content";
@@ -433,8 +498,7 @@ describe("UDropdownButton.vue", () => {
433
498
  expect(component.find(`.${slotClass}`).text()).toBe(slotText);
434
499
  });
435
500
 
436
- // Toggle slot
437
- it("renders content from toggle slot", () => {
501
+ it("Toggle – renders content from toggle slot", () => {
438
502
  const label = "Dropdown Button";
439
503
  const slotText = "Toggle";
440
504
  const slotClass = "toggle-content";
@@ -453,8 +517,7 @@ describe("UDropdownButton.vue", () => {
453
517
  expect(component.find(`.${slotClass}`).text()).toBe(slotText);
454
518
  });
455
519
 
456
- // Before-option slot
457
- it("renders content from before-option slot", async () => {
520
+ it("Before – renders content from before-option slot", async () => {
458
521
  const label = "Dropdown Button";
459
522
  const slotText = "Before";
460
523
  const slotClass = "before-option-content";
@@ -478,8 +541,7 @@ describe("UDropdownButton.vue", () => {
478
541
  expect(beforeOptionSlot.text()).toBe(slotText);
479
542
  });
480
543
 
481
- // Option slot
482
- it("renders custom content from option slot", async () => {
544
+ it("Option – renders custom content from option slot", async () => {
483
545
  const label = "Dropdown Button";
484
546
  const slotClass = "custom-option-content";
485
547
 
@@ -502,8 +564,7 @@ describe("UDropdownButton.vue", () => {
502
564
  expect(customOptionSlot.text()).toBe("Custom Option 1");
503
565
  });
504
566
 
505
- // After-option slot
506
- it("renders content from after-option slot", async () => {
567
+ it("After – renders content from after-option slot", async () => {
507
568
  const label = "Dropdown Button";
508
569
  const slotText = "After";
509
570
  const slotClass = "after-option-content";
@@ -527,8 +588,7 @@ describe("UDropdownButton.vue", () => {
527
588
  expect(afterOptionSlot.text()).toBe(slotText);
528
589
  });
529
590
 
530
- // Empty slot
531
- it("renders custom content from empty slot", async () => {
591
+ it("Empty – renders custom content from empty slot", async () => {
532
592
  const label = "Dropdown Button";
533
593
  const slotContent = "No options available";
534
594
  const slotClass = "custom-empty";
@@ -553,10 +613,8 @@ describe("UDropdownButton.vue", () => {
553
613
  });
554
614
  });
555
615
 
556
- // Events tests
557
616
  describe("Events", () => {
558
- // Click event to open dropdown
559
- it("opens dropdown when button is clicked", async () => {
617
+ it("Click opens dropdown when button is clicked", async () => {
560
618
  const component = mount(UDropdownButton, {
561
619
  props: {
562
620
  options: defaultOptions,
@@ -573,8 +631,7 @@ describe("UDropdownButton.vue", () => {
573
631
  expect(component.findComponent(UListbox).exists()).toBe(true);
574
632
  });
575
633
 
576
- // update:modelValue event
577
- it("emits update:modelValue event when an option is selected", async () => {
634
+ it("update:modelValue – emits update:modelValue event when an option is selected", async () => {
578
635
  const component = mount(UDropdownButton, {
579
636
  props: {
580
637
  options: defaultOptions,
@@ -595,8 +652,7 @@ describe("UDropdownButton.vue", () => {
595
652
  expect(component.emitted("update:modelValue")?.[0]).toEqual([2]);
596
653
  });
597
654
 
598
- // clickOption event
599
- it("emits clickOption event when an option is clicked", async () => {
655
+ it("clickOption – emits clickOption event when an option is clicked", async () => {
600
656
  const component = mount(UDropdownButton, {
601
657
  props: {
602
658
  options: defaultOptions,
@@ -617,8 +673,7 @@ describe("UDropdownButton.vue", () => {
617
673
  expect(component.emitted("clickOption")?.[0]).toEqual([defaultOptions[1]]);
618
674
  });
619
675
 
620
- // Close dropdown when clicking outside
621
- it("closes dropdown when clicking outside", async () => {
676
+ it("Close – closes dropdown when clicking outside", async () => {
622
677
  const component = mount(UDropdownButton, {
623
678
  props: {
624
679
  options: defaultOptions,
@@ -629,20 +684,81 @@ describe("UDropdownButton.vue", () => {
629
684
  await component.findComponent(UButton).trigger("click");
630
685
  expect(component.findComponent(UListbox).exists()).toBe(true);
631
686
 
632
- // Directly call the hideOptions function
687
+ // Directly call the hide function
633
688
  // This is equivalent to what happens when clicking outside
634
- component.vm.hideOptions();
689
+ component.vm.hide();
635
690
  await component.vm.$nextTick();
636
691
 
637
692
  // Dropdown should be closed
638
693
  expect(component.findComponent(UListbox).exists()).toBe(false);
639
694
  });
695
+
696
+ it("Open – emits open event when dropdown is opened", async () => {
697
+ const component = mount(UDropdownButton, {
698
+ props: {
699
+ options: defaultOptions,
700
+ },
701
+ });
702
+
703
+ await component.findComponent(UButton).trigger("click");
704
+
705
+ expect(component.emitted("open")).toBeTruthy();
706
+ });
707
+
708
+ it("Close – emits close event when dropdown is closed", async () => {
709
+ const component = mount(UDropdownButton, {
710
+ props: {
711
+ options: defaultOptions,
712
+ },
713
+ });
714
+
715
+ await component.findComponent(UButton).trigger("click");
716
+
717
+ component.vm.hide();
718
+ await component.vm.$nextTick();
719
+
720
+ expect(component.emitted("close")).toBeTruthy();
721
+ });
722
+
723
+ it("SearchChange – emits searchChange event when search value changes", async () => {
724
+ const component = mount(UDropdownButton, {
725
+ props: {
726
+ searchable: true,
727
+ options: defaultOptions,
728
+ },
729
+ });
730
+
731
+ await component.findComponent(UButton).trigger("click");
732
+
733
+ const dropdown = component.findComponent({ name: "UDropdown" });
734
+
735
+ dropdown.vm.$emit("searchChange", "test query");
736
+
737
+ expect(component.emitted("searchChange")).toBeTruthy();
738
+ expect(component.emitted("searchChange")?.[0]).toEqual(["test query"]);
739
+ });
740
+
741
+ it("Update:search – emits update:search event when search value updates", async () => {
742
+ const component = mount(UDropdownButton, {
743
+ props: {
744
+ searchable: true,
745
+ options: defaultOptions,
746
+ },
747
+ });
748
+
749
+ await component.findComponent(UButton).trigger("click");
750
+
751
+ const dropdown = component.findComponent({ name: "UDropdown" });
752
+
753
+ dropdown.vm.$emit("update:search", "new search");
754
+
755
+ expect(component.emitted("update:search")).toBeTruthy();
756
+ expect(component.emitted("update:search")?.[0]).toEqual(["new search"]);
757
+ });
640
758
  });
641
759
 
642
- // Exposed refs tests
643
760
  describe("Exposed refs", () => {
644
- // wrapperRef
645
- it("exposes wrapperRef", () => {
761
+ it("wrapperRef – exposes wrapperRef", () => {
646
762
  const component = mount(UDropdownButton, {
647
763
  props: {
648
764
  options: defaultOptions,