@furystack/shades-common-components 12.3.0 → 12.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 (268) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/esm/components/app-bar-link.spec.js +16 -19
  3. package/esm/components/app-bar-link.spec.js.map +1 -1
  4. package/esm/components/app-bar.spec.js +6 -4
  5. package/esm/components/app-bar.spec.js.map +1 -1
  6. package/esm/components/avatar.spec.js +9 -9
  7. package/esm/components/avatar.spec.js.map +1 -1
  8. package/esm/components/breadcrumb.spec.js +2 -2
  9. package/esm/components/breadcrumb.spec.js.map +1 -1
  10. package/esm/components/button-group.d.ts +32 -0
  11. package/esm/components/button-group.d.ts.map +1 -1
  12. package/esm/components/button-group.js +26 -2
  13. package/esm/components/button-group.js.map +1 -1
  14. package/esm/components/button-group.spec.js +127 -11
  15. package/esm/components/button-group.spec.js.map +1 -1
  16. package/esm/components/button.spec.js +4 -4
  17. package/esm/components/button.spec.js.map +1 -1
  18. package/esm/components/cache-view.spec.js +2 -3
  19. package/esm/components/cache-view.spec.js.map +1 -1
  20. package/esm/components/carousel.spec.js +47 -47
  21. package/esm/components/carousel.spec.js.map +1 -1
  22. package/esm/components/circular-progress.spec.js +2 -2
  23. package/esm/components/command-palette/command-palette-input.spec.js +23 -19
  24. package/esm/components/command-palette/command-palette-input.spec.js.map +1 -1
  25. package/esm/components/command-palette/command-palette-suggestion-list.spec.js +27 -27
  26. package/esm/components/command-palette/command-palette-suggestion-list.spec.js.map +1 -1
  27. package/esm/components/command-palette/index.spec.js +64 -51
  28. package/esm/components/command-palette/index.spec.js.map +1 -1
  29. package/esm/components/context-menu/context-menu.spec.js +33 -33
  30. package/esm/components/context-menu/context-menu.spec.js.map +1 -1
  31. package/esm/components/data-grid/body.spec.js +13 -13
  32. package/esm/components/data-grid/body.spec.js.map +1 -1
  33. package/esm/components/data-grid/data-grid-row.spec.js +8 -8
  34. package/esm/components/data-grid/data-grid-row.spec.js.map +1 -1
  35. package/esm/components/data-grid/data-grid.d.ts +40 -2
  36. package/esm/components/data-grid/data-grid.d.ts.map +1 -1
  37. package/esm/components/data-grid/data-grid.js +7 -10
  38. package/esm/components/data-grid/data-grid.js.map +1 -1
  39. package/esm/components/data-grid/data-grid.spec.js +71 -28
  40. package/esm/components/data-grid/data-grid.spec.js.map +1 -1
  41. package/esm/components/data-grid/filters/boolean-filter.d.ts +12 -0
  42. package/esm/components/data-grid/filters/boolean-filter.d.ts.map +1 -0
  43. package/esm/components/data-grid/filters/boolean-filter.js +27 -0
  44. package/esm/components/data-grid/filters/boolean-filter.js.map +1 -0
  45. package/esm/components/data-grid/filters/boolean-filter.spec.d.ts +2 -0
  46. package/esm/components/data-grid/filters/boolean-filter.spec.d.ts.map +1 -0
  47. package/esm/components/data-grid/filters/boolean-filter.spec.js +114 -0
  48. package/esm/components/data-grid/filters/boolean-filter.spec.js.map +1 -0
  49. package/esm/components/data-grid/filters/date-filter.d.ts +12 -0
  50. package/esm/components/data-grid/filters/date-filter.d.ts.map +1 -0
  51. package/esm/components/data-grid/filters/date-filter.js +109 -0
  52. package/esm/components/data-grid/filters/date-filter.js.map +1 -0
  53. package/esm/components/data-grid/filters/date-filter.spec.d.ts +2 -0
  54. package/esm/components/data-grid/filters/date-filter.spec.d.ts.map +1 -0
  55. package/esm/components/data-grid/filters/date-filter.spec.js +145 -0
  56. package/esm/components/data-grid/filters/date-filter.spec.js.map +1 -0
  57. package/esm/components/data-grid/filters/enum-filter.d.ts +16 -0
  58. package/esm/components/data-grid/filters/enum-filter.d.ts.map +1 -0
  59. package/esm/components/data-grid/filters/enum-filter.js +72 -0
  60. package/esm/components/data-grid/filters/enum-filter.js.map +1 -0
  61. package/esm/components/data-grid/filters/enum-filter.spec.d.ts +2 -0
  62. package/esm/components/data-grid/filters/enum-filter.spec.d.ts.map +1 -0
  63. package/esm/components/data-grid/filters/enum-filter.spec.js +136 -0
  64. package/esm/components/data-grid/filters/enum-filter.spec.js.map +1 -0
  65. package/esm/components/data-grid/filters/filter-dropdown.d.ts +6 -0
  66. package/esm/components/data-grid/filters/filter-dropdown.d.ts.map +1 -0
  67. package/esm/components/data-grid/filters/filter-dropdown.js +41 -0
  68. package/esm/components/data-grid/filters/filter-dropdown.js.map +1 -0
  69. package/esm/components/data-grid/filters/filter-dropdown.spec.d.ts +2 -0
  70. package/esm/components/data-grid/filters/filter-dropdown.spec.d.ts.map +1 -0
  71. package/esm/components/data-grid/filters/filter-dropdown.spec.js +69 -0
  72. package/esm/components/data-grid/filters/filter-dropdown.spec.js.map +1 -0
  73. package/esm/components/data-grid/filters/filter-styles.d.ts +24 -0
  74. package/esm/components/data-grid/filters/filter-styles.d.ts.map +1 -0
  75. package/esm/components/data-grid/filters/filter-styles.js +25 -0
  76. package/esm/components/data-grid/filters/filter-styles.js.map +1 -0
  77. package/esm/components/data-grid/filters/index.d.ts +7 -0
  78. package/esm/components/data-grid/filters/index.d.ts.map +1 -0
  79. package/esm/components/data-grid/filters/index.js +7 -0
  80. package/esm/components/data-grid/filters/index.js.map +1 -0
  81. package/esm/components/data-grid/filters/number-filter.d.ts +12 -0
  82. package/esm/components/data-grid/filters/number-filter.d.ts.map +1 -0
  83. package/esm/components/data-grid/filters/number-filter.js +65 -0
  84. package/esm/components/data-grid/filters/number-filter.js.map +1 -0
  85. package/esm/components/data-grid/filters/number-filter.spec.d.ts +2 -0
  86. package/esm/components/data-grid/filters/number-filter.spec.d.ts.map +1 -0
  87. package/esm/components/data-grid/filters/number-filter.spec.js +142 -0
  88. package/esm/components/data-grid/filters/number-filter.spec.js.map +1 -0
  89. package/esm/components/data-grid/filters/string-filter.d.ts +12 -0
  90. package/esm/components/data-grid/filters/string-filter.d.ts.map +1 -0
  91. package/esm/components/data-grid/filters/string-filter.js +63 -0
  92. package/esm/components/data-grid/filters/string-filter.js.map +1 -0
  93. package/esm/components/data-grid/filters/string-filter.spec.d.ts +2 -0
  94. package/esm/components/data-grid/filters/string-filter.spec.d.ts.map +1 -0
  95. package/esm/components/data-grid/filters/string-filter.spec.js +128 -0
  96. package/esm/components/data-grid/filters/string-filter.spec.js.map +1 -0
  97. package/esm/components/data-grid/footer.d.ts.map +1 -1
  98. package/esm/components/data-grid/footer.js +24 -9
  99. package/esm/components/data-grid/footer.js.map +1 -1
  100. package/esm/components/data-grid/footer.spec.js +38 -36
  101. package/esm/components/data-grid/footer.spec.js.map +1 -1
  102. package/esm/components/data-grid/header.d.ts +6 -9
  103. package/esm/components/data-grid/header.d.ts.map +1 -1
  104. package/esm/components/data-grid/header.js +51 -117
  105. package/esm/components/data-grid/header.js.map +1 -1
  106. package/esm/components/data-grid/header.spec.js +116 -187
  107. package/esm/components/data-grid/header.spec.js.map +1 -1
  108. package/esm/components/data-grid/index.d.ts +1 -0
  109. package/esm/components/data-grid/index.d.ts.map +1 -1
  110. package/esm/components/data-grid/index.js +1 -0
  111. package/esm/components/data-grid/index.js.map +1 -1
  112. package/esm/components/data-grid/selection-cell.spec.js +8 -8
  113. package/esm/components/data-grid/selection-cell.spec.js.map +1 -1
  114. package/esm/components/drawer/drawer-toggle-button.spec.js +22 -22
  115. package/esm/components/drawer/drawer-toggle-button.spec.js.map +1 -1
  116. package/esm/components/drawer/index.spec.js +36 -36
  117. package/esm/components/drawer/index.spec.js.map +1 -1
  118. package/esm/components/dropdown.spec.js +38 -30
  119. package/esm/components/dropdown.spec.js.map +1 -1
  120. package/esm/components/fab.spec.js +4 -4
  121. package/esm/components/fab.spec.js.map +1 -1
  122. package/esm/components/form.d.ts +5 -2
  123. package/esm/components/form.d.ts.map +1 -1
  124. package/esm/components/form.js +28 -6
  125. package/esm/components/form.js.map +1 -1
  126. package/esm/components/form.spec.js +227 -20
  127. package/esm/components/form.spec.js.map +1 -1
  128. package/esm/components/grid.spec.js +3 -3
  129. package/esm/components/grid.spec.js.map +1 -1
  130. package/esm/components/image.spec.js +55 -52
  131. package/esm/components/image.spec.js.map +1 -1
  132. package/esm/components/inputs/autocomplete.spec.js +7 -14
  133. package/esm/components/inputs/autocomplete.spec.js.map +1 -1
  134. package/esm/components/inputs/checkbox.spec.js +22 -22
  135. package/esm/components/inputs/checkbox.spec.js.map +1 -1
  136. package/esm/components/inputs/input-number.spec.js +47 -47
  137. package/esm/components/inputs/input-number.spec.js.map +1 -1
  138. package/esm/components/inputs/input.spec.js +53 -53
  139. package/esm/components/inputs/input.spec.js.map +1 -1
  140. package/esm/components/inputs/radio-group.spec.js +14 -14
  141. package/esm/components/inputs/radio-group.spec.js.map +1 -1
  142. package/esm/components/inputs/radio.spec.js +16 -16
  143. package/esm/components/inputs/radio.spec.js.map +1 -1
  144. package/esm/components/inputs/select.spec.js +74 -74
  145. package/esm/components/inputs/select.spec.js.map +1 -1
  146. package/esm/components/inputs/slider.spec.js +16 -16
  147. package/esm/components/inputs/slider.spec.js.map +1 -1
  148. package/esm/components/inputs/switch.spec.js +24 -24
  149. package/esm/components/inputs/switch.spec.js.map +1 -1
  150. package/esm/components/inputs/text-area.spec.js +17 -17
  151. package/esm/components/inputs/text-area.spec.js.map +1 -1
  152. package/esm/components/linear-progress.spec.js +2 -2
  153. package/esm/components/list/list.spec.js +36 -36
  154. package/esm/components/list/list.spec.js.map +1 -1
  155. package/esm/components/markdown/markdown-display.spec.js +15 -15
  156. package/esm/components/markdown/markdown-display.spec.js.map +1 -1
  157. package/esm/components/markdown/markdown-editor.spec.js +8 -8
  158. package/esm/components/markdown/markdown-editor.spec.js.map +1 -1
  159. package/esm/components/markdown/markdown-input.spec.js +17 -17
  160. package/esm/components/markdown/markdown-input.spec.js.map +1 -1
  161. package/esm/components/menu/menu.spec.js +28 -28
  162. package/esm/components/menu/menu.spec.js.map +1 -1
  163. package/esm/components/modal.spec.js +15 -18
  164. package/esm/components/modal.spec.js.map +1 -1
  165. package/esm/components/noty-list.spec.js +25 -23
  166. package/esm/components/noty-list.spec.js.map +1 -1
  167. package/esm/components/page-container/index.spec.js +16 -16
  168. package/esm/components/page-container/index.spec.js.map +1 -1
  169. package/esm/components/page-container/page-header.spec.js +16 -16
  170. package/esm/components/page-container/page-header.spec.js.map +1 -1
  171. package/esm/components/page-layout/index.spec.js +29 -29
  172. package/esm/components/page-layout/index.spec.js.map +1 -1
  173. package/esm/components/paper.spec.js +3 -3
  174. package/esm/components/paper.spec.js.map +1 -1
  175. package/esm/components/rating.spec.js +61 -61
  176. package/esm/components/rating.spec.js.map +1 -1
  177. package/esm/components/skeleton.spec.js +10 -6
  178. package/esm/components/skeleton.spec.js.map +1 -1
  179. package/esm/components/suggest/suggest-input.spec.js +4 -10
  180. package/esm/components/suggest/suggest-input.spec.js.map +1 -1
  181. package/esm/components/tabs.spec.js +30 -30
  182. package/esm/components/tabs.spec.js.map +1 -1
  183. package/esm/components/tree/tree.spec.js +27 -27
  184. package/esm/components/tree/tree.spec.js.map +1 -1
  185. package/esm/components/typography.spec.js +3 -3
  186. package/esm/components/typography.spec.js.map +1 -1
  187. package/esm/components/wizard/index.spec.js +5 -5
  188. package/esm/components/wizard/index.spec.js.map +1 -1
  189. package/esm/utils/promisify-animation.d.ts.map +1 -1
  190. package/esm/utils/promisify-animation.js +3 -0
  191. package/esm/utils/promisify-animation.js.map +1 -1
  192. package/package.json +2 -2
  193. package/src/components/app-bar-link.spec.tsx +16 -19
  194. package/src/components/app-bar.spec.tsx +6 -4
  195. package/src/components/avatar.spec.tsx +9 -9
  196. package/src/components/breadcrumb.spec.tsx +2 -2
  197. package/src/components/button-group.spec.tsx +155 -11
  198. package/src/components/button-group.tsx +49 -2
  199. package/src/components/button.spec.tsx +4 -4
  200. package/src/components/cache-view.spec.tsx +3 -3
  201. package/src/components/carousel.spec.tsx +47 -47
  202. package/src/components/circular-progress.spec.tsx +2 -2
  203. package/src/components/command-palette/command-palette-input.spec.tsx +23 -19
  204. package/src/components/command-palette/command-palette-suggestion-list.spec.tsx +27 -27
  205. package/src/components/command-palette/index.spec.tsx +64 -51
  206. package/src/components/context-menu/context-menu.spec.tsx +33 -33
  207. package/src/components/data-grid/body.spec.tsx +13 -13
  208. package/src/components/data-grid/data-grid-row.spec.tsx +8 -8
  209. package/src/components/data-grid/data-grid.spec.tsx +106 -28
  210. package/src/components/data-grid/data-grid.tsx +44 -11
  211. package/src/components/data-grid/filters/boolean-filter.spec.tsx +142 -0
  212. package/src/components/data-grid/filters/boolean-filter.tsx +45 -0
  213. package/src/components/data-grid/filters/date-filter.spec.tsx +181 -0
  214. package/src/components/data-grid/filters/date-filter.tsx +162 -0
  215. package/src/components/data-grid/filters/enum-filter.spec.tsx +168 -0
  216. package/src/components/data-grid/filters/enum-filter.tsx +119 -0
  217. package/src/components/data-grid/filters/filter-dropdown.spec.tsx +89 -0
  218. package/src/components/data-grid/filters/filter-dropdown.tsx +60 -0
  219. package/src/components/data-grid/filters/filter-styles.ts +26 -0
  220. package/src/components/data-grid/filters/index.ts +6 -0
  221. package/src/components/data-grid/filters/number-filter.spec.tsx +174 -0
  222. package/src/components/data-grid/filters/number-filter.tsx +115 -0
  223. package/src/components/data-grid/filters/string-filter.spec.tsx +157 -0
  224. package/src/components/data-grid/filters/string-filter.tsx +112 -0
  225. package/src/components/data-grid/footer.spec.tsx +38 -36
  226. package/src/components/data-grid/footer.tsx +21 -8
  227. package/src/components/data-grid/header.spec.tsx +128 -212
  228. package/src/components/data-grid/header.tsx +95 -183
  229. package/src/components/data-grid/index.tsx +1 -0
  230. package/src/components/data-grid/selection-cell.spec.tsx +8 -8
  231. package/src/components/drawer/drawer-toggle-button.spec.tsx +22 -22
  232. package/src/components/drawer/index.spec.tsx +36 -36
  233. package/src/components/dropdown.spec.tsx +38 -30
  234. package/src/components/fab.spec.tsx +4 -4
  235. package/src/components/form.spec.tsx +329 -20
  236. package/src/components/form.tsx +31 -8
  237. package/src/components/grid.spec.tsx +3 -3
  238. package/src/components/image.spec.tsx +55 -52
  239. package/src/components/inputs/autocomplete.spec.tsx +7 -14
  240. package/src/components/inputs/checkbox.spec.tsx +22 -22
  241. package/src/components/inputs/input-number.spec.tsx +47 -47
  242. package/src/components/inputs/input.spec.tsx +53 -53
  243. package/src/components/inputs/radio-group.spec.tsx +14 -14
  244. package/src/components/inputs/radio.spec.tsx +16 -16
  245. package/src/components/inputs/select.spec.tsx +74 -74
  246. package/src/components/inputs/slider.spec.tsx +16 -16
  247. package/src/components/inputs/switch.spec.tsx +24 -24
  248. package/src/components/inputs/text-area.spec.tsx +17 -17
  249. package/src/components/linear-progress.spec.tsx +2 -2
  250. package/src/components/list/list.spec.tsx +36 -36
  251. package/src/components/markdown/markdown-display.spec.tsx +15 -15
  252. package/src/components/markdown/markdown-editor.spec.tsx +8 -8
  253. package/src/components/markdown/markdown-input.spec.tsx +17 -17
  254. package/src/components/menu/menu.spec.tsx +28 -28
  255. package/src/components/modal.spec.tsx +15 -18
  256. package/src/components/noty-list.spec.tsx +25 -23
  257. package/src/components/page-container/index.spec.tsx +16 -16
  258. package/src/components/page-container/page-header.spec.tsx +16 -16
  259. package/src/components/page-layout/index.spec.tsx +29 -29
  260. package/src/components/paper.spec.tsx +3 -3
  261. package/src/components/rating.spec.tsx +61 -61
  262. package/src/components/skeleton.spec.tsx +10 -6
  263. package/src/components/suggest/suggest-input.spec.tsx +4 -10
  264. package/src/components/tabs.spec.tsx +30 -30
  265. package/src/components/tree/tree.spec.tsx +27 -27
  266. package/src/components/typography.spec.tsx +3 -3
  267. package/src/components/wizard/index.spec.tsx +5 -5
  268. package/src/utils/promisify-animation.ts +3 -0
@@ -1,6 +1,6 @@
1
1
  import { Injector } from '@furystack/inject'
2
2
  import { createComponent, flushUpdates, initializeShadeRoot, LocationService } from '@furystack/shades'
3
- import { sleepAsync, usingAsync } from '@furystack/utils'
3
+ import { usingAsync } from '@furystack/utils'
4
4
  import { afterEach, beforeEach, describe, expect, it } from 'vitest'
5
5
  import { AppBarLink } from './app-bar-link.js'
6
6
 
@@ -24,7 +24,7 @@ describe('AppBarLink component', () => {
24
24
  jsxElement: <AppBarLink href="/test">Link</AppBarLink>,
25
25
  })
26
26
 
27
- await sleepAsync(50)
27
+ await flushUpdates()
28
28
 
29
29
  const appBarLink = document.querySelector('shade-app-bar-link')
30
30
  expect(appBarLink).not.toBeNull()
@@ -42,7 +42,7 @@ describe('AppBarLink component', () => {
42
42
  jsxElement: <AppBarLink href="/test">Test Link Text</AppBarLink>,
43
43
  })
44
44
 
45
- await sleepAsync(50)
45
+ await flushUpdates()
46
46
 
47
47
  expect(document.body.innerHTML).toContain('Test Link Text')
48
48
  })
@@ -58,7 +58,7 @@ describe('AppBarLink component', () => {
58
58
  jsxElement: <AppBarLink href="/my-route">Link</AppBarLink>,
59
59
  })
60
60
 
61
- await sleepAsync(50)
61
+ await flushUpdates()
62
62
 
63
63
  expect(document.body.innerHTML).toContain('href="/my-route"')
64
64
  })
@@ -78,7 +78,7 @@ describe('AppBarLink component', () => {
78
78
  jsxElement: <AppBarLink href="/dashboard">Dashboard</AppBarLink>,
79
79
  })
80
80
 
81
- await sleepAsync(50)
81
+ await flushUpdates()
82
82
 
83
83
  const appBarLink = document.querySelector('shade-app-bar-link')
84
84
  expect(appBarLink?.hasAttribute('data-active')).toBe(true)
@@ -97,7 +97,7 @@ describe('AppBarLink component', () => {
97
97
  jsxElement: <AppBarLink href="/dashboard">Dashboard</AppBarLink>,
98
98
  })
99
99
 
100
- await sleepAsync(50)
100
+ await flushUpdates()
101
101
 
102
102
  const appBarLink = document.querySelector('shade-app-bar-link')
103
103
  expect(appBarLink?.hasAttribute('data-active')).toBe(false)
@@ -116,7 +116,7 @@ describe('AppBarLink component', () => {
116
116
  jsxElement: <AppBarLink href="/dashboard">Dashboard</AppBarLink>,
117
117
  })
118
118
 
119
- await sleepAsync(50)
119
+ await flushUpdates()
120
120
 
121
121
  const appBarLink = document.querySelector('shade-app-bar-link')
122
122
  expect(appBarLink?.hasAttribute('data-active')).toBe(false)
@@ -125,7 +125,6 @@ describe('AppBarLink component', () => {
125
125
  history.pushState(null, '', '/dashboard')
126
126
  injector.getInstance(LocationService).updateState()
127
127
 
128
- await sleepAsync(50)
129
128
  await flushUpdates()
130
129
 
131
130
  expect(appBarLink?.hasAttribute('data-active')).toBe(true)
@@ -144,7 +143,7 @@ describe('AppBarLink component', () => {
144
143
  jsxElement: <AppBarLink href="/dashboard">Dashboard</AppBarLink>,
145
144
  })
146
145
 
147
- await sleepAsync(50)
146
+ await flushUpdates()
148
147
 
149
148
  const appBarLink = document.querySelector('shade-app-bar-link')
150
149
  expect(appBarLink?.hasAttribute('data-active')).toBe(true)
@@ -153,7 +152,6 @@ describe('AppBarLink component', () => {
153
152
  history.pushState(null, '', '/other')
154
153
  injector.getInstance(LocationService).updateState()
155
154
 
156
- await sleepAsync(50)
157
155
  await flushUpdates()
158
156
 
159
157
  expect(appBarLink?.hasAttribute('data-active')).toBe(false)
@@ -172,7 +170,7 @@ describe('AppBarLink component', () => {
172
170
  jsxElement: <AppBarLink href="/users/:id">Users</AppBarLink>,
173
171
  })
174
172
 
175
- await sleepAsync(50)
173
+ await flushUpdates()
176
174
 
177
175
  const appBarLink = document.querySelector('shade-app-bar-link')
178
176
  expect(appBarLink?.hasAttribute('data-active')).toBe(true)
@@ -195,7 +193,7 @@ describe('AppBarLink component', () => {
195
193
  ),
196
194
  })
197
195
 
198
- await sleepAsync(50)
196
+ await flushUpdates()
199
197
 
200
198
  const appBarLink = document.querySelector('shade-app-bar-link')
201
199
  expect(appBarLink?.hasAttribute('data-active')).toBe(true)
@@ -214,7 +212,7 @@ describe('AppBarLink component', () => {
214
212
  jsxElement: <AppBarLink href="/admin">Admin</AppBarLink>,
215
213
  })
216
214
 
217
- await sleepAsync(50)
215
+ await flushUpdates()
218
216
 
219
217
  const appBarLink = document.querySelector('shade-app-bar-link')
220
218
  expect(appBarLink?.hasAttribute('data-active')).toBe(false)
@@ -241,7 +239,7 @@ describe('AppBarLink component', () => {
241
239
  ),
242
240
  })
243
241
 
244
- await sleepAsync(50)
242
+ await flushUpdates()
245
243
 
246
244
  const links = document.querySelectorAll('shade-app-bar-link')
247
245
  expect(links[0]?.hasAttribute('data-active')).toBe(false)
@@ -267,7 +265,7 @@ describe('AppBarLink component', () => {
267
265
  ),
268
266
  })
269
267
 
270
- await sleepAsync(50)
268
+ await flushUpdates()
271
269
 
272
270
  const links = document.querySelectorAll('shade-app-bar-link')
273
271
  expect(links[0]?.hasAttribute('data-active')).toBe(true)
@@ -277,7 +275,6 @@ describe('AppBarLink component', () => {
277
275
  history.pushState(null, '', '/settings')
278
276
  injector.getInstance(LocationService).updateState()
279
277
 
280
- await sleepAsync(50)
281
278
  await flushUpdates()
282
279
 
283
280
  expect(links[0]?.hasAttribute('data-active')).toBe(false)
@@ -297,7 +294,7 @@ describe('AppBarLink component', () => {
297
294
  jsxElement: <AppBarLink href="/test">Link</AppBarLink>,
298
295
  })
299
296
 
300
- await sleepAsync(50)
297
+ await flushUpdates()
301
298
 
302
299
  const appBarLink = document.querySelector('shade-app-bar-link') as HTMLElement
303
300
  const computedStyle = window.getComputedStyle(appBarLink)
@@ -315,7 +312,7 @@ describe('AppBarLink component', () => {
315
312
  jsxElement: <AppBarLink href="/test">Link</AppBarLink>,
316
313
  })
317
314
 
318
- await sleepAsync(50)
315
+ await flushUpdates()
319
316
 
320
317
  const appBarLink = document.querySelector('shade-app-bar-link') as HTMLElement
321
318
  const computedStyle = window.getComputedStyle(appBarLink)
@@ -333,7 +330,7 @@ describe('AppBarLink component', () => {
333
330
  jsxElement: <AppBarLink href="/test">Link</AppBarLink>,
334
331
  })
335
332
 
336
- await sleepAsync(50)
333
+ await flushUpdates()
337
334
 
338
335
  const appBarLink = document.querySelector('shade-app-bar-link') as HTMLElement
339
336
  const computedStyle = window.getComputedStyle(appBarLink)
@@ -1,6 +1,6 @@
1
1
  import { Injector } from '@furystack/inject'
2
- import { createComponent, initializeShadeRoot } from '@furystack/shades'
3
- import { sleepAsync, usingAsync } from '@furystack/utils'
2
+ import { createComponent, flushUpdates, initializeShadeRoot } from '@furystack/shades'
3
+ import { usingAsync } from '@furystack/utils'
4
4
  import { afterEach, beforeEach, describe, expect, it } from 'vitest'
5
5
  import { AppBar } from './app-bar.js'
6
6
 
@@ -23,7 +23,9 @@ describe('AppBar component', () => {
23
23
  jsxElement: <AppBar>{children}</AppBar>,
24
24
  })
25
25
 
26
- await sleepAsync(50)
26
+ await flushUpdates()
27
+ await new Promise((resolve) => requestAnimationFrame(resolve))
28
+ await flushUpdates()
27
29
 
28
30
  return {
29
31
  injector,
@@ -63,7 +65,7 @@ describe('AppBar component', () => {
63
65
  ),
64
66
  })
65
67
 
66
- await sleepAsync(50)
68
+ await flushUpdates()
67
69
 
68
70
  const appBar = document.querySelector('shade-app-bar')
69
71
  expect(appBar).not.toBeNull()
@@ -1,6 +1,6 @@
1
1
  import { Injector } from '@furystack/inject'
2
- import { createComponent, initializeShadeRoot } from '@furystack/shades'
3
- import { sleepAsync, usingAsync } from '@furystack/utils'
2
+ import { createComponent, flushUpdates, initializeShadeRoot } from '@furystack/shades'
3
+ import { usingAsync } from '@furystack/utils'
4
4
  import { afterEach, beforeEach, describe, expect, it } from 'vitest'
5
5
  import { Avatar } from './avatar.js'
6
6
 
@@ -24,7 +24,7 @@ describe('Avatar component', () => {
24
24
  jsxElement: <Avatar avatarUrl={testUrl} />,
25
25
  })
26
26
 
27
- await sleepAsync(50)
27
+ await flushUpdates()
28
28
 
29
29
  const avatar = document.querySelector('shade-avatar')
30
30
  expect(avatar).not.toBeNull()
@@ -46,7 +46,7 @@ describe('Avatar component', () => {
46
46
  jsxElement: <Avatar avatarUrl="invalid-url" />,
47
47
  })
48
48
 
49
- await sleepAsync(50)
49
+ await flushUpdates()
50
50
 
51
51
  const avatar = document.querySelector('shade-avatar')
52
52
  expect(avatar).not.toBeNull()
@@ -58,7 +58,7 @@ describe('Avatar component', () => {
58
58
  const errorEvent = new Event('error')
59
59
  img?.dispatchEvent(errorEvent)
60
60
 
61
- await sleepAsync(50)
61
+ await flushUpdates()
62
62
 
63
63
  // After error, img should be replaced with fallback div
64
64
  const fallbackImg = avatar?.querySelector('img')
@@ -81,7 +81,7 @@ describe('Avatar component', () => {
81
81
  jsxElement: <Avatar avatarUrl="invalid-url" fallback={customFallback} />,
82
82
  })
83
83
 
84
- await sleepAsync(50)
84
+ await flushUpdates()
85
85
 
86
86
  const avatar = document.querySelector('shade-avatar')
87
87
  expect(avatar).not.toBeNull()
@@ -93,7 +93,7 @@ describe('Avatar component', () => {
93
93
  const errorEvent = new Event('error')
94
94
  img?.dispatchEvent(errorEvent)
95
95
 
96
- await sleepAsync(50)
96
+ await flushUpdates()
97
97
 
98
98
  // After error, img should be replaced with fallback div
99
99
  const fallbackImg = avatar?.querySelector('img')
@@ -116,7 +116,7 @@ describe('Avatar component', () => {
116
116
  jsxElement: <Avatar avatarUrl="https://example.com/avatar.png" style={{ width: '64px', height: '64px' }} />,
117
117
  })
118
118
 
119
- await sleepAsync(50)
119
+ await flushUpdates()
120
120
 
121
121
  const avatar = document.querySelector('shade-avatar') as HTMLElement
122
122
  expect(avatar).not.toBeNull()
@@ -135,7 +135,7 @@ describe('Avatar component', () => {
135
135
  jsxElement: <Avatar avatarUrl="https://example.com/avatar.png" className="custom-avatar" title="User Avatar" />,
136
136
  })
137
137
 
138
- await sleepAsync(50)
138
+ await flushUpdates()
139
139
 
140
140
  const avatar = document.querySelector('shade-avatar') as HTMLElement
141
141
  expect(avatar).not.toBeNull()
@@ -1,7 +1,7 @@
1
1
  import { Injector } from '@furystack/inject'
2
2
  import { createComponent, flushUpdates, initializeShadeRoot, LocationService } from '@furystack/shades'
3
3
  import type { ExtractRouteParams, NestedRoute } from '@furystack/shades'
4
- import { sleepAsync, usingAsync } from '@furystack/utils'
4
+ import { usingAsync } from '@furystack/utils'
5
5
  import { afterEach, beforeEach, describe, expect, expectTypeOf, it, vi } from 'vitest'
6
6
  import type { BreadcrumbItem, TypedBreadcrumbProps } from './breadcrumb.js'
7
7
  import { Breadcrumb, createBreadcrumb } from './breadcrumb.js'
@@ -247,7 +247,7 @@ describe('Breadcrumb', () => {
247
247
  ),
248
248
  })
249
249
 
250
- await sleepAsync(50)
250
+ await flushUpdates()
251
251
 
252
252
  const breadcrumb = rootElement.querySelector('nav[is="shade-breadcrumb"]')
253
253
  expect(breadcrumb?.classList.contains('custom-breadcrumb')).toBe(true)
@@ -1,6 +1,6 @@
1
1
  import { Injector } from '@furystack/inject'
2
- import { createComponent, initializeShadeRoot } from '@furystack/shades'
3
- import { sleepAsync, usingAsync } from '@furystack/utils'
2
+ import { createComponent, flushUpdates, initializeShadeRoot } from '@furystack/shades'
3
+ import { usingAsync } from '@furystack/utils'
4
4
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
5
5
  import {
6
6
  ButtonGroup,
@@ -28,7 +28,7 @@ describe('ButtonGroup', () => {
28
28
  rootElement: root,
29
29
  jsxElement: <ButtonGroup {...props}>{children}</ButtonGroup>,
30
30
  })
31
- await sleepAsync(50)
31
+ await flushUpdates()
32
32
  return {
33
33
  injector,
34
34
  group: root.querySelector('shade-button-group') as HTMLElement,
@@ -132,6 +132,78 @@ describe('ButtonGroup', () => {
132
132
  })
133
133
  })
134
134
 
135
+ describe('ToggleButton', () => {
136
+ beforeEach(() => {
137
+ document.body.innerHTML = '<div id="root"></div>'
138
+ })
139
+
140
+ afterEach(() => {
141
+ document.body.innerHTML = ''
142
+ })
143
+
144
+ const renderToggleButton = async (props: Parameters<typeof ToggleButton>[0]) => {
145
+ const injector = new Injector()
146
+ const root = document.getElementById('root')!
147
+ initializeShadeRoot({
148
+ injector,
149
+ rootElement: root,
150
+ jsxElement: <ToggleButton {...props}>Label</ToggleButton>,
151
+ })
152
+ await flushUpdates()
153
+ return {
154
+ injector,
155
+ button: root.querySelector('button[is="shade-toggle-button"]') as HTMLButtonElement,
156
+ [Symbol.asyncDispose]: () => injector[Symbol.asyncDispose](),
157
+ }
158
+ }
159
+
160
+ describe('pressed', () => {
161
+ it('should not set data-selected when pressed is not specified', async () => {
162
+ await usingAsync(await renderToggleButton({ value: 'a' }), async ({ button }) => {
163
+ expect(button.hasAttribute('data-selected')).toBe(false)
164
+ })
165
+ })
166
+
167
+ it('should set data-selected when pressed is true', async () => {
168
+ await usingAsync(await renderToggleButton({ value: 'a', pressed: true }), async ({ button }) => {
169
+ expect(button.hasAttribute('data-selected')).toBe(true)
170
+ })
171
+ })
172
+
173
+ it('should not set data-selected when pressed is false', async () => {
174
+ await usingAsync(await renderToggleButton({ value: 'a', pressed: false }), async ({ button }) => {
175
+ expect(button.hasAttribute('data-selected')).toBe(false)
176
+ })
177
+ })
178
+ })
179
+
180
+ describe('size', () => {
181
+ it('should not set data-size by default', async () => {
182
+ await usingAsync(await renderToggleButton({ value: 'a' }), async ({ button }) => {
183
+ expect(button.hasAttribute('data-size')).toBe(false)
184
+ })
185
+ })
186
+
187
+ it('should not set data-size for medium (default)', async () => {
188
+ await usingAsync(await renderToggleButton({ value: 'a', size: 'medium' }), async ({ button }) => {
189
+ expect(button.hasAttribute('data-size')).toBe(false)
190
+ })
191
+ })
192
+
193
+ it('should set data-size="small" for small size', async () => {
194
+ await usingAsync(await renderToggleButton({ value: 'a', size: 'small' }), async ({ button }) => {
195
+ expect(button.getAttribute('data-size')).toBe('small')
196
+ })
197
+ })
198
+
199
+ it('should set data-size="large" for large size', async () => {
200
+ await usingAsync(await renderToggleButton({ value: 'a', size: 'large' }), async ({ button }) => {
201
+ expect(button.getAttribute('data-size')).toBe('large')
202
+ })
203
+ })
204
+ })
205
+ })
206
+
135
207
  describe('ToggleButtonGroup', () => {
136
208
  beforeEach(() => {
137
209
  document.body.innerHTML = '<div id="root"></div>'
@@ -149,7 +221,7 @@ describe('ToggleButtonGroup', () => {
149
221
  rootElement: root,
150
222
  jsxElement: <ToggleButtonGroup {...props}>{children}</ToggleButtonGroup>,
151
223
  })
152
- await sleepAsync(100)
224
+ await flushUpdates()
153
225
  return {
154
226
  injector,
155
227
  group: root.querySelector('shade-toggle-button-group') as HTMLElement,
@@ -257,8 +329,8 @@ describe('ToggleButtonGroup', () => {
257
329
  <ToggleButton value="right">Right</ToggleButton>,
258
330
  ] as unknown as JSX.Element[]),
259
331
  async ({ group }) => {
260
- // Wait for requestAnimationFrame
261
- await sleepAsync(50)
332
+ await flushUpdates()
333
+ await new Promise<void>((resolve) => requestAnimationFrame(() => resolve()))
262
334
  const centerBtn = group.querySelector('button[data-value="center"]') as HTMLButtonElement
263
335
  const leftBtn = group.querySelector('button[data-value="left"]') as HTMLButtonElement
264
336
  expect(centerBtn.hasAttribute('data-selected')).toBe(true)
@@ -275,7 +347,8 @@ describe('ToggleButtonGroup', () => {
275
347
  <ToggleButton value="underline">U</ToggleButton>,
276
348
  ] as unknown as JSX.Element[]),
277
349
  async ({ group }) => {
278
- await sleepAsync(50)
350
+ await flushUpdates()
351
+ await new Promise<void>((resolve) => requestAnimationFrame(() => resolve()))
279
352
  const boldBtn = group.querySelector('button[data-value="bold"]') as HTMLButtonElement
280
353
  const italicBtn = group.querySelector('button[data-value="italic"]') as HTMLButtonElement
281
354
  const underlineBtn = group.querySelector('button[data-value="underline"]') as HTMLButtonElement
@@ -314,6 +387,75 @@ describe('ToggleButtonGroup', () => {
314
387
  })
315
388
  })
316
389
  })
390
+
391
+ describe('size', () => {
392
+ it('should not set data-size on children by default', async () => {
393
+ await usingAsync(
394
+ await renderToggleGroup({}, [
395
+ <ToggleButton value="a">A</ToggleButton>,
396
+ <ToggleButton value="b">B</ToggleButton>,
397
+ ] as unknown as JSX.Element[]),
398
+ async ({ group }) => {
399
+ await flushUpdates()
400
+ await new Promise<void>((resolve) => requestAnimationFrame(() => resolve()))
401
+ const buttons = group.querySelectorAll('button[data-value]')
402
+ buttons.forEach((btn) => {
403
+ expect(btn.hasAttribute('data-size')).toBe(false)
404
+ })
405
+ },
406
+ )
407
+ })
408
+
409
+ it('should propagate size="small" to child buttons', async () => {
410
+ await usingAsync(
411
+ await renderToggleGroup({ size: 'small' }, [
412
+ <ToggleButton value="a">A</ToggleButton>,
413
+ <ToggleButton value="b">B</ToggleButton>,
414
+ ] as unknown as JSX.Element[]),
415
+ async ({ group }) => {
416
+ await flushUpdates()
417
+ await new Promise<void>((resolve) => requestAnimationFrame(() => resolve()))
418
+ const buttons = group.querySelectorAll('button[data-value]')
419
+ buttons.forEach((btn) => {
420
+ expect(btn.getAttribute('data-size')).toBe('small')
421
+ })
422
+ },
423
+ )
424
+ })
425
+
426
+ it('should propagate size="large" to child buttons', async () => {
427
+ await usingAsync(
428
+ await renderToggleGroup({ size: 'large' }, [
429
+ <ToggleButton value="a">A</ToggleButton>,
430
+ <ToggleButton value="b">B</ToggleButton>,
431
+ ] as unknown as JSX.Element[]),
432
+ async ({ group }) => {
433
+ await flushUpdates()
434
+ await new Promise<void>((resolve) => requestAnimationFrame(() => resolve()))
435
+ const buttons = group.querySelectorAll('button[data-value]')
436
+ buttons.forEach((btn) => {
437
+ expect(btn.getAttribute('data-size')).toBe('large')
438
+ })
439
+ },
440
+ )
441
+ })
442
+
443
+ it('should remove data-size when size is medium', async () => {
444
+ await usingAsync(
445
+ await renderToggleGroup({ size: 'medium' }, [
446
+ <ToggleButton value="a" size="small">
447
+ A
448
+ </ToggleButton>,
449
+ ] as unknown as JSX.Element[]),
450
+ async ({ group }) => {
451
+ await flushUpdates()
452
+ await new Promise<void>((resolve) => requestAnimationFrame(() => resolve()))
453
+ const btn = group.querySelector('button[data-value]')
454
+ expect(btn?.hasAttribute('data-size')).toBe(false)
455
+ },
456
+ )
457
+ })
458
+ })
317
459
  })
318
460
 
319
461
  describe('SegmentedControl', () => {
@@ -339,7 +481,7 @@ describe('SegmentedControl', () => {
339
481
  rootElement: root,
340
482
  jsxElement: <SegmentedControl options={defaultOptions} {...props} />,
341
483
  })
342
- await sleepAsync(50)
484
+ await flushUpdates()
343
485
  return {
344
486
  injector,
345
487
  control: root.querySelector('shade-segmented-control') as HTMLElement,
@@ -502,7 +644,7 @@ describe('ToggleButtonGroup edge cases', () => {
502
644
  rootElement: root,
503
645
  jsxElement: <ToggleButtonGroup {...props}>{children}</ToggleButtonGroup>,
504
646
  })
505
- await sleepAsync(100)
647
+ await flushUpdates()
506
648
  return {
507
649
  injector,
508
650
  group: root.querySelector('shade-toggle-button-group') as HTMLElement,
@@ -577,7 +719,8 @@ describe('ToggleButtonGroup edge cases', () => {
577
719
  <ToggleButton value="b">B</ToggleButton>,
578
720
  ] as unknown as JSX.Element[]),
579
721
  async ({ group }) => {
580
- await sleepAsync(50)
722
+ await flushUpdates()
723
+ await new Promise<void>((resolve) => requestAnimationFrame(() => resolve()))
581
724
  const buttons = group.querySelectorAll('button[data-value]')
582
725
  buttons.forEach((btn) => {
583
726
  expect(btn.hasAttribute('disabled')).toBe(true)
@@ -593,7 +736,8 @@ describe('ToggleButtonGroup edge cases', () => {
593
736
  <ToggleButton value="b">B</ToggleButton>,
594
737
  ] as unknown as JSX.Element[]),
595
738
  async ({ group }) => {
596
- await sleepAsync(50)
739
+ await flushUpdates()
740
+ await new Promise<void>((resolve) => requestAnimationFrame(() => resolve()))
597
741
  const buttons = group.querySelectorAll('button[data-value]')
598
742
  // First button should have top radius
599
743
  expect((buttons[0] as HTMLElement).style.borderRadius).toContain('0 0')
@@ -89,6 +89,19 @@ export type ToggleButtonProps = PartialElement<HTMLButtonElement> & {
89
89
  value: string
90
90
  /** Whether the button is disabled */
91
91
  disabled?: boolean
92
+ /**
93
+ * The size of the toggle button.
94
+ * @default 'medium'
95
+ */
96
+ size?: 'small' | 'medium' | 'large'
97
+ /**
98
+ * Whether the button is in a pressed (selected) state.
99
+ * Use this for standalone toggle buttons or controlled state.
100
+ * When used inside a `ToggleButtonGroup`, the group manages the
101
+ * pressed state automatically via its `value` prop and will
102
+ * override this attribute.
103
+ */
104
+ pressed?: boolean
92
105
  }
93
106
 
94
107
  export const ToggleButton = Shade<ToggleButtonProps>({
@@ -111,13 +124,17 @@ export const ToggleButton = Shade<ToggleButtonProps>({
111
124
  userSelect: 'none',
112
125
  background: 'transparent',
113
126
  color: 'var(--toggle-color-main)',
114
- boxShadow: '0px 0px 0px 1px var(--toggle-color-main)',
127
+ boxShadow: 'none',
115
128
  transition: buildTransition(
116
129
  ['background', cssVariableTheme.transitions.duration.normal, cssVariableTheme.transitions.easing.default],
117
130
  ['color', cssVariableTheme.transitions.duration.normal, cssVariableTheme.transitions.easing.default],
118
131
  ['box-shadow', cssVariableTheme.transitions.duration.normal, cssVariableTheme.transitions.easing.default],
119
132
  ),
120
133
 
134
+ '&[data-grouped]': {
135
+ boxShadow: '0px 0px 0px 1px var(--toggle-color-main)',
136
+ },
137
+
121
138
  '&:hover:not(:disabled):not([data-selected])': {
122
139
  background: 'color-mix(in srgb, var(--toggle-color-main) 10%, transparent)',
123
140
  },
@@ -140,11 +157,27 @@ export const ToggleButton = Shade<ToggleButtonProps>({
140
157
  '&:active:not(:disabled)': {
141
158
  transform: 'scale(0.96)',
142
159
  },
160
+
161
+ '&[data-size="small"]': {
162
+ padding: `${cssVariableTheme.spacing.xs} ${cssVariableTheme.spacing.sm}`,
163
+ fontSize: cssVariableTheme.typography.fontSize.sm,
164
+ },
165
+
166
+ '&[data-size="large"]': {
167
+ padding: `${cssVariableTheme.spacing.md} ${cssVariableTheme.spacing.xl}`,
168
+ fontSize: cssVariableTheme.typography.fontSize.lg,
169
+ },
143
170
  },
144
171
  render: ({ props, children, useHostProps }) => {
145
172
  useHostProps({
146
173
  'data-value': props.value || undefined,
174
+ 'data-size': props.size && props.size !== 'medium' ? props.size : undefined,
175
+ 'data-selected': props.pressed ? '' : undefined,
147
176
  type: 'button',
177
+ style: {
178
+ '--toggle-color-main': cssVariableTheme.text.secondary,
179
+ ...(props.style as Record<string, string>),
180
+ },
148
181
  })
149
182
 
150
183
  return <>{children}</>
@@ -171,6 +204,12 @@ export type ToggleButtonGroupProps = PartialElement<HTMLElement> & {
171
204
  orientation?: 'horizontal' | 'vertical'
172
205
  /** Whether all toggle buttons are disabled */
173
206
  disabled?: boolean
207
+ /**
208
+ * Size applied to all toggle buttons in the group.
209
+ * Individual ToggleButton `size` props are overridden by this value.
210
+ * @default 'medium'
211
+ */
212
+ size?: 'small' | 'medium' | 'large'
174
213
  }
175
214
 
176
215
  export const ToggleButtonGroup: (props: ToggleButtonGroupProps, children: ChildrenList) => JSX.Element =
@@ -228,7 +267,7 @@ export const ToggleButtonGroup: (props: ToggleButtonGroupProps, children: Childr
228
267
  return { [Symbol.dispose]: () => el?.removeEventListener('click', handleClick) }
229
268
  })
230
269
 
231
- const { orientation = 'horizontal', disabled, color, style } = props
270
+ const { orientation = 'horizontal', disabled, color, size, style } = props
232
271
  const selectedValues = Array.isArray(props.value) ? props.value : props.value ? [props.value] : ([] as string[])
233
272
 
234
273
  const colors = color ? paletteFullColors[color] : defaultToggleColors
@@ -256,10 +295,18 @@ export const ToggleButtonGroup: (props: ToggleButtonGroupProps, children: Childr
256
295
  btn.removeAttribute('data-selected')
257
296
  }
258
297
 
298
+ btn.setAttribute('data-grouped', '')
299
+
259
300
  if (disabled) {
260
301
  btn.setAttribute('disabled', '')
261
302
  }
262
303
 
304
+ if (size && size !== 'medium') {
305
+ btn.setAttribute('data-size', size)
306
+ } else if (size === 'medium') {
307
+ btn.removeAttribute('data-size')
308
+ }
309
+
263
310
  // Propagate color CSS variable
264
311
  ;(btn as HTMLElement).style.setProperty('--toggle-color-main', colors.main)
265
312
 
@@ -1,6 +1,6 @@
1
1
  import { Injector } from '@furystack/inject'
2
- import { createComponent, initializeShadeRoot, Shade } from '@furystack/shades'
3
- import { sleepAsync, usingAsync } from '@furystack/utils'
2
+ import { createComponent, flushUpdates, initializeShadeRoot, Shade } from '@furystack/shades'
3
+ import { usingAsync } from '@furystack/utils'
4
4
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
5
5
  import { Button } from './button.js'
6
6
 
@@ -22,7 +22,7 @@ describe('Button', () => {
22
22
  rootElement: root,
23
23
  jsxElement: <Button {...props}>{children}</Button>,
24
24
  })
25
- await sleepAsync(50)
25
+ await flushUpdates()
26
26
  return {
27
27
  injector,
28
28
  button: root.querySelector('button[is="shade-button"]') as HTMLButtonElement,
@@ -86,7 +86,7 @@ describe('Button', () => {
86
86
  jsxElement: <TestComponent variant="contained" />,
87
87
  })
88
88
 
89
- await sleepAsync(50)
89
+ await flushUpdates()
90
90
  const button = root.querySelector('button[is="shade-button"]') as HTMLButtonElement
91
91
  expect(button.getAttribute('data-variant')).toBe('contained')
92
92
  })
@@ -1,7 +1,7 @@
1
1
  import { Cache } from '@furystack/cache'
2
2
  import type { CacheResult, CacheWithValue } from '@furystack/cache'
3
3
  import { Shade, createComponent, flushUpdates } from '@furystack/shades'
4
- import { sleepAsync } from '@furystack/utils'
4
+
5
5
  import { describe, expect, it, vi } from 'vitest'
6
6
  import { CacheView } from './cache-view.js'
7
7
 
@@ -162,7 +162,7 @@ describe('CacheView', () => {
162
162
 
163
163
  loadFn.mockResolvedValueOnce('recovered')
164
164
  capturedRetry!()
165
- await sleepAsync(50)
165
+ await flushUpdates()
166
166
 
167
167
  const observable = cache.getObservable('test')
168
168
  const result = observable.getValue()
@@ -183,7 +183,7 @@ describe('CacheView', () => {
183
183
  const contentEl = cacheView.querySelector('test-cache-content')
184
184
  expect(contentEl).not.toBeNull()
185
185
 
186
- await sleepAsync(50)
186
+ await flushUpdates()
187
187
  // reload should have been called (initial load + obsolete reload)
188
188
  expect(loadFn).toHaveBeenCalledTimes(2)
189
189
  cache[Symbol.dispose]()