@dile/ui 3.4.5 → 3.5.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 (181) hide show
  1. package/components/accordion/accordion-item.js +3 -1
  2. package/components/accordion/accordion.js +3 -1
  3. package/components/app-drawer/app-drawer.js +3 -1
  4. package/components/avatar/avatar.js +3 -1
  5. package/components/avatar/avatar.spec.js +25 -0
  6. package/components/box-selector/box-selector-item.js +3 -1
  7. package/components/box-selector/box-selector-item.spec.js +27 -0
  8. package/components/box-selector/box-selector.js +3 -1
  9. package/components/box-selector/box-selector.spec.js +27 -0
  10. package/components/breadcrumbs/breadcrumbs-item.js +3 -1
  11. package/components/breadcrumbs/breadcrumbs-item.spec.js +28 -0
  12. package/components/breadcrumbs/breadcrumbs.js +3 -1
  13. package/components/breadcrumbs/breadcrumbs.spec.js +33 -0
  14. package/components/button/button-icon.js +3 -1
  15. package/components/button/button.js +3 -1
  16. package/components/card/card-slide.js +3 -1
  17. package/components/card/card-slide.spec.js +30 -0
  18. package/components/card/card.js +3 -1
  19. package/components/card/card.spec.js +26 -0
  20. package/components/checkbox/checkbox.js +3 -1
  21. package/components/chip/chip.js +3 -1
  22. package/components/chip/chip.spec.js +31 -0
  23. package/components/color-picker/color-picker.js +3 -1
  24. package/components/confirm/confirm.js +3 -1
  25. package/components/confirm/confirm.spec.js +32 -0
  26. package/components/confirm-text/confirm-text.js +3 -1
  27. package/components/confirm-text/confirm-text.spec.js +29 -0
  28. package/components/copy-markdown-url/copy-markdown-url.spec.js +27 -0
  29. package/components/copy-markdown-url/index.js +3 -1
  30. package/components/copy-text/__screenshots__/copy-text.spec.js/dile-copy-text-dispatches-dile-text-copied-with-the-content-on-copy---1.png +0 -0
  31. package/components/copy-text/copy-text.spec.js +38 -0
  32. package/components/copy-text/index.js +3 -1
  33. package/components/drop-file/drop-file.js +3 -1
  34. package/components/drop-file/drop-file.spec.js +33 -0
  35. package/components/drop-file/file-preview.js +3 -1
  36. package/components/drop-file/file-preview.spec.js +35 -0
  37. package/components/floating-feedback/floating-feedback.spec.js +30 -0
  38. package/components/floating-feedback/index.js +3 -1
  39. package/components/floating-menu/floating-menu-item.js +3 -1
  40. package/components/floating-menu/floating-menu-item.spec.js +27 -0
  41. package/components/floating-menu/floating-menu.js +3 -1
  42. package/components/floating-menu/floating-menu.spec.js +31 -0
  43. package/components/form-separator/form-separator.js +3 -1
  44. package/components/form-separator/form-separator.spec.js +28 -0
  45. package/components/hamburger/hamburger.js +3 -1
  46. package/components/hamburger/hamburger.spec.js +28 -0
  47. package/components/icon/icon.js +3 -1
  48. package/components/icon/icon.spec.js +31 -0
  49. package/components/icon-switch/icon-switch-group.js +3 -1
  50. package/components/icon-switch/icon-switch-group.spec.js +46 -0
  51. package/components/icon-switch/icon-switch.js +3 -1
  52. package/components/icon-switch/icon-switch.spec.js +35 -0
  53. package/components/info-box/info-box.js +3 -1
  54. package/components/info-box/info-box.spec.js +38 -0
  55. package/components/inline-feedback/inline-feedback.js +3 -1
  56. package/components/inline-feedback/inline-feedback.spec.js +46 -0
  57. package/components/input/__screenshots__/input-number-mask.spec.js/dile-input-number-mask-masks-digit-keydowns-following-the-given-pattern-1.png +0 -0
  58. package/components/input/input-contact.js +3 -1
  59. package/components/input/input-contact.spec.js +32 -0
  60. package/components/input/input-integer.js +3 -1
  61. package/components/input/input-integer.spec.js +31 -0
  62. package/components/input/input-message.js +3 -1
  63. package/components/input/input-message.spec.js +27 -0
  64. package/components/input/input-money.js +3 -1
  65. package/components/input/input-money.spec.js +30 -0
  66. package/components/input/input-number-mask.js +3 -1
  67. package/components/input/input-number-mask.spec.js +32 -0
  68. package/components/input/input-percentage.js +3 -1
  69. package/components/input/input-percentage.spec.js +31 -0
  70. package/components/input/input-search.js +3 -1
  71. package/components/input/input-search.spec.js +39 -0
  72. package/components/input/input.js +3 -1
  73. package/components/input/input.spec.js +47 -0
  74. package/components/light-mode-switch/light-mode-switch.js +3 -1
  75. package/components/light-mode-switch/light-mode-switch.spec.js +34 -0
  76. package/components/menu-hamburger/menu-hamburger.js +3 -1
  77. package/components/menu-hamburger/menu-hamburger.spec.js +34 -0
  78. package/components/menu-overlay/menu-overlay.js +3 -1
  79. package/components/menu-overlay/menu-overlay.spec.js +44 -0
  80. package/components/message/message.js +3 -1
  81. package/components/message/message.spec.js +42 -0
  82. package/components/modal/__screenshots__/modal-help.spec.js/dile-modal-help-opens-the-inner-modal-on-open---1.png +0 -0
  83. package/components/modal/modal-help.js +3 -1
  84. package/components/modal/modal-help.spec.js +32 -0
  85. package/components/modal/modal.js +3 -1
  86. package/components/modal/modal.spec.js +46 -0
  87. package/components/nav/nav.js +3 -1
  88. package/components/nav/nav.spec.js +33 -0
  89. package/components/number-picker/number-picker-element.js +3 -1
  90. package/components/number-picker/number-picker-element.spec.js +30 -0
  91. package/components/number-picker/number-picker.js +3 -1
  92. package/components/number-picker/number-picker.spec.js +30 -0
  93. package/components/order-switch/order-switch.js +3 -1
  94. package/components/order-switch/order-switch.spec.js +31 -0
  95. package/components/otp-input/otp-input.js +3 -1
  96. package/components/otp-input/otp-input.spec.js +41 -0
  97. package/components/pages/pages.js +3 -1
  98. package/components/pages/pages.spec.js +44 -0
  99. package/components/password/password.js +3 -1
  100. package/components/password/password.spec.js +35 -0
  101. package/components/progress-bar/progress-bar.js +3 -1
  102. package/components/progress-bar/progress-bar.spec.js +28 -0
  103. package/components/radio-group/radio-group.js +3 -1
  104. package/components/radio-group/radio-group.spec.js +44 -0
  105. package/components/radio-group/radio.js +3 -1
  106. package/components/radio-group/radio.spec.js +32 -0
  107. package/components/range/range.js +3 -1
  108. package/components/range/range.spec.js +36 -0
  109. package/components/rating/rating.js +3 -1
  110. package/components/rating/rating.spec.js +34 -0
  111. package/components/rating/star.js +3 -1
  112. package/components/rating/star.spec.js +30 -0
  113. package/components/rating-scale-question/rating-scale-option.js +3 -1
  114. package/components/rating-scale-question/rating-scale-option.spec.js +32 -0
  115. package/components/rating-scale-question/rating-scale-question.js +3 -1
  116. package/components/rating-scale-question/rating-scale-question.spec.js +35 -0
  117. package/components/select/__screenshots__/select-ajax-overlay.spec.js/dile-select-ajax-overlay-Selecting-a-result-clearing-the-selection-returns-to-the-search-field-1.png +0 -0
  118. package/components/select/__screenshots__/select-ajax-overlay.spec.js/dile-select-ajax-overlay-Selecting-a-result-selecting-an-option-sets-value-selectedText--closes-the-popup-and-fires-events-1.png +0 -0
  119. package/components/select/__screenshots__/select-ajax-overlay.spec.js/dile-select-ajax-overlay-Selecting-a-result-shows-the-read-only-field-with-the-clear-icon-after-selecting-1.png +0 -0
  120. package/components/select/__screenshots__/select-ajax-overlay.spec.js/dile-select-ajax-overlay-static-mode-loads-all-data-on-init-and-renders-it-inline-without-requiring-a-search-1.png +0 -0
  121. package/components/select/__screenshots__/select-ajax-overlay.spec.js/dile-select-ajax-overlay-static-mode-shows-a-visible--clickable-trigger-instead-of-hiding-it--there-is-no-separate-search-field-to-compose-under--1.png +0 -0
  122. package/components/select/__screenshots__/select-overlay.spec.js/dile-select-overlay-Positioning-keeps-the-same-moveTop-tightened-gap-when-flipping-above-the-trigger-as-when-sitting-below-it-1.png +0 -0
  123. package/components/select/__screenshots__/select-overlay.spec.js/dile-select-overlay-Rendering-throws-when-no-select-element-is-slotted-1.png +0 -0
  124. package/components/select/__screenshots__/select-overlay.spec.js/dile-select-overlay-hideTrigger-handleExternalKeydown---drives-navigation-without-a-visible-trigger-1.png +0 -0
  125. package/components/select/__screenshots__/zzdebug2.spec.js/debug-static-debug-1.png +0 -0
  126. package/components/select/__screenshots__/zzdebug3.spec.js/debug-rapid-close-reopen-reproduces-blur-then-quick-refocus-1.png +0 -0
  127. package/components/select/index.js +3 -1
  128. package/components/select/select-ajax-overlay.js +6 -0
  129. package/components/select/select-ajax-overlay.spec.js +389 -0
  130. package/components/select/select-ajax.js +3 -1
  131. package/components/select/select-boolean.js +3 -1
  132. package/components/select/select-overlay.js +5 -0
  133. package/components/select/select-overlay.spec.js +507 -0
  134. package/components/select/select.js +3 -1
  135. package/components/select/src/DileSelectAjaxOverlay.js +521 -0
  136. package/components/select/src/DileSelectOverlay.js +511 -0
  137. package/components/selector/selector-item.js +3 -1
  138. package/components/selector/selector-item.spec.js +40 -0
  139. package/components/selector/selector-overlay.js +3 -1
  140. package/components/selector/selector.js +3 -1
  141. package/components/selector/selector.spec.js +45 -0
  142. package/components/slide-menu/slide-menu.js +3 -1
  143. package/components/slide-menu/slide-menu.spec.js +38 -0
  144. package/components/slide-show/slide-show.js +3 -1
  145. package/components/slide-show/slide-show.spec.js +34 -0
  146. package/components/social-icon/social-icon.js +3 -1
  147. package/components/social-icon/social-icon.spec.js +26 -0
  148. package/components/spinner/spinner-bar.js +3 -1
  149. package/components/spinner/spinner-bar.spec.js +26 -0
  150. package/components/spinner/spinner-block.js +3 -1
  151. package/components/spinner/spinner-block.spec.js +21 -0
  152. package/components/spinner/spinner-horizontal.js +3 -1
  153. package/components/spinner/spinner-horizontal.spec.js +25 -0
  154. package/components/spinner/spinner-icon.js +3 -1
  155. package/components/spinner/spinner-icon.spec.js +25 -0
  156. package/components/spinner/spinner-modal.js +3 -1
  157. package/components/spinner/spinner-modal.spec.js +26 -0
  158. package/components/spinner/spinner.js +3 -1
  159. package/components/spinner/spinner.spec.js +26 -0
  160. package/components/switch/switch.js +3 -1
  161. package/components/switch/switch.spec.js +33 -0
  162. package/components/tabs/tab.js +3 -1
  163. package/components/tabs/tabs.js +3 -1
  164. package/components/tabs/tabs.spec.js +45 -0
  165. package/components/textarea/textarea.js +3 -1
  166. package/components/textarea/textarea.spec.js +39 -0
  167. package/components/time-picker/time-picker.js +3 -1
  168. package/components/time-picker/time-picker.spec.js +26 -0
  169. package/components/timer/timer.js +3 -1
  170. package/components/timer/timer.spec.js +31 -0
  171. package/components/toast/toast-item.js +3 -1
  172. package/components/toast/toast-persistent.js +3 -1
  173. package/components/toast/toast.js +3 -1
  174. package/components/tooltip/chip-tooltip.js +3 -1
  175. package/components/tooltip/chip-tooltip.spec.js +29 -0
  176. package/components/tooltip/tooltip.js +3 -1
  177. package/components/tooltip/tooltip.spec.js +32 -0
  178. package/components/web-visor/web-visor.js +3 -1
  179. package/components/web-visor/web-visor.spec.js +32 -0
  180. package/mixins/overlay/src/DileOverlay.js +9 -6
  181. package/package.json +3 -3
@@ -1,3 +1,5 @@
1
1
  import { DileAccordionItem } from './src/DileAccordionItem.js';
2
2
 
3
- window.customElements.define('dile-accordion-item', DileAccordionItem);
3
+ if (!customElements.get('dile-accordion-item')) {
4
+ window.customElements.define('dile-accordion-item', DileAccordionItem);
5
+ }
@@ -1,3 +1,5 @@
1
1
  import { DileAccordion } from './src/DileAccordion.js';
2
2
 
3
- window.customElements.define('dile-accordion', DileAccordion);
3
+ if (!customElements.get('dile-accordion')) {
4
+ window.customElements.define('dile-accordion', DileAccordion);
5
+ }
@@ -1,3 +1,5 @@
1
1
  import { DileAppDrawer } from "./src/DileAppDrawer.js";
2
2
 
3
- customElements.define("dile-app-drawer", DileAppDrawer);
3
+ if (!customElements.get("dile-app-drawer")) {
4
+ customElements.define("dile-app-drawer", DileAppDrawer);
5
+ }
@@ -1,3 +1,5 @@
1
1
  import { DileAvatar } from "./src/DileAvatar.js";
2
2
 
3
- window.customElements.define("dile-avatar", DileAvatar);
3
+ if (!customElements.get("dile-avatar")) {
4
+ window.customElements.define("dile-avatar", DileAvatar);
5
+ }
@@ -0,0 +1,25 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './avatar.js';
3
+
4
+ describe('dile-avatar', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderAvatar(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-avatar');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('renders an image placeholder div when no initial is set', async () => {
17
+ const el = await renderAvatar('<dile-avatar></dile-avatar>');
18
+ expect(el.shadowRoot.querySelector('#img')).toBeTruthy();
19
+ });
20
+
21
+ it('renders the first letter of the initial property', async () => {
22
+ const el = await renderAvatar('<dile-avatar initial="Miguel"></dile-avatar>');
23
+ expect(el.shadowRoot.querySelector('.initial').textContent.trim()).toBe('M');
24
+ });
25
+ });
@@ -1,2 +1,4 @@
1
1
  import { DileBoxSelectorItem } from './src/DileBoxSelectorItem.js';
2
- customElements.define("dile-box-selector-item", DileBoxSelectorItem);
2
+ if (!customElements.get("dile-box-selector-item")) {
3
+ customElements.define("dile-box-selector-item", DileBoxSelectorItem);
4
+ }
@@ -0,0 +1,27 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './box-selector-item.js';
3
+
4
+ describe('dile-box-selector-item', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderItem(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-box-selector-item');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('renders the label property', async () => {
17
+ const el = await renderItem('<dile-box-selector-item label="Option A"></dile-box-selector-item>');
18
+ expect(el.shadowRoot.textContent.trim()).toBe('Option A');
19
+ });
20
+
21
+ it('reflects selected attribute when clicked', async () => {
22
+ const el = await renderItem('<dile-box-selector-item label="Option A"></dile-box-selector-item>');
23
+ el.select();
24
+ await el.updateComplete;
25
+ expect(el.selected).toBe(false);
26
+ });
27
+ });
@@ -1,2 +1,4 @@
1
1
  import { DileBoxSelector } from './src/DileBoxSelector.js'
2
- customElements.define("dile-box-selector", DileBoxSelector);
2
+ if (!customElements.get("dile-box-selector")) {
3
+ customElements.define("dile-box-selector", DileBoxSelector);
4
+ }
@@ -0,0 +1,27 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './box-selector.js';
3
+ import './box-selector-item.js';
4
+
5
+ describe('dile-box-selector', () => {
6
+ afterEach(() => {
7
+ document.body.innerHTML = '';
8
+ });
9
+
10
+ async function renderSelector(html) {
11
+ document.body.innerHTML = html;
12
+ const el = document.body.querySelector('dile-box-selector');
13
+ await el.updateComplete;
14
+ return el;
15
+ }
16
+
17
+ it('renders the slotted items', async () => {
18
+ const el = await renderSelector(`
19
+ <dile-box-selector>
20
+ <dile-box-selector-item label="One"></dile-box-selector-item>
21
+ <dile-box-selector-item label="Two"></dile-box-selector-item>
22
+ </dile-box-selector>
23
+ `);
24
+ expect(el.shadowRoot.querySelector('slot')).toBeTruthy();
25
+ expect(el.querySelectorAll('dile-box-selector-item').length).toBe(2);
26
+ });
27
+ });
@@ -1,3 +1,5 @@
1
1
  import { DileBreadcrumbsItem } from "./src/DileBreadcrumbsItem.js";
2
2
 
3
- window.customElements.define("dile-breadcrumbs-item", DileBreadcrumbsItem);
3
+ if (!customElements.get("dile-breadcrumbs-item")) {
4
+ window.customElements.define("dile-breadcrumbs-item", DileBreadcrumbsItem);
5
+ }
@@ -0,0 +1,28 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './breadcrumbs-item.js';
3
+
4
+ describe('dile-breadcrumbs-item', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderItem(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-breadcrumbs-item');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('renders an anchor when href is set', async () => {
17
+ const el = await renderItem('<dile-breadcrumbs-item href="/home">Home</dile-breadcrumbs-item>');
18
+ const anchor = el.shadowRoot.querySelector('a');
19
+ expect(anchor).toBeTruthy();
20
+ expect(anchor.getAttribute('href')).toBe('/home');
21
+ });
22
+
23
+ it('renders a span when href is not set', async () => {
24
+ const el = await renderItem('<dile-breadcrumbs-item>Current</dile-breadcrumbs-item>');
25
+ expect(el.shadowRoot.querySelector('span')).toBeTruthy();
26
+ expect(el.shadowRoot.querySelector('a')).toBeNull();
27
+ });
28
+ });
@@ -1,4 +1,6 @@
1
1
  import './breadcrumbs-item.js';
2
2
  import { DileBreadcrumbs } from "./src/DileBreadcrumbs.js";
3
3
 
4
- window.customElements.define("dile-breadcrumbs", DileBreadcrumbs);
4
+ if (!customElements.get("dile-breadcrumbs")) {
5
+ window.customElements.define("dile-breadcrumbs", DileBreadcrumbs);
6
+ }
@@ -0,0 +1,33 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './breadcrumbs.js';
3
+
4
+ describe('dile-breadcrumbs', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderBreadcrumbs(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-breadcrumbs');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('renders slotted breadcrumb items', async () => {
17
+ const el = await renderBreadcrumbs(`
18
+ <dile-breadcrumbs>
19
+ <dile-breadcrumbs-item href="/">Home</dile-breadcrumbs-item>
20
+ <dile-breadcrumbs-item>Current</dile-breadcrumbs-item>
21
+ </dile-breadcrumbs>
22
+ `);
23
+ expect(el.querySelectorAll('dile-breadcrumbs-item').length).toBe(2);
24
+ });
25
+
26
+ it('renders items from the items property', async () => {
27
+ const el = await renderBreadcrumbs('<dile-breadcrumbs></dile-breadcrumbs>');
28
+ el.items = [{ text: 'Home', href: '/' }, { text: 'Page' }];
29
+ await el.updateComplete;
30
+
31
+ expect(el.shadowRoot.querySelectorAll('dile-breadcrumbs-item').length).toBe(2);
32
+ });
33
+ });
@@ -1,3 +1,5 @@
1
1
  import { DileButtonIcon } from "./src/DileButtonIcon.js";
2
2
 
3
- window.customElements.define("dile-button-icon", DileButtonIcon);
3
+ if (!customElements.get("dile-button-icon")) {
4
+ window.customElements.define("dile-button-icon", DileButtonIcon);
5
+ }
@@ -1,3 +1,5 @@
1
1
  import { DileButton } from "./src/DileButton.js";
2
2
 
3
- window.customElements.define("dile-button", DileButton);
3
+ if (!customElements.get("dile-button")) {
4
+ window.customElements.define("dile-button", DileButton);
5
+ }
@@ -1,3 +1,5 @@
1
1
  import { DileCardSlide } from "./src/DileCardSlide.js";
2
2
 
3
- window.customElements.define("dile-card-slide", DileCardSlide);
3
+ if (!customElements.get("dile-card-slide")) {
4
+ window.customElements.define("dile-card-slide", DileCardSlide);
5
+ }
@@ -0,0 +1,30 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './card-slide.js';
3
+
4
+ describe('dile-card-slide', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderCardSlide(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-card-slide');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('renders the title as a toggle button', async () => {
17
+ const el = await renderCardSlide('<dile-card-slide title="My title">Content</dile-card-slide>');
18
+ const button = el.shadowRoot.querySelector('.card-title button');
19
+ expect(button).toBeTruthy();
20
+ expect(el.opened).toBe(false);
21
+ });
22
+
23
+ it('toggles opened state when clicked', async () => {
24
+ const el = await renderCardSlide('<dile-card-slide title="My title">Content</dile-card-slide>');
25
+ el.shadowRoot.querySelector('.card-title button').click();
26
+ await el.updateComplete;
27
+
28
+ expect(el.opened).toBe(true);
29
+ });
30
+ });
@@ -1,3 +1,5 @@
1
1
  import { DileCard } from "./src/DileCard.js";
2
2
 
3
- window.customElements.define("dile-card", DileCard);
3
+ if (!customElements.get("dile-card")) {
4
+ window.customElements.define("dile-card", DileCard);
5
+ }
@@ -0,0 +1,26 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './card.js';
3
+
4
+ describe('dile-card', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderCard(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-card');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('renders the title and slotted content', async () => {
17
+ const el = await renderCard('<dile-card title="My title">Content</dile-card>');
18
+ expect(el.shadowRoot.querySelector('.card-title').textContent.trim()).toBe('My title');
19
+ expect(el.textContent.trim()).toBe('Content');
20
+ });
21
+
22
+ it('does not render a title element when title is not set', async () => {
23
+ const el = await renderCard('<dile-card>Content</dile-card>');
24
+ expect(el.shadowRoot.querySelector('.card-title')).toBeNull();
25
+ });
26
+ });
@@ -1,3 +1,5 @@
1
1
  import { DileCheckbox } from "./src/DileCheckbox.js";
2
2
 
3
- window.customElements.define("dile-checkbox", DileCheckbox);
3
+ if (!customElements.get("dile-checkbox")) {
4
+ window.customElements.define("dile-checkbox", DileCheckbox);
5
+ }
@@ -1,2 +1,4 @@
1
1
  import { DileChip } from "./src/DileChip.js";
2
- customElements.define('dile-chip', DileChip);
2
+ if (!customElements.get('dile-chip')) {
3
+ customElements.define('dile-chip', DileChip);
4
+ }
@@ -0,0 +1,31 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './chip.js';
3
+
4
+ describe('dile-chip', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderChip(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-chip');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('renders the slotted content and a close icon', async () => {
17
+ const el = await renderChip('<dile-chip>Tag</dile-chip>');
18
+ expect(el.textContent.trim()).toBe('Tag');
19
+ expect(el.shadowRoot.querySelector('dile-icon')).toBeTruthy();
20
+ });
21
+
22
+ it('dispatches dile-chip-icon-click with the name when the icon is clicked', async () => {
23
+ const el = await renderChip('<dile-chip name="tag1">Tag</dile-chip>');
24
+ let detail = null;
25
+ el.addEventListener('dile-chip-icon-click', (e) => { detail = e.detail; });
26
+
27
+ el.shadowRoot.querySelector('dile-icon').click();
28
+
29
+ expect(detail).toEqual({ name: 'tag1' });
30
+ });
31
+ });
@@ -1,3 +1,5 @@
1
1
  import { DileColorPicker } from './src/DileColorPicker.js';
2
2
 
3
- window.customElements.define('dile-color-picker', DileColorPicker);
3
+ if (!customElements.get('dile-color-picker')) {
4
+ window.customElements.define('dile-color-picker', DileColorPicker);
5
+ }
@@ -1,3 +1,5 @@
1
1
  import { DileConfirm } from './src/DileConfirm.js';
2
2
 
3
- customElements.define("dile-confirm", DileConfirm);
3
+ if (!customElements.get("dile-confirm")) {
4
+ customElements.define("dile-confirm", DileConfirm);
5
+ }
@@ -0,0 +1,32 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './confirm.js';
3
+
4
+ describe('dile-confirm', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderConfirm(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-confirm');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('renders a dile-modal with the default action labels', async () => {
17
+ const el = await renderConfirm('<dile-confirm>Are you sure?</dile-confirm>');
18
+ expect(el.shadowRoot.querySelector('dile-modal')).toBeTruthy();
19
+ expect(el.shadowRoot.querySelector('.accept').textContent.trim()).toBe('Accept');
20
+ expect(el.shadowRoot.querySelector('.cancel').textContent.trim()).toBe('Cancell');
21
+ });
22
+
23
+ it('dispatches dile-confirm-accepted when accept is clicked', async () => {
24
+ const el = await renderConfirm('<dile-confirm>Are you sure?</dile-confirm>');
25
+ let accepted = false;
26
+ el.addEventListener('dile-confirm-accepted', () => { accepted = true; });
27
+
28
+ el.shadowRoot.querySelector('.accept').click();
29
+
30
+ expect(accepted).toBe(true);
31
+ });
32
+ });
@@ -1,3 +1,5 @@
1
1
  import { DileConfirmText } from './src/DileConfirmText.js';
2
2
 
3
- window.customElements.define('dile-confirm-text', DileConfirmText);
3
+ if (!customElements.get('dile-confirm-text')) {
4
+ window.customElements.define('dile-confirm-text', DileConfirmText);
5
+ }
@@ -0,0 +1,29 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './confirm-text.js';
3
+
4
+ describe('dile-confirm-text', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderConfirmText(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-confirm-text');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('renders the title and an input to type the confirmation text', async () => {
17
+ const el = await renderConfirmText('<dile-confirm-text title="Delete item">This cannot be undone</dile-confirm-text>');
18
+ expect(el.shadowRoot.querySelector('.title').textContent.trim()).toBe('Delete item');
19
+ expect(el.shadowRoot.querySelector('dile-input')).toBeTruthy();
20
+ });
21
+
22
+ it('shows negative feedback when accepting with an empty text field', async () => {
23
+ const el = await renderConfirmText('<dile-confirm-text>Confirm</dile-confirm-text>');
24
+ el.shadowRoot.querySelector('.accept').click();
25
+ await el.updateComplete;
26
+
27
+ expect(el.feedback.shadowRoot.textContent).toContain(el.emptyTextMessage);
28
+ });
29
+ });
@@ -0,0 +1,27 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './copy-markdown-url.js';
3
+
4
+ describe('dile-copy-markdown-url', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderCopyMarkdownUrl(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-copy-markdown-url');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('renders a dile-copy-text with the slotted content', async () => {
17
+ const el = await renderCopyMarkdownUrl('<dile-copy-markdown-url url="/doc.md">Copy link</dile-copy-markdown-url>');
18
+ expect(el.shadowRoot.querySelector('dile-copy-text')).toBeTruthy();
19
+ expect(el.textContent.trim()).toBe('Copy link');
20
+ });
21
+
22
+ it('defaults to an empty url and content', async () => {
23
+ const el = await renderCopyMarkdownUrl('<dile-copy-markdown-url></dile-copy-markdown-url>');
24
+ expect(el.url).toBe('');
25
+ expect(el.content).toBe('');
26
+ });
27
+ });
@@ -1,5 +1,7 @@
1
1
  import { DileCopyMarkdownUrl } from './src/DileCopyMarkdownUrl.js';
2
2
 
3
- window.customElements.define('dile-copy-markdown-url', DileCopyMarkdownUrl);
3
+ if (!customElements.get('dile-copy-markdown-url')) {
4
+ window.customElements.define('dile-copy-markdown-url', DileCopyMarkdownUrl);
5
+ }
4
6
 
5
7
  export { DileCopyMarkdownUrl };
@@ -0,0 +1,38 @@
1
+ import { describe, it, expect, afterEach, vi } from 'vitest';
2
+ import './copy-text.js';
3
+
4
+ describe('dile-copy-text', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderCopyText(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-copy-text');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('renders the slotted content inside a clickable link', async () => {
17
+ const el = await renderCopyText('<dile-copy-text content="hello">Copy me</dile-copy-text>');
18
+ const link = el.shadowRoot.querySelector('a');
19
+ expect(link).toBeTruthy();
20
+ expect(el.textContent.trim()).toBe('Copy me');
21
+ });
22
+
23
+ it('dispatches dile-text-copied with the content on copy()', async () => {
24
+ const el = await renderCopyText('<dile-copy-text content="hello">Copy me</dile-copy-text>');
25
+ const writeText = vi.fn().mockResolvedValue(undefined);
26
+ vi.stubGlobal('navigator', { ...navigator, clipboard: { writeText } });
27
+
28
+ let detail = null;
29
+ el.addEventListener('dile-text-copied', (e) => { detail = e.detail; });
30
+
31
+ await el.copy();
32
+
33
+ expect(writeText).toHaveBeenCalledWith('hello');
34
+ expect(detail).toEqual({ text: 'hello' });
35
+
36
+ vi.unstubAllGlobals();
37
+ });
38
+ });
@@ -1,5 +1,7 @@
1
1
  import { DileCopyText } from './src/DileCopyText.js';
2
2
 
3
- window.customElements.define('dile-copy-text', DileCopyText);
3
+ if (!customElements.get('dile-copy-text')) {
4
+ window.customElements.define('dile-copy-text', DileCopyText);
5
+ }
4
6
 
5
7
  export { DileCopyText };
@@ -1,3 +1,5 @@
1
1
  import { DileDropFile } from "./src/DileDropFile.js";
2
2
 
3
- customElements.define('dile-drop-file', DileDropFile);
3
+ if (!customElements.get('dile-drop-file')) {
4
+ customElements.define('dile-drop-file', DileDropFile);
5
+ }
@@ -0,0 +1,33 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './drop-file.js';
3
+
4
+ describe('dile-drop-file', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderDropFile(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-drop-file');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('renders the drop zone with label and file input', async () => {
17
+ const el = await renderDropFile('<dile-drop-file label="Upload"></dile-drop-file>');
18
+ expect(el.shadowRoot.querySelector('#dropZone')).toBeTruthy();
19
+ expect(el.shadowRoot.querySelector('label').textContent.trim()).toBe('Upload');
20
+ expect(el.shadowRoot.querySelector('input[type="file"]')).toBeTruthy();
21
+ });
22
+
23
+ it('clears the selected file name', async () => {
24
+ const el = await renderDropFile('<dile-drop-file></dile-drop-file>');
25
+ el.fileName = 'test.png';
26
+ await el.updateComplete;
27
+
28
+ el.clear();
29
+ await el.updateComplete;
30
+
31
+ expect(el.fileName).toBe('');
32
+ });
33
+ });
@@ -1,2 +1,4 @@
1
1
  import { DileFilePreview } from "./src/DileFilePreview.js";
2
- customElements.define('dile-file-preview', DileFilePreview);
2
+ if (!customElements.get('dile-file-preview')) {
3
+ customElements.define('dile-file-preview', DileFilePreview);
4
+ }
@@ -0,0 +1,35 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './file-preview.js';
3
+
4
+ describe('dile-file-preview', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ });
8
+
9
+ async function renderFilePreview(html) {
10
+ document.body.innerHTML = html;
11
+ const el = document.body.querySelector('dile-file-preview');
12
+ await el.updateComplete;
13
+ return el;
14
+ }
15
+
16
+ it('renders nothing when there is no fileName', async () => {
17
+ const el = await renderFilePreview('<dile-file-preview></dile-file-preview>');
18
+ expect(el.shadowRoot.querySelector('div')).toBeNull();
19
+ });
20
+
21
+ it('renders the file name and a clear link when fileName is set', async () => {
22
+ const el = await renderFilePreview('<dile-file-preview fileName="report.pdf" selectedFileLabel="Selected"></dile-file-preview>');
23
+ expect(el.shadowRoot.querySelector('div span').textContent).toContain('report.pdf');
24
+ });
25
+
26
+ it('dispatches dile-file-clear when the clear link is clicked', async () => {
27
+ const el = await renderFilePreview('<dile-file-preview fileName="report.pdf"></dile-file-preview>');
28
+ let detail = null;
29
+ el.addEventListener('dile-file-clear', (e) => { detail = e.detail; });
30
+
31
+ el.shadowRoot.querySelector('a').click();
32
+
33
+ expect(detail).toEqual({ fileName: 'report.pdf' });
34
+ });
35
+ });
@@ -0,0 +1,30 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import './floating-feedback.js';
3
+
4
+ describe('dile-floating-feedback', () => {
5
+ afterEach(() => {
6
+ document.body.innerHTML = '';
7
+ const styles = document.getElementById('dile-floating-feedback-styles');
8
+ if (styles) styles.remove();
9
+ });
10
+
11
+ async function renderFloatingFeedback(html) {
12
+ document.body.innerHTML = html;
13
+ const el = document.body.querySelector('dile-floating-feedback');
14
+ await el.updateComplete;
15
+ return el;
16
+ }
17
+
18
+ it('renders the slotted content', async () => {
19
+ const el = await renderFloatingFeedback('<dile-floating-feedback feedback="Copied!"><button>Click</button></dile-floating-feedback>');
20
+ expect(el.shadowRoot.querySelector('slot')).toBeTruthy();
21
+ expect(el.textContent.trim()).toBe('Click');
22
+ });
23
+
24
+ it('creates a floating text element in the document body when shown', async () => {
25
+ const el = await renderFloatingFeedback('<dile-floating-feedback feedback="Copied!"><button>Click</button></dile-floating-feedback>');
26
+ el.show();
27
+
28
+ expect(document.body.querySelector('.dile-floating-feedback-text')).toBeTruthy();
29
+ });
30
+ });