@nuvia-ui/components 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +27 -0
- package/src/ds-accordion/ds-accordion-item.js +288 -0
- package/src/ds-accordion/ds-accordion-item.stories.js +82 -0
- package/src/ds-accordion/ds-accordion.a11y.test.js +92 -0
- package/src/ds-accordion/ds-accordion.js +68 -0
- package/src/ds-accordion/ds-accordion.stories.js +118 -0
- package/src/ds-accordion/ds-accordion.test.js +146 -0
- package/src/ds-accordion/index.js +2 -0
- package/src/ds-action-bar/ds-action-bar.js +116 -0
- package/src/ds-action-bar/ds-action-bar.stories.js +86 -0
- package/src/ds-action-bar/ds-action-bar.test.js +64 -0
- package/src/ds-action-bar/index.js +1 -0
- package/src/ds-alert/ds-alert.a11y.test.js +151 -0
- package/src/ds-alert/ds-alert.js +223 -0
- package/src/ds-alert/ds-alert.mdx +142 -0
- package/src/ds-alert/ds-alert.stories.js +166 -0
- package/src/ds-alert/ds-alert.test.js +256 -0
- package/src/ds-alert/index.js +1 -0
- package/src/ds-avatar/ds-avatar.a11y.test.js +45 -0
- package/src/ds-avatar/ds-avatar.js +216 -0
- package/src/ds-avatar/ds-avatar.stories.js +120 -0
- package/src/ds-avatar/ds-avatar.test.js +83 -0
- package/src/ds-avatar/index.js +1 -0
- package/src/ds-avatar-extended/ds-avatar-extended.a11y.test.js +29 -0
- package/src/ds-avatar-extended/ds-avatar-extended.js +108 -0
- package/src/ds-avatar-extended/ds-avatar-extended.stories.js +93 -0
- package/src/ds-avatar-extended/ds-avatar-extended.test.js +66 -0
- package/src/ds-avatar-extended/index.js +1 -0
- package/src/ds-banner/ds-banner.a11y.test.js +51 -0
- package/src/ds-banner/ds-banner.js +233 -0
- package/src/ds-banner/ds-banner.stories.js +185 -0
- package/src/ds-banner/ds-banner.test.js +116 -0
- package/src/ds-banner/index.js +1 -0
- package/src/ds-breadcrumb-item/ds-breadcrumb-item.js +135 -0
- package/src/ds-breadcrumb-item/ds-breadcrumb-item.stories.js +49 -0
- package/src/ds-breadcrumb-item/ds-breadcrumb-item.test.js +55 -0
- package/src/ds-breadcrumbs/ds-breadcrumbs.js +194 -0
- package/src/ds-breadcrumbs/ds-breadcrumbs.stories.js +54 -0
- package/src/ds-breadcrumbs/ds-breadcrumbs.test.js +33 -0
- package/src/ds-button/ds-button.a11y.test.js +49 -0
- package/src/ds-button/ds-button.js +205 -0
- package/src/ds-button/ds-button.mdx +141 -0
- package/src/ds-button/ds-button.stories.js +152 -0
- package/src/ds-button/ds-button.test.js +62 -0
- package/src/ds-button/index.js +1 -0
- package/src/ds-button-group/ds-button-group.js +82 -0
- package/src/ds-button-group/ds-button-group.mdx +39 -0
- package/src/ds-button-group/ds-button-group.stories.js +47 -0
- package/src/ds-button-group/ds-button-group.test.js +47 -0
- package/src/ds-button-group/index.js +1 -0
- package/src/ds-checkbox/ds-checkbox.a11y.test.js +79 -0
- package/src/ds-checkbox/ds-checkbox.js +271 -0
- package/src/ds-checkbox/ds-checkbox.stories.js +77 -0
- package/src/ds-checkbox/ds-checkbox.test.js +191 -0
- package/src/ds-checkbox/index.js +1 -0
- package/src/ds-checkbox-group/ds-checkbox-group.a11y.test.js +146 -0
- package/src/ds-checkbox-group/ds-checkbox-group.js +235 -0
- package/src/ds-checkbox-group/ds-checkbox-group.stories.js +210 -0
- package/src/ds-checkbox-group/ds-checkbox-group.test.js +150 -0
- package/src/ds-checkbox-group/index.js +1 -0
- package/src/ds-dialog/ds-dialog.js +466 -0
- package/src/ds-dialog/ds-dialog.stories.js +274 -0
- package/src/ds-dialog/ds-dialog.test.js +441 -0
- package/src/ds-dialog/index.js +1 -0
- package/src/ds-dropdown/ds-dropdown.a11y.test.js +80 -0
- package/src/ds-dropdown/ds-dropdown.js +891 -0
- package/src/ds-dropdown/ds-dropdown.stories.js +259 -0
- package/src/ds-dropdown/ds-dropdown.test.js +268 -0
- package/src/ds-dropdown/index.js +1 -0
- package/src/ds-dropdown-group/ds-dropdown-group.js +55 -0
- package/src/ds-dropdown-panel/ds-dropdown-panel.js +34 -0
- package/src/ds-file-uploaded/ds-file-uploaded.a11y.test.js +40 -0
- package/src/ds-file-uploaded/ds-file-uploaded.js +135 -0
- package/src/ds-file-uploaded/ds-file-uploaded.mdx +33 -0
- package/src/ds-file-uploaded/ds-file-uploaded.stories.js +81 -0
- package/src/ds-file-uploaded/ds-file-uploaded.test.js +85 -0
- package/src/ds-file-uploader/ds-file-uploader.a11y.test.js +61 -0
- package/src/ds-file-uploader/ds-file-uploader.js +442 -0
- package/src/ds-file-uploader/ds-file-uploader.mdx +44 -0
- package/src/ds-file-uploader/ds-file-uploader.stories.js +76 -0
- package/src/ds-file-uploader/ds-file-uploader.test.js +142 -0
- package/src/ds-header/ds-header.a11y.test.js +38 -0
- package/src/ds-header/ds-header.js +149 -0
- package/src/ds-header/ds-header.stories.js +63 -0
- package/src/ds-header/ds-header.test.js +52 -0
- package/src/ds-header/index.js +1 -0
- package/src/ds-header-nav/ds-header-nav.a11y.test.js +69 -0
- package/src/ds-header-nav/ds-header-nav.js +114 -0
- package/src/ds-header-nav/ds-header-nav.stories.js +17 -0
- package/src/ds-header-nav/ds-header-nav.test.js +93 -0
- package/src/ds-header-nav-item/ds-header-nav-item.a11y.test.js +71 -0
- package/src/ds-header-nav-item/ds-header-nav-item.js +124 -0
- package/src/ds-header-nav-item/ds-header-nav-item.stories.js +43 -0
- package/src/ds-header-nav-item/ds-header-nav-item.test.js +61 -0
- package/src/ds-icon/ds-icon.a11y.test.js +49 -0
- package/src/ds-icon/ds-icon.js +75 -0
- package/src/ds-icon/ds-icon.mdx +36 -0
- package/src/ds-icon/ds-icon.stories.js +88 -0
- package/src/ds-icon/ds-icon.test.js +97 -0
- package/src/ds-icon/index.js +1 -0
- package/src/ds-icon-button/ds-icon-button.a11y.test.js +55 -0
- package/src/ds-icon-button/ds-icon-button.js +224 -0
- package/src/ds-icon-button/ds-icon-button.mdx +131 -0
- package/src/ds-icon-button/ds-icon-button.stories.js +128 -0
- package/src/ds-icon-button/ds-icon-button.test.js +90 -0
- package/src/ds-icon-button/index.js +1 -0
- package/src/ds-input/ds-input.a11y.test.js +145 -0
- package/src/ds-input/ds-input.js +645 -0
- package/src/ds-input/ds-input.mdx +251 -0
- package/src/ds-input/ds-input.stories.js +298 -0
- package/src/ds-input/ds-input.test.js +792 -0
- package/src/ds-input/index.js +1 -0
- package/src/ds-link/ds-link.js +111 -0
- package/src/ds-link/ds-link.stories.js +56 -0
- package/src/ds-link/ds-link.test.js +74 -0
- package/src/ds-list-item/ds-list-item.a11y.test.js +39 -0
- package/src/ds-list-item/ds-list-item.js +292 -0
- package/src/ds-list-item/ds-list-item.stories.js +101 -0
- package/src/ds-list-item/ds-list-item.test.js +63 -0
- package/src/ds-menu/ds-menu.js +30 -0
- package/src/ds-menu/ds-menu.stories.js +120 -0
- package/src/ds-menu/ds-menu.test.js +123 -0
- package/src/ds-menu-group/ds-menu-group.js +101 -0
- package/src/ds-menu-group/ds-menu-group.stories.js +99 -0
- package/src/ds-nav-item/ds-nav-item.a11y.test.js +91 -0
- package/src/ds-nav-item/ds-nav-item.js +307 -0
- package/src/ds-nav-item/ds-nav-item.stories.js +99 -0
- package/src/ds-nav-item/ds-nav-item.test.js +169 -0
- package/src/ds-nav-item/index.js +1 -0
- package/src/ds-nav-vertical/ds-nav-vertical.a11y.test.js +69 -0
- package/src/ds-nav-vertical/ds-nav-vertical.js +173 -0
- package/src/ds-nav-vertical/ds-nav-vertical.stories.js +124 -0
- package/src/ds-nav-vertical/ds-nav-vertical.test.js +176 -0
- package/src/ds-nav-vertical/index.js +1 -0
- package/src/ds-pagination/ds-pagination.a11y.test.js +50 -0
- package/src/ds-pagination/ds-pagination.js +232 -0
- package/src/ds-pagination/ds-pagination.stories.js +63 -0
- package/src/ds-pagination/ds-pagination.test.js +141 -0
- package/src/ds-pagination/index.js +1 -0
- package/src/ds-progress-bar/ds-progress-bar.a11y.test.js +25 -0
- package/src/ds-progress-bar/ds-progress-bar.js +81 -0
- package/src/ds-progress-bar/ds-progress-bar.stories.js +69 -0
- package/src/ds-progress-bar/ds-progress-bar.test.js +60 -0
- package/src/ds-radio/ds-radio.a11y.test.js +69 -0
- package/src/ds-radio/ds-radio.js +240 -0
- package/src/ds-radio/ds-radio.stories.js +102 -0
- package/src/ds-radio/ds-radio.test.js +114 -0
- package/src/ds-radio/index.js +1 -0
- package/src/ds-radio-group/ds-radio-group.a11y.test.js +164 -0
- package/src/ds-radio-group/ds-radio-group.js +257 -0
- package/src/ds-radio-group/ds-radio-group.stories.js +247 -0
- package/src/ds-radio-group/ds-radio-group.test.js +194 -0
- package/src/ds-radio-group/index.js +1 -0
- package/src/ds-rich-list/ds-rich-list.js +246 -0
- package/src/ds-rich-list/ds-rich-list.stories.js +368 -0
- package/src/ds-rich-list/ds-rich-list.test.js +293 -0
- package/src/ds-rich-list-item/ds-rich-list-item.js +579 -0
- package/src/ds-rich-list-item/ds-rich-list-item.stories.js +197 -0
- package/src/ds-rich-list-item/ds-rich-list-item.test.js +434 -0
- package/src/ds-slider/ds-slider.js +399 -0
- package/src/ds-slider/ds-slider.stories.js +107 -0
- package/src/ds-slider/ds-slider.test.js +308 -0
- package/src/ds-spinner/ds-spinner.js +173 -0
- package/src/ds-spinner/ds-spinner.stories.js +52 -0
- package/src/ds-spinner/ds-spinner.test.js +50 -0
- package/src/ds-status-border/ds-status-border.js +88 -0
- package/src/ds-status-border/ds-status-border.stories.js +242 -0
- package/src/ds-status-border/ds-status-border.test.js +168 -0
- package/src/ds-stepper/ds-stepper.a11y.test.js +198 -0
- package/src/ds-stepper/ds-stepper.js +207 -0
- package/src/ds-stepper/ds-stepper.stories.js +530 -0
- package/src/ds-stepper/ds-stepper.test.js +311 -0
- package/src/ds-stepper-item/ds-stepper-item.js +485 -0
- package/src/ds-stepper-item/ds-stepper-item.stories.js +288 -0
- package/src/ds-switch/ds-switch.js +348 -0
- package/src/ds-switch/ds-switch.stories.js +145 -0
- package/src/ds-switch/ds-switch.test.js +226 -0
- package/src/ds-switch/index.js +1 -0
- package/src/ds-tab-item/ds-tab-item.js +341 -0
- package/src/ds-tab-item/ds-tab-item.stories.js +69 -0
- package/src/ds-tabs/ds-tab-panel.js +48 -0
- package/src/ds-tabs/ds-tabs.a11y.test.js +56 -0
- package/src/ds-tabs/ds-tabs.js +180 -0
- package/src/ds-tabs/ds-tabs.stories.js +152 -0
- package/src/ds-tabs/ds-tabs.test.js +306 -0
- package/src/ds-tabs/index.js +3 -0
- package/src/ds-tag-action/ds-tag-action.a11y.test.js +32 -0
- package/src/ds-tag-action/ds-tag-action.js +185 -0
- package/src/ds-tag-action/ds-tag-action.stories.js +55 -0
- package/src/ds-tag-action/ds-tag-action.test.js +44 -0
- package/src/ds-tag-removable/ds-tag-removable.a11y.test.js +24 -0
- package/src/ds-tag-removable/ds-tag-removable.js +146 -0
- package/src/ds-tag-removable/ds-tag-removable.stories.js +52 -0
- package/src/ds-tag-removable/ds-tag-removable.test.js +46 -0
- package/src/ds-tag-status/ds-tag-status.a11y.test.js +93 -0
- package/src/ds-tag-status/ds-tag-status.js +164 -0
- package/src/ds-tag-status/ds-tag-status.stories.js +200 -0
- package/src/ds-tag-status/ds-tag-status.test.js +140 -0
- package/src/ds-tag-status/index.js +1 -0
- package/src/ds-textarea/ds-textarea-clearable.test.js +89 -0
- package/src/ds-textarea/ds-textarea.a11y.test.js +66 -0
- package/src/ds-textarea/ds-textarea.js +505 -0
- package/src/ds-textarea/ds-textarea.stories.js +335 -0
- package/src/ds-textarea/ds-textarea.test.js +218 -0
- package/src/ds-textarea/index.js +1 -0
- package/src/ds-thumbnail/ds-thumbnail.js +207 -0
- package/src/ds-thumbnail/ds-thumbnail.stories.js +217 -0
- package/src/ds-thumbnail/ds-thumbnail.test.js +220 -0
- package/src/ds-toast/ds-toast-provider.js +110 -0
- package/src/ds-toast/ds-toast.a11y.test.js +34 -0
- package/src/ds-toast/ds-toast.js +243 -0
- package/src/ds-toast/ds-toast.stories.js +143 -0
- package/src/ds-toast/ds-toast.test.js +93 -0
- package/src/ds-toast/index.js +2 -0
- package/src/ds-tooltip/ds-tooltip.a11y.test.js +110 -0
- package/src/ds-tooltip/ds-tooltip.js +217 -0
- package/src/ds-tooltip/ds-tooltip.mdx +75 -0
- package/src/ds-tooltip/ds-tooltip.stories.js +72 -0
- package/src/ds-tooltip/ds-tooltip.test.js +191 -0
- package/src/ds-tooltip/index.js +1 -0
- package/src/ds-tooltip/positioner.js +117 -0
- package/src/index.js +50 -0
- package/src/mixins/field-label.mixin.js +113 -0
- package/src/mixins/field-message.mixin.js +66 -0
- package/src/token-provider/index.js +1 -0
- package/src/token-provider/token-provider.a11y.test.js +44 -0
- package/src/token-provider/token-provider.js +85 -0
- package/src/token-provider/token-provider.stories.js +105 -0
- package/src/token-provider/token-provider.test.js +134 -0
- package/src/utils/number-input.utils.js +42 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import './ds-rich-list.js';
|
|
3
|
+
import '../ds-rich-list-item/ds-rich-list-item.js';
|
|
4
|
+
|
|
5
|
+
describe('ds-rich-list', () => {
|
|
6
|
+
let container;
|
|
7
|
+
|
|
8
|
+
const tick = (ms = 50) => new Promise(resolve => setTimeout(resolve, ms));
|
|
9
|
+
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
container = document.createElement('div');
|
|
12
|
+
document.body.appendChild(container);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
container.remove();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// ─── Rendering ───
|
|
20
|
+
|
|
21
|
+
it('renders with default values', async () => {
|
|
22
|
+
container.innerHTML = '<ds-rich-list></ds-rich-list>';
|
|
23
|
+
const el = container.querySelector('ds-rich-list');
|
|
24
|
+
await tick();
|
|
25
|
+
|
|
26
|
+
expect(el.selectable).toBe('none');
|
|
27
|
+
expect(el.name).toBe('');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('renders items via slot', async () => {
|
|
31
|
+
container.innerHTML = `
|
|
32
|
+
<ds-rich-list>
|
|
33
|
+
<ds-rich-list-item value="a"><span slot="title">A</span></ds-rich-list-item>
|
|
34
|
+
<ds-rich-list-item value="b"><span slot="title">B</span></ds-rich-list-item>
|
|
35
|
+
</ds-rich-list>
|
|
36
|
+
`;
|
|
37
|
+
const el = container.querySelector('ds-rich-list');
|
|
38
|
+
await tick();
|
|
39
|
+
|
|
40
|
+
const items = el.querySelectorAll('ds-rich-list-item');
|
|
41
|
+
expect(items.length).toBe(2);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// ─── ARIA ───
|
|
45
|
+
|
|
46
|
+
it('sets role=list for non-selectable', async () => {
|
|
47
|
+
container.innerHTML = '<ds-rich-list><ds-rich-list-item><span slot="title">A</span></ds-rich-list-item></ds-rich-list>';
|
|
48
|
+
const el = container.querySelector('ds-rich-list');
|
|
49
|
+
await tick();
|
|
50
|
+
|
|
51
|
+
const listDiv = el.shadowRoot.querySelector('.list');
|
|
52
|
+
expect(listDiv.getAttribute('role')).toBe('list');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('sets role=listbox for selectable', async () => {
|
|
56
|
+
container.innerHTML = '<ds-rich-list selectable="single"><ds-rich-list-item><span slot="title">A</span></ds-rich-list-item></ds-rich-list>';
|
|
57
|
+
const el = container.querySelector('ds-rich-list');
|
|
58
|
+
await tick();
|
|
59
|
+
|
|
60
|
+
const listDiv = el.shadowRoot.querySelector('.list');
|
|
61
|
+
expect(listDiv.getAttribute('role')).toBe('listbox');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('sets aria-multiselectable for multiple', async () => {
|
|
65
|
+
container.innerHTML = '<ds-rich-list selectable="multiple"><ds-rich-list-item><span slot="title">A</span></ds-rich-list-item></ds-rich-list>';
|
|
66
|
+
const el = container.querySelector('ds-rich-list');
|
|
67
|
+
await tick();
|
|
68
|
+
|
|
69
|
+
const listDiv = el.shadowRoot.querySelector('.list');
|
|
70
|
+
expect(listDiv.getAttribute('aria-multiselectable')).toBe('true');
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// ─── Selection Propagation ───
|
|
74
|
+
|
|
75
|
+
it('propagates selectable to items', async () => {
|
|
76
|
+
container.innerHTML = `
|
|
77
|
+
<ds-rich-list selectable="multiple">
|
|
78
|
+
<ds-rich-list-item value="a"><span slot="title">A</span></ds-rich-list-item>
|
|
79
|
+
<ds-rich-list-item value="b"><span slot="title">B</span></ds-rich-list-item>
|
|
80
|
+
</ds-rich-list>
|
|
81
|
+
`;
|
|
82
|
+
const el = container.querySelector('ds-rich-list');
|
|
83
|
+
await tick();
|
|
84
|
+
|
|
85
|
+
const items = el.querySelectorAll('ds-rich-list-item');
|
|
86
|
+
items.forEach(item => {
|
|
87
|
+
expect(item._selectable).toBe('multiple');
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('propagates name to items', async () => {
|
|
92
|
+
container.innerHTML = `
|
|
93
|
+
<ds-rich-list selectable="single" name="test-group">
|
|
94
|
+
<ds-rich-list-item value="a"><span slot="title">A</span></ds-rich-list-item>
|
|
95
|
+
</ds-rich-list>
|
|
96
|
+
`;
|
|
97
|
+
const el = container.querySelector('ds-rich-list');
|
|
98
|
+
await tick();
|
|
99
|
+
|
|
100
|
+
const item = el.querySelector('ds-rich-list-item');
|
|
101
|
+
expect(item._name).toBe('test-group');
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// ─── Single Selection ───
|
|
105
|
+
|
|
106
|
+
it('deselects siblings on single selection', async () => {
|
|
107
|
+
container.innerHTML = `
|
|
108
|
+
<ds-rich-list selectable="single">
|
|
109
|
+
<ds-rich-list-item value="a" selected><span slot="title">A</span></ds-rich-list-item>
|
|
110
|
+
<ds-rich-list-item value="b"><span slot="title">B</span></ds-rich-list-item>
|
|
111
|
+
</ds-rich-list>
|
|
112
|
+
`;
|
|
113
|
+
const el = container.querySelector('ds-rich-list');
|
|
114
|
+
await tick();
|
|
115
|
+
|
|
116
|
+
const items = el.querySelectorAll('ds-rich-list-item');
|
|
117
|
+
expect(items[0].selected).toBe(true);
|
|
118
|
+
|
|
119
|
+
// Click item B
|
|
120
|
+
const itemB = items[1].shadowRoot.querySelector('.item');
|
|
121
|
+
itemB.click();
|
|
122
|
+
await tick();
|
|
123
|
+
|
|
124
|
+
expect(items[0].selected).toBe(false);
|
|
125
|
+
expect(items[1].selected).toBe(true);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// ─── Multiple Selection ───
|
|
129
|
+
|
|
130
|
+
it('allows multiple selections', async () => {
|
|
131
|
+
container.innerHTML = `
|
|
132
|
+
<ds-rich-list selectable="multiple">
|
|
133
|
+
<ds-rich-list-item value="a"><span slot="title">A</span></ds-rich-list-item>
|
|
134
|
+
<ds-rich-list-item value="b"><span slot="title">B</span></ds-rich-list-item>
|
|
135
|
+
</ds-rich-list>
|
|
136
|
+
`;
|
|
137
|
+
const el = container.querySelector('ds-rich-list');
|
|
138
|
+
await tick();
|
|
139
|
+
|
|
140
|
+
const items = el.querySelectorAll('ds-rich-list-item');
|
|
141
|
+
|
|
142
|
+
items[0].shadowRoot.querySelector('.item').click();
|
|
143
|
+
await tick();
|
|
144
|
+
items[1].shadowRoot.querySelector('.item').click();
|
|
145
|
+
await tick();
|
|
146
|
+
|
|
147
|
+
expect(items[0].selected).toBe(true);
|
|
148
|
+
expect(items[1].selected).toBe(true);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// ─── Change Event ───
|
|
152
|
+
|
|
153
|
+
it('dispatches aggregated change event', async () => {
|
|
154
|
+
container.innerHTML = `
|
|
155
|
+
<ds-rich-list selectable="single">
|
|
156
|
+
<ds-rich-list-item value="a"><span slot="title">A</span></ds-rich-list-item>
|
|
157
|
+
<ds-rich-list-item value="b"><span slot="title">B</span></ds-rich-list-item>
|
|
158
|
+
</ds-rich-list>
|
|
159
|
+
`;
|
|
160
|
+
const el = container.querySelector('ds-rich-list');
|
|
161
|
+
await tick();
|
|
162
|
+
|
|
163
|
+
let detail = null;
|
|
164
|
+
el.addEventListener('change', (e) => { detail = e.detail; });
|
|
165
|
+
|
|
166
|
+
const items = el.querySelectorAll('ds-rich-list-item');
|
|
167
|
+
items[0].shadowRoot.querySelector('.item').click();
|
|
168
|
+
await tick();
|
|
169
|
+
|
|
170
|
+
expect(detail).not.toBeNull();
|
|
171
|
+
expect(detail.value).toBe('a');
|
|
172
|
+
expect(detail.values).toEqual(['a']);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// ─── Layout Propagation ───
|
|
176
|
+
|
|
177
|
+
it('forces media column when any item has media', async () => {
|
|
178
|
+
container.innerHTML = `
|
|
179
|
+
<ds-rich-list>
|
|
180
|
+
<ds-rich-list-item media="test.jpg"><span slot="title">With media</span></ds-rich-list-item>
|
|
181
|
+
<ds-rich-list-item><span slot="title">Without media</span></ds-rich-list-item>
|
|
182
|
+
</ds-rich-list>
|
|
183
|
+
`;
|
|
184
|
+
const el = container.querySelector('ds-rich-list');
|
|
185
|
+
await tick(100);
|
|
186
|
+
|
|
187
|
+
const items = el.querySelectorAll('ds-rich-list-item');
|
|
188
|
+
// Item with media has has-media
|
|
189
|
+
expect(items[0].hasAttribute('has-media')).toBe(true);
|
|
190
|
+
// Item without media should get force-media from parent
|
|
191
|
+
expect(items[1].hasAttribute('force-media')).toBe(true);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// ─── Keyboard Navigation ───
|
|
195
|
+
|
|
196
|
+
it('handles arrow key navigation', async () => {
|
|
197
|
+
container.innerHTML = `
|
|
198
|
+
<ds-rich-list selectable="single">
|
|
199
|
+
<ds-rich-list-item value="a"><span slot="title">A</span></ds-rich-list-item>
|
|
200
|
+
<ds-rich-list-item value="b"><span slot="title">B</span></ds-rich-list-item>
|
|
201
|
+
<ds-rich-list-item value="c"><span slot="title">C</span></ds-rich-list-item>
|
|
202
|
+
</ds-rich-list>
|
|
203
|
+
`;
|
|
204
|
+
const el = container.querySelector('ds-rich-list');
|
|
205
|
+
await tick();
|
|
206
|
+
|
|
207
|
+
const items = el.querySelectorAll('ds-rich-list-item');
|
|
208
|
+
|
|
209
|
+
// Focus first item
|
|
210
|
+
items[0].focus();
|
|
211
|
+
await tick();
|
|
212
|
+
|
|
213
|
+
// ArrowDown should move focus to next item
|
|
214
|
+
el.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }));
|
|
215
|
+
await tick();
|
|
216
|
+
|
|
217
|
+
expect(document.activeElement).toBe(items[1]);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('handles Home/End key navigation', async () => {
|
|
221
|
+
container.innerHTML = `
|
|
222
|
+
<ds-rich-list selectable="single">
|
|
223
|
+
<ds-rich-list-item value="a"><span slot="title">A</span></ds-rich-list-item>
|
|
224
|
+
<ds-rich-list-item value="b"><span slot="title">B</span></ds-rich-list-item>
|
|
225
|
+
<ds-rich-list-item value="c"><span slot="title">C</span></ds-rich-list-item>
|
|
226
|
+
</ds-rich-list>
|
|
227
|
+
`;
|
|
228
|
+
const el = container.querySelector('ds-rich-list');
|
|
229
|
+
await tick();
|
|
230
|
+
|
|
231
|
+
const items = el.querySelectorAll('ds-rich-list-item');
|
|
232
|
+
|
|
233
|
+
items[0].focus();
|
|
234
|
+
await tick();
|
|
235
|
+
|
|
236
|
+
// End goes to last
|
|
237
|
+
el.dispatchEvent(new KeyboardEvent('keydown', { key: 'End', bubbles: true }));
|
|
238
|
+
await tick();
|
|
239
|
+
|
|
240
|
+
expect(document.activeElement).toBe(items[2]);
|
|
241
|
+
|
|
242
|
+
// Home goes back to first
|
|
243
|
+
el.dispatchEvent(new KeyboardEvent('keydown', { key: 'Home', bubbles: true }));
|
|
244
|
+
await tick();
|
|
245
|
+
|
|
246
|
+
expect(document.activeElement).toBe(items[0]);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// ─── Custom Width ───
|
|
250
|
+
|
|
251
|
+
it('updates layout when item structure changes', async () => {
|
|
252
|
+
container.innerHTML = `
|
|
253
|
+
<ds-rich-list>
|
|
254
|
+
<ds-rich-list-item id="item1"><span slot="action-group">Action</span></ds-rich-list-item>
|
|
255
|
+
<ds-rich-list-item id="item2"><span slot="title">No Action</span></ds-rich-list-item>
|
|
256
|
+
</ds-rich-list>
|
|
257
|
+
`;
|
|
258
|
+
const el = container.querySelector('ds-rich-list');
|
|
259
|
+
await tick(100);
|
|
260
|
+
|
|
261
|
+
const item1 = el.querySelector('#item1');
|
|
262
|
+
const item2 = el.querySelector('#item2');
|
|
263
|
+
|
|
264
|
+
// Initially item2 should be forced to show action group
|
|
265
|
+
expect(item1.hasAttribute('has-action-group')).toBe(true);
|
|
266
|
+
expect(item2.hasAttribute('force-action-group')).toBe(true);
|
|
267
|
+
|
|
268
|
+
// Remove action group from item1
|
|
269
|
+
item1.innerHTML = '<span slot="title">Updated</span>';
|
|
270
|
+
await tick(100);
|
|
271
|
+
|
|
272
|
+
// item1 no longer has actions
|
|
273
|
+
expect(item1.hasAttribute('has-action-group')).toBe(false);
|
|
274
|
+
// item2 should no longer be forced
|
|
275
|
+
expect(item2.hasAttribute('force-action-group')).toBe(false);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
// ─── Custom Width ───
|
|
279
|
+
|
|
280
|
+
it('propagates custom-width to items', async () => {
|
|
281
|
+
container.innerHTML = `
|
|
282
|
+
<ds-rich-list custom-width="200px">
|
|
283
|
+
<ds-rich-list-item><span slot="title">A</span><div slot="custom">Custom</div></ds-rich-list-item>
|
|
284
|
+
</ds-rich-list>
|
|
285
|
+
`;
|
|
286
|
+
const el = container.querySelector('ds-rich-list');
|
|
287
|
+
await tick(100);
|
|
288
|
+
|
|
289
|
+
const item = el.querySelector('ds-rich-list-item');
|
|
290
|
+
const value = item.style.getPropertyValue('--ds-rich-list-custom-width');
|
|
291
|
+
expect(value).toBe('200px');
|
|
292
|
+
});
|
|
293
|
+
});
|