@greypan/web-ui 11.2.0 → 12.0.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 (667) hide show
  1. package/README.CN.md +79 -68
  2. package/README.md +81 -72
  3. package/dist/_virtual/_@oxc-project_runtime@0.155.0/helpers/esm/decorate.js +8 -0
  4. package/dist/assets/menu-portal.js +3 -4
  5. package/dist/assets/menu-portal.js.map +1 -1
  6. package/dist/assets/modal-surface.js +3 -4
  7. package/dist/assets/modal-surface.js.map +1 -1
  8. package/dist/assets/overlay-motion.js +3 -4
  9. package/dist/assets/overlay-motion.js.map +1 -1
  10. package/dist/assets/scrollbar.js +5 -0
  11. package/dist/assets/scrollbar.js.map +1 -0
  12. package/dist/assets/selection-control.js +3 -4
  13. package/dist/assets/selection-control.js.map +1 -1
  14. package/dist/assets/toast-containers.js +3 -4
  15. package/dist/assets/toast-containers.js.map +1 -1
  16. package/dist/classes/glass.js +3 -4
  17. package/dist/classes/glass.js.map +1 -1
  18. package/dist/classes/glow.js +3 -4
  19. package/dist/classes/glow.js.map +1 -1
  20. package/dist/components/autocomplete/index.d.ts +485 -483
  21. package/dist/components/autocomplete/index.d.ts.map +1 -0
  22. package/dist/components/autocomplete/index.js +475 -267
  23. package/dist/components/autocomplete/index.js.map +1 -1
  24. package/dist/components/autocomplete/style.js +3 -4
  25. package/dist/components/autocomplete/style.js.map +1 -1
  26. package/dist/components/avatar/index.d.ts +26 -24
  27. package/dist/components/avatar/index.d.ts.map +1 -0
  28. package/dist/components/avatar/index.js +72 -52
  29. package/dist/components/avatar/index.js.map +1 -1
  30. package/dist/components/avatar/style.js +3 -4
  31. package/dist/components/avatar/style.js.map +1 -1
  32. package/dist/components/back-top/index.d.ts +30 -27
  33. package/dist/components/back-top/index.d.ts.map +1 -0
  34. package/dist/components/back-top/index.js +96 -62
  35. package/dist/components/back-top/index.js.map +1 -1
  36. package/dist/components/back-top/style.js +3 -4
  37. package/dist/components/back-top/style.js.map +1 -1
  38. package/dist/components/badge/index.d.ts +32 -26
  39. package/dist/components/badge/index.d.ts.map +1 -0
  40. package/dist/components/badge/index.js +116 -74
  41. package/dist/components/badge/index.js.map +1 -1
  42. package/dist/components/badge/style.js +3 -4
  43. package/dist/components/badge/style.js.map +1 -1
  44. package/dist/components/button/index.d.ts +392 -390
  45. package/dist/components/button/index.d.ts.map +1 -0
  46. package/dist/components/button/index.js +108 -74
  47. package/dist/components/button/index.js.map +1 -1
  48. package/dist/components/button/style.js +3 -4
  49. package/dist/components/button/style.js.map +1 -1
  50. package/dist/components/button-group/index.d.ts +14 -13
  51. package/dist/components/button-group/index.d.ts.map +1 -0
  52. package/dist/components/button-group/index.js +43 -33
  53. package/dist/components/button-group/index.js.map +1 -1
  54. package/dist/components/button-group/style.js +3 -4
  55. package/dist/components/button-group/style.js.map +1 -1
  56. package/dist/components/checkbox/index.d.ts +399 -397
  57. package/dist/components/checkbox/index.d.ts.map +1 -0
  58. package/dist/components/checkbox/index.js +103 -74
  59. package/dist/components/checkbox/index.js.map +1 -1
  60. package/dist/components/checkbox/style.js +3 -4
  61. package/dist/components/checkbox/style.js.map +1 -1
  62. package/dist/components/checkbox-group/index.d.ts +397 -396
  63. package/dist/components/checkbox-group/index.d.ts.map +1 -0
  64. package/dist/components/checkbox-group/index.js +92 -70
  65. package/dist/components/checkbox-group/index.js.map +1 -1
  66. package/dist/components/checkbox-group/style.js +3 -4
  67. package/dist/components/checkbox-group/style.js.map +1 -1
  68. package/dist/components/collapse/index.d.ts +72 -71
  69. package/dist/components/collapse/index.d.ts.map +1 -0
  70. package/dist/components/collapse/index.js +225 -130
  71. package/dist/components/collapse/index.js.map +1 -1
  72. package/dist/components/collapse/style.js +3 -4
  73. package/dist/components/collapse/style.js.map +1 -1
  74. package/dist/components/context-menu/index.d.ts +307 -310
  75. package/dist/components/context-menu/index.d.ts.map +1 -0
  76. package/dist/components/context-menu/index.js +685 -270
  77. package/dist/components/context-menu/index.js.map +1 -1
  78. package/dist/components/context-menu/scrim.js +3 -4
  79. package/dist/components/context-menu/scrim.js.map +1 -1
  80. package/dist/components/context-menu/style.js +3 -4
  81. package/dist/components/context-menu/style.js.map +1 -1
  82. package/dist/components/dialog/index.d.ts +87 -78
  83. package/dist/components/dialog/index.d.ts.map +1 -0
  84. package/dist/components/dialog/index.js +183 -88
  85. package/dist/components/dialog/index.js.map +1 -1
  86. package/dist/components/dialog/style.js +3 -4
  87. package/dist/components/dialog/style.js.map +1 -1
  88. package/dist/components/drawer/index.d.ts +159 -150
  89. package/dist/components/drawer/index.d.ts.map +1 -0
  90. package/dist/components/drawer/index.js +503 -242
  91. package/dist/components/drawer/index.js.map +1 -1
  92. package/dist/components/drawer/style.js +3 -4
  93. package/dist/components/drawer/style.js.map +1 -1
  94. package/dist/components/dropdown/index.d.ts +125 -124
  95. package/dist/components/dropdown/index.d.ts.map +1 -0
  96. package/dist/components/dropdown/index.js +556 -328
  97. package/dist/components/dropdown/index.js.map +1 -1
  98. package/dist/components/dropdown/style.js +3 -4
  99. package/dist/components/dropdown/style.js.map +1 -1
  100. package/dist/components/dropdown-divider/index.d.ts +7 -6
  101. package/dist/components/dropdown-divider/index.d.ts.map +1 -0
  102. package/dist/components/dropdown-divider/index.js +10 -11
  103. package/dist/components/dropdown-divider/index.js.map +1 -1
  104. package/dist/components/dropdown-divider/style.js +3 -4
  105. package/dist/components/dropdown-divider/style.js.map +1 -1
  106. package/dist/components/dropdown-header/index.d.ts +7 -6
  107. package/dist/components/dropdown-header/index.d.ts.map +1 -0
  108. package/dist/components/dropdown-header/index.js +10 -11
  109. package/dist/components/dropdown-header/index.js.map +1 -1
  110. package/dist/components/dropdown-header/style.js +3 -4
  111. package/dist/components/dropdown-header/style.js.map +1 -1
  112. package/dist/components/dropdown-item/index.d.ts +13 -11
  113. package/dist/components/dropdown-item/index.d.ts.map +1 -0
  114. package/dist/components/dropdown-item/index.js +32 -25
  115. package/dist/components/dropdown-item/index.js.map +1 -1
  116. package/dist/components/dropdown-item/style.js +3 -4
  117. package/dist/components/dropdown-item/style.js.map +1 -1
  118. package/dist/components/editable-text/index.d.ts +506 -505
  119. package/dist/components/editable-text/index.d.ts.map +1 -0
  120. package/dist/components/editable-text/index.js +281 -127
  121. package/dist/components/editable-text/index.js.map +1 -1
  122. package/dist/components/editable-text/style.js +3 -4
  123. package/dist/components/editable-text/style.js.map +1 -1
  124. package/dist/components/empty/index.d.ts +17 -15
  125. package/dist/components/empty/index.d.ts.map +1 -0
  126. package/dist/components/empty/index.js +66 -37
  127. package/dist/components/empty/index.js.map +1 -1
  128. package/dist/components/empty/style.js +3 -4
  129. package/dist/components/empty/style.js.map +1 -1
  130. package/dist/components/icon/index.d.ts +12 -11
  131. package/dist/components/icon/index.d.ts.map +1 -0
  132. package/dist/components/icon/index.js +34 -27
  133. package/dist/components/icon/index.js.map +1 -1
  134. package/dist/components/icon/style.js +3 -4
  135. package/dist/components/icon/style.js.map +1 -1
  136. package/dist/components/image-preview/index.d.ts +58 -44
  137. package/dist/components/image-preview/index.d.ts.map +1 -0
  138. package/dist/components/image-preview/index.js +536 -265
  139. package/dist/components/image-preview/index.js.map +1 -1
  140. package/dist/components/image-preview/style.js +3 -4
  141. package/dist/components/image-preview/style.js.map +1 -1
  142. package/dist/components/index.d.ts +46 -43
  143. package/dist/components/index.d.ts.map +1 -0
  144. package/dist/components/index.js +41 -41
  145. package/dist/components/input/index.d.ts +418 -413
  146. package/dist/components/input/index.d.ts.map +1 -0
  147. package/dist/components/input/index.js +148 -84
  148. package/dist/components/input/index.js.map +1 -1
  149. package/dist/components/input/style.js +3 -4
  150. package/dist/components/input/style.js.map +1 -1
  151. package/dist/components/input-number/index.d.ts +453 -447
  152. package/dist/components/input-number/index.d.ts.map +1 -0
  153. package/dist/components/input-number/index.js +484 -292
  154. package/dist/components/input-number/index.js.map +1 -1
  155. package/dist/components/input-number/style.js +3 -4
  156. package/dist/components/input-number/style.js.map +1 -1
  157. package/dist/components/layout/index.d.ts +110 -87
  158. package/dist/components/layout/index.d.ts.map +1 -0
  159. package/dist/components/layout/index.js +238 -144
  160. package/dist/components/layout/index.js.map +1 -1
  161. package/dist/components/layout/style.js +3 -4
  162. package/dist/components/layout/style.js.map +1 -1
  163. package/dist/components/middle-ellipsis/index.d.ts +93 -92
  164. package/dist/components/middle-ellipsis/index.d.ts.map +1 -0
  165. package/dist/components/middle-ellipsis/index.js +261 -107
  166. package/dist/components/middle-ellipsis/index.js.map +1 -1
  167. package/dist/components/middle-ellipsis/style.js +3 -4
  168. package/dist/components/middle-ellipsis/style.js.map +1 -1
  169. package/dist/components/middle-ellipsis/truncate.js +60 -30
  170. package/dist/components/middle-ellipsis/truncate.js.map +1 -1
  171. package/dist/components/option/index.d.ts +20 -18
  172. package/dist/components/option/index.d.ts.map +1 -0
  173. package/dist/components/option/index.js +53 -40
  174. package/dist/components/option/index.js.map +1 -1
  175. package/dist/components/option/style.js +3 -4
  176. package/dist/components/option/style.js.map +1 -1
  177. package/dist/components/popover/index.d.ts +69 -68
  178. package/dist/components/popover/index.d.ts.map +1 -0
  179. package/dist/components/popover/index.js +221 -104
  180. package/dist/components/popover/index.js.map +1 -1
  181. package/dist/components/popover/style.js +3 -4
  182. package/dist/components/popover/style.js.map +1 -1
  183. package/dist/components/radio/index.d.ts +396 -395
  184. package/dist/components/radio/index.d.ts.map +1 -0
  185. package/dist/components/radio/index.js +91 -62
  186. package/dist/components/radio/index.js.map +1 -1
  187. package/dist/components/radio/interaction.js +10 -11
  188. package/dist/components/radio/interaction.js.map +1 -1
  189. package/dist/components/radio/style.js +3 -4
  190. package/dist/components/radio/style.js.map +1 -1
  191. package/dist/components/radio-group/index.d.ts +417 -416
  192. package/dist/components/radio-group/index.d.ts.map +1 -0
  193. package/dist/components/radio-group/index.js +307 -207
  194. package/dist/components/radio-group/index.js.map +1 -1
  195. package/dist/components/radio-group/style.js +3 -4
  196. package/dist/components/radio-group/style.js.map +1 -1
  197. package/dist/components/segmented/index.d.ts +408 -402
  198. package/dist/components/segmented/index.d.ts.map +1 -0
  199. package/dist/components/segmented/index.js +267 -158
  200. package/dist/components/segmented/index.js.map +1 -1
  201. package/dist/components/segmented/style.js +3 -4
  202. package/dist/components/segmented/style.js.map +1 -1
  203. package/dist/components/segmented-trigger/index.d.ts +18 -17
  204. package/dist/components/segmented-trigger/index.d.ts.map +1 -0
  205. package/dist/components/segmented-trigger/index.js +45 -36
  206. package/dist/components/segmented-trigger/index.js.map +1 -1
  207. package/dist/components/segmented-trigger/style.js +3 -4
  208. package/dist/components/segmented-trigger/style.js.map +1 -1
  209. package/dist/components/select/index.d.ts +450 -448
  210. package/dist/components/select/index.d.ts.map +1 -0
  211. package/dist/components/select/index.js +342 -188
  212. package/dist/components/select/index.js.map +1 -1
  213. package/dist/components/select/style.js +3 -4
  214. package/dist/components/select/style.js.map +1 -1
  215. package/dist/components/slider/index.d.ts +428 -427
  216. package/dist/components/slider/index.d.ts.map +1 -0
  217. package/dist/components/slider/index.js +308 -216
  218. package/dist/components/slider/index.js.map +1 -1
  219. package/dist/components/slider/style.js +3 -4
  220. package/dist/components/slider/style.js.map +1 -1
  221. package/dist/components/spinner/index.d.ts +39 -38
  222. package/dist/components/spinner/index.d.ts.map +1 -0
  223. package/dist/components/spinner/index.js +118 -65
  224. package/dist/components/spinner/index.js.map +1 -1
  225. package/dist/components/spinner/style.js +3 -4
  226. package/dist/components/spinner/style.js.map +1 -1
  227. package/dist/components/svg-draw-lines/index.d.ts +40 -39
  228. package/dist/components/svg-draw-lines/index.d.ts.map +1 -0
  229. package/dist/components/svg-draw-lines/index.js +189 -106
  230. package/dist/components/svg-draw-lines/index.js.map +1 -1
  231. package/dist/components/svg-draw-lines/style.js +3 -4
  232. package/dist/components/svg-draw-lines/style.js.map +1 -1
  233. package/dist/components/switch/index.d.ts +411 -409
  234. package/dist/components/switch/index.d.ts.map +1 -0
  235. package/dist/components/switch/index.js +193 -106
  236. package/dist/components/switch/index.js.map +1 -1
  237. package/dist/components/switch/style.js +3 -4
  238. package/dist/components/switch/style.js.map +1 -1
  239. package/dist/components/textarea/index.d.ts +430 -425
  240. package/dist/components/textarea/index.d.ts.map +1 -0
  241. package/dist/components/textarea/index.js +187 -100
  242. package/dist/components/textarea/index.js.map +1 -1
  243. package/dist/components/textarea/style.js +3 -4
  244. package/dist/components/textarea/style.js.map +1 -1
  245. package/dist/components/theme/index.d.ts +45 -44
  246. package/dist/components/theme/index.d.ts.map +1 -0
  247. package/dist/components/theme/index.js +268 -161
  248. package/dist/components/theme/index.js.map +1 -1
  249. package/dist/components/theme/style.js +3 -4
  250. package/dist/components/theme/style.js.map +1 -1
  251. package/dist/components/toast/index.d.ts +4 -3
  252. package/dist/components/toast/index.js +3 -3
  253. package/dist/components/toast/manager.d.ts +9 -8
  254. package/dist/components/toast/manager.d.ts.map +1 -0
  255. package/dist/components/toast/manager.js +215 -119
  256. package/dist/components/toast/manager.js.map +1 -1
  257. package/dist/components/toast/style.js +3 -4
  258. package/dist/components/toast/style.js.map +1 -1
  259. package/dist/components/toast/toast.d.ts +75 -71
  260. package/dist/components/toast/toast.d.ts.map +1 -0
  261. package/dist/components/toast/toast.js +203 -96
  262. package/dist/components/toast/toast.js.map +1 -1
  263. package/dist/components/toast/types.d.ts +10 -9
  264. package/dist/components/toast/types.d.ts.map +1 -0
  265. package/dist/components/tooltip/index.d.ts +72 -62
  266. package/dist/components/tooltip/index.d.ts.map +1 -0
  267. package/dist/components/tooltip/index.js +251 -93
  268. package/dist/components/tooltip/index.js.map +1 -1
  269. package/dist/components/tooltip/style.js +3 -4
  270. package/dist/components/tooltip/style.js.map +1 -1
  271. package/dist/icons/generated/akar-icons-check.d.ts +5 -4
  272. package/dist/icons/generated/akar-icons-check.d.ts.map +1 -0
  273. package/dist/icons/generated/akar-icons-check.js +3 -4
  274. package/dist/icons/generated/akar-icons-check.js.map +1 -1
  275. package/dist/icons/generated/akar-icons-circle-check.d.ts +5 -4
  276. package/dist/icons/generated/akar-icons-circle-check.d.ts.map +1 -0
  277. package/dist/icons/generated/akar-icons-circle-check.js +3 -4
  278. package/dist/icons/generated/akar-icons-circle-check.js.map +1 -1
  279. package/dist/icons/generated/andrsrxn-inbox.d.ts +5 -4
  280. package/dist/icons/generated/andrsrxn-inbox.d.ts.map +1 -0
  281. package/dist/icons/generated/andrsrxn-inbox.js +3 -4
  282. package/dist/icons/generated/andrsrxn-inbox.js.map +1 -1
  283. package/dist/icons/generated/bi-check-lg.d.ts +5 -4
  284. package/dist/icons/generated/bi-check-lg.d.ts.map +1 -0
  285. package/dist/icons/generated/bi-check-lg.js +3 -4
  286. package/dist/icons/generated/bi-check-lg.js.map +1 -1
  287. package/dist/icons/generated/bi-check.d.ts +5 -4
  288. package/dist/icons/generated/bi-check.d.ts.map +1 -0
  289. package/dist/icons/generated/bi-check.js +3 -4
  290. package/dist/icons/generated/bi-check.js.map +1 -1
  291. package/dist/icons/generated/fluent-tag-search-24-regular.d.ts +5 -4
  292. package/dist/icons/generated/fluent-tag-search-24-regular.d.ts.map +1 -0
  293. package/dist/icons/generated/fluent-tag-search-24-regular.js +3 -4
  294. package/dist/icons/generated/fluent-tag-search-24-regular.js.map +1 -1
  295. package/dist/icons/generated/heroicons-bars-arrow-down-16-solid.d.ts +5 -4
  296. package/dist/icons/generated/heroicons-bars-arrow-down-16-solid.d.ts.map +1 -0
  297. package/dist/icons/generated/heroicons-bars-arrow-down-16-solid.js +3 -4
  298. package/dist/icons/generated/heroicons-bars-arrow-down-16-solid.js.map +1 -1
  299. package/dist/icons/generated/heroicons-bars-arrow-up-16-solid.d.ts +5 -4
  300. package/dist/icons/generated/heroicons-bars-arrow-up-16-solid.d.ts.map +1 -0
  301. package/dist/icons/generated/heroicons-bars-arrow-up-16-solid.js +3 -4
  302. package/dist/icons/generated/heroicons-bars-arrow-up-16-solid.js.map +1 -1
  303. package/dist/icons/generated/heroicons-check-16-solid.d.ts +5 -4
  304. package/dist/icons/generated/heroicons-check-16-solid.d.ts.map +1 -0
  305. package/dist/icons/generated/heroicons-check-16-solid.js +3 -4
  306. package/dist/icons/generated/heroicons-check-16-solid.js.map +1 -1
  307. package/dist/icons/generated/heroicons-x-mark-16-solid.d.ts +5 -4
  308. package/dist/icons/generated/heroicons-x-mark-16-solid.d.ts.map +1 -0
  309. package/dist/icons/generated/heroicons-x-mark-16-solid.js +3 -4
  310. package/dist/icons/generated/heroicons-x-mark-16-solid.js.map +1 -1
  311. package/dist/icons/generated/jam-close-circle-f.d.ts +7 -6
  312. package/dist/icons/generated/jam-close-circle-f.d.ts.map +1 -0
  313. package/dist/icons/generated/jam-close-circle-f.js +3 -4
  314. package/dist/icons/generated/jam-close-circle-f.js.map +1 -1
  315. package/dist/icons/generated/lucide-arrow-down-to-line.d.ts +5 -4
  316. package/dist/icons/generated/lucide-arrow-down-to-line.d.ts.map +1 -0
  317. package/dist/icons/generated/lucide-arrow-down-to-line.js +3 -4
  318. package/dist/icons/generated/lucide-arrow-down-to-line.js.map +1 -1
  319. package/dist/icons/generated/lucide-arrow-up-to-line.d.ts +5 -4
  320. package/dist/icons/generated/lucide-arrow-up-to-line.d.ts.map +1 -0
  321. package/dist/icons/generated/lucide-arrow-up-to-line.js +3 -4
  322. package/dist/icons/generated/lucide-arrow-up-to-line.js.map +1 -1
  323. package/dist/icons/generated/lucide-bell.d.ts +5 -4
  324. package/dist/icons/generated/lucide-bell.d.ts.map +1 -0
  325. package/dist/icons/generated/lucide-bell.js +3 -4
  326. package/dist/icons/generated/lucide-bell.js.map +1 -1
  327. package/dist/icons/generated/lucide-check.d.ts +5 -4
  328. package/dist/icons/generated/lucide-check.d.ts.map +1 -0
  329. package/dist/icons/generated/lucide-check.js +3 -4
  330. package/dist/icons/generated/lucide-check.js.map +1 -1
  331. package/dist/icons/generated/lucide-chevron-down.d.ts +5 -4
  332. package/dist/icons/generated/lucide-chevron-down.d.ts.map +1 -0
  333. package/dist/icons/generated/lucide-chevron-down.js +3 -4
  334. package/dist/icons/generated/lucide-chevron-down.js.map +1 -1
  335. package/dist/icons/generated/lucide-chevron-left.d.ts +5 -4
  336. package/dist/icons/generated/lucide-chevron-left.d.ts.map +1 -0
  337. package/dist/icons/generated/lucide-chevron-left.js +3 -4
  338. package/dist/icons/generated/lucide-chevron-left.js.map +1 -1
  339. package/dist/icons/generated/lucide-chevron-right.d.ts +5 -4
  340. package/dist/icons/generated/lucide-chevron-right.d.ts.map +1 -0
  341. package/dist/icons/generated/lucide-chevron-right.js +3 -4
  342. package/dist/icons/generated/lucide-chevron-right.js.map +1 -1
  343. package/dist/icons/generated/lucide-chevron-up.d.ts +5 -4
  344. package/dist/icons/generated/lucide-chevron-up.d.ts.map +1 -0
  345. package/dist/icons/generated/lucide-chevron-up.js +3 -4
  346. package/dist/icons/generated/lucide-chevron-up.js.map +1 -1
  347. package/dist/icons/generated/lucide-circle-alert.d.ts +5 -4
  348. package/dist/icons/generated/lucide-circle-alert.d.ts.map +1 -0
  349. package/dist/icons/generated/lucide-circle-alert.js +3 -4
  350. package/dist/icons/generated/lucide-circle-alert.js.map +1 -1
  351. package/dist/icons/generated/lucide-clapperboard.d.ts +5 -4
  352. package/dist/icons/generated/lucide-clapperboard.d.ts.map +1 -0
  353. package/dist/icons/generated/lucide-clapperboard.js +3 -4
  354. package/dist/icons/generated/lucide-clapperboard.js.map +1 -1
  355. package/dist/icons/generated/lucide-clipboard-paste.d.ts +5 -4
  356. package/dist/icons/generated/lucide-clipboard-paste.d.ts.map +1 -0
  357. package/dist/icons/generated/lucide-clipboard-paste.js +3 -4
  358. package/dist/icons/generated/lucide-clipboard-paste.js.map +1 -1
  359. package/dist/icons/generated/lucide-code.d.ts +5 -4
  360. package/dist/icons/generated/lucide-code.d.ts.map +1 -0
  361. package/dist/icons/generated/lucide-code.js +3 -4
  362. package/dist/icons/generated/lucide-code.js.map +1 -1
  363. package/dist/icons/generated/lucide-copy.d.ts +5 -4
  364. package/dist/icons/generated/lucide-copy.d.ts.map +1 -0
  365. package/dist/icons/generated/lucide-copy.js +3 -4
  366. package/dist/icons/generated/lucide-copy.js.map +1 -1
  367. package/dist/icons/generated/lucide-download.d.ts +5 -4
  368. package/dist/icons/generated/lucide-download.d.ts.map +1 -0
  369. package/dist/icons/generated/lucide-download.js +3 -4
  370. package/dist/icons/generated/lucide-download.js.map +1 -1
  371. package/dist/icons/generated/lucide-ellipsis-vertical.d.ts +5 -4
  372. package/dist/icons/generated/lucide-ellipsis-vertical.d.ts.map +1 -0
  373. package/dist/icons/generated/lucide-ellipsis-vertical.js +3 -4
  374. package/dist/icons/generated/lucide-ellipsis-vertical.js.map +1 -1
  375. package/dist/icons/generated/lucide-external-link.d.ts +5 -4
  376. package/dist/icons/generated/lucide-external-link.d.ts.map +1 -0
  377. package/dist/icons/generated/lucide-external-link.js +3 -4
  378. package/dist/icons/generated/lucide-external-link.js.map +1 -1
  379. package/dist/icons/generated/lucide-eye.d.ts +5 -4
  380. package/dist/icons/generated/lucide-eye.d.ts.map +1 -0
  381. package/dist/icons/generated/lucide-eye.js +3 -4
  382. package/dist/icons/generated/lucide-eye.js.map +1 -1
  383. package/dist/icons/generated/lucide-file-text.d.ts +5 -4
  384. package/dist/icons/generated/lucide-file-text.d.ts.map +1 -0
  385. package/dist/icons/generated/lucide-file-text.js +3 -4
  386. package/dist/icons/generated/lucide-file-text.js.map +1 -1
  387. package/dist/icons/generated/lucide-file.d.ts +5 -4
  388. package/dist/icons/generated/lucide-file.d.ts.map +1 -0
  389. package/dist/icons/generated/lucide-file.js +3 -4
  390. package/dist/icons/generated/lucide-file.js.map +1 -1
  391. package/dist/icons/generated/lucide-film.d.ts +5 -4
  392. package/dist/icons/generated/lucide-film.d.ts.map +1 -0
  393. package/dist/icons/generated/lucide-film.js +3 -4
  394. package/dist/icons/generated/lucide-film.js.map +1 -1
  395. package/dist/icons/generated/lucide-folder-open.d.ts +5 -4
  396. package/dist/icons/generated/lucide-folder-open.d.ts.map +1 -0
  397. package/dist/icons/generated/lucide-folder-open.js +3 -4
  398. package/dist/icons/generated/lucide-folder-open.js.map +1 -1
  399. package/dist/icons/generated/lucide-folder.d.ts +5 -4
  400. package/dist/icons/generated/lucide-folder.d.ts.map +1 -0
  401. package/dist/icons/generated/lucide-folder.js +3 -4
  402. package/dist/icons/generated/lucide-folder.js.map +1 -1
  403. package/dist/icons/generated/lucide-globe.d.ts +5 -4
  404. package/dist/icons/generated/lucide-globe.d.ts.map +1 -0
  405. package/dist/icons/generated/lucide-globe.js +3 -4
  406. package/dist/icons/generated/lucide-globe.js.map +1 -1
  407. package/dist/icons/generated/lucide-headphones.d.ts +5 -4
  408. package/dist/icons/generated/lucide-headphones.d.ts.map +1 -0
  409. package/dist/icons/generated/lucide-headphones.js +3 -4
  410. package/dist/icons/generated/lucide-headphones.js.map +1 -1
  411. package/dist/icons/generated/lucide-heart.d.ts +5 -4
  412. package/dist/icons/generated/lucide-heart.d.ts.map +1 -0
  413. package/dist/icons/generated/lucide-heart.js +3 -4
  414. package/dist/icons/generated/lucide-heart.js.map +1 -1
  415. package/dist/icons/generated/lucide-image.d.ts +5 -4
  416. package/dist/icons/generated/lucide-image.d.ts.map +1 -0
  417. package/dist/icons/generated/lucide-image.js +3 -4
  418. package/dist/icons/generated/lucide-image.js.map +1 -1
  419. package/dist/icons/generated/lucide-inbox.d.ts +5 -4
  420. package/dist/icons/generated/lucide-inbox.d.ts.map +1 -0
  421. package/dist/icons/generated/lucide-inbox.js +3 -4
  422. package/dist/icons/generated/lucide-inbox.js.map +1 -1
  423. package/dist/icons/generated/lucide-info.d.ts +5 -4
  424. package/dist/icons/generated/lucide-info.d.ts.map +1 -0
  425. package/dist/icons/generated/lucide-info.js +3 -4
  426. package/dist/icons/generated/lucide-info.js.map +1 -1
  427. package/dist/icons/generated/lucide-layout-grid.d.ts +5 -4
  428. package/dist/icons/generated/lucide-layout-grid.d.ts.map +1 -0
  429. package/dist/icons/generated/lucide-layout-grid.js +3 -4
  430. package/dist/icons/generated/lucide-layout-grid.js.map +1 -1
  431. package/dist/icons/generated/lucide-link.d.ts +5 -4
  432. package/dist/icons/generated/lucide-link.d.ts.map +1 -0
  433. package/dist/icons/generated/lucide-link.js +3 -4
  434. package/dist/icons/generated/lucide-link.js.map +1 -1
  435. package/dist/icons/generated/lucide-list-filter.d.ts +5 -4
  436. package/dist/icons/generated/lucide-list-filter.d.ts.map +1 -0
  437. package/dist/icons/generated/lucide-list-filter.js +3 -4
  438. package/dist/icons/generated/lucide-list-filter.js.map +1 -1
  439. package/dist/icons/generated/lucide-list-restart.d.ts +5 -4
  440. package/dist/icons/generated/lucide-list-restart.d.ts.map +1 -0
  441. package/dist/icons/generated/lucide-list-restart.js +3 -4
  442. package/dist/icons/generated/lucide-list-restart.js.map +1 -1
  443. package/dist/icons/generated/lucide-loader-circle.d.ts +5 -4
  444. package/dist/icons/generated/lucide-loader-circle.d.ts.map +1 -0
  445. package/dist/icons/generated/lucide-loader-circle.js +3 -4
  446. package/dist/icons/generated/lucide-loader-circle.js.map +1 -1
  447. package/dist/icons/generated/lucide-mail.d.ts +5 -4
  448. package/dist/icons/generated/lucide-mail.d.ts.map +1 -0
  449. package/dist/icons/generated/lucide-mail.js +3 -4
  450. package/dist/icons/generated/lucide-mail.js.map +1 -1
  451. package/dist/icons/generated/lucide-minus.d.ts +5 -4
  452. package/dist/icons/generated/lucide-minus.d.ts.map +1 -0
  453. package/dist/icons/generated/lucide-minus.js +3 -4
  454. package/dist/icons/generated/lucide-minus.js.map +1 -1
  455. package/dist/icons/generated/lucide-music.d.ts +5 -4
  456. package/dist/icons/generated/lucide-music.d.ts.map +1 -0
  457. package/dist/icons/generated/lucide-music.js +3 -4
  458. package/dist/icons/generated/lucide-music.js.map +1 -1
  459. package/dist/icons/generated/lucide-package.d.ts +5 -4
  460. package/dist/icons/generated/lucide-package.d.ts.map +1 -0
  461. package/dist/icons/generated/lucide-package.js +3 -4
  462. package/dist/icons/generated/lucide-package.js.map +1 -1
  463. package/dist/icons/generated/lucide-pen-line.d.ts +5 -4
  464. package/dist/icons/generated/lucide-pen-line.d.ts.map +1 -0
  465. package/dist/icons/generated/lucide-pen-line.js +3 -4
  466. package/dist/icons/generated/lucide-pen-line.js.map +1 -1
  467. package/dist/icons/generated/lucide-pencil.d.ts +5 -4
  468. package/dist/icons/generated/lucide-pencil.d.ts.map +1 -0
  469. package/dist/icons/generated/lucide-pencil.js +3 -4
  470. package/dist/icons/generated/lucide-pencil.js.map +1 -1
  471. package/dist/icons/generated/lucide-play.d.ts +5 -4
  472. package/dist/icons/generated/lucide-play.d.ts.map +1 -0
  473. package/dist/icons/generated/lucide-play.js +3 -4
  474. package/dist/icons/generated/lucide-play.js.map +1 -1
  475. package/dist/icons/generated/lucide-plus.d.ts +5 -4
  476. package/dist/icons/generated/lucide-plus.d.ts.map +1 -0
  477. package/dist/icons/generated/lucide-plus.js +3 -4
  478. package/dist/icons/generated/lucide-plus.js.map +1 -1
  479. package/dist/icons/generated/lucide-printer.d.ts +5 -4
  480. package/dist/icons/generated/lucide-printer.d.ts.map +1 -0
  481. package/dist/icons/generated/lucide-printer.js +3 -4
  482. package/dist/icons/generated/lucide-printer.js.map +1 -1
  483. package/dist/icons/generated/lucide-redo-2.d.ts +5 -4
  484. package/dist/icons/generated/lucide-redo-2.d.ts.map +1 -0
  485. package/dist/icons/generated/lucide-redo-2.js +3 -4
  486. package/dist/icons/generated/lucide-redo-2.js.map +1 -1
  487. package/dist/icons/generated/lucide-refresh-cw.d.ts +5 -4
  488. package/dist/icons/generated/lucide-refresh-cw.d.ts.map +1 -0
  489. package/dist/icons/generated/lucide-refresh-cw.js +3 -4
  490. package/dist/icons/generated/lucide-refresh-cw.js.map +1 -1
  491. package/dist/icons/generated/lucide-scissors.d.ts +5 -4
  492. package/dist/icons/generated/lucide-scissors.d.ts.map +1 -0
  493. package/dist/icons/generated/lucide-scissors.js +3 -4
  494. package/dist/icons/generated/lucide-scissors.js.map +1 -1
  495. package/dist/icons/generated/lucide-search.d.ts +5 -4
  496. package/dist/icons/generated/lucide-search.d.ts.map +1 -0
  497. package/dist/icons/generated/lucide-search.js +3 -4
  498. package/dist/icons/generated/lucide-search.js.map +1 -1
  499. package/dist/icons/generated/lucide-settings.d.ts +5 -4
  500. package/dist/icons/generated/lucide-settings.d.ts.map +1 -0
  501. package/dist/icons/generated/lucide-settings.js +3 -4
  502. package/dist/icons/generated/lucide-settings.js.map +1 -1
  503. package/dist/icons/generated/lucide-sliders-horizontal.d.ts +5 -4
  504. package/dist/icons/generated/lucide-sliders-horizontal.d.ts.map +1 -0
  505. package/dist/icons/generated/lucide-sliders-horizontal.js +3 -4
  506. package/dist/icons/generated/lucide-sliders-horizontal.js.map +1 -1
  507. package/dist/icons/generated/lucide-star.d.ts +5 -4
  508. package/dist/icons/generated/lucide-star.d.ts.map +1 -0
  509. package/dist/icons/generated/lucide-star.js +3 -4
  510. package/dist/icons/generated/lucide-star.js.map +1 -1
  511. package/dist/icons/generated/lucide-tag.d.ts +5 -4
  512. package/dist/icons/generated/lucide-tag.d.ts.map +1 -0
  513. package/dist/icons/generated/lucide-tag.js +3 -4
  514. package/dist/icons/generated/lucide-tag.js.map +1 -1
  515. package/dist/icons/generated/lucide-tags.d.ts +5 -4
  516. package/dist/icons/generated/lucide-tags.d.ts.map +1 -0
  517. package/dist/icons/generated/lucide-tags.js +3 -4
  518. package/dist/icons/generated/lucide-tags.js.map +1 -1
  519. package/dist/icons/generated/lucide-trash-2.d.ts +5 -4
  520. package/dist/icons/generated/lucide-trash-2.d.ts.map +1 -0
  521. package/dist/icons/generated/lucide-trash-2.js +3 -4
  522. package/dist/icons/generated/lucide-trash-2.js.map +1 -1
  523. package/dist/icons/generated/lucide-triangle-alert.d.ts +5 -4
  524. package/dist/icons/generated/lucide-triangle-alert.d.ts.map +1 -0
  525. package/dist/icons/generated/lucide-triangle-alert.js +3 -4
  526. package/dist/icons/generated/lucide-triangle-alert.js.map +1 -1
  527. package/dist/icons/generated/lucide-undo-2.d.ts +5 -4
  528. package/dist/icons/generated/lucide-undo-2.d.ts.map +1 -0
  529. package/dist/icons/generated/lucide-undo-2.js +3 -4
  530. package/dist/icons/generated/lucide-undo-2.js.map +1 -1
  531. package/dist/icons/generated/lucide-upload.d.ts +5 -4
  532. package/dist/icons/generated/lucide-upload.d.ts.map +1 -0
  533. package/dist/icons/generated/lucide-upload.js +3 -4
  534. package/dist/icons/generated/lucide-upload.js.map +1 -1
  535. package/dist/icons/generated/lucide-user.d.ts +5 -4
  536. package/dist/icons/generated/lucide-user.d.ts.map +1 -0
  537. package/dist/icons/generated/lucide-user.js +3 -4
  538. package/dist/icons/generated/lucide-user.js.map +1 -1
  539. package/dist/icons/generated/lucide-wrench.d.ts +5 -4
  540. package/dist/icons/generated/lucide-wrench.d.ts.map +1 -0
  541. package/dist/icons/generated/lucide-wrench.js +3 -4
  542. package/dist/icons/generated/lucide-wrench.js.map +1 -1
  543. package/dist/icons/generated/lucide-x.d.ts +5 -4
  544. package/dist/icons/generated/lucide-x.d.ts.map +1 -0
  545. package/dist/icons/generated/lucide-x.js +3 -4
  546. package/dist/icons/generated/lucide-x.js.map +1 -1
  547. package/dist/icons/generated/mdi-tag-search-outline.d.ts +5 -4
  548. package/dist/icons/generated/mdi-tag-search-outline.d.ts.map +1 -0
  549. package/dist/icons/generated/mdi-tag-search-outline.js +3 -4
  550. package/dist/icons/generated/mdi-tag-search-outline.js.map +1 -1
  551. package/dist/icons/generated/ooui-close.d.ts +5 -4
  552. package/dist/icons/generated/ooui-close.d.ts.map +1 -0
  553. package/dist/icons/generated/ooui-close.js +3 -4
  554. package/dist/icons/generated/ooui-close.js.map +1 -1
  555. package/dist/icons/generated/radix-icons-panel-left-minimized.d.ts +5 -4
  556. package/dist/icons/generated/radix-icons-panel-left-minimized.d.ts.map +1 -0
  557. package/dist/icons/generated/radix-icons-panel-left-minimized.js +3 -4
  558. package/dist/icons/generated/radix-icons-panel-left-minimized.js.map +1 -1
  559. package/dist/icons/generated/radix-icons-reset.d.ts +5 -4
  560. package/dist/icons/generated/radix-icons-reset.d.ts.map +1 -0
  561. package/dist/icons/generated/radix-icons-reset.js +3 -4
  562. package/dist/icons/generated/radix-icons-reset.js.map +1 -1
  563. package/dist/icons/generated/tabler-sort-ascending-letters.d.ts +5 -4
  564. package/dist/icons/generated/tabler-sort-ascending-letters.d.ts.map +1 -0
  565. package/dist/icons/generated/tabler-sort-ascending-letters.js +3 -4
  566. package/dist/icons/generated/tabler-sort-ascending-letters.js.map +1 -1
  567. package/dist/icons/index.d.ts +75 -74
  568. package/dist/icons/index.js +75 -75
  569. package/dist/shared/element-height/index.js +51 -25
  570. package/dist/shared/element-height/index.js.map +1 -1
  571. package/dist/shared/element-width/index.js +39 -24
  572. package/dist/shared/element-width/index.js.map +1 -1
  573. package/dist/shared/events/user-change.js +14 -8
  574. package/dist/shared/events/user-change.js.map +1 -1
  575. package/dist/shared/focus/pointer-focus.js +56 -30
  576. package/dist/shared/focus/pointer-focus.js.map +1 -1
  577. package/dist/shared/focus/tabbable.js +96 -0
  578. package/dist/shared/focus/tabbable.js.map +1 -0
  579. package/dist/shared/form-association/field-id.js +13 -6
  580. package/dist/shared/form-association/field-id.js.map +1 -1
  581. package/dist/shared/form-association/index.js +75 -42
  582. package/dist/shared/form-association/index.js.map +1 -1
  583. package/dist/shared/gesture/drag-gesture.js +239 -99
  584. package/dist/shared/gesture/drag-gesture.js.map +1 -1
  585. package/dist/shared/gesture/physics.js +49 -16
  586. package/dist/shared/gesture/physics.js.map +1 -1
  587. package/dist/shared/gesture/pinch-gesture.js +111 -60
  588. package/dist/shared/gesture/pinch-gesture.js.map +1 -1
  589. package/dist/shared/group-management/index.js +181 -84
  590. package/dist/shared/group-management/index.js.map +1 -1
  591. package/dist/shared/label-emptiness/index.js +45 -26
  592. package/dist/shared/label-emptiness/index.js.map +1 -1
  593. package/dist/shared/locale/builtin-labels.js +38 -0
  594. package/dist/shared/locale/builtin-labels.js.map +1 -0
  595. package/dist/shared/menu-behavior/index.js +113 -60
  596. package/dist/shared/menu-behavior/index.js.map +1 -1
  597. package/dist/shared/menu-portal/menu-portal.js +47 -26
  598. package/dist/shared/menu-portal/menu-portal.js.map +1 -1
  599. package/dist/shared/menu-portal/menu-tree.js +132 -75
  600. package/dist/shared/menu-portal/menu-tree.js.map +1 -1
  601. package/dist/shared/normalize/index.js +16 -7
  602. package/dist/shared/normalize/index.js.map +1 -1
  603. package/dist/shared/open-state/index.js +7 -8
  604. package/dist/shared/open-state/index.js.map +1 -1
  605. package/dist/shared/option-portal/combobox-shell.js +121 -56
  606. package/dist/shared/option-portal/combobox-shell.js.map +1 -1
  607. package/dist/shared/option-portal/index.js +65 -44
  608. package/dist/shared/option-portal/index.js.map +1 -1
  609. package/dist/shared/overlay/anchored-panel.js +75 -40
  610. package/dist/shared/overlay/anchored-panel.js.map +1 -1
  611. package/dist/shared/overlay/native-dialog-presence.js +116 -52
  612. package/dist/shared/overlay/native-dialog-presence.js.map +1 -1
  613. package/dist/shared/overlay/nested-drawer-layers.js +76 -46
  614. package/dist/shared/overlay/nested-drawer-layers.js.map +1 -1
  615. package/dist/shared/overlay/open-overlay.js +240 -136
  616. package/dist/shared/overlay/open-overlay.js.map +1 -1
  617. package/dist/shared/overlay/overlay-root.js +33 -24
  618. package/dist/shared/overlay/overlay-root.js.map +1 -1
  619. package/dist/shared/overlay/overlay.js +109 -66
  620. package/dist/shared/overlay/overlay.js.map +1 -1
  621. package/dist/shared/overlay/placement-props.js +9 -4
  622. package/dist/shared/overlay/placement-props.js.map +1 -1
  623. package/dist/shared/overlay/portal.d.ts +2 -0
  624. package/dist/shared/overlay/portal.d.ts.map +1 -0
  625. package/dist/shared/overlay/portal.js +202 -117
  626. package/dist/shared/overlay/portal.js.map +1 -1
  627. package/dist/shared/overlay/positioning-generation.js +9 -10
  628. package/dist/shared/overlay/positioning-generation.js.map +1 -1
  629. package/dist/shared/overlay/presence.js +43 -21
  630. package/dist/shared/overlay/presence.js.map +1 -1
  631. package/dist/shared/overlay/theme-overlay-scope.js +22 -19
  632. package/dist/shared/overlay/theme-overlay-scope.js.map +1 -1
  633. package/dist/shared/scroll-lock/scroll-lock.js +49 -15
  634. package/dist/shared/scroll-lock/scroll-lock.js.map +1 -1
  635. package/dist/shared/theme/duration.js +13 -6
  636. package/dist/shared/theme/duration.js.map +1 -1
  637. package/dist/shared/theme/reduced-motion.js +14 -9
  638. package/dist/shared/theme/reduced-motion.js.map +1 -1
  639. package/dist/shared/theme/root-sync.js +85 -32
  640. package/dist/shared/theme/root-sync.js.map +1 -1
  641. package/dist/shared/visible-area/index.js +81 -37
  642. package/dist/shared/visible-area/index.js.map +1 -1
  643. package/dist/types/iconify.d.ts +1 -1
  644. package/dist/types/iconify.js +0 -0
  645. package/dist/types/react.d.ts +8 -10
  646. package/dist/types/react.d.ts.map +1 -0
  647. package/dist/types/react.js +0 -0
  648. package/dist/types/utils.d.ts +8 -13
  649. package/dist/types/utils.d.ts.map +1 -0
  650. package/dist/types/utils.js +0 -0
  651. package/dist/types/vue.d.ts +9 -13
  652. package/dist/types/vue.d.ts.map +1 -0
  653. package/dist/types/vue.js +0 -0
  654. package/dist/vite/index.d.ts +1 -0
  655. package/dist/vite/index.d.ts.map +1 -0
  656. package/dist/vite/index.js +30 -4
  657. package/dist/vite/index.js.map +1 -1
  658. package/package.json +10 -23
  659. package/dist/_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js +0 -9
  660. package/dist/components/middle-ellipsis/truncate.d.ts +0 -62
  661. package/dist/components/radio/interaction.d.ts +0 -4
  662. package/dist/scrollbars/index.d.ts +0 -33
  663. package/dist/scrollbars/index.js +0 -18
  664. package/dist/scrollbars/index.js.map +0 -1
  665. package/dist/scrollbars/internal.js +0 -6
  666. package/dist/scrollbars/internal.js.map +0 -1
  667. package/dist/scrollbars/style.css +0 -10
@@ -1,151 +1,236 @@
1
- import { getFallbackOverlayRoot as e } from "./overlay-root.js";
2
- import { findNearestTheme as t, findRootTheme as n } from "./theme-overlay-scope.js";
3
- import { definePlugin as r } from "@greypan/js-kit";
4
- //#region src/shared/overlay/portal.ts
5
- function i(e, t, n) {
6
- let r = getComputedStyle(t);
7
- for (let t of n) {
8
- let n = r.getPropertyValue(t).trim();
9
- n && e.style.setProperty(t, n);
1
+ import { getFallbackOverlayRoot } from "./overlay-root.js";
2
+ import { findNearestTheme, findRootTheme } from "./theme-overlay-scope.js";
3
+ import { definePlugin } from "@greypan/js-kit";
4
+ // src/shared/overlay/portal.ts
5
+ /**
6
+ * Portal panel 位于独立 shadow root,宿主上的 CSS 自定义属性不会沿渲染树继承到 panel。
7
+ * 这里在创建时镜像锚点解析后的变量,让组件 host 上的尺寸配置对 portal 仍然生效。
8
+ */
9
+ function applyOverlayVariables(panel, source, variables) {
10
+ const computedStyle = getComputedStyle(source);
11
+ for (const variable of variables) {
12
+ const value = computedStyle.getPropertyValue(variable).trim();
13
+ if (value) panel.style.setProperty(variable, value);
10
14
  }
11
15
  }
12
- var a = "wui-portal-content-anchor", o = () => r((e) => {
13
- let t = document.createElement("div");
14
- t.style.display = "contents";
15
- let n = t.attachShadow({ mode: "open" }), r = document.createElement("style");
16
- r.textContent = e.style;
17
- let i = document.createElement("div");
18
- i.className = e.className, i.dataset.wuiPresence = "entering", n.append(r, i);
19
- let o = [], s = new MutationObserver((t) => {
20
- f(t);
21
- let n = new Set(t.flatMap((e) => [...e.addedNodes])), r = t.flatMap((e) => [...e.removedNodes]).filter((e) => !n.has(e));
22
- r.length && l(r), e.onContentChange?.(t);
23
- }), c = (e) => {
24
- let t = e.parentNode;
25
- if (!t) return null;
26
- let n = document.createComment(a);
27
- t.insertBefore(n, e);
28
- let r = {
29
- node: e,
30
- marker: n
16
+ const PORTAL_CONTENT_MARKER = "wui-portal-content-anchor";
17
+ /**
18
+ * 构建带 Shadow DOM 样式边界的 Portal panel,并追踪被迁移的内容节点以便恢复。
19
+ */
20
+ const defineOverlayPortal = () => definePlugin((ctx) => {
21
+ const host = document.createElement("div");
22
+ host.style.display = "contents";
23
+ const root = host.attachShadow({ mode: "open" });
24
+ const style = document.createElement("style");
25
+ style.textContent = ctx.style;
26
+ const panel = document.createElement("div");
27
+ panel.className = ctx.className;
28
+ panel.dataset.wuiPresence = "entering";
29
+ root.append(style, panel);
30
+ const trackedNodes = [];
31
+ const contentObserver = new MutationObserver((mutations) => {
32
+ returnStrayFrameworkComments(mutations);
33
+ const addedInBatch = new Set(mutations.flatMap((mutation) => [...mutation.addedNodes]));
34
+ const removedNodes = mutations.flatMap((mutation) => [...mutation.removedNodes]).filter((node) => !addedInBatch.has(node));
35
+ if (removedNodes.length) untrackNodes(removedNodes);
36
+ ctx.onContentChange?.(mutations);
37
+ });
38
+ const recordEntry = (node) => {
39
+ const parent = node.parentNode;
40
+ if (!parent) return null;
41
+ const marker = document.createComment(PORTAL_CONTENT_MARKER);
42
+ parent.insertBefore(marker, node);
43
+ const entry = {
44
+ node,
45
+ marker
31
46
  };
32
- return o.push(r), r;
33
- }, l = (e) => {
34
- for (let t of e) {
35
- let e = o.findIndex((e) => e.node === t);
36
- e >= 0 && (o[e].marker.remove(), o.splice(e, 1));
47
+ trackedNodes.push(entry);
48
+ return entry;
49
+ };
50
+ const untrackNodes = (nodes) => {
51
+ for (const node of nodes) {
52
+ const index = trackedNodes.findIndex((entry) => entry.node === node);
53
+ if (index >= 0) {
54
+ trackedNodes[index].marker.remove();
55
+ trackedNodes.splice(index, 1);
56
+ }
37
57
  }
38
- }, d = (t) => {
39
- let n = [];
40
- for (let r of Array.from(e.target.childNodes)) if (r instanceof Comment && r.textContent === a) {
41
- let e = o.find((e) => e.marker === r);
42
- e && e.node.parentNode === t && n.push(e.node);
58
+ };
59
+ const orderTargetBySkeleton = (target) => {
60
+ const skeleton = [];
61
+ for (const node of Array.from(ctx.target.childNodes)) if (node instanceof Comment && node.textContent === PORTAL_CONTENT_MARKER) {
62
+ const entry = trackedNodes.find((e) => e.marker === node);
63
+ if (entry && entry.node.parentNode === target) skeleton.push(entry.node);
43
64
  }
44
- if (n.length === 0) return;
45
- let r = Array.from(t.childNodes).filter((e) => n.includes(e) || !(e instanceof Comment));
46
- if (!(r.length === n.length && r.every((e, t) => e === n[t]))) for (let e = n.length - 1; e >= 0; e--) {
47
- let r = n[e], i = n[e + 1];
48
- i ? r.nextElementSibling !== i && t.insertBefore(r, i) : t.appendChild(r);
65
+ if (skeleton.length === 0) return;
66
+ const current = Array.from(target.childNodes).filter((node) => skeleton.includes(node) || !(node instanceof Comment));
67
+ if (current.length === skeleton.length && current.every((node, index) => node === skeleton[index])) return;
68
+ for (let index = skeleton.length - 1; index >= 0; index--) {
69
+ const node = skeleton[index];
70
+ const next = skeleton[index + 1];
71
+ if (next) {
72
+ if (node.nextElementSibling !== next) target.insertBefore(node, next);
73
+ } else target.appendChild(node);
49
74
  }
50
- }, f = (t) => {
51
- let n = (e) => {
52
- let t = e;
53
- for (; t && t !== i;) {
54
- if (o.some((e) => e.node === t)) return !0;
55
- t = t.parentNode;
75
+ };
76
+ /**
77
+ * 打开期不变量:框架删除已迁移节点时,其条件渲染占位注释(v-if 等)会被插进
78
+ * panel 内容区而不是宿主——block 子树 patch 以 hostParentNode(oldVNode.el) 重定
79
+ * container,而旧 el 已在 panel(可能是 panel 自身或组件的内容子容器)。
80
+ * 注释是框架后续翻转依赖的 vnode.el:留在 panel 会随 panel 销毁,下次翻转把内容插进
81
+ * 已脱离文档的旧 panel(内容"既不在宿主也不在 panel"且无法恢复)。
82
+ * 每个 panel mutation 批次内即时归还:与同批次被框架删除的 tracked 节点按宿主
83
+ * marker 序配对,插到其 marker 位(多注释对多删除为近似配对;无配对时落宿主
84
+ * 骨架末尾兜底)。tracked 子树内的注释是迁移内容自身的嵌套条件渲染,不属游离
85
+ * 锚点,必须留在原位;随整个子树被删的注释已不在 panel 内,无需救援。
86
+ */
87
+ const returnStrayFrameworkComments = (mutations) => {
88
+ const isInsideTrackedSubtree = (start) => {
89
+ let current = start;
90
+ while (current && current !== panel) {
91
+ if (trackedNodes.some((entry) => entry.node === current)) return true;
92
+ current = current.parentNode;
56
93
  }
57
- return !1;
58
- }, r = new Set(t.flatMap((e) => [...e.addedNodes])), s = [];
59
- for (let e of t) for (let t of e.addedNodes) t instanceof Comment && t.textContent !== a && i.contains(t) && (n(e.target) || s.push(t));
60
- if (!s.length) return;
61
- let c = Array.from(e.target.childNodes), l = o.filter((e) => !r.has(e.node) && t.some((t) => [...t.removedNodes].includes(e.node))).sort((e, t) => c.indexOf(e.marker) - c.indexOf(t.marker));
62
- for (let [t, n] of s.entries()) {
63
- let r = l[Math.min(t, l.length - 1)]?.marker;
64
- r && r.parentNode === e.target ? e.target.insertBefore(n, r) : e.target.appendChild(n);
94
+ return false;
95
+ };
96
+ const addedNodes = new Set(mutations.flatMap((mutation) => [...mutation.addedNodes]));
97
+ const strays = [];
98
+ for (const mutation of mutations) for (const node of mutation.addedNodes) {
99
+ if (!(node instanceof Comment) || node.textContent === PORTAL_CONTENT_MARKER) continue;
100
+ if (!panel.contains(node)) continue;
101
+ if (isInsideTrackedSubtree(mutation.target)) continue;
102
+ strays.push(node);
103
+ }
104
+ if (!strays.length) return;
105
+ const hostChildren = Array.from(ctx.target.childNodes);
106
+ const removedEntries = trackedNodes.filter((entry) => !addedNodes.has(entry.node) && mutations.some((mutation) => [...mutation.removedNodes].includes(entry.node))).sort((a, b) => hostChildren.indexOf(a.marker) - hostChildren.indexOf(b.marker));
107
+ for (const [index, comment] of strays.entries()) {
108
+ const marker = removedEntries[Math.min(index, removedEntries.length - 1)]?.marker;
109
+ if (marker && marker.parentNode === ctx.target) ctx.target.insertBefore(comment, marker);
110
+ else ctx.target.appendChild(comment);
65
111
  }
66
112
  };
67
- u(e.container, e.target).appendChild(t), s.observe(i, {
68
- childList: !0,
69
- subtree: !0
113
+ resolveOverlayContainer(ctx.container, ctx.target).appendChild(host);
114
+ contentObserver.observe(panel, {
115
+ childList: true,
116
+ subtree: true
70
117
  });
71
- let p = e.migrateAddedNodes, m = new MutationObserver((e) => {
72
- let t = new Set(e.flatMap((e) => [...e.addedNodes])), n = e.flatMap((e) => [...e.removedNodes]).filter((e) => e instanceof Comment && e.textContent === a && !t.has(e)).map((e) => o.find((t) => t.marker === e)?.node).filter((e) => e !== void 0);
73
- if (n.length) {
74
- h.removeContent(n);
75
- for (let e of n) e.parentNode?.removeChild(e);
118
+ const migrateAddedNodes = ctx.migrateAddedNodes;
119
+ const hostObserver = new MutationObserver((mutations) => {
120
+ const addedNodes = new Set(mutations.flatMap((mutation) => [...mutation.addedNodes]));
121
+ const strandedNodes = mutations.flatMap((mutation) => [...mutation.removedNodes]).filter((node) => node instanceof Comment && node.textContent === PORTAL_CONTENT_MARKER && !addedNodes.has(node)).map((marker) => trackedNodes.find((entry) => entry.marker === marker)?.node).filter((node) => node !== void 0);
122
+ if (strandedNodes.length) {
123
+ api.removeContent(strandedNodes);
124
+ for (const node of strandedNodes) node.parentNode?.removeChild(node);
76
125
  }
77
- if (!p) return;
78
- let r = p(e.flatMap((e) => [...e.addedNodes]));
79
- r.length && h.appendContent(r);
126
+ if (!migrateAddedNodes) return;
127
+ const migratable = migrateAddedNodes(mutations.flatMap((mutation) => [...mutation.addedNodes]));
128
+ if (migratable.length) api.appendContent(migratable);
80
129
  });
81
- m.observe(e.target, { childList: !0 });
82
- let h = {
83
- panel: i,
84
- moveContent(e, t = i) {
85
- o.forEach((e) => e.marker.remove());
86
- let n = e.map(c).filter((e) => e !== null);
87
- o.length = 0, o.push(...n), t.append(...e), d(t);
130
+ hostObserver.observe(ctx.target, { childList: true });
131
+ const api = {
132
+ panel,
133
+ moveContent(nodes, target = panel) {
134
+ trackedNodes.forEach((entry) => entry.marker.remove());
135
+ const entries = nodes.map(recordEntry).filter((entry) => entry !== null);
136
+ trackedNodes.length = 0;
137
+ trackedNodes.push(...entries);
138
+ target.append(...nodes);
139
+ orderTargetBySkeleton(target);
88
140
  },
89
- appendContent(e, t = i) {
90
- for (let n of e) {
91
- l([n]);
92
- let e = c(n);
93
- e && t.appendChild(e.node);
141
+ appendContent(nodes, target = panel) {
142
+ for (const node of nodes) {
143
+ untrackNodes([node]);
144
+ const entry = recordEntry(node);
145
+ if (!entry) continue;
146
+ target.appendChild(entry.node);
94
147
  }
95
- d(t);
148
+ orderTargetBySkeleton(target);
96
149
  },
97
- removeContent(e) {
98
- l(e);
150
+ removeContent(nodes) {
151
+ untrackNodes(nodes);
99
152
  },
100
153
  restoreContent() {
101
- m.disconnect();
102
- for (let t of o) {
103
- let n = [], r = t.node.previousSibling;
104
- for (; r instanceof Comment && r.textContent !== a;) n.unshift(r), r = r.previousSibling;
105
- for (let r of n) t.marker.parentNode === e.target ? e.target.insertBefore(r, t.marker) : e.target.appendChild(r);
106
- t.marker.parentNode === e.target ? e.target.insertBefore(t.node, t.marker) : e.target.appendChild(t.node), t.marker.remove();
154
+ hostObserver.disconnect();
155
+ for (const entry of trackedNodes) {
156
+ const pending = [];
157
+ let previous = entry.node.previousSibling;
158
+ while (previous instanceof Comment && previous.textContent !== PORTAL_CONTENT_MARKER) {
159
+ pending.unshift(previous);
160
+ previous = previous.previousSibling;
161
+ }
162
+ for (const comment of pending) if (entry.marker.parentNode === ctx.target) ctx.target.insertBefore(comment, entry.marker);
163
+ else ctx.target.appendChild(comment);
164
+ if (entry.marker.parentNode === ctx.target) ctx.target.insertBefore(entry.node, entry.marker);
165
+ else ctx.target.appendChild(entry.node);
166
+ entry.marker.remove();
107
167
  }
108
- o.length = 0;
168
+ trackedNodes.length = 0;
109
169
  },
110
170
  remove() {
111
- m.disconnect(), s.disconnect(), o.forEach((e) => e.marker.remove()), o.length = 0, t.remove();
171
+ hostObserver.disconnect();
172
+ contentObserver.disconnect();
173
+ trackedNodes.forEach((entry) => entry.marker.remove());
174
+ trackedNodes.length = 0;
175
+ host.remove();
112
176
  }
113
177
  };
114
- return h;
178
+ return api;
115
179
  });
116
- function s(e, t, n) {
117
- let r = e;
118
- for (; r && r !== n;) {
119
- if (r === t) return !0;
120
- r = r.parentNode;
180
+ /**
181
+ * 判断 node 是否是 slot 已分配节点(或其 light DOM 后代),即 node 实际渲染在 shadowRoot 内。
182
+ * slotted 内容的 parentNode 仍停留在 light DOM,因此不能用普通祖先遍历跨过 shadow 边界,
183
+ * 只能通过 slot.assignedNodes() 判断内容被渲染到哪个 slot。
184
+ */
185
+ function isAssignedIntoTarget(node, assignedNode, boundary) {
186
+ let current = node;
187
+ while (current && current !== boundary) {
188
+ if (current === assignedNode) return true;
189
+ current = current.parentNode;
121
190
  }
122
- return !1;
191
+ return false;
123
192
  }
124
- function c(e) {
125
- if (e.parentNode) return e.parentNode;
126
- let t = e.getRootNode();
127
- return t instanceof ShadowRoot ? t.host : null;
193
+ /** parentNode 为 null 时跨过 shadow 边界上行到 host(portal panel 等 shadow 子树的 parentNode 链会断裂)。 */
194
+ function getParentAcrossShadow(node) {
195
+ if (node.parentNode) return node.parentNode;
196
+ const root = node.getRootNode();
197
+ return root instanceof ShadowRoot ? root.host : null;
128
198
  }
129
- function l(e) {
130
- let t = e;
131
- for (; t && t !== document.documentElement;) {
132
- if (t instanceof HTMLDialogElement && t.open) return t;
133
- if (t instanceof Element && t.shadowRoot) {
134
- let n = t.shadowRoot.querySelectorAll("dialog");
135
- for (let r of n) {
136
- if (!(r instanceof HTMLDialogElement) || !r.open) continue;
137
- let n = r.querySelectorAll("slot");
138
- for (let i of n) for (let n of i.assignedNodes()) if (n instanceof Node && s(e, n, t)) return r;
199
+ /**
200
+ * 查找包含 target 且处于打开态的最近原生 <dialog>。
201
+ * 原生 showModal() 会把 dialog 提升到浏览器 top layer,而常规 overlay 容器在普通文档流,
202
+ * 二者无法靠 z-index 叠序——overlay 会被 top layer 的 dialog 遮住。
203
+ * 因此 target 被渲染到某个已打开的原生 dialog 内时,应把 overlay 挂到该 dialog 上,
204
+ * 使其一并进入 top layer(drawer / dialog 内的 dropdown、tooltip、context-menu 均适用)。
205
+ * 上行路径必须跨 shadow 边界:target 可能位于 portal panel(shadow 子树)内,
206
+ * 纯 parentNode 链在该处断裂会误判为 dialog 外,overlay 落进 fallback root 被遮挡。
207
+ */
208
+ function findEnclosingOpenDialog(target) {
209
+ let current = target;
210
+ while (current && current !== document.documentElement) {
211
+ if (current instanceof HTMLDialogElement && current.open) return current;
212
+ if (current instanceof Element && current.shadowRoot) {
213
+ const dialogs = current.shadowRoot.querySelectorAll("dialog");
214
+ for (const dialog of dialogs) {
215
+ if (!(dialog instanceof HTMLDialogElement) || !dialog.open) continue;
216
+ const slots = dialog.querySelectorAll("slot");
217
+ for (const slot of slots) for (const assigned of slot.assignedNodes()) {
218
+ if (!(assigned instanceof Node)) continue;
219
+ if (isAssignedIntoTarget(target, assigned, current)) return dialog;
220
+ }
139
221
  }
140
222
  }
141
- t = c(t);
223
+ current = getParentAcrossShadow(current);
142
224
  }
143
225
  return null;
144
226
  }
145
- function u(r, i, a = {}) {
146
- return (typeof r == "function" ? r() : r) || l(i) || ((a.preferRootTheme ? n() : t(i))?.getOverlayRoot() ?? e());
227
+ function resolveOverlayContainer(container, target, options = {}) {
228
+ const explicit = typeof container === "function" ? container() : container;
229
+ if (explicit) return explicit;
230
+ const enclosingDialog = findEnclosingOpenDialog(target);
231
+ if (enclosingDialog) return enclosingDialog;
232
+ return (options.preferRootTheme ? findRootTheme() : findNearestTheme(target))?.getOverlayRoot() ?? getFallbackOverlayRoot();
147
233
  }
148
- //#endregion
149
- export { i as applyOverlayVariables, o as defineOverlayPortal, u as resolveOverlayContainer };
234
+ export { applyOverlayVariables, defineOverlayPortal, resolveOverlayContainer };
150
235
 
151
236
  //# sourceMappingURL=portal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"portal.js","names":[],"sources":["../../../src/shared/overlay/portal.ts"],"sourcesContent":["import { definePlugin } from '@greypan/js-kit'\n\nimport { getFallbackOverlayRoot } from '@/shared/overlay/overlay-root'\nimport { findNearestTheme, findRootTheme } from '@/shared/overlay/theme-overlay-scope'\n\nexport type OverlayContainer = HTMLElement | (() => HTMLElement | undefined)\n\nexport interface OverlayContainerResolutionOptions {\n /** 无 target 时优先使用文档中 root theme 的 theme-owned overlay root。 */\n preferRootTheme?: boolean\n}\n\nexport interface OverlayPortalOptions {\n container?: OverlayContainer\n target: Element\n style: string\n className: string\n /**\n * 额外的 panel 内容变化反应。注意:已迁移节点被框架物理删除后的解除追踪\n * (removeContent)是 portal 的内建默认行为,不经过该回调;这里只承载\n * 组件自己的附加逻辑(如 option 域的刷新、空态占位改写)。\n */\n onContentChange?: (mutations: MutationRecord[]) => void\n /**\n * 打开期实时渲染契约:框架(Vue/React 条件渲染)可能在 overlay 打开期间向宿主\n * light DOM 持续插入节点。提供该回调时,portal 监听宿主直接子节点的 childList,\n * 把回调认定的可迁移节点增量迁入 panel;关闭恢复时与初始迁移节点一样按原位回插。\n * 回调应只返回渲染性内容(元素/文本),框架注释锚点必须留在宿主,\n * 否则框架后续 patch 会以 panel 内节点为插入基准。\n * 返回空数组表示本次新增无需迁移。\n */\n migrateAddedNodes?: (addedNodes: Node[]) => Node[]\n}\n\nexport interface OverlayPortal {\n readonly panel: HTMLElement\n restoreContent(): void\n moveContent(nodes: Node[], target?: HTMLElement): void\n appendContent(nodes: Node[], target?: HTMLElement): void\n removeContent(nodes: Node[]): void\n remove(): void\n}\n\n/**\n * Portal panel 位于独立 shadow root,宿主上的 CSS 自定义属性不会沿渲染树继承到 panel。\n * 这里在创建时镜像锚点解析后的变量,让组件 host 上的尺寸配置对 portal 仍然生效。\n */\nexport function applyOverlayVariables(panel: HTMLElement, source: Element, variables: readonly string[]): void {\n const computedStyle = getComputedStyle(source)\n for (const variable of variables) {\n const value = computedStyle.getPropertyValue(variable).trim()\n if (value) panel.style.setProperty(variable, value)\n }\n}\n\n/**\n * 迁移节点的追踪条目。每个节点迁入 panel 时在宿主 light DOM 原位留一个 marker 注释:\n * 宿主因此始终持有完整有序的骨架(marker + 框架注释锚点 + 未迁移节点),\n * 框架(Vue/React 条件渲染)打开期的插入以宿主为容器、以真实锚点为基准;\n * panel 内节点按宿主骨架序重排(中段插入不落到 panel 末尾);关闭时按 marker 位\n * 双向归还、marker 摘除。机制与 menu-tree 的托管 menu item 锚一致(context-menu/dropdown 共用)。\n */\ninterface TrackedNodeEntry {\n node: Node\n marker: Comment\n}\n\nconst PORTAL_CONTENT_MARKER = 'wui-portal-content-anchor'\n\n/**\n * 构建带 Shadow DOM 样式边界的 Portal panel,并追踪被迁移的内容节点以便恢复。\n */\nexport const defineOverlayPortal = () =>\n definePlugin<OverlayPortal, OverlayPortalOptions>(ctx => {\n const host = document.createElement('div')\n // :host 规则可能让宿主在 overlay 容器中生成行盒;display: contents 保留 panel 定位而不参与布局。\n host.style.display = 'contents'\n\n const root = host.attachShadow({ mode: 'open' })\n const style = document.createElement('style')\n style.textContent = ctx.style\n const panel = document.createElement('div')\n // 单层玻璃:wui-glass 原样留在 panel 自身,背景/阴影/backdrop-filter 随 panel\n // opacity 与 blur 插值一起过渡(见 overlay-motion.css),无 blur/surface 双层。\n panel.className = ctx.className\n panel.dataset.wuiPresence = 'entering'\n root.append(style, panel)\n\n const trackedNodes: TrackedNodeEntry[] = []\n const contentObserver = new MutationObserver(mutations => {\n // 内部不变量先于消费方回调执行:配对依赖 trackedNodes 尚未被消费方 untrack 的状态。\n returnStrayFrameworkComments(mutations)\n // 框架在打开期物理删除已迁移节点:即时解除追踪,否则关闭恢复时会把已删除\n // 节点复活回宿主 light DOM。panel 内部移动(重排 insertBefore)在同一 mutation\n // record 中同时出现在 removed/added,不属于删除,须排除。\n const addedInBatch = new Set(mutations.flatMap(mutation => [...mutation.addedNodes]))\n const removedNodes = mutations\n .flatMap(mutation => [...mutation.removedNodes])\n .filter(node => !addedInBatch.has(node))\n if (removedNodes.length) untrackNodes(removedNodes)\n ctx.onContentChange?.(mutations)\n })\n // 同一 observer 批次内被插入又移除的游离节点没有宿主位可锚,不追踪不迁移\n // (insertBefore 要求 node 是 parent 的子节点);其归宿由框架的删除语义决定。\n const recordEntry = (node: Node): TrackedNodeEntry | null => {\n const parent = node.parentNode\n if (!parent) return null\n const marker = document.createComment(PORTAL_CONTENT_MARKER)\n parent.insertBefore(marker, node)\n const entry: TrackedNodeEntry = { node, marker }\n trackedNodes.push(entry)\n return entry\n }\n const untrackNodes = (nodes: Node[]) => {\n for (const node of nodes) {\n const index = trackedNodes.findIndex(entry => entry.node === node)\n if (index >= 0) {\n trackedNodes[index].marker.remove()\n trackedNodes.splice(index, 1)\n }\n }\n }\n // panel 内节点按宿主骨架序重排:骨架 = 宿主 childNodes 中本 portal 的 marker 序。\n // 只在已跟踪节点之间移动(insertBefore 相对定位),不触碰 panel 内的组件自有节点\n // (如 autocomplete 的空态占位);末位节点 append,越过 panel 内注释锚点的情形由\n // restoreContent 的相邻注释随迁兜底。\n const orderTargetBySkeleton = (target: HTMLElement) => {\n const skeleton: Node[] = []\n for (const node of Array.from(ctx.target.childNodes)) {\n if (node instanceof Comment && node.textContent === PORTAL_CONTENT_MARKER) {\n const entry = trackedNodes.find(e => e.marker === node)\n if (entry && entry.node.parentNode === target) skeleton.push(entry.node)\n }\n }\n if (skeleton.length === 0) return\n const current = Array.from(target.childNodes).filter(\n node => skeleton.includes(node) || !(node instanceof Comment)\n )\n if (current.length === skeleton.length && current.every((node, index) => node === skeleton[index])) return\n for (let index = skeleton.length - 1; index >= 0; index--) {\n const node = skeleton[index]\n const next = skeleton[index + 1]\n if (next) {\n if ((node as Element).nextElementSibling !== next) target.insertBefore(node, next)\n } else {\n target.appendChild(node)\n }\n }\n }\n\n /**\n * 打开期不变量:框架删除已迁移节点时,其条件渲染占位注释(v-if 等)会被插进\n * panel 内容区而不是宿主——block 子树 patch 以 hostParentNode(oldVNode.el) 重定\n * container,而旧 el 已在 panel(可能是 panel 自身或组件的内容子容器)。\n * 注释是框架后续翻转依赖的 vnode.el:留在 panel 会随 panel 销毁,下次翻转把内容插进\n * 已脱离文档的旧 panel(内容\"既不在宿主也不在 panel\"且无法恢复)。\n * 每个 panel mutation 批次内即时归还:与同批次被框架删除的 tracked 节点按宿主\n * marker 序配对,插到其 marker 位(多注释对多删除为近似配对;无配对时落宿主\n * 骨架末尾兜底)。tracked 子树内的注释是迁移内容自身的嵌套条件渲染,不属游离\n * 锚点,必须留在原位;随整个子树被删的注释已不在 panel 内,无需救援。\n */\n const returnStrayFrameworkComments = (mutations: MutationRecord[]) => {\n const isInsideTrackedSubtree = (start: Node): boolean => {\n let current: Node | null = start\n while (current && current !== panel) {\n if (trackedNodes.some(entry => entry.node === current)) return true\n current = current.parentNode\n }\n return false\n }\n const addedNodes = new Set(mutations.flatMap(mutation => [...mutation.addedNodes]))\n const strays: Comment[] = []\n for (const mutation of mutations) {\n for (const node of mutation.addedNodes) {\n if (!(node instanceof Comment) || node.textContent === PORTAL_CONTENT_MARKER) continue\n // 同批次移入又移除的游离注释、随删除子树一起消失的注释都不在 panel 内,跳过\n if (!panel.contains(node)) continue\n if (isInsideTrackedSubtree(mutation.target)) continue\n strays.push(node)\n }\n }\n if (!strays.length) return\n const hostChildren = Array.from(ctx.target.childNodes)\n const removedEntries = trackedNodes\n .filter(\n entry =>\n !addedNodes.has(entry.node) && mutations.some(mutation => [...mutation.removedNodes].includes(entry.node))\n )\n .sort((a, b) => hostChildren.indexOf(a.marker) - hostChildren.indexOf(b.marker))\n for (const [index, comment] of strays.entries()) {\n const marker = removedEntries[Math.min(index, removedEntries.length - 1)]?.marker\n if (marker && marker.parentNode === ctx.target) ctx.target.insertBefore(comment, marker)\n else ctx.target.appendChild(comment)\n }\n }\n\n resolveOverlayContainer(ctx.container, ctx.target).appendChild(host)\n // panel 内容观察是 portal 自身的不变量(游离注释救援 + 删除节点解除追踪),\n // 不依赖消费方是否注册 onContentChange。\n contentObserver.observe(panel, { childList: true, subtree: true })\n\n // 打开期宿主 childList 观察(不含子树,框架 patch 嵌套组件的 light DOM 不属于\n // 本 panel 内容)。portal 实例的生命周期即打开期,随恢复/移除断开。\n const migrateAddedNodes = ctx.migrateAddedNodes\n const hostObserver = new MutationObserver(mutations => {\n // 框架清除逻辑(如 lit 的 _$clear)按宿主 marker 邻位遍历已迁移内容:元素\n // 物理上在 panel,遍历找不到本体,会把 portal marker 当作内容本体移除。\n // marker 被框架摘除即框架删除语义——解除追踪并清掉滞留 panel 的游离元素;\n // 同批次移入又移回的 marker(框架重排)不属于删除。实时迁移仍以\n // migrateAddedNodes 的回调为准,无该回调的 portal(如 option 域)只做删除清理。\n const addedNodes = new Set(mutations.flatMap(mutation => [...mutation.addedNodes]))\n const strandedNodes = mutations\n .flatMap(mutation => [...mutation.removedNodes])\n .filter(node => node instanceof Comment && node.textContent === PORTAL_CONTENT_MARKER && !addedNodes.has(node))\n .map(marker => trackedNodes.find(entry => entry.marker === marker)?.node)\n .filter((node): node is Node => node !== undefined)\n if (strandedNodes.length) {\n api.removeContent(strandedNodes)\n // remove() 的规范语义即 parentNode.removeChild:宿主/类型层面都以 Node 表达\n for (const node of strandedNodes) node.parentNode?.removeChild(node)\n }\n if (!migrateAddedNodes) return\n const migratable = migrateAddedNodes(mutations.flatMap(mutation => [...mutation.addedNodes]))\n if (migratable.length) api.appendContent(migratable)\n })\n hostObserver.observe(ctx.target, { childList: true })\n\n const api: OverlayPortal = {\n panel,\n\n moveContent(nodes, target = panel) {\n trackedNodes.forEach(entry => entry.marker.remove())\n const entries = nodes.map(recordEntry).filter((entry): entry is TrackedNodeEntry => entry !== null)\n trackedNodes.length = 0\n trackedNodes.push(...entries)\n target.append(...nodes)\n orderTargetBySkeleton(target)\n },\n\n appendContent(nodes, target = panel) {\n for (const node of nodes) {\n untrackNodes([node])\n const entry = recordEntry(node)\n if (!entry) continue\n target.appendChild(entry.node)\n }\n orderTargetBySkeleton(target)\n },\n\n removeContent(nodes) {\n // 框架删除节点时插进 panel 的占位注释由 contentObserver 的内部不变量\n // (returnStrayFrameworkComments)即时归还宿主,这里只负责解除追踪。\n untrackNodes(nodes)\n },\n\n restoreContent() {\n // 先停掉实时迁移:恢复动作本身会改动宿主 childList,\n // 否则回插的节点会被当成新增内容再次迁入 panel 形成回环。\n hostObserver.disconnect()\n\n // 节点回到宿主中自己的 marker 位;panel 内紧邻其前的框架注释锚点(v-if 占位)\n // 随元素一起迁回——Vue 仍持有这些锚点的 vnode.el 引用,留在 panel 会随 panel 销毁,\n // 下次翻转将因 parentNode === null 崩溃。\n for (const entry of trackedNodes) {\n const pending: Comment[] = []\n let previous = entry.node.previousSibling\n while (previous instanceof Comment && previous.textContent !== PORTAL_CONTENT_MARKER) {\n pending.unshift(previous)\n previous = previous.previousSibling\n }\n for (const comment of pending) {\n if (entry.marker.parentNode === ctx.target) ctx.target.insertBefore(comment, entry.marker)\n else ctx.target.appendChild(comment)\n }\n if (entry.marker.parentNode === ctx.target) ctx.target.insertBefore(entry.node, entry.marker)\n else ctx.target.appendChild(entry.node)\n entry.marker.remove()\n }\n trackedNodes.length = 0\n },\n\n remove() {\n hostObserver.disconnect()\n contentObserver.disconnect()\n // 防御:正常 dispose 先 restore(marker 已清),异常路径下避免 marker 泄漏在宿主。\n trackedNodes.forEach(entry => entry.marker.remove())\n trackedNodes.length = 0\n host.remove()\n }\n }\n return api\n })\n\n/**\n * 判断 node 是否是 slot 已分配节点(或其 light DOM 后代),即 node 实际渲染在 shadowRoot 内。\n * slotted 内容的 parentNode 仍停留在 light DOM,因此不能用普通祖先遍历跨过 shadow 边界,\n * 只能通过 slot.assignedNodes() 判断内容被渲染到哪个 slot。\n */\nfunction isAssignedIntoTarget(node: Node, assignedNode: Node, boundary: Node): boolean {\n let current: Node | null = node\n while (current && current !== boundary) {\n if (current === assignedNode) return true\n current = current.parentNode\n }\n return false\n}\n\n/** parentNode 为 null 时跨过 shadow 边界上行到 host(portal panel 等 shadow 子树的 parentNode 链会断裂)。 */\nfunction getParentAcrossShadow(node: Node): Node | null {\n if (node.parentNode) return node.parentNode\n const root = node.getRootNode()\n return root instanceof ShadowRoot ? root.host : null\n}\n\n/**\n * 查找包含 target 且处于打开态的最近原生 <dialog>。\n * 原生 showModal() 会把 dialog 提升到浏览器 top layer,而常规 overlay 容器在普通文档流,\n * 二者无法靠 z-index 叠序——overlay 会被 top layer 的 dialog 遮住。\n * 因此 target 被渲染到某个已打开的原生 dialog 内时,应把 overlay 挂到该 dialog 上,\n * 使其一并进入 top layer(drawer / dialog 内的 dropdown、tooltip、context-menu 均适用)。\n * 上行路径必须跨 shadow 边界:target 可能位于 portal panel(shadow 子树)内,\n * 纯 parentNode 链在该处断裂会误判为 dialog 外,overlay 落进 fallback root 被遮挡。\n */\nfunction findEnclosingOpenDialog(target: Element): HTMLDialogElement | null {\n let current: Node | null = target\n while (current && current !== document.documentElement) {\n if (current instanceof HTMLDialogElement && current.open) return current\n\n // 跨过 shadow host:检查其 shadowRoot 内已打开的 dialog 是否渲染了 target。\n if (current instanceof Element && current.shadowRoot) {\n const dialogs = current.shadowRoot.querySelectorAll('dialog')\n for (const dialog of dialogs) {\n if (!(dialog instanceof HTMLDialogElement) || !dialog.open) continue\n const slots = dialog.querySelectorAll('slot')\n for (const slot of slots) {\n for (const assigned of slot.assignedNodes()) {\n if (!(assigned instanceof Node)) continue\n if (isAssignedIntoTarget(target, assigned, current)) return dialog\n }\n }\n }\n }\n\n current = getParentAcrossShadow(current)\n }\n return null\n}\n\nexport function resolveOverlayContainer(\n container: OverlayContainer | undefined,\n target: Element,\n options: OverlayContainerResolutionOptions = {}\n): HTMLElement {\n const explicit = typeof container === 'function' ? container() : container\n if (explicit) return explicit\n\n // target 在已打开的原生 dialog / drawer 内:挂到该 dialog,加入 top layer。\n const enclosingDialog = findEnclosingOpenDialog(target)\n if (enclosingDialog) return enclosingDialog\n\n // 无 target 的调用(如 menu)优先使用 root theme 的 theme-owned overlay root;\n // 有 target 时使用最近 theme 的 theme-owned overlay root。\n const theme = options.preferRootTheme ? findRootTheme() : findNearestTheme(target)\n return theme?.getOverlayRoot() ?? getFallbackOverlayRoot()\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"portal.js","names":[],"sources":["../../../src/shared/overlay/portal.ts"],"sourcesContent":["import { definePlugin } from '@greypan/js-kit'\n\nimport { getFallbackOverlayRoot } from '@/shared/overlay/overlay-root'\nimport { findNearestTheme, findRootTheme } from '@/shared/overlay/theme-overlay-scope'\n\nexport type OverlayContainer = HTMLElement | (() => HTMLElement | undefined)\n\nexport interface OverlayContainerResolutionOptions {\n /** 无 target 时优先使用文档中 root theme 的 theme-owned overlay root。 */\n preferRootTheme?: boolean\n}\n\nexport interface OverlayPortalOptions {\n container?: OverlayContainer\n target: Element\n style: string\n className: string\n /**\n * 额外的 panel 内容变化反应。注意:已迁移节点被框架物理删除后的解除追踪\n * (removeContent)是 portal 的内建默认行为,不经过该回调;这里只承载\n * 组件自己的附加逻辑(如 option 域的刷新、空态占位改写)。\n */\n onContentChange?: (mutations: MutationRecord[]) => void\n /**\n * 打开期实时渲染契约:框架(Vue/React 条件渲染)可能在 overlay 打开期间向宿主\n * light DOM 持续插入节点。提供该回调时,portal 监听宿主直接子节点的 childList,\n * 把回调认定的可迁移节点增量迁入 panel;关闭恢复时与初始迁移节点一样按原位回插。\n * 回调应只返回渲染性内容(元素/文本),框架注释锚点必须留在宿主,\n * 否则框架后续 patch 会以 panel 内节点为插入基准。\n * 返回空数组表示本次新增无需迁移。\n */\n migrateAddedNodes?: (addedNodes: Node[]) => Node[]\n}\n\nexport interface OverlayPortal {\n readonly panel: HTMLElement\n restoreContent(): void\n moveContent(nodes: Node[], target?: HTMLElement): void\n appendContent(nodes: Node[], target?: HTMLElement): void\n removeContent(nodes: Node[]): void\n remove(): void\n}\n\n/**\n * Portal panel 位于独立 shadow root,宿主上的 CSS 自定义属性不会沿渲染树继承到 panel。\n * 这里在创建时镜像锚点解析后的变量,让组件 host 上的尺寸配置对 portal 仍然生效。\n */\nexport function applyOverlayVariables(panel: HTMLElement, source: Element, variables: readonly string[]): void {\n const computedStyle = getComputedStyle(source)\n for (const variable of variables) {\n const value = computedStyle.getPropertyValue(variable).trim()\n if (value) panel.style.setProperty(variable, value)\n }\n}\n\n/**\n * 迁移节点的追踪条目。每个节点迁入 panel 时在宿主 light DOM 原位留一个 marker 注释:\n * 宿主因此始终持有完整有序的骨架(marker + 框架注释锚点 + 未迁移节点),\n * 框架(Vue/React 条件渲染)打开期的插入以宿主为容器、以真实锚点为基准;\n * panel 内节点按宿主骨架序重排(中段插入不落到 panel 末尾);关闭时按 marker 位\n * 双向归还、marker 摘除。机制与 menu-tree 的托管 menu item 锚一致(context-menu/dropdown 共用)。\n */\ninterface TrackedNodeEntry {\n node: Node\n marker: Comment\n}\n\nconst PORTAL_CONTENT_MARKER = 'wui-portal-content-anchor'\n\n/**\n * 构建带 Shadow DOM 样式边界的 Portal panel,并追踪被迁移的内容节点以便恢复。\n */\nexport const defineOverlayPortal = () =>\n definePlugin<OverlayPortal, OverlayPortalOptions>(ctx => {\n const host = document.createElement('div')\n // :host 规则可能让宿主在 overlay 容器中生成行盒;display: contents 保留 panel 定位而不参与布局。\n host.style.display = 'contents'\n\n const root = host.attachShadow({ mode: 'open' })\n const style = document.createElement('style')\n style.textContent = ctx.style\n const panel = document.createElement('div')\n // 单层玻璃:wui-glass 原样留在 panel 自身,背景/阴影/backdrop-filter 随 panel\n // opacity 与 blur 插值一起过渡(见 overlay-motion.css),无 blur/surface 双层。\n panel.className = ctx.className\n panel.dataset.wuiPresence = 'entering'\n root.append(style, panel)\n\n const trackedNodes: TrackedNodeEntry[] = []\n const contentObserver = new MutationObserver(mutations => {\n // 内部不变量先于消费方回调执行:配对依赖 trackedNodes 尚未被消费方 untrack 的状态。\n returnStrayFrameworkComments(mutations)\n // 框架在打开期物理删除已迁移节点:即时解除追踪,否则关闭恢复时会把已删除\n // 节点复活回宿主 light DOM。panel 内部移动(重排 insertBefore)在同一 mutation\n // record 中同时出现在 removed/added,不属于删除,须排除。\n const addedInBatch = new Set(mutations.flatMap(mutation => [...mutation.addedNodes]))\n const removedNodes = mutations\n .flatMap(mutation => [...mutation.removedNodes])\n .filter(node => !addedInBatch.has(node))\n if (removedNodes.length) untrackNodes(removedNodes)\n ctx.onContentChange?.(mutations)\n })\n // 同一 observer 批次内被插入又移除的游离节点没有宿主位可锚,不追踪不迁移\n // (insertBefore 要求 node 是 parent 的子节点);其归宿由框架的删除语义决定。\n const recordEntry = (node: Node): TrackedNodeEntry | null => {\n const parent = node.parentNode\n if (!parent) return null\n const marker = document.createComment(PORTAL_CONTENT_MARKER)\n parent.insertBefore(marker, node)\n const entry: TrackedNodeEntry = { node, marker }\n trackedNodes.push(entry)\n return entry\n }\n const untrackNodes = (nodes: Node[]) => {\n for (const node of nodes) {\n const index = trackedNodes.findIndex(entry => entry.node === node)\n if (index >= 0) {\n trackedNodes[index].marker.remove()\n trackedNodes.splice(index, 1)\n }\n }\n }\n // panel 内节点按宿主骨架序重排:骨架 = 宿主 childNodes 中本 portal 的 marker 序。\n // 只在已跟踪节点之间移动(insertBefore 相对定位),不触碰 panel 内的组件自有节点\n // (如 autocomplete 的空态占位);末位节点 append,越过 panel 内注释锚点的情形由\n // restoreContent 的相邻注释随迁兜底。\n const orderTargetBySkeleton = (target: HTMLElement) => {\n const skeleton: Node[] = []\n for (const node of Array.from(ctx.target.childNodes)) {\n if (node instanceof Comment && node.textContent === PORTAL_CONTENT_MARKER) {\n const entry = trackedNodes.find(e => e.marker === node)\n if (entry && entry.node.parentNode === target) skeleton.push(entry.node)\n }\n }\n if (skeleton.length === 0) return\n const current = Array.from(target.childNodes).filter(\n node => skeleton.includes(node) || !(node instanceof Comment)\n )\n if (current.length === skeleton.length && current.every((node, index) => node === skeleton[index])) return\n for (let index = skeleton.length - 1; index >= 0; index--) {\n const node = skeleton[index]\n const next = skeleton[index + 1]\n if (next) {\n if ((node as Element).nextElementSibling !== next) target.insertBefore(node, next)\n } else {\n target.appendChild(node)\n }\n }\n }\n\n /**\n * 打开期不变量:框架删除已迁移节点时,其条件渲染占位注释(v-if 等)会被插进\n * panel 内容区而不是宿主——block 子树 patch 以 hostParentNode(oldVNode.el) 重定\n * container,而旧 el 已在 panel(可能是 panel 自身或组件的内容子容器)。\n * 注释是框架后续翻转依赖的 vnode.el:留在 panel 会随 panel 销毁,下次翻转把内容插进\n * 已脱离文档的旧 panel(内容\"既不在宿主也不在 panel\"且无法恢复)。\n * 每个 panel mutation 批次内即时归还:与同批次被框架删除的 tracked 节点按宿主\n * marker 序配对,插到其 marker 位(多注释对多删除为近似配对;无配对时落宿主\n * 骨架末尾兜底)。tracked 子树内的注释是迁移内容自身的嵌套条件渲染,不属游离\n * 锚点,必须留在原位;随整个子树被删的注释已不在 panel 内,无需救援。\n */\n const returnStrayFrameworkComments = (mutations: MutationRecord[]) => {\n const isInsideTrackedSubtree = (start: Node): boolean => {\n let current: Node | null = start\n while (current && current !== panel) {\n if (trackedNodes.some(entry => entry.node === current)) return true\n current = current.parentNode\n }\n return false\n }\n const addedNodes = new Set(mutations.flatMap(mutation => [...mutation.addedNodes]))\n const strays: Comment[] = []\n for (const mutation of mutations) {\n for (const node of mutation.addedNodes) {\n if (!(node instanceof Comment) || node.textContent === PORTAL_CONTENT_MARKER) continue\n // 同批次移入又移除的游离注释、随删除子树一起消失的注释都不在 panel 内,跳过\n if (!panel.contains(node)) continue\n if (isInsideTrackedSubtree(mutation.target)) continue\n strays.push(node)\n }\n }\n if (!strays.length) return\n const hostChildren = Array.from(ctx.target.childNodes)\n const removedEntries = trackedNodes\n .filter(\n entry =>\n !addedNodes.has(entry.node) && mutations.some(mutation => [...mutation.removedNodes].includes(entry.node))\n )\n .sort((a, b) => hostChildren.indexOf(a.marker) - hostChildren.indexOf(b.marker))\n for (const [index, comment] of strays.entries()) {\n const marker = removedEntries[Math.min(index, removedEntries.length - 1)]?.marker\n if (marker && marker.parentNode === ctx.target) ctx.target.insertBefore(comment, marker)\n else ctx.target.appendChild(comment)\n }\n }\n\n resolveOverlayContainer(ctx.container, ctx.target).appendChild(host)\n // panel 内容观察是 portal 自身的不变量(游离注释救援 + 删除节点解除追踪),\n // 不依赖消费方是否注册 onContentChange。\n contentObserver.observe(panel, { childList: true, subtree: true })\n\n // 打开期宿主 childList 观察(不含子树,框架 patch 嵌套组件的 light DOM 不属于\n // 本 panel 内容)。portal 实例的生命周期即打开期,随恢复/移除断开。\n const migrateAddedNodes = ctx.migrateAddedNodes\n const hostObserver = new MutationObserver(mutations => {\n // 框架清除逻辑(如 lit 的 _$clear)按宿主 marker 邻位遍历已迁移内容:元素\n // 物理上在 panel,遍历找不到本体,会把 portal marker 当作内容本体移除。\n // marker 被框架摘除即框架删除语义——解除追踪并清掉滞留 panel 的游离元素;\n // 同批次移入又移回的 marker(框架重排)不属于删除。实时迁移仍以\n // migrateAddedNodes 的回调为准,无该回调的 portal(如 option 域)只做删除清理。\n const addedNodes = new Set(mutations.flatMap(mutation => [...mutation.addedNodes]))\n const strandedNodes = mutations\n .flatMap(mutation => [...mutation.removedNodes])\n .filter(node => node instanceof Comment && node.textContent === PORTAL_CONTENT_MARKER && !addedNodes.has(node))\n .map(marker => trackedNodes.find(entry => entry.marker === marker)?.node)\n .filter((node): node is Node => node !== undefined)\n if (strandedNodes.length) {\n api.removeContent(strandedNodes)\n // remove() 的规范语义即 parentNode.removeChild:宿主/类型层面都以 Node 表达\n for (const node of strandedNodes) node.parentNode?.removeChild(node)\n }\n if (!migrateAddedNodes) return\n const migratable = migrateAddedNodes(mutations.flatMap(mutation => [...mutation.addedNodes]))\n if (migratable.length) api.appendContent(migratable)\n })\n hostObserver.observe(ctx.target, { childList: true })\n\n const api: OverlayPortal = {\n panel,\n\n moveContent(nodes, target = panel) {\n trackedNodes.forEach(entry => entry.marker.remove())\n const entries = nodes.map(recordEntry).filter((entry): entry is TrackedNodeEntry => entry !== null)\n trackedNodes.length = 0\n trackedNodes.push(...entries)\n target.append(...nodes)\n orderTargetBySkeleton(target)\n },\n\n appendContent(nodes, target = panel) {\n for (const node of nodes) {\n untrackNodes([node])\n const entry = recordEntry(node)\n if (!entry) continue\n target.appendChild(entry.node)\n }\n orderTargetBySkeleton(target)\n },\n\n removeContent(nodes) {\n // 框架删除节点时插进 panel 的占位注释由 contentObserver 的内部不变量\n // (returnStrayFrameworkComments)即时归还宿主,这里只负责解除追踪。\n untrackNodes(nodes)\n },\n\n restoreContent() {\n // 先停掉实时迁移:恢复动作本身会改动宿主 childList,\n // 否则回插的节点会被当成新增内容再次迁入 panel 形成回环。\n hostObserver.disconnect()\n\n // 节点回到宿主中自己的 marker 位;panel 内紧邻其前的框架注释锚点(v-if 占位)\n // 随元素一起迁回——Vue 仍持有这些锚点的 vnode.el 引用,留在 panel 会随 panel 销毁,\n // 下次翻转将因 parentNode === null 崩溃。\n for (const entry of trackedNodes) {\n const pending: Comment[] = []\n let previous = entry.node.previousSibling\n while (previous instanceof Comment && previous.textContent !== PORTAL_CONTENT_MARKER) {\n pending.unshift(previous)\n previous = previous.previousSibling\n }\n for (const comment of pending) {\n if (entry.marker.parentNode === ctx.target) ctx.target.insertBefore(comment, entry.marker)\n else ctx.target.appendChild(comment)\n }\n if (entry.marker.parentNode === ctx.target) ctx.target.insertBefore(entry.node, entry.marker)\n else ctx.target.appendChild(entry.node)\n entry.marker.remove()\n }\n trackedNodes.length = 0\n },\n\n remove() {\n hostObserver.disconnect()\n contentObserver.disconnect()\n // 防御:正常 dispose 先 restore(marker 已清),异常路径下避免 marker 泄漏在宿主。\n trackedNodes.forEach(entry => entry.marker.remove())\n trackedNodes.length = 0\n host.remove()\n }\n }\n return api\n })\n\n/**\n * 判断 node 是否是 slot 已分配节点(或其 light DOM 后代),即 node 实际渲染在 shadowRoot 内。\n * slotted 内容的 parentNode 仍停留在 light DOM,因此不能用普通祖先遍历跨过 shadow 边界,\n * 只能通过 slot.assignedNodes() 判断内容被渲染到哪个 slot。\n */\nfunction isAssignedIntoTarget(node: Node, assignedNode: Node, boundary: Node): boolean {\n let current: Node | null = node\n while (current && current !== boundary) {\n if (current === assignedNode) return true\n current = current.parentNode\n }\n return false\n}\n\n/** parentNode 为 null 时跨过 shadow 边界上行到 host(portal panel 等 shadow 子树的 parentNode 链会断裂)。 */\nfunction getParentAcrossShadow(node: Node): Node | null {\n if (node.parentNode) return node.parentNode\n const root = node.getRootNode()\n return root instanceof ShadowRoot ? root.host : null\n}\n\n/**\n * 查找包含 target 且处于打开态的最近原生 <dialog>。\n * 原生 showModal() 会把 dialog 提升到浏览器 top layer,而常规 overlay 容器在普通文档流,\n * 二者无法靠 z-index 叠序——overlay 会被 top layer 的 dialog 遮住。\n * 因此 target 被渲染到某个已打开的原生 dialog 内时,应把 overlay 挂到该 dialog 上,\n * 使其一并进入 top layer(drawer / dialog 内的 dropdown、tooltip、context-menu 均适用)。\n * 上行路径必须跨 shadow 边界:target 可能位于 portal panel(shadow 子树)内,\n * 纯 parentNode 链在该处断裂会误判为 dialog 外,overlay 落进 fallback root 被遮挡。\n */\nfunction findEnclosingOpenDialog(target: Element): HTMLDialogElement | null {\n let current: Node | null = target\n while (current && current !== document.documentElement) {\n if (current instanceof HTMLDialogElement && current.open) return current\n\n // 跨过 shadow host:检查其 shadowRoot 内已打开的 dialog 是否渲染了 target。\n if (current instanceof Element && current.shadowRoot) {\n const dialogs = current.shadowRoot.querySelectorAll('dialog')\n for (const dialog of dialogs) {\n if (!(dialog instanceof HTMLDialogElement) || !dialog.open) continue\n const slots = dialog.querySelectorAll('slot')\n for (const slot of slots) {\n for (const assigned of slot.assignedNodes()) {\n if (!(assigned instanceof Node)) continue\n if (isAssignedIntoTarget(target, assigned, current)) return dialog\n }\n }\n }\n }\n\n current = getParentAcrossShadow(current)\n }\n return null\n}\n\nexport function resolveOverlayContainer(\n container: OverlayContainer | undefined,\n target: Element,\n options: OverlayContainerResolutionOptions = {}\n): HTMLElement {\n const explicit = typeof container === 'function' ? container() : container\n if (explicit) return explicit\n\n // target 在已打开的原生 dialog / drawer 内:挂到该 dialog,加入 top layer。\n const enclosingDialog = findEnclosingOpenDialog(target)\n if (enclosingDialog) return enclosingDialog\n\n // 无 target 的调用(如 menu)优先使用 root theme 的 theme-owned overlay root;\n // 有 target 时使用最近 theme 的 theme-owned overlay root。\n const theme = options.preferRootTheme ? findRootTheme() : findNearestTheme(target)\n return theme?.getOverlayRoot() ?? getFallbackOverlayRoot()\n}\n"],"mappings":";;;;;;;;AA+CA,SAAgB,sBAAsB,OAAoB,QAAiB,WAAoC;CAC7G,MAAM,gBAAgB,iBAAiB,MAAM;CAC7C,KAAK,MAAM,YAAY,WAAW;EAChC,MAAM,QAAQ,cAAc,iBAAiB,QAAQ,CAAC,CAAC,KAAK;EAC5D,IAAI,OAAO,MAAM,MAAM,YAAY,UAAU,KAAK;CACpD;AACF;AAcA,MAAM,wBAAwB;;;;AAK9B,MAAa,4BACX,cAAkD,QAAO;CACvD,MAAM,OAAO,SAAS,cAAc,KAAK;CAEzC,KAAK,MAAM,UAAU;CAErB,MAAM,OAAO,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;CAC/C,MAAM,QAAQ,SAAS,cAAc,OAAO;CAC5C,MAAM,cAAc,IAAI;CACxB,MAAM,QAAQ,SAAS,cAAc,KAAK;CAG1C,MAAM,YAAY,IAAI;CACtB,MAAM,QAAQ,cAAc;CAC5B,KAAK,OAAO,OAAO,KAAK;CAExB,MAAM,eAAmC,CAAC;CAC1C,MAAM,kBAAkB,IAAI,kBAAiB,cAAa;EAExD,6BAA6B,SAAS;EAItC,MAAM,eAAe,IAAI,IAAI,UAAU,SAAQ,aAAY,CAAC,GAAG,SAAS,UAAU,CAAC,CAAC;EACpF,MAAM,eAAe,UAClB,SAAQ,aAAY,CAAC,GAAG,SAAS,YAAY,CAAC,CAAC,CAC/C,QAAO,SAAQ,CAAC,aAAa,IAAI,IAAI,CAAC;EACzC,IAAI,aAAa,QAAQ,aAAa,YAAY;EAClD,IAAI,kBAAkB,SAAS;CACjC,CAAC;CAGD,MAAM,eAAe,SAAwC;EAC3D,MAAM,SAAS,KAAK;EACpB,IAAI,CAAC,QAAQ,OAAO;EACpB,MAAM,SAAS,SAAS,cAAc,qBAAqB;EAC3D,OAAO,aAAa,QAAQ,IAAI;EAChC,MAAM,QAA0B;GAAE;GAAM;EAAO;EAC/C,aAAa,KAAK,KAAK;EACvB,OAAO;CACT;CACA,MAAM,gBAAgB,UAAkB;EACtC,KAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,QAAQ,aAAa,WAAU,UAAS,MAAM,SAAS,IAAI;GACjE,IAAI,SAAS,GAAG;IACd,aAAa,MAAM,CAAC,OAAO,OAAO;IAClC,aAAa,OAAO,OAAO,CAAC;GAC9B;EACF;CACF;CAKA,MAAM,yBAAyB,WAAwB;EACrD,MAAM,WAAmB,CAAC;EAC1B,KAAK,MAAM,QAAQ,MAAM,KAAK,IAAI,OAAO,UAAU,GACjD,IAAI,gBAAgB,WAAW,KAAK,gBAAgB,uBAAuB;GACzE,MAAM,QAAQ,aAAa,MAAK,MAAK,EAAE,WAAW,IAAI;GACtD,IAAI,SAAS,MAAM,KAAK,eAAe,QAAQ,SAAS,KAAK,MAAM,IAAI;EACzE;EAEF,IAAI,SAAS,WAAW,GAAG;EAC3B,MAAM,UAAU,MAAM,KAAK,OAAO,UAAU,CAAC,CAAC,QAC5C,SAAQ,SAAS,SAAS,IAAI,KAAK,EAAE,gBAAgB,QACvD;EACA,IAAI,QAAQ,WAAW,SAAS,UAAU,QAAQ,OAAO,MAAM,UAAU,SAAS,SAAS,MAAM,GAAG;EACpG,KAAK,IAAI,QAAQ,SAAS,SAAS,GAAG,SAAS,GAAG,SAAS;GACzD,MAAM,OAAO,SAAS;GACtB,MAAM,OAAO,SAAS,QAAQ;GAC9B,IAAI,MACG;QAAA,KAAiB,uBAAuB,MAAM,OAAO,aAAa,MAAM,IAAI;GAAA,OAEjF,OAAO,YAAY,IAAI;EAE3B;CACF;;;;;;;;;;;;CAaA,MAAM,gCAAgC,cAAgC;EACpE,MAAM,0BAA0B,UAAyB;GACvD,IAAI,UAAuB;GAC3B,OAAO,WAAW,YAAY,OAAO;IACnC,IAAI,aAAa,MAAK,UAAS,MAAM,SAAS,OAAO,GAAG,OAAO;IAC/D,UAAU,QAAQ;GACpB;GACA,OAAO;EACT;EACA,MAAM,aAAa,IAAI,IAAI,UAAU,SAAQ,aAAY,CAAC,GAAG,SAAS,UAAU,CAAC,CAAC;EAClF,MAAM,SAAoB,CAAC;EAC3B,KAAK,MAAM,YAAY,WACrB,KAAK,MAAM,QAAQ,SAAS,YAAY;GACtC,IAAI,EAAE,gBAAgB,YAAY,KAAK,gBAAgB,uBAAuB;GAE9E,IAAI,CAAC,MAAM,SAAS,IAAI,GAAG;GAC3B,IAAI,uBAAuB,SAAS,MAAM,GAAG;GAC7C,OAAO,KAAK,IAAI;EAClB;EAEF,IAAI,CAAC,OAAO,QAAQ;EACpB,MAAM,eAAe,MAAM,KAAK,IAAI,OAAO,UAAU;EACrD,MAAM,iBAAiB,aACpB,QACC,UACE,CAAC,WAAW,IAAI,MAAM,IAAI,KAAK,UAAU,MAAK,aAAY,CAAC,GAAG,SAAS,YAAY,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,CAC7G,CAAC,CACA,MAAM,GAAG,MAAM,aAAa,QAAQ,EAAE,MAAM,IAAI,aAAa,QAAQ,EAAE,MAAM,CAAC;EACjF,KAAK,MAAM,CAAC,OAAO,YAAY,OAAO,QAAQ,GAAG;GAC/C,MAAM,SAAS,eAAe,KAAK,IAAI,OAAO,eAAe,SAAS,CAAC,EAAE,EAAE;GAC3E,IAAI,UAAU,OAAO,eAAe,IAAI,QAAQ,IAAI,OAAO,aAAa,SAAS,MAAM;QAClF,IAAI,OAAO,YAAY,OAAO;EACrC;CACF;CAEA,wBAAwB,IAAI,WAAW,IAAI,MAAM,CAAC,CAAC,YAAY,IAAI;CAGnE,gBAAgB,QAAQ,OAAO;EAAE,WAAW;EAAM,SAAS;CAAK,CAAC;CAIjE,MAAM,oBAAoB,IAAI;CAC9B,MAAM,eAAe,IAAI,kBAAiB,cAAa;EAMrD,MAAM,aAAa,IAAI,IAAI,UAAU,SAAQ,aAAY,CAAC,GAAG,SAAS,UAAU,CAAC,CAAC;EAClF,MAAM,gBAAgB,UACnB,SAAQ,aAAY,CAAC,GAAG,SAAS,YAAY,CAAC,CAAC,CAC/C,QAAO,SAAQ,gBAAgB,WAAW,KAAK,gBAAgB,yBAAyB,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,CAC9G,KAAI,WAAU,aAAa,MAAK,UAAS,MAAM,WAAW,MAAM,CAAC,EAAE,IAAI,CAAC,CACxE,QAAQ,SAAuB,SAAS,KAAA,CAAS;EACpD,IAAI,cAAc,QAAQ;GACxB,IAAI,cAAc,aAAa;GAE/B,KAAK,MAAM,QAAQ,eAAe,KAAK,YAAY,YAAY,IAAI;EACrE;EACA,IAAI,CAAC,mBAAmB;EACxB,MAAM,aAAa,kBAAkB,UAAU,SAAQ,aAAY,CAAC,GAAG,SAAS,UAAU,CAAC,CAAC;EAC5F,IAAI,WAAW,QAAQ,IAAI,cAAc,UAAU;CACrD,CAAC;CACD,aAAa,QAAQ,IAAI,QAAQ,EAAE,WAAW,KAAK,CAAC;CAEpD,MAAM,MAAqB;EACzB;EAEA,YAAY,OAAO,SAAS,OAAO;GACjC,aAAa,SAAQ,UAAS,MAAM,OAAO,OAAO,CAAC;GACnD,MAAM,UAAU,MAAM,IAAI,WAAW,CAAC,CAAC,QAAQ,UAAqC,UAAU,IAAI;GAClG,aAAa,SAAS;GACtB,aAAa,KAAK,GAAG,OAAO;GAC5B,OAAO,OAAO,GAAG,KAAK;GACtB,sBAAsB,MAAM;EAC9B;EAEA,cAAc,OAAO,SAAS,OAAO;GACnC,KAAK,MAAM,QAAQ,OAAO;IACxB,aAAa,CAAC,IAAI,CAAC;IACnB,MAAM,QAAQ,YAAY,IAAI;IAC9B,IAAI,CAAC,OAAO;IACZ,OAAO,YAAY,MAAM,IAAI;GAC/B;GACA,sBAAsB,MAAM;EAC9B;EAEA,cAAc,OAAO;GAGnB,aAAa,KAAK;EACpB;EAEA,iBAAiB;GAGf,aAAa,WAAW;GAKxB,KAAK,MAAM,SAAS,cAAc;IAChC,MAAM,UAAqB,CAAC;IAC5B,IAAI,WAAW,MAAM,KAAK;IAC1B,OAAO,oBAAoB,WAAW,SAAS,gBAAgB,uBAAuB;KACpF,QAAQ,QAAQ,QAAQ;KACxB,WAAW,SAAS;IACtB;IACA,KAAK,MAAM,WAAW,SACpB,IAAI,MAAM,OAAO,eAAe,IAAI,QAAQ,IAAI,OAAO,aAAa,SAAS,MAAM,MAAM;SACpF,IAAI,OAAO,YAAY,OAAO;IAErC,IAAI,MAAM,OAAO,eAAe,IAAI,QAAQ,IAAI,OAAO,aAAa,MAAM,MAAM,MAAM,MAAM;SACvF,IAAI,OAAO,YAAY,MAAM,IAAI;IACtC,MAAM,OAAO,OAAO;GACtB;GACA,aAAa,SAAS;EACxB;EAEA,SAAS;GACP,aAAa,WAAW;GACxB,gBAAgB,WAAW;GAE3B,aAAa,SAAQ,UAAS,MAAM,OAAO,OAAO,CAAC;GACnD,aAAa,SAAS;GACtB,KAAK,OAAO;EACd;CACF;CACA,OAAO;AACT,CAAC;;;;;;AAOH,SAAS,qBAAqB,MAAY,cAAoB,UAAyB;CACrF,IAAI,UAAuB;CAC3B,OAAO,WAAW,YAAY,UAAU;EACtC,IAAI,YAAY,cAAc,OAAO;EACrC,UAAU,QAAQ;CACpB;CACA,OAAO;AACT;;AAGA,SAAS,sBAAsB,MAAyB;CACtD,IAAI,KAAK,YAAY,OAAO,KAAK;CACjC,MAAM,OAAO,KAAK,YAAY;CAC9B,OAAO,gBAAgB,aAAa,KAAK,OAAO;AAClD;;;;;;;;;;AAWA,SAAS,wBAAwB,QAA2C;CAC1E,IAAI,UAAuB;CAC3B,OAAO,WAAW,YAAY,SAAS,iBAAiB;EACtD,IAAI,mBAAmB,qBAAqB,QAAQ,MAAM,OAAO;EAGjE,IAAI,mBAAmB,WAAW,QAAQ,YAAY;GACpD,MAAM,UAAU,QAAQ,WAAW,iBAAiB,QAAQ;GAC5D,KAAK,MAAM,UAAU,SAAS;IAC5B,IAAI,EAAE,kBAAkB,sBAAsB,CAAC,OAAO,MAAM;IAC5D,MAAM,QAAQ,OAAO,iBAAiB,MAAM;IAC5C,KAAK,MAAM,QAAQ,OACjB,KAAK,MAAM,YAAY,KAAK,cAAc,GAAG;KAC3C,IAAI,EAAE,oBAAoB,OAAO;KACjC,IAAI,qBAAqB,QAAQ,UAAU,OAAO,GAAG,OAAO;IAC9D;GAEJ;EACF;EAEA,UAAU,sBAAsB,OAAO;CACzC;CACA,OAAO;AACT;AAEA,SAAgB,wBACd,WACA,QACA,UAA6C,CAAC,GACjC;CACb,MAAM,WAAW,OAAO,cAAc,aAAa,UAAU,IAAI;CACjE,IAAI,UAAU,OAAO;CAGrB,MAAM,kBAAkB,wBAAwB,MAAM;CACtD,IAAI,iBAAiB,OAAO;CAK5B,QADc,QAAQ,kBAAkB,cAAc,IAAI,iBAAiB,MAAM,EAAA,EACnE,eAAe,KAAK,uBAAuB;AAC3D"}
@@ -1,20 +1,19 @@
1
- import { definePlugin as e } from "@greypan/js-kit";
2
- //#region src/shared/overlay/positioning-generation.ts
3
- var t = () => e(() => {
4
- let e = 0;
1
+ import { definePlugin } from "@greypan/js-kit";
2
+ // src/shared/overlay/positioning-generation.ts
3
+ const defineOverlayPositioningGeneration = () => definePlugin(() => {
4
+ let generation = 0;
5
5
  return {
6
6
  next() {
7
- return ++e;
7
+ return ++generation;
8
8
  },
9
9
  invalidate() {
10
- ++e;
10
+ ++generation;
11
11
  },
12
- isCurrent(t) {
13
- return t === e;
12
+ isCurrent(candidate) {
13
+ return candidate === generation;
14
14
  }
15
15
  };
16
16
  });
17
- //#endregion
18
- export { t as defineOverlayPositioningGeneration };
17
+ export { defineOverlayPositioningGeneration };
19
18
 
20
19
  //# sourceMappingURL=positioning-generation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"positioning-generation.js","names":[],"sources":["../../../src/shared/overlay/positioning-generation.ts"],"sourcesContent":["import { definePlugin } from '@greypan/js-kit'\n\n/**\n * 异步 positioning 的代数令牌。一次定位请求启动前取得 generation;\n * 新请求或 close/reconfigure 后 invalidate,迟到 promise 不得再写 DOM。\n */\nexport interface OverlayPositioningGeneration {\n next(): number\n invalidate(): void\n isCurrent(generation: number): boolean\n}\n\nexport const defineOverlayPositioningGeneration = () =>\n definePlugin<OverlayPositioningGeneration, Record<never, never>>(() => {\n let generation = 0\n\n return {\n next() {\n return ++generation\n },\n\n invalidate() {\n ++generation\n },\n\n isCurrent(candidate: number) {\n return candidate === generation\n }\n }\n })\n"],"mappings":";;AAYA,IAAa,UACX,QAAuE;CACrE,IAAI,IAAa;CAEjB,OAAO;EACL,OAAO;GACL,OAAO,EAAE;EACX;EAEA,aAAa;GACX,EAAE;EACJ;EAEA,UAAU,GAAmB;GAC3B,OAAO,MAAc;EACvB;CACF;AACF,CAAC"}
1
+ {"version":3,"file":"positioning-generation.js","names":[],"sources":["../../../src/shared/overlay/positioning-generation.ts"],"sourcesContent":["import { definePlugin } from '@greypan/js-kit'\n\n/**\n * 异步 positioning 的代数令牌。一次定位请求启动前取得 generation;\n * 新请求或 close/reconfigure 后 invalidate,迟到 promise 不得再写 DOM。\n */\nexport interface OverlayPositioningGeneration {\n next(): number\n invalidate(): void\n isCurrent(generation: number): boolean\n}\n\nexport const defineOverlayPositioningGeneration = () =>\n definePlugin<OverlayPositioningGeneration, Record<never, never>>(() => {\n let generation = 0\n\n return {\n next() {\n return ++generation\n },\n\n invalidate() {\n ++generation\n },\n\n isCurrent(candidate: number) {\n return candidate === generation\n }\n }\n })\n"],"mappings":";;AAYA,MAAa,2CACX,mBAAuE;CACrE,IAAI,aAAa;CAEjB,OAAO;EACL,OAAO;GACL,OAAO,EAAE;EACX;EAEA,aAAa;GACX,EAAE;EACJ;EAEA,UAAU,WAAmB;GAC3B,OAAO,cAAc;EACvB;CACF;AACF,CAAC"}
@@ -1,31 +1,53 @@
1
- import { parseDuration as e } from "../theme/duration.js";
2
- //#region src/shared/overlay/presence.ts
3
- var t = 160, n = 80, r = /* @__PURE__ */ new WeakMap();
4
- function i(n, r = t) {
5
- let i = getComputedStyle(n), a = i.transitionDuration.split(",").map((t) => e(t) ?? 0), o = i.transitionDelay.split(",").map((t) => e(t) ?? 0);
6
- return a.reduce((e, t, n) => Math.max(e, t + (o[n] ?? o[0] ?? 0)), 0) || r;
1
+ import { parseDuration } from "../theme/duration.js";
2
+ // src/shared/overlay/presence.ts
3
+ const DEFAULT_EXIT_DURATION = 160;
4
+ const EXIT_FALLBACK_BUFFER = 80;
5
+ const pendingExits = /* @__PURE__ */ new WeakMap();
6
+ function getTransitionDuration(panel, fallback = DEFAULT_EXIT_DURATION) {
7
+ const style = getComputedStyle(panel);
8
+ const durations = style.transitionDuration.split(",").map((value) => parseDuration(value) ?? 0);
9
+ const delays = style.transitionDelay.split(",").map((value) => parseDuration(value) ?? 0);
10
+ return durations.reduce((max, duration, index) => Math.max(max, duration + (delays[index] ?? delays[0] ?? 0)), 0) || fallback;
7
11
  }
8
- function a(e, t = {}) {
9
- if (r.get(e)?.(), e.hidden = !1, t.isInstant) {
10
- e.dataset.wuiPresence = "open";
12
+ function showOverlayPresence(panel, options = {}) {
13
+ pendingExits.get(panel)?.();
14
+ panel.hidden = false;
15
+ if (options.isInstant) {
16
+ panel.dataset.wuiPresence = "open";
11
17
  return;
12
18
  }
13
- e.dataset.wuiPresence = "entering", e.offsetWidth, requestAnimationFrame(() => {
14
- e.dataset.wuiPresence === "entering" && (e.dataset.wuiPresence = "open");
19
+ panel.dataset.wuiPresence = "entering";
20
+ panel.offsetWidth;
21
+ requestAnimationFrame(() => {
22
+ if (panel.dataset.wuiPresence === "entering") panel.dataset.wuiPresence = "open";
15
23
  });
16
24
  }
17
- function o(e) {
18
- return r.get(e)?.(), e.dataset.wuiPresence = "closing", i(e, 0) === 0 ? (e.hidden = !0, Promise.resolve(!0)) : new Promise((t) => {
19
- let a = !1, o = (n) => {
20
- a || (a = !0, e.removeEventListener("transitionend", s), clearTimeout(c), r.delete(e), n && e.dataset.wuiPresence === "closing" && (e.hidden = !0), t(n));
21
- }, s = (t) => {
22
- t.target === e && (t.propertyName === "opacity" || t.propertyName === "transform") && o(!0);
25
+ function hideOverlayPresence(panel) {
26
+ pendingExits.get(panel)?.();
27
+ panel.dataset.wuiPresence = "closing";
28
+ if (getTransitionDuration(panel, 0) === 0) {
29
+ panel.hidden = true;
30
+ return Promise.resolve(true);
31
+ }
32
+ return new Promise((resolve) => {
33
+ let settled = false;
34
+ const finish = (didClose) => {
35
+ if (settled) return;
36
+ settled = true;
37
+ panel.removeEventListener("transitionend", onTransitionEnd);
38
+ clearTimeout(timeout);
39
+ pendingExits.delete(panel);
40
+ if (didClose && panel.dataset.wuiPresence === "closing") panel.hidden = true;
41
+ resolve(didClose);
42
+ };
43
+ const onTransitionEnd = (event) => {
44
+ if (event.target === panel && (event.propertyName === "opacity" || event.propertyName === "transform")) finish(true);
23
45
  };
24
- r.set(e, () => o(!1)), e.addEventListener("transitionend", s);
25
- let c = setTimeout(() => o(!0), i(e) + n);
46
+ pendingExits.set(panel, () => finish(false));
47
+ panel.addEventListener("transitionend", onTransitionEnd);
48
+ const timeout = setTimeout(() => finish(true), getTransitionDuration(panel) + EXIT_FALLBACK_BUFFER);
26
49
  });
27
50
  }
28
- //#endregion
29
- export { i as getTransitionDuration, o as hideOverlayPresence, a as showOverlayPresence };
51
+ export { getTransitionDuration, hideOverlayPresence, showOverlayPresence };
30
52
 
31
53
  //# sourceMappingURL=presence.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"presence.js","names":[],"sources":["../../../src/shared/overlay/presence.ts"],"sourcesContent":["import { parseDuration } from '@/shared/theme/duration'\n\nconst DEFAULT_EXIT_DURATION = 160\nconst EXIT_FALLBACK_BUFFER = 80\n\nconst pendingExits = new WeakMap<HTMLElement, () => void>()\n\ninterface OverlayPresenceOptions {\n isInstant?: boolean\n}\n\n// 读取元素实际 CSS transition 的最长时长,供可覆盖主题 token 的 JS 生命周期使用。\nexport function getTransitionDuration(panel: HTMLElement, fallback = DEFAULT_EXIT_DURATION): number {\n const style = getComputedStyle(panel)\n const durations = style.transitionDuration.split(',').map(value => parseDuration(value) ?? 0)\n const delays = style.transitionDelay.split(',').map(value => parseDuration(value) ?? 0)\n const longest = durations.reduce(\n (max, duration, index) => Math.max(max, duration + (delays[index] ?? delays[0] ?? 0)),\n 0\n )\n\n return longest || fallback\n}\n\n// 以可中断的方式显示 overlay,避免快速切换时重启动画。\nexport function showOverlayPresence(panel: HTMLElement, options: OverlayPresenceOptions = {}) {\n pendingExits.get(panel)?.()\n panel.hidden = false\n if (options.isInstant) {\n panel.dataset.wuiPresence = 'open'\n return\n }\n panel.dataset.wuiPresence = 'entering'\n\n // 提交初始状态,让新挂载的 panel 拥有过渡起点。\n void panel.offsetWidth\n\n requestAnimationFrame(() => {\n if (panel.dataset.wuiPresence === 'entering') panel.dataset.wuiPresence = 'open'\n })\n}\n\n// 播放退出过渡;若在结束前重新显示则返回 false。\nexport function hideOverlayPresence(panel: HTMLElement): Promise<boolean> {\n pendingExits.get(panel)?.()\n panel.dataset.wuiPresence = 'closing'\n\n // jsdom 等没有计算 CSS transition 的环境无需伪造退场等待。\n if (getTransitionDuration(panel, 0) === 0) {\n panel.hidden = true\n return Promise.resolve(true)\n }\n\n return new Promise(resolve => {\n let settled = false\n const finish = (didClose: boolean) => {\n if (settled) return\n settled = true\n panel.removeEventListener('transitionend', onTransitionEnd)\n clearTimeout(timeout)\n pendingExits.delete(panel)\n if (didClose && panel.dataset.wuiPresence === 'closing') panel.hidden = true\n resolve(didClose)\n }\n\n const onTransitionEnd = (event: TransitionEvent) => {\n if (event.target === panel && (event.propertyName === 'opacity' || event.propertyName === 'transform'))\n finish(true)\n }\n\n pendingExits.set(panel, () => finish(false))\n panel.addEventListener('transitionend', onTransitionEnd)\n const timeout = setTimeout(() => finish(true), getTransitionDuration(panel) + EXIT_FALLBACK_BUFFER)\n })\n}\n"],"mappings":";;AAEA,IAAM,IAAwB,KACxB,IAAuB,IAEvB,oBAAe,IAAI,QAAiC;AAO1D,SAAgB,EAAsB,GAAoB,IAAW,GAA+B;CAClG,IAAM,IAAQ,iBAAiB,CAAK,GAC9B,IAAY,EAAM,mBAAmB,MAAM,GAAG,CAAC,CAAC,KAAI,MAAS,EAAc,CAAK,KAAK,CAAC,GACtF,IAAS,EAAM,gBAAgB,MAAM,GAAG,CAAC,CAAC,KAAI,MAAS,EAAc,CAAK,KAAK,CAAC;CAMtF,OALgB,EAAU,QACvB,GAAK,GAAU,MAAU,KAAK,IAAI,GAAK,KAAY,EAAO,MAAU,EAAO,MAAM,EAAE,GACpF,CAGK,KAAW;AACpB;AAGA,SAAgB,EAAoB,GAAoB,IAAkC,CAAC,GAAG;CAG5F,IAFA,EAAa,IAAI,CAAK,CAAC,GAAG,GAC1B,EAAM,SAAS,IACX,EAAQ,WAAW;EACrB,EAAM,QAAQ,cAAc;EAC5B;CACF;CAMA,AALA,EAAM,QAAQ,cAAc,YAG5B,EAAW,aAEX,4BAA4B;EAC1B,AAAI,EAAM,QAAQ,gBAAgB,eAAY,EAAM,QAAQ,cAAc;CAC5E,CAAC;AACH;AAGA,SAAgB,EAAoB,GAAsC;CAUxE,OATA,EAAa,IAAI,CAAK,CAAC,GAAG,GAC1B,EAAM,QAAQ,cAAc,WAGxB,EAAsB,GAAO,CAAC,MAAM,KACtC,EAAM,SAAS,IACR,QAAQ,QAAQ,EAAI,KAGtB,IAAI,SAAQ,MAAW;EAC5B,IAAI,IAAU,IACR,KAAU,MAAsB;GAChC,MACJ,IAAU,IACV,EAAM,oBAAoB,iBAAiB,CAAe,GAC1D,aAAa,CAAO,GACpB,EAAa,OAAO,CAAK,GACrB,KAAY,EAAM,QAAQ,gBAAgB,cAAW,EAAM,SAAS,KACxE,EAAQ,CAAQ;EAClB,GAEM,KAAmB,MAA2B;GAClD,AAAI,EAAM,WAAW,MAAU,EAAM,iBAAiB,aAAa,EAAM,iBAAiB,gBACxF,EAAO,EAAI;EACf;EAGA,AADA,EAAa,IAAI,SAAa,EAAO,EAAK,CAAC,GAC3C,EAAM,iBAAiB,iBAAiB,CAAe;EACvD,IAAM,IAAU,iBAAiB,EAAO,EAAI,GAAG,EAAsB,CAAK,IAAI,CAAoB;CACpG,CAAC;AACH"}
1
+ {"version":3,"file":"presence.js","names":[],"sources":["../../../src/shared/overlay/presence.ts"],"sourcesContent":["import { parseDuration } from '@/shared/theme/duration'\n\nconst DEFAULT_EXIT_DURATION = 160\nconst EXIT_FALLBACK_BUFFER = 80\n\nconst pendingExits = new WeakMap<HTMLElement, () => void>()\n\ninterface OverlayPresenceOptions {\n isInstant?: boolean\n}\n\n// 读取元素实际 CSS transition 的最长时长,供可覆盖主题 token 的 JS 生命周期使用。\nexport function getTransitionDuration(panel: HTMLElement, fallback = DEFAULT_EXIT_DURATION): number {\n const style = getComputedStyle(panel)\n const durations = style.transitionDuration.split(',').map(value => parseDuration(value) ?? 0)\n const delays = style.transitionDelay.split(',').map(value => parseDuration(value) ?? 0)\n const longest = durations.reduce(\n (max, duration, index) => Math.max(max, duration + (delays[index] ?? delays[0] ?? 0)),\n 0\n )\n\n return longest || fallback\n}\n\n// 以可中断的方式显示 overlay,避免快速切换时重启动画。\nexport function showOverlayPresence(panel: HTMLElement, options: OverlayPresenceOptions = {}) {\n pendingExits.get(panel)?.()\n panel.hidden = false\n if (options.isInstant) {\n panel.dataset.wuiPresence = 'open'\n return\n }\n panel.dataset.wuiPresence = 'entering'\n\n // 提交初始状态,让新挂载的 panel 拥有过渡起点。\n void panel.offsetWidth\n\n requestAnimationFrame(() => {\n if (panel.dataset.wuiPresence === 'entering') panel.dataset.wuiPresence = 'open'\n })\n}\n\n// 播放退出过渡;若在结束前重新显示则返回 false。\nexport function hideOverlayPresence(panel: HTMLElement): Promise<boolean> {\n pendingExits.get(panel)?.()\n panel.dataset.wuiPresence = 'closing'\n\n // jsdom 等没有计算 CSS transition 的环境无需伪造退场等待。\n if (getTransitionDuration(panel, 0) === 0) {\n panel.hidden = true\n return Promise.resolve(true)\n }\n\n return new Promise(resolve => {\n let settled = false\n const finish = (didClose: boolean) => {\n if (settled) return\n settled = true\n panel.removeEventListener('transitionend', onTransitionEnd)\n clearTimeout(timeout)\n pendingExits.delete(panel)\n if (didClose && panel.dataset.wuiPresence === 'closing') panel.hidden = true\n resolve(didClose)\n }\n\n const onTransitionEnd = (event: TransitionEvent) => {\n if (event.target === panel && (event.propertyName === 'opacity' || event.propertyName === 'transform'))\n finish(true)\n }\n\n pendingExits.set(panel, () => finish(false))\n panel.addEventListener('transitionend', onTransitionEnd)\n const timeout = setTimeout(() => finish(true), getTransitionDuration(panel) + EXIT_FALLBACK_BUFFER)\n })\n}\n"],"mappings":";;AAEA,MAAM,wBAAwB;AAC9B,MAAM,uBAAuB;AAE7B,MAAM,+BAAe,IAAI,QAAiC;AAO1D,SAAgB,sBAAsB,OAAoB,WAAW,uBAA+B;CAClG,MAAM,QAAQ,iBAAiB,KAAK;CACpC,MAAM,YAAY,MAAM,mBAAmB,MAAM,GAAG,CAAC,CAAC,KAAI,UAAS,cAAc,KAAK,KAAK,CAAC;CAC5F,MAAM,SAAS,MAAM,gBAAgB,MAAM,GAAG,CAAC,CAAC,KAAI,UAAS,cAAc,KAAK,KAAK,CAAC;CAMtF,OALgB,UAAU,QACvB,KAAK,UAAU,UAAU,KAAK,IAAI,KAAK,YAAY,OAAO,UAAU,OAAO,MAAM,EAAE,GACpF,CAGW,KAAK;AACpB;AAGA,SAAgB,oBAAoB,OAAoB,UAAkC,CAAC,GAAG;CAC5F,aAAa,IAAI,KAAK,CAAC,GAAG;CAC1B,MAAM,SAAS;CACf,IAAI,QAAQ,WAAW;EACrB,MAAM,QAAQ,cAAc;EAC5B;CACF;CACA,MAAM,QAAQ,cAAc;CAG5B,MAAW;CAEX,4BAA4B;EAC1B,IAAI,MAAM,QAAQ,gBAAgB,YAAY,MAAM,QAAQ,cAAc;CAC5E,CAAC;AACH;AAGA,SAAgB,oBAAoB,OAAsC;CACxE,aAAa,IAAI,KAAK,CAAC,GAAG;CAC1B,MAAM,QAAQ,cAAc;CAG5B,IAAI,sBAAsB,OAAO,CAAC,MAAM,GAAG;EACzC,MAAM,SAAS;EACf,OAAO,QAAQ,QAAQ,IAAI;CAC7B;CAEA,OAAO,IAAI,SAAQ,YAAW;EAC5B,IAAI,UAAU;EACd,MAAM,UAAU,aAAsB;GACpC,IAAI,SAAS;GACb,UAAU;GACV,MAAM,oBAAoB,iBAAiB,eAAe;GAC1D,aAAa,OAAO;GACpB,aAAa,OAAO,KAAK;GACzB,IAAI,YAAY,MAAM,QAAQ,gBAAgB,WAAW,MAAM,SAAS;GACxE,QAAQ,QAAQ;EAClB;EAEA,MAAM,mBAAmB,UAA2B;GAClD,IAAI,MAAM,WAAW,UAAU,MAAM,iBAAiB,aAAa,MAAM,iBAAiB,cACxF,OAAO,IAAI;EACf;EAEA,aAAa,IAAI,aAAa,OAAO,KAAK,CAAC;EAC3C,MAAM,iBAAiB,iBAAiB,eAAe;EACvD,MAAM,UAAU,iBAAiB,OAAO,IAAI,GAAG,sBAAsB,KAAK,IAAI,oBAAoB;CACpG,CAAC;AACH"}