@greypan/web-ui 11.1.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.
- package/README.CN.md +79 -68
- package/README.md +81 -72
- package/dist/_virtual/_@oxc-project_runtime@0.155.0/helpers/esm/decorate.js +8 -0
- package/dist/assets/menu-portal.js +3 -4
- package/dist/assets/menu-portal.js.map +1 -1
- package/dist/assets/modal-surface.js +3 -4
- package/dist/assets/modal-surface.js.map +1 -1
- package/dist/assets/overlay-motion.js +3 -4
- package/dist/assets/overlay-motion.js.map +1 -1
- package/dist/assets/scrollbar.js +5 -0
- package/dist/assets/scrollbar.js.map +1 -0
- package/dist/assets/selection-control.js +3 -4
- package/dist/assets/selection-control.js.map +1 -1
- package/dist/assets/toast-containers.js +3 -4
- package/dist/assets/toast-containers.js.map +1 -1
- package/dist/classes/glass.js +3 -4
- package/dist/classes/glass.js.map +1 -1
- package/dist/classes/glow.js +3 -4
- package/dist/classes/glow.js.map +1 -1
- package/dist/components/autocomplete/index.d.ts +485 -483
- package/dist/components/autocomplete/index.d.ts.map +1 -0
- package/dist/components/autocomplete/index.js +475 -267
- package/dist/components/autocomplete/index.js.map +1 -1
- package/dist/components/autocomplete/style.js +3 -4
- package/dist/components/autocomplete/style.js.map +1 -1
- package/dist/components/avatar/index.d.ts +26 -24
- package/dist/components/avatar/index.d.ts.map +1 -0
- package/dist/components/avatar/index.js +72 -52
- package/dist/components/avatar/index.js.map +1 -1
- package/dist/components/avatar/style.js +3 -4
- package/dist/components/avatar/style.js.map +1 -1
- package/dist/components/back-top/index.d.ts +30 -27
- package/dist/components/back-top/index.d.ts.map +1 -0
- package/dist/components/back-top/index.js +96 -62
- package/dist/components/back-top/index.js.map +1 -1
- package/dist/components/back-top/style.js +3 -4
- package/dist/components/back-top/style.js.map +1 -1
- package/dist/components/badge/index.d.ts +32 -26
- package/dist/components/badge/index.d.ts.map +1 -0
- package/dist/components/badge/index.js +116 -74
- package/dist/components/badge/index.js.map +1 -1
- package/dist/components/badge/style.js +3 -4
- package/dist/components/badge/style.js.map +1 -1
- package/dist/components/button/index.d.ts +392 -391
- package/dist/components/button/index.d.ts.map +1 -0
- package/dist/components/button/index.js +109 -79
- package/dist/components/button/index.js.map +1 -1
- package/dist/components/button/style.js +3 -4
- package/dist/components/button/style.js.map +1 -1
- package/dist/components/button-group/index.d.ts +14 -13
- package/dist/components/button-group/index.d.ts.map +1 -0
- package/dist/components/button-group/index.js +43 -33
- package/dist/components/button-group/index.js.map +1 -1
- package/dist/components/button-group/style.js +3 -4
- package/dist/components/button-group/style.js.map +1 -1
- package/dist/components/checkbox/index.d.ts +399 -397
- package/dist/components/checkbox/index.d.ts.map +1 -0
- package/dist/components/checkbox/index.js +103 -74
- package/dist/components/checkbox/index.js.map +1 -1
- package/dist/components/checkbox/style.js +3 -4
- package/dist/components/checkbox/style.js.map +1 -1
- package/dist/components/checkbox-group/index.d.ts +397 -396
- package/dist/components/checkbox-group/index.d.ts.map +1 -0
- package/dist/components/checkbox-group/index.js +92 -70
- package/dist/components/checkbox-group/index.js.map +1 -1
- package/dist/components/checkbox-group/style.js +3 -4
- package/dist/components/checkbox-group/style.js.map +1 -1
- package/dist/components/collapse/index.d.ts +82 -75
- package/dist/components/collapse/index.d.ts.map +1 -0
- package/dist/components/collapse/index.js +228 -135
- package/dist/components/collapse/index.js.map +1 -1
- package/dist/components/collapse/style.js +3 -4
- package/dist/components/collapse/style.js.map +1 -1
- package/dist/components/context-menu/index.d.ts +307 -310
- package/dist/components/context-menu/index.d.ts.map +1 -0
- package/dist/components/context-menu/index.js +685 -270
- package/dist/components/context-menu/index.js.map +1 -1
- package/dist/components/context-menu/scrim.js +3 -4
- package/dist/components/context-menu/scrim.js.map +1 -1
- package/dist/components/context-menu/style.js +3 -4
- package/dist/components/context-menu/style.js.map +1 -1
- package/dist/components/dialog/index.d.ts +87 -78
- package/dist/components/dialog/index.d.ts.map +1 -0
- package/dist/components/dialog/index.js +183 -88
- package/dist/components/dialog/index.js.map +1 -1
- package/dist/components/dialog/style.js +3 -4
- package/dist/components/dialog/style.js.map +1 -1
- package/dist/components/drawer/index.d.ts +159 -150
- package/dist/components/drawer/index.d.ts.map +1 -0
- package/dist/components/drawer/index.js +503 -242
- package/dist/components/drawer/index.js.map +1 -1
- package/dist/components/drawer/style.js +3 -4
- package/dist/components/drawer/style.js.map +1 -1
- package/dist/components/dropdown/index.d.ts +125 -124
- package/dist/components/dropdown/index.d.ts.map +1 -0
- package/dist/components/dropdown/index.js +556 -328
- package/dist/components/dropdown/index.js.map +1 -1
- package/dist/components/dropdown/style.js +3 -4
- package/dist/components/dropdown/style.js.map +1 -1
- package/dist/components/dropdown-divider/index.d.ts +7 -6
- package/dist/components/dropdown-divider/index.d.ts.map +1 -0
- package/dist/components/dropdown-divider/index.js +10 -11
- package/dist/components/dropdown-divider/index.js.map +1 -1
- package/dist/components/dropdown-divider/style.js +3 -4
- package/dist/components/dropdown-divider/style.js.map +1 -1
- package/dist/components/dropdown-header/index.d.ts +7 -6
- package/dist/components/dropdown-header/index.d.ts.map +1 -0
- package/dist/components/dropdown-header/index.js +10 -11
- package/dist/components/dropdown-header/index.js.map +1 -1
- package/dist/components/dropdown-header/style.js +3 -4
- package/dist/components/dropdown-header/style.js.map +1 -1
- package/dist/components/dropdown-item/index.d.ts +13 -11
- package/dist/components/dropdown-item/index.d.ts.map +1 -0
- package/dist/components/dropdown-item/index.js +32 -25
- package/dist/components/dropdown-item/index.js.map +1 -1
- package/dist/components/dropdown-item/style.js +3 -4
- package/dist/components/dropdown-item/style.js.map +1 -1
- package/dist/components/editable-text/index.d.ts +506 -505
- package/dist/components/editable-text/index.d.ts.map +1 -0
- package/dist/components/editable-text/index.js +281 -127
- package/dist/components/editable-text/index.js.map +1 -1
- package/dist/components/editable-text/style.js +3 -4
- package/dist/components/editable-text/style.js.map +1 -1
- package/dist/components/empty/index.d.ts +26 -36
- package/dist/components/empty/index.d.ts.map +1 -0
- package/dist/components/empty/index.js +73 -60
- package/dist/components/empty/index.js.map +1 -1
- package/dist/components/empty/style.js +3 -4
- package/dist/components/empty/style.js.map +1 -1
- package/dist/components/icon/index.d.ts +12 -11
- package/dist/components/icon/index.d.ts.map +1 -0
- package/dist/components/icon/index.js +34 -27
- package/dist/components/icon/index.js.map +1 -1
- package/dist/components/icon/style.js +3 -4
- package/dist/components/icon/style.js.map +1 -1
- package/dist/components/image-preview/index.d.ts +58 -44
- package/dist/components/image-preview/index.d.ts.map +1 -0
- package/dist/components/image-preview/index.js +536 -265
- package/dist/components/image-preview/index.js.map +1 -1
- package/dist/components/image-preview/style.js +3 -4
- package/dist/components/image-preview/style.js.map +1 -1
- package/dist/components/index.d.ts +46 -43
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +41 -41
- package/dist/components/input/index.d.ts +418 -413
- package/dist/components/input/index.d.ts.map +1 -0
- package/dist/components/input/index.js +148 -84
- package/dist/components/input/index.js.map +1 -1
- package/dist/components/input/style.js +3 -4
- package/dist/components/input/style.js.map +1 -1
- package/dist/components/input-number/index.d.ts +453 -447
- package/dist/components/input-number/index.d.ts.map +1 -0
- package/dist/components/input-number/index.js +484 -292
- package/dist/components/input-number/index.js.map +1 -1
- package/dist/components/input-number/style.js +3 -4
- package/dist/components/input-number/style.js.map +1 -1
- package/dist/components/layout/index.d.ts +110 -87
- package/dist/components/layout/index.d.ts.map +1 -0
- package/dist/components/layout/index.js +238 -144
- package/dist/components/layout/index.js.map +1 -1
- package/dist/components/layout/style.js +3 -4
- package/dist/components/layout/style.js.map +1 -1
- package/dist/components/middle-ellipsis/index.d.ts +93 -92
- package/dist/components/middle-ellipsis/index.d.ts.map +1 -0
- package/dist/components/middle-ellipsis/index.js +261 -107
- package/dist/components/middle-ellipsis/index.js.map +1 -1
- package/dist/components/middle-ellipsis/style.js +3 -4
- package/dist/components/middle-ellipsis/style.js.map +1 -1
- package/dist/components/middle-ellipsis/truncate.js +60 -30
- package/dist/components/middle-ellipsis/truncate.js.map +1 -1
- package/dist/components/option/index.d.ts +20 -18
- package/dist/components/option/index.d.ts.map +1 -0
- package/dist/components/option/index.js +53 -40
- package/dist/components/option/index.js.map +1 -1
- package/dist/components/option/style.js +3 -4
- package/dist/components/option/style.js.map +1 -1
- package/dist/components/popover/index.d.ts +69 -68
- package/dist/components/popover/index.d.ts.map +1 -0
- package/dist/components/popover/index.js +221 -104
- package/dist/components/popover/index.js.map +1 -1
- package/dist/components/popover/style.js +3 -4
- package/dist/components/popover/style.js.map +1 -1
- package/dist/components/radio/index.d.ts +396 -395
- package/dist/components/radio/index.d.ts.map +1 -0
- package/dist/components/radio/index.js +91 -62
- package/dist/components/radio/index.js.map +1 -1
- package/dist/components/radio/interaction.js +10 -11
- package/dist/components/radio/interaction.js.map +1 -1
- package/dist/components/radio/style.js +3 -4
- package/dist/components/radio/style.js.map +1 -1
- package/dist/components/radio-group/index.d.ts +417 -416
- package/dist/components/radio-group/index.d.ts.map +1 -0
- package/dist/components/radio-group/index.js +307 -207
- package/dist/components/radio-group/index.js.map +1 -1
- package/dist/components/radio-group/style.js +3 -4
- package/dist/components/radio-group/style.js.map +1 -1
- package/dist/components/segmented/index.d.ts +408 -402
- package/dist/components/segmented/index.d.ts.map +1 -0
- package/dist/components/segmented/index.js +267 -158
- package/dist/components/segmented/index.js.map +1 -1
- package/dist/components/segmented/style.js +3 -4
- package/dist/components/segmented/style.js.map +1 -1
- package/dist/components/segmented-trigger/index.d.ts +18 -17
- package/dist/components/segmented-trigger/index.d.ts.map +1 -0
- package/dist/components/segmented-trigger/index.js +45 -36
- package/dist/components/segmented-trigger/index.js.map +1 -1
- package/dist/components/segmented-trigger/style.js +3 -4
- package/dist/components/segmented-trigger/style.js.map +1 -1
- package/dist/components/select/index.d.ts +450 -448
- package/dist/components/select/index.d.ts.map +1 -0
- package/dist/components/select/index.js +342 -188
- package/dist/components/select/index.js.map +1 -1
- package/dist/components/select/style.js +3 -4
- package/dist/components/select/style.js.map +1 -1
- package/dist/components/slider/index.d.ts +428 -427
- package/dist/components/slider/index.d.ts.map +1 -0
- package/dist/components/slider/index.js +308 -216
- package/dist/components/slider/index.js.map +1 -1
- package/dist/components/slider/style.js +3 -4
- package/dist/components/slider/style.js.map +1 -1
- package/dist/components/spinner/index.d.ts +39 -38
- package/dist/components/spinner/index.d.ts.map +1 -0
- package/dist/components/spinner/index.js +118 -65
- package/dist/components/spinner/index.js.map +1 -1
- package/dist/components/spinner/style.js +3 -4
- package/dist/components/spinner/style.js.map +1 -1
- package/dist/components/svg-draw-lines/index.d.ts +40 -39
- package/dist/components/svg-draw-lines/index.d.ts.map +1 -0
- package/dist/components/svg-draw-lines/index.js +189 -106
- package/dist/components/svg-draw-lines/index.js.map +1 -1
- package/dist/components/svg-draw-lines/style.js +3 -4
- package/dist/components/svg-draw-lines/style.js.map +1 -1
- package/dist/components/switch/index.d.ts +411 -409
- package/dist/components/switch/index.d.ts.map +1 -0
- package/dist/components/switch/index.js +193 -106
- package/dist/components/switch/index.js.map +1 -1
- package/dist/components/switch/style.js +3 -4
- package/dist/components/switch/style.js.map +1 -1
- package/dist/components/textarea/index.d.ts +430 -425
- package/dist/components/textarea/index.d.ts.map +1 -0
- package/dist/components/textarea/index.js +187 -100
- package/dist/components/textarea/index.js.map +1 -1
- package/dist/components/textarea/style.js +3 -4
- package/dist/components/textarea/style.js.map +1 -1
- package/dist/components/theme/index.d.ts +45 -44
- package/dist/components/theme/index.d.ts.map +1 -0
- package/dist/components/theme/index.js +268 -161
- package/dist/components/theme/index.js.map +1 -1
- package/dist/components/theme/style.js +3 -4
- package/dist/components/theme/style.js.map +1 -1
- package/dist/components/toast/index.d.ts +4 -3
- package/dist/components/toast/index.js +3 -3
- package/dist/components/toast/manager.d.ts +9 -8
- package/dist/components/toast/manager.d.ts.map +1 -0
- package/dist/components/toast/manager.js +215 -119
- package/dist/components/toast/manager.js.map +1 -1
- package/dist/components/toast/style.js +3 -4
- package/dist/components/toast/style.js.map +1 -1
- package/dist/components/toast/toast.d.ts +75 -71
- package/dist/components/toast/toast.d.ts.map +1 -0
- package/dist/components/toast/toast.js +203 -96
- package/dist/components/toast/toast.js.map +1 -1
- package/dist/components/toast/types.d.ts +10 -9
- package/dist/components/toast/types.d.ts.map +1 -0
- package/dist/components/tooltip/index.d.ts +72 -62
- package/dist/components/tooltip/index.d.ts.map +1 -0
- package/dist/components/tooltip/index.js +251 -93
- package/dist/components/tooltip/index.js.map +1 -1
- package/dist/components/tooltip/style.js +3 -4
- package/dist/components/tooltip/style.js.map +1 -1
- package/dist/icons/generated/akar-icons-check.d.ts +5 -4
- package/dist/icons/generated/akar-icons-check.d.ts.map +1 -0
- package/dist/icons/generated/akar-icons-check.js +3 -4
- package/dist/icons/generated/akar-icons-check.js.map +1 -1
- package/dist/icons/generated/akar-icons-circle-check.d.ts +5 -4
- package/dist/icons/generated/akar-icons-circle-check.d.ts.map +1 -0
- package/dist/icons/generated/akar-icons-circle-check.js +3 -4
- package/dist/icons/generated/akar-icons-circle-check.js.map +1 -1
- package/dist/icons/generated/andrsrxn-inbox.d.ts +7 -0
- package/dist/icons/generated/andrsrxn-inbox.d.ts.map +1 -0
- package/dist/icons/generated/andrsrxn-inbox.js +9 -0
- package/dist/icons/generated/andrsrxn-inbox.js.map +1 -0
- package/dist/icons/generated/bi-check-lg.d.ts +5 -4
- package/dist/icons/generated/bi-check-lg.d.ts.map +1 -0
- package/dist/icons/generated/bi-check-lg.js +3 -4
- package/dist/icons/generated/bi-check-lg.js.map +1 -1
- package/dist/icons/generated/bi-check.d.ts +5 -4
- package/dist/icons/generated/bi-check.d.ts.map +1 -0
- package/dist/icons/generated/bi-check.js +3 -4
- package/dist/icons/generated/bi-check.js.map +1 -1
- package/dist/icons/generated/fluent-tag-search-24-regular.d.ts +5 -4
- package/dist/icons/generated/fluent-tag-search-24-regular.d.ts.map +1 -0
- package/dist/icons/generated/fluent-tag-search-24-regular.js +3 -4
- package/dist/icons/generated/fluent-tag-search-24-regular.js.map +1 -1
- package/dist/icons/generated/heroicons-bars-arrow-down-16-solid.d.ts +5 -4
- package/dist/icons/generated/heroicons-bars-arrow-down-16-solid.d.ts.map +1 -0
- package/dist/icons/generated/heroicons-bars-arrow-down-16-solid.js +3 -4
- package/dist/icons/generated/heroicons-bars-arrow-down-16-solid.js.map +1 -1
- package/dist/icons/generated/heroicons-bars-arrow-up-16-solid.d.ts +5 -4
- package/dist/icons/generated/heroicons-bars-arrow-up-16-solid.d.ts.map +1 -0
- package/dist/icons/generated/heroicons-bars-arrow-up-16-solid.js +3 -4
- package/dist/icons/generated/heroicons-bars-arrow-up-16-solid.js.map +1 -1
- package/dist/icons/generated/heroicons-check-16-solid.d.ts +5 -4
- package/dist/icons/generated/heroicons-check-16-solid.d.ts.map +1 -0
- package/dist/icons/generated/heroicons-check-16-solid.js +3 -4
- package/dist/icons/generated/heroicons-check-16-solid.js.map +1 -1
- package/dist/icons/generated/heroicons-x-mark-16-solid.d.ts +5 -4
- package/dist/icons/generated/heroicons-x-mark-16-solid.d.ts.map +1 -0
- package/dist/icons/generated/heroicons-x-mark-16-solid.js +3 -4
- package/dist/icons/generated/heroicons-x-mark-16-solid.js.map +1 -1
- package/dist/icons/generated/jam-close-circle-f.d.ts +7 -6
- package/dist/icons/generated/jam-close-circle-f.d.ts.map +1 -0
- package/dist/icons/generated/jam-close-circle-f.js +3 -4
- package/dist/icons/generated/jam-close-circle-f.js.map +1 -1
- package/dist/icons/generated/lucide-arrow-down-to-line.d.ts +5 -4
- package/dist/icons/generated/lucide-arrow-down-to-line.d.ts.map +1 -0
- package/dist/icons/generated/lucide-arrow-down-to-line.js +3 -4
- package/dist/icons/generated/lucide-arrow-down-to-line.js.map +1 -1
- package/dist/icons/generated/lucide-arrow-up-to-line.d.ts +5 -4
- package/dist/icons/generated/lucide-arrow-up-to-line.d.ts.map +1 -0
- package/dist/icons/generated/lucide-arrow-up-to-line.js +3 -4
- package/dist/icons/generated/lucide-arrow-up-to-line.js.map +1 -1
- package/dist/icons/generated/lucide-bell.d.ts +5 -4
- package/dist/icons/generated/lucide-bell.d.ts.map +1 -0
- package/dist/icons/generated/lucide-bell.js +3 -4
- package/dist/icons/generated/lucide-bell.js.map +1 -1
- package/dist/icons/generated/lucide-check.d.ts +5 -4
- package/dist/icons/generated/lucide-check.d.ts.map +1 -0
- package/dist/icons/generated/lucide-check.js +3 -4
- package/dist/icons/generated/lucide-check.js.map +1 -1
- package/dist/icons/generated/lucide-chevron-down.d.ts +5 -4
- package/dist/icons/generated/lucide-chevron-down.d.ts.map +1 -0
- package/dist/icons/generated/lucide-chevron-down.js +3 -4
- package/dist/icons/generated/lucide-chevron-down.js.map +1 -1
- package/dist/icons/generated/lucide-chevron-left.d.ts +5 -4
- package/dist/icons/generated/lucide-chevron-left.d.ts.map +1 -0
- package/dist/icons/generated/lucide-chevron-left.js +3 -4
- package/dist/icons/generated/lucide-chevron-left.js.map +1 -1
- package/dist/icons/generated/lucide-chevron-right.d.ts +5 -4
- package/dist/icons/generated/lucide-chevron-right.d.ts.map +1 -0
- package/dist/icons/generated/lucide-chevron-right.js +3 -4
- package/dist/icons/generated/lucide-chevron-right.js.map +1 -1
- package/dist/icons/generated/lucide-chevron-up.d.ts +5 -4
- package/dist/icons/generated/lucide-chevron-up.d.ts.map +1 -0
- package/dist/icons/generated/lucide-chevron-up.js +3 -4
- package/dist/icons/generated/lucide-chevron-up.js.map +1 -1
- package/dist/icons/generated/lucide-circle-alert.d.ts +5 -4
- package/dist/icons/generated/lucide-circle-alert.d.ts.map +1 -0
- package/dist/icons/generated/lucide-circle-alert.js +3 -4
- package/dist/icons/generated/lucide-circle-alert.js.map +1 -1
- package/dist/icons/generated/lucide-clapperboard.d.ts +5 -4
- package/dist/icons/generated/lucide-clapperboard.d.ts.map +1 -0
- package/dist/icons/generated/lucide-clapperboard.js +3 -4
- package/dist/icons/generated/lucide-clapperboard.js.map +1 -1
- package/dist/icons/generated/lucide-clipboard-paste.d.ts +5 -4
- package/dist/icons/generated/lucide-clipboard-paste.d.ts.map +1 -0
- package/dist/icons/generated/lucide-clipboard-paste.js +3 -4
- package/dist/icons/generated/lucide-clipboard-paste.js.map +1 -1
- package/dist/icons/generated/lucide-code.d.ts +5 -4
- package/dist/icons/generated/lucide-code.d.ts.map +1 -0
- package/dist/icons/generated/lucide-code.js +3 -4
- package/dist/icons/generated/lucide-code.js.map +1 -1
- package/dist/icons/generated/lucide-copy.d.ts +5 -4
- package/dist/icons/generated/lucide-copy.d.ts.map +1 -0
- package/dist/icons/generated/lucide-copy.js +3 -4
- package/dist/icons/generated/lucide-copy.js.map +1 -1
- package/dist/icons/generated/lucide-download.d.ts +5 -4
- package/dist/icons/generated/lucide-download.d.ts.map +1 -0
- package/dist/icons/generated/lucide-download.js +3 -4
- package/dist/icons/generated/lucide-download.js.map +1 -1
- package/dist/icons/generated/lucide-ellipsis-vertical.d.ts +5 -4
- package/dist/icons/generated/lucide-ellipsis-vertical.d.ts.map +1 -0
- package/dist/icons/generated/lucide-ellipsis-vertical.js +3 -4
- package/dist/icons/generated/lucide-ellipsis-vertical.js.map +1 -1
- package/dist/icons/generated/lucide-external-link.d.ts +5 -4
- package/dist/icons/generated/lucide-external-link.d.ts.map +1 -0
- package/dist/icons/generated/lucide-external-link.js +3 -4
- package/dist/icons/generated/lucide-external-link.js.map +1 -1
- package/dist/icons/generated/lucide-eye.d.ts +5 -4
- package/dist/icons/generated/lucide-eye.d.ts.map +1 -0
- package/dist/icons/generated/lucide-eye.js +3 -4
- package/dist/icons/generated/lucide-eye.js.map +1 -1
- package/dist/icons/generated/lucide-file-text.d.ts +5 -4
- package/dist/icons/generated/lucide-file-text.d.ts.map +1 -0
- package/dist/icons/generated/lucide-file-text.js +3 -4
- package/dist/icons/generated/lucide-file-text.js.map +1 -1
- package/dist/icons/generated/lucide-file.d.ts +5 -4
- package/dist/icons/generated/lucide-file.d.ts.map +1 -0
- package/dist/icons/generated/lucide-file.js +3 -4
- package/dist/icons/generated/lucide-file.js.map +1 -1
- package/dist/icons/generated/lucide-film.d.ts +5 -4
- package/dist/icons/generated/lucide-film.d.ts.map +1 -0
- package/dist/icons/generated/lucide-film.js +3 -4
- package/dist/icons/generated/lucide-film.js.map +1 -1
- package/dist/icons/generated/lucide-folder-open.d.ts +5 -4
- package/dist/icons/generated/lucide-folder-open.d.ts.map +1 -0
- package/dist/icons/generated/lucide-folder-open.js +3 -4
- package/dist/icons/generated/lucide-folder-open.js.map +1 -1
- package/dist/icons/generated/lucide-folder.d.ts +5 -4
- package/dist/icons/generated/lucide-folder.d.ts.map +1 -0
- package/dist/icons/generated/lucide-folder.js +3 -4
- package/dist/icons/generated/lucide-folder.js.map +1 -1
- package/dist/icons/generated/lucide-globe.d.ts +5 -4
- package/dist/icons/generated/lucide-globe.d.ts.map +1 -0
- package/dist/icons/generated/lucide-globe.js +3 -4
- package/dist/icons/generated/lucide-globe.js.map +1 -1
- package/dist/icons/generated/lucide-headphones.d.ts +5 -4
- package/dist/icons/generated/lucide-headphones.d.ts.map +1 -0
- package/dist/icons/generated/lucide-headphones.js +3 -4
- package/dist/icons/generated/lucide-headphones.js.map +1 -1
- package/dist/icons/generated/lucide-heart.d.ts +5 -4
- package/dist/icons/generated/lucide-heart.d.ts.map +1 -0
- package/dist/icons/generated/lucide-heart.js +3 -4
- package/dist/icons/generated/lucide-heart.js.map +1 -1
- package/dist/icons/generated/lucide-image.d.ts +5 -4
- package/dist/icons/generated/lucide-image.d.ts.map +1 -0
- package/dist/icons/generated/lucide-image.js +3 -4
- package/dist/icons/generated/lucide-image.js.map +1 -1
- package/dist/icons/generated/lucide-inbox.d.ts +5 -4
- package/dist/icons/generated/lucide-inbox.d.ts.map +1 -0
- package/dist/icons/generated/lucide-inbox.js +3 -4
- package/dist/icons/generated/lucide-inbox.js.map +1 -1
- package/dist/icons/generated/lucide-info.d.ts +5 -4
- package/dist/icons/generated/lucide-info.d.ts.map +1 -0
- package/dist/icons/generated/lucide-info.js +3 -4
- package/dist/icons/generated/lucide-info.js.map +1 -1
- package/dist/icons/generated/lucide-layout-grid.d.ts +5 -4
- package/dist/icons/generated/lucide-layout-grid.d.ts.map +1 -0
- package/dist/icons/generated/lucide-layout-grid.js +3 -4
- package/dist/icons/generated/lucide-layout-grid.js.map +1 -1
- package/dist/icons/generated/lucide-link.d.ts +5 -4
- package/dist/icons/generated/lucide-link.d.ts.map +1 -0
- package/dist/icons/generated/lucide-link.js +3 -4
- package/dist/icons/generated/lucide-link.js.map +1 -1
- package/dist/icons/generated/lucide-list-filter.d.ts +5 -4
- package/dist/icons/generated/lucide-list-filter.d.ts.map +1 -0
- package/dist/icons/generated/lucide-list-filter.js +3 -4
- package/dist/icons/generated/lucide-list-filter.js.map +1 -1
- package/dist/icons/generated/lucide-list-restart.d.ts +5 -4
- package/dist/icons/generated/lucide-list-restart.d.ts.map +1 -0
- package/dist/icons/generated/lucide-list-restart.js +3 -4
- package/dist/icons/generated/lucide-list-restart.js.map +1 -1
- package/dist/icons/generated/lucide-loader-circle.d.ts +5 -4
- package/dist/icons/generated/lucide-loader-circle.d.ts.map +1 -0
- package/dist/icons/generated/lucide-loader-circle.js +3 -4
- package/dist/icons/generated/lucide-loader-circle.js.map +1 -1
- package/dist/icons/generated/lucide-mail.d.ts +5 -4
- package/dist/icons/generated/lucide-mail.d.ts.map +1 -0
- package/dist/icons/generated/lucide-mail.js +3 -4
- package/dist/icons/generated/lucide-mail.js.map +1 -1
- package/dist/icons/generated/lucide-minus.d.ts +5 -4
- package/dist/icons/generated/lucide-minus.d.ts.map +1 -0
- package/dist/icons/generated/lucide-minus.js +3 -4
- package/dist/icons/generated/lucide-minus.js.map +1 -1
- package/dist/icons/generated/lucide-music.d.ts +5 -4
- package/dist/icons/generated/lucide-music.d.ts.map +1 -0
- package/dist/icons/generated/lucide-music.js +3 -4
- package/dist/icons/generated/lucide-music.js.map +1 -1
- package/dist/icons/generated/lucide-package.d.ts +5 -4
- package/dist/icons/generated/lucide-package.d.ts.map +1 -0
- package/dist/icons/generated/lucide-package.js +3 -4
- package/dist/icons/generated/lucide-package.js.map +1 -1
- package/dist/icons/generated/lucide-pen-line.d.ts +5 -4
- package/dist/icons/generated/lucide-pen-line.d.ts.map +1 -0
- package/dist/icons/generated/lucide-pen-line.js +3 -4
- package/dist/icons/generated/lucide-pen-line.js.map +1 -1
- package/dist/icons/generated/lucide-pencil.d.ts +5 -4
- package/dist/icons/generated/lucide-pencil.d.ts.map +1 -0
- package/dist/icons/generated/lucide-pencil.js +3 -4
- package/dist/icons/generated/lucide-pencil.js.map +1 -1
- package/dist/icons/generated/lucide-play.d.ts +5 -4
- package/dist/icons/generated/lucide-play.d.ts.map +1 -0
- package/dist/icons/generated/lucide-play.js +3 -4
- package/dist/icons/generated/lucide-play.js.map +1 -1
- package/dist/icons/generated/lucide-plus.d.ts +5 -4
- package/dist/icons/generated/lucide-plus.d.ts.map +1 -0
- package/dist/icons/generated/lucide-plus.js +3 -4
- package/dist/icons/generated/lucide-plus.js.map +1 -1
- package/dist/icons/generated/lucide-printer.d.ts +5 -4
- package/dist/icons/generated/lucide-printer.d.ts.map +1 -0
- package/dist/icons/generated/lucide-printer.js +3 -4
- package/dist/icons/generated/lucide-printer.js.map +1 -1
- package/dist/icons/generated/lucide-redo-2.d.ts +5 -4
- package/dist/icons/generated/lucide-redo-2.d.ts.map +1 -0
- package/dist/icons/generated/lucide-redo-2.js +3 -4
- package/dist/icons/generated/lucide-redo-2.js.map +1 -1
- package/dist/icons/generated/lucide-refresh-cw.d.ts +5 -4
- package/dist/icons/generated/lucide-refresh-cw.d.ts.map +1 -0
- package/dist/icons/generated/lucide-refresh-cw.js +3 -4
- package/dist/icons/generated/lucide-refresh-cw.js.map +1 -1
- package/dist/icons/generated/lucide-scissors.d.ts +5 -4
- package/dist/icons/generated/lucide-scissors.d.ts.map +1 -0
- package/dist/icons/generated/lucide-scissors.js +3 -4
- package/dist/icons/generated/lucide-scissors.js.map +1 -1
- package/dist/icons/generated/lucide-search.d.ts +5 -4
- package/dist/icons/generated/lucide-search.d.ts.map +1 -0
- package/dist/icons/generated/lucide-search.js +3 -4
- package/dist/icons/generated/lucide-search.js.map +1 -1
- package/dist/icons/generated/lucide-settings.d.ts +5 -4
- package/dist/icons/generated/lucide-settings.d.ts.map +1 -0
- package/dist/icons/generated/lucide-settings.js +3 -4
- package/dist/icons/generated/lucide-settings.js.map +1 -1
- package/dist/icons/generated/lucide-sliders-horizontal.d.ts +5 -4
- package/dist/icons/generated/lucide-sliders-horizontal.d.ts.map +1 -0
- package/dist/icons/generated/lucide-sliders-horizontal.js +3 -4
- package/dist/icons/generated/lucide-sliders-horizontal.js.map +1 -1
- package/dist/icons/generated/lucide-star.d.ts +5 -4
- package/dist/icons/generated/lucide-star.d.ts.map +1 -0
- package/dist/icons/generated/lucide-star.js +3 -4
- package/dist/icons/generated/lucide-star.js.map +1 -1
- package/dist/icons/generated/lucide-tag.d.ts +5 -4
- package/dist/icons/generated/lucide-tag.d.ts.map +1 -0
- package/dist/icons/generated/lucide-tag.js +3 -4
- package/dist/icons/generated/lucide-tag.js.map +1 -1
- package/dist/icons/generated/lucide-tags.d.ts +5 -4
- package/dist/icons/generated/lucide-tags.d.ts.map +1 -0
- package/dist/icons/generated/lucide-tags.js +3 -4
- package/dist/icons/generated/lucide-tags.js.map +1 -1
- package/dist/icons/generated/lucide-trash-2.d.ts +5 -4
- package/dist/icons/generated/lucide-trash-2.d.ts.map +1 -0
- package/dist/icons/generated/lucide-trash-2.js +3 -4
- package/dist/icons/generated/lucide-trash-2.js.map +1 -1
- package/dist/icons/generated/lucide-triangle-alert.d.ts +5 -4
- package/dist/icons/generated/lucide-triangle-alert.d.ts.map +1 -0
- package/dist/icons/generated/lucide-triangle-alert.js +3 -4
- package/dist/icons/generated/lucide-triangle-alert.js.map +1 -1
- package/dist/icons/generated/lucide-undo-2.d.ts +5 -4
- package/dist/icons/generated/lucide-undo-2.d.ts.map +1 -0
- package/dist/icons/generated/lucide-undo-2.js +3 -4
- package/dist/icons/generated/lucide-undo-2.js.map +1 -1
- package/dist/icons/generated/lucide-upload.d.ts +5 -4
- package/dist/icons/generated/lucide-upload.d.ts.map +1 -0
- package/dist/icons/generated/lucide-upload.js +3 -4
- package/dist/icons/generated/lucide-upload.js.map +1 -1
- package/dist/icons/generated/lucide-user.d.ts +5 -4
- package/dist/icons/generated/lucide-user.d.ts.map +1 -0
- package/dist/icons/generated/lucide-user.js +3 -4
- package/dist/icons/generated/lucide-user.js.map +1 -1
- package/dist/icons/generated/lucide-wrench.d.ts +5 -4
- package/dist/icons/generated/lucide-wrench.d.ts.map +1 -0
- package/dist/icons/generated/lucide-wrench.js +3 -4
- package/dist/icons/generated/lucide-wrench.js.map +1 -1
- package/dist/icons/generated/lucide-x.d.ts +5 -4
- package/dist/icons/generated/lucide-x.d.ts.map +1 -0
- package/dist/icons/generated/lucide-x.js +3 -4
- package/dist/icons/generated/lucide-x.js.map +1 -1
- package/dist/icons/generated/mdi-tag-search-outline.d.ts +5 -4
- package/dist/icons/generated/mdi-tag-search-outline.d.ts.map +1 -0
- package/dist/icons/generated/mdi-tag-search-outline.js +3 -4
- package/dist/icons/generated/mdi-tag-search-outline.js.map +1 -1
- package/dist/icons/generated/ooui-close.d.ts +5 -4
- package/dist/icons/generated/ooui-close.d.ts.map +1 -0
- package/dist/icons/generated/ooui-close.js +3 -4
- package/dist/icons/generated/ooui-close.js.map +1 -1
- package/dist/icons/generated/radix-icons-panel-left-minimized.d.ts +5 -4
- package/dist/icons/generated/radix-icons-panel-left-minimized.d.ts.map +1 -0
- package/dist/icons/generated/radix-icons-panel-left-minimized.js +3 -4
- package/dist/icons/generated/radix-icons-panel-left-minimized.js.map +1 -1
- package/dist/icons/generated/radix-icons-reset.d.ts +5 -4
- package/dist/icons/generated/radix-icons-reset.d.ts.map +1 -0
- package/dist/icons/generated/radix-icons-reset.js +3 -4
- package/dist/icons/generated/radix-icons-reset.js.map +1 -1
- package/dist/icons/generated/tabler-sort-ascending-letters.d.ts +5 -4
- package/dist/icons/generated/tabler-sort-ascending-letters.d.ts.map +1 -0
- package/dist/icons/generated/tabler-sort-ascending-letters.js +3 -4
- package/dist/icons/generated/tabler-sort-ascending-letters.js.map +1 -1
- package/dist/icons/index.d.ts +75 -73
- package/dist/icons/index.js +75 -74
- package/dist/shared/element-height/index.js +51 -25
- package/dist/shared/element-height/index.js.map +1 -1
- package/dist/shared/element-width/index.js +39 -24
- package/dist/shared/element-width/index.js.map +1 -1
- package/dist/shared/events/user-change.js +14 -8
- package/dist/shared/events/user-change.js.map +1 -1
- package/dist/shared/focus/pointer-focus.js +56 -30
- package/dist/shared/focus/pointer-focus.js.map +1 -1
- package/dist/shared/focus/tabbable.js +96 -0
- package/dist/shared/focus/tabbable.js.map +1 -0
- package/dist/shared/form-association/field-id.js +13 -6
- package/dist/shared/form-association/field-id.js.map +1 -1
- package/dist/shared/form-association/index.js +75 -42
- package/dist/shared/form-association/index.js.map +1 -1
- package/dist/shared/gesture/drag-gesture.js +239 -99
- package/dist/shared/gesture/drag-gesture.js.map +1 -1
- package/dist/shared/gesture/physics.js +49 -16
- package/dist/shared/gesture/physics.js.map +1 -1
- package/dist/shared/gesture/pinch-gesture.js +111 -60
- package/dist/shared/gesture/pinch-gesture.js.map +1 -1
- package/dist/shared/group-management/index.js +181 -84
- package/dist/shared/group-management/index.js.map +1 -1
- package/dist/shared/label-emptiness/index.js +45 -26
- package/dist/shared/label-emptiness/index.js.map +1 -1
- package/dist/shared/locale/builtin-labels.js +38 -0
- package/dist/shared/locale/builtin-labels.js.map +1 -0
- package/dist/shared/menu-behavior/index.js +113 -60
- package/dist/shared/menu-behavior/index.js.map +1 -1
- package/dist/shared/menu-portal/menu-portal.js +47 -26
- package/dist/shared/menu-portal/menu-portal.js.map +1 -1
- package/dist/shared/menu-portal/menu-tree.js +132 -75
- package/dist/shared/menu-portal/menu-tree.js.map +1 -1
- package/dist/shared/normalize/index.js +16 -7
- package/dist/shared/normalize/index.js.map +1 -1
- package/dist/shared/open-state/index.js +7 -8
- package/dist/shared/open-state/index.js.map +1 -1
- package/dist/shared/option-portal/combobox-shell.js +121 -56
- package/dist/shared/option-portal/combobox-shell.js.map +1 -1
- package/dist/shared/option-portal/index.js +65 -44
- package/dist/shared/option-portal/index.js.map +1 -1
- package/dist/shared/overlay/anchored-panel.js +75 -40
- package/dist/shared/overlay/anchored-panel.js.map +1 -1
- package/dist/shared/overlay/native-dialog-presence.js +116 -52
- package/dist/shared/overlay/native-dialog-presence.js.map +1 -1
- package/dist/shared/overlay/nested-drawer-layers.js +76 -46
- package/dist/shared/overlay/nested-drawer-layers.js.map +1 -1
- package/dist/shared/overlay/open-overlay.js +240 -136
- package/dist/shared/overlay/open-overlay.js.map +1 -1
- package/dist/shared/overlay/overlay-root.js +33 -24
- package/dist/shared/overlay/overlay-root.js.map +1 -1
- package/dist/shared/overlay/overlay.js +109 -66
- package/dist/shared/overlay/overlay.js.map +1 -1
- package/dist/shared/overlay/placement-props.js +9 -4
- package/dist/shared/overlay/placement-props.js.map +1 -1
- package/dist/shared/overlay/portal.d.ts +2 -0
- package/dist/shared/overlay/portal.d.ts.map +1 -0
- package/dist/shared/overlay/portal.js +202 -117
- package/dist/shared/overlay/portal.js.map +1 -1
- package/dist/shared/overlay/positioning-generation.js +9 -10
- package/dist/shared/overlay/positioning-generation.js.map +1 -1
- package/dist/shared/overlay/presence.js +43 -21
- package/dist/shared/overlay/presence.js.map +1 -1
- package/dist/shared/overlay/theme-overlay-scope.js +22 -19
- package/dist/shared/overlay/theme-overlay-scope.js.map +1 -1
- package/dist/shared/scroll-lock/scroll-lock.js +49 -15
- package/dist/shared/scroll-lock/scroll-lock.js.map +1 -1
- package/dist/shared/theme/duration.js +13 -6
- package/dist/shared/theme/duration.js.map +1 -1
- package/dist/shared/theme/reduced-motion.js +14 -9
- package/dist/shared/theme/reduced-motion.js.map +1 -1
- package/dist/shared/theme/root-sync.js +85 -32
- package/dist/shared/theme/root-sync.js.map +1 -1
- package/dist/shared/visible-area/index.js +81 -37
- package/dist/shared/visible-area/index.js.map +1 -1
- package/dist/types/iconify.d.ts +1 -1
- package/dist/types/iconify.js +0 -0
- package/dist/types/react.d.ts +8 -10
- package/dist/types/react.d.ts.map +1 -0
- package/dist/types/react.js +0 -0
- package/dist/types/utils.d.ts +8 -13
- package/dist/types/utils.d.ts.map +1 -0
- package/dist/types/utils.js +0 -0
- package/dist/types/vue.d.ts +9 -13
- package/dist/types/vue.d.ts.map +1 -0
- package/dist/types/vue.js +0 -0
- package/dist/vite/index.d.ts +1 -0
- package/dist/vite/index.d.ts.map +1 -0
- package/dist/vite/index.js +30 -4
- package/dist/vite/index.js.map +1 -1
- package/package.json +11 -23
- package/dist/_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js +0 -9
- package/dist/components/middle-ellipsis/truncate.d.ts +0 -62
- package/dist/components/radio/interaction.d.ts +0 -4
- package/dist/scrollbars/index.d.ts +0 -33
- package/dist/scrollbars/index.js +0 -18
- package/dist/scrollbars/index.js.map +0 -1
- package/dist/scrollbars/internal.js +0 -6
- package/dist/scrollbars/internal.js.map +0 -1
- package/dist/scrollbars/style.css +0 -10
|
@@ -1,198 +1,302 @@
|
|
|
1
|
-
import { definePlugin
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { definePlugin } from "@greypan/js-kit";
|
|
2
|
+
// src/shared/overlay/open-overlay.ts
|
|
3
|
+
/**
|
|
4
|
+
* 开启态 overlay(open overlay)——「哪一层正开着」的唯一拥有者。
|
|
5
|
+
*
|
|
6
|
+
* 本模块合并三块职责:composition(逻辑父子树)、escape-dismiss(最内层仲裁)、
|
|
7
|
+
* lifecycle(帧事务失效)。合并的判据不是三者职责相邻,而是它们共享同一条不变量:
|
|
8
|
+
* **已登记 ⟺ 在场 ⟺ 有仲裁身份**。
|
|
9
|
+
*
|
|
10
|
+
* 这条不变量需要唯一的仲裁者:让 8 个 overlay 组件各自把它拼成三步协议
|
|
11
|
+
* (`registerPanelFromAncestry` + `setPanel` / `unregisterPanel` + `setPanel(null)`),
|
|
12
|
+
* 「漏撤销」与「重挂载后与仲裁失联」就只能靠每个组件自己记得,而
|
|
13
|
+
* `lifecycle` 还要调用方手工传一个 `expectedOpen` 来复述「我开着吗」。
|
|
14
|
+
*
|
|
15
|
+
* 本模块的取舍:
|
|
16
|
+
*
|
|
17
|
+
* - 身份是**handle**而非 panel 元素:`release()` 不需要调用方回忆当初传了哪个 panel。
|
|
18
|
+
* - 开启状态是**声明**而非询问:仲裁时不再回调宿主问 `isOpen()`,宿主只提供
|
|
19
|
+
* `requestClose()` 与一个仅供惰性回收读取的 `isConnected()`;模块持有的真相即真相。
|
|
20
|
+
* - `claim` 即「我开着」:一次 claim 对应一次开启,登记与仲裁是同一个动作。
|
|
21
|
+
* - 在场分两态:开启中(Escape 走关闭入口)与退场中(panel 仍可见,暂缓仲裁、只作兜底
|
|
22
|
+
* 候选)。后者由 `deferArbitration()` 进入、随 `release()`、重新 claim 或显式
|
|
23
|
+
* `deferArbitration(false)` 离开:于是「退场被打断」与「宿主仍认为开着」不再把看得见
|
|
24
|
+
* 的 panel 留在未登记状态,而退场已播完、宿主却仍认为开着的那一格,也不会让一个看不
|
|
25
|
+
* 见的 panel 无限吞掉 Escape。
|
|
26
|
+
* - 查询走 handle(`contains` / `containsEvent` / `hasFocusWithin`),调用方不再需要
|
|
27
|
+
* 持有 panel 引用,也不知道存在全局注册表。
|
|
28
|
+
* - 实例作用域与会话作用域分开:帧事务的 lifetime 比一次开合长(tooltip 跨断连
|
|
29
|
+
* `resume()`),把它压进会话 handle 会在 `release()` 时误杀事务。
|
|
30
|
+
*
|
|
31
|
+
* 刻意**不**吸收 presence、滚动锁与 drawer 的层序(nested layers):它们回答的是
|
|
32
|
+
* 视觉问题(`is-visible`、层序缩放),与「谁是最内层」正交,硬合并会互相污染。
|
|
33
|
+
*/
|
|
34
|
+
const layers = /* @__PURE__ */ new Set();
|
|
35
|
+
const layerByPanel = /* @__PURE__ */ new WeakMap();
|
|
36
|
+
const layerByHandle = /* @__PURE__ */ new WeakMap();
|
|
37
|
+
const parents = /* @__PURE__ */ new WeakMap();
|
|
38
|
+
const childPanels = /* @__PURE__ */ new WeakMap();
|
|
39
|
+
let listening = false;
|
|
40
|
+
let sequence = 0;
|
|
41
|
+
if (import.meta.env.DEV) globalThis.__openOverlayLayerCount = () => layers.size;
|
|
42
|
+
const inactiveHandle = {
|
|
4
43
|
deferArbitration() {},
|
|
5
44
|
setInert() {},
|
|
6
|
-
adopt: () =>
|
|
7
|
-
contains: () =>
|
|
8
|
-
containsEvent: () =>
|
|
9
|
-
hasFocusWithin: () =>
|
|
45
|
+
adopt: () => inactiveHandle,
|
|
46
|
+
contains: () => false,
|
|
47
|
+
containsEvent: () => false,
|
|
48
|
+
hasFocusWithin: () => false,
|
|
10
49
|
release() {}
|
|
11
50
|
};
|
|
12
|
-
function
|
|
13
|
-
|
|
51
|
+
function nextCompositionNode(node) {
|
|
52
|
+
if (node instanceof Element && node.assignedSlot) return node.assignedSlot;
|
|
53
|
+
if (node.parentNode) return node.parentNode;
|
|
54
|
+
if (node instanceof ShadowRoot) return node.host;
|
|
55
|
+
return null;
|
|
14
56
|
}
|
|
15
|
-
function
|
|
16
|
-
let
|
|
17
|
-
|
|
18
|
-
if (
|
|
19
|
-
|
|
57
|
+
function nodeIsInside(root, node) {
|
|
58
|
+
let current = node;
|
|
59
|
+
while (current) {
|
|
60
|
+
if (current === root || root.contains(current)) return true;
|
|
61
|
+
current = nextCompositionNode(current);
|
|
20
62
|
}
|
|
21
|
-
return
|
|
63
|
+
return false;
|
|
22
64
|
}
|
|
23
|
-
function
|
|
24
|
-
|
|
25
|
-
if (!
|
|
26
|
-
|
|
27
|
-
|
|
65
|
+
function detachFromParent(panel) {
|
|
66
|
+
const parent = parents.get(panel);
|
|
67
|
+
if (!parent) return;
|
|
68
|
+
const siblings = childPanels.get(parent);
|
|
69
|
+
siblings?.delete(panel);
|
|
70
|
+
if (siblings?.size === 0) childPanels.delete(parent);
|
|
71
|
+
parents.delete(panel);
|
|
28
72
|
}
|
|
29
|
-
function
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
73
|
+
function attachToParent(panel, parent) {
|
|
74
|
+
detachFromParent(panel);
|
|
75
|
+
if (!parent || parent === panel) return;
|
|
76
|
+
const siblings = childPanels.get(parent) ?? /* @__PURE__ */ new Set();
|
|
77
|
+
siblings.add(panel);
|
|
78
|
+
childPanels.set(parent, siblings);
|
|
79
|
+
parents.set(panel, parent);
|
|
33
80
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return
|
|
81
|
+
/** panel 自身或其任何已登记子层是否包含 target。 */
|
|
82
|
+
function containsPanel(panel, target) {
|
|
83
|
+
if (nodeIsInside(panel, target)) return true;
|
|
84
|
+
for (const child of childPanels.get(panel) ?? []) if (containsPanel(child, target)) return true;
|
|
85
|
+
return false;
|
|
38
86
|
}
|
|
39
|
-
function
|
|
40
|
-
if (
|
|
41
|
-
for (
|
|
42
|
-
return
|
|
87
|
+
function hasFocusWithinPanel(panel) {
|
|
88
|
+
if (panel.matches(":focus-within")) return true;
|
|
89
|
+
for (const child of childPanels.get(panel) ?? []) if (hasFocusWithinPanel(child)) return true;
|
|
90
|
+
return false;
|
|
43
91
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
92
|
+
/** 从 from 沿祖先链找最近的已开启 overlay panel;panel 自身永远不算自己的父级。 */
|
|
93
|
+
function findOpenAncestor(panel, from) {
|
|
94
|
+
let current = from === panel ? nextCompositionNode(from) : from;
|
|
95
|
+
while (current) {
|
|
96
|
+
if (current instanceof HTMLElement && current !== panel) {
|
|
97
|
+
const candidate = layerByPanel.get(current);
|
|
98
|
+
if (candidate && !candidate.released) return current;
|
|
50
99
|
}
|
|
51
|
-
|
|
100
|
+
current = nextCompositionNode(current);
|
|
52
101
|
}
|
|
53
102
|
return null;
|
|
54
103
|
}
|
|
55
|
-
function
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
t.delete(e), n.delete(e.panel), a.delete(e.panel), d(e.panel);
|
|
104
|
+
function releaseLayer(layer) {
|
|
105
|
+
if (layer.released) return;
|
|
106
|
+
layer.released = true;
|
|
107
|
+
for (const child of Array.from(childPanels.get(layer.panel) ?? [])) {
|
|
108
|
+
const childLayer = layerByPanel.get(child);
|
|
109
|
+
if (childLayer) releaseLayer(childLayer);
|
|
110
|
+
else detachFromParent(child);
|
|
63
111
|
}
|
|
112
|
+
layers.delete(layer);
|
|
113
|
+
layerByPanel.delete(layer.panel);
|
|
114
|
+
childPanels.delete(layer.panel);
|
|
115
|
+
detachFromParent(layer.panel);
|
|
64
116
|
}
|
|
65
|
-
function
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
panel:
|
|
71
|
-
host:
|
|
72
|
-
arbitration:
|
|
73
|
-
inert:
|
|
74
|
-
deferred:
|
|
75
|
-
seq: ++
|
|
76
|
-
released:
|
|
117
|
+
function createLayer(input) {
|
|
118
|
+
reclaimDisconnectedLayers();
|
|
119
|
+
const previous = layerByPanel.get(input.panel);
|
|
120
|
+
if (previous) releaseLayer(previous);
|
|
121
|
+
const layer = {
|
|
122
|
+
panel: input.panel,
|
|
123
|
+
host: input.host,
|
|
124
|
+
arbitration: input.arbitration,
|
|
125
|
+
inert: false,
|
|
126
|
+
deferred: false,
|
|
127
|
+
seq: ++sequence,
|
|
128
|
+
released: false
|
|
77
129
|
};
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
130
|
+
layers.add(layer);
|
|
131
|
+
layerByPanel.set(input.panel, layer);
|
|
132
|
+
attachToParent(input.panel, input.parent);
|
|
133
|
+
const handle = {
|
|
134
|
+
deferArbitration(deferred = true) {
|
|
135
|
+
if (layer.released) return;
|
|
136
|
+
layer.deferred = deferred;
|
|
82
137
|
},
|
|
83
|
-
setInert(
|
|
84
|
-
|
|
138
|
+
setInert(inert) {
|
|
139
|
+
if (layer.released) return;
|
|
140
|
+
layer.inert = inert;
|
|
85
141
|
},
|
|
86
|
-
adopt(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
142
|
+
adopt(panel, options = {}) {
|
|
143
|
+
if (layer.released) return inactiveHandle;
|
|
144
|
+
return createLayer({
|
|
145
|
+
panel,
|
|
146
|
+
host: layer.host,
|
|
147
|
+
arbitration: options.arbitration ?? "none",
|
|
148
|
+
parent: layer.panel
|
|
92
149
|
});
|
|
93
150
|
},
|
|
94
|
-
contains(
|
|
95
|
-
return !
|
|
151
|
+
contains(node) {
|
|
152
|
+
return !layer.released && containsPanel(layer.panel, node);
|
|
96
153
|
},
|
|
97
|
-
containsEvent(
|
|
98
|
-
return !
|
|
154
|
+
containsEvent(event) {
|
|
155
|
+
return !layer.released && event.composedPath().some((node) => node instanceof Node && containsPanel(layer.panel, node));
|
|
99
156
|
},
|
|
100
157
|
hasFocusWithin() {
|
|
101
|
-
return !
|
|
158
|
+
return !layer.released && hasFocusWithinPanel(layer.panel);
|
|
102
159
|
},
|
|
103
160
|
release() {
|
|
104
|
-
|
|
161
|
+
releaseLayer(layer);
|
|
162
|
+
syncListener();
|
|
105
163
|
}
|
|
106
164
|
};
|
|
107
|
-
|
|
165
|
+
layerByHandle.set(handle, layer);
|
|
166
|
+
syncListener(false);
|
|
167
|
+
return handle;
|
|
108
168
|
}
|
|
109
|
-
function
|
|
110
|
-
return !
|
|
169
|
+
function isCandidate(layer) {
|
|
170
|
+
return !layer.released && layer.arbitration !== "none" && layer.panel.isConnected;
|
|
111
171
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
172
|
+
/** 在候选里取最内层:子树包含关系下的极大元;互不包含时取后开的。 */
|
|
173
|
+
function pickInnermost(candidates) {
|
|
174
|
+
let best = null;
|
|
175
|
+
for (const layer of candidates) {
|
|
176
|
+
if (!best) {
|
|
177
|
+
best = layer;
|
|
117
178
|
continue;
|
|
118
179
|
}
|
|
119
|
-
if (
|
|
120
|
-
|
|
180
|
+
if (containsPanel(best.panel, layer.panel)) {
|
|
181
|
+
best = layer;
|
|
121
182
|
continue;
|
|
122
183
|
}
|
|
123
|
-
|
|
184
|
+
if (containsPanel(layer.panel, best.panel)) continue;
|
|
185
|
+
if (layer.seq > best.seq) best = layer;
|
|
124
186
|
}
|
|
125
|
-
return
|
|
187
|
+
return best;
|
|
126
188
|
}
|
|
127
|
-
function
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
189
|
+
function resolve() {
|
|
190
|
+
syncListener();
|
|
191
|
+
const live = [];
|
|
192
|
+
const deferred = [];
|
|
193
|
+
for (const layer of layers) {
|
|
194
|
+
if (!isCandidate(layer)) continue;
|
|
195
|
+
if (layer.deferred) deferred.push(layer);
|
|
196
|
+
else live.push(layer);
|
|
197
|
+
}
|
|
198
|
+
return pickInnermost(live) ?? pickInnermost(deferred);
|
|
132
199
|
}
|
|
133
|
-
function
|
|
134
|
-
if (
|
|
135
|
-
|
|
136
|
-
|
|
200
|
+
function handleKeydown(event) {
|
|
201
|
+
if (event.key !== "Escape") return;
|
|
202
|
+
if (event.defaultPrevented) return;
|
|
203
|
+
const layer = resolve();
|
|
204
|
+
if (!layer) return;
|
|
205
|
+
event.preventDefault();
|
|
206
|
+
event.stopPropagation();
|
|
207
|
+
if (layer.inert || layer.deferred) return;
|
|
208
|
+
layer.host.requestClose();
|
|
137
209
|
}
|
|
138
|
-
|
|
139
|
-
|
|
210
|
+
/**
|
|
211
|
+
* panel 与 host 同时失联的层是死层:显式 release 之外的兜底删除路径。
|
|
212
|
+
*
|
|
213
|
+
* 惰性体现在只在遍历登记表的入口跑(建层之前、仲裁、release),不挂 DOM 变动回调 ——
|
|
214
|
+
* panel 短暂移除再放回必须不丢登记。建层**之后**不跑:新层可能还没挂载,扫它就会误杀
|
|
215
|
+
* (见 `createLayer` 开头与 `layers` 注册表处的注释)。
|
|
216
|
+
*/
|
|
217
|
+
function reclaimDisconnectedLayers() {
|
|
218
|
+
for (const layer of Array.from(layers)) {
|
|
219
|
+
if (layer.released || layer.panel.isConnected || layer.host.isConnected()) continue;
|
|
220
|
+
releaseLayer(layer);
|
|
221
|
+
}
|
|
140
222
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
223
|
+
/**
|
|
224
|
+
* 监听器对账:惰性回收死层,再按登记表重算 document 监听。
|
|
225
|
+
*
|
|
226
|
+
* `reclaim` 关掉回收,只给 `createLayer` 建层之后那一次调用用:新层刚入注册表,调用方
|
|
227
|
+
* 可能还没把 panel 与宿主挂进文档,那一刻扫它等于把新层判成死层。死层不会因此漏掉——
|
|
228
|
+
* 回收在建层之前已经单独跑过一轮(见 `createLayer` 开头)。
|
|
229
|
+
*/
|
|
230
|
+
function syncListener(reclaim = true) {
|
|
231
|
+
if (reclaim) reclaimDisconnectedLayers();
|
|
232
|
+
let shouldListen = false;
|
|
233
|
+
for (const layer of layers) if (!layer.released && layer.arbitration !== "none") {
|
|
234
|
+
shouldListen = true;
|
|
146
235
|
break;
|
|
147
236
|
}
|
|
148
|
-
|
|
237
|
+
if (shouldListen === listening) return;
|
|
238
|
+
listening = shouldListen;
|
|
239
|
+
if (shouldListen) document.addEventListener("keydown", handleKeydown, true);
|
|
240
|
+
else document.removeEventListener("keydown", handleKeydown, true);
|
|
149
241
|
}
|
|
150
|
-
|
|
151
|
-
let
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
242
|
+
const defineOpenOverlay = () => definePlugin((host) => {
|
|
243
|
+
let generation = 0;
|
|
244
|
+
let suspended = false;
|
|
245
|
+
const frames = /* @__PURE__ */ new Set();
|
|
246
|
+
const cancelFrame = (frame) => {
|
|
247
|
+
cancelAnimationFrame(frame.id);
|
|
248
|
+
frames.delete(frame);
|
|
249
|
+
};
|
|
250
|
+
const cancelFrames = () => {
|
|
251
|
+
for (const frame of Array.from(frames)) cancelFrame(frame);
|
|
252
|
+
};
|
|
253
|
+
const invalidateCurrent = () => {
|
|
254
|
+
generation += 1;
|
|
255
|
+
cancelFrames();
|
|
155
256
|
};
|
|
156
257
|
return {
|
|
157
|
-
claim(
|
|
158
|
-
return
|
|
159
|
-
panel
|
|
160
|
-
host
|
|
161
|
-
arbitration:
|
|
162
|
-
parent:
|
|
258
|
+
claim(panel, options = {}) {
|
|
259
|
+
return createLayer({
|
|
260
|
+
panel,
|
|
261
|
+
host,
|
|
262
|
+
arbitration: options.arbitration ?? "escape",
|
|
263
|
+
parent: findOpenAncestor(panel, options.ancestryFrom ?? panel) ?? void 0
|
|
163
264
|
});
|
|
164
265
|
},
|
|
165
|
-
scheduleFrame(
|
|
166
|
-
if (
|
|
167
|
-
|
|
168
|
-
|
|
266
|
+
scheduleFrame(callback, whileLive) {
|
|
267
|
+
if (suspended) return { cancel() {} };
|
|
268
|
+
const scheduledGeneration = generation;
|
|
269
|
+
const frame = {
|
|
270
|
+
generation: scheduledGeneration,
|
|
169
271
|
id: requestAnimationFrame(() => {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
e();
|
|
272
|
+
frames.delete(frame);
|
|
273
|
+
if (suspended || scheduledGeneration !== generation) return;
|
|
274
|
+
if (whileLive) {
|
|
275
|
+
const liveLayer = layerByHandle.get(whileLive);
|
|
276
|
+
if (!liveLayer || liveLayer.released) return;
|
|
176
277
|
}
|
|
278
|
+
callback();
|
|
177
279
|
}),
|
|
178
280
|
cancel() {
|
|
179
|
-
|
|
281
|
+
cancelFrame(frame);
|
|
180
282
|
}
|
|
181
283
|
};
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
invalidate: () => {
|
|
185
|
-
t += 1, o();
|
|
284
|
+
frames.add(frame);
|
|
285
|
+
return frame;
|
|
186
286
|
},
|
|
287
|
+
invalidate: invalidateCurrent,
|
|
187
288
|
suspend() {
|
|
188
|
-
|
|
289
|
+
if (suspended) return;
|
|
290
|
+
suspended = true;
|
|
291
|
+
cancelFrames();
|
|
189
292
|
},
|
|
190
293
|
resume() {
|
|
191
|
-
|
|
294
|
+
if (!suspended) return;
|
|
295
|
+
suspended = false;
|
|
296
|
+
generation += 1;
|
|
192
297
|
}
|
|
193
298
|
};
|
|
194
299
|
});
|
|
195
|
-
|
|
196
|
-
export { w as defineOpenOverlay };
|
|
300
|
+
export { defineOpenOverlay };
|
|
197
301
|
|
|
198
302
|
//# sourceMappingURL=open-overlay.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"open-overlay.js","names":[],"sources":["../../../src/shared/overlay/open-overlay.ts"],"sourcesContent":["/**\n * 开启态 overlay(open overlay)——「哪一层正开着」的唯一拥有者。\n *\n * 合并原先三个各自问一遍「你现在开着吗」的模块:composition(逻辑父子树)、\n * escape-dismiss(最内层仲裁)、lifecycle(帧事务失效)。合并的判据不是三者文件相邻,\n * 而是它们共享同一条不变量:**已登记 ⟺ 在场 ⟺ 有仲裁身份**。\n *\n * 拆成三个模块时这条不变量没有主人,8 个 overlay 组件各自把它拼成三步协议\n * (`registerPanelFromAncestry` + `setPanel` / `unregisterPanel` + `setPanel(null)`)。\n * 结果是「漏撤销」与「重挂载后与仲裁失联」只能靠每个组件自己记得,而\n * `lifecycle` 还得让调用方手工传一个 `expectedOpen` 来复述「我开着吗」。\n *\n * 本模块的取舍:\n *\n * - 身份是**handle**而非 panel 元素:`release()` 不需要调用方回忆当初传了哪个 panel。\n * - 开启状态是**声明**而非询问:仲裁时不再回调宿主问 `isOpen()`,宿主只提供\n * `requestClose()` 与一个仅供惰性回收读取的 `isConnected()`;模块持有的真相即真相。\n * - `claim` 即「我开着」:一次 claim 对应一次开启,登记与仲裁是同一个动作。\n * - 在场分两态:开启中(Escape 走关闭入口)与退场中(panel 仍可见,暂缓仲裁、只作兜底\n * 候选)。后者由 `deferArbitration()` 进入、随 `release()`、重新 claim 或显式\n * `deferArbitration(false)` 离开:于是「退场被打断」与「宿主仍认为开着」不再把看得见\n * 的 panel 留在未登记状态,而退场已播完、宿主却仍认为开着的那一格,也不会让一个看不\n * 见的 panel 无限吞掉 Escape。\n * - 查询走 handle(`contains` / `containsEvent` / `hasFocusWithin`),调用方不再需要\n * 持有 panel 引用,也不知道存在全局注册表。\n * - 实例作用域与会话作用域分开:帧事务的 lifetime 比一次开合长(tooltip 跨断连\n * `resume()`),把它压进会话 handle 会在 `release()` 时误杀事务。\n *\n * 刻意**不**吸收 presence、滚动锁与 drawer 的层序(nested layers):它们回答的是\n * 视觉问题(`is-visible`、层序缩放),与「谁是最内层」正交,硬合并会互相污染。\n */\n\nimport { definePlugin } from '@greypan/js-kit'\n\n/**\n * 本层是否参与 Escape 仲裁。\n *\n * - `escape`:正常候选。命中即走宿主既有的用户关闭入口。\n * - `none`:只在逻辑组合树内,完全不参与仲裁,Escape 穿过它落到下层。用于 tooltip\n * —— 它今天就在树里(经 anchored panel 登记)但从不作为候选。\n *\n * 「暂时不可关闭」不在这里,而由 `setInert` 表达。静态与动态是同一件事的两面:\n * `no-escape-close` 这类策略看似静态,但它是**被观察的属性**,开启期间可被改写,\n * 所以同样要走动态通道(claim 后立即 `setInert(noEscapeClose)`)。把静态策略做成\n * 第三个枚举值只会产生一个没有真实调用方的成员。\n */\nexport type OverlayArbitration = 'escape' | 'none'\n\nexport interface OverlayClaimOptions {\n /** 默认 `escape`。 */\n arbitration?: OverlayArbitration\n /**\n * 沿该节点的祖先链寻找最近的已开启 overlay,作为本层的逻辑父级;缺省用 panel 自身。\n *\n * portal panel 与宿主物理分离,从 panel 自身向上走找不到组合父级,必须由调用方给出\n * 锚点(trigger)或宿主,才能把「谁在谁里面」判对。\n *\n * **顺序约束**:祖先链查找要求 panel 与 ancestryFrom 此刻都已就位(在 DOM 中)。\n * 本模块不做「等一帧再补登记」——那会让「已登记」与「已开启」短暂不等。\n */\n ancestryFrom?: Node\n}\n\nexport interface OverlayFrameHandle {\n cancel(): void\n}\n\n/** 会话作用域:一次开启对应一个 handle。 */\nexport interface OpenOverlayHandle {\n /**\n * 惰性:仍是候选(照旧 `preventDefault()` 压掉原生 `<dialog>` 的关闭请求),但不走\n * 关闭入口。这是「暂时不可关闭」的唯一通道,静态策略与瞬时状态都走这里。\n *\n * 不改变本层在树里的位置,也不改变 `seq` —— 因此不会影响并列 overlay 的裁决顺序。\n * `none` 层不受影响(它本就不是候选)。\n *\n * **与会话同 lifetime,新会话恒从 `false` 开始**:`claim` 建立的每一层都重置为\n * 非惰性。所以凡是「重新 claim」的路径(`anchored-panel.reconfigure`、同一 panel 重复\n * `open()`)之后,都必须按当前状态重推一次,否则惰性会被静默清掉。重推放在哪里取决于\n * 该组件在 reconfigure 后是否渲染:会渲染的(select / autocomplete 在 `updated()` 里\n * 同步)可以把紧随 claim 的那一行降级为备份,不会渲染的(popover)必须自己补。\n */\n setInert(inert: boolean): void\n /**\n * 进入退场暂缓态:panel 仍在场(可见),本层继续留在登记表里并吞掉 Escape,但不走\n * 关闭入口。`anchored-panel.close()` 在退场等待前调用它。\n *\n * 与 `setInert` 的分工:`inert` 是**调用方**对「暂时不可关闭」的声明,会随渲染被\n * 重推;本态由**生命周期**进入,调用方没有任何途径清掉它,只有 `release()` 与\n * 渲染重推它,只有 `release()`、「同一 panel 重新 claim」与下面那个 `false` 能让它\n * 消失。因此重新 claim 出来的新会话恒不暂缓,退场被打断后由新会话接管仲裁。\n *\n * 传 `false` 退出暂态。唯一的使用者是 `anchored-panel.close()`:退场已播完(panel\n * 已隐藏)而宿主仍认为开着时,把层交还仲裁——此刻 panel 并不在「可见但暂缓」的前提\n * 里,继续暂缓会让一个看不见的 panel 无限吞掉 Escape,用户再也没有按键路径把这个\n * 不一致的状态收敛掉。\n *\n * 暂缓层只是兜底候选:`resolve()` 里仍在开启的层永远优先。否则「内层关掉后立刻\n * 再按一次 Escape」会被退场动画吞掉,外层永远等不到自己那一次(issue #120)。\n */\n deferArbitration(deferred?: boolean): void\n /**\n * 把子层 panel 纳入本 handle 的子树(多级 submenu),默认不成为独立候选。\n *\n * 与 `claim` 的区别只在父级如何确定:`claim` 走祖先链,`adopt` 由调用方指名。\n *\n * 在已 `release()` 的 handle 上调用**不建层**、返回空操作 handle —— 否则会建出一个父层已死\n * 的孤层:它仍参与仲裁,却不在父层的子树里,除调用方手里那个 handle 外没有回收路径。\n */\n adopt(panel: HTMLElement, options?: OverlayClaimOptions): OpenOverlayHandle\n /** 本层子树(含已 adopt 的子层)是否包含 node。 */\n contains(node: Node): boolean\n /** event 的完整 composed path 是否落入本层子树。 */\n containsEvent(event: Event): boolean\n /** 焦点是否在本层子树内。 */\n hasFocusWithin(): boolean\n /** 幂等。撤销本层及其全部子层,退出仲裁。 */\n release(): void\n}\n\n/** 实例作用域:每个宿主组件一次,跨开合与断连存活。 */\nexport interface OpenOverlay {\n claim(panel: HTMLElement, options?: OverlayClaimOptions): OpenOverlayHandle\n /**\n * 帧事务调度。`whileLive` handle 一旦 release,回调自动作废 —— 取代原先由调用方\n * 手工传入 `expectedOpen` 的轮询(那个参数正是「模块还得回头问宿主」的证据)。\n */\n scheduleFrame(callback: () => void, whileLive?: OpenOverlayHandle): OverlayFrameHandle\n /** 结束当前事务:取消未执行的 frame,并让旧 generation 的回调失效。 */\n invalidate(): void\n /** 断连后停止调度(可 `resume()`);generation 继续单调递增,旧事务保持失效。 */\n suspend(): void\n resume(): void\n}\n\nexport interface OpenOverlayHost {\n /** 走宿主既有的用户关闭入口(内部负责 controlled 语义与 `open-change` 派发)。 */\n requestClose(): void\n /**\n * 宿主元素是否仍在文档中。只被惰性回收读取(见 `layers` 注册表处的注释),\n * 仲裁路径不回调它——读 DOM 连接状态不是回调宿主问「我开着吗」。\n */\n isConnected(): boolean\n}\n\ninterface Layer {\n panel: HTMLElement\n host: OpenOverlayHost\n arbitration: OverlayArbitration\n /** 动态惰性 toggle,与会话同 lifetime。 */\n inert: boolean\n /** 退场暂缓 switch:panel 仍在场,但只作兜底候选(见 `deferArbitration`)。 */\n deferred: boolean\n /** 登记序号:互不包含的并列 overlay 里,后开的更靠上。 */\n seq: number\n released: boolean\n}\n\n/*\n * 模块级注册表:单例 document 监听器需要一个全局视野,这正是「谁是最内层」不能被\n * 拆到各组件里的原因。\n *\n * `Layer` 强引用 panel 与 host,所以一条没被删掉的记录会让整个组件(含子树)无法回收。\n * 删除路径有两条:显式 `release()`,以及 `reclaimDisconnectedLayers()` 的惰性兜底\n * ——「宿主还在但组件被丢弃」这类漏 release 的路径,光靠 `isCandidate()` 筛掉不可达\n * 候选只会留下永久泄漏,还会让 `shouldListen` 恒为 true 把 document 监听留住。\n * 兜底判据取 panel 与 host **同时**失联:panel 可能被 portal 在容器间搬运,也可能只是\n * 短暂移除再放回(层对象比 DOM 连接活得久),只有两者都不在文档里才判定为死层。\n * 回收**不扫刚 claim 的新层**:调用方完全可能先 claim 再把 panel 与宿主挂进文档,\n * 那一刻两者都还没连上。所以 claim 路径的回收跑在建层之前(`createLayer` 开头),\n * 新层入表之后只做监听对账。\n * 读 DOM 连接状态不是回调宿主问「我开着吗」,不违反声明式的取舍。\n */\nconst layers = new Set<Layer>()\nconst layerByPanel = new WeakMap<HTMLElement, Layer>()\nconst layerByHandle = new WeakMap<OpenOverlayHandle, Layer>()\nconst parents = new WeakMap<HTMLElement, HTMLElement>()\nconst childPanels = new WeakMap<HTMLElement, Set<HTMLElement>>()\nlet listening = false\nlet sequence = 0\n\n/*\n * dev 期测试钩子:登记表尺寸。\n *\n * 「漏 release」是结构性风险,而 `layers` 的尺寸无法从公开 interface 观察——调用方\n * 只持有 handle,看不到全局注册表,测试于是只能靠 GC 语义推断。有了它,泄漏在测试里\n * 是一个可直接断言的数字。`import.meta.env.DEV` 是编译期常量,生产构建里整段消失。\n */\ndeclare global {\n // eslint-disable-next-line no-var\n var __openOverlayLayerCount: () => number\n}\n\nif (import.meta.env.DEV) {\n globalThis.__openOverlayLayerCount = () => layers.size\n}\n\n/*\n * 已失效 handle 的空操作替身,用于 `adopt` 在 released handle 上的返回值。其余 handle 方法在\n * released 时都静默降级,返回值也必须一起降级,否则调用方会以为自己拿到了一棵可用子树。\n */\nconst inactiveHandle: OpenOverlayHandle = {\n deferArbitration() {},\n setInert() {},\n adopt: () => inactiveHandle,\n contains: () => false,\n containsEvent: () => false,\n hasFocusWithin: () => false,\n release() {}\n}\n\nfunction nextCompositionNode(node: Node): Node | null {\n if (node instanceof Element && node.assignedSlot) return node.assignedSlot\n if (node.parentNode) return node.parentNode\n if (node instanceof ShadowRoot) return node.host\n return null\n}\n\nfunction nodeIsInside(root: HTMLElement, node: Node): boolean {\n let current: Node | null = node\n while (current) {\n if (current === root || root.contains(current)) return true\n current = nextCompositionNode(current)\n }\n return false\n}\n\nfunction detachFromParent(panel: HTMLElement): void {\n const parent = parents.get(panel)\n if (!parent) return\n const siblings = childPanels.get(parent)\n siblings?.delete(panel)\n if (siblings?.size === 0) childPanels.delete(parent)\n parents.delete(panel)\n}\n\nfunction attachToParent(panel: HTMLElement, parent: HTMLElement | undefined): void {\n detachFromParent(panel)\n if (!parent || parent === panel) return\n const siblings = childPanels.get(parent) ?? new Set<HTMLElement>()\n siblings.add(panel)\n childPanels.set(parent, siblings)\n parents.set(panel, parent)\n}\n\n/** panel 自身或其任何已登记子层是否包含 target。 */\nfunction containsPanel(panel: HTMLElement, target: Node): boolean {\n if (nodeIsInside(panel, target)) return true\n for (const child of childPanels.get(panel) ?? []) {\n if (containsPanel(child, target)) return true\n }\n return false\n}\n\nfunction hasFocusWithinPanel(panel: HTMLElement): boolean {\n if (panel.matches(':focus-within')) return true\n for (const child of childPanels.get(panel) ?? []) {\n if (hasFocusWithinPanel(child)) return true\n }\n return false\n}\n\n/** 从 from 沿祖先链找最近的已开启 overlay panel;panel 自身永远不算自己的父级。 */\nfunction findOpenAncestor(panel: HTMLElement, from: Node): HTMLElement | null {\n let current: Node | null = from === panel ? nextCompositionNode(from) : from\n while (current) {\n if (current instanceof HTMLElement && current !== panel) {\n const candidate = layerByPanel.get(current)\n if (candidate && !candidate.released) return current\n }\n current = nextCompositionNode(current)\n }\n return null\n}\n\nfunction releaseLayer(layer: Layer): void {\n if (layer.released) return\n layer.released = true\n for (const child of Array.from(childPanels.get(layer.panel) ?? [])) {\n const childLayer = layerByPanel.get(child)\n if (childLayer) releaseLayer(childLayer)\n else detachFromParent(child)\n }\n layers.delete(layer)\n layerByPanel.delete(layer.panel)\n childPanels.delete(layer.panel)\n detachFromParent(layer.panel)\n // 不在这里 syncListener:本函数被子层递归与兜底回收复用,监听器对账由调用方在\n // 整棵子树摘完后做一次即可。\n}\n\nfunction createLayer(input: {\n panel: HTMLElement\n host: OpenOverlayHost\n arbitration: OverlayArbitration\n parent?: HTMLElement\n}): OpenOverlayHandle {\n /*\n * 先摘死层,再建新层。claim/adopt 是完全合法的「先开启后挂载」时序——调用方那一刻\n * 可能还没把 panel 与宿主挂进文档,两者都失联。回收跑在新层入表**之前**,新层就不\n * 会被自己的 claim 判成死层;而漏 release 留下的死层依旧在这里被扫掉,与旧实现一致。\n */\n reclaimDisconnectedLayers()\n\n const previous = layerByPanel.get(input.panel)\n // 同一 panel 重新 claim = 新的一次开启:旧会话(含其子层)整体作废,seq 重新分配。\n if (previous) releaseLayer(previous)\n\n const layer: Layer = {\n panel: input.panel,\n host: input.host,\n arbitration: input.arbitration,\n inert: false,\n deferred: false,\n seq: ++sequence,\n released: false\n }\n layers.add(layer)\n layerByPanel.set(input.panel, layer)\n attachToParent(input.panel, input.parent)\n\n const handle: OpenOverlayHandle = {\n deferArbitration(deferred = true) {\n if (layer.released) return\n layer.deferred = deferred\n },\n\n setInert(inert) {\n if (layer.released) return\n layer.inert = inert\n },\n\n adopt(panel, options = {}) {\n if (layer.released) return inactiveHandle\n return createLayer({\n panel,\n host: layer.host,\n arbitration: options.arbitration ?? 'none',\n parent: layer.panel\n })\n },\n\n contains(node) {\n return !layer.released && containsPanel(layer.panel, node)\n },\n\n containsEvent(event) {\n return (\n !layer.released && event.composedPath().some(node => node instanceof Node && containsPanel(layer.panel, node))\n )\n },\n\n hasFocusWithin() {\n return !layer.released && hasFocusWithinPanel(layer.panel)\n },\n\n release() {\n releaseLayer(layer)\n syncListener()\n }\n }\n\n layerByHandle.set(handle, layer)\n // 不带回收:新层 panel 与宿主可能还没挂载,回收已在函数开头跑过(见 `reclaim` 参数)。\n syncListener(false)\n return handle\n}\n\nfunction isCandidate(layer: Layer): boolean {\n return !layer.released && layer.arbitration !== 'none' && layer.panel.isConnected\n}\n\n/** 在候选里取最内层:子树包含关系下的极大元;互不包含时取后开的。 */\nfunction pickInnermost(candidates: Layer[]): Layer | null {\n let best: Layer | null = null\n for (const layer of candidates) {\n if (!best) {\n best = layer\n continue\n }\n if (containsPanel(best.panel, layer.panel)) {\n best = layer\n continue\n }\n if (containsPanel(layer.panel, best.panel)) continue\n if (layer.seq > best.seq) best = layer\n }\n return best\n}\n\nfunction resolve(): Layer | null {\n // 兜底回收:每次仲裁先摘掉死层,漏 release 的组件不会把注册表和监听一起拖住。\n syncListener()\n\n const live: Layer[] = []\n const deferred: Layer[] = []\n for (const layer of layers) {\n if (!isCandidate(layer)) continue\n if (layer.deferred) deferred.push(layer)\n else live.push(layer)\n }\n\n /*\n * 暂缓层只是兜底候选:仍在开启的层永远优先。\n *\n * 反过来(暂缓层也按最内层取胜)会让「内层关掉后立刻再按一次 Escape」被退场动画吞掉\n * ——它已不再开启却仍占着名额,外层永远等不到自己那一次,正是 issue #120 的契约\n * (escape-ownership.browser.spec.ts 压住它)。第三态要补的缺口是另一件事:退场被\n * 打断、新会话 claim 之前,panel 还在场上却不再登记,此刻按 Escape 会关到外层。\n *\n * 与 `pickInnermost` 同样刻意**不按事件路径筛选**:drawer 打开、内部列表也打开、而焦点\n * 停在 drawer 上时,事件路径只命中 drawer,按路径判定会关掉外层、留下内层。正确语义是\n * 「最内层优先」,与焦点无关。\n */\n return pickInnermost(live) ?? pickInnermost(deferred)\n}\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (event.key !== 'Escape') return\n // 已有更早的捕获监听处理过本次 Escape:不重复介入。\n if (event.defaultPrevented) return\n\n const layer = resolve()\n if (!layer) return\n\n /*\n * preventDefault 压掉原生 dialog 的关闭请求;stopPropagation 让组件自身的 handler\n * 不再执行。惰性层与暂缓层同样被吞掉按键,只是不走关闭入口 —— 否则事件会落到下层\n * overlay,关闭顺序与用户预期相反。\n *\n * 已知边界:stopPropagation 不阻止**同一节点**(document)上后注册的其他捕获监听。\n * 刻意不用 stopImmediatePropagation —— 那会连带掐掉应用自己在 document 上的捕获\n * 监听,超出本模块职责。\n */\n event.preventDefault()\n event.stopPropagation()\n // 惰性与暂缓都吞掉按键,只是不走关闭入口。\n if (layer.inert || layer.deferred) return\n layer.host.requestClose()\n}\n\n/**\n * panel 与 host 同时失联的层是死层:显式 release 之外的兜底删除路径。\n *\n * 惰性体现在只在遍历登记表的入口跑(建层之前、仲裁、release),不挂 DOM 变动回调 ——\n * panel 短暂移除再放回必须不丢登记。建层**之后**不跑:新层可能还没挂载,扫它就会误杀\n * (见 `createLayer` 开头与 `layers` 注册表处的注释)。\n */\nfunction reclaimDisconnectedLayers(): void {\n for (const layer of Array.from(layers)) {\n if (layer.released || layer.panel.isConnected || layer.host.isConnected()) continue\n releaseLayer(layer)\n }\n}\n\n/**\n * 监听器对账:惰性回收死层,再按登记表重算 document 监听。\n *\n * `reclaim` 关掉回收,只给 `createLayer` 建层之后那一次调用用:新层刚入注册表,调用方\n * 可能还没把 panel 与宿主挂进文档,那一刻扫它等于把新层判成死层。死层不会因此漏掉——\n * 回收在建层之前已经单独跑过一轮(见 `createLayer` 开头)。\n */\nfunction syncListener(reclaim = true): void {\n if (reclaim) reclaimDisconnectedLayers()\n\n let shouldListen = false\n for (const layer of layers) {\n /*\n * 未 release 的非 `none` 层就是监听理由,**不附加连接判据**:刚 claim 而尚未挂载的\n * 层要靠这条把监听开着——panel 挂上之后没有任何入口(不挂 DOM 变动回调)把它加回来,\n * 监听一撤这一层就再也听不见 Escape。死层的截杀交给上面的回收:它在每个带回收的\n * 入口先跑一步,轮到这里时同时失联的层已经不在表里,这条判据因此不会把死层留下来。\n */\n if (!layer.released && layer.arbitration !== 'none') {\n shouldListen = true\n break\n }\n }\n if (shouldListen === listening) return\n listening = shouldListen\n if (shouldListen) document.addEventListener('keydown', handleKeydown, true)\n else document.removeEventListener('keydown', handleKeydown, true)\n}\n\nexport const defineOpenOverlay = () =>\n definePlugin<OpenOverlay, OpenOverlayHost>(host => {\n let generation = 0\n let suspended = false\n const frames = new Set<OverlayFrameHandle & { id: number; generation: number }>()\n\n const cancelFrame = (frame: OverlayFrameHandle & { id: number; generation: number }) => {\n cancelAnimationFrame(frame.id)\n frames.delete(frame)\n }\n\n const cancelFrames = () => {\n for (const frame of Array.from(frames)) cancelFrame(frame)\n }\n\n const invalidateCurrent = () => {\n generation += 1\n cancelFrames()\n }\n\n const api: OpenOverlay = {\n claim(panel, options = {}) {\n const arbitration = options.arbitration ?? 'escape'\n const ancestryFrom = options.ancestryFrom ?? panel\n return createLayer({\n panel,\n host,\n arbitration,\n parent: findOpenAncestor(panel, ancestryFrom) ?? undefined\n })\n },\n\n scheduleFrame(callback, whileLive) {\n if (suspended) return { cancel() {} }\n\n const scheduledGeneration = generation\n const frame: OverlayFrameHandle & { id: number; generation: number } = {\n generation: scheduledGeneration,\n id: requestAnimationFrame(() => {\n frames.delete(frame)\n if (suspended || scheduledGeneration !== generation) return\n // 会话已结束:该帧属于上一轮开合,丢弃而不是执行在错误的层上。\n // handle 已 release,或同一 panel 重新 claim 换了新 handle(旧层仍在 WeakMap 里,\n // 标记为 released),两种情形都要丢。\n if (whileLive) {\n const liveLayer = layerByHandle.get(whileLive)\n if (!liveLayer || liveLayer.released) return\n }\n callback()\n }),\n cancel() {\n cancelFrame(frame)\n }\n }\n frames.add(frame)\n return frame\n },\n\n invalidate: invalidateCurrent,\n\n suspend() {\n if (suspended) return\n suspended = true\n // 停调度之后再撤销在途帧(两者互不依赖,顺序不影响语义)。不能只靠回调内部的\n // suspended 复查:那会让这些帧白占一个 rAF 周期(旧实现在此处因早退而没有取消)。\n cancelFrames()\n },\n\n resume() {\n if (!suspended) return\n suspended = false\n generation += 1\n }\n }\n\n return api\n })\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"open-overlay.js","names":[],"sources":["../../../src/shared/overlay/open-overlay.ts"],"sourcesContent":["/**\n * 开启态 overlay(open overlay)——「哪一层正开着」的唯一拥有者。\n *\n * 本模块合并三块职责:composition(逻辑父子树)、escape-dismiss(最内层仲裁)、\n * lifecycle(帧事务失效)。合并的判据不是三者职责相邻,而是它们共享同一条不变量:\n * **已登记 ⟺ 在场 ⟺ 有仲裁身份**。\n *\n * 这条不变量需要唯一的仲裁者:让 8 个 overlay 组件各自把它拼成三步协议\n * (`registerPanelFromAncestry` + `setPanel` / `unregisterPanel` + `setPanel(null)`),\n * 「漏撤销」与「重挂载后与仲裁失联」就只能靠每个组件自己记得,而\n * `lifecycle` 还要调用方手工传一个 `expectedOpen` 来复述「我开着吗」。\n *\n * 本模块的取舍:\n *\n * - 身份是**handle**而非 panel 元素:`release()` 不需要调用方回忆当初传了哪个 panel。\n * - 开启状态是**声明**而非询问:仲裁时不再回调宿主问 `isOpen()`,宿主只提供\n * `requestClose()` 与一个仅供惰性回收读取的 `isConnected()`;模块持有的真相即真相。\n * - `claim` 即「我开着」:一次 claim 对应一次开启,登记与仲裁是同一个动作。\n * - 在场分两态:开启中(Escape 走关闭入口)与退场中(panel 仍可见,暂缓仲裁、只作兜底\n * 候选)。后者由 `deferArbitration()` 进入、随 `release()`、重新 claim 或显式\n * `deferArbitration(false)` 离开:于是「退场被打断」与「宿主仍认为开着」不再把看得见\n * 的 panel 留在未登记状态,而退场已播完、宿主却仍认为开着的那一格,也不会让一个看不\n * 见的 panel 无限吞掉 Escape。\n * - 查询走 handle(`contains` / `containsEvent` / `hasFocusWithin`),调用方不再需要\n * 持有 panel 引用,也不知道存在全局注册表。\n * - 实例作用域与会话作用域分开:帧事务的 lifetime 比一次开合长(tooltip 跨断连\n * `resume()`),把它压进会话 handle 会在 `release()` 时误杀事务。\n *\n * 刻意**不**吸收 presence、滚动锁与 drawer 的层序(nested layers):它们回答的是\n * 视觉问题(`is-visible`、层序缩放),与「谁是最内层」正交,硬合并会互相污染。\n */\n\nimport { definePlugin } from '@greypan/js-kit'\n\n/**\n * 本层是否参与 Escape 仲裁。\n *\n * - `escape`:正常候选。命中即走宿主既有的用户关闭入口。\n * - `none`:只在逻辑组合树内,完全不参与仲裁,Escape 穿过它落到下层。用于 tooltip\n * —— 它今天就在树里(经 anchored panel 登记)但从不作为候选。\n *\n * 「暂时不可关闭」不在这里,而由 `setInert` 表达。静态与动态是同一件事的两面:\n * `no-escape-close` 这类策略看似静态,但它是**被观察的属性**,开启期间可被改写,\n * 所以同样要走动态通道(claim 后立即 `setInert(noEscapeClose)`)。把静态策略做成\n * 第三个枚举值只会产生一个没有真实调用方的成员。\n */\nexport type OverlayArbitration = 'escape' | 'none'\n\nexport interface OverlayClaimOptions {\n /** 默认 `escape`。 */\n arbitration?: OverlayArbitration\n /**\n * 沿该节点的祖先链寻找最近的已开启 overlay,作为本层的逻辑父级;缺省用 panel 自身。\n *\n * portal panel 与宿主物理分离,从 panel 自身向上走找不到组合父级,必须由调用方给出\n * 锚点(trigger)或宿主,才能把「谁在谁里面」判对。\n *\n * **顺序约束**:祖先链查找要求 panel 与 ancestryFrom 此刻都已就位(在 DOM 中)。\n * 本模块不做「等一帧再补登记」——那会让「已登记」与「已开启」短暂不等。\n */\n ancestryFrom?: Node\n}\n\nexport interface OverlayFrameHandle {\n cancel(): void\n}\n\n/** 会话作用域:一次开启对应一个 handle。 */\nexport interface OpenOverlayHandle {\n /**\n * 惰性:仍是候选(照旧 `preventDefault()` 压掉原生 `<dialog>` 的关闭请求),但不走\n * 关闭入口。这是「暂时不可关闭」的唯一通道,静态策略与瞬时状态都走这里。\n *\n * 不改变本层在树里的位置,也不改变 `seq` —— 因此不会影响并列 overlay 的裁决顺序。\n * `none` 层不受影响(它本就不是候选)。\n *\n * **与会话同 lifetime,新会话恒从 `false` 开始**:`claim` 建立的每一层都重置为\n * 非惰性。所以凡是「重新 claim」的路径(`anchored-panel.reconfigure`、同一 panel 重复\n * `open()`)之后,都必须按当前状态重推一次,否则惰性会被静默清掉。重推放在哪里取决于\n * 该组件在 reconfigure 后是否渲染:会渲染的(select / autocomplete 在 `updated()` 里\n * 同步)可以把紧随 claim 的那一行降级为备份,不会渲染的(popover)必须自己补。\n */\n setInert(inert: boolean): void\n /**\n * 进入退场暂缓态:panel 仍在场(可见),本层继续留在登记表里并吞掉 Escape,但不走\n * 关闭入口。`anchored-panel.close()` 在退场等待前调用它。\n *\n * 与 `setInert` 的分工:`inert` 是**调用方**对「暂时不可关闭」的声明,会随渲染被\n * 重推;本态由**生命周期**进入,调用方没有任何途径清掉它,只有 `release()` 与\n * 渲染重推它,只有 `release()`、「同一 panel 重新 claim」与下面那个 `false` 能让它\n * 消失。因此重新 claim 出来的新会话恒不暂缓,退场被打断后由新会话接管仲裁。\n *\n * 传 `false` 退出暂态。唯一的使用者是 `anchored-panel.close()`:退场已播完(panel\n * 已隐藏)而宿主仍认为开着时,把层交还仲裁——此刻 panel 并不在「可见但暂缓」的前提\n * 里,继续暂缓会让一个看不见的 panel 无限吞掉 Escape,用户再也没有按键路径把这个\n * 不一致的状态收敛掉。\n *\n * 暂缓层只是兜底候选:`resolve()` 里仍在开启的层永远优先。否则「内层关掉后立刻\n * 再按一次 Escape」会被退场动画吞掉,外层永远等不到自己那一次(issue #120)。\n */\n deferArbitration(deferred?: boolean): void\n /**\n * 把子层 panel 纳入本 handle 的子树(多级 submenu),默认不成为独立候选。\n *\n * 与 `claim` 的区别只在父级如何确定:`claim` 走祖先链,`adopt` 由调用方指名。\n *\n * 在已 `release()` 的 handle 上调用**不建层**、返回空操作 handle —— 否则会建出一个父层已死\n * 的孤层:它仍参与仲裁,却不在父层的子树里,除调用方手里那个 handle 外没有回收路径。\n */\n adopt(panel: HTMLElement, options?: OverlayClaimOptions): OpenOverlayHandle\n /** 本层子树(含已 adopt 的子层)是否包含 node。 */\n contains(node: Node): boolean\n /** event 的完整 composed path 是否落入本层子树。 */\n containsEvent(event: Event): boolean\n /** 焦点是否在本层子树内。 */\n hasFocusWithin(): boolean\n /** 幂等。撤销本层及其全部子层,退出仲裁。 */\n release(): void\n}\n\n/** 实例作用域:每个宿主组件一次,跨开合与断连存活。 */\nexport interface OpenOverlay {\n claim(panel: HTMLElement, options?: OverlayClaimOptions): OpenOverlayHandle\n /**\n * 帧事务调度。`whileLive` handle 一旦 release,回调自动作废 —— 调用方不必手工传入\n * `expectedOpen` 轮询(那个参数正是「模块还得回头问宿主」的证据)。\n */\n scheduleFrame(callback: () => void, whileLive?: OpenOverlayHandle): OverlayFrameHandle\n /** 结束当前事务:取消未执行的 frame,并让旧 generation 的回调失效。 */\n invalidate(): void\n /** 断连后停止调度(可 `resume()`);generation 继续单调递增,旧事务保持失效。 */\n suspend(): void\n resume(): void\n}\n\nexport interface OpenOverlayHost {\n /** 走宿主既有的用户关闭入口(内部负责 controlled 语义与 `open-change` 派发)。 */\n requestClose(): void\n /**\n * 宿主元素是否仍在文档中。只被惰性回收读取(见 `layers` 注册表处的注释),\n * 仲裁路径不回调它——读 DOM 连接状态不是回调宿主问「我开着吗」。\n */\n isConnected(): boolean\n}\n\ninterface Layer {\n panel: HTMLElement\n host: OpenOverlayHost\n arbitration: OverlayArbitration\n /** 动态惰性 toggle,与会话同 lifetime。 */\n inert: boolean\n /** 退场暂缓 switch:panel 仍在场,但只作兜底候选(见 `deferArbitration`)。 */\n deferred: boolean\n /** 登记序号:互不包含的并列 overlay 里,后开的更靠上。 */\n seq: number\n released: boolean\n}\n\n/*\n * 模块级注册表:单例 document 监听器需要一个全局视野,这正是「谁是最内层」不能被\n * 拆到各组件里的原因。\n *\n * `Layer` 强引用 panel 与 host,所以一条没被删掉的记录会让整个组件(含子树)无法回收。\n * 删除路径有两条:显式 `release()`,以及 `reclaimDisconnectedLayers()` 的惰性兜底\n * ——「宿主还在但组件被丢弃」这类漏 release 的路径,光靠 `isCandidate()` 筛掉不可达\n * 候选只会留下永久泄漏,还会让 `shouldListen` 恒为 true 把 document 监听留住。\n * 兜底判据取 panel 与 host **同时**失联:panel 可能被 portal 在容器间搬运,也可能只是\n * 短暂移除再放回(层对象比 DOM 连接活得久),只有两者都不在文档里才判定为死层。\n * 回收**不扫刚 claim 的新层**:调用方完全可能先 claim 再把 panel 与宿主挂进文档,\n * 那一刻两者都还没连上。所以 claim 路径的回收跑在建层之前(`createLayer` 开头),\n * 新层入表之后只做监听对账。\n * 读 DOM 连接状态不是回调宿主问「我开着吗」,不违反声明式的取舍。\n */\nconst layers = new Set<Layer>()\nconst layerByPanel = new WeakMap<HTMLElement, Layer>()\nconst layerByHandle = new WeakMap<OpenOverlayHandle, Layer>()\nconst parents = new WeakMap<HTMLElement, HTMLElement>()\nconst childPanels = new WeakMap<HTMLElement, Set<HTMLElement>>()\nlet listening = false\nlet sequence = 0\n\n/*\n * dev 期测试钩子:登记表尺寸。\n *\n * 「漏 release」是结构性风险,而 `layers` 的尺寸无法从公开 interface 观察——调用方\n * 只持有 handle,看不到全局注册表,测试于是只能靠 GC 语义推断。有了它,泄漏在测试里\n * 是一个可直接断言的数字。`import.meta.env.DEV` 是编译期常量,生产构建里整段消失。\n */\ndeclare global {\n // eslint-disable-next-line no-var\n var __openOverlayLayerCount: () => number\n}\n\nif (import.meta.env.DEV) {\n globalThis.__openOverlayLayerCount = () => layers.size\n}\n\n/*\n * 已失效 handle 的空操作替身,用于 `adopt` 在 released handle 上的返回值。其余 handle 方法在\n * released 时都静默降级,返回值也必须一起降级,否则调用方会以为自己拿到了一棵可用子树。\n */\nconst inactiveHandle: OpenOverlayHandle = {\n deferArbitration() {},\n setInert() {},\n adopt: () => inactiveHandle,\n contains: () => false,\n containsEvent: () => false,\n hasFocusWithin: () => false,\n release() {}\n}\n\nfunction nextCompositionNode(node: Node): Node | null {\n if (node instanceof Element && node.assignedSlot) return node.assignedSlot\n if (node.parentNode) return node.parentNode\n if (node instanceof ShadowRoot) return node.host\n return null\n}\n\nfunction nodeIsInside(root: HTMLElement, node: Node): boolean {\n let current: Node | null = node\n while (current) {\n if (current === root || root.contains(current)) return true\n current = nextCompositionNode(current)\n }\n return false\n}\n\nfunction detachFromParent(panel: HTMLElement): void {\n const parent = parents.get(panel)\n if (!parent) return\n const siblings = childPanels.get(parent)\n siblings?.delete(panel)\n if (siblings?.size === 0) childPanels.delete(parent)\n parents.delete(panel)\n}\n\nfunction attachToParent(panel: HTMLElement, parent: HTMLElement | undefined): void {\n detachFromParent(panel)\n if (!parent || parent === panel) return\n const siblings = childPanels.get(parent) ?? new Set<HTMLElement>()\n siblings.add(panel)\n childPanels.set(parent, siblings)\n parents.set(panel, parent)\n}\n\n/** panel 自身或其任何已登记子层是否包含 target。 */\nfunction containsPanel(panel: HTMLElement, target: Node): boolean {\n if (nodeIsInside(panel, target)) return true\n for (const child of childPanels.get(panel) ?? []) {\n if (containsPanel(child, target)) return true\n }\n return false\n}\n\nfunction hasFocusWithinPanel(panel: HTMLElement): boolean {\n if (panel.matches(':focus-within')) return true\n for (const child of childPanels.get(panel) ?? []) {\n if (hasFocusWithinPanel(child)) return true\n }\n return false\n}\n\n/** 从 from 沿祖先链找最近的已开启 overlay panel;panel 自身永远不算自己的父级。 */\nfunction findOpenAncestor(panel: HTMLElement, from: Node): HTMLElement | null {\n let current: Node | null = from === panel ? nextCompositionNode(from) : from\n while (current) {\n if (current instanceof HTMLElement && current !== panel) {\n const candidate = layerByPanel.get(current)\n if (candidate && !candidate.released) return current\n }\n current = nextCompositionNode(current)\n }\n return null\n}\n\nfunction releaseLayer(layer: Layer): void {\n if (layer.released) return\n layer.released = true\n for (const child of Array.from(childPanels.get(layer.panel) ?? [])) {\n const childLayer = layerByPanel.get(child)\n if (childLayer) releaseLayer(childLayer)\n else detachFromParent(child)\n }\n layers.delete(layer)\n layerByPanel.delete(layer.panel)\n childPanels.delete(layer.panel)\n detachFromParent(layer.panel)\n // 不在这里 syncListener:本函数被子层递归与兜底回收复用,监听器对账由调用方在\n // 整棵子树摘完后做一次即可。\n}\n\nfunction createLayer(input: {\n panel: HTMLElement\n host: OpenOverlayHost\n arbitration: OverlayArbitration\n parent?: HTMLElement\n}): OpenOverlayHandle {\n /*\n * 先摘死层,再建新层。claim/adopt 是完全合法的「先开启后挂载」时序——调用方那一刻\n * 可能还没把 panel 与宿主挂进文档,两者都失联。回收跑在新层入表**之前**,新层就不\n * 会被自己的 claim 判成死层;而漏 release 留下的死层依旧在这里被扫掉。\n */\n reclaimDisconnectedLayers()\n\n const previous = layerByPanel.get(input.panel)\n // 同一 panel 重新 claim = 新的一次开启:旧会话(含其子层)整体作废,seq 重新分配。\n if (previous) releaseLayer(previous)\n\n const layer: Layer = {\n panel: input.panel,\n host: input.host,\n arbitration: input.arbitration,\n inert: false,\n deferred: false,\n seq: ++sequence,\n released: false\n }\n layers.add(layer)\n layerByPanel.set(input.panel, layer)\n attachToParent(input.panel, input.parent)\n\n const handle: OpenOverlayHandle = {\n deferArbitration(deferred = true) {\n if (layer.released) return\n layer.deferred = deferred\n },\n\n setInert(inert) {\n if (layer.released) return\n layer.inert = inert\n },\n\n adopt(panel, options = {}) {\n if (layer.released) return inactiveHandle\n return createLayer({\n panel,\n host: layer.host,\n arbitration: options.arbitration ?? 'none',\n parent: layer.panel\n })\n },\n\n contains(node) {\n return !layer.released && containsPanel(layer.panel, node)\n },\n\n containsEvent(event) {\n return (\n !layer.released && event.composedPath().some(node => node instanceof Node && containsPanel(layer.panel, node))\n )\n },\n\n hasFocusWithin() {\n return !layer.released && hasFocusWithinPanel(layer.panel)\n },\n\n release() {\n releaseLayer(layer)\n syncListener()\n }\n }\n\n layerByHandle.set(handle, layer)\n // 不带回收:新层 panel 与宿主可能还没挂载,回收已在函数开头跑过(见 `reclaim` 参数)。\n syncListener(false)\n return handle\n}\n\nfunction isCandidate(layer: Layer): boolean {\n return !layer.released && layer.arbitration !== 'none' && layer.panel.isConnected\n}\n\n/** 在候选里取最内层:子树包含关系下的极大元;互不包含时取后开的。 */\nfunction pickInnermost(candidates: Layer[]): Layer | null {\n let best: Layer | null = null\n for (const layer of candidates) {\n if (!best) {\n best = layer\n continue\n }\n if (containsPanel(best.panel, layer.panel)) {\n best = layer\n continue\n }\n if (containsPanel(layer.panel, best.panel)) continue\n if (layer.seq > best.seq) best = layer\n }\n return best\n}\n\nfunction resolve(): Layer | null {\n // 兜底回收:每次仲裁先摘掉死层,漏 release 的组件不会把注册表和监听一起拖住。\n syncListener()\n\n const live: Layer[] = []\n const deferred: Layer[] = []\n for (const layer of layers) {\n if (!isCandidate(layer)) continue\n if (layer.deferred) deferred.push(layer)\n else live.push(layer)\n }\n\n /*\n * 暂缓层只是兜底候选:仍在开启的层永远优先。\n *\n * 反过来(暂缓层也按最内层取胜)会让「内层关掉后立刻再按一次 Escape」被退场动画吞掉\n * ——它已不再开启却仍占着名额,外层永远等不到自己那一次,正是 issue #120 的契约\n * (escape-ownership.browser.spec.ts 压住它)。第三态要补的缺口是另一件事:退场被\n * 打断、新会话 claim 之前,panel 还在场上却不再登记,此刻按 Escape 会关到外层。\n *\n * 与 `pickInnermost` 同样刻意**不按事件路径筛选**:drawer 打开、内部列表也打开、而焦点\n * 停在 drawer 上时,事件路径只命中 drawer,按路径判定会关掉外层、留下内层。正确语义是\n * 「最内层优先」,与焦点无关。\n */\n return pickInnermost(live) ?? pickInnermost(deferred)\n}\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (event.key !== 'Escape') return\n // 已有更早的捕获监听处理过本次 Escape:不重复介入。\n if (event.defaultPrevented) return\n\n const layer = resolve()\n if (!layer) return\n\n /*\n * preventDefault 压掉原生 dialog 的关闭请求;stopPropagation 让组件自身的 handler\n * 不再执行。惰性层与暂缓层同样被吞掉按键,只是不走关闭入口 —— 否则事件会落到下层\n * overlay,关闭顺序与用户预期相反。\n *\n * 已知边界:stopPropagation 不阻止**同一节点**(document)上后注册的其他捕获监听。\n * 刻意不用 stopImmediatePropagation —— 那会连带掐掉应用自己在 document 上的捕获\n * 监听,超出本模块职责。\n */\n event.preventDefault()\n event.stopPropagation()\n // 惰性与暂缓都吞掉按键,只是不走关闭入口。\n if (layer.inert || layer.deferred) return\n layer.host.requestClose()\n}\n\n/**\n * panel 与 host 同时失联的层是死层:显式 release 之外的兜底删除路径。\n *\n * 惰性体现在只在遍历登记表的入口跑(建层之前、仲裁、release),不挂 DOM 变动回调 ——\n * panel 短暂移除再放回必须不丢登记。建层**之后**不跑:新层可能还没挂载,扫它就会误杀\n * (见 `createLayer` 开头与 `layers` 注册表处的注释)。\n */\nfunction reclaimDisconnectedLayers(): void {\n for (const layer of Array.from(layers)) {\n if (layer.released || layer.panel.isConnected || layer.host.isConnected()) continue\n releaseLayer(layer)\n }\n}\n\n/**\n * 监听器对账:惰性回收死层,再按登记表重算 document 监听。\n *\n * `reclaim` 关掉回收,只给 `createLayer` 建层之后那一次调用用:新层刚入注册表,调用方\n * 可能还没把 panel 与宿主挂进文档,那一刻扫它等于把新层判成死层。死层不会因此漏掉——\n * 回收在建层之前已经单独跑过一轮(见 `createLayer` 开头)。\n */\nfunction syncListener(reclaim = true): void {\n if (reclaim) reclaimDisconnectedLayers()\n\n let shouldListen = false\n for (const layer of layers) {\n /*\n * 未 release 的非 `none` 层就是监听理由,**不附加连接判据**:刚 claim 而尚未挂载的\n * 层要靠这条把监听开着——panel 挂上之后没有任何入口(不挂 DOM 变动回调)把它加回来,\n * 监听一撤这一层就再也听不见 Escape。死层的截杀交给上面的回收:它在每个带回收的\n * 入口先跑一步,轮到这里时同时失联的层已经不在表里,这条判据因此不会把死层留下来。\n */\n if (!layer.released && layer.arbitration !== 'none') {\n shouldListen = true\n break\n }\n }\n if (shouldListen === listening) return\n listening = shouldListen\n if (shouldListen) document.addEventListener('keydown', handleKeydown, true)\n else document.removeEventListener('keydown', handleKeydown, true)\n}\n\nexport const defineOpenOverlay = () =>\n definePlugin<OpenOverlay, OpenOverlayHost>(host => {\n let generation = 0\n let suspended = false\n const frames = new Set<OverlayFrameHandle & { id: number; generation: number }>()\n\n const cancelFrame = (frame: OverlayFrameHandle & { id: number; generation: number }) => {\n cancelAnimationFrame(frame.id)\n frames.delete(frame)\n }\n\n const cancelFrames = () => {\n for (const frame of Array.from(frames)) cancelFrame(frame)\n }\n\n const invalidateCurrent = () => {\n generation += 1\n cancelFrames()\n }\n\n const api: OpenOverlay = {\n claim(panel, options = {}) {\n const arbitration = options.arbitration ?? 'escape'\n const ancestryFrom = options.ancestryFrom ?? panel\n return createLayer({\n panel,\n host,\n arbitration,\n parent: findOpenAncestor(panel, ancestryFrom) ?? undefined\n })\n },\n\n scheduleFrame(callback, whileLive) {\n if (suspended) return { cancel() {} }\n\n const scheduledGeneration = generation\n const frame: OverlayFrameHandle & { id: number; generation: number } = {\n generation: scheduledGeneration,\n id: requestAnimationFrame(() => {\n frames.delete(frame)\n if (suspended || scheduledGeneration !== generation) return\n // 会话已结束:该帧属于上一轮开合,丢弃而不是执行在错误的层上。\n // handle 已 release,或同一 panel 重新 claim 换了新 handle(旧层仍在 WeakMap 里,\n // 标记为 released),两种情形都要丢。\n if (whileLive) {\n const liveLayer = layerByHandle.get(whileLive)\n if (!liveLayer || liveLayer.released) return\n }\n callback()\n }),\n cancel() {\n cancelFrame(frame)\n }\n }\n frames.add(frame)\n return frame\n },\n\n invalidate: invalidateCurrent,\n\n suspend() {\n if (suspended) return\n suspended = true\n // 停调度之后再撤销在途帧(两者互不依赖,顺序不影响语义)。不能只靠回调内部的\n // suspended 复查:那会让这些帧白占一个 rAF 周期。\n cancelFrames()\n },\n\n resume() {\n if (!suspended) return\n suspended = false\n generation += 1\n }\n }\n\n return api\n })\n"],"mappings":"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"}
|