@easemate/web-kit 0.1.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 (358) hide show
  1. package/README.md +824 -0
  2. package/build/components/code/index.cjs +152 -0
  3. package/build/components/code/index.d.cts +11 -0
  4. package/build/components/code/index.d.ts +11 -0
  5. package/build/components/code/index.js +148 -0
  6. package/build/components/code/utils/highlight-api.cjs +18 -0
  7. package/build/components/code/utils/highlight-api.d.cts +7 -0
  8. package/build/components/code/utils/highlight-api.d.ts +7 -0
  9. package/build/components/code/utils/highlight-api.js +14 -0
  10. package/build/components/code/utils/syntax-grammars.cjs +62 -0
  11. package/build/components/code/utils/syntax-grammars.d.cts +7 -0
  12. package/build/components/code/utils/syntax-grammars.d.ts +7 -0
  13. package/build/components/code/utils/syntax-grammars.js +59 -0
  14. package/build/components/code/utils/syntax-highlighter-theme.cjs +27 -0
  15. package/build/components/code/utils/syntax-highlighter-theme.d.cts +3 -0
  16. package/build/components/code/utils/syntax-highlighter-theme.d.ts +3 -0
  17. package/build/components/code/utils/syntax-highlighter-theme.js +23 -0
  18. package/build/components/code/utils/syntax-highlighter-types.cjs +2 -0
  19. package/build/components/code/utils/syntax-highlighter-types.d.cts +12 -0
  20. package/build/components/code/utils/syntax-highlighter-types.d.ts +12 -0
  21. package/build/components/code/utils/syntax-highlighter-types.js +1 -0
  22. package/build/components/code/utils/syntax-tokenizer.cjs +63 -0
  23. package/build/components/code/utils/syntax-tokenizer.d.cts +3 -0
  24. package/build/components/code/utils/syntax-tokenizer.d.ts +3 -0
  25. package/build/components/code/utils/syntax-tokenizer.js +58 -0
  26. package/build/components/curve/bezier-conversion.cjs +23 -0
  27. package/build/components/curve/bezier-conversion.d.cts +2 -0
  28. package/build/components/curve/bezier-conversion.d.ts +2 -0
  29. package/build/components/curve/bezier-conversion.js +19 -0
  30. package/build/components/curve/canvas-controls.cjs +300 -0
  31. package/build/components/curve/canvas-controls.d.cts +12 -0
  32. package/build/components/curve/canvas-controls.d.ts +12 -0
  33. package/build/components/curve/canvas-controls.js +296 -0
  34. package/build/components/curve/canvas.cjs +1208 -0
  35. package/build/components/curve/canvas.d.cts +24 -0
  36. package/build/components/curve/canvas.d.ts +24 -0
  37. package/build/components/curve/canvas.js +1204 -0
  38. package/build/components/curve/constants.cjs +203 -0
  39. package/build/components/curve/constants.d.cts +23 -0
  40. package/build/components/curve/constants.d.ts +23 -0
  41. package/build/components/curve/constants.js +200 -0
  42. package/build/components/curve/controls.cjs +942 -0
  43. package/build/components/curve/controls.d.cts +37 -0
  44. package/build/components/curve/controls.d.ts +37 -0
  45. package/build/components/curve/controls.js +938 -0
  46. package/build/components/curve/index.cjs +335 -0
  47. package/build/components/curve/index.d.cts +31 -0
  48. package/build/components/curve/index.d.ts +31 -0
  49. package/build/components/curve/index.js +330 -0
  50. package/build/components/curve/output.cjs +141 -0
  51. package/build/components/curve/output.d.cts +19 -0
  52. package/build/components/curve/output.d.ts +19 -0
  53. package/build/components/curve/output.js +137 -0
  54. package/build/components/curve/styles.cjs +493 -0
  55. package/build/components/curve/styles.d.cts +6 -0
  56. package/build/components/curve/styles.d.ts +6 -0
  57. package/build/components/curve/styles.js +490 -0
  58. package/build/components/curve/svg-renderer.cjs +185 -0
  59. package/build/components/curve/svg-renderer.d.cts +9 -0
  60. package/build/components/curve/svg-renderer.d.ts +9 -0
  61. package/build/components/curve/svg-renderer.js +175 -0
  62. package/build/components/curve/toolbar.cjs +368 -0
  63. package/build/components/curve/toolbar.d.cts +26 -0
  64. package/build/components/curve/toolbar.d.ts +26 -0
  65. package/build/components/curve/toolbar.js +364 -0
  66. package/build/components/curve/types.cjs +10 -0
  67. package/build/components/curve/types.d.cts +33 -0
  68. package/build/components/curve/types.d.ts +33 -0
  69. package/build/components/curve/types.js +7 -0
  70. package/build/components/curve/utils.cjs +541 -0
  71. package/build/components/curve/utils.d.cts +33 -0
  72. package/build/components/curve/utils.d.ts +33 -0
  73. package/build/components/curve/utils.js +521 -0
  74. package/build/components/index.cjs +18 -0
  75. package/build/components/index.d.cts +2 -0
  76. package/build/components/index.d.ts +2 -0
  77. package/build/components/index.js +2 -0
  78. package/build/decorators/Component.cjs +127 -0
  79. package/build/decorators/Component.d.cts +28 -0
  80. package/build/decorators/Component.d.ts +28 -0
  81. package/build/decorators/Component.js +123 -0
  82. package/build/decorators/Listen.cjs +154 -0
  83. package/build/decorators/Listen.d.cts +18 -0
  84. package/build/decorators/Listen.d.ts +18 -0
  85. package/build/decorators/Listen.js +151 -0
  86. package/build/decorators/OutsideClick.cjs +64 -0
  87. package/build/decorators/OutsideClick.d.cts +16 -0
  88. package/build/decorators/OutsideClick.d.ts +16 -0
  89. package/build/decorators/OutsideClick.js +59 -0
  90. package/build/decorators/Prop.cjs +273 -0
  91. package/build/decorators/Prop.d.cts +22 -0
  92. package/build/decorators/Prop.d.ts +22 -0
  93. package/build/decorators/Prop.js +270 -0
  94. package/build/decorators/Query.cjs +79 -0
  95. package/build/decorators/Query.d.cts +27 -0
  96. package/build/decorators/Query.d.ts +27 -0
  97. package/build/decorators/Query.js +76 -0
  98. package/build/decorators/Watch.cjs +52 -0
  99. package/build/decorators/Watch.d.cts +11 -0
  100. package/build/decorators/Watch.d.ts +11 -0
  101. package/build/decorators/Watch.js +49 -0
  102. package/build/decorators/index.cjs +15 -0
  103. package/build/decorators/index.d.cts +6 -0
  104. package/build/decorators/index.d.ts +6 -0
  105. package/build/decorators/index.js +6 -0
  106. package/build/elements/button/index.cjs +214 -0
  107. package/build/elements/button/index.d.cts +11 -0
  108. package/build/elements/button/index.d.ts +11 -0
  109. package/build/elements/button/index.js +210 -0
  110. package/build/elements/checkbox/index.cjs +316 -0
  111. package/build/elements/checkbox/index.d.cts +14 -0
  112. package/build/elements/checkbox/index.d.ts +14 -0
  113. package/build/elements/checkbox/index.js +312 -0
  114. package/build/elements/color/index.cjs +154 -0
  115. package/build/elements/color/index.d.cts +18 -0
  116. package/build/elements/color/index.d.ts +18 -0
  117. package/build/elements/color/index.js +150 -0
  118. package/build/elements/color/picker.cjs +544 -0
  119. package/build/elements/color/picker.d.cts +37 -0
  120. package/build/elements/color/picker.d.ts +37 -0
  121. package/build/elements/color/picker.js +540 -0
  122. package/build/elements/color/utils.cjs +235 -0
  123. package/build/elements/color/utils.d.cts +37 -0
  124. package/build/elements/color/utils.d.ts +37 -0
  125. package/build/elements/color/utils.js +218 -0
  126. package/build/elements/dropdown/index.cjs +875 -0
  127. package/build/elements/dropdown/index.d.cts +30 -0
  128. package/build/elements/dropdown/index.d.ts +30 -0
  129. package/build/elements/dropdown/index.js +871 -0
  130. package/build/elements/field/index.cjs +82 -0
  131. package/build/elements/field/index.d.cts +4 -0
  132. package/build/elements/field/index.d.ts +4 -0
  133. package/build/elements/field/index.js +78 -0
  134. package/build/elements/icons/animation/chevron.cjs +57 -0
  135. package/build/elements/icons/animation/chevron.d.cts +10 -0
  136. package/build/elements/icons/animation/chevron.d.ts +10 -0
  137. package/build/elements/icons/animation/chevron.js +53 -0
  138. package/build/elements/icons/animation/clear.cjs +74 -0
  139. package/build/elements/icons/animation/clear.d.cts +3 -0
  140. package/build/elements/icons/animation/clear.d.ts +3 -0
  141. package/build/elements/icons/animation/clear.js +70 -0
  142. package/build/elements/icons/animation/grid.cjs +77 -0
  143. package/build/elements/icons/animation/grid.d.cts +8 -0
  144. package/build/elements/icons/animation/grid.d.ts +8 -0
  145. package/build/elements/icons/animation/grid.js +73 -0
  146. package/build/elements/icons/animation/loading.cjs +68 -0
  147. package/build/elements/icons/animation/loading.d.cts +3 -0
  148. package/build/elements/icons/animation/loading.d.ts +3 -0
  149. package/build/elements/icons/animation/loading.js +64 -0
  150. package/build/elements/icons/animation/snap.cjs +133 -0
  151. package/build/elements/icons/animation/snap.d.cts +8 -0
  152. package/build/elements/icons/animation/snap.d.ts +8 -0
  153. package/build/elements/icons/animation/snap.js +129 -0
  154. package/build/elements/icons/index.cjs +40 -0
  155. package/build/elements/icons/index.d.cts +24 -0
  156. package/build/elements/icons/index.d.ts +24 -0
  157. package/build/elements/icons/index.js +24 -0
  158. package/build/elements/icons/interface/anchor-add.cjs +35 -0
  159. package/build/elements/icons/interface/anchor-add.d.cts +3 -0
  160. package/build/elements/icons/interface/anchor-add.d.ts +3 -0
  161. package/build/elements/icons/interface/anchor-add.js +31 -0
  162. package/build/elements/icons/interface/anchor-remove.cjs +34 -0
  163. package/build/elements/icons/interface/anchor-remove.d.cts +3 -0
  164. package/build/elements/icons/interface/anchor-remove.d.ts +3 -0
  165. package/build/elements/icons/interface/anchor-remove.js +30 -0
  166. package/build/elements/icons/interface/arrow-up.cjs +30 -0
  167. package/build/elements/icons/interface/arrow-up.d.cts +3 -0
  168. package/build/elements/icons/interface/arrow-up.d.ts +3 -0
  169. package/build/elements/icons/interface/arrow-up.js +26 -0
  170. package/build/elements/icons/interface/arrows-vertical.cjs +30 -0
  171. package/build/elements/icons/interface/arrows-vertical.d.cts +3 -0
  172. package/build/elements/icons/interface/arrows-vertical.d.ts +3 -0
  173. package/build/elements/icons/interface/arrows-vertical.js +26 -0
  174. package/build/elements/icons/interface/bezier-angle.cjs +33 -0
  175. package/build/elements/icons/interface/bezier-angle.d.cts +3 -0
  176. package/build/elements/icons/interface/bezier-angle.d.ts +3 -0
  177. package/build/elements/icons/interface/bezier-angle.js +29 -0
  178. package/build/elements/icons/interface/bezier-distribute.cjs +34 -0
  179. package/build/elements/icons/interface/bezier-distribute.d.cts +3 -0
  180. package/build/elements/icons/interface/bezier-distribute.d.ts +3 -0
  181. package/build/elements/icons/interface/bezier-distribute.js +30 -0
  182. package/build/elements/icons/interface/bezier-length.cjs +31 -0
  183. package/build/elements/icons/interface/bezier-length.d.cts +3 -0
  184. package/build/elements/icons/interface/bezier-length.d.ts +3 -0
  185. package/build/elements/icons/interface/bezier-length.js +27 -0
  186. package/build/elements/icons/interface/bezier-mirror.cjs +31 -0
  187. package/build/elements/icons/interface/bezier-mirror.d.cts +3 -0
  188. package/build/elements/icons/interface/bezier-mirror.d.ts +3 -0
  189. package/build/elements/icons/interface/bezier-mirror.js +27 -0
  190. package/build/elements/icons/interface/bezier.cjs +26 -0
  191. package/build/elements/icons/interface/bezier.d.cts +3 -0
  192. package/build/elements/icons/interface/bezier.d.ts +3 -0
  193. package/build/elements/icons/interface/bezier.js +22 -0
  194. package/build/elements/icons/interface/check.cjs +30 -0
  195. package/build/elements/icons/interface/check.d.cts +3 -0
  196. package/build/elements/icons/interface/check.d.ts +3 -0
  197. package/build/elements/icons/interface/check.js +26 -0
  198. package/build/elements/icons/interface/circle-arrow-left.cjs +30 -0
  199. package/build/elements/icons/interface/circle-arrow-left.d.cts +3 -0
  200. package/build/elements/icons/interface/circle-arrow-left.d.ts +3 -0
  201. package/build/elements/icons/interface/circle-arrow-left.js +26 -0
  202. package/build/elements/icons/interface/circle-arrow-right.cjs +30 -0
  203. package/build/elements/icons/interface/circle-arrow-right.d.cts +3 -0
  204. package/build/elements/icons/interface/circle-arrow-right.d.ts +3 -0
  205. package/build/elements/icons/interface/circle-arrow-right.js +26 -0
  206. package/build/elements/icons/interface/code.cjs +30 -0
  207. package/build/elements/icons/interface/code.d.cts +3 -0
  208. package/build/elements/icons/interface/code.d.ts +3 -0
  209. package/build/elements/icons/interface/code.js +26 -0
  210. package/build/elements/icons/interface/dots.cjs +32 -0
  211. package/build/elements/icons/interface/dots.d.cts +3 -0
  212. package/build/elements/icons/interface/dots.d.ts +3 -0
  213. package/build/elements/icons/interface/dots.js +28 -0
  214. package/build/elements/icons/interface/mention.cjs +30 -0
  215. package/build/elements/icons/interface/mention.d.cts +3 -0
  216. package/build/elements/icons/interface/mention.d.ts +3 -0
  217. package/build/elements/icons/interface/mention.js +26 -0
  218. package/build/elements/icons/interface/minus.cjs +30 -0
  219. package/build/elements/icons/interface/minus.d.cts +3 -0
  220. package/build/elements/icons/interface/minus.d.ts +3 -0
  221. package/build/elements/icons/interface/minus.js +26 -0
  222. package/build/elements/icons/interface/picker.cjs +34 -0
  223. package/build/elements/icons/interface/picker.d.cts +3 -0
  224. package/build/elements/icons/interface/picker.d.ts +3 -0
  225. package/build/elements/icons/interface/picker.js +30 -0
  226. package/build/elements/icons/interface/plus.cjs +30 -0
  227. package/build/elements/icons/interface/plus.d.cts +3 -0
  228. package/build/elements/icons/interface/plus.d.ts +3 -0
  229. package/build/elements/icons/interface/plus.js +26 -0
  230. package/build/elements/icons/interface/settings.cjs +30 -0
  231. package/build/elements/icons/interface/settings.d.cts +3 -0
  232. package/build/elements/icons/interface/settings.d.ts +3 -0
  233. package/build/elements/icons/interface/settings.js +26 -0
  234. package/build/elements/index.cjs +62 -0
  235. package/build/elements/index.d.cts +22 -0
  236. package/build/elements/index.d.ts +22 -0
  237. package/build/elements/index.js +22 -0
  238. package/build/elements/input/index.cjs +273 -0
  239. package/build/elements/input/index.d.cts +17 -0
  240. package/build/elements/input/index.d.ts +17 -0
  241. package/build/elements/input/index.js +269 -0
  242. package/build/elements/logo/index.cjs +732 -0
  243. package/build/elements/logo/index.d.cts +17 -0
  244. package/build/elements/logo/index.d.ts +17 -0
  245. package/build/elements/logo/index.js +728 -0
  246. package/build/elements/monitor/fps.cjs +432 -0
  247. package/build/elements/monitor/fps.d.cts +21 -0
  248. package/build/elements/monitor/fps.d.ts +21 -0
  249. package/build/elements/monitor/fps.js +428 -0
  250. package/build/elements/monitor/index.cjs +670 -0
  251. package/build/elements/monitor/index.d.cts +112 -0
  252. package/build/elements/monitor/index.d.ts +112 -0
  253. package/build/elements/monitor/index.js +666 -0
  254. package/build/elements/number/index.cjs +173 -0
  255. package/build/elements/number/index.d.cts +19 -0
  256. package/build/elements/number/index.d.ts +19 -0
  257. package/build/elements/number/index.js +169 -0
  258. package/build/elements/origin/index.cjs +169 -0
  259. package/build/elements/origin/index.d.cts +12 -0
  260. package/build/elements/origin/index.d.ts +12 -0
  261. package/build/elements/origin/index.js +165 -0
  262. package/build/elements/popover/index.cjs +209 -0
  263. package/build/elements/popover/index.d.cts +19 -0
  264. package/build/elements/popover/index.d.ts +19 -0
  265. package/build/elements/popover/index.js +205 -0
  266. package/build/elements/radio/index.cjs +301 -0
  267. package/build/elements/radio/index.d.cts +13 -0
  268. package/build/elements/radio/index.d.ts +13 -0
  269. package/build/elements/radio/index.js +283 -0
  270. package/build/elements/radio/input.cjs +329 -0
  271. package/build/elements/radio/input.d.cts +15 -0
  272. package/build/elements/radio/input.d.ts +15 -0
  273. package/build/elements/radio/input.js +325 -0
  274. package/build/elements/radio/option.cjs +15 -0
  275. package/build/elements/radio/option.d.cts +3 -0
  276. package/build/elements/radio/option.d.ts +3 -0
  277. package/build/elements/radio/option.js +11 -0
  278. package/build/elements/shared.cjs +66 -0
  279. package/build/elements/shared.d.cts +40 -0
  280. package/build/elements/shared.d.ts +40 -0
  281. package/build/elements/shared.js +59 -0
  282. package/build/elements/slider/index.cjs +232 -0
  283. package/build/elements/slider/index.d.cts +20 -0
  284. package/build/elements/slider/index.d.ts +20 -0
  285. package/build/elements/slider/index.js +228 -0
  286. package/build/elements/state/index.cjs +681 -0
  287. package/build/elements/state/index.d.cts +86 -0
  288. package/build/elements/state/index.d.ts +86 -0
  289. package/build/elements/state/index.js +677 -0
  290. package/build/elements/toggle/index.cjs +151 -0
  291. package/build/elements/toggle/index.d.cts +9 -0
  292. package/build/elements/toggle/index.d.ts +9 -0
  293. package/build/elements/toggle/index.js +147 -0
  294. package/build/elements/tooltip/index.cjs +187 -0
  295. package/build/elements/tooltip/index.d.cts +17 -0
  296. package/build/elements/tooltip/index.d.ts +17 -0
  297. package/build/elements/tooltip/index.js +183 -0
  298. package/build/index.cjs +40 -0
  299. package/build/index.d.cts +6 -0
  300. package/build/index.d.ts +6 -0
  301. package/build/index.js +12 -0
  302. package/build/init.cjs +325 -0
  303. package/build/init.d.cts +157 -0
  304. package/build/init.d.ts +157 -0
  305. package/build/init.js +289 -0
  306. package/build/internal/component-loaders.cjs +206 -0
  307. package/build/internal/component-loaders.d.cts +52 -0
  308. package/build/internal/component-loaders.d.ts +52 -0
  309. package/build/internal/component-loaders.js +167 -0
  310. package/build/internal/fonts.cjs +128 -0
  311. package/build/internal/fonts.d.cts +32 -0
  312. package/build/internal/fonts.d.ts +32 -0
  313. package/build/internal/fonts.js +123 -0
  314. package/build/internal/lazy-load.cjs +89 -0
  315. package/build/internal/lazy-load.d.cts +32 -0
  316. package/build/internal/lazy-load.d.ts +32 -0
  317. package/build/internal/lazy-load.js +86 -0
  318. package/build/internal/style-inject.cjs +236 -0
  319. package/build/internal/style-inject.d.cts +44 -0
  320. package/build/internal/style-inject.d.ts +44 -0
  321. package/build/internal/style-inject.js +226 -0
  322. package/build/register.cjs +36 -0
  323. package/build/register.d.cts +32 -0
  324. package/build/register.d.ts +32 -0
  325. package/build/register.js +34 -0
  326. package/build/theme/index.cjs +452 -0
  327. package/build/theme/index.d.cts +146 -0
  328. package/build/theme/index.d.ts +146 -0
  329. package/build/theme/index.js +423 -0
  330. package/build/theme/presets.cjs +54 -0
  331. package/build/theme/presets.d.cts +19 -0
  332. package/build/theme/presets.d.ts +19 -0
  333. package/build/theme/presets.js +51 -0
  334. package/build/theme/registry.cjs +204 -0
  335. package/build/theme/registry.d.cts +99 -0
  336. package/build/theme/registry.d.ts +99 -0
  337. package/build/theme/registry.js +194 -0
  338. package/build/theme/tokens.cjs +148 -0
  339. package/build/theme/tokens.d.cts +163 -0
  340. package/build/theme/tokens.d.ts +163 -0
  341. package/build/theme/tokens.js +145 -0
  342. package/build/utils/dismiss-controller.cjs +77 -0
  343. package/build/utils/dismiss-controller.d.cts +14 -0
  344. package/build/utils/dismiss-controller.d.ts +14 -0
  345. package/build/utils/dismiss-controller.js +73 -0
  346. package/build/utils/index.cjs +18 -0
  347. package/build/utils/index.d.cts +3 -0
  348. package/build/utils/index.d.ts +3 -0
  349. package/build/utils/index.js +3 -0
  350. package/build/utils/outside-click.cjs +82 -0
  351. package/build/utils/outside-click.d.cts +18 -0
  352. package/build/utils/outside-click.d.ts +18 -0
  353. package/build/utils/outside-click.js +74 -0
  354. package/build/utils/template-helpers.cjs +39 -0
  355. package/build/utils/template-helpers.d.cts +13 -0
  356. package/build/utils/template-helpers.d.ts +13 -0
  357. package/build/utils/template-helpers.js +28 -0
  358. package/package.json +96 -0
@@ -0,0 +1,875 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Dropdown = void 0;
4
+ require("../popover/index.cjs");
5
+ require("../icons/animation/chevron.cjs");
6
+ const lit_html_1 = require("lit-html");
7
+ const shared_1 = require("../shared.cjs");
8
+ const Component_1 = require("~/decorators/Component");
9
+ const OutsideClick_1 = require("~/decorators/OutsideClick");
10
+ const Prop_1 = require("~/decorators/Prop");
11
+ const Query_1 = require("~/decorators/Query");
12
+ const nextOptionId = (() => {
13
+ let counter = 0;
14
+ return () => {
15
+ counter += 1;
16
+ return `ease-dropdown-option-${counter}`;
17
+ };
18
+ })();
19
+ const nextPanelId = (() => {
20
+ let counter = 0;
21
+ return () => {
22
+ counter += 1;
23
+ return `ease-dropdown-content-${counter}`;
24
+ };
25
+ })();
26
+ @(0, Component_1.Component)({
27
+ tag: 'ease-dropdown',
28
+ styles: `
29
+ :host {
30
+ display: grid;
31
+ width: 100%;
32
+ }
33
+
34
+ ease-popover {
35
+ --ease-popover-content-min-width: var(--ease-dropdown-panel-min-width, anchor-size(width));
36
+ --ease-popover-content-width: var(--ease-dropdown-panel-width, max-content);
37
+ --ease-popover-content-max-width: var(--ease-dropdown-panel-max-width, none);
38
+ }
39
+
40
+ [part="trigger"] {
41
+ display: flex;
42
+ align-items: center;
43
+ justify-content: space-between;
44
+ width: 100%;
45
+ gap: 8px;
46
+ padding: var(--ease-dropdown-trigger-padding, 8px 8px 8px 12px);
47
+ border-radius: var(--ease-dropdown-radius, var(--radii-md));
48
+ background-color: var(--ease-dropdown-background, var(--color-gray-850));
49
+ cursor: pointer;
50
+ box-shadow: var(
51
+ --ease-dropdown-shadow,
52
+ inset 0 1px 0.25px 0 var(--color-white-4),
53
+ 0 1px 2.5px 0 var(--color-black-8)
54
+ );
55
+ font-family: var(--ease-font-family, inherit);
56
+ font-optical-sizing: auto;
57
+ box-sizing: border-box;
58
+ font-size: var(--ease-dropdown-font-size, var(--ease-font-size, 13px));
59
+ font-weight: var(--ease-dropdown-font-weight, 500);
60
+ color: var(--ease-dropdown-color, var(--color-foreground));
61
+ min-width: 0;
62
+ border: none;
63
+ outline: none;
64
+ margin: 0;
65
+ line-height: var(--ease-dropdown-line-height, 14px);
66
+ transition: color 0.2s, background-color 0.2s;
67
+ text-align: left;
68
+
69
+ &:hover,
70
+ &:focus-within {
71
+ background-color: var(--ease-dropdown-background-hover, var(--color-gray-825));
72
+ }
73
+
74
+ [part="trigger-icon"] {
75
+ display: block;
76
+ margin: -1px 0 -1px -2px;
77
+ }
78
+
79
+ &[data-pill="true"] {
80
+ border-radius: 999px;
81
+ }
82
+
83
+ &[data-block="small"] {
84
+ padding: 4px 8px 4px 4px;
85
+ }
86
+
87
+ &[data-headless="true"] {
88
+ background: transparent;
89
+ box-shadow: none;
90
+ padding: 0;
91
+ border-radius: 0;
92
+ gap: 4px;
93
+
94
+ &:hover,
95
+ &:focus-within {
96
+ background: transparent;
97
+ }
98
+ }
99
+ }
100
+
101
+ input[part="trigger-input"] {
102
+ background: transparent;
103
+ border: none;
104
+ outline: none;
105
+ color: inherit;
106
+ font: inherit;
107
+ width: fit-content;
108
+ min-width: 0;
109
+ padding: 0;
110
+ margin: 0;
111
+ cursor: pointer;
112
+ field-sizing: var(--ease-dropdown-field-sizing, fixed);
113
+ }
114
+
115
+ :host([open]) input[part="trigger-input"] {
116
+ cursor: text;
117
+ }
118
+
119
+ [part="trigger"][data-placeholder="true"],
120
+ [part="trigger"] [part="trigger-label"][data-placeholder="true"],
121
+ input[part="trigger-input"]::placeholder {
122
+ color: var(--ease-dropdown-placeholder-color, var(--color-gray-600));
123
+ }
124
+
125
+ [part="trigger"] [part="trigger-label"] {
126
+ flex-grow: 1;
127
+ text-overflow: ellipsis;
128
+ overflow: hidden;
129
+ white-space: nowrap;
130
+ }
131
+
132
+ [part="content"] {
133
+ border-radius: var(--ease-dropdown-panel-radius, var(--ease-dropdown-radius, var(--radii-md)));
134
+ background: var(--ease-dropdown-panel-background, var(--color-gray-875));
135
+ border: none;
136
+ outline: none;
137
+ box-shadow: var(
138
+ --ease-dropdown-panel-shadow,
139
+ 0 5px 20px 0 var(--color-black-15),
140
+ 0 1px 4px 0 var(--color-black-15),
141
+ 0 0 0 1px var(--color-white-4) inset,
142
+ 0 1px 0 0 var(--color-white-4) inset
143
+ );
144
+ background-clip: padding-box;
145
+ border: 1px solid var(--ease-dropdown-panel-border-color, var(--color-gray-825));
146
+ box-sizing: border-box;
147
+ padding: var(--ease-dropdown-panel-padding, 4px);
148
+ }
149
+
150
+ [part="content"] ::slotted(hr) {
151
+ margin: 4px 0;
152
+ height: 1px;
153
+ background-color: var(--color-white-4);
154
+ border: none;
155
+
156
+ &:first-child,
157
+ &:last-child {
158
+ display: none;
159
+ }
160
+ }
161
+
162
+ [part="content"] ::slotted(h4) {
163
+ margin: 4px 0 8px 0 !important;
164
+ font-size: var(--ease-dropdown-group-label-font-size, 11px);
165
+ line-height: 1;
166
+ padding: var(--ease-dropdown-group-label-padding, 0 8px);
167
+ font-family: var(--ease-font-family, inherit);
168
+ font-weight: 450;
169
+ color: var(--ease-dropdown-group-label-color, var(--color-gray-700));
170
+ display: block;
171
+
172
+ &:first-child,
173
+ &:last-child {
174
+ display: none;
175
+ }
176
+ }
177
+
178
+ [part="section"] {
179
+ flex-grow: 1;
180
+ min-width: max(100%, var(--ease-dropdown-min-width, 140px));
181
+ display: grid;
182
+ grid-gap: 3px;
183
+ max-height: var(--ease-dropdown-max-height, auto);
184
+ overflow-y: auto;
185
+ overscroll-behavior: contain;
186
+ container-type: inline-size;
187
+ container-name: scroll-area;
188
+ mask: linear-gradient(to bottom,
189
+ #0000,
190
+ #ffff var(--top-fade) calc(100% - var(--bottom-fade)),
191
+ #0000
192
+ );
193
+ animation: scroll;
194
+ animation-timeline: --scroll;
195
+ scroll-timeline: --scroll y;
196
+ scroll-snap-type: y mandatory;
197
+ scrollbar-width: none;
198
+ -ms-overflow-style: none;
199
+ box-sizing: border-box;
200
+ }
201
+
202
+ [part="section"]::-webkit-scrollbar {
203
+ width: 0;
204
+ height: 0;
205
+ display: none;
206
+ }
207
+
208
+ @property --top-fade {
209
+ syntax: '<length>';
210
+ inherits: false;
211
+ initial-value: 0;
212
+ }
213
+
214
+ @property --bottom-fade {
215
+ syntax: '<length>';
216
+ inherits: false;
217
+ initial-value: 0;
218
+ }
219
+
220
+ @keyframes scroll {
221
+ 0% {
222
+ --bottom-fade: 16px;
223
+ --top-fade: 0;
224
+ }
225
+ 10%,
226
+ 100% {
227
+ --top-fade: 16px;
228
+ }
229
+ 90% {
230
+ --bottom-fade: 16px;
231
+ }
232
+ 100% {
233
+ --bottom-fade: 0;
234
+ }
235
+ }
236
+
237
+ ::slotted(button[slot="content"]) {
238
+ appearance: none;
239
+ font-family: var(--ease-font-family, inherit);
240
+ font-optical-sizing: auto;
241
+ font-size: var(--ease-dropdown-option-font-size, var(--ease-font-size-sm, 12px));
242
+ font-weight: var(--ease-dropdown-option-font-weight, 400);
243
+ color: var(--ease-dropdown-option-color, var(--color-blue-100));
244
+ min-width: 0;
245
+ padding: var(--ease-dropdown-option-padding, 7px 8px);
246
+ display: block;
247
+ border-radius: var(--ease-dropdown-option-radius, 5px);
248
+ background-color: var(--ease-dropdown-option-background, var(--color-gray-875));
249
+ border: none;
250
+ outline: none;
251
+ margin: 0;
252
+ line-height: var(--ease-dropdown-option-line-height, 14px);
253
+ transition: color 0.2s, background-color 0.2s;
254
+ cursor: pointer;
255
+ width: 100%;
256
+ text-align: left;
257
+ }
258
+
259
+ ::slotted(button[slot="content"]:hover),
260
+ ::slotted(button[slot="content"]:focus-visible),
261
+ ::slotted(button[slot="content"][data-active="true"]),
262
+ ::slotted(button[slot="content"][aria-selected="true"]) {
263
+ background-color: var(--ease-dropdown-option-background-active, var(--color-gray-825));
264
+ color: var(--ease-dropdown-option-color-active, var(--color-white));
265
+ }
266
+ `
267
+ })
268
+ class Dropdown extends HTMLElement {
269
+ @(0, Prop_1.Prop)({
270
+ type: Boolean,
271
+ reflect: true,
272
+ onChange(next, previous) {
273
+ this.handleOpenChange(next, previous);
274
+ }
275
+ })
276
+ accessor open = false;
277
+ @(0, Prop_1.Prop)({ type: Boolean, reflect: true })
278
+ accessor disabled = false;
279
+ @(0, Prop_1.Prop)({ type: Boolean, reflect: true })
280
+ accessor pill = false;
281
+ @(0, Prop_1.Prop)({ type: Boolean, reflect: true })
282
+ accessor headless = false;
283
+ @(0, Prop_1.Prop)({ type: Boolean, reflect: true })
284
+ accessor searchable = false;
285
+ @(0, Prop_1.Prop)({
286
+ type: String,
287
+ reflect: true,
288
+ defaultValue: 'medium',
289
+ onAttributeChange() {
290
+ this.requestRender?.();
291
+ }
292
+ })
293
+ accessor block = 'medium';
294
+ @(0, Prop_1.Prop)({
295
+ reflect: true,
296
+ defaultValue: 'auto',
297
+ onChange(next) {
298
+ this.style.setProperty('--ease-dropdown-max-height', next ?? 'auto');
299
+ }
300
+ })
301
+ accessor maxHeight = 'auto';
302
+ @(0, Prop_1.Prop)({ reflect: true, defaultValue: null })
303
+ accessor name = null;
304
+ @(0, Prop_1.Prop)({ reflect: true, defaultValue: null })
305
+ accessor value = null;
306
+ @(0, Prop_1.Prop)({
307
+ reflect: true,
308
+ attribute: 'placeholder',
309
+ defaultValue: 'Select an option'
310
+ })
311
+ accessor placeholder = 'Select an option';
312
+ @(0, Prop_1.Prop)({ reflect: true, defaultValue: 'bottom-start' })
313
+ accessor placement = 'bottom-start';
314
+ @(0, Query_1.Query)('[part="trigger"]')
315
+ accessor trigger;
316
+ @(0, Query_1.Query)('input[part="trigger-input"]')
317
+ accessor searchInput;
318
+ @(0, Query_1.Query)('[part="content"]')
319
+ accessor panelContent;
320
+ @(0, Query_1.Query)('slot[name="content"]')
321
+ accessor contentSlot;
322
+ #options = [];
323
+ #selectedLabel = null;
324
+ #currentSlot = null;
325
+ #pendingFocus = null;
326
+ #optionsInitialized = false;
327
+ #lastToggleOrigin = null;
328
+ #handleSlotChange = () => {
329
+ this.#syncOptions();
330
+ };
331
+ connectedCallback() {
332
+ this.#ensureSlotListener();
333
+ }
334
+ disconnectedCallback() {
335
+ this.#removeSlotListener();
336
+ this.#teardownOptions();
337
+ this.#lastToggleOrigin = null;
338
+ }
339
+ afterRender() {
340
+ const trigger = this.trigger;
341
+ const ariaLabel = this.getAttribute('aria-label');
342
+ if (trigger) {
343
+ if (trigger instanceof HTMLButtonElement) {
344
+ trigger.disabled = Boolean(this.disabled);
345
+ }
346
+ trigger.setAttribute('aria-expanded', this.open && !this.disabled ? 'true' : 'false');
347
+ trigger.setAttribute('aria-haspopup', 'listbox');
348
+ if (trigger instanceof HTMLButtonElement) {
349
+ if (ariaLabel && ariaLabel.trim().length > 0) {
350
+ trigger.setAttribute('aria-label', ariaLabel.trim());
351
+ }
352
+ else {
353
+ trigger.removeAttribute('aria-label');
354
+ }
355
+ }
356
+ }
357
+ if (this.searchInput) {
358
+ this.searchInput.disabled = Boolean(this.disabled);
359
+ if (ariaLabel && ariaLabel.trim().length > 0) {
360
+ this.searchInput.setAttribute('aria-label', ariaLabel.trim());
361
+ }
362
+ else {
363
+ this.searchInput.removeAttribute('aria-label');
364
+ }
365
+ }
366
+ const panel = this.panelContent;
367
+ const isInteractive = this.open && !this.disabled;
368
+ if (panel) {
369
+ if (!panel.id) {
370
+ panel.id = nextPanelId();
371
+ }
372
+ panel.tabIndex = -1;
373
+ panel.setAttribute('role', 'listbox');
374
+ panel.setAttribute('aria-hidden', isInteractive ? 'false' : 'true');
375
+ if (trigger) {
376
+ trigger.setAttribute('aria-controls', panel.id);
377
+ }
378
+ }
379
+ else if (trigger) {
380
+ trigger.removeAttribute('aria-controls');
381
+ }
382
+ (0, shared_1.setBooleanAttribute)(this, 'disabled', Boolean(this.disabled));
383
+ this.#ensureSlotListener();
384
+ if (!this.#optionsInitialized) {
385
+ queueMicrotask(() => {
386
+ this.#syncOptions();
387
+ });
388
+ }
389
+ else {
390
+ this.#updateOptionSelectionState();
391
+ }
392
+ if (this.disabled && this.open) {
393
+ this.#lastToggleOrigin = null;
394
+ this.open = false;
395
+ }
396
+ }
397
+ render() {
398
+ const placeholderActive = this.#isPlaceholderActive();
399
+ return (0, lit_html_1.html) `
400
+ <ease-popover
401
+ .placement=${this.placement}
402
+ .open=${this.open && !this.disabled}
403
+ >
404
+ ${this.searchable ? this.#renderSearchTrigger(placeholderActive) : this.#renderButtonTrigger(placeholderActive)}
405
+ <div
406
+ part="content"
407
+ role="listbox"
408
+ tabindex="-1"
409
+ data-open=${this.open && !this.disabled ? 'true' : 'false'}
410
+ ?hidden=${!this.open || this.disabled}
411
+ @keydown=${this.#handlePanelKeydown}
412
+ >
413
+ <div part="section">
414
+ <slot name="content"></slot>
415
+ </div>
416
+ </div>
417
+ </ease-popover>
418
+ `;
419
+ }
420
+ #renderButtonTrigger(placeholderActive) {
421
+ return (0, lit_html_1.html) `
422
+ <button
423
+ part="trigger"
424
+ slot="trigger"
425
+ type="button"
426
+ data-placeholder=${placeholderActive ? 'true' : 'false'}
427
+ data-headless=${this.headless}
428
+ @keydown=${this.#handleTriggerKeydown}
429
+ @click=${this.#handleTriggerClick}
430
+ data-pill=${this.pill}
431
+ >
432
+ <slot name="trigger">
433
+ <span part="trigger-label" data-placeholder=${placeholderActive ? 'true' : 'false'}>
434
+ ${this.#getTriggerLabel()}
435
+ </span>
436
+
437
+ <ease-icon-chevron part="trigger-icon" state=${this.open ? 'up' : 'down'} />
438
+ </slot>
439
+ </button>
440
+ `;
441
+ }
442
+ #renderSearchTrigger(placeholderActive) {
443
+ return (0, lit_html_1.html) `
444
+ <div
445
+ part="trigger"
446
+ slot="trigger"
447
+ data-placeholder=${placeholderActive ? 'true' : 'false'}
448
+ data-headless=${this.headless}
449
+ @click=${this.#handleSearchTriggerClick}
450
+ data-pill=${this.pill}
451
+ >
452
+ <slot name="trigger">
453
+ <input
454
+ part="trigger-input"
455
+ type="text"
456
+ .value=${this.open ? (this.searchInput?.value ?? '') : this.#getTriggerLabel()}
457
+ placeholder=${this.placeholder ?? ''}
458
+ ?readonly=${!this.open}
459
+ @input=${this.#handleSearchInput}
460
+ @keydown=${this.#handleTriggerKeydown}
461
+ />
462
+ <ease-icon-chevron part="trigger-icon" state=${this.open ? 'up' : 'down'} />
463
+ </slot>
464
+ </div>
465
+ `;
466
+ }
467
+ #handleSearchTriggerClick = (event) => {
468
+ if (this.disabled) {
469
+ return;
470
+ }
471
+ if (!this.open) {
472
+ this.toggle(true, event);
473
+ if (this.searchInput) {
474
+ this.searchInput.value = '';
475
+ this.#filterOptions('');
476
+ this.searchInput.focus();
477
+ }
478
+ }
479
+ else {
480
+ if (event.target !== this.searchInput) {
481
+ this.toggle(false, event);
482
+ }
483
+ }
484
+ };
485
+ #handleSearchInput = (event) => {
486
+ const input = event.target;
487
+ this.#filterOptions(input.value);
488
+ if (!this.open) {
489
+ this.toggle(true, event);
490
+ }
491
+ };
492
+ #filterOptions(query) {
493
+ const lowerQuery = query.toLowerCase();
494
+ this.#options.forEach((option) => {
495
+ const match = option.label.toLowerCase().includes(lowerQuery);
496
+ if (match) {
497
+ option.element.style.display = '';
498
+ }
499
+ else {
500
+ option.element.style.display = 'none';
501
+ }
502
+ });
503
+ }
504
+ toggle(force, originEvent) {
505
+ if (this.disabled) {
506
+ return;
507
+ }
508
+ const current = this.open;
509
+ const next = force ?? !current;
510
+ if (current === next) {
511
+ return;
512
+ }
513
+ this.#lastToggleOrigin = originEvent ?? null;
514
+ this.open = next;
515
+ if (!next) {
516
+ this.#pendingFocus = null;
517
+ // Reset filter when closing
518
+ this.#filterOptions('');
519
+ // Restore label in input if searchable
520
+ if (this.searchable && this.searchInput) {
521
+ this.searchInput.value = this.#getTriggerLabel();
522
+ this.searchInput.blur(); // Blur to look like static text
523
+ }
524
+ }
525
+ }
526
+ handleOpenChange(next, previous) {
527
+ if (next === previous) {
528
+ return;
529
+ }
530
+ if (!next) {
531
+ this.#pendingFocus = null;
532
+ }
533
+ const origin = this.#lastToggleOrigin ?? new Event(next ? 'open' : 'close');
534
+ this.#lastToggleOrigin = null;
535
+ if (next) {
536
+ if (this.searchable && this.searchInput) {
537
+ this.searchInput.focus();
538
+ }
539
+ else {
540
+ queueMicrotask(() => this.#focusActiveOption());
541
+ }
542
+ }
543
+ (0, shared_1.dispatchControlEvent)(this, 'toggle', { value: next, event: origin });
544
+ (0, OutsideClick_1.requestOutsideClickUpdate)(this);
545
+ }
546
+ @(0, OutsideClick_1.OutsideClick)({
547
+ content: (host) => host.panelContent,
548
+ triggers: (host) => [host.trigger, host.panelContent],
549
+ disabled: (host) => host.disabled || !host.open
550
+ })
551
+ handleOutsideDismiss(event) {
552
+ if (!this.open) {
553
+ return;
554
+ }
555
+ this.toggle(false, event);
556
+ }
557
+ #handleTriggerKeydown = (event) => {
558
+ switch (event.key) {
559
+ case 'ArrowDown':
560
+ event.preventDefault();
561
+ this.#pendingFocus = 'first';
562
+ this.toggle(true, event);
563
+ break;
564
+ case 'ArrowUp':
565
+ event.preventDefault();
566
+ this.#pendingFocus = 'last';
567
+ this.toggle(true, event);
568
+ break;
569
+ case 'Enter':
570
+ if (!this.searchable) {
571
+ event.preventDefault();
572
+ this.toggle(true, event);
573
+ }
574
+ break;
575
+ case ' ': // Space
576
+ if (!this.searchable) {
577
+ event.preventDefault();
578
+ this.toggle(true, event);
579
+ }
580
+ break;
581
+ case 'Escape':
582
+ if (this.open) {
583
+ event.preventDefault();
584
+ this.toggle(false, event);
585
+ }
586
+ break;
587
+ default:
588
+ break;
589
+ }
590
+ };
591
+ #ensureSlotListener() {
592
+ const slot = this.contentSlot;
593
+ if (slot === this.#currentSlot) {
594
+ return;
595
+ }
596
+ if (this.#currentSlot) {
597
+ this.#currentSlot.removeEventListener('slotchange', this.#handleSlotChange);
598
+ }
599
+ if (slot) {
600
+ slot.addEventListener('slotchange', this.#handleSlotChange);
601
+ }
602
+ this.#currentSlot = slot ?? null;
603
+ }
604
+ #removeSlotListener() {
605
+ if (!this.#currentSlot) {
606
+ return;
607
+ }
608
+ this.#currentSlot.removeEventListener('slotchange', this.#handleSlotChange);
609
+ this.#currentSlot = null;
610
+ }
611
+ #handleTriggerClick = (event) => {
612
+ this.toggle(!this.open, event);
613
+ };
614
+ #syncOptions() {
615
+ const assigned = this.contentSlot?.assignedElements({ flatten: true }) ?? [];
616
+ const elements = assigned.filter((node) => node instanceof HTMLElement);
617
+ this.#removeOptionListeners(this.#options);
618
+ const options = [];
619
+ elements.forEach((element) => {
620
+ if (element.hasAttribute('data-select-ignore') || element.getAttribute('role') === 'separator') {
621
+ return;
622
+ }
623
+ const value = this.#resolveOptionValue(element);
624
+ const label = this.#resolveOptionLabel(element, value);
625
+ const id = element.id && element.id.trim().length > 0 ? element.id : nextOptionId();
626
+ if (!element.id) {
627
+ element.id = id;
628
+ }
629
+ element.setAttribute('role', 'option');
630
+ element.setAttribute('aria-selected', 'false');
631
+ element.dataset.active = 'false';
632
+ element.tabIndex = -1;
633
+ const handlers = {
634
+ click: (event) => {
635
+ event.preventDefault();
636
+ event.stopPropagation();
637
+ this.#selectOption(value, label, event);
638
+ },
639
+ keydown: (event) => {
640
+ if (event.key === 'Enter' || event.key === ' ') {
641
+ event.preventDefault();
642
+ this.#selectOption(value, label, event);
643
+ }
644
+ }
645
+ };
646
+ element.addEventListener('click', handlers.click, { passive: false });
647
+ element.addEventListener('keydown', handlers.keydown);
648
+ options.push({ element, value, label, id, handlers });
649
+ });
650
+ this.#options = options;
651
+ this.#optionsInitialized = options.length > 0;
652
+ if (this.value === null && options.length > 0) {
653
+ const preselected = options.find((option) => option.element.hasAttribute('selected') ||
654
+ option.element.dataset.selected === 'true' ||
655
+ option.element.getAttribute('aria-selected') === 'true');
656
+ if (preselected) {
657
+ this.value = preselected.value;
658
+ }
659
+ }
660
+ this.#updateOptionSelectionState();
661
+ }
662
+ #teardownOptions() {
663
+ this.#removeOptionListeners(this.#options);
664
+ this.#options = [];
665
+ this.#optionsInitialized = false;
666
+ this.#selectedLabel = null;
667
+ }
668
+ #removeOptionListeners(options) {
669
+ options.forEach((option) => {
670
+ option.element.removeEventListener('click', option.handlers.click);
671
+ option.element.removeEventListener('keydown', option.handlers.keydown);
672
+ option.element.dataset.active = 'false';
673
+ option.element.setAttribute('aria-selected', 'false');
674
+ option.element.tabIndex = -1;
675
+ });
676
+ }
677
+ #updateOptionSelectionState() {
678
+ if (!this.#optionsInitialized) {
679
+ this.toggleAttribute('data-has-value', false);
680
+ return;
681
+ }
682
+ let selectedLabel = null;
683
+ const previousLabel = this.#selectedLabel;
684
+ const options = this.#options;
685
+ options.forEach((option) => {
686
+ const isSelected = this.value !== null && option.value === this.value;
687
+ option.element.setAttribute('aria-selected', isSelected ? 'true' : 'false');
688
+ option.element.dataset.active = isSelected ? 'true' : 'false';
689
+ option.element.tabIndex = isSelected ? 0 : -1;
690
+ if (isSelected) {
691
+ selectedLabel = option.label;
692
+ }
693
+ });
694
+ if (!selectedLabel) {
695
+ const fallback = options[0];
696
+ if (fallback) {
697
+ fallback.element.tabIndex = 0;
698
+ }
699
+ }
700
+ this.#selectedLabel = selectedLabel;
701
+ const hasValue = Boolean(this.value && this.#selectedLabel);
702
+ this.toggleAttribute('data-has-value', hasValue);
703
+ if (previousLabel !== this.#selectedLabel && typeof this.requestRender === 'function') {
704
+ this.requestRender();
705
+ }
706
+ }
707
+ #isPlaceholderActive() {
708
+ return !this.value || !this.#selectedLabel;
709
+ }
710
+ #getTriggerLabel() {
711
+ if (this.#selectedLabel) {
712
+ return this.#selectedLabel;
713
+ }
714
+ if (typeof this.placeholder === 'string' && this.placeholder.trim().length > 0) {
715
+ return this.placeholder.trim();
716
+ }
717
+ return 'Select';
718
+ }
719
+ #focusActiveOption() {
720
+ if (!this.open) {
721
+ return;
722
+ }
723
+ const options = this.#options.filter((o) => o.element.style.display !== 'none');
724
+ if (options.length === 0) {
725
+ this.panelContent?.focus();
726
+ return;
727
+ }
728
+ let target = options[0];
729
+ if (this.#pendingFocus === 'first') {
730
+ target = options[0];
731
+ }
732
+ else if (this.#pendingFocus === 'last') {
733
+ target = options[options.length - 1];
734
+ }
735
+ else if (this.#pendingFocus === null && this.value !== null) {
736
+ const match = this.#findOptionByValue(this.value);
737
+ if (match && match.element.style.display !== 'none') {
738
+ target = match;
739
+ }
740
+ }
741
+ if (target) {
742
+ this.#focusOption(target);
743
+ }
744
+ this.#pendingFocus = null;
745
+ }
746
+ #focusOption(option) {
747
+ this.#options.forEach((entry) => {
748
+ entry.element.tabIndex = entry === option ? 0 : -1;
749
+ });
750
+ option.element.focus({ preventScroll: true });
751
+ }
752
+ #focusOptionByIndex(index) {
753
+ const options = this.#options.filter((o) => o.element.style.display !== 'none');
754
+ if (options.length === 0) {
755
+ this.panelContent?.focus();
756
+ return;
757
+ }
758
+ const normalized = Math.max(0, Math.min(index, options.length - 1));
759
+ const option = options[normalized];
760
+ if (option) {
761
+ this.#focusOption(option);
762
+ }
763
+ }
764
+ #findOptionByValue(value) {
765
+ if (value === null) {
766
+ return undefined;
767
+ }
768
+ return this.#options.find((option) => option.value === value);
769
+ }
770
+ #moveFocus(step) {
771
+ const options = this.#options.filter((o) => o.element.style.display !== 'none');
772
+ if (options.length === 0) {
773
+ this.panelContent?.focus();
774
+ return;
775
+ }
776
+ const activeElement = document.activeElement;
777
+ const currentIndex = options.findIndex((option) => option.element === activeElement);
778
+ if (currentIndex === -1) {
779
+ this.#focusOptionByIndex(step > 0 ? 0 : options.length - 1);
780
+ return;
781
+ }
782
+ const nextIndex = (currentIndex + step + options.length) % options.length;
783
+ this.#focusOptionByIndex(nextIndex);
784
+ }
785
+ #handlePanelKeydown = (event) => {
786
+ switch (event.key) {
787
+ case 'ArrowDown':
788
+ event.preventDefault();
789
+ this.#moveFocus(1);
790
+ break;
791
+ case 'ArrowUp':
792
+ event.preventDefault();
793
+ this.#moveFocus(-1);
794
+ break;
795
+ case 'Home':
796
+ event.preventDefault();
797
+ this.#focusOptionByIndex(0);
798
+ break;
799
+ case 'End':
800
+ event.preventDefault();
801
+ this.#focusOptionByIndex(this.#options.length - 1);
802
+ break;
803
+ case 'Enter':
804
+ case ' ': {
805
+ event.preventDefault();
806
+ this.#activateFocusedOption(event);
807
+ break;
808
+ }
809
+ case 'Escape':
810
+ event.preventDefault();
811
+ this.toggle(false, event);
812
+ this.trigger?.focus();
813
+ break;
814
+ default:
815
+ break;
816
+ }
817
+ };
818
+ #activateFocusedOption(event) {
819
+ const active = this.#options.find((option) => option.element === document.activeElement);
820
+ if (active) {
821
+ this.#selectOption(active.value, active.label, event);
822
+ }
823
+ }
824
+ #selectOption(value, label, originEvent) {
825
+ if (this.disabled) {
826
+ return;
827
+ }
828
+ originEvent.preventDefault();
829
+ originEvent.stopPropagation();
830
+ const previousValue = this.value;
831
+ this.value = value;
832
+ this.#selectedLabel = label;
833
+ this.#updateOptionSelectionState();
834
+ this.toggle(false, originEvent);
835
+ if (previousValue !== value) {
836
+ this.#dispatchValueChange(value, label, originEvent);
837
+ }
838
+ if (!this.searchable) {
839
+ queueMicrotask(() => this.trigger?.focus());
840
+ }
841
+ }
842
+ #resolveOptionValue(element) {
843
+ const explicitValue = element.getAttribute('value') ?? element.getAttribute('data-value') ?? element.dataset.value;
844
+ if (explicitValue && explicitValue.trim().length > 0) {
845
+ return explicitValue.trim();
846
+ }
847
+ const text = element.textContent?.trim();
848
+ if (text && text.length > 0) {
849
+ return text;
850
+ }
851
+ const fallback = nextOptionId();
852
+ element.dataset.value = fallback;
853
+ return fallback;
854
+ }
855
+ #resolveOptionLabel(element, fallback) {
856
+ const explicitLabel = element.getAttribute('data-label') ?? element.getAttribute('aria-label');
857
+ if (explicitLabel && explicitLabel.trim().length > 0) {
858
+ return explicitLabel.trim();
859
+ }
860
+ const text = element.textContent?.trim();
861
+ if (text && text.length > 0) {
862
+ return text;
863
+ }
864
+ return fallback;
865
+ }
866
+ #dispatchValueChange(value, label, event) {
867
+ (0, shared_1.dispatchControlEvent)(this, 'change', { value, event });
868
+ this.dispatchEvent(new CustomEvent('value-change', {
869
+ detail: { value, label, event },
870
+ bubbles: true,
871
+ composed: true
872
+ }));
873
+ }
874
+ }
875
+ exports.Dropdown = Dropdown;