@arbor-education/design-system.components 0.21.1 → 0.23.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 (189) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/component-library.md +77 -14
  3. package/dist/components/articleCard/ArticleCard.d.ts +2 -2
  4. package/dist/components/articleCard/ArticleCard.d.ts.map +1 -1
  5. package/dist/components/articleCard/ArticleCard.js +3 -3
  6. package/dist/components/articleCard/ArticleCard.js.map +1 -1
  7. package/dist/components/articleCard/ArticleCard.stories.d.ts +11 -3
  8. package/dist/components/articleCard/ArticleCard.stories.d.ts.map +1 -1
  9. package/dist/components/articleCard/ArticleCard.stories.js +16 -11
  10. package/dist/components/articleCard/ArticleCard.stories.js.map +1 -1
  11. package/dist/components/combobox/Combobox.js +1 -1
  12. package/dist/components/combobox/Combobox.js.map +1 -1
  13. package/dist/components/combobox/Combobox.stories.d.ts +4 -0
  14. package/dist/components/combobox/Combobox.stories.d.ts.map +1 -1
  15. package/dist/components/combobox/Combobox.stories.js +144 -12
  16. package/dist/components/combobox/Combobox.stories.js.map +1 -1
  17. package/dist/components/combobox/Combobox.test.js +22 -0
  18. package/dist/components/combobox/Combobox.test.js.map +1 -1
  19. package/dist/components/combobox/ComboboxButtonTrigger.d.ts +4 -4
  20. package/dist/components/combobox/ComboboxButtonTrigger.d.ts.map +1 -1
  21. package/dist/components/combobox/ComboboxButtonTrigger.js +35 -40
  22. package/dist/components/combobox/ComboboxButtonTrigger.js.map +1 -1
  23. package/dist/components/combobox/ComboboxTrigger.d.ts.map +1 -1
  24. package/dist/components/combobox/ComboboxTrigger.js +11 -4
  25. package/dist/components/combobox/ComboboxTrigger.js.map +1 -1
  26. package/dist/components/combobox/useVisibleTriggerTags.d.ts +21 -0
  27. package/dist/components/combobox/useVisibleTriggerTags.d.ts.map +1 -0
  28. package/dist/components/combobox/useVisibleTriggerTags.js +46 -0
  29. package/dist/components/combobox/useVisibleTriggerTags.js.map +1 -0
  30. package/dist/components/combobox/useVisibleTriggerTags.test.d.ts +2 -0
  31. package/dist/components/combobox/useVisibleTriggerTags.test.d.ts.map +1 -0
  32. package/dist/components/combobox/useVisibleTriggerTags.test.js +81 -0
  33. package/dist/components/combobox/useVisibleTriggerTags.test.js.map +1 -0
  34. package/dist/components/filterBar/FilterBar.d.ts +71 -0
  35. package/dist/components/filterBar/FilterBar.d.ts.map +1 -0
  36. package/dist/components/filterBar/FilterBar.js +89 -0
  37. package/dist/components/filterBar/FilterBar.js.map +1 -0
  38. package/dist/components/filterBar/FilterBar.stories.d.ts +170 -0
  39. package/dist/components/filterBar/FilterBar.stories.d.ts.map +1 -0
  40. package/dist/components/filterBar/FilterBar.stories.js +894 -0
  41. package/dist/components/filterBar/FilterBar.stories.js.map +1 -0
  42. package/dist/components/filterBar/FilterBar.test.d.ts +2 -0
  43. package/dist/components/filterBar/FilterBar.test.d.ts.map +1 -0
  44. package/dist/components/filterBar/FilterBar.test.js +164 -0
  45. package/dist/components/filterBar/FilterBar.test.js.map +1 -0
  46. package/dist/components/icon/allowedIcons.d.ts +1 -0
  47. package/dist/components/icon/allowedIcons.d.ts.map +1 -1
  48. package/dist/components/icon/allowedIcons.js +2 -1
  49. package/dist/components/icon/allowedIcons.js.map +1 -1
  50. package/dist/components/iconText/IconText.d.ts +43 -0
  51. package/dist/components/iconText/IconText.d.ts.map +1 -0
  52. package/dist/components/iconText/IconText.js +29 -0
  53. package/dist/components/iconText/IconText.js.map +1 -0
  54. package/dist/components/{icoText/IcoText.stories.d.ts → iconText/IconText.stories.d.ts} +8 -9
  55. package/dist/components/iconText/IconText.stories.d.ts.map +1 -0
  56. package/dist/components/{icoText/IcoText.stories.js → iconText/IconText.stories.js} +81 -81
  57. package/dist/components/iconText/IconText.stories.js.map +1 -0
  58. package/dist/components/iconText/IconText.test.d.ts +2 -0
  59. package/dist/components/iconText/IconText.test.d.ts.map +1 -0
  60. package/dist/components/{icoText/IcoText.test.js → iconText/IconText.test.js} +6 -6
  61. package/dist/components/iconText/IconText.test.js.map +1 -0
  62. package/dist/components/modal/Modal.d.ts +1 -0
  63. package/dist/components/modal/Modal.d.ts.map +1 -1
  64. package/dist/components/modal/Modal.js +2 -2
  65. package/dist/components/modal/Modal.js.map +1 -1
  66. package/dist/components/table/cellRenderers/ComboboxCellRenderer.test.d.ts.map +1 -1
  67. package/dist/components/table/cellRenderers/ComboboxCellRenderer.test.js +13 -2
  68. package/dist/components/table/cellRenderers/ComboboxCellRenderer.test.js.map +1 -1
  69. package/dist/components/tag/Tag.d.ts +14 -1
  70. package/dist/components/tag/Tag.d.ts.map +1 -1
  71. package/dist/components/tag/Tag.js +9 -3
  72. package/dist/components/tag/Tag.js.map +1 -1
  73. package/dist/components/tag/Tag.stories.d.ts +1 -1
  74. package/dist/components/tag/Tag.stories.d.ts.map +1 -1
  75. package/dist/components/tag/Tag.stories.js +3 -3
  76. package/dist/components/tag/Tag.stories.js.map +1 -1
  77. package/dist/components/tag/Tag.test.js +36 -5
  78. package/dist/components/tag/Tag.test.js.map +1 -1
  79. package/dist/components/tagList/TagList.d.ts +49 -0
  80. package/dist/components/tagList/TagList.d.ts.map +1 -0
  81. package/dist/components/tagList/TagList.js +114 -0
  82. package/dist/components/tagList/TagList.js.map +1 -0
  83. package/dist/components/tagList/TagList.stories.d.ts +130 -0
  84. package/dist/components/tagList/TagList.stories.d.ts.map +1 -0
  85. package/dist/components/tagList/TagList.stories.js +443 -0
  86. package/dist/components/tagList/TagList.stories.js.map +1 -0
  87. package/dist/components/{icoText/IcoText.test.d.ts → tagList/TagList.test.d.ts} +1 -1
  88. package/dist/components/tagList/TagList.test.d.ts.map +1 -0
  89. package/dist/components/tagList/TagList.test.js +246 -0
  90. package/dist/components/tagList/TagList.test.js.map +1 -0
  91. package/dist/components/tagList/useTagListCollapsedLayout.d.ts +19 -0
  92. package/dist/components/tagList/useTagListCollapsedLayout.d.ts.map +1 -0
  93. package/dist/components/tagList/useTagListCollapsedLayout.js +48 -0
  94. package/dist/components/tagList/useTagListCollapsedLayout.js.map +1 -0
  95. package/dist/components/tagList/useVisibleTags.d.ts +18 -0
  96. package/dist/components/tagList/useVisibleTags.d.ts.map +1 -0
  97. package/dist/components/tagList/useVisibleTags.js +41 -0
  98. package/dist/components/tagList/useVisibleTags.js.map +1 -0
  99. package/dist/index.css +272 -13
  100. package/dist/index.css.map +1 -1
  101. package/dist/index.d.ts +4 -1
  102. package/dist/index.d.ts.map +1 -1
  103. package/dist/index.js +3 -1
  104. package/dist/index.js.map +1 -1
  105. package/dist/utils/hooks/useElementWidth.d.ts.map +1 -0
  106. package/dist/{components/combobox → utils/hooks}/useElementWidth.js +0 -1
  107. package/dist/utils/hooks/useElementWidth.js.map +1 -0
  108. package/dist/utils/hooks/useMeasuredChildWidths.d.ts +8 -0
  109. package/dist/utils/hooks/useMeasuredChildWidths.d.ts.map +1 -0
  110. package/dist/utils/hooks/useMeasuredChildWidths.js +26 -0
  111. package/dist/utils/hooks/useMeasuredChildWidths.js.map +1 -0
  112. package/dist/utils/hooks/useRovingFocus.d.ts +18 -0
  113. package/dist/utils/hooks/useRovingFocus.d.ts.map +1 -0
  114. package/dist/utils/hooks/useRovingFocus.js +130 -0
  115. package/dist/utils/hooks/useRovingFocus.js.map +1 -0
  116. package/dist/utils/hooks/useRovingFocus.test.d.ts +2 -0
  117. package/dist/utils/hooks/useRovingFocus.test.d.ts.map +1 -0
  118. package/dist/utils/hooks/useRovingFocus.test.js +59 -0
  119. package/dist/utils/hooks/useRovingFocus.test.js.map +1 -0
  120. package/dist/utils/spacedWidths.d.ts +3 -0
  121. package/dist/utils/spacedWidths.d.ts.map +1 -0
  122. package/dist/utils/spacedWidths.js +28 -0
  123. package/dist/utils/spacedWidths.js.map +1 -0
  124. package/dist/utils/spacedWidths.test.d.ts +2 -0
  125. package/dist/utils/spacedWidths.test.d.ts.map +1 -0
  126. package/dist/utils/spacedWidths.test.js +17 -0
  127. package/dist/utils/spacedWidths.test.js.map +1 -0
  128. package/package.json +1 -1
  129. package/src/components/articleCard/ArticleCard.stories.tsx +17 -12
  130. package/src/components/articleCard/ArticleCard.tsx +9 -9
  131. package/src/components/combobox/Combobox.stories.tsx +186 -12
  132. package/src/components/combobox/Combobox.test.tsx +53 -0
  133. package/src/components/combobox/Combobox.tsx +3 -3
  134. package/src/components/combobox/ComboboxButtonTrigger.tsx +52 -56
  135. package/src/components/combobox/ComboboxTrigger.tsx +19 -16
  136. package/src/components/combobox/combobox.scss +8 -3
  137. package/src/components/combobox/useVisibleTriggerTags.test.tsx +91 -0
  138. package/src/components/combobox/useVisibleTriggerTags.ts +83 -0
  139. package/src/components/filterBar/FilterBar.stories.tsx +1199 -0
  140. package/src/components/filterBar/FilterBar.test.tsx +248 -0
  141. package/src/components/filterBar/FilterBar.tsx +298 -0
  142. package/src/components/filterBar/filterBar.scss +143 -0
  143. package/src/components/icon/allowedIcons.tsx +3 -1
  144. package/src/components/{icoText/IcoText.stories.tsx → iconText/IconText.stories.tsx} +112 -112
  145. package/src/components/{icoText/IcoText.test.tsx → iconText/IconText.test.tsx} +10 -10
  146. package/src/components/{icoText/IcoText.tsx → iconText/IconText.tsx} +27 -20
  147. package/src/components/modal/Modal.tsx +5 -1
  148. package/src/components/table/cellRenderers/ComboboxCellRenderer.test.tsx +20 -3
  149. package/src/components/tag/Tag.stories.tsx +4 -4
  150. package/src/components/tag/Tag.test.tsx +62 -5
  151. package/src/components/tag/Tag.tsx +61 -3
  152. package/src/components/tag/tag.scss +80 -9
  153. package/src/components/tagList/TagList.stories.tsx +564 -0
  154. package/src/components/tagList/TagList.test.tsx +342 -0
  155. package/src/components/tagList/TagList.tsx +296 -0
  156. package/src/components/tagList/tagList.scss +56 -0
  157. package/src/components/tagList/useTagListCollapsedLayout.ts +83 -0
  158. package/src/components/tagList/useVisibleTags.ts +74 -0
  159. package/src/index.scss +3 -1
  160. package/src/index.ts +13 -1
  161. package/src/tokens.scss +3 -1
  162. package/src/{components/combobox → utils/hooks}/useElementWidth.ts +0 -1
  163. package/src/utils/hooks/useMeasuredChildWidths.ts +39 -0
  164. package/src/utils/hooks/useRovingFocus.test.tsx +105 -0
  165. package/src/utils/hooks/useRovingFocus.ts +163 -0
  166. package/src/utils/spacedWidths.test.ts +20 -0
  167. package/src/utils/spacedWidths.ts +37 -0
  168. package/dist/components/combobox/useElementWidth.d.ts.map +0 -1
  169. package/dist/components/combobox/useElementWidth.js.map +0 -1
  170. package/dist/components/combobox/useVisibleChips.d.ts +0 -21
  171. package/dist/components/combobox/useVisibleChips.d.ts.map +0 -1
  172. package/dist/components/combobox/useVisibleChips.js +0 -59
  173. package/dist/components/combobox/useVisibleChips.js.map +0 -1
  174. package/dist/components/combobox/useVisibleChips.test.d.ts +0 -2
  175. package/dist/components/combobox/useVisibleChips.test.d.ts.map +0 -1
  176. package/dist/components/combobox/useVisibleChips.test.js +0 -81
  177. package/dist/components/combobox/useVisibleChips.test.js.map +0 -1
  178. package/dist/components/icoText/IcoText.d.ts +0 -37
  179. package/dist/components/icoText/IcoText.d.ts.map +0 -1
  180. package/dist/components/icoText/IcoText.js +0 -29
  181. package/dist/components/icoText/IcoText.js.map +0 -1
  182. package/dist/components/icoText/IcoText.stories.d.ts.map +0 -1
  183. package/dist/components/icoText/IcoText.stories.js.map +0 -1
  184. package/dist/components/icoText/IcoText.test.d.ts.map +0 -1
  185. package/dist/components/icoText/IcoText.test.js.map +0 -1
  186. package/src/components/combobox/useVisibleChips.test.tsx +0 -91
  187. package/src/components/combobox/useVisibleChips.ts +0 -100
  188. /package/dist/{components/combobox → utils/hooks}/useElementWidth.d.ts +0 -0
  189. /package/src/components/{icoText/icoText.scss → iconText/iconText.scss} +0 -0
@@ -0,0 +1,246 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import '@testing-library/jest-dom/vitest';
3
+ import { render, screen } from '@testing-library/react';
4
+ import userEvent from '@testing-library/user-event';
5
+ import { Icon } from '../icon/Icon.js';
6
+ import { useRef, useState } from 'react';
7
+ import { describe, expect, test, vi } from 'vitest';
8
+ import { TagList } from './TagList.js';
9
+ const mockTagListCollapseRects = () => vi.spyOn(HTMLElement.prototype, 'getBoundingClientRect').mockImplementation(function mockRect() {
10
+ let width = 0;
11
+ if (this.classList.contains('ds-tag-list__viewport'))
12
+ width = 220;
13
+ else if (this.classList.contains('ds-tag-list__item'))
14
+ width = 72;
15
+ else if (this.classList.contains('ds-tag-list__overflow'))
16
+ width = 76;
17
+ return {
18
+ width,
19
+ height: 0,
20
+ top: 0,
21
+ left: 0,
22
+ right: width,
23
+ bottom: 0,
24
+ x: 0,
25
+ y: 0,
26
+ toJSON() {
27
+ return {};
28
+ },
29
+ };
30
+ });
31
+ describe('TagList', () => {
32
+ test('renders empty state when there are no items', () => {
33
+ render(_jsx(TagList, { items: [], emptyState: _jsx("span", { children: "No filters set" }) }));
34
+ expect(screen.getByText('No filters set')).toBeInTheDocument();
35
+ });
36
+ test('calls the item action when a tag is clicked', async () => {
37
+ const onClick = vi.fn();
38
+ render(_jsx(TagList, { items: [{ id: 'attendance', children: 'Attendance', onClick }] }));
39
+ await userEvent.click(screen.getByRole('button', { name: 'Attendance' }));
40
+ expect(onClick).toHaveBeenCalledOnce();
41
+ });
42
+ test('forwards item-level aria-controls and aria-expanded to the tag action button', () => {
43
+ render(_jsx(TagList, { items: [
44
+ {
45
+ id: 'attendance',
46
+ children: 'Attendance',
47
+ onClick: vi.fn(),
48
+ ariaControls: 'filter-modal',
49
+ ariaExpanded: true,
50
+ },
51
+ ] }));
52
+ expect(screen.getByRole('button', { name: 'Attendance' })).toHaveAttribute('aria-controls', 'filter-modal');
53
+ expect(screen.getByRole('button', { name: 'Attendance' })).toHaveAttribute('aria-expanded', 'true');
54
+ });
55
+ test('moves roving focus between interactive tags with arrow keys', async () => {
56
+ const user = userEvent.setup();
57
+ render(_jsx(TagList, { items: [
58
+ { id: 'attendance', children: 'Attendance', onClick: vi.fn() },
59
+ { id: 'registers', children: 'Registers', onClick: vi.fn() },
60
+ { id: 'interventions', children: 'Interventions', onClick: vi.fn() },
61
+ ] }));
62
+ await user.tab();
63
+ expect(screen.getByRole('button', { name: 'Attendance' })).toHaveFocus();
64
+ await user.keyboard('{ArrowRight}');
65
+ expect(screen.getByRole('button', { name: 'Registers' })).toHaveFocus();
66
+ await user.keyboard('{End}');
67
+ expect(screen.getByRole('button', { name: 'Interventions' })).toHaveFocus();
68
+ });
69
+ test('ArrowRight moves from the tag action to its remove button, then to the next tag', async () => {
70
+ const user = userEvent.setup();
71
+ render(_jsx(TagList, { items: [
72
+ {
73
+ id: 'attendance',
74
+ children: 'Attendance',
75
+ onClick: vi.fn(),
76
+ onRemove: vi.fn(),
77
+ removeLabel: 'Remove Attendance',
78
+ },
79
+ {
80
+ id: 'registers',
81
+ children: 'Registers',
82
+ onClick: vi.fn(),
83
+ },
84
+ ] }));
85
+ await user.tab();
86
+ expect(screen.getByRole('button', { name: 'Attendance' })).toHaveFocus();
87
+ expect(screen.getByRole('button', { name: 'Remove Attendance' })).toHaveAttribute('tabindex', '-1');
88
+ await user.keyboard('{ArrowRight}');
89
+ expect(screen.getByRole('button', { name: 'Remove Attendance' })).toHaveFocus();
90
+ expect(screen.getByRole('button', { name: 'Remove Attendance' })).toHaveAttribute('tabindex', '0');
91
+ await user.keyboard('{ArrowRight}');
92
+ expect(screen.getByRole('button', { name: 'Registers' })).toHaveFocus();
93
+ });
94
+ test('ArrowLeft moves from the remove button back to the tag action', async () => {
95
+ const user = userEvent.setup();
96
+ render(_jsx(TagList, { items: [
97
+ {
98
+ id: 'attendance',
99
+ children: 'Attendance',
100
+ onClick: vi.fn(),
101
+ onRemove: vi.fn(),
102
+ removeLabel: 'Remove Attendance',
103
+ },
104
+ ] }));
105
+ await user.tab();
106
+ await user.keyboard('{ArrowRight}');
107
+ expect(screen.getByRole('button', { name: 'Remove Attendance' })).toHaveFocus();
108
+ await user.keyboard('{ArrowLeft}');
109
+ expect(screen.getByRole('button', { name: 'Attendance' })).toHaveFocus();
110
+ });
111
+ test('Delete triggers the focused tag remove callback', async () => {
112
+ const user = userEvent.setup();
113
+ const onRemove = vi.fn();
114
+ render(_jsx(TagList, { items: [
115
+ {
116
+ id: 'attendance',
117
+ children: 'Attendance',
118
+ slotStart: _jsx(Icon, { name: "funnel", size: 12 }),
119
+ onClick: vi.fn(),
120
+ onRemove,
121
+ removeLabel: 'Remove Attendance',
122
+ },
123
+ ] }));
124
+ await user.tab();
125
+ await user.keyboard('{Delete}');
126
+ expect(onRemove).toHaveBeenCalledOnce();
127
+ });
128
+ test('focuses the next available target after a removable tag is deleted', async () => {
129
+ const user = userEvent.setup();
130
+ const Example = () => {
131
+ const [itemIds, setItemIds] = useState(['attendance', 'registers']);
132
+ const items = itemIds.map(itemId => ({
133
+ id: itemId,
134
+ children: itemId === 'attendance' ? 'Attendance' : 'Registers',
135
+ onRemove: () => setItemIds(current => current.filter(id => id !== itemId)),
136
+ removeLabel: itemId === 'attendance' ? 'Remove Attendance' : 'Remove Registers',
137
+ }));
138
+ return _jsx(TagList, { items: items });
139
+ };
140
+ render(_jsx(Example, {}));
141
+ await user.tab();
142
+ expect(screen.getByRole('button', { name: 'Remove Attendance' })).toHaveFocus();
143
+ await user.click(screen.getByRole('button', { name: 'Remove Attendance' }));
144
+ expect(screen.getByRole('button', { name: 'Remove Registers' })).toHaveFocus();
145
+ });
146
+ test('returns focus to the provided fallback element when the last removable tag is deleted', async () => {
147
+ const user = userEvent.setup();
148
+ const Example = () => {
149
+ const [items, setItems] = useState([
150
+ {
151
+ id: 'attendance',
152
+ children: 'Attendance',
153
+ onRemove: () => setItems([]),
154
+ removeLabel: 'Remove Attendance',
155
+ },
156
+ ]);
157
+ const returnFocusRef = useRef(null);
158
+ return (_jsxs(_Fragment, { children: [_jsx(TagList, { items: items, returnFocusRef: returnFocusRef }), _jsx("button", { ref: returnFocusRef, type: "button", children: "Return home" })] }));
159
+ };
160
+ render(_jsx(Example, {}));
161
+ await user.tab();
162
+ expect(screen.getByRole('button', { name: 'Remove Attendance' })).toHaveFocus();
163
+ await user.click(screen.getByRole('button', { name: 'Remove Attendance' }));
164
+ expect(screen.getByRole('button', { name: 'Return home' })).toHaveFocus();
165
+ });
166
+ test('returns focus to the fallback element when the last removal unmounts TagList immediately', async () => {
167
+ const user = userEvent.setup();
168
+ const Example = () => {
169
+ const [items, setItems] = useState([
170
+ {
171
+ id: 'attendance',
172
+ children: 'Attendance',
173
+ onRemove: () => setItems([]),
174
+ removeLabel: 'Remove Attendance',
175
+ },
176
+ ]);
177
+ const returnFocusRef = useRef(null);
178
+ return (_jsxs(_Fragment, { children: [items.length > 0 && _jsx(TagList, { items: items, returnFocusRef: returnFocusRef }), _jsx("button", { ref: returnFocusRef, type: "button", children: "Return home" })] }));
179
+ };
180
+ render(_jsx(Example, {}));
181
+ await user.tab();
182
+ expect(screen.getByRole('button', { name: 'Remove Attendance' })).toHaveFocus();
183
+ await user.click(screen.getByRole('button', { name: 'Remove Attendance' }));
184
+ expect(screen.getByRole('button', { name: 'Return home' })).toHaveFocus();
185
+ });
186
+ test('deleting a focused remove button in the composite model focuses the next available tag target', async () => {
187
+ const user = userEvent.setup();
188
+ const Example = () => {
189
+ const [itemIds, setItemIds] = useState(['attendance', 'registers']);
190
+ const items = itemIds.map(itemId => ({
191
+ id: itemId,
192
+ children: itemId === 'attendance' ? 'Attendance' : 'Registers',
193
+ onClick: vi.fn(),
194
+ onRemove: itemId === 'attendance'
195
+ ? () => setItemIds(current => current.filter(id => id !== itemId))
196
+ : undefined,
197
+ removeLabel: itemId === 'attendance' ? 'Remove Attendance' : undefined,
198
+ }));
199
+ return _jsx(TagList, { items: items });
200
+ };
201
+ render(_jsx(Example, {}));
202
+ await user.tab();
203
+ expect(screen.getByRole('button', { name: 'Attendance' })).toHaveFocus();
204
+ await user.keyboard('{ArrowRight}');
205
+ expect(screen.getByRole('button', { name: 'Remove Attendance' })).toHaveFocus();
206
+ await user.keyboard('{Delete}');
207
+ expect(screen.getByRole('button', { name: 'Registers' })).toHaveFocus();
208
+ });
209
+ test('collapses overflowing items into a trailing summary', () => {
210
+ const rectSpy = mockTagListCollapseRects();
211
+ try {
212
+ render(_jsx(TagList, { collapseOverflow: true, items: [
213
+ { id: 'date', children: 'Wed, 05 Feb 2025 AM' },
214
+ { id: 'registers', children: 'Attendance registers' },
215
+ { id: 'interventions', children: 'Interventions' },
216
+ { id: 'exclusions', children: 'Internal exclusions' },
217
+ ] }));
218
+ expect(screen.getByText('+3 more')).toBeInTheDocument();
219
+ }
220
+ finally {
221
+ rectSpy.mockRestore();
222
+ }
223
+ });
224
+ test('makes the +N more summary focusable and clickable when an overflow action is provided', async () => {
225
+ const user = userEvent.setup();
226
+ const onOverflowClick = vi.fn();
227
+ const rectSpy = mockTagListCollapseRects();
228
+ try {
229
+ render(_jsx(TagList, { collapseOverflow: true, overflowOnClick: onOverflowClick, overflowActionLabel: "Show more filters", items: [
230
+ { id: 'date', children: 'Wed, 05 Feb 2025 AM', onClick: vi.fn() },
231
+ { id: 'registers', children: 'Attendance registers', onClick: vi.fn() },
232
+ { id: 'interventions', children: 'Interventions', onClick: vi.fn() },
233
+ { id: 'exclusions', children: 'Internal exclusions', onClick: vi.fn() },
234
+ ] }));
235
+ await user.tab();
236
+ await user.keyboard('{ArrowRight}');
237
+ expect(screen.getByRole('button', { name: 'Show more filters' })).toHaveFocus();
238
+ await user.keyboard('{Enter}');
239
+ expect(onOverflowClick).toHaveBeenCalledOnce();
240
+ }
241
+ finally {
242
+ rectSpy.mockRestore();
243
+ }
244
+ });
245
+ });
246
+ //# sourceMappingURL=TagList.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TagList.test.js","sourceRoot":"","sources":["../../../src/components/tagList/TagList.test.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { TagListItem, TagListOverflowRenderArgs } from './TagList.js';
2
+ type UseTagListCollapsedLayoutParams = {
3
+ items: TagListItem[];
4
+ wrap: boolean;
5
+ collapseOverflow: boolean;
6
+ };
7
+ type TagListCollapsedLayout = {
8
+ contentRef: React.RefObject<HTMLDivElement | null>;
9
+ measureTrackRef: React.RefObject<HTMLUListElement | null>;
10
+ overflowProbeRef: React.RefObject<HTMLDivElement | null>;
11
+ shouldCollapse: boolean;
12
+ visibleItemIndices: number[];
13
+ visibleItems: TagListItem[];
14
+ hiddenItemCount: number;
15
+ overflowArgs: TagListOverflowRenderArgs;
16
+ };
17
+ export declare const useTagListCollapsedLayout: ({ items, wrap, collapseOverflow, }: UseTagListCollapsedLayoutParams) => TagListCollapsedLayout;
18
+ export {};
19
+ //# sourceMappingURL=useTagListCollapsedLayout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTagListCollapsedLayout.d.ts","sourceRoot":"","sources":["../../../src/components/tagList/useTagListCollapsedLayout.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAG3E,KAAK,+BAA+B,GAAG;IACrC,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,IAAI,EAAE,OAAO,CAAC;IACd,gBAAgB,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,KAAK,sBAAsB,GAAG;IAC5B,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACnD,eAAe,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC1D,gBAAgB,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACzD,cAAc,EAAE,OAAO,CAAC;IACxB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,yBAAyB,CAAC;CACzC,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAI,oCAIvC,+BAA+B,KAAG,sBAuDpC,CAAC"}
@@ -0,0 +1,48 @@
1
+ import { useMemo, useRef } from 'react';
2
+ import { useMeasuredChildWidths } from '../../utils/hooks/useMeasuredChildWidths.js';
3
+ import { useElementWidth } from '../../utils/hooks/useElementWidth.js';
4
+ import { useVisibleTags } from './useVisibleTags.js';
5
+ export const useTagListCollapsedLayout = ({ items, wrap, collapseOverflow, }) => {
6
+ const contentRef = useRef(null);
7
+ const measureTrackRef = useRef(null);
8
+ const overflowProbeRef = useRef(null);
9
+ const shouldCollapse = collapseOverflow && !wrap && items.length > 0;
10
+ const itemWatchKey = useMemo(() => items.map(item => item.id).join('|'), [items]);
11
+ const contentWidth = useElementWidth(contentRef, itemWatchKey);
12
+ const overflowProbeWidth = useElementWidth(overflowProbeRef, `${itemWatchKey}-overflow`);
13
+ const { childGap: itemGap, childWidths: itemWidths } = useMeasuredChildWidths(measureTrackRef, itemWatchKey);
14
+ const layout = useVisibleTags({
15
+ containerWidth: contentWidth,
16
+ itemWidths,
17
+ itemGap,
18
+ overflowWidth: overflowProbeWidth,
19
+ allowOverflow: shouldCollapse,
20
+ });
21
+ const canMeasureCollapsedLayout = shouldCollapse
22
+ && contentWidth > 0
23
+ && itemWidths.length === items.length
24
+ && overflowProbeWidth > 0;
25
+ const visibleItemIndices = useMemo(() => canMeasureCollapsedLayout
26
+ ? layout.visibleItemIndices
27
+ : items.map((_, index) => index), [canMeasureCollapsedLayout, items, layout.visibleItemIndices]);
28
+ const hiddenItemCount = canMeasureCollapsedLayout ? layout.hiddenItemCount : 0;
29
+ const visibleItems = visibleItemIndices
30
+ .map(index => items[index])
31
+ .filter((item) => item != null);
32
+ const overflowArgs = useMemo(() => ({
33
+ hiddenItemCount,
34
+ totalItemCount: items.length,
35
+ visibleItemCount: visibleItems.length,
36
+ }), [hiddenItemCount, items.length, visibleItems.length]);
37
+ return {
38
+ contentRef,
39
+ measureTrackRef,
40
+ overflowProbeRef,
41
+ shouldCollapse,
42
+ visibleItemIndices,
43
+ visibleItems,
44
+ hiddenItemCount,
45
+ overflowArgs,
46
+ };
47
+ };
48
+ //# sourceMappingURL=useTagListCollapsedLayout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTagListCollapsedLayout.js","sourceRoot":"","sources":["../../../src/components/tagList/useTagListCollapsedLayout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAC5E,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAE9D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAmBrD,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,EACxC,KAAK,EACL,IAAI,EACJ,gBAAgB,GACgB,EAA0B,EAAE;IAC5D,MAAM,UAAU,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAChD,MAAM,eAAe,GAAG,MAAM,CAAmB,IAAI,CAAC,CAAC;IACvD,MAAM,gBAAgB,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAEtD,MAAM,cAAc,GAAG,gBAAgB,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IACrE,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAElF,MAAM,YAAY,GAAG,eAAe,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IAC/D,MAAM,kBAAkB,GAAG,eAAe,CAAC,gBAAgB,EAAE,GAAG,YAAY,WAAW,CAAC,CAAC;IACzF,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,sBAAsB,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC;IAE7G,MAAM,MAAM,GAAG,cAAc,CAAC;QAC5B,cAAc,EAAE,YAAY;QAC5B,UAAU;QACV,OAAO;QACP,aAAa,EAAE,kBAAkB;QACjC,aAAa,EAAE,cAAc;KAC9B,CAAC,CAAC;IAEH,MAAM,yBAAyB,GAAG,cAAc;WAC3C,YAAY,GAAG,CAAC;WAChB,UAAU,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM;WAClC,kBAAkB,GAAG,CAAC,CAAC;IAE5B,MAAM,kBAAkB,GAAG,OAAO,CAChC,GAAG,EAAE,CACH,yBAAyB;QACvB,CAAC,CAAC,MAAM,CAAC,kBAAkB;QAC3B,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EACpC,CAAC,yBAAyB,EAAE,KAAK,EAAE,MAAM,CAAC,kBAAkB,CAAC,CAC9D,CAAC;IACF,MAAM,eAAe,GAAG,yBAAyB,CAAC,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/E,MAAM,YAAY,GAAG,kBAAkB;SACpC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;SAC1B,MAAM,CAAC,CAAC,IAAI,EAAuB,EAAE,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;IACvD,MAAM,YAAY,GAAG,OAAO,CAC1B,GAA8B,EAAE,CAAC,CAAC;QAChC,eAAe;QACf,cAAc,EAAE,KAAK,CAAC,MAAM;QAC5B,gBAAgB,EAAE,YAAY,CAAC,MAAM;KACtC,CAAC,EACF,CAAC,eAAe,EAAE,KAAK,CAAC,MAAM,EAAE,YAAY,CAAC,MAAM,CAAC,CACrD,CAAC;IAEF,OAAO;QACL,UAAU;QACV,eAAe;QACf,gBAAgB;QAChB,cAAc;QACd,kBAAkB;QAClB,YAAY;QACZ,eAAe;QACf,YAAY;KACb,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,18 @@
1
+ type ComputeVisibleTagsLayoutParams = {
2
+ containerWidth: number;
3
+ itemWidths: number[];
4
+ itemGap: number;
5
+ overflowWidth: number;
6
+ allowOverflow: boolean;
7
+ safetyBuffer?: number;
8
+ };
9
+ export type VisibleTagsLayout = {
10
+ visibleItemIndices: number[];
11
+ hiddenItemCount: number;
12
+ hasOverflow: boolean;
13
+ };
14
+ export declare const computeVisibleTagsLayout: ({ containerWidth, itemWidths, itemGap, overflowWidth, allowOverflow, safetyBuffer, }: ComputeVisibleTagsLayoutParams) => VisibleTagsLayout;
15
+ type UseVisibleTagsParams = ComputeVisibleTagsLayoutParams;
16
+ export declare const useVisibleTags: (params: UseVisibleTagsParams) => VisibleTagsLayout;
17
+ export {};
18
+ //# sourceMappingURL=useVisibleTags.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useVisibleTags.d.ts","sourceRoot":"","sources":["../../../src/components/tagList/useVisibleTags.ts"],"names":[],"mappings":"AAGA,KAAK,8BAA8B,GAAG;IACpC,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAI,sFAOtC,8BAA8B,KAAG,iBAiCnC,CAAC;AAEF,KAAK,oBAAoB,GAAG,8BAA8B,CAAC;AAE3D,eAAO,MAAM,cAAc,GAAI,QAAQ,oBAAoB,KAAG,iBAW3D,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { useMemo } from 'react';
2
+ import { sumSpacedWidths } from '../../utils/spacedWidths.js';
3
+ export const computeVisibleTagsLayout = ({ containerWidth, itemWidths, itemGap, overflowWidth, allowOverflow, safetyBuffer = 1, }) => {
4
+ const totalItemCount = itemWidths.length;
5
+ if (totalItemCount === 0 || containerWidth <= 0) {
6
+ return {
7
+ visibleItemIndices: [],
8
+ hiddenItemCount: 0,
9
+ hasOverflow: false,
10
+ };
11
+ }
12
+ for (let visibleItemCount = totalItemCount; visibleItemCount >= 0; visibleItemCount -= 1) {
13
+ const hiddenItemCount = totalItemCount - visibleItemCount;
14
+ const hasOverflow = hiddenItemCount > 0;
15
+ const overflowReserve = hasOverflow && allowOverflow
16
+ ? overflowWidth + (visibleItemCount > 0 ? itemGap : 0)
17
+ : 0;
18
+ const requiredWidth = sumSpacedWidths(itemWidths, itemGap, visibleItemCount) + overflowReserve;
19
+ if (requiredWidth <= Math.max(0, containerWidth - safetyBuffer)) {
20
+ return {
21
+ visibleItemIndices: Array.from({ length: visibleItemCount }, (_, index) => index),
22
+ hiddenItemCount,
23
+ hasOverflow,
24
+ };
25
+ }
26
+ }
27
+ return {
28
+ visibleItemIndices: [],
29
+ hiddenItemCount: totalItemCount,
30
+ hasOverflow: allowOverflow,
31
+ };
32
+ };
33
+ export const useVisibleTags = (params) => useMemo(() => computeVisibleTagsLayout(params), [
34
+ params.allowOverflow,
35
+ params.containerWidth,
36
+ params.itemGap,
37
+ params.itemWidths,
38
+ params.overflowWidth,
39
+ params.safetyBuffer,
40
+ ]);
41
+ //# sourceMappingURL=useVisibleTags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useVisibleTags.js","sourceRoot":"","sources":["../../../src/components/tagList/useVisibleTags.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAiBrD,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,EACvC,cAAc,EACd,UAAU,EACV,OAAO,EACP,aAAa,EACb,aAAa,EACb,YAAY,GAAG,CAAC,GACe,EAAqB,EAAE;IACtD,MAAM,cAAc,GAAG,UAAU,CAAC,MAAM,CAAC;IAEzC,IAAI,cAAc,KAAK,CAAC,IAAI,cAAc,IAAI,CAAC,EAAE,CAAC;QAChD,OAAO;YACL,kBAAkB,EAAE,EAAE;YACtB,eAAe,EAAE,CAAC;YAClB,WAAW,EAAE,KAAK;SACnB,CAAC;IACJ,CAAC;IAED,KAAK,IAAI,gBAAgB,GAAG,cAAc,EAAE,gBAAgB,IAAI,CAAC,EAAE,gBAAgB,IAAI,CAAC,EAAE,CAAC;QACzF,MAAM,eAAe,GAAG,cAAc,GAAG,gBAAgB,CAAC;QAC1D,MAAM,WAAW,GAAG,eAAe,GAAG,CAAC,CAAC;QACxC,MAAM,eAAe,GAAG,WAAW,IAAI,aAAa;YAClD,CAAC,CAAC,aAAa,GAAG,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;YACtD,CAAC,CAAC,CAAC,CAAC;QACN,MAAM,aAAa,GAAG,eAAe,CAAC,UAAU,EAAE,OAAO,EAAE,gBAAgB,CAAC,GAAG,eAAe,CAAC;QAE/F,IAAI,aAAa,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,cAAc,GAAG,YAAY,CAAC,EAAE,CAAC;YAChE,OAAO;gBACL,kBAAkB,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC;gBACjF,eAAe;gBACf,WAAW;aACZ,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,kBAAkB,EAAE,EAAE;QACtB,eAAe,EAAE,cAAc;QAC/B,WAAW,EAAE,aAAa;KAC3B,CAAC;AACJ,CAAC,CAAC;AAIF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,MAA4B,EAAqB,EAAE,CAChF,OAAO,CACL,GAAG,EAAE,CAAC,wBAAwB,CAAC,MAAM,CAAC,EACtC;IACE,MAAM,CAAC,aAAa;IACpB,MAAM,CAAC,cAAc;IACrB,MAAM,CAAC,OAAO;IACd,MAAM,CAAC,UAAU;IACjB,MAAM,CAAC,aAAa;IACpB,MAAM,CAAC,YAAY;CACpB,CACF,CAAC"}