@sekiui/elements 0.0.55 → 0.0.57

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 (298) hide show
  1. package/dist/cdn/index.js +1053 -91
  2. package/dist/cdn/p-BJCq8m2o.js +138 -0
  3. package/dist/cdn/p-BfRJQMIU.js +111 -0
  4. package/dist/cdn/{p-bMBhrs0a.js → p-Bp7tjKwQ.js} +427 -7
  5. package/dist/cdn/seki-button.js +1 -1
  6. package/dist/cdn/seki-card-action.d.ts +11 -0
  7. package/dist/cdn/seki-card-action.js +38 -0
  8. package/dist/cdn/seki-card-content.d.ts +11 -0
  9. package/dist/cdn/seki-card-content.js +38 -0
  10. package/dist/cdn/seki-card-description.d.ts +11 -0
  11. package/dist/cdn/seki-card-description.js +38 -0
  12. package/dist/cdn/seki-card-footer.d.ts +11 -0
  13. package/dist/cdn/seki-card-footer.js +44 -0
  14. package/dist/cdn/seki-card-header.d.ts +11 -0
  15. package/dist/cdn/seki-card-header.js +38 -0
  16. package/dist/cdn/seki-card-title.d.ts +11 -0
  17. package/dist/cdn/seki-card-title.js +59 -0
  18. package/dist/cdn/seki-card.d.ts +11 -0
  19. package/dist/cdn/seki-card.js +39 -0
  20. package/dist/cdn/seki-field-description.js +2 -2
  21. package/dist/cdn/seki-field-error.js +2 -2
  22. package/dist/cdn/seki-field-group.js +2 -2
  23. package/dist/cdn/seki-field-label.js +2 -2
  24. package/dist/cdn/seki-field-legend.js +2 -2
  25. package/dist/cdn/seki-field.js +2 -2
  26. package/dist/cdn/seki-fieldset.js +2 -2
  27. package/dist/cdn/seki-input.js +2 -2
  28. package/dist/cdn/seki-select-content.js +1 -1
  29. package/dist/cdn/seki-select-group.js +2 -2
  30. package/dist/cdn/seki-select-option.js +2 -2
  31. package/dist/cdn/seki-select-trigger.js +1 -1
  32. package/dist/cdn/seki-select.js +2 -2
  33. package/dist/cdn/seki-sidebar-content.d.ts +11 -0
  34. package/dist/cdn/seki-sidebar-content.js +38 -0
  35. package/dist/cdn/seki-sidebar-footer.d.ts +11 -0
  36. package/dist/cdn/seki-sidebar-footer.js +38 -0
  37. package/dist/cdn/seki-sidebar-group.d.ts +11 -0
  38. package/dist/cdn/seki-sidebar-group.js +131 -0
  39. package/dist/cdn/seki-sidebar-header.d.ts +11 -0
  40. package/dist/cdn/seki-sidebar-header.js +38 -0
  41. package/dist/cdn/seki-sidebar-menu-item.d.ts +11 -0
  42. package/dist/cdn/seki-sidebar-menu-item.js +200 -0
  43. package/dist/cdn/seki-sidebar-menu-sub.d.ts +11 -0
  44. package/dist/cdn/seki-sidebar-menu-sub.js +123 -0
  45. package/dist/cdn/seki-sidebar-menu.d.ts +11 -0
  46. package/dist/cdn/seki-sidebar-menu.js +38 -0
  47. package/dist/cdn/seki-sidebar-trigger.d.ts +11 -0
  48. package/dist/cdn/seki-sidebar-trigger.js +109 -0
  49. package/dist/cdn/seki-sidebar.d.ts +11 -0
  50. package/dist/cdn/seki-sidebar.js +380 -0
  51. package/dist/cdn/seki-skeleton.js +2 -2
  52. package/dist/cdn/seki-switch.js +1 -1
  53. package/dist/cdn/seki-tooltip.js +1 -1
  54. package/dist/cjs/{index-Dd6_-KaR.js → index-tQYksITZ.js} +426 -6
  55. package/dist/cjs/index.cjs.js +1115 -63
  56. package/dist/cjs/keyboard-Cjl5HYES.js +142 -0
  57. package/dist/cjs/loader.cjs.js +2 -2
  58. package/dist/cjs/seki-button.cjs.entry.js +1 -1
  59. package/dist/cjs/seki-card-action.cjs.entry.js +17 -0
  60. package/dist/cjs/seki-card-content.cjs.entry.js +17 -0
  61. package/dist/cjs/seki-card-description.cjs.entry.js +17 -0
  62. package/dist/cjs/seki-card-footer.cjs.entry.js +22 -0
  63. package/dist/cjs/seki-card-header.cjs.entry.js +17 -0
  64. package/dist/cjs/seki-card-title.cjs.entry.js +37 -0
  65. package/dist/cjs/seki-card.cjs.entry.js +17 -0
  66. package/dist/cjs/seki-field-description.cjs.entry.js +2 -2
  67. package/dist/cjs/seki-field-error.cjs.entry.js +2 -2
  68. package/dist/cjs/seki-field-group.cjs.entry.js +2 -2
  69. package/dist/cjs/seki-field-label.cjs.entry.js +2 -2
  70. package/dist/cjs/seki-field-legend.cjs.entry.js +2 -2
  71. package/dist/cjs/seki-field.cjs.entry.js +2 -2
  72. package/dist/cjs/seki-fieldset.cjs.entry.js +2 -2
  73. package/dist/cjs/seki-input.cjs.entry.js +2 -2
  74. package/dist/cjs/seki-select-content.cjs.entry.js +1 -1
  75. package/dist/cjs/seki-select-group.cjs.entry.js +2 -2
  76. package/dist/cjs/seki-select-option.cjs.entry.js +2 -2
  77. package/dist/cjs/seki-select-trigger.cjs.entry.js +1 -1
  78. package/dist/cjs/seki-select.cjs.entry.js +2 -2
  79. package/dist/cjs/seki-sidebar-content.cjs.entry.js +20 -0
  80. package/dist/cjs/seki-sidebar-footer.cjs.entry.js +20 -0
  81. package/dist/cjs/seki-sidebar-group.cjs.entry.js +105 -0
  82. package/dist/cjs/seki-sidebar-header.cjs.entry.js +20 -0
  83. package/dist/cjs/seki-sidebar-menu-item.cjs.entry.js +174 -0
  84. package/dist/cjs/seki-sidebar-menu-sub.cjs.entry.js +99 -0
  85. package/dist/cjs/seki-sidebar-menu.cjs.entry.js +20 -0
  86. package/dist/cjs/seki-sidebar-trigger.cjs.entry.js +86 -0
  87. package/dist/cjs/seki-sidebar.cjs.entry.js +342 -0
  88. package/dist/cjs/seki-skeleton.cjs.entry.js +2 -2
  89. package/dist/cjs/seki-switch.cjs.entry.js +81 -3
  90. package/dist/cjs/seki-tooltip.cjs.entry.js +1 -1
  91. package/dist/cjs/sekiui.cjs.js +2 -2
  92. package/dist/collection/collection-manifest.json +16 -0
  93. package/dist/collection/components/card/seki-card-action.js +50 -0
  94. package/dist/collection/components/card/seki-card-content.js +51 -0
  95. package/dist/collection/components/card/seki-card-description.js +48 -0
  96. package/dist/collection/components/card/seki-card-footer.js +83 -0
  97. package/dist/collection/components/card/seki-card-header.js +54 -0
  98. package/dist/collection/components/card/seki-card-title.js +95 -0
  99. package/dist/collection/components/card/seki-card.a11y.js +363 -0
  100. package/dist/collection/components/card/seki-card.css +608 -0
  101. package/dist/collection/components/card/seki-card.js +72 -0
  102. package/dist/collection/components/field/seki-field.js +1 -1
  103. package/dist/collection/components/field-description/seki-field-description.js +1 -1
  104. package/dist/collection/components/field-error/seki-field-error.js +1 -1
  105. package/dist/collection/components/field-group/seki-field-group.js +1 -1
  106. package/dist/collection/components/field-label/seki-field-label.js +1 -1
  107. package/dist/collection/components/field-legend/seki-field-legend.js +1 -1
  108. package/dist/collection/components/fieldset/seki-fieldset.js +1 -1
  109. package/dist/collection/components/input/seki-input.js +1 -1
  110. package/dist/collection/components/select/seki-select.js +1 -1
  111. package/dist/collection/components/select-group/seki-select-group.js +1 -1
  112. package/dist/collection/components/select-option/seki-select-option.js +1 -1
  113. package/dist/collection/components/sidebar/seki-sidebar-content.css +82 -0
  114. package/dist/collection/components/sidebar/seki-sidebar-content.js +33 -0
  115. package/dist/collection/components/sidebar/seki-sidebar-footer.css +44 -0
  116. package/dist/collection/components/sidebar/seki-sidebar-footer.js +31 -0
  117. package/dist/collection/components/sidebar/seki-sidebar-group.css +158 -0
  118. package/dist/collection/components/sidebar/seki-sidebar-group.js +300 -0
  119. package/dist/collection/components/sidebar/seki-sidebar-header.css +44 -0
  120. package/dist/collection/components/sidebar/seki-sidebar-header.js +32 -0
  121. package/dist/collection/components/sidebar/seki-sidebar-menu-item.css +196 -0
  122. package/dist/collection/components/sidebar/seki-sidebar-menu-item.js +403 -0
  123. package/dist/collection/components/sidebar/seki-sidebar-menu-sub.css +357 -0
  124. package/dist/collection/components/sidebar/seki-sidebar-menu-sub.js +256 -0
  125. package/dist/collection/components/sidebar/seki-sidebar-menu.css +25 -0
  126. package/dist/collection/components/sidebar/seki-sidebar-menu.js +32 -0
  127. package/dist/collection/components/sidebar/seki-sidebar-trigger.css +68 -0
  128. package/dist/collection/components/sidebar/seki-sidebar-trigger.js +175 -0
  129. package/dist/collection/components/sidebar/seki-sidebar.css +352 -0
  130. package/dist/collection/components/sidebar/seki-sidebar.js +812 -0
  131. package/dist/collection/components/sidebar/types.js +18 -0
  132. package/dist/collection/components/skeleton/seki-skeleton.js +1 -1
  133. package/dist/collection/index.js +7 -0
  134. package/dist/collection/services/focus.js +192 -0
  135. package/dist/collection/services/index.js +7 -0
  136. package/dist/collection/services/keyboard.js +136 -0
  137. package/dist/collection/services/media-query.js +254 -0
  138. package/dist/collection/types.js +41 -0
  139. package/dist/collection/utils/a11y.js +291 -0
  140. package/dist/collection/utils/common.js +286 -0
  141. package/dist/components/index.js +1053 -91
  142. package/dist/components/p-BJCq8m2o.js +138 -0
  143. package/dist/components/{p-QhPshhKB.js → p-BzYKy7d3.js} +427 -7
  144. package/dist/components/p-DwTISp-i.js +111 -0
  145. package/dist/components/seki-button.js +1 -1
  146. package/dist/components/seki-card-action.d.ts +11 -0
  147. package/dist/components/seki-card-action.js +38 -0
  148. package/dist/components/seki-card-content.d.ts +11 -0
  149. package/dist/components/seki-card-content.js +38 -0
  150. package/dist/components/seki-card-description.d.ts +11 -0
  151. package/dist/components/seki-card-description.js +38 -0
  152. package/dist/components/seki-card-footer.d.ts +11 -0
  153. package/dist/components/seki-card-footer.js +44 -0
  154. package/dist/components/seki-card-header.d.ts +11 -0
  155. package/dist/components/seki-card-header.js +38 -0
  156. package/dist/components/seki-card-title.d.ts +11 -0
  157. package/dist/components/seki-card-title.js +59 -0
  158. package/dist/components/seki-card.d.ts +11 -0
  159. package/dist/components/seki-card.js +39 -0
  160. package/dist/components/seki-field-description.js +2 -2
  161. package/dist/components/seki-field-error.js +2 -2
  162. package/dist/components/seki-field-group.js +2 -2
  163. package/dist/components/seki-field-label.js +2 -2
  164. package/dist/components/seki-field-legend.js +2 -2
  165. package/dist/components/seki-field.js +2 -2
  166. package/dist/components/seki-fieldset.js +2 -2
  167. package/dist/components/seki-input.js +2 -2
  168. package/dist/components/seki-select-content.js +1 -1
  169. package/dist/components/seki-select-group.js +2 -2
  170. package/dist/components/seki-select-option.js +2 -2
  171. package/dist/components/seki-select-trigger.js +1 -1
  172. package/dist/components/seki-select.js +2 -2
  173. package/dist/components/seki-sidebar-content.d.ts +11 -0
  174. package/dist/components/seki-sidebar-content.js +38 -0
  175. package/dist/components/seki-sidebar-footer.d.ts +11 -0
  176. package/dist/components/seki-sidebar-footer.js +38 -0
  177. package/dist/components/seki-sidebar-group.d.ts +11 -0
  178. package/dist/components/seki-sidebar-group.js +131 -0
  179. package/dist/components/seki-sidebar-header.d.ts +11 -0
  180. package/dist/components/seki-sidebar-header.js +38 -0
  181. package/dist/components/seki-sidebar-menu-item.d.ts +11 -0
  182. package/dist/components/seki-sidebar-menu-item.js +200 -0
  183. package/dist/components/seki-sidebar-menu-sub.d.ts +11 -0
  184. package/dist/components/seki-sidebar-menu-sub.js +123 -0
  185. package/dist/components/seki-sidebar-menu.d.ts +11 -0
  186. package/dist/components/seki-sidebar-menu.js +38 -0
  187. package/dist/components/seki-sidebar-trigger.d.ts +11 -0
  188. package/dist/components/seki-sidebar-trigger.js +109 -0
  189. package/dist/components/seki-sidebar.d.ts +11 -0
  190. package/dist/components/seki-sidebar.js +380 -0
  191. package/dist/components/seki-skeleton.js +2 -2
  192. package/dist/components/seki-switch.js +1 -1
  193. package/dist/components/seki-tooltip.js +1 -1
  194. package/dist/esm/{index-CuXbV_yz.js → index-Dfzpqq0a.js} +426 -6
  195. package/dist/esm/index.js +1053 -63
  196. package/dist/esm/keyboard-BJCq8m2o.js +138 -0
  197. package/dist/esm/loader.js +3 -3
  198. package/dist/esm/seki-button.entry.js +1 -1
  199. package/dist/esm/seki-card-action.entry.js +15 -0
  200. package/dist/esm/seki-card-content.entry.js +15 -0
  201. package/dist/esm/seki-card-description.entry.js +15 -0
  202. package/dist/esm/seki-card-footer.entry.js +20 -0
  203. package/dist/esm/seki-card-header.entry.js +15 -0
  204. package/dist/esm/seki-card-title.entry.js +35 -0
  205. package/dist/esm/seki-card.entry.js +15 -0
  206. package/dist/esm/seki-field-description.entry.js +2 -2
  207. package/dist/esm/seki-field-error.entry.js +2 -2
  208. package/dist/esm/seki-field-group.entry.js +2 -2
  209. package/dist/esm/seki-field-label.entry.js +2 -2
  210. package/dist/esm/seki-field-legend.entry.js +2 -2
  211. package/dist/esm/seki-field.entry.js +2 -2
  212. package/dist/esm/seki-fieldset.entry.js +2 -2
  213. package/dist/esm/seki-input.entry.js +2 -2
  214. package/dist/esm/seki-select-content.entry.js +1 -1
  215. package/dist/esm/seki-select-group.entry.js +2 -2
  216. package/dist/esm/seki-select-option.entry.js +2 -2
  217. package/dist/esm/seki-select-trigger.entry.js +1 -1
  218. package/dist/esm/seki-select.entry.js +2 -2
  219. package/dist/esm/seki-sidebar-content.entry.js +18 -0
  220. package/dist/esm/seki-sidebar-footer.entry.js +18 -0
  221. package/dist/esm/seki-sidebar-group.entry.js +103 -0
  222. package/dist/esm/seki-sidebar-header.entry.js +18 -0
  223. package/dist/esm/seki-sidebar-menu-item.entry.js +172 -0
  224. package/dist/esm/seki-sidebar-menu-sub.entry.js +97 -0
  225. package/dist/esm/seki-sidebar-menu.entry.js +18 -0
  226. package/dist/esm/seki-sidebar-trigger.entry.js +84 -0
  227. package/dist/esm/seki-sidebar.entry.js +340 -0
  228. package/dist/esm/seki-skeleton.entry.js +2 -2
  229. package/dist/esm/seki-switch.entry.js +84 -2
  230. package/dist/esm/seki-tooltip.entry.js +1 -1
  231. package/dist/esm/sekiui.js +3 -3
  232. package/dist/sekiui/index.esm.js +1 -1
  233. package/dist/sekiui/p-01cfb4e7.entry.js +1 -0
  234. package/dist/sekiui/{p-431f46a1.entry.js → p-042ec460.entry.js} +1 -1
  235. package/dist/sekiui/{p-a36f1ac4.entry.js → p-10c008fc.entry.js} +1 -1
  236. package/dist/sekiui/p-352bd295.entry.js +1 -0
  237. package/dist/sekiui/p-37c5f4d9.entry.js +1 -0
  238. package/dist/sekiui/p-40fb71d6.entry.js +1 -0
  239. package/dist/sekiui/{p-eefbc037.entry.js → p-44191aed.entry.js} +1 -1
  240. package/dist/sekiui/{p-81709fc2.entry.js → p-4423d621.entry.js} +1 -1
  241. package/dist/sekiui/{p-e679d501.entry.js → p-4636588f.entry.js} +1 -1
  242. package/dist/sekiui/p-471b97a5.entry.js +1 -0
  243. package/dist/sekiui/{p-de4735fb.entry.js → p-56f0d754.entry.js} +1 -1
  244. package/dist/sekiui/p-5bc0f5aa.entry.js +1 -0
  245. package/dist/sekiui/p-6164cd8a.entry.js +1 -0
  246. package/dist/sekiui/{p-0fba4e2d.entry.js → p-635f4098.entry.js} +1 -1
  247. package/dist/sekiui/{p-434be19f.entry.js → p-743fc6d9.entry.js} +1 -1
  248. package/dist/sekiui/p-83e65cbe.entry.js +1 -0
  249. package/dist/sekiui/p-8b7bd061.entry.js +1 -0
  250. package/dist/sekiui/p-8d9a4878.entry.js +1 -0
  251. package/dist/sekiui/p-9cb9cdfe.entry.js +1 -0
  252. package/dist/sekiui/p-9f2d95d7.entry.js +1 -0
  253. package/dist/sekiui/p-BJCq8m2o.js +1 -0
  254. package/dist/sekiui/p-Dfzpqq0a.js +2 -0
  255. package/dist/sekiui/p-a1a71958.entry.js +1 -0
  256. package/dist/sekiui/{p-bf942ad5.entry.js → p-a71e0c55.entry.js} +1 -1
  257. package/dist/sekiui/{p-6ff91f7f.entry.js → p-ae227955.entry.js} +1 -1
  258. package/dist/sekiui/{p-80a41058.entry.js → p-b365f5fb.entry.js} +1 -1
  259. package/dist/sekiui/{p-6bde807e.entry.js → p-b387a2a5.entry.js} +1 -1
  260. package/dist/sekiui/p-b8590f4d.entry.js +1 -0
  261. package/dist/sekiui/p-c98b6d6a.entry.js +1 -0
  262. package/dist/sekiui/{p-7c2245be.entry.js → p-d73cdb9a.entry.js} +1 -1
  263. package/dist/sekiui/{p-a56602b3.entry.js → p-d96e770e.entry.js} +1 -1
  264. package/dist/sekiui/p-e62dd89b.entry.js +1 -0
  265. package/dist/sekiui/{p-386c00ac.entry.js → p-e7bb140c.entry.js} +1 -1
  266. package/dist/sekiui/{p-6e238adf.entry.js → p-eecc18f3.entry.js} +1 -1
  267. package/dist/sekiui/p-ff636955.entry.js +1 -0
  268. package/dist/sekiui/sekiui.esm.js +1 -1
  269. package/dist/types/components/card/seki-card-action.d.ts +16 -0
  270. package/dist/types/components/card/seki-card-content.d.ts +17 -0
  271. package/dist/types/components/card/seki-card-description.d.ts +14 -0
  272. package/dist/types/components/card/seki-card-footer.d.ts +24 -0
  273. package/dist/types/components/card/seki-card-header.d.ts +20 -0
  274. package/dist/types/components/card/seki-card-title.d.ts +20 -0
  275. package/dist/types/components/card/seki-card.a11y.d.ts +1 -0
  276. package/dist/types/components/card/seki-card.d.ts +23 -0
  277. package/dist/types/components/sidebar/seki-sidebar-content.d.ts +18 -0
  278. package/dist/types/components/sidebar/seki-sidebar-footer.d.ts +16 -0
  279. package/dist/types/components/sidebar/seki-sidebar-group.d.ts +81 -0
  280. package/dist/types/components/sidebar/seki-sidebar-header.d.ts +17 -0
  281. package/dist/types/components/sidebar/seki-sidebar-menu-item.d.ts +104 -0
  282. package/dist/types/components/sidebar/seki-sidebar-menu-sub.d.ts +81 -0
  283. package/dist/types/components/sidebar/seki-sidebar-menu.d.ts +17 -0
  284. package/dist/types/components/sidebar/seki-sidebar-trigger.d.ts +53 -0
  285. package/dist/types/components/sidebar/seki-sidebar.d.ts +185 -0
  286. package/dist/types/components/sidebar/types.d.ts +245 -0
  287. package/dist/types/components.d.ts +899 -0
  288. package/dist/types/index.d.ts +4 -0
  289. package/dist/types/services/focus.d.ts +74 -0
  290. package/dist/types/services/index.d.ts +7 -0
  291. package/dist/types/services/keyboard.d.ts +74 -0
  292. package/dist/types/services/media-query.d.ts +121 -0
  293. package/dist/types/types.d.ts +105 -0
  294. package/dist/types/utils/a11y.d.ts +130 -0
  295. package/dist/types/utils/common.d.ts +142 -0
  296. package/package.json +2 -1
  297. package/dist/sekiui/p-9fe07f6e.entry.js +0 -1
  298. package/dist/sekiui/p-CuXbV_yz.js +0 -2
package/dist/esm/index.js CHANGED
@@ -1,84 +1,1074 @@
1
- import { r as registerInstance, c as createEvent, h, H as Host } from './index-CuXbV_yz.js';
1
+ export { seki_switch as SekiSwitch } from './seki-switch.entry.js';
2
+ export { K as KeyboardService, c as createKeyboardService, g as getKeyboardService } from './keyboard-BJCq8m2o.js';
3
+ import './index-Dfzpqq0a.js';
2
4
 
3
- const sekiSwitchCss = ":host{--seki-neutral-50:hsl(0, 0%, 98%);--seki-neutral-100:hsl(0, 0%, 96.1%);--seki-neutral-200:hsl(0, 0%, 89.8%);--seki-neutral-300:hsl(0, 0%, 83.1%);--seki-neutral-400:hsl(0, 0%, 63.9%);--seki-neutral-500:hsl(0, 0%, 45.1%);--seki-neutral-600:hsl(0, 0%, 32.2%);--seki-neutral-700:hsl(0, 0%, 25.1%);--seki-neutral-800:hsl(0, 0%, 14.9%);--seki-neutral-900:hsl(0, 0%, 9%);--seki-neutral-950:hsl(0, 0%, 3.9%);--seki-primary-50:hsl(210, 100%, 97%);--seki-primary-100:hsl(210, 95%, 93%);--seki-primary-200:hsl(210, 95%, 85%);--seki-primary-300:hsl(210, 90%, 73%);--seki-primary-400:hsl(210, 85%, 58%);--seki-primary-500:hsl(210, 80%, 48%);--seki-primary-600:hsl(210, 75%, 40%);--seki-primary-700:hsl(210, 70%, 32%);--seki-primary-800:hsl(210, 65%, 25%);--seki-primary-900:hsl(210, 60%, 18%);--seki-primary-950:hsl(210, 55%, 10%);--seki-success-500:hsl(142, 71%, 45%);--seki-success-600:hsl(142, 71%, 35%);--seki-warning-500:hsl(38, 92%, 50%);--seki-warning-600:hsl(38, 92%, 40%);--seki-destructive-500:hsl(0, 84.2%, 60.2%);--seki-destructive-600:hsl(0, 72%, 41%)}:host{--seki-background:hsl(0, 0%, 100%);--seki-foreground:hsl(0, 0%, 3.9%);--seki-muted:hsl(0, 0%, 96.1%);--seki-muted-foreground:hsl(0, 0%, 45.1%);--seki-card:hsl(0, 0%, 100%);--seki-card-foreground:hsl(0, 0%, 3.9%);--seki-popover:hsl(0, 0%, 100%);--seki-popover-foreground:hsl(0, 0%, 3.9%);--seki-border:hsl(0, 0%, 89.8%);--seki-input:hsl(0, 0%, 89.8%);--seki-primary:hsl(0, 0%, 9%);--seki-primary-foreground:hsl(0, 0%, 98%);--seki-secondary:hsl(0, 0%, 96.1%);--seki-secondary-foreground:hsl(0, 0%, 9%);--seki-accent:hsl(0, 0%, 96.1%);--seki-accent-foreground:hsl(0, 0%, 9%);--seki-destructive:hsl(0, 84.2%, 60.2%);--seki-destructive-foreground:hsl(0, 0%, 98%);--seki-ring:hsl(0, 0%, 3.9%);--seki-bg-primary:var(--seki-background);--seki-bg-secondary:var(--seki-muted);--seki-bg-tertiary:var(--seki-accent);--seki-text-primary:var(--seki-foreground);--seki-text-secondary:var(--seki-muted-foreground);--seki-text-tertiary:var(--seki-neutral-400);--seki-border-default:var(--seki-border);--seki-border-emphasis:var(--seki-neutral-300)}:host([data-theme='dark']){--seki-background:hsl(0, 0%, 3.9%);--seki-foreground:hsl(0, 0%, 98%);--seki-muted:hsl(0, 0%, 14.9%);--seki-muted-foreground:hsl(0, 0%, 63.9%);--seki-card:hsl(0, 0%, 3.9%);--seki-card-foreground:hsl(0, 0%, 98%);--seki-popover:hsl(0, 0%, 3.9%);--seki-popover-foreground:hsl(0, 0%, 98%);--seki-border:hsl(0, 0%, 14.9%);--seki-input:hsl(0, 0%, 14.9%);--seki-primary:hsl(0, 0%, 98%);--seki-primary-foreground:hsl(0, 0%, 9%);--seki-secondary:hsl(0, 0%, 14.9%);--seki-secondary-foreground:hsl(0, 0%, 98%);--seki-accent:hsl(0, 0%, 14.9%);--seki-accent-foreground:hsl(0, 0%, 98%);--seki-destructive:hsl(0, 62.8%, 30.6%);--seki-destructive-foreground:hsl(0, 0%, 98%);--seki-ring:hsl(0, 0%, 83.1%);--seki-bg-primary:var(--seki-background);--seki-bg-secondary:var(--seki-muted);--seki-bg-tertiary:var(--seki-accent);--seki-text-primary:var(--seki-foreground);--seki-text-secondary:var(--seki-muted-foreground);--seki-text-tertiary:var(--seki-neutral-600);--seki-border-default:var(--seki-border);--seki-border-emphasis:var(--seki-neutral-700);--seki-button-primary-hover-bg:hsl(0, 0%, 98%, 0.9);--seki-button-secondary-hover-bg:hsl(0, 0%, 14.9%, 0.8)}:host{--seki-button-primary-bg:var(--seki-primary);--seki-button-primary-text:var(--seki-primary-foreground);--seki-button-primary-border:transparent;--seki-button-primary-hover-bg:hsl(0, 0%, 9%, 0.9);--seki-button-primary-hover-text:var(--seki-primary-foreground);--seki-button-primary-hover-border:transparent;--seki-button-secondary-bg:var(--seki-secondary);--seki-button-secondary-text:var(--seki-secondary-foreground);--seki-button-secondary-border:transparent;--seki-button-secondary-hover-bg:hsl(0, 0%, 96.1%, 0.8);--seki-button-secondary-hover-text:var(--seki-secondary-foreground);--seki-button-secondary-hover-border:transparent;--seki-button-outline-bg:transparent;--seki-button-outline-text:var(--seki-foreground);--seki-button-outline-border:var(--seki-input);--seki-button-outline-hover-bg:var(--seki-accent);--seki-button-outline-hover-text:var(--seki-accent-foreground);--seki-button-outline-hover-border:var(--seki-input);--seki-button-ghost-bg:transparent;--seki-button-ghost-text:var(--seki-foreground);--seki-button-ghost-border:transparent;--seki-button-ghost-hover-bg:var(--seki-accent);--seki-button-ghost-hover-text:var(--seki-accent-foreground);--seki-button-ghost-hover-border:transparent;--seki-button-destructive-bg:var(--seki-destructive);--seki-button-destructive-text:var(--seki-destructive-foreground);--seki-button-destructive-border:transparent;--seki-button-destructive-hover-bg:hsl(0, 84.2%, 60.2%, 0.9);--seki-button-destructive-hover-border:transparent;--seki-button-sm-padding-x:var(--seki-spacing-3, 0.75rem);--seki-button-sm-padding-y:0.375rem;--seki-button-sm-font-size:var(--seki-text-sm, 0.875rem);--seki-button-sm-height:2.25rem;--seki-button-md-padding-x:var(--seki-spacing-4, 1rem);--seki-button-md-padding-y:var(--seki-spacing-2, 0.5rem);--seki-button-md-font-size:var(--seki-text-base, 1rem);--seki-button-md-height:2.5rem;--seki-button-lg-padding-x:2rem;--seki-button-lg-padding-y:0.5rem;--seki-button-lg-font-size:1rem;--seki-button-lg-height:2.75rem;--seki-button-icon-sm-size:2rem;--seki-button-icon-size:2.5rem;--seki-button-icon-lg-size:3rem;--seki-button-icon-gap:0.5rem;--seki-button-link-bg:transparent;--seki-button-link-text:var(--seki-primary);--seki-button-link-border:transparent;--seki-button-link-hover-bg:transparent;--seki-button-link-hover-text:var(--seki-primary);--seki-button-link-hover-border:transparent;--seki-button-radius:var(--seki-radius-md, 0.375rem);--seki-button-font-weight:var(--seki-font-medium, 500);--seki-button-transition-duration:150ms;--seki-button-transition-timing:ease-in-out;--seki-button-shadow:var(--seki-shadow-sm, 0 1px 2px 0 rgb(0 0 0 / 0.05));--seki-button-shadow-hover:var(--seki-shadow-md, 0 4px 6px -1px rgb(0 0 0 / 0.1));--seki-button-disabled-opacity:0.5;--seki-input-bg:var(--seki-background);--seki-input-border:var(--seki-border);--seki-input-text:var(--seki-foreground);--seki-input-placeholder:var(--seki-muted-foreground);--seki-input-ring:var(--seki-ring);--seki-input-invalid-border:var(--seki-destructive);--seki-input-invalid-ring:var(--seki-destructive);--seki-input-disabled-opacity:0.5;--seki-input-radius:var(--seki-radius-md);--seki-input-ring-offset:2px;--seki-select-trigger-bg:var(--seki-background);--seki-select-trigger-border:1px solid var(--seki-border);--seki-select-trigger-bg-hover:var(--seki-muted);--seki-select-trigger-radius:var(--seki-radius-md);--seki-select-trigger-min-height:2.5rem;--seki-select-trigger-padding:0.5rem 0.75rem;--seki-select-trigger-gap:0.5rem;--seki-select-content-bg:var(--seki-popover);--seki-select-content-border:1px solid var(--seki-border);--seki-select-content-shadow:0 10px 15px -3px rgb(0 0 0 / 0.1);--seki-select-content-radius:var(--seki-radius-md);--seki-select-content-padding:0.5rem 0;--seki-select-option-padding:0.5rem 0.75rem;--seki-select-option-gap:0.5rem;--seki-select-option-radius:var(--seki-radius-sm);--seki-select-option-bg-hover:var(--seki-muted);--seki-select-option-bg-selected:var(--seki-muted);--seki-select-group-label-padding:0.5rem 0.75rem;--seki-select-group-label-font-size:var(--seki-font-size-xs);--seki-select-group-label-font-weight:var(--seki-font-semibold);--seki-select-group-label-color:var(--seki-muted-foreground);--seki-select-group-separator:1px solid var(--seki-border)}:host{--seki-spacing-0:0;--seki-spacing-0-5:0.125rem;--seki-spacing-1:0.25rem;--seki-spacing-1-5:0.375rem;--seki-spacing-2:0.5rem;--seki-spacing-2-5:0.625rem;--seki-spacing-3:0.75rem;--seki-spacing-3-5:0.875rem;--seki-spacing-4:1rem;--seki-spacing-5:1.25rem;--seki-spacing-6:1.5rem;--seki-spacing-8:2rem;--seki-spacing-10:2.5rem;--seki-spacing-12:3rem;--seki-spacing-16:4rem;--seki-spacing-20:5rem;--seki-spacing-24:6rem;--seki-input-height-sm:2rem;--seki-input-height-md:2.5rem;--seki-input-height-lg:3rem;--seki-input-padding-x:0.75rem;--seki-input-padding-y:0.5rem;--seki-input-font-size:0.875rem;--seki-input-ring-offset:2px}:host{--seki-shadow-sm:0 1px 2px 0 rgb(0 0 0 / 0.05);--seki-shadow-md:0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);--seki-shadow-lg:0 10px 15px -3px rgb(0 0 0 / 0.15), 0 4px 6px -4px rgb(0 0 0 / 0.1)}:host{--seki-font-sans:-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue',\n Arial, sans-serif;--seki-font-mono:ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;--seki-text-xs:0.75rem;--seki-text-sm:0.875rem;--seki-text-base:1rem;--seki-text-lg:1.125rem;--seki-text-xl:1.25rem;--seki-text-2xl:1.5rem;--seki-text-3xl:1.875rem;--seki-text-4xl:2.25rem;--seki-font-normal:400;--seki-font-medium:500;--seki-font-semibold:600;--seki-font-bold:700;--seki-leading-tight:1.25;--seki-leading-normal:1.5;--seki-leading-relaxed:1.75}:host{--seki-radius-sm:0.25rem;--seki-radius-md:0.375rem;--seki-radius-lg:0.5rem;--seki-radius-xl:1rem;}:host{display:inline-flex;align-items:center;justify-content:center;min-width:44px;min-height:44px}.switch{width:var(--seki-switch-width, 2.75rem);height:var(--seki-switch-height, 1.5rem);position:relative;display:inline-flex;align-items:center;flex-shrink:0;background-color:var(--seki-switch-bg-unchecked, hsl(var(--muted, 240 4.8% 95.9%)));border-radius:9999px;cursor:pointer;transition:background-color var(--seki-switch-transition-duration, 150ms) ease-out;outline:none}.switch:focus-visible{outline:2px solid var(--seki-switch-focus-ring, hsl(var(--ring, 240 5% 64.9%)));outline-offset:2px}:host([data-state=\"checked\"]) .switch{background-color:var(--seki-switch-bg-checked, hsl(var(--primary, 240 5.9% 10%)))}:host([data-disabled]) .switch{background-color:var(--seki-switch-bg-disabled, hsl(var(--muted, 240 4.8% 95.9%) / 0.5));cursor:not-allowed;opacity:0.5}.thumb{width:var(--seki-switch-thumb-size, 1.25rem);height:var(--seki-switch-thumb-size, 1.25rem);background-color:var(--seki-switch-thumb-bg, hsl(var(--background, 0 0% 100%)));position:absolute;left:0.125rem;border-radius:50%;box-shadow:0 1px 2px 0 rgb(0 0 0 / 0.05);transition:transform var(--seki-switch-transition-duration, 150ms) ease-out;pointer-events:none}:host([data-state=\"checked\"]) .thumb{transform:translateX(calc(var(--seki-switch-width, 2.75rem) - var(--seki-switch-thumb-size, 1.25rem) - 0.25rem))}@media (prefers-color-scheme: dark){.switch{--seki-switch-bg-unchecked:hsl(var(--muted, 240 3.7% 15.9%))}.thumb{--seki-switch-thumb-bg:hsl(var(--background, 240 10% 3.9%))}}";
4
-
5
- const SekiSwitch = class {
6
- constructor(hostRef) {
7
- registerInstance(this, hostRef);
8
- this.sekiChange = createEvent(this, "sekiChange");
9
- /**
10
- * @description Initial checked state for uncontrolled mode. Ignored if checked prop is provided.
11
- */
12
- this.defaultChecked = false;
13
- /**
14
- * @description Disables all interactions when true.
15
- */
16
- this.disabled = false;
17
- /**
18
- * @description Marks switch as required for form validation.
19
- */
20
- this.required = false;
21
- /**
22
- * @description Value sent in form data when switch is checked. Defaults to 'on'.
23
- */
24
- this.value = 'on';
25
- /**
26
- * @description Internal checked state for uncontrolled mode.
27
- */
28
- this.internalChecked = false;
29
- /**
30
- * Toggle switch state and emit event
31
- */
32
- this.toggle = () => {
33
- if (this.disabled) {
5
+ /**
6
+ * Focus Management Service
7
+ * Provides utilities for focus management, focus traps, and focus restoration
8
+ */
9
+ /**
10
+ * FocusService - Centralized focus management
11
+ * Provides:
12
+ * - Focus trap implementation
13
+ * - Focus restoration
14
+ * - Focusable element detection
15
+ * - Focus utilities for accessibility
16
+ */
17
+ class FocusService {
18
+ constructor() {
19
+ this.focusTrapStack = new Map();
20
+ this.previouslyFocusedElement = null;
21
+ }
22
+ /**
23
+ * Get all focusable elements within a container
24
+ * Includes buttons, links, inputs, textareas, selects, and elements with tabindex
25
+ */
26
+ getFocusableElements(container = document) {
27
+ const focusableSelectors = [
28
+ 'button:not([disabled])',
29
+ 'a[href]',
30
+ 'input:not([disabled])',
31
+ 'textarea:not([disabled])',
32
+ 'select:not([disabled])',
33
+ '[tabindex]:not([tabindex="-1"])',
34
+ ].join(',');
35
+ const elements = Array.from(container.querySelectorAll(focusableSelectors));
36
+ return elements.filter((el) => {
37
+ // Exclude hidden elements
38
+ const style = window.getComputedStyle(el);
39
+ return style.display !== 'none' && style.visibility !== 'hidden';
40
+ });
41
+ }
42
+ /**
43
+ * Check if an element is focusable
44
+ */
45
+ isFocusable(element) {
46
+ const focusableSelectors = [
47
+ 'button',
48
+ 'a[href]',
49
+ 'input',
50
+ 'textarea',
51
+ 'select',
52
+ '[tabindex]',
53
+ ];
54
+ return focusableSelectors.some((selector) => element.matches(selector)) && !element.hasAttribute('disabled');
55
+ }
56
+ /**
57
+ * Set focus to an element with optional callbacks
58
+ */
59
+ setFocus(element, options) {
60
+ var _a;
61
+ if (!element)
62
+ return false;
63
+ try {
64
+ element.focus({ preventScroll: (_a = options === null || options === void 0 ? void 0 : options.preventScroll) !== null && _a !== void 0 ? _a : false });
65
+ return document.activeElement === element;
66
+ }
67
+ catch (error) {
68
+ console.warn('Failed to set focus:', error);
69
+ return false;
70
+ }
71
+ }
72
+ /**
73
+ * Trap focus within a container (keyboard navigation stays within bounds)
74
+ * @param container - The element to trap focus within
75
+ * @param options - Focus trap options
76
+ */
77
+ createFocusTrap(container, options = {}) {
78
+ if (typeof window === 'undefined')
79
+ return;
80
+ const { initialFocus, restoreFocus = true } = options;
81
+ // Store the previously focused element for restoration
82
+ if (restoreFocus) {
83
+ this.previouslyFocusedElement = document.activeElement;
84
+ }
85
+ // Set initial focus
86
+ if (initialFocus) {
87
+ this.setFocus(initialFocus);
88
+ }
89
+ else {
90
+ const focusableElements = this.getFocusableElements(container);
91
+ if (focusableElements.length > 0) {
92
+ this.setFocus(focusableElements[0]);
93
+ }
94
+ }
95
+ // Handle Tab key for focus trap
96
+ const handleKeyDown = (event) => {
97
+ if (event.key !== 'Tab')
34
98
  return;
99
+ const focusableElements = this.getFocusableElements(container);
100
+ if (focusableElements.length === 0)
101
+ return;
102
+ const currentFocusIndex = focusableElements.indexOf(document.activeElement);
103
+ if (event.shiftKey) {
104
+ // Shift+Tab - move backwards
105
+ const previousIndex = currentFocusIndex - 1;
106
+ const targetElement = previousIndex >= 0 ? focusableElements[previousIndex] : focusableElements[focusableElements.length - 1];
107
+ event.preventDefault();
108
+ this.setFocus(targetElement);
35
109
  }
36
- const newCheckedState = !this.isChecked;
37
- // Update internal state only in uncontrolled mode
38
- if (this.checked === undefined) {
39
- this.internalChecked = newCheckedState;
110
+ else {
111
+ // Tab - move forwards
112
+ const nextIndex = currentFocusIndex + 1;
113
+ const targetElement = nextIndex < focusableElements.length ? focusableElements[nextIndex] : focusableElements[0];
114
+ event.preventDefault();
115
+ this.setFocus(targetElement);
40
116
  }
41
- // Always emit event (for both controlled and uncontrolled)
42
- this.sekiChange.emit({ checked: newCheckedState });
43
117
  };
44
- /**
45
- * Handle click events
46
- */
47
- this.handleClick = () => {
48
- this.toggle();
118
+ container.addEventListener('keydown', handleKeyDown);
119
+ this.focusTrapStack.set(container, this.previouslyFocusedElement);
120
+ // Store the handler for potential later cleanup
121
+ // Note: Manual cleanup should be done via releaseFocusTrap()
122
+ }
123
+ /**
124
+ * Release focus trap from a container
125
+ */
126
+ releaseFocusTrap(container, restoreFocus = true) {
127
+ const previousElement = this.focusTrapStack.get(container);
128
+ this.focusTrapStack.delete(container);
129
+ if (restoreFocus && previousElement) {
130
+ this.setFocus(previousElement);
131
+ }
132
+ }
133
+ /**
134
+ * Get the first focusable element in a container
135
+ */
136
+ getFirstFocusable(container = document) {
137
+ const focusable = this.getFocusableElements(container);
138
+ return focusable.length > 0 ? focusable[0] : null;
139
+ }
140
+ /**
141
+ * Get the last focusable element in a container
142
+ */
143
+ getLastFocusable(container = document) {
144
+ const focusable = this.getFocusableElements(container);
145
+ return focusable.length > 0 ? focusable[focusable.length - 1] : null;
146
+ }
147
+ /**
148
+ * Move focus to the next focusable element
149
+ */
150
+ focusNext(container = document) {
151
+ const focusable = this.getFocusableElements(container);
152
+ const currentIndex = focusable.indexOf(document.activeElement);
153
+ const nextIndex = (currentIndex + 1) % focusable.length;
154
+ if (focusable.length > 0) {
155
+ this.setFocus(focusable[nextIndex]);
156
+ return true;
157
+ }
158
+ return false;
159
+ }
160
+ /**
161
+ * Move focus to the previous focusable element
162
+ */
163
+ focusPrevious(container = document) {
164
+ const focusable = this.getFocusableElements(container);
165
+ const currentIndex = focusable.indexOf(document.activeElement);
166
+ const previousIndex = (currentIndex - 1 + focusable.length) % focusable.length;
167
+ if (focusable.length > 0) {
168
+ this.setFocus(focusable[previousIndex]);
169
+ return true;
170
+ }
171
+ return false;
172
+ }
173
+ /**
174
+ * Clear all focus traps
175
+ */
176
+ clearFocusTraps() {
177
+ this.focusTrapStack.clear();
178
+ }
179
+ }
180
+ // Singleton instance
181
+ let focusServiceInstance = null;
182
+ /**
183
+ * Get the singleton FocusService instance
184
+ */
185
+ function getFocusService() {
186
+ if (!focusServiceInstance) {
187
+ focusServiceInstance = new FocusService();
188
+ }
189
+ return focusServiceInstance;
190
+ }
191
+ /**
192
+ * Create a new isolated FocusService instance
193
+ */
194
+ function createFocusService() {
195
+ return new FocusService();
196
+ }
197
+
198
+ /**
199
+ * Media Query Service
200
+ * Provides utilities for responsive design and media query management
201
+ */
202
+ /**
203
+ * Default breakpoints (Tailwind-inspired)
204
+ */
205
+ const DEFAULT_BREAKPOINTS = {
206
+ sm: '640px',
207
+ md: '768px',
208
+ lg: '1024px',
209
+ xl: '1280px',
210
+ '2xl': '1536px',
211
+ };
212
+ /**
213
+ * MediaQueryService - Centralized media query management
214
+ * Provides:
215
+ * - Media query listener registration
216
+ * - Breakpoint detection
217
+ * - Window resize handling
218
+ * - Current viewport information
219
+ */
220
+ class MediaQueryService {
221
+ constructor(breakpoints = DEFAULT_BREAKPOINTS) {
222
+ this.listeners = new Map();
223
+ this.resizeObserver = null;
224
+ this.resizeListeners = new Map();
225
+ this.breakpoints = breakpoints;
226
+ }
227
+ /**
228
+ * Register a media query listener
229
+ * @param id - Unique identifier for this listener
230
+ * @param query - CSS media query string
231
+ * @param handler - Callback when media query matches/unmatches
232
+ */
233
+ registerMediaQuery(id, query, handler) {
234
+ if (typeof window === 'undefined')
235
+ return;
236
+ try {
237
+ const matcher = window.matchMedia(query);
238
+ const listener = { query, handler, matcher };
239
+ // Call handler with initial state
240
+ handler(matcher.matches);
241
+ // Listen for changes
242
+ matcher.addEventListener('change', (e) => handler(e.matches));
243
+ this.listeners.set(id, listener);
244
+ }
245
+ catch (error) {
246
+ console.warn(`Failed to register media query "${query}":`, error);
247
+ }
248
+ }
249
+ /**
250
+ * Register a breakpoint listener (easier than raw media queries)
251
+ * @param id - Unique identifier
252
+ * @param breakpoint - Breakpoint name (sm, md, lg, xl, 2xl)
253
+ * @param type - Type of match: 'min' (mobile-first) or 'max' (desktop-first)
254
+ * @param handler - Callback when breakpoint matches
255
+ */
256
+ registerBreakpoint(id, breakpoint, type = 'min', handler) {
257
+ const size = this.breakpoints[breakpoint];
258
+ if (!size) {
259
+ console.warn(`Unknown breakpoint: ${breakpoint}`);
260
+ return;
261
+ }
262
+ const query = type === 'min' ? `(min-width: ${size})` : `(max-width: ${size})`;
263
+ this.registerMediaQuery(id, query, handler);
264
+ }
265
+ /**
266
+ * Unregister a media query listener
267
+ */
268
+ unregisterMediaQuery(id) {
269
+ const listener = this.listeners.get(id);
270
+ if (listener && listener.matcher) {
271
+ listener.matcher.removeEventListener('change', () => { });
272
+ }
273
+ this.listeners.delete(id);
274
+ }
275
+ /**
276
+ * Check if a media query currently matches
277
+ */
278
+ isMatching(query) {
279
+ if (typeof window === 'undefined')
280
+ return false;
281
+ try {
282
+ return window.matchMedia(query).matches;
283
+ }
284
+ catch (error) {
285
+ console.warn(`Failed to check media query "${query}":`, error);
286
+ return false;
287
+ }
288
+ }
289
+ /**
290
+ * Check if a breakpoint is currently active
291
+ */
292
+ isBreakpointActive(breakpoint, type = 'min') {
293
+ const size = this.breakpoints[breakpoint];
294
+ if (!size)
295
+ return false;
296
+ const query = type === 'min' ? `(min-width: ${size})` : `(max-width: ${size})`;
297
+ return this.isMatching(query);
298
+ }
299
+ /**
300
+ * Get the current viewport width
301
+ */
302
+ getViewportWidth() {
303
+ if (typeof window === 'undefined')
304
+ return 0;
305
+ return window.innerWidth;
306
+ }
307
+ /**
308
+ * Get the current viewport height
309
+ */
310
+ getViewportHeight() {
311
+ if (typeof window === 'undefined')
312
+ return 0;
313
+ return window.innerHeight;
314
+ }
315
+ /**
316
+ * Check if viewport is mobile-sized (< 768px)
317
+ */
318
+ isMobile() {
319
+ return this.getViewportWidth() < 768;
320
+ }
321
+ /**
322
+ * Check if viewport is tablet-sized (768px - 1024px)
323
+ */
324
+ isTablet() {
325
+ const width = this.getViewportWidth();
326
+ return width >= 768 && width < 1024;
327
+ }
328
+ /**
329
+ * Check if viewport is desktop-sized (>= 1024px)
330
+ */
331
+ isDesktop() {
332
+ return this.getViewportWidth() >= 1024;
333
+ }
334
+ /**
335
+ * Check if prefers-reduced-motion is enabled
336
+ */
337
+ prefersReducedMotion() {
338
+ if (typeof window === 'undefined')
339
+ return false;
340
+ try {
341
+ return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
342
+ }
343
+ catch (_a) {
344
+ return false;
345
+ }
346
+ }
347
+ /**
348
+ * Check if dark mode is preferred
349
+ */
350
+ prefersDarkMode() {
351
+ if (typeof window === 'undefined')
352
+ return false;
353
+ try {
354
+ return window.matchMedia('(prefers-color-scheme: dark)').matches;
355
+ }
356
+ catch (_a) {
357
+ return false;
358
+ }
359
+ }
360
+ /**
361
+ * Get the current device orientation
362
+ */
363
+ getOrientation() {
364
+ if (typeof window === 'undefined')
365
+ return 'portrait';
366
+ return window.innerHeight > window.innerWidth ? 'portrait' : 'landscape';
367
+ }
368
+ /**
369
+ * Register a window resize listener
370
+ * @param id - Unique identifier
371
+ * @param handler - Callback with (width, height)
372
+ * @param debounceMs - Debounce delay in milliseconds
373
+ */
374
+ registerResizeListener(id, handler, debounceMs = 0) {
375
+ if (typeof window === 'undefined')
376
+ return;
377
+ let timeoutId = null;
378
+ const eventListener = () => {
379
+ if (timeoutId)
380
+ clearTimeout(timeoutId);
381
+ if (debounceMs > 0) {
382
+ timeoutId = setTimeout(() => {
383
+ handler(this.getViewportWidth(), this.getViewportHeight());
384
+ }, debounceMs);
385
+ }
386
+ else {
387
+ handler(this.getViewportWidth(), this.getViewportHeight());
388
+ }
49
389
  };
390
+ this.resizeListeners.set(id, { handler, eventListener });
391
+ window.addEventListener('resize', eventListener);
392
+ // Call handler with initial dimensions
393
+ handler(this.getViewportWidth(), this.getViewportHeight());
50
394
  }
51
395
  /**
52
- * Initialize internal checked state from defaultChecked
396
+ * Unregister a resize listener
53
397
  */
54
- componentWillLoad() {
55
- this.internalChecked = this.defaultChecked;
398
+ unregisterResizeListener(id) {
399
+ if (typeof window === 'undefined')
400
+ return;
401
+ const entry = this.resizeListeners.get(id);
402
+ if (entry) {
403
+ window.removeEventListener('resize', entry.eventListener);
404
+ this.resizeListeners.delete(id);
405
+ }
56
406
  }
57
407
  /**
58
- * Get current checked state (controlled vs uncontrolled)
408
+ * Clean up all listeners
59
409
  */
60
- get isChecked() {
61
- return this.checked !== undefined ? this.checked : this.internalChecked;
410
+ cleanup() {
411
+ this.listeners.forEach((listener) => {
412
+ if (listener.matcher) {
413
+ listener.matcher.removeEventListener('change', () => { });
414
+ }
415
+ });
416
+ this.listeners.clear();
417
+ if (typeof window !== 'undefined') {
418
+ this.resizeListeners.forEach((entry) => {
419
+ window.removeEventListener('resize', entry.eventListener);
420
+ });
421
+ }
422
+ this.resizeListeners.clear();
423
+ if (this.resizeObserver) {
424
+ this.resizeObserver.disconnect();
425
+ this.resizeObserver = null;
426
+ }
62
427
  }
63
428
  /**
64
- * Handle keyboard events (Space and Enter keys)
429
+ * Update breakpoint configuration
65
430
  */
66
- handleKeyDown(event) {
67
- if (this.disabled) {
431
+ setBreakpoints(breakpoints) {
432
+ this.breakpoints = Object.assign(Object.assign({}, DEFAULT_BREAKPOINTS), breakpoints);
433
+ }
434
+ }
435
+ // Singleton instance
436
+ let mediaQueryServiceInstance = null;
437
+ /**
438
+ * Get the singleton MediaQueryService instance
439
+ */
440
+ function getMediaQueryService(breakpoints) {
441
+ if (!mediaQueryServiceInstance) {
442
+ mediaQueryServiceInstance = new MediaQueryService(breakpoints);
443
+ }
444
+ return mediaQueryServiceInstance;
445
+ }
446
+ /**
447
+ * Create a new isolated MediaQueryService instance
448
+ */
449
+ function createMediaQueryService(breakpoints) {
450
+ return new MediaQueryService(breakpoints || DEFAULT_BREAKPOINTS);
451
+ }
452
+
453
+ /**
454
+ * Common Utilities
455
+ * Shared utility functions used across the component library
456
+ */
457
+ /* eslint-disable no-undef, @typescript-eslint/no-explicit-any */
458
+ let idCounter = 0;
459
+ /**
460
+ * Generate a unique ID with optional prefix
461
+ * @param prefix - Optional prefix for the ID (default: 'id')
462
+ */
463
+ function generateUniqueId(prefix = 'id') {
464
+ return `${prefix}-${++idCounter}-${Math.random().toString(36).substr(2, 9)}`;
465
+ }
466
+ /**
467
+ * Reset ID counter (useful for testing)
468
+ */
469
+ function resetIdCounter() {
470
+ idCounter = 0;
471
+ }
472
+ /**
473
+ * Debounce a function
474
+ * @param fn - Function to debounce
475
+ * @param delay - Delay in milliseconds
476
+ */
477
+ function debounce(fn, delay) {
478
+ let timeoutId = null;
479
+ return (...args) => {
480
+ if (timeoutId)
481
+ clearTimeout(timeoutId);
482
+ timeoutId = setTimeout(() => fn(...args), delay);
483
+ };
484
+ }
485
+ /**
486
+ * Throttle a function
487
+ * @param fn - Function to throttle
488
+ * @param delay - Delay in milliseconds
489
+ */
490
+ function throttle(fn, delay) {
491
+ let lastCall = 0;
492
+ let timeoutId = null;
493
+ return (...args) => {
494
+ const now = Date.now();
495
+ if (now - lastCall >= delay) {
496
+ lastCall = now;
497
+ fn(...args);
498
+ }
499
+ else {
500
+ if (timeoutId)
501
+ clearTimeout(timeoutId);
502
+ timeoutId = setTimeout(() => {
503
+ lastCall = Date.now();
504
+ fn(...args);
505
+ }, delay - (now - lastCall));
506
+ }
507
+ };
508
+ }
509
+ /**
510
+ * Add a class to an element
511
+ * @param element - The element
512
+ * @param className - Class name to add
513
+ */
514
+ function addClass(element, className) {
515
+ element.classList.add(className);
516
+ }
517
+ /**
518
+ * Remove a class from an element
519
+ * @param element - The element
520
+ * @param className - Class name to remove
521
+ */
522
+ function removeClass(element, className) {
523
+ element.classList.remove(className);
524
+ }
525
+ /**
526
+ * Toggle a class on an element
527
+ * @param element - The element
528
+ * @param className - Class name to toggle
529
+ * @param force - Optional force add/remove
530
+ */
531
+ function toggleClass(element, className, force) {
532
+ element.classList.toggle(className, force);
533
+ }
534
+ /**
535
+ * Check if element has a class
536
+ * @param element - The element
537
+ * @param className - Class name to check
538
+ */
539
+ function hasClass(element, className) {
540
+ return element.classList.contains(className);
541
+ }
542
+ /**
543
+ * Get all data attributes from an element as an object
544
+ */
545
+ function getDataAttributes(element) {
546
+ const data = {};
547
+ Array.from(element.attributes).forEach((attr) => {
548
+ if (attr.name.startsWith('data-')) {
549
+ const key = attr.name.slice(5); // Remove 'data-' prefix
550
+ data[key] = attr.value;
551
+ }
552
+ });
553
+ return data;
554
+ }
555
+ /**
556
+ * Set a data attribute on an element
557
+ * @param element - The element
558
+ * @param key - Data attribute name (without 'data-' prefix)
559
+ * @param value - The value to set
560
+ */
561
+ function setDataAttribute(element, key, value) {
562
+ if (value === null) {
563
+ element.removeAttribute(`data-${key}`);
564
+ }
565
+ else {
566
+ element.setAttribute(`data-${key}`, value);
567
+ }
568
+ }
569
+ /**
570
+ * Get the value of a data attribute
571
+ * @param element - The element
572
+ * @param key - Data attribute name (without 'data-' prefix)
573
+ */
574
+ function getDataAttribute(element, key) {
575
+ return element.getAttribute(`data-${key}`) || undefined;
576
+ }
577
+ /**
578
+ * Dispatch a custom event from an element
579
+ * @param element - The element to dispatch from
580
+ * @param eventName - Name of the custom event
581
+ * @param detail - Optional detail object to include in the event
582
+ */
583
+ function dispatchCustomEvent(element, eventName, detail) {
584
+ const event = new CustomEvent(eventName, {
585
+ detail,
586
+ bubbles: true,
587
+ cancelable: true,
588
+ composed: true,
589
+ });
590
+ element.dispatchEvent(event);
591
+ }
592
+ /**
593
+ * Listen for a custom event
594
+ * @param element - The element to listen on
595
+ * @param eventName - Name of the custom event
596
+ * @param handler - Callback function
597
+ * @returns Cleanup function to remove listener
598
+ */
599
+ function onCustomEvent(element, eventName, handler) {
600
+ const listener = (event) => {
601
+ handler(event.detail);
602
+ };
603
+ element.addEventListener(eventName, listener);
604
+ return () => {
605
+ element.removeEventListener(eventName, listener);
606
+ };
607
+ }
608
+ /**
609
+ * Get the offset position of an element relative to the viewport
610
+ */
611
+ function getElementOffset(element) {
612
+ const rect = element.getBoundingClientRect();
613
+ return {
614
+ top: rect.top + window.scrollY,
615
+ left: rect.left + window.scrollX,
616
+ };
617
+ }
618
+ /**
619
+ * Check if an element is in the viewport
620
+ */
621
+ function isElementInViewport(element) {
622
+ const rect = element.getBoundingClientRect();
623
+ return rect.top < window.innerHeight && rect.bottom > 0 && rect.left < window.innerWidth && rect.right > 0;
624
+ }
625
+ /**
626
+ * Scroll element into view
627
+ * @param element - The element to scroll into view
628
+ * @param options - Scroll behavior options
629
+ */
630
+ function scrollIntoView(element, options = {}) {
631
+ element.scrollIntoView(Object.assign({ behavior: 'smooth', block: 'nearest', inline: 'nearest' }, options));
632
+ }
633
+ /**
634
+ * Get computed style value
635
+ */
636
+ function getComputedValue(element, property) {
637
+ return window.getComputedStyle(element).getPropertyValue(property);
638
+ }
639
+ /**
640
+ * Wait for a specific time
641
+ * @param ms - Time in milliseconds
642
+ */
643
+ function wait(ms) {
644
+ return new Promise((resolve) => setTimeout(resolve, ms));
645
+ }
646
+ /**
647
+ * Wait for an element to appear in the DOM
648
+ * @param selector - CSS selector to wait for
649
+ * @param timeout - Timeout in milliseconds (default: 5000)
650
+ */
651
+ function waitForElement(selector, timeout = 5000) {
652
+ return new Promise((resolve, reject) => {
653
+ const element = document.querySelector(selector);
654
+ if (element) {
655
+ resolve(element);
68
656
  return;
69
657
  }
70
- // Toggle on Space or Enter
71
- if (event.key === ' ' || event.key === 'Enter') {
72
- event.preventDefault(); // Prevent page scroll on Space
73
- this.toggle();
658
+ const observer = new MutationObserver(() => {
659
+ const el = document.querySelector(selector);
660
+ if (el) {
661
+ observer.disconnect();
662
+ resolve(el);
663
+ }
664
+ });
665
+ observer.observe(document.body, { childList: true, subtree: true });
666
+ setTimeout(() => {
667
+ observer.disconnect();
668
+ reject(new Error(`Element "${selector}" not found within ${timeout}ms`));
669
+ }, timeout);
670
+ });
671
+ }
672
+ /**
673
+ * Clone an object deeply
674
+ */
675
+ function deepClone(obj) {
676
+ if (obj === null || typeof obj !== 'object')
677
+ return obj;
678
+ if (obj instanceof Date)
679
+ return new Date(obj.getTime());
680
+ if (obj instanceof Array)
681
+ return obj.map((item) => deepClone(item));
682
+ if (obj instanceof Object) {
683
+ const cloned = {};
684
+ Object.keys(obj).forEach((key) => {
685
+ cloned[key] = deepClone(obj[key]);
686
+ });
687
+ return cloned;
688
+ }
689
+ return obj;
690
+ }
691
+ /**
692
+ * Merge objects
693
+ */
694
+ function mergeObjects(target, ...sources) {
695
+ return sources.reduce((result, source) => (Object.assign(Object.assign({}, result), source)), target);
696
+ }
697
+ /**
698
+ * Get the prefixed CSS property name (for vendor prefixes)
699
+ */
700
+ function getPrefixedProperty(property) {
701
+ const element = document.createElement('div');
702
+ const style = element.style;
703
+ if (property in style)
704
+ return property;
705
+ if (`webkit${property[0].toUpperCase()}${property.slice(1)}` in style)
706
+ return `webkit${property[0].toUpperCase()}${property.slice(1)}`;
707
+ if (`moz${property[0].toUpperCase()}${property.slice(1)}` in style)
708
+ return `moz${property[0].toUpperCase()}${property.slice(1)}`;
709
+ if (`ms${property[0].toUpperCase()}${property.slice(1)}` in style)
710
+ return `ms${property[0].toUpperCase()}${property.slice(1)}`;
711
+ return property;
712
+ }
713
+ /**
714
+ * Check if browser supports a CSS feature
715
+ */
716
+ function supportsCSSFeature(property, value) {
717
+ const element = document.createElement('div');
718
+ element.style.setProperty(property, value);
719
+ return element.style.getPropertyValue(property) !== '';
720
+ }
721
+ /**
722
+ * Request animation frame with promise
723
+ */
724
+ function requestAnimationFramePromise() {
725
+ return new Promise((resolve) => requestAnimationFrame(resolve));
726
+ }
727
+ /**
728
+ * Convert camelCase to kebab-case
729
+ */
730
+ function camelToKebab(str) {
731
+ return str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
732
+ }
733
+ /**
734
+ * Convert kebab-case to camelCase
735
+ */
736
+ function kebabToCamel(str) {
737
+ return str.replace(/-./g, (x) => x[1].toUpperCase());
738
+ }
739
+
740
+ /**
741
+ * Accessibility Utilities
742
+ * Provides helpers for ARIA attributes, keyboard navigation, and accessibility features
743
+ */
744
+ /**
745
+ * Generate a unique ID for ARIA relationships
746
+ * @param prefix - Optional prefix for the ID
747
+ * @param suffix - Optional suffix for the ID
748
+ */
749
+ function generateAriaId(prefix = 'aria', suffix) {
750
+ const timestamp = Date.now().toString(36);
751
+ const random = Math.random().toString(36).substr(2, 9);
752
+ const finalSuffix = suffix ? `-${suffix}` : '';
753
+ return `${prefix}-${timestamp}-${random}${finalSuffix}`;
754
+ }
755
+ /**
756
+ * Set ARIA attributes on an element
757
+ * @param element - The element to set attributes on
758
+ * @param attributes - Object with attribute names and values
759
+ */
760
+ function setAriaAttributes(element, attributes) {
761
+ Object.entries(attributes).forEach(([key, value]) => {
762
+ if (value === null || value === false) {
763
+ element.removeAttribute(`aria-${key}`);
764
+ }
765
+ else if (value === true) {
766
+ element.setAttribute(`aria-${key}`, 'true');
767
+ }
768
+ else {
769
+ element.setAttribute(`aria-${key}`, String(value));
74
770
  }
771
+ });
772
+ }
773
+ /**
774
+ * Add accessible label to an element
775
+ * @param element - The element to label
776
+ * @param label - The label text or element ID
777
+ * @param useAriaLabel - If true, uses aria-label; if false, uses aria-labelledby
778
+ */
779
+ function addAriaLabel(element, label, useAriaLabel = true) {
780
+ if (useAriaLabel) {
781
+ element.setAttribute('aria-label', label);
75
782
  }
76
- render() {
77
- const isChecked = this.isChecked;
78
- const dataState = isChecked ? 'checked' : 'unchecked';
79
- return (h(Host, { key: '3046a6647d7cfd10bf9789aa9cf3b7a88b9a3a10', "data-state": dataState, "data-disabled": this.disabled ? '' : null }, h("div", { key: 'cd8423b9f7295e5e3ef9d7e64ead3fe6502386a2', class: "switch", part: "switch", role: "switch", "aria-checked": isChecked ? 'true' : 'false', "aria-disabled": this.disabled ? 'true' : undefined, "aria-label": this.ariaLabel || undefined, "aria-required": this.required ? 'true' : undefined, tabindex: this.disabled ? -1 : 0, onClick: this.handleClick }, h("span", { key: '618ab67d5fab80323f64ec0b1b342561be2585b0', class: "thumb", part: "thumb" })), this.name && (h("input", { key: 'd51e9108038b8796175082231ca3ce7e61106f31', type: "checkbox", name: this.name, value: this.value, checked: isChecked, required: this.required, disabled: this.disabled, style: { display: 'none' }, tabindex: -1, "aria-hidden": "true" }))));
783
+ else {
784
+ element.setAttribute('aria-labelledby', label);
80
785
  }
81
- };
82
- SekiSwitch.style = sekiSwitchCss;
786
+ }
787
+ /**
788
+ * Add accessible description to an element
789
+ * @param element - The element to describe
790
+ * @param description - The description text or element ID
791
+ * @param useAriaDescription - If true, uses aria-description; if false, uses aria-describedby
792
+ */
793
+ function addAriaDescription(element, description, useAriaDescription = false) {
794
+ if (useAriaDescription) {
795
+ element.setAttribute('aria-description', description);
796
+ }
797
+ else {
798
+ element.setAttribute('aria-describedby', description);
799
+ }
800
+ }
801
+ /**
802
+ * Set ARIA live region announcement
803
+ * @param element - The element to make a live region
804
+ * @param message - The message to announce
805
+ * @param politeness - 'polite' (default), 'assertive', or 'off'
806
+ * @param atomic - Whether to announce the entire region
807
+ */
808
+ function announceAriaLive(element, message, politeness = 'polite', atomic = false) {
809
+ element.setAttribute('aria-live', politeness);
810
+ if (atomic) {
811
+ element.setAttribute('aria-atomic', 'true');
812
+ }
813
+ element.textContent = message;
814
+ }
815
+ /**
816
+ * Mark an element as disabled with ARIA attributes
817
+ * @param element - The element to mark as disabled
818
+ * @param disabled - Whether the element is disabled
819
+ */
820
+ function setAriaDisabled(element, disabled) {
821
+ if (disabled) {
822
+ element.setAttribute('aria-disabled', 'true');
823
+ element.style.pointerEvents = 'none';
824
+ element.style.opacity = '0.5';
825
+ }
826
+ else {
827
+ element.removeAttribute('aria-disabled');
828
+ element.style.pointerEvents = '';
829
+ element.style.opacity = '';
830
+ }
831
+ }
832
+ /**
833
+ * Mark an element as expanded/collapsed (for collapsible sections)
834
+ * @param element - The element to mark
835
+ * @param expanded - Whether the element is expanded
836
+ * @param targetId - ID of the element being controlled (optional)
837
+ */
838
+ function setAriaExpanded(element, expanded, targetId) {
839
+ element.setAttribute('aria-expanded', expanded ? 'true' : 'false');
840
+ if (targetId) {
841
+ element.setAttribute('aria-controls', targetId);
842
+ }
843
+ }
844
+ /**
845
+ * Mark an element as selected
846
+ * @param element - The element to mark
847
+ * @param selected - Whether the element is selected
848
+ */
849
+ function setAriaSelected(element, selected) {
850
+ element.setAttribute('aria-selected', selected ? 'true' : 'false');
851
+ }
852
+ /**
853
+ * Mark an element as checked (for checkboxes and radio buttons)
854
+ * @param element - The element to mark
855
+ * @param checked - The checked state ('true', 'false', or 'mixed')
856
+ */
857
+ function setAriaChecked(element, checked) {
858
+ element.setAttribute('aria-checked', checked);
859
+ }
860
+ /**
861
+ * Set the current value of an element (for sliders, spinbuttons, etc.)
862
+ * @param element - The element
863
+ * @param current - Current value
864
+ * @param min - Minimum value
865
+ * @param max - Maximum value
866
+ * @param text - Optional text description of the value
867
+ */
868
+ function setAriaValueNow(element, current, min, max, text) {
869
+ element.setAttribute('aria-valuenow', String(current));
870
+ if (min !== undefined)
871
+ element.setAttribute('aria-valuemin', String(min));
872
+ if (max !== undefined)
873
+ element.setAttribute('aria-valuemax', String(max));
874
+ if (text !== undefined)
875
+ element.setAttribute('aria-valuetext', text);
876
+ }
877
+ /**
878
+ * Mark an element as having a popup (for menus, popovers, etc.)
879
+ * @param element - The element with the popup trigger
880
+ * @param type - Type of popup: 'menu', 'listbox', 'tree', 'grid', 'dialog'
881
+ * @param popupId - ID of the popup element
882
+ */
883
+ function setAriaPopup(element, type = 'menu', popupId) {
884
+ element.setAttribute('aria-haspopup', type);
885
+ if (popupId) {
886
+ element.setAttribute('aria-owns', popupId);
887
+ }
888
+ }
889
+ /**
890
+ * Set role for an element
891
+ * @param element - The element
892
+ * @param role - The role (button, menu, menuitem, etc.)
893
+ */
894
+ function setRole(element, role) {
895
+ element.setAttribute('role', role);
896
+ }
897
+ /**
898
+ * Get the accessible name of an element
899
+ * Follows ARIA naming convention: aria-labelledby > aria-label > title > textContent
900
+ */
901
+ function getAccessibleName(element) {
902
+ // Check aria-labelledby
903
+ const labelledby = element.getAttribute('aria-labelledby');
904
+ if (labelledby) {
905
+ const labelElement = document.getElementById(labelledby);
906
+ if (labelElement)
907
+ return labelElement.textContent || '';
908
+ }
909
+ // Check aria-label
910
+ const ariaLabel = element.getAttribute('aria-label');
911
+ if (ariaLabel)
912
+ return ariaLabel;
913
+ // Check title
914
+ const title = element.getAttribute('title');
915
+ if (title)
916
+ return title;
917
+ // Fall back to textContent
918
+ return element.textContent || '';
919
+ }
920
+ /**
921
+ * Create a skip link for keyboard navigation
922
+ * @param text - Link text
923
+ * @param targetId - ID of element to skip to
924
+ */
925
+ function createSkipLink(text, targetId) {
926
+ const link = document.createElement('a');
927
+ link.href = `#${targetId}`;
928
+ link.textContent = text;
929
+ link.className = 'sr-only'; // Visually hidden but accessible to screen readers
930
+ link.style.position = 'absolute';
931
+ link.style.top = '-9999px';
932
+ link.style.left = '-9999px';
933
+ // Show on focus
934
+ link.addEventListener('focus', () => {
935
+ link.style.top = '0';
936
+ link.style.left = '0';
937
+ });
938
+ // Hide on blur
939
+ link.addEventListener('blur', () => {
940
+ link.style.top = '-9999px';
941
+ link.style.left = '-9999px';
942
+ });
943
+ return link;
944
+ }
945
+ /**
946
+ * Check if element should be hidden from screen readers
947
+ */
948
+ function isAriaHidden(element) {
949
+ return element.getAttribute('aria-hidden') === 'true';
950
+ }
951
+ /**
952
+ * Hide element from screen readers but keep visually visible
953
+ */
954
+ function setAriaHidden(element, hidden) {
955
+ if (hidden) {
956
+ element.setAttribute('aria-hidden', 'true');
957
+ }
958
+ else {
959
+ element.removeAttribute('aria-hidden');
960
+ }
961
+ }
962
+ /**
963
+ * Announce a message to screen readers immediately (without ARIA live regions)
964
+ * @param message - The message to announce
965
+ * @param politeness - 'polite' (default) or 'assertive'
966
+ */
967
+ function announceToScreenReader(message, politeness = 'polite') {
968
+ if (typeof document === 'undefined')
969
+ return;
970
+ const announcement = document.createElement('div');
971
+ announcement.setAttribute('aria-live', politeness);
972
+ announcement.setAttribute('aria-atomic', 'true');
973
+ announcement.className = 'sr-only';
974
+ announcement.style.position = 'absolute';
975
+ announcement.style.left = '-9999px';
976
+ announcement.style.top = '-9999px';
977
+ announcement.textContent = message;
978
+ document.body.appendChild(announcement);
979
+ // Remove after announcement is made
980
+ setTimeout(() => {
981
+ announcement.remove();
982
+ }, 1000);
983
+ }
984
+ /**
985
+ * Set proper heading hierarchy
986
+ * @param element - The heading element
987
+ * @param level - Heading level (1-6)
988
+ */
989
+ function setHeadingLevel(element, level) {
990
+ const tag = `h${level}`;
991
+ if (element.tagName.toLowerCase() !== tag) {
992
+ // If element is not correct tag, set role as fallback
993
+ element.setAttribute('role', tag);
994
+ }
995
+ }
996
+ /**
997
+ * Enable keyboard navigation for a custom component
998
+ * @param element - The element that should handle keyboard
999
+ * @param keys - Map of key to handler function
1000
+ */
1001
+ function enableKeyboardNavigation(element, keys) {
1002
+ const handleKeyDown = (event) => {
1003
+ const handler = keys[event.key.toLowerCase()];
1004
+ if (handler) {
1005
+ event.preventDefault();
1006
+ handler(event);
1007
+ }
1008
+ };
1009
+ element.addEventListener('keydown', handleKeyDown);
1010
+ // Return cleanup function
1011
+ return () => {
1012
+ element.removeEventListener('keydown', handleKeyDown);
1013
+ };
1014
+ }
1015
+ /**
1016
+ * Check if element has accessible focus styling
1017
+ */
1018
+ function hasAccessibleFocus(element) {
1019
+ const styles = window.getComputedStyle(element);
1020
+ return !!(styles.outline || styles.boxShadow || styles.border);
1021
+ }
1022
+ /**
1023
+ * Ensure focus visible styling (for focus-visible pseudo-class)
1024
+ */
1025
+ function ensureFocusVisible(element) {
1026
+ if (!hasAccessibleFocus(element)) {
1027
+ element.style.outline = '2px solid #4A90E2';
1028
+ element.style.outlineOffset = '2px';
1029
+ }
1030
+ }
1031
+
1032
+ /**
1033
+ * SekiUI Type Definitions
1034
+ * Central export point for all type definitions across components and services
1035
+ */
1036
+ // ============================================================================
1037
+ // NOTE: Types from ./components/sidebar/types and ./utils/select/types
1038
+ // are already re-exported at the top of this file via the main index.ts
1039
+ // ============================================================================
1040
+ // ============================================================================
1041
+ // TYPE GUARDS AND UTILITY TYPES
1042
+ // ============================================================================
1043
+ /**
1044
+ * Type guard to check if a value is a valid sidebar variant
1045
+ */
1046
+ function isSidebarVariant(value) {
1047
+ return ['sidebar', 'floating', 'inset'].includes(value);
1048
+ }
1049
+ /**
1050
+ * Type guard to check if a value is a valid collapse mode
1051
+ */
1052
+ function isCollapseMode(value) {
1053
+ return ['offcanvas', 'icon', 'none'].includes(value);
1054
+ }
1055
+ /**
1056
+ * Type guard to check if a value is a valid button size
1057
+ */
1058
+ function isButtonSize(value) {
1059
+ return ['sm', 'md', 'lg', 'icon-sm', 'icon', 'icon-lg'].includes(value);
1060
+ }
1061
+ /**
1062
+ * Type guard to check if a value is a valid button variant
1063
+ */
1064
+ function isButtonVariant(value) {
1065
+ return ['primary', 'secondary', 'outline', 'ghost', 'destructive', 'link'].includes(value);
1066
+ }
1067
+ /**
1068
+ * Type guard to check if a value is a valid tooltip side
1069
+ */
1070
+ function isTooltipSide(value) {
1071
+ return ['top', 'right', 'bottom', 'left'].includes(value);
1072
+ }
83
1073
 
84
- export { SekiSwitch };
1074
+ export { DEFAULT_BREAKPOINTS, FocusService, MediaQueryService, addAriaDescription, addAriaLabel, addClass, announceAriaLive, announceToScreenReader, camelToKebab, createFocusService, createMediaQueryService, createSkipLink, debounce, deepClone, dispatchCustomEvent, enableKeyboardNavigation, ensureFocusVisible, generateAriaId, generateUniqueId, getAccessibleName, getComputedValue, getDataAttribute, getDataAttributes, getElementOffset, getFocusService, getMediaQueryService, getPrefixedProperty, hasAccessibleFocus, hasClass, isAriaHidden, isButtonSize, isButtonVariant, isCollapseMode, isElementInViewport, isSidebarVariant, isTooltipSide, kebabToCamel, mergeObjects, onCustomEvent, removeClass, requestAnimationFramePromise, resetIdCounter, scrollIntoView, setAriaAttributes, setAriaChecked, setAriaDisabled, setAriaExpanded, setAriaHidden, setAriaPopup, setAriaSelected, setAriaValueNow, setDataAttribute, setHeadingLevel, setRole, supportsCSSFeature, throttle, toggleClass, wait, waitForElement };