@grantcodes/ui 2.15.7 → 2.16.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 (300) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/custom-elements.json +476 -346
  3. package/package.json +23 -23
  4. package/src/components/accordion/accordion-item.component.js +17 -19
  5. package/src/components/accordion/accordion-item.css +40 -44
  6. package/src/components/accordion/accordion.component.js +7 -7
  7. package/src/components/accordion/accordion.css +5 -5
  8. package/src/components/accordion/accordion.js +6 -6
  9. package/src/components/accordion/accordion.react.js +6 -6
  10. package/src/components/accordion/accordion.stories.js +10 -10
  11. package/src/components/accordion/accordion.test.js +100 -100
  12. package/src/components/accordion/index.js +6 -6
  13. package/src/components/app-bar/app-bar.component.js +86 -92
  14. package/src/components/app-bar/app-bar.css +187 -203
  15. package/src/components/app-bar/app-bar.js +3 -3
  16. package/src/components/app-bar/app-bar.react.js +9 -9
  17. package/src/components/app-bar/app-bar.stories.js +20 -20
  18. package/src/components/app-bar/app-bar.test.js +190 -237
  19. package/src/components/app-bar/index.js +1 -1
  20. package/src/components/app-bar/nav-link.component.js +7 -9
  21. package/src/components/app-bar/nav-link.css +23 -28
  22. package/src/components/app-bar/nav-link.js +3 -3
  23. package/src/components/app-bar/nav-link.react.js +6 -6
  24. package/src/components/avatar/avatar.component.js +79 -68
  25. package/src/components/avatar/avatar.css +18 -18
  26. package/src/components/avatar/avatar.js +3 -3
  27. package/src/components/avatar/avatar.react.js +6 -6
  28. package/src/components/avatar/avatar.stories.js +24 -23
  29. package/src/components/avatar/avatar.test.js +128 -84
  30. package/src/components/avatar/index.js +1 -1
  31. package/src/components/badge/badge.component.js +23 -23
  32. package/src/components/badge/badge.css +39 -52
  33. package/src/components/badge/badge.js +3 -3
  34. package/src/components/badge/badge.react.js +6 -6
  35. package/src/components/badge/badge.stories.js +23 -23
  36. package/src/components/badge/badge.test.js +53 -68
  37. package/src/components/badge/index.js +1 -1
  38. package/src/components/breadcrumb/breadcrumb.component.js +95 -96
  39. package/src/components/breadcrumb/breadcrumb.css +42 -44
  40. package/src/components/breadcrumb/breadcrumb.js +6 -9
  41. package/src/components/breadcrumb/breadcrumb.react.js +9 -12
  42. package/src/components/breadcrumb/breadcrumb.stories.js +5 -5
  43. package/src/components/breadcrumb/breadcrumb.test.js +139 -151
  44. package/src/components/breadcrumb/index.js +1 -1
  45. package/src/components/button/button.component.js +101 -103
  46. package/src/components/button/button.css +90 -94
  47. package/src/components/button/button.js +3 -3
  48. package/src/components/button/button.react.js +6 -6
  49. package/src/components/button/button.stories.js +25 -25
  50. package/src/components/button/button.test.js +324 -344
  51. package/src/components/button/index.js +1 -1
  52. package/src/components/button-group/button-group.component.js +18 -18
  53. package/src/components/button-group/button-group.css +16 -16
  54. package/src/components/button-group/button-group.js +3 -3
  55. package/src/components/button-group/button-group.react.js +6 -6
  56. package/src/components/button-group/button-group.stories.js +23 -23
  57. package/src/components/button-group/button-group.test.js +54 -54
  58. package/src/components/button-group/index.js +1 -1
  59. package/src/components/card/card.component.js +31 -33
  60. package/src/components/card/card.css +85 -85
  61. package/src/components/card/card.js +4 -4
  62. package/src/components/card/card.react.js +6 -6
  63. package/src/components/card/card.stories.js +27 -26
  64. package/src/components/card/card.test.js +56 -56
  65. package/src/components/card/index.js +1 -1
  66. package/src/components/code-preview/code-preview.component.js +47 -48
  67. package/src/components/code-preview/code-preview.css +11 -11
  68. package/src/components/code-preview/code-preview.js +3 -3
  69. package/src/components/code-preview/code-preview.react.js +6 -6
  70. package/src/components/code-preview/code-preview.stories.js +29 -29
  71. package/src/components/code-preview/code-preview.test.js +112 -135
  72. package/src/components/code-preview/index.js +1 -1
  73. package/src/components/container/container.component.js +27 -27
  74. package/src/components/container/container.css +22 -22
  75. package/src/components/container/container.js +3 -3
  76. package/src/components/container/container.react.js +6 -6
  77. package/src/components/container/container.stories.js +44 -44
  78. package/src/components/container/container.test.js +54 -66
  79. package/src/components/container/index.js +1 -1
  80. package/src/components/countdown/countdown.component.js +160 -162
  81. package/src/components/countdown/countdown.css +50 -34
  82. package/src/components/countdown/countdown.js +3 -3
  83. package/src/components/countdown/countdown.react.js +6 -6
  84. package/src/components/countdown/countdown.stories.js +34 -34
  85. package/src/components/countdown/index.js +1 -1
  86. package/src/components/cta/cta.component.js +77 -81
  87. package/src/components/cta/cta.css +24 -24
  88. package/src/components/cta/cta.js +3 -3
  89. package/src/components/cta/cta.react.js +6 -6
  90. package/src/components/cta/cta.stories.js +32 -32
  91. package/src/components/cta/index.js +1 -1
  92. package/src/components/dialog/dialog.component.js +95 -58
  93. package/src/components/dialog/dialog.css +45 -50
  94. package/src/components/dialog/dialog.js +3 -3
  95. package/src/components/dialog/dialog.react.js +6 -6
  96. package/src/components/dialog/dialog.stories.js +38 -29
  97. package/src/components/dialog/dialog.test.js +188 -102
  98. package/src/components/dialog/index.js +1 -1
  99. package/src/components/dropdown/dropdown.component.js +220 -201
  100. package/src/components/dropdown/dropdown.css +60 -84
  101. package/src/components/dropdown/dropdown.js +6 -9
  102. package/src/components/dropdown/dropdown.react.js +15 -15
  103. package/src/components/dropdown/dropdown.stories.js +10 -10
  104. package/src/components/dropdown/dropdown.test.js +211 -157
  105. package/src/components/dropdown/index.js +1 -1
  106. package/src/components/dropzone/dropzone.component.js +126 -129
  107. package/src/components/dropzone/dropzone.css +35 -37
  108. package/src/components/dropzone/dropzone.js +3 -3
  109. package/src/components/dropzone/dropzone.react.js +6 -6
  110. package/src/components/dropzone/dropzone.stories.js +28 -28
  111. package/src/components/dropzone/dropzone.test.js +91 -99
  112. package/src/components/dropzone/index.js +1 -1
  113. package/src/components/feature-list/feature-list.component.js +78 -86
  114. package/src/components/feature-list/feature-list.css +37 -37
  115. package/src/components/feature-list/feature-list.js +3 -3
  116. package/src/components/feature-list/feature-list.react.js +6 -6
  117. package/src/components/feature-list/feature-list.stories.js +86 -90
  118. package/src/components/feature-list/index.js +1 -1
  119. package/src/components/footer/footer-column.component.js +7 -7
  120. package/src/components/footer/footer-column.css +22 -22
  121. package/src/components/footer/footer.component.js +19 -19
  122. package/src/components/footer/footer.css +38 -38
  123. package/src/components/footer/footer.js +8 -8
  124. package/src/components/footer/footer.react.js +9 -9
  125. package/src/components/footer/footer.stories.js +9 -9
  126. package/src/components/footer/footer.test.js +101 -111
  127. package/src/components/footer/index.js +2 -2
  128. package/src/components/form-field/form-field.component.js +167 -125
  129. package/src/components/form-field/form-field.css +24 -24
  130. package/src/components/form-field/form-field.js +3 -3
  131. package/src/components/form-field/form-field.react.js +6 -6
  132. package/src/components/form-field/form-field.stories.js +53 -44
  133. package/src/components/form-field/form-field.test.js +280 -134
  134. package/src/components/form-field/index.js +1 -1
  135. package/src/components/gallery/gallery-image.component.js +30 -30
  136. package/src/components/gallery/gallery-image.js +3 -3
  137. package/src/components/gallery/gallery-image.react.js +6 -6
  138. package/src/components/gallery/gallery.component.js +24 -17
  139. package/src/components/gallery/gallery.css +79 -72
  140. package/src/components/gallery/gallery.js +3 -3
  141. package/src/components/gallery/gallery.react.js +6 -6
  142. package/src/components/gallery/gallery.stories.js +69 -68
  143. package/src/components/gallery/gallery.test.js +95 -88
  144. package/src/components/gallery/index.js +2 -2
  145. package/src/components/hero/hero.component.js +53 -57
  146. package/src/components/hero/hero.css +27 -27
  147. package/src/components/hero/hero.js +3 -3
  148. package/src/components/hero/hero.react.js +6 -6
  149. package/src/components/hero/hero.stories.js +39 -39
  150. package/src/components/hero/index.js +1 -1
  151. package/src/components/icon/icon.component.js +10 -10
  152. package/src/components/icon/icon.css +13 -13
  153. package/src/components/icon/icon.js +4 -4
  154. package/src/components/icon/icon.react.js +6 -6
  155. package/src/components/icon/icon.stories.js +8 -9
  156. package/src/components/icon/icon.test.js +54 -55
  157. package/src/components/icon/index.js +1 -1
  158. package/src/components/loading/index.js +1 -1
  159. package/src/components/loading/loading.component.js +41 -14
  160. package/src/components/loading/loading.css +47 -30
  161. package/src/components/loading/loading.js +4 -4
  162. package/src/components/loading/loading.react.js +6 -6
  163. package/src/components/loading/loading.stories.js +19 -18
  164. package/src/components/loading/loading.test.js +77 -54
  165. package/src/components/logo-cloud/index.js +1 -1
  166. package/src/components/logo-cloud/logo-cloud.component.js +39 -43
  167. package/src/components/logo-cloud/logo-cloud.css +31 -31
  168. package/src/components/logo-cloud/logo-cloud.js +3 -3
  169. package/src/components/logo-cloud/logo-cloud.react.js +6 -6
  170. package/src/components/logo-cloud/logo-cloud.stories.js +80 -80
  171. package/src/components/map/index.js +1 -1
  172. package/src/components/map/map.component.js +103 -107
  173. package/src/components/map/map.css +22 -22
  174. package/src/components/map/map.js +3 -3
  175. package/src/components/map/map.react.js +6 -6
  176. package/src/components/map/map.stories.js +38 -38
  177. package/src/components/media-text/index.js +1 -1
  178. package/src/components/media-text/media-text.component.js +76 -70
  179. package/src/components/media-text/media-text.css +32 -32
  180. package/src/components/media-text/media-text.js +3 -3
  181. package/src/components/media-text/media-text.react.js +6 -6
  182. package/src/components/media-text/media-text.stories.js +45 -45
  183. package/src/components/media-text/media-text.test.js +72 -0
  184. package/src/components/newsletter/index.js +1 -1
  185. package/src/components/newsletter/newsletter.component.js +56 -64
  186. package/src/components/newsletter/newsletter.css +48 -48
  187. package/src/components/newsletter/newsletter.js +3 -3
  188. package/src/components/newsletter/newsletter.react.js +6 -6
  189. package/src/components/newsletter/newsletter.stories.js +35 -35
  190. package/src/components/notice/index.js +1 -1
  191. package/src/components/notice/notice.component.js +66 -55
  192. package/src/components/notice/notice.css +37 -38
  193. package/src/components/notice/notice.js +3 -3
  194. package/src/components/notice/notice.react.js +6 -6
  195. package/src/components/notice/notice.stories.js +54 -53
  196. package/src/components/notice/notice.test.js +210 -156
  197. package/src/components/pagination/index.js +1 -1
  198. package/src/components/pagination/pagination.component.js +44 -44
  199. package/src/components/pagination/pagination.css +6 -6
  200. package/src/components/pagination/pagination.js +4 -4
  201. package/src/components/pagination/pagination.react.js +6 -6
  202. package/src/components/pagination/pagination.stories.js +20 -18
  203. package/src/components/pagination/pagination.test.js +95 -102
  204. package/src/components/person/index.js +1 -1
  205. package/src/components/person/person.component.js +29 -29
  206. package/src/components/person/person.css +17 -17
  207. package/src/components/person/person.js +4 -4
  208. package/src/components/person/person.react.js +6 -6
  209. package/src/components/person/person.stories.js +34 -33
  210. package/src/components/person/person.test.js +55 -68
  211. package/src/components/pricing/index.js +1 -1
  212. package/src/components/pricing/pricing.component.js +58 -70
  213. package/src/components/pricing/pricing.css +65 -65
  214. package/src/components/pricing/pricing.js +3 -3
  215. package/src/components/pricing/pricing.react.js +6 -6
  216. package/src/components/pricing/pricing.stories.js +96 -96
  217. package/src/components/sidebar/index.js +1 -1
  218. package/src/components/sidebar/sidebar.component.js +157 -130
  219. package/src/components/sidebar/sidebar.css +118 -115
  220. package/src/components/sidebar/sidebar.js +4 -4
  221. package/src/components/sidebar/sidebar.react.js +10 -10
  222. package/src/components/sidebar/sidebar.stories.js +10 -10
  223. package/src/components/sidebar/sidebar.test.js +250 -230
  224. package/src/components/stats/index.js +1 -1
  225. package/src/components/stats/stats.component.js +42 -50
  226. package/src/components/stats/stats.css +29 -29
  227. package/src/components/stats/stats.js +3 -3
  228. package/src/components/stats/stats.react.js +6 -6
  229. package/src/components/stats/stats.stories.js +40 -40
  230. package/src/components/tabs/index.js +2 -2
  231. package/src/components/tabs/internal/tabs-button.component.js +16 -27
  232. package/src/components/tabs/internal/tabs-button.js +3 -3
  233. package/src/components/tabs/internal/tabs-button.react.js +6 -6
  234. package/src/components/tabs/internal/tabs-item.component.js +30 -30
  235. package/src/components/tabs/tab.component.js +9 -11
  236. package/src/components/tabs/tab.js +3 -3
  237. package/src/components/tabs/tab.react.js +6 -6
  238. package/src/components/tabs/tabs.component.js +107 -109
  239. package/src/components/tabs/tabs.css +50 -59
  240. package/src/components/tabs/tabs.js +4 -4
  241. package/src/components/tabs/tabs.react.js +6 -6
  242. package/src/components/tabs/tabs.stories.js +23 -22
  243. package/src/components/tabs/tabs.test.js +201 -147
  244. package/src/components/testimonials/index.js +1 -1
  245. package/src/components/testimonials/testimonials.component.js +47 -51
  246. package/src/components/testimonials/testimonials.css +31 -31
  247. package/src/components/testimonials/testimonials.js +3 -3
  248. package/src/components/testimonials/testimonials.react.js +6 -6
  249. package/src/components/testimonials/testimonials.stories.js +49 -51
  250. package/src/components/toast/index.js +1 -1
  251. package/src/components/toast/toast.component.js +217 -148
  252. package/src/components/toast/toast.css +101 -99
  253. package/src/components/toast/toast.js +6 -9
  254. package/src/components/toast/toast.react.js +12 -12
  255. package/src/components/toast/toast.stories.js +75 -49
  256. package/src/components/toast/toast.test.js +260 -221
  257. package/src/components/tooltip/index.js +1 -1
  258. package/src/components/tooltip/tooltip.component.js +56 -49
  259. package/src/components/tooltip/tooltip.css +61 -50
  260. package/src/components/tooltip/tooltip.js +4 -4
  261. package/src/components/tooltip/tooltip.react.js +6 -6
  262. package/src/components/tooltip/tooltip.stories.js +24 -23
  263. package/src/components/tooltip/tooltip.test.js +143 -155
  264. package/src/constructor.test.js +31 -0
  265. package/src/css/base.css +1 -0
  266. package/src/css/colors.stories.js +120 -122
  267. package/src/css/elements/a.css +28 -28
  268. package/src/css/elements/forms/button.css +1 -1
  269. package/src/css/elements/forms/input.css +80 -80
  270. package/src/css/elements/forms/label.css +3 -3
  271. package/src/css/elements/media/image.css +2 -2
  272. package/src/css/elements.stories.js +48 -49
  273. package/src/css/helpers.css +8 -8
  274. package/src/css/layers.stories.js +5 -5
  275. package/src/css/reset.css +102 -102
  276. package/src/css/themes/todomap.css +1 -1
  277. package/src/css/tokens.stories.js +50 -53
  278. package/src/css/typography.css +30 -32
  279. package/src/css/typography.stories.js +92 -92
  280. package/src/css/util/focus-ring.css +12 -20
  281. package/src/css/view-transitions.css +16 -0
  282. package/src/exports.test.js +89 -105
  283. package/src/icons.js +1 -1
  284. package/src/lib/generate-id.js +1 -1
  285. package/src/lib/slot-presence-controller.js +48 -0
  286. package/src/lib/styles/all.css +38 -37
  287. package/src/lib/styles/focus-ring.css +12 -20
  288. package/src/lib/view-transition.js +42 -0
  289. package/src/lib/view-transition.test.js +105 -0
  290. package/src/main.js +29 -29
  291. package/src/pages/agency.stories.js +59 -59
  292. package/src/pages/blog-post.stories.js +48 -48
  293. package/src/pages/saas-landing.stories.js +180 -180
  294. package/src/react.js +44 -44
  295. package/src/react.test.js +42 -51
  296. package/src/test-utils/assert-helpers.js +39 -58
  297. package/src/test-utils/events.js +32 -34
  298. package/src/test-utils/fixture.js +31 -31
  299. package/src/test-utils/index.js +3 -3
  300. package/src/types.d.ts +3 -3
@@ -1,125 +1,109 @@
1
- import { describe, it } from "node:test";
2
- import assert from "node:assert";
3
- import fs from "node:fs";
4
- import path from "node:path";
5
- import { fileURLToPath } from "node:url";
1
+ import assert from 'node:assert';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { describe, it } from 'node:test';
5
+ import { fileURLToPath } from 'node:url';
6
6
 
7
7
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
- const pkgPath = path.resolve(__dirname, "..", "package.json");
8
+ const pkgPath = path.resolve(__dirname, '..', 'package.json');
9
9
  const pkgRoot = path.dirname(pkgPath);
10
- const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
10
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
11
11
  const exports = pkg.exports;
12
12
 
13
13
  // All 34 component CSS files expected to exist on disk
14
14
  // These are resolved via the ./components/* wildcard export
15
15
  const expectedComponentCss = [
16
- "accordion/accordion.css",
17
- "app-bar/app-bar.css",
18
- "avatar/avatar.css",
19
- "badge/badge.css",
20
- "breadcrumb/breadcrumb.css",
21
- "button/button.css",
22
- "button-group/button-group.css",
23
- "card/card.css",
24
- "code-preview/code-preview.css",
25
- "container/container.css",
26
- "cta/cta.css",
27
- "dialog/dialog.css",
28
- "dropdown/dropdown.css",
29
- "dropzone/dropzone.css",
30
- "feature-list/feature-list.css",
31
- "footer/footer.css",
32
- "footer/footer-column.css",
33
- "form-field/form-field.css",
34
- "gallery/gallery.css",
35
- "hero/hero.css",
36
- "icon/icon.css",
37
- "loading/loading.css",
38
- "logo-cloud/logo-cloud.css",
39
- "media-text/media-text.css",
40
- "newsletter/newsletter.css",
41
- "notice/notice.css",
42
- "pagination/pagination.css",
43
- "pricing/pricing.css",
44
- "sidebar/sidebar.css",
45
- "stats/stats.css",
46
- "tabs/tabs.css",
47
- "testimonials/testimonials.css",
48
- "toast/toast.css",
49
- "tooltip/tooltip.css",
16
+ 'accordion/accordion.css',
17
+ 'app-bar/app-bar.css',
18
+ 'avatar/avatar.css',
19
+ 'badge/badge.css',
20
+ 'breadcrumb/breadcrumb.css',
21
+ 'button/button.css',
22
+ 'button-group/button-group.css',
23
+ 'card/card.css',
24
+ 'code-preview/code-preview.css',
25
+ 'container/container.css',
26
+ 'cta/cta.css',
27
+ 'dialog/dialog.css',
28
+ 'dropdown/dropdown.css',
29
+ 'dropzone/dropzone.css',
30
+ 'feature-list/feature-list.css',
31
+ 'footer/footer.css',
32
+ 'footer/footer-column.css',
33
+ 'form-field/form-field.css',
34
+ 'gallery/gallery.css',
35
+ 'hero/hero.css',
36
+ 'icon/icon.css',
37
+ 'loading/loading.css',
38
+ 'logo-cloud/logo-cloud.css',
39
+ 'media-text/media-text.css',
40
+ 'newsletter/newsletter.css',
41
+ 'notice/notice.css',
42
+ 'pagination/pagination.css',
43
+ 'pricing/pricing.css',
44
+ 'sidebar/sidebar.css',
45
+ 'stats/stats.css',
46
+ 'tabs/tabs.css',
47
+ 'testimonials/testimonials.css',
48
+ 'toast/toast.css',
49
+ 'tooltip/tooltip.css',
50
50
  ];
51
51
 
52
- describe("package.json exports", () => {
53
- describe("component CSS files exist (resolved via ./components/* wildcard)", () => {
54
- for (const cssFile of expectedComponentCss) {
55
- it(`src/components/${cssFile} exists on disk`, () => {
56
- const fullPath = path.resolve(pkgRoot, "src", "components", cssFile);
57
- assert.ok(
58
- fs.existsSync(fullPath),
59
- `CSS file does not exist: ${fullPath}`,
60
- );
61
- });
62
- }
52
+ describe('package.json exports', () => {
53
+ describe('component CSS files exist (resolved via ./components/* wildcard)', () => {
54
+ for (const cssFile of expectedComponentCss) {
55
+ it(`src/components/${cssFile} exists on disk`, () => {
56
+ const fullPath = path.resolve(pkgRoot, 'src', 'components', cssFile);
57
+ assert.ok(fs.existsSync(fullPath), `CSS file does not exist: ${fullPath}`);
58
+ });
59
+ }
63
60
 
64
- it("has ./components/* wildcard export that covers CSS files", () => {
65
- assert.ok(
66
- exports["./components/*"],
67
- "Missing ./components/* wildcard export",
68
- );
69
- });
70
- });
61
+ it('has ./components/* wildcard export that covers CSS files', () => {
62
+ assert.ok(exports['./components/*'], 'Missing ./components/* wildcard export');
63
+ });
64
+ });
71
65
 
72
- describe("focus-ring shared styles export", () => {
73
- it("has export for ./styles/focus-ring.css", () => {
74
- assert.ok(
75
- exports["./styles/focus-ring.css"] !== undefined,
76
- "Missing export for ./styles/focus-ring.css",
77
- );
78
- });
66
+ describe('focus-ring shared styles export', () => {
67
+ it('has export for ./styles/focus-ring.css', () => {
68
+ assert.ok(
69
+ exports['./styles/focus-ring.css'] !== undefined,
70
+ 'Missing export for ./styles/focus-ring.css',
71
+ );
72
+ });
79
73
 
80
- it("./styles/focus-ring.css points to an existing file", () => {
81
- const exportValue = exports["./styles/focus-ring.css"];
82
- const filePath =
83
- typeof exportValue === "string" ? exportValue : exportValue?.import;
84
- assert.ok(filePath, "No file path found for ./styles/focus-ring.css");
85
- const fullPath = path.resolve(pkgRoot, filePath);
86
- assert.ok(fs.existsSync(fullPath), `File does not exist: ${fullPath}`);
87
- });
88
- });
74
+ it('./styles/focus-ring.css points to an existing file', () => {
75
+ const exportValue = exports['./styles/focus-ring.css'];
76
+ const filePath = typeof exportValue === 'string' ? exportValue : exportValue?.import;
77
+ assert.ok(filePath, 'No file path found for ./styles/focus-ring.css');
78
+ const fullPath = path.resolve(pkgRoot, filePath);
79
+ assert.ok(fs.existsSync(fullPath), `File does not exist: ${fullPath}`);
80
+ });
81
+ });
89
82
 
90
- describe("existing exports preserved", () => {
91
- it("has root export (.)", () => {
92
- assert.ok(exports["."], "Missing root export");
93
- assert.ok(exports["."].import, "Missing root import");
94
- });
83
+ describe('existing exports preserved', () => {
84
+ it('has root export (.)', () => {
85
+ assert.ok(exports['.'], 'Missing root export');
86
+ assert.ok(exports['.'].import, 'Missing root import');
87
+ });
95
88
 
96
- it("has ./icons export", () => {
97
- assert.ok(exports["./icons"], "Missing ./icons export");
98
- });
89
+ it('has ./icons export', () => {
90
+ assert.ok(exports['./icons'], 'Missing ./icons export');
91
+ });
99
92
 
100
- it("has ./styles/base.css export", () => {
101
- assert.ok(
102
- exports["./styles/base.css"],
103
- "Missing ./styles/base.css export",
104
- );
105
- });
93
+ it('has ./styles/base.css export', () => {
94
+ assert.ok(exports['./styles/base.css'], 'Missing ./styles/base.css export');
95
+ });
106
96
 
107
- it("has ./styles/themes/* export", () => {
108
- assert.ok(
109
- exports["./styles/themes/*"],
110
- "Missing ./styles/themes/* export",
111
- );
112
- });
97
+ it('has ./styles/themes/* export', () => {
98
+ assert.ok(exports['./styles/themes/*'], 'Missing ./styles/themes/* export');
99
+ });
113
100
 
114
- it("has ./components/* wildcard export", () => {
115
- assert.ok(
116
- exports["./components/*"],
117
- "Missing ./components/* wildcard export",
118
- );
119
- });
101
+ it('has ./components/* wildcard export', () => {
102
+ assert.ok(exports['./components/*'], 'Missing ./components/* wildcard export');
103
+ });
120
104
 
121
- it("has ./fonts/* export", () => {
122
- assert.ok(exports["./fonts/*"], "Missing ./fonts/* export");
123
- });
124
- });
105
+ it('has ./fonts/* export', () => {
106
+ assert.ok(exports['./fonts/*'], 'Missing ./fonts/* export');
107
+ });
108
+ });
125
109
  });
package/src/icons.js CHANGED
@@ -1,3 +1,3 @@
1
1
  // Map icons to Lucide icons
2
2
 
3
- export * from "lucide-static";
3
+ export * from 'lucide-static';
@@ -4,7 +4,7 @@
4
4
  * @returns {string} Generated unique ID
5
5
  */
6
6
  function generateId(prefix) {
7
- return `${prefix || "id"}-${Math.random().toString(36).substr(2, 9)}`;
7
+ return `${prefix || 'id'}-${Math.random().toString(36).substr(2, 9)}`;
8
8
  }
9
9
 
10
10
  export { generateId };
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Tracks whether a slot has slotted content.
3
+ *
4
+ * CSS cannot do this: `:has(slot:empty)` always matches because the `<slot>`
5
+ * element itself is always empty in the shadow tree. `:host(:has([slot=x]))`
6
+ * does not help either — a `:has()` inside a shadow root cannot match light-DOM
7
+ * children (checked in Chromium 153), so the check has to happen in JS.
8
+ */
9
+ export class SlotPresenceController {
10
+ /**
11
+ * @param {import('lit').ReactiveControllerHost} host
12
+ * @param {string} slotName - Slot to watch; `''` for the default slot.
13
+ * @param {(present: boolean) => void} onChange
14
+ */
15
+ constructor(host, slotName, onChange) {
16
+ this.host = host;
17
+ this.slotName = slotName;
18
+ this.onChange = onChange;
19
+ /** @type {boolean | undefined} */
20
+ this.present = undefined;
21
+ host.addController(this);
22
+ }
23
+
24
+ hostUpdate() {
25
+ this.refresh();
26
+ }
27
+
28
+ /** Re-checks the light DOM and notifies on the first check and on changes. */
29
+ refresh() {
30
+ const present = this._detect();
31
+ if (present === this.present) return;
32
+ this.present = present;
33
+ this.onChange(present);
34
+ }
35
+
36
+ _nodes() {
37
+ if (this.slotName) {
38
+ return Array.from(this.host.querySelectorAll(`[slot="${this.slotName}"]`));
39
+ }
40
+ return Array.from(this.host.childNodes).filter((node) => !node.getAttribute?.('slot'));
41
+ }
42
+
43
+ _detect() {
44
+ return this._nodes().some(
45
+ (node) => node.nodeType === 1 || (node.textContent ?? '').trim() !== '',
46
+ );
47
+ }
48
+ }
@@ -1,39 +1,40 @@
1
1
  @layer components {
2
- @import "./focus-ring.css";
3
- @import "../../components/accordion/accordion.css";
4
- @import "../../components/app-bar/app-bar.css";
5
- @import "../../components/avatar/avatar.css";
6
- @import "../../components/badge/badge.css";
7
- @import "../../components/breadcrumb/breadcrumb.css";
8
- @import "../../components/button/button.css";
9
- @import "../../components/button-group/button-group.css";
10
- @import "../../components/card/card.css";
11
- @import "../../components/code-preview/code-preview.css";
12
- @import "../../components/container/container.css";
13
- @import "../../components/countdown/countdown.css";
14
- @import "../../components/cta/cta.css";
15
- @import "../../components/dialog/dialog.css";
16
- @import "../../components/dropdown/dropdown.css";
17
- @import "../../components/dropzone/dropzone.css";
18
- @import "../../components/feature-list/feature-list.css";
19
- @import "../../components/footer/footer.css";
20
- @import "../../components/footer/footer-column.css";
21
- @import "../../components/form-field/form-field.css";
22
- @import "../../components/gallery/gallery.css";
23
- @import "../../components/hero/hero.css";
24
- @import "../../components/icon/icon.css";
25
- @import "../../components/loading/loading.css";
26
- @import "../../components/logo-cloud/logo-cloud.css";
27
- @import "../../components/map/map.css";
28
- @import "../../components/media-text/media-text.css";
29
- @import "../../components/newsletter/newsletter.css";
30
- @import "../../components/notice/notice.css";
31
- @import "../../components/pagination/pagination.css";
32
- @import "../../components/pricing/pricing.css";
33
- @import "../../components/sidebar/sidebar.css";
34
- @import "../../components/stats/stats.css";
35
- @import "../../components/tabs/tabs.css";
36
- @import "../../components/testimonials/testimonials.css";
37
- @import "../../components/toast/toast.css";
38
- @import "../../components/tooltip/tooltip.css";
2
+ @import "./focus-ring.css";
3
+ @import "../../css/view-transitions.css";
4
+ @import "../../components/accordion/accordion.css";
5
+ @import "../../components/app-bar/app-bar.css";
6
+ @import "../../components/avatar/avatar.css";
7
+ @import "../../components/badge/badge.css";
8
+ @import "../../components/breadcrumb/breadcrumb.css";
9
+ @import "../../components/button/button.css";
10
+ @import "../../components/button-group/button-group.css";
11
+ @import "../../components/card/card.css";
12
+ @import "../../components/code-preview/code-preview.css";
13
+ @import "../../components/container/container.css";
14
+ @import "../../components/countdown/countdown.css";
15
+ @import "../../components/cta/cta.css";
16
+ @import "../../components/dialog/dialog.css";
17
+ @import "../../components/dropdown/dropdown.css";
18
+ @import "../../components/dropzone/dropzone.css";
19
+ @import "../../components/feature-list/feature-list.css";
20
+ @import "../../components/footer/footer.css";
21
+ @import "../../components/footer/footer-column.css";
22
+ @import "../../components/form-field/form-field.css";
23
+ @import "../../components/gallery/gallery.css";
24
+ @import "../../components/hero/hero.css";
25
+ @import "../../components/icon/icon.css";
26
+ @import "../../components/loading/loading.css";
27
+ @import "../../components/logo-cloud/logo-cloud.css";
28
+ @import "../../components/map/map.css";
29
+ @import "../../components/media-text/media-text.css";
30
+ @import "../../components/newsletter/newsletter.css";
31
+ @import "../../components/notice/notice.css";
32
+ @import "../../components/pagination/pagination.css";
33
+ @import "../../components/pricing/pricing.css";
34
+ @import "../../components/sidebar/sidebar.css";
35
+ @import "../../components/stats/stats.css";
36
+ @import "../../components/tabs/tabs.css";
37
+ @import "../../components/testimonials/testimonials.css";
38
+ @import "../../components/toast/toast.css";
39
+ @import "../../components/tooltip/tooltip.css";
39
40
  }
@@ -1,30 +1,22 @@
1
1
  .focus-ring,
2
2
  :host(.focus-ring) {
3
- outline: 0px solid transparent;
4
- outline-offset: var(--g-focus-ring-offset-default);
5
- transition-duration: var(--g-animation-move-quick);
6
- transition-property: outline-color, width;
3
+ outline: 0px solid transparent;
4
+ outline-offset: var(--g-focus-ring-offset-default);
5
+ transition-duration: var(--g-animation-move-quick);
6
+ transition-property: outline-color, width;
7
7
  }
8
8
 
9
9
  .focus-ring:focus-visible,
10
10
  :host(.focus-ring):focus-visible {
11
- outline: var(--g-focus-ring-width-default) solid
12
- var(--g-focus-ring-color-default);
11
+ outline: var(--g-focus-ring-width-default) solid var(--g-focus-ring-color-default);
13
12
  }
14
13
 
15
14
  @media (prefers-contrast: more) {
16
- .focus-ring:focus-visible,
17
- :host(.focus-ring):focus-visible {
18
- outline: var(--g-focus-ring-width-default) solid
19
- var(--g-focus-ring-color-contrast);
20
- box-shadow: 0 0 0
21
- calc(
22
- (
23
- var(--g-focus-ring-width-default) +
24
- var(--g-focus-ring-offset-default)
25
- ) *
26
- 1.5
27
- )
28
- var(--g-focus-ring-color-contrast-shadow);
29
- }
15
+ .focus-ring:focus-visible,
16
+ :host(.focus-ring):focus-visible {
17
+ outline: var(--g-focus-ring-width-default) solid var(--g-focus-ring-color-contrast);
18
+ box-shadow: 0 0 0
19
+ calc((var(--g-focus-ring-width-default) + var(--g-focus-ring-offset-default)) * 1.5)
20
+ var(--g-focus-ring-color-contrast-shadow);
21
+ }
30
22
  }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * True when the user has asked for reduced motion.
3
+ *
4
+ * @returns {boolean}
5
+ */
6
+ export function prefersReducedMotion() {
7
+ return (
8
+ typeof window !== 'undefined' &&
9
+ Boolean(window.matchMedia?.('(prefers-reduced-motion: reduce)').matches)
10
+ );
11
+ }
12
+
13
+ /**
14
+ * True when `startViewTransition` would actually run a transition, so callers can
15
+ * keep their previous animation as the fallback path.
16
+ *
17
+ * @returns {boolean}
18
+ */
19
+ export function canViewTransition() {
20
+ return (
21
+ typeof document !== 'undefined' &&
22
+ typeof document.startViewTransition === 'function' &&
23
+ !prefersReducedMotion()
24
+ );
25
+ }
26
+
27
+ /**
28
+ * Runs `update` inside a view transition when the platform supports one and the
29
+ * user has not asked for reduced motion. Returns the transition, or `null` when
30
+ * `update` ran synchronously.
31
+ *
32
+ * @param {() => void | Promise<unknown>} update
33
+ * @returns {ViewTransition | null}
34
+ */
35
+ export function startViewTransition(update) {
36
+ if (!canViewTransition()) {
37
+ update();
38
+ return null;
39
+ }
40
+
41
+ return document.startViewTransition(update);
42
+ }
@@ -0,0 +1,105 @@
1
+ import { strict as assert } from 'node:assert';
2
+ import { afterEach, describe, it } from 'node:test';
3
+ // Side-effect import: sets up the happy-dom window and document globals.
4
+ import '../test-utils/index.js';
5
+ import { startViewTransition, canViewTransition } from './view-transition.js';
6
+
7
+ describe('startViewTransition', () => {
8
+ const originalMatchMedia = globalThis.window?.matchMedia;
9
+ const originalStartViewTransition = globalThis.document?.startViewTransition;
10
+
11
+ const stubMotion = (reduce) => {
12
+ globalThis.window.matchMedia = () => ({ matches: reduce });
13
+ };
14
+
15
+ afterEach(() => {
16
+ globalThis.window.matchMedia = originalMatchMedia;
17
+ globalThis.document.startViewTransition = originalStartViewTransition;
18
+ });
19
+
20
+ it('runs the update inside a transition when motion is allowed', () => {
21
+ stubMotion(false);
22
+ const transition = { finished: Promise.resolve() };
23
+ let transitions = 0;
24
+ let updates = 0;
25
+ globalThis.document.startViewTransition = (callback) => {
26
+ transitions++;
27
+ callback();
28
+ return transition;
29
+ };
30
+
31
+ const result = startViewTransition(() => {
32
+ updates++;
33
+ });
34
+
35
+ assert.strictEqual(transitions, 1, 'Expected one view transition');
36
+ assert.strictEqual(updates, 1, 'Expected the update to run once');
37
+ assert.strictEqual(result, transition, 'Expected the transition to be returned');
38
+ });
39
+
40
+ it('runs the update directly when reduced motion is preferred', () => {
41
+ stubMotion(true);
42
+ let transitions = 0;
43
+ let updates = 0;
44
+ globalThis.document.startViewTransition = () => {
45
+ transitions++;
46
+ return { finished: Promise.resolve() };
47
+ };
48
+
49
+ const result = startViewTransition(() => {
50
+ updates++;
51
+ });
52
+
53
+ assert.strictEqual(transitions, 0, 'Reduced motion must skip the transition');
54
+ assert.strictEqual(updates, 1, 'Expected the update to run once');
55
+ assert.strictEqual(result, null);
56
+ });
57
+
58
+ it('runs the update directly when the platform has no view transitions', () => {
59
+ stubMotion(false);
60
+ globalThis.document.startViewTransition = undefined;
61
+ let updates = 0;
62
+
63
+ const result = startViewTransition(() => {
64
+ updates++;
65
+ });
66
+
67
+ assert.strictEqual(updates, 1, 'Expected the update to run once');
68
+ assert.strictEqual(result, null);
69
+ });
70
+ });
71
+
72
+ describe('canViewTransition', () => {
73
+ const originalMatchMedia = globalThis.window?.matchMedia;
74
+ const originalStartViewTransition = globalThis.document?.startViewTransition;
75
+
76
+ const stubMotion = (reduce) => {
77
+ globalThis.window.matchMedia = () => ({ matches: reduce });
78
+ };
79
+
80
+ afterEach(() => {
81
+ globalThis.window.matchMedia = originalMatchMedia;
82
+ globalThis.document.startViewTransition = originalStartViewTransition;
83
+ });
84
+
85
+ it('reports support when the API is present and motion is allowed', () => {
86
+ stubMotion(false);
87
+ globalThis.document.startViewTransition = () => ({ finished: Promise.resolve() });
88
+
89
+ assert.strictEqual(canViewTransition(), true);
90
+ });
91
+
92
+ it('reports no support under reduced motion', () => {
93
+ stubMotion(true);
94
+ globalThis.document.startViewTransition = () => ({ finished: Promise.resolve() });
95
+
96
+ assert.strictEqual(canViewTransition(), false);
97
+ });
98
+
99
+ it('reports no support when the API is missing', () => {
100
+ stubMotion(false);
101
+ globalThis.document.startViewTransition = undefined;
102
+
103
+ assert.strictEqual(canViewTransition(), false);
104
+ });
105
+ });
package/src/main.js CHANGED
@@ -1,29 +1,29 @@
1
- export * from "./components/accordion/index.js";
2
- export * from "./components/avatar/index.js";
3
- export * from "./components/button/index.js";
4
- export * from "./components/button-group/index.js";
5
- export * from "./components/card/index.js";
6
- export * from "./components/code-preview/index.js";
7
- export * from "./components/container/index.js";
8
- export * from "./components/countdown/index.js";
9
- export * from "./components/cta/index.js";
10
- export * from "./components/dialog/index.js";
11
- export * from "./components/dropzone/index.js";
12
- export * from "./components/feature-list/index.js";
13
- export * from "./components/form-field/index.js";
14
- export * from "./components/gallery/index.js";
15
- export * from "./components/hero/index.js";
16
- export * from "./components/icon/index.js";
17
- export * from "./components/loading/index.js";
18
- export * from "./components/logo-cloud/index.js";
19
- export * from "./components/map/index.js";
20
- export * from "./components/media-text/index.js";
21
- export * from "./components/newsletter/index.js";
22
- export * from "./components/notice/index.js";
23
- export * from "./components/pagination/index.js";
24
- export * from "./components/person/index.js";
25
- export * from "./components/pricing/index.js";
26
- export * from "./components/stats/index.js";
27
- export * from "./components/tabs/index.js";
28
- export * from "./components/testimonials/index.js";
29
- export * from "./components/tooltip/index.js";
1
+ export * from './components/accordion/index.js';
2
+ export * from './components/avatar/index.js';
3
+ export * from './components/button/index.js';
4
+ export * from './components/button-group/index.js';
5
+ export * from './components/card/index.js';
6
+ export * from './components/code-preview/index.js';
7
+ export * from './components/container/index.js';
8
+ export * from './components/countdown/index.js';
9
+ export * from './components/cta/index.js';
10
+ export * from './components/dialog/index.js';
11
+ export * from './components/dropzone/index.js';
12
+ export * from './components/feature-list/index.js';
13
+ export * from './components/form-field/index.js';
14
+ export * from './components/gallery/index.js';
15
+ export * from './components/hero/index.js';
16
+ export * from './components/icon/index.js';
17
+ export * from './components/loading/index.js';
18
+ export * from './components/logo-cloud/index.js';
19
+ export * from './components/map/index.js';
20
+ export * from './components/media-text/index.js';
21
+ export * from './components/newsletter/index.js';
22
+ export * from './components/notice/index.js';
23
+ export * from './components/pagination/index.js';
24
+ export * from './components/person/index.js';
25
+ export * from './components/pricing/index.js';
26
+ export * from './components/stats/index.js';
27
+ export * from './components/tabs/index.js';
28
+ export * from './components/testimonials/index.js';
29
+ export * from './components/tooltip/index.js';