@qw-ui/core 0.3.0-next.9 → 0.3.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.md +21 -37
- package/dist/action-sheet/action-sheet.d.ts +110 -0
- package/dist/action-sheet/index.d.ts +2 -0
- package/dist/action-sheet/index.js +2 -0
- package/dist/action-sheet-Cvcr1S_m.js +183 -0
- package/dist/action-sheet-Cvcr1S_m.js.map +1 -0
- package/dist/area-picker/area-picker.d.ts +113 -0
- package/dist/area-picker/index.d.ts +1 -0
- package/dist/area-picker/index.js +348 -0
- package/dist/area-picker/index.js.map +1 -0
- package/dist/aria-description-CimD2M_C.js +13 -0
- package/dist/aria-description-CimD2M_C.js.map +1 -0
- package/dist/aria-description.d.ts +2 -0
- package/dist/avatar/avatar-load.d.ts +76 -0
- package/dist/avatar/avatar.d.ts +22 -5
- package/dist/avatar/index.d.ts +1 -0
- package/dist/avatar/index.js +57 -18
- package/dist/avatar/index.js.map +1 -1
- package/dist/avatar-load-w9dq05oV.js +139 -0
- package/dist/avatar-load-w9dq05oV.js.map +1 -0
- package/dist/back-top/back-top.d.ts +77 -0
- package/dist/back-top/index.d.ts +1 -0
- package/dist/back-top/index.js +189 -0
- package/dist/back-top/index.js.map +1 -0
- package/dist/badge/badge.d.ts +85 -0
- package/dist/badge/index.d.ts +1 -0
- package/dist/badge/index.js +88 -0
- package/dist/badge/index.js.map +1 -0
- package/dist/button/button.d.ts +13 -0
- package/dist/button/index.js +3 -5
- package/dist/button/index.js.map +1 -1
- package/dist/calendar/calendar.d.ts +100 -0
- package/dist/calendar/index.d.ts +1 -0
- package/dist/calendar/index.js +2 -0
- package/dist/calendar-CmpK3stz.js +363 -0
- package/dist/calendar-CmpK3stz.js.map +1 -0
- package/dist/card/card.d.ts +68 -0
- package/dist/card/index.d.ts +2 -0
- package/dist/card/index.js +2 -0
- package/dist/card-DRtWa6Cr.js +107 -0
- package/dist/card-DRtWa6Cr.js.map +1 -0
- package/dist/cascader/cascader.d.ts +115 -0
- package/dist/cascader/index.d.ts +1 -0
- package/dist/cascader/index.js +2 -0
- package/dist/cascader-D-xMjs7P.js +333 -0
- package/dist/cascader-D-xMjs7P.js.map +1 -0
- package/dist/cell/cell.d.ts +41 -0
- package/dist/cell/index.d.ts +1 -0
- package/dist/cell/index.js +43 -0
- package/dist/cell/index.js.map +1 -0
- package/dist/check-list/check-list.d.ts +78 -0
- package/dist/check-list/index.d.ts +2 -0
- package/dist/check-list/index.js +2 -0
- package/dist/check-list-BvZHQt5w.js +60 -0
- package/dist/check-list-BvZHQt5w.js.map +1 -0
- package/dist/checkbox/checkbox.d.ts +59 -0
- package/dist/checkbox/index.d.ts +2 -0
- package/dist/checkbox/index.js +2 -0
- package/dist/checkbox-BlndJrz5.js +127 -0
- package/dist/checkbox-BlndJrz5.js.map +1 -0
- package/dist/checkbox-group/checkbox-group.d.ts +86 -0
- package/dist/checkbox-group/index.d.ts +3 -0
- package/dist/checkbox-group/index.js +2 -0
- package/dist/checkbox-group-gGfsTv-e.js +223 -0
- package/dist/checkbox-group-gGfsTv-e.js.map +1 -0
- package/dist/choice-group-C4c9m0qe.js +373 -0
- package/dist/choice-group-C4c9m0qe.js.map +1 -0
- package/dist/circle/circle.d.ts +97 -0
- package/dist/circle/index.d.ts +1 -0
- package/dist/circle/index.js +119 -0
- package/dist/circle/index.js.map +1 -0
- package/dist/collapse/collapse.d.ts +98 -0
- package/dist/collapse/index.d.ts +2 -0
- package/dist/collapse/index.js +2 -0
- package/dist/collapse-B969h7-H.js +226 -0
- package/dist/collapse-B969h7-H.js.map +1 -0
- package/dist/countdown/countdown.d.ts +114 -0
- package/dist/countdown/index.d.ts +1 -0
- package/dist/countdown/index.js +309 -0
- package/dist/countdown/index.js.map +1 -0
- package/dist/date-picker/date-picker.d.ts +168 -0
- package/dist/date-picker/index.d.ts +1 -0
- package/dist/date-picker/index.js +401 -0
- package/dist/date-picker/index.js.map +1 -0
- package/dist/descriptions/descriptions.d.ts +69 -0
- package/dist/descriptions/index.d.ts +1 -0
- package/dist/descriptions/index.js +86 -0
- package/dist/descriptions/index.js.map +1 -0
- package/dist/dialog/dialog.d.ts +61 -43
- package/dist/dialog/index.js +73 -19
- package/dist/dialog/index.js.map +1 -1
- package/dist/divider/divider.d.ts +18 -2
- package/dist/divider/index.js +20 -2
- package/dist/divider/index.js.map +1 -1
- package/dist/dropdown/dropdown.d.ts +172 -0
- package/dist/dropdown/index.d.ts +2 -0
- package/dist/dropdown/index.js +467 -0
- package/dist/dropdown/index.js.map +1 -0
- package/dist/ellipsis/ellipsis-layout.d.ts +34 -0
- package/dist/ellipsis/ellipsis.d.ts +88 -0
- package/dist/ellipsis/index.d.ts +2 -0
- package/dist/ellipsis/index.js +320 -0
- package/dist/ellipsis/index.js.map +1 -0
- package/dist/empty/empty-illustration.d.ts +3 -0
- package/dist/empty/empty.d.ts +43 -1
- package/dist/empty/index.js +2 -21
- package/dist/empty-CAgyvhUI.js +166 -0
- package/dist/empty-CAgyvhUI.js.map +1 -0
- package/dist/field/field.d.ts +95 -0
- package/dist/field/index.d.ts +2 -0
- package/dist/field/index.js +2 -0
- package/dist/field-DMHGIMZF.js +241 -0
- package/dist/field-DMHGIMZF.js.map +1 -0
- package/dist/floating-bubble/floating-bubble.d.ts +116 -0
- package/dist/floating-bubble/index.d.ts +1 -0
- package/dist/floating-bubble/index.js +333 -0
- package/dist/floating-bubble/index.js.map +1 -0
- package/dist/floating-panel/floating-panel.d.ts +80 -0
- package/dist/floating-panel/index.d.ts +2 -0
- package/dist/floating-panel/index.js +2 -0
- package/dist/floating-panel-Cbm5njBJ.js +363 -0
- package/dist/floating-panel-Cbm5njBJ.js.map +1 -0
- package/dist/footer/footer.d.ts +94 -0
- package/dist/footer/index.d.ts +1 -0
- package/dist/footer/index.js +154 -0
- package/dist/footer/index.js.map +1 -0
- package/dist/form/connect.d.ts +6 -0
- package/dist/form/form.d.ts +100 -0
- package/dist/form/ids.d.ts +14 -0
- package/dist/form/index.d.ts +13 -0
- package/dist/form/index.js +3 -0
- package/dist/form/methods.d.ts +5 -0
- package/dist/form/model.d.ts +24 -0
- package/dist/form/native.d.ts +25 -0
- package/dist/form/rules.d.ts +40 -0
- package/dist/form/ssr.d.ts +7 -0
- package/dist/form/types.d.ts +150 -0
- package/dist/form-BAGkIEMY.js +1354 -0
- package/dist/form-BAGkIEMY.js.map +1 -0
- package/dist/format-BDUY0C_c.js +89 -0
- package/dist/format-BDUY0C_c.js.map +1 -0
- package/dist/gesture-_SRHIvBm.js +30 -0
- package/dist/gesture-_SRHIvBm.js.map +1 -0
- package/dist/grid/grid-item.d.ts +22 -0
- package/dist/grid/grid.d.ts +42 -0
- package/dist/grid/index.d.ts +2 -0
- package/dist/grid/index.js +73 -0
- package/dist/grid/index.js.map +1 -0
- package/dist/icon/icon.d.ts +37 -1
- package/dist/icon/identity.d.ts +3 -0
- package/dist/icon/index.js +2 -20
- package/dist/icon-Cgdbnk1u.js +77 -0
- package/dist/icon-Cgdbnk1u.js.map +1 -0
- package/dist/image/image-load.d.ts +24 -0
- package/dist/image/image.d.ts +45 -8
- package/dist/image/index.d.ts +1 -0
- package/dist/image/index.js +116 -14
- package/dist/image/index.js.map +1 -1
- package/dist/image-preview/image-preview.d.ts +124 -0
- package/dist/image-preview/index.d.ts +1 -0
- package/dist/image-preview/index.js +450 -0
- package/dist/image-preview/index.js.map +1 -0
- package/dist/index-bar/index-bar.d.ts +121 -0
- package/dist/index-bar/index.d.ts +1 -0
- package/dist/index-bar/index.js +386 -0
- package/dist/index-bar/index.js.map +1 -0
- package/dist/index.d.ts +115 -10
- package/dist/index.js +151 -11
- package/dist/index.js.map +1 -0
- package/dist/infinite-scroll/index.d.ts +1 -0
- package/dist/infinite-scroll/index.js +248 -0
- package/dist/infinite-scroll/index.js.map +1 -0
- package/dist/infinite-scroll/infinite-scroll.d.ts +95 -0
- package/dist/input/index.js +181 -22
- package/dist/input/index.js.map +1 -1
- package/dist/input/input.d.ts +44 -1
- package/dist/layer-IpFrl5--.js +414 -0
- package/dist/layer-IpFrl5--.js.map +1 -0
- package/dist/layout-BRSqi4AQ.js +43 -0
- package/dist/layout-BRSqi4AQ.js.map +1 -0
- package/dist/layout.d.ts +13 -0
- package/dist/list/index.d.ts +2 -0
- package/dist/list/index.js +2 -0
- package/dist/list/list.d.ts +30 -0
- package/dist/list-6-iz-Irh.js +28 -0
- package/dist/list-6-iz-Irh.js.map +1 -0
- package/dist/loading/index.js +45 -2
- package/dist/loading/index.js.map +1 -1
- package/dist/loading/loading.d.ts +45 -2
- package/dist/modal-dialog-machine-CF9_z3Dm.js +487 -0
- package/dist/modal-dialog-machine-CF9_z3Dm.js.map +1 -0
- package/dist/modal-dialog-machine.d.ts +21 -0
- package/dist/modal-dismissable-lifetime.d.ts +21 -0
- package/dist/modal-registry.d.ts +24 -0
- package/dist/modal-render-hydration.d.ts +35 -0
- package/dist/modal-render-runtime.d.ts +19 -0
- package/dist/modal-render-scope.d.ts +63 -0
- package/dist/nav-bar/index.d.ts +1 -0
- package/dist/nav-bar/index.js +115 -0
- package/dist/nav-bar/index.js.map +1 -0
- package/dist/nav-bar/nav-bar.d.ts +76 -0
- package/dist/notice-bar/index.d.ts +2 -0
- package/dist/notice-bar/index.js +2 -0
- package/dist/notice-bar/notice-bar.d.ts +103 -0
- package/dist/notice-bar-DMpwLvRb.js +231 -0
- package/dist/notice-bar-DMpwLvRb.js.map +1 -0
- package/dist/notify/index.d.ts +1 -0
- package/dist/notify/index.js +251 -0
- package/dist/notify/index.js.map +1 -0
- package/dist/notify/notify.d.ts +123 -0
- package/dist/number-keyboard/index.d.ts +1 -0
- package/dist/number-keyboard/index.js +333 -0
- package/dist/number-keyboard/index.js.map +1 -0
- package/dist/number-keyboard/number-keyboard.d.ts +141 -0
- package/dist/overlay-panel/index.d.ts +2 -0
- package/dist/overlay-panel/index.js +2 -0
- package/dist/overlay-panel/overlay-panel.d.ts +20 -0
- package/dist/overlay-panel-Z_qdKeBj.js +26 -0
- package/dist/overlay-panel-Z_qdKeBj.js.map +1 -0
- package/dist/page-indicator/index.d.ts +1 -0
- package/dist/page-indicator/index.js +138 -0
- package/dist/page-indicator/index.js.map +1 -0
- package/dist/page-indicator/page-indicator.d.ts +93 -0
- package/dist/pagination/index.d.ts +1 -0
- package/dist/pagination/index.js +198 -0
- package/dist/pagination/index.js.map +1 -0
- package/dist/pagination/pagination.d.ts +125 -0
- package/dist/password-input/index.d.ts +1 -0
- package/dist/password-input/index.js +317 -0
- package/dist/password-input/index.js.map +1 -0
- package/dist/password-input/password-input.d.ts +144 -0
- package/dist/picker/index.d.ts +8 -0
- package/dist/picker/index.js +2 -0
- package/dist/picker/picker-machine.d.ts +80 -0
- package/dist/picker/picker.d.ts +121 -0
- package/dist/picker/platform.d.ts +84 -0
- package/dist/picker/selection-connect.d.ts +90 -0
- package/dist/picker/selection-model.d.ts +211 -0
- package/dist/picker-BykFntQN.js +1675 -0
- package/dist/picker-BykFntQN.js.map +1 -0
- package/dist/popover/index.d.ts +3 -0
- package/dist/popover/index.js +253 -0
- package/dist/popover/index.js.map +1 -0
- package/dist/popover/layer.d.ts +44 -0
- package/dist/popover/popover.d.ts +104 -0
- package/dist/popover/positioning.d.ts +132 -0
- package/dist/popup/index.d.ts +2 -0
- package/dist/popup/index.js +2 -0
- package/dist/popup/popup.d.ts +60 -0
- package/dist/popup-z5d8IYCt.js +576 -0
- package/dist/popup-z5d8IYCt.js.map +1 -0
- package/dist/portal-BHCNTWhg.js +78 -0
- package/dist/portal-BHCNTWhg.js.map +1 -0
- package/dist/portal.d.ts +61 -0
- package/dist/price/format.d.ts +19 -0
- package/dist/price/index.d.ts +1 -0
- package/dist/price/index.js +154 -0
- package/dist/price/index.js.map +1 -0
- package/dist/price/price.d.ts +88 -0
- package/dist/progress/index.d.ts +1 -0
- package/dist/progress/index.js +2 -0
- package/dist/progress/progress.d.ts +32 -0
- package/dist/progress-f3iYEfdA.js +37 -0
- package/dist/progress-f3iYEfdA.js.map +1 -0
- package/dist/pull-refresh/index.d.ts +1 -0
- package/dist/pull-refresh/index.js +414 -0
- package/dist/pull-refresh/index.js.map +1 -0
- package/dist/pull-refresh/pull-refresh.d.ts +118 -0
- package/dist/radio-group/index.d.ts +3 -0
- package/dist/radio-group/index.js +2 -0
- package/dist/radio-group/radio-group.d.ts +78 -0
- package/dist/radio-group-BOIMuqnS.js +230 -0
- package/dist/radio-group-BOIMuqnS.js.map +1 -0
- package/dist/rate/index.d.ts +1 -0
- package/dist/rate/index.js +2 -0
- package/dist/rate/rate-form.d.ts +28 -0
- package/dist/rate/rate.d.ts +144 -0
- package/dist/rate-5XsU2QkY.js +631 -0
- package/dist/rate-5XsU2QkY.js.map +1 -0
- package/dist/reorder/index.d.ts +1 -0
- package/dist/reorder/index.js +720 -0
- package/dist/reorder/index.js.map +1 -0
- package/dist/reorder/reorder.d.ts +190 -0
- package/dist/result/index.d.ts +1 -0
- package/dist/result/index.js +123 -0
- package/dist/result/index.js.map +1 -0
- package/dist/result/result.d.ts +88 -0
- package/dist/safe-area/index.d.ts +1 -0
- package/dist/safe-area/index.js +42 -0
- package/dist/safe-area/index.js.map +1 -0
- package/dist/safe-area/safe-area.d.ts +28 -0
- package/dist/search-bar/index.js +4 -2
- package/dist/search-bar/index.js.map +1 -1
- package/dist/search-bar/search-bar.d.ts +6 -0
- package/dist/segmented/index.d.ts +2 -0
- package/dist/segmented/index.js +2 -0
- package/dist/segmented/segmented.d.ts +127 -0
- package/dist/segmented-BaU38_L4.js +367 -0
- package/dist/segmented-BaU38_L4.js.map +1 -0
- package/dist/selection-form-BOM_odUk.js +88 -0
- package/dist/selection-form-BOM_odUk.js.map +1 -0
- package/dist/selection-form.d.ts +27 -0
- package/dist/selection-ivXqO1eu.js +55 -0
- package/dist/selection-ivXqO1eu.js.map +1 -0
- package/dist/selection.d.ts +29 -0
- package/dist/selector/choice-group.d.ts +114 -0
- package/dist/selector/index.d.ts +2 -0
- package/dist/selector/index.js +2 -0
- package/dist/selector/selector.d.ts +90 -0
- package/dist/selector-BU2MMJ4N.js +93 -0
- package/dist/selector-BU2MMJ4N.js.map +1 -0
- package/dist/share-sheet/index.d.ts +1 -0
- package/dist/share-sheet/index.js +138 -0
- package/dist/share-sheet/index.js.map +1 -0
- package/dist/share-sheet/share-sheet.d.ts +139 -0
- package/dist/side-nav/index.d.ts +1 -0
- package/dist/side-nav/index.js +99 -0
- package/dist/side-nav/index.js.map +1 -0
- package/dist/side-nav/side-nav.d.ts +94 -0
- package/dist/skeleton/index.js +51 -2
- package/dist/skeleton/index.js.map +1 -1
- package/dist/skeleton/skeleton.d.ts +34 -3
- package/dist/slider/index.d.ts +1 -0
- package/dist/slider/index.js +482 -0
- package/dist/slider/index.js.map +1 -0
- package/dist/slider/slider.d.ts +174 -0
- package/dist/space/index.d.ts +1 -0
- package/dist/space/index.js +52 -0
- package/dist/space/index.js.map +1 -0
- package/dist/space/space.d.ts +46 -0
- package/dist/statistic/index.d.ts +1 -0
- package/dist/statistic/index.js +152 -0
- package/dist/statistic/index.js.map +1 -0
- package/dist/statistic/statistic.d.ts +101 -0
- package/dist/stepper/index.d.ts +1 -0
- package/dist/stepper/index.js +172 -0
- package/dist/stepper/index.js.map +1 -0
- package/dist/stepper/stepper.d.ts +161 -0
- package/dist/steps/index.d.ts +1 -0
- package/dist/steps/index.js +72 -0
- package/dist/steps/index.js.map +1 -0
- package/dist/steps/steps.d.ts +67 -0
- package/dist/sticky/index.d.ts +1 -0
- package/dist/sticky/index.js +145 -0
- package/dist/sticky/index.js.map +1 -0
- package/dist/sticky/sticky.d.ts +70 -0
- package/dist/swipe-action/index.d.ts +1 -0
- package/dist/swipe-action/index.js +417 -0
- package/dist/swipe-action/index.js.map +1 -0
- package/dist/swipe-action/swipe-action.d.ts +148 -0
- package/dist/swiper/gesture.d.ts +32 -0
- package/dist/swiper/index.d.ts +1 -0
- package/dist/swiper/index.js +2 -0
- package/dist/swiper/swiper.d.ts +177 -0
- package/dist/swiper-BKivDkHp.js +550 -0
- package/dist/swiper-BKivDkHp.js.map +1 -0
- package/dist/switch/index.d.ts +1 -0
- package/dist/switch/index.js +168 -0
- package/dist/switch/index.js.map +1 -0
- package/dist/switch/switch.d.ts +142 -0
- package/dist/tabbar/index.d.ts +1 -0
- package/dist/tabbar/index.js +95 -0
- package/dist/tabbar/index.js.map +1 -0
- package/dist/tabbar/tabbar.d.ts +119 -0
- package/dist/tabs/index.js +22 -1
- package/dist/tabs/index.js.map +1 -1
- package/dist/tabs/tabs.d.ts +12 -8
- package/dist/tag/index.js +123 -2
- package/dist/tag/index.js.map +1 -1
- package/dist/tag/tag.d.ts +67 -1
- package/dist/textarea/index.d.ts +2 -0
- package/dist/textarea/index.js +2 -242
- package/dist/textarea/platform.d.ts +22 -0
- package/dist/textarea/textarea.d.ts +169 -46
- package/dist/textarea-qbnruDUG.js +775 -0
- package/dist/textarea-qbnruDUG.js.map +1 -0
- package/dist/time-picker/index.d.ts +1 -0
- package/dist/time-picker/index.js +228 -0
- package/dist/time-picker/index.js.map +1 -0
- package/dist/time-picker/time-picker.d.ts +83 -0
- package/dist/timeline/index.d.ts +1 -0
- package/dist/timeline/index.js +131 -0
- package/dist/timeline/index.js.map +1 -0
- package/dist/timeline/timeline.d.ts +79 -0
- package/dist/toast/index.js +47 -4
- package/dist/toast/index.js.map +1 -1
- package/dist/toast/toast.d.ts +26 -3
- package/dist/top-bar/index.js +16 -2
- package/dist/top-bar/index.js.map +1 -1
- package/dist/top-bar/top-bar.d.ts +13 -2
- package/dist/tree-select/index.d.ts +1 -0
- package/dist/tree-select/index.js +512 -0
- package/dist/tree-select/index.js.map +1 -0
- package/dist/tree-select/tree-select.d.ts +215 -0
- package/dist/typography/index.d.ts +1 -0
- package/dist/typography/index.js +82 -0
- package/dist/typography/index.js.map +1 -0
- package/dist/typography/typography.d.ts +54 -0
- package/dist/upload/index.d.ts +1 -0
- package/dist/upload/index.js +458 -0
- package/dist/upload/index.js.map +1 -0
- package/dist/upload/upload.d.ts +172 -0
- package/dist/virtual-list/index.d.ts +1 -0
- package/dist/virtual-list/index.js +445 -0
- package/dist/virtual-list/index.js.map +1 -0
- package/dist/virtual-list/virtual-list.d.ts +160 -0
- package/dist/visual-manifest.d.ts +27 -0
- package/dist/watermark/index.d.ts +1 -0
- package/dist/watermark/index.js +260 -0
- package/dist/watermark/index.js.map +1 -0
- package/dist/watermark/watermark.d.ts +106 -0
- package/package.json +417 -44
- package/dist/empty/index.js.map +0 -1
- package/dist/icon/index.js.map +0 -1
- package/dist/textarea/index.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/back-top/back-top.ts"],"sourcesContent":["import { createMachine, type Machine, type Service } from \"@zag-js/core\";\nimport type { NormalizeProps, PropTypes } from \"@zag-js/types\";\nimport { resolveIconState, type IconState } from \"../icon/index.js\";\n\n/** Stable DOM parts shared by every adapter. */\nexport const BACK_TOP_PARTS = [\"root\", \"icon\", \"label\"] as const;\n/** SSR-safe input shared by all adapters. */\nexport interface QwBackTopProps {\n /** Page-unique instance identity; adapters generate one when omitted. */\n id?: string;\n /** Accessible button name; defaults to 回到顶部. */\n label?: string;\n /** Show the visible label next to the icon; the name is always present. */\n showLabel?: boolean;\n /** Scroll distance in CSS pixels after which the button appears; defaults to 400. */\n visibilityHeight?: number;\n /** Element id of the scrolling container; omitted or missing means the document scroller. */\n target?: string;\n /** Called once per activation, after the scroll request is issued. */\n onActivate?: () => void;\n}\nexport interface ResolvedBackTopState { label: string; showLabel: boolean; visibilityHeight: number; target: string | undefined }\nexport function resolveBackTopState(props: QwBackTopProps = {}): ResolvedBackTopState {\n const height = props.visibilityHeight;\n return { label: typeof props.label === \"string\" && props.label.trim() ? props.label : \"回到顶部\", showLabel: !!props.showLabel,\n visibilityHeight: typeof height === \"number\" && Number.isFinite(height) && height >= 0 ? height : 400,\n target: typeof props.target === \"string\" && props.target.trim() ? props.target : undefined };\n}\n/** Visible above the threshold; a focused button is never hidden under the user. */\nexport function isBackTopShown(state: ResolvedBackTopState, scrollTop: number, focused: boolean): boolean {\n return focused || scrollTop >= Math.max(1, state.visibilityHeight);\n}\nexport function createBackTopProps(props: QwBackTopProps = {}): QwBackTopProps {\n if (props.id !== undefined && (typeof props.id !== \"string\" || !props.id.trim())) throw new TypeError(\"BackTop requires a nonempty instance id when provided\");\n return { ...props };\n}\n\nexport interface QwBackTopSchema {\n props: QwBackTopProps;\n context: { scrollTop: number; focused: boolean };\n refs: { schedule: (() => void) | null };\n state: \"ready\";\n action: \"setScroll\" | \"setFocused\" | \"scrollToTop\" | \"remeasure\";\n effect: \"trackScroll\";\n event: { type: \"SCROLL.SET\"; scrollTop: number } | { type: \"FOCUS.SET\"; focused: boolean } | { type: \"ACTIVATE\" };\n}\nexport type QwBackTopMachine = Machine<QwBackTopSchema>;\nexport type QwBackTopService = Service<QwBackTopSchema>;\nconst rootId = (scope: QwBackTopService[\"scope\"]) => `back-top:${scope.id}`;\nconst live = (service: Pick<QwBackTopService, \"prop\">) => resolveBackTopState({ label: service.prop(\"label\"), showLabel: service.prop(\"showLabel\"), visibilityHeight: service.prop(\"visibilityHeight\"), target: service.prop(\"target\") });\n\n/** Platform boundary: the element id is looked up in the button's own root node. */\nfunction resolveScroller(root: HTMLElement, state: ResolvedBackTopState): { node: HTMLElement | null; events: EventTarget } {\n const win = root.ownerDocument.defaultView!;\n const owner = root.getRootNode() as Document | ShadowRoot;\n const found = state.target ? owner.getElementById?.(state.target) ?? root.ownerDocument.getElementById(state.target) : null;\n return found ? { node: found, events: found } : { node: null, events: win };\n}\nfunction readScrollTop(root: HTMLElement, node: HTMLElement | null): number {\n if (node) return node.scrollTop;\n const win = root.ownerDocument.defaultView;\n return win?.scrollY ?? root.ownerDocument.documentElement.scrollTop;\n}\n\n/** Core owns listening, threshold decisions, reduced-motion scrolling and cleanup. */\nexport const backTopMachine: QwBackTopMachine = createMachine<QwBackTopSchema>({\n props: ({ props }) => createBackTopProps(props), initialState: () => \"ready\", states: { ready: {} },\n context: ({ bindable }) => ({ scrollTop: bindable(() => ({ defaultValue: 0 })), focused: bindable(() => ({ defaultValue: false })) }),\n refs: () => ({ schedule: null }),\n watch({ track, prop, action }) { track([() => prop(\"target\"), () => prop(\"visibilityHeight\")], () => action([\"remeasure\"])); },\n on: { \"SCROLL.SET\": { actions: [\"setScroll\"] }, \"FOCUS.SET\": { actions: [\"setFocused\"] }, ACTIVATE: { actions: [\"scrollToTop\"] } },\n effects: [\"trackScroll\"],\n implementations: {\n actions: {\n setScroll(params) { if (params.event.type === \"SCROLL.SET\") params.context.set(\"scrollTop\", params.event.scrollTop); },\n setFocused(params) { if (params.event.type === \"FOCUS.SET\") params.context.set(\"focused\", params.event.focused); },\n remeasure(params) { params.refs.get(\"schedule\")?.(); },\n scrollToTop({ scope, prop }) {\n const root = scope.getById<HTMLElement>(rootId(scope)), win = root?.ownerDocument.defaultView;\n if (root && win) {\n const reduce = win.matchMedia?.(\"(prefers-reduced-motion: reduce)\").matches ?? false;\n const { node } = resolveScroller(root, live({ prop }));\n const options: ScrollToOptions = { top: 0, behavior: reduce ? \"auto\" : \"smooth\" };\n if (node) node.scrollTo?.(options); else win.scrollTo?.(options);\n }\n prop(\"onActivate\")?.();\n },\n },\n effects: { trackScroll({ scope, prop, send, refs, context }) {\n const root = scope.getById<HTMLElement>(rootId(scope)), win = root?.ownerDocument.defaultView;\n if (!root || !win) return;\n let frame = 0, events: EventTarget | null = null, node: HTMLElement | null = null, disposed = false;\n const run = () => {\n frame = 0; if (disposed) return;\n const next = resolveScroller(root, live({ prop }));\n if (next.events !== events) { events?.removeEventListener(\"scroll\", schedule); events = next.events; node = next.node; events.addEventListener(\"scroll\", schedule, { passive: true }); }\n const top = readScrollTop(root, node);\n if (top !== context.get(\"scrollTop\")) send({ type: \"SCROLL.SET\", scrollTop: top });\n };\n function schedule() { if (!frame && !disposed) frame = win!.requestAnimationFrame(run); }\n refs.set(\"schedule\", schedule); run();\n return () => { disposed = true; refs.set(\"schedule\", null); if (frame) win.cancelAnimationFrame(frame); events?.removeEventListener(\"scroll\", schedule); };\n } },\n },\n});\n\nexport interface QwBackTopApi<T extends PropTypes = PropTypes> {\n shown: boolean; label: string; showLabel: boolean;\n activate(): void;\n getRootProps(): T[\"button\"];\n getIconProps(): T[\"element\"];\n getIconState(): IconState;\n getLabelProps(): T[\"element\"];\n}\n/** Framework/native event shape; only cancellation is read. */\nexport interface BackTopDomEvent { readonly defaultPrevented: boolean }\ntype BackTopCallerHandler = (event: BackTopDomEvent) => void;\n/** Caller root handlers run first; Core then activates (unless prevented) and always tracks focus. Method syntax keeps framework handlers assignable. */\nexport interface BackTopConnectOptions {\n onClick?(event: BackTopDomEvent): void;\n onFocus?(event: BackTopDomEvent): void;\n onBlur?(event: BackTopDomEvent): void;\n}\nconst callAll = (handlers: unknown, event: BackTopDomEvent) => {\n for (const handler of Array.isArray(handlers) ? handlers : [handlers]) if (typeof handler === \"function\") (handler as BackTopCallerHandler)(event);\n};\nexport function connectBackTop<T extends PropTypes>(service: QwBackTopService, normalize: NormalizeProps<T>, options: BackTopConnectOptions = {}): QwBackTopApi<T> {\n const state = live(service), id = rootId(service.scope);\n const shown = isBackTopShown(state, service.context.get(\"scrollTop\"), service.context.get(\"focused\"));\n const activate = () => service.send({ type: \"ACTIVATE\" });\n return {\n shown, label: state.label, showLabel: state.showLabel, activate,\n getRootProps: () => normalize.button({ \"data-scope\": \"back-top\", \"data-part\": \"root\", id, type: \"button\", hidden: !shown || undefined, \"data-state\": shown ? \"visible\" : \"hidden\",\n \"data-show-label\": state.showLabel ? \"true\" : undefined, \"aria-label\": state.showLabel ? undefined : state.label,\n onClick(event: BackTopDomEvent) { callAll(options.onClick, event); if (!event.defaultPrevented) activate(); },\n onFocus(event: BackTopDomEvent) { callAll(options.onFocus, event); service.send({ type: \"FOCUS.SET\", focused: true }); },\n onBlur(event: BackTopDomEvent) { callAll(options.onBlur, event); service.send({ type: \"FOCUS.SET\", focused: false }); } }),\n getIconProps: () => normalize.element({ \"data-scope\": \"back-top\", \"data-part\": \"icon\", \"aria-hidden\": true }),\n getIconState: () => resolveIconState({ id: `${id}:icon`, name: \"to-top\" }),\n getLabelProps: () => normalize.element({ \"data-scope\": \"back-top\", \"data-part\": \"label\", hidden: !state.showLabel || undefined }),\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Badge 契约 — 原型 A(无状态),core 无 machine,
|
|
3
|
+
* 承载双栈共享的类型契约与纯函数状态解析(SSR-safe,无 DOM 依赖)。
|
|
4
|
+
* 渲染契约:`data-scope="badge"`,`data-part="root"`;
|
|
5
|
+
* `data-variant` / `data-kind` 摊平枚举。
|
|
6
|
+
*
|
|
7
|
+
* 变体 / 形态 / 部位词表以运行时常量数组为唯一事实源(类型从常量推导),__test__ 直接锁死。
|
|
8
|
+
*/
|
|
9
|
+
/** 视觉变体全集:solid 强提示(默认)/ subtle 弱提示。 */
|
|
10
|
+
export declare const BADGE_VARIANTS: readonly ["solid", "subtle"];
|
|
11
|
+
/** 形态全集:number 数字(默认)/ dot 纯红点。 */
|
|
12
|
+
export declare const BADGE_KINDS: readonly ["number", "dot"];
|
|
13
|
+
/** Badge 各渲染部位全集(data-part 取值)。 */
|
|
14
|
+
export declare const BADGE_PARTS: readonly ["root"];
|
|
15
|
+
/** 默认溢出阈值:数值超过时收敛为「99+」。 */
|
|
16
|
+
export declare const DEFAULT_BADGE_MAX_COUNT = 99;
|
|
17
|
+
export type BadgeVariant = (typeof BADGE_VARIANTS)[number];
|
|
18
|
+
export type BadgeKind = (typeof BADGE_KINDS)[number];
|
|
19
|
+
export type BadgePart = (typeof BADGE_PARTS)[number];
|
|
20
|
+
/**
|
|
21
|
+
* QwBadgeProps — 双栈共享的行为契约(全字段可选)。
|
|
22
|
+
* 视觉完全由语义令牌驱动,组件不开放自定义色值入口。
|
|
23
|
+
*/
|
|
24
|
+
export interface QwBadgeProps {
|
|
25
|
+
/** 视觉变体,默认 solid;dot 形态强制 solid。 */
|
|
26
|
+
variant?: BadgeVariant;
|
|
27
|
+
/** 纯红点形态,默认 false;为 true 时优先于 count。 */
|
|
28
|
+
dot?: boolean;
|
|
29
|
+
/** 未读数量;≤0 / 非有限数值不渲染。 */
|
|
30
|
+
count?: number;
|
|
31
|
+
/** 溢出阈值,默认 99;非法值(≤0 或非整数)回退默认。 */
|
|
32
|
+
maxCount?: number;
|
|
33
|
+
/** 自定义无障碍播报文案,全量覆盖默认文案。 */
|
|
34
|
+
ariaLabel?: string;
|
|
35
|
+
}
|
|
36
|
+
/** 适配层从 locale 传入的默认播报文案。 */
|
|
37
|
+
export interface BadgeAriaTexts {
|
|
38
|
+
/** 数字形态播报模板,含 {count} 占位符。 */
|
|
39
|
+
unreadAriaTemplate: string;
|
|
40
|
+
/** 纯红点形态播报文案。 */
|
|
41
|
+
dotAria: string;
|
|
42
|
+
}
|
|
43
|
+
/** resolveBadgeState 的解析结果,适配层据此摊平渲染。 */
|
|
44
|
+
export interface ResolvedBadgeState {
|
|
45
|
+
/** 是否渲染徽标本体;false 时双栈一致返回空渲染。 */
|
|
46
|
+
visible: boolean;
|
|
47
|
+
/** 形态。 */
|
|
48
|
+
kind: BadgeKind;
|
|
49
|
+
/** 解析后的视觉变体(dot + subtle 已降级为 solid)。 */
|
|
50
|
+
variant: BadgeVariant;
|
|
51
|
+
/** 可见文本(溢出为「<阈值>+」;dot / 不可见为空串)。 */
|
|
52
|
+
label: string;
|
|
53
|
+
/** 数值是否超过阈值。 */
|
|
54
|
+
overflow: boolean;
|
|
55
|
+
/** 解析后的生效阈值。 */
|
|
56
|
+
maxCount: number;
|
|
57
|
+
/** 生效的无障碍播报文案。 */
|
|
58
|
+
ariaLabel: string;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 纯函数:props + 文案 → 解析结果。
|
|
62
|
+
* 规则:dot 优先于 count;dot 强制 solid;数值四舍五入;
|
|
63
|
+
* ≤0 / NaN / Infinity 不渲染;溢出渲染「<阈值>+」。
|
|
64
|
+
*/
|
|
65
|
+
export declare function resolveBadgeState(props: QwBadgeProps, texts: BadgeAriaTexts): ResolvedBadgeState;
|
|
66
|
+
/** 根元素 prop-getter 返回的 DOM 属性集。 */
|
|
67
|
+
export interface BadgeRootProps {
|
|
68
|
+
"data-scope": "badge";
|
|
69
|
+
"data-part": "root";
|
|
70
|
+
"data-variant": BadgeVariant;
|
|
71
|
+
"data-kind": BadgeKind;
|
|
72
|
+
role: "status";
|
|
73
|
+
"aria-label": string;
|
|
74
|
+
}
|
|
75
|
+
/** 根元素 prop-getter:摊平 data 状态属性 + role="status" + 播报文案。 */
|
|
76
|
+
export declare function getBadgeRootProps(state: ResolvedBadgeState): BadgeRootProps;
|
|
77
|
+
/** Passive root retained by native hosts even when no badge is visible. */
|
|
78
|
+
export interface BadgeRetainedRootProps extends Omit<BadgeRootProps, "role" | "aria-label"> {
|
|
79
|
+
role?: "status";
|
|
80
|
+
"aria-label"?: string;
|
|
81
|
+
hidden?: true;
|
|
82
|
+
"aria-hidden"?: "true";
|
|
83
|
+
}
|
|
84
|
+
/** Keep visibility and announcement decisions in Core while retaining the DOM root. */
|
|
85
|
+
export declare function getBadgeRetainedRootProps(state: ResolvedBadgeState, hidden?: boolean): BadgeRetainedRootProps;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./badge.js";
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
//#region src/badge/badge.ts
|
|
2
|
+
/**
|
|
3
|
+
* Badge 契约 — 原型 A(无状态),core 无 machine,
|
|
4
|
+
* 承载双栈共享的类型契约与纯函数状态解析(SSR-safe,无 DOM 依赖)。
|
|
5
|
+
* 渲染契约:`data-scope="badge"`,`data-part="root"`;
|
|
6
|
+
* `data-variant` / `data-kind` 摊平枚举。
|
|
7
|
+
*
|
|
8
|
+
* 变体 / 形态 / 部位词表以运行时常量数组为唯一事实源(类型从常量推导),__test__ 直接锁死。
|
|
9
|
+
*/
|
|
10
|
+
/** 视觉变体全集:solid 强提示(默认)/ subtle 弱提示。 */
|
|
11
|
+
const BADGE_VARIANTS = ["solid", "subtle"];
|
|
12
|
+
/** 形态全集:number 数字(默认)/ dot 纯红点。 */
|
|
13
|
+
const BADGE_KINDS = ["number", "dot"];
|
|
14
|
+
/** Badge 各渲染部位全集(data-part 取值)。 */
|
|
15
|
+
const BADGE_PARTS = ["root"];
|
|
16
|
+
/** 默认溢出阈值:数值超过时收敛为「99+」。 */
|
|
17
|
+
const DEFAULT_BADGE_MAX_COUNT = 99;
|
|
18
|
+
/** 非法阈值(≤0 或非整数)一律回退默认值,避免非法配置导致空渲染。 */
|
|
19
|
+
function resolveMaxCount(maxCount) {
|
|
20
|
+
return typeof maxCount === "number" && Number.isInteger(maxCount) && maxCount > 0 ? maxCount : 99;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 纯函数:props + 文案 → 解析结果。
|
|
24
|
+
* 规则:dot 优先于 count;dot 强制 solid;数值四舍五入;
|
|
25
|
+
* ≤0 / NaN / Infinity 不渲染;溢出渲染「<阈值>+」。
|
|
26
|
+
*/
|
|
27
|
+
function resolveBadgeState(props, texts) {
|
|
28
|
+
const { variant = "solid", dot = false, count, maxCount, ariaLabel } = props;
|
|
29
|
+
const safeMax = resolveMaxCount(maxCount);
|
|
30
|
+
if (dot) return {
|
|
31
|
+
visible: true,
|
|
32
|
+
kind: "dot",
|
|
33
|
+
variant: "solid",
|
|
34
|
+
label: "",
|
|
35
|
+
overflow: false,
|
|
36
|
+
maxCount: safeMax,
|
|
37
|
+
ariaLabel: ariaLabel ?? texts.dotAria
|
|
38
|
+
};
|
|
39
|
+
const normalized = typeof count === "number" && Number.isFinite(count) && count > 0 ? Math.round(count) : 0;
|
|
40
|
+
if (normalized === 0) return {
|
|
41
|
+
visible: false,
|
|
42
|
+
kind: "number",
|
|
43
|
+
variant,
|
|
44
|
+
label: "",
|
|
45
|
+
overflow: false,
|
|
46
|
+
maxCount: safeMax,
|
|
47
|
+
ariaLabel: ""
|
|
48
|
+
};
|
|
49
|
+
const overflow = normalized > safeMax;
|
|
50
|
+
const label = overflow ? `${safeMax}+` : `${normalized}`;
|
|
51
|
+
return {
|
|
52
|
+
visible: true,
|
|
53
|
+
kind: "number",
|
|
54
|
+
variant,
|
|
55
|
+
label,
|
|
56
|
+
overflow,
|
|
57
|
+
maxCount: safeMax,
|
|
58
|
+
ariaLabel: ariaLabel ?? texts.unreadAriaTemplate.replaceAll("{count}", label)
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/** 根元素 prop-getter:摊平 data 状态属性 + role="status" + 播报文案。 */
|
|
62
|
+
function getBadgeRootProps(state) {
|
|
63
|
+
return {
|
|
64
|
+
"data-scope": "badge",
|
|
65
|
+
"data-part": "root",
|
|
66
|
+
"data-variant": state.variant,
|
|
67
|
+
"data-kind": state.kind,
|
|
68
|
+
role: "status",
|
|
69
|
+
"aria-label": state.ariaLabel
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/** Keep visibility and announcement decisions in Core while retaining the DOM root. */
|
|
73
|
+
function getBadgeRetainedRootProps(state, hidden = false) {
|
|
74
|
+
const root = getBadgeRootProps(state);
|
|
75
|
+
if (!hidden && state.visible) return root;
|
|
76
|
+
const retained = {
|
|
77
|
+
...root,
|
|
78
|
+
hidden: true,
|
|
79
|
+
"aria-hidden": "true"
|
|
80
|
+
};
|
|
81
|
+
delete retained.role;
|
|
82
|
+
delete retained["aria-label"];
|
|
83
|
+
return retained;
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
export { BADGE_KINDS, BADGE_PARTS, BADGE_VARIANTS, DEFAULT_BADGE_MAX_COUNT, getBadgeRetainedRootProps, getBadgeRootProps, resolveBadgeState };
|
|
87
|
+
|
|
88
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/badge/badge.ts"],"sourcesContent":["/**\n * Badge 契约 — 原型 A(无状态),core 无 machine,\n * 承载双栈共享的类型契约与纯函数状态解析(SSR-safe,无 DOM 依赖)。\n * 渲染契约:`data-scope=\"badge\"`,`data-part=\"root\"`;\n * `data-variant` / `data-kind` 摊平枚举。\n *\n * 变体 / 形态 / 部位词表以运行时常量数组为唯一事实源(类型从常量推导),__test__ 直接锁死。\n */\n\n/** 视觉变体全集:solid 强提示(默认)/ subtle 弱提示。 */\nexport const BADGE_VARIANTS = [\"solid\", \"subtle\"] as const;\n\n/** 形态全集:number 数字(默认)/ dot 纯红点。 */\nexport const BADGE_KINDS = [\"number\", \"dot\"] as const;\n\n/** Badge 各渲染部位全集(data-part 取值)。 */\nexport const BADGE_PARTS = [\"root\"] as const;\n\n/** 默认溢出阈值:数值超过时收敛为「99+」。 */\nexport const DEFAULT_BADGE_MAX_COUNT = 99;\n\nexport type BadgeVariant = (typeof BADGE_VARIANTS)[number];\nexport type BadgeKind = (typeof BADGE_KINDS)[number];\nexport type BadgePart = (typeof BADGE_PARTS)[number];\n\n/**\n * QwBadgeProps — 双栈共享的行为契约(全字段可选)。\n * 视觉完全由语义令牌驱动,组件不开放自定义色值入口。\n */\nexport interface QwBadgeProps {\n /** 视觉变体,默认 solid;dot 形态强制 solid。 */\n variant?: BadgeVariant;\n /** 纯红点形态,默认 false;为 true 时优先于 count。 */\n dot?: boolean;\n /** 未读数量;≤0 / 非有限数值不渲染。 */\n count?: number;\n /** 溢出阈值,默认 99;非法值(≤0 或非整数)回退默认。 */\n maxCount?: number;\n /** 自定义无障碍播报文案,全量覆盖默认文案。 */\n ariaLabel?: string;\n}\n\n/** 适配层从 locale 传入的默认播报文案。 */\nexport interface BadgeAriaTexts {\n /** 数字形态播报模板,含 {count} 占位符。 */\n unreadAriaTemplate: string;\n /** 纯红点形态播报文案。 */\n dotAria: string;\n}\n\n/** resolveBadgeState 的解析结果,适配层据此摊平渲染。 */\nexport interface ResolvedBadgeState {\n /** 是否渲染徽标本体;false 时双栈一致返回空渲染。 */\n visible: boolean;\n /** 形态。 */\n kind: BadgeKind;\n /** 解析后的视觉变体(dot + subtle 已降级为 solid)。 */\n variant: BadgeVariant;\n /** 可见文本(溢出为「<阈值>+」;dot / 不可见为空串)。 */\n label: string;\n /** 数值是否超过阈值。 */\n overflow: boolean;\n /** 解析后的生效阈值。 */\n maxCount: number;\n /** 生效的无障碍播报文案。 */\n ariaLabel: string;\n}\n\n/** 非法阈值(≤0 或非整数)一律回退默认值,避免非法配置导致空渲染。 */\nfunction resolveMaxCount(maxCount: number | undefined): number {\n return typeof maxCount === \"number\" && Number.isInteger(maxCount) && maxCount > 0\n ? maxCount\n : DEFAULT_BADGE_MAX_COUNT;\n}\n\n/**\n * 纯函数:props + 文案 → 解析结果。\n * 规则:dot 优先于 count;dot 强制 solid;数值四舍五入;\n * ≤0 / NaN / Infinity 不渲染;溢出渲染「<阈值>+」。\n */\nexport function resolveBadgeState(\n props: QwBadgeProps,\n texts: BadgeAriaTexts,\n): ResolvedBadgeState {\n const { variant = \"solid\", dot = false, count, maxCount, ariaLabel } = props;\n const safeMax = resolveMaxCount(maxCount);\n\n if (dot) {\n return {\n visible: true,\n kind: \"dot\",\n variant: \"solid\",\n label: \"\",\n overflow: false,\n maxCount: safeMax,\n ariaLabel: ariaLabel ?? texts.dotAria,\n };\n }\n\n const normalized =\n typeof count === \"number\" && Number.isFinite(count) && count > 0\n ? Math.round(count)\n : 0;\n\n if (normalized === 0) {\n return {\n visible: false,\n kind: \"number\",\n variant,\n label: \"\",\n overflow: false,\n maxCount: safeMax,\n ariaLabel: \"\",\n };\n }\n\n const overflow = normalized > safeMax;\n const label = overflow ? `${safeMax}+` : `${normalized}`;\n return {\n visible: true,\n kind: \"number\",\n variant,\n label,\n overflow,\n maxCount: safeMax,\n ariaLabel: ariaLabel ?? texts.unreadAriaTemplate.replaceAll(\"{count}\", label),\n };\n}\n\n/** 根元素 prop-getter 返回的 DOM 属性集。 */\nexport interface BadgeRootProps {\n \"data-scope\": \"badge\";\n \"data-part\": \"root\";\n \"data-variant\": BadgeVariant;\n \"data-kind\": BadgeKind;\n role: \"status\";\n \"aria-label\": string;\n}\n\n/** 根元素 prop-getter:摊平 data 状态属性 + role=\"status\" + 播报文案。 */\nexport function getBadgeRootProps(state: ResolvedBadgeState): BadgeRootProps {\n return {\n \"data-scope\": \"badge\",\n \"data-part\": \"root\",\n \"data-variant\": state.variant,\n \"data-kind\": state.kind,\n role: \"status\",\n \"aria-label\": state.ariaLabel,\n };\n}\n\n/** Passive root retained by native hosts even when no badge is visible. */\nexport interface BadgeRetainedRootProps extends Omit<BadgeRootProps, \"role\" | \"aria-label\"> {\n role?: \"status\";\n \"aria-label\"?: string;\n hidden?: true;\n \"aria-hidden\"?: \"true\";\n}\n\n/** Keep visibility and announcement decisions in Core while retaining the DOM root. */\nexport function getBadgeRetainedRootProps(state: ResolvedBadgeState, hidden = false): BadgeRetainedRootProps {\n const root = getBadgeRootProps(state);\n if (!hidden && state.visible) return root;\n const retained: BadgeRetainedRootProps = { ...root, hidden: true, \"aria-hidden\": \"true\" };\n delete retained.role;\n delete retained[\"aria-label\"];\n return retained;\n}\n"],"mappings":";;;;;;;;;;AAUA,MAAa,iBAAiB,CAAC,SAAS,QAAQ;;AAGhD,MAAa,cAAc,CAAC,UAAU,KAAK;;AAG3C,MAAa,cAAc,CAAC,MAAM;;AAGlC,MAAa,0BAA0B;;AAkDvC,SAAS,gBAAgB,UAAsC;CAC7D,OAAO,OAAO,aAAa,YAAY,OAAO,UAAU,QAAQ,KAAK,WAAW,IAC5E,WAAA;AAEN;;;;;;AAOA,SAAgB,kBACd,OACA,OACoB;CACpB,MAAM,EAAE,UAAU,SAAS,MAAM,OAAO,OAAO,UAAU,cAAc;CACvE,MAAM,UAAU,gBAAgB,QAAQ;CAExC,IAAI,KACF,OAAO;EACL,SAAS;EACT,MAAM;EACN,SAAS;EACT,OAAO;EACP,UAAU;EACV,UAAU;EACV,WAAW,aAAa,MAAM;CAChC;CAGF,MAAM,aACJ,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,KAAK,QAAQ,IAC3D,KAAK,MAAM,KAAK,IAChB;CAEN,IAAI,eAAe,GACjB,OAAO;EACL,SAAS;EACT,MAAM;EACN;EACA,OAAO;EACP,UAAU;EACV,UAAU;EACV,WAAW;CACb;CAGF,MAAM,WAAW,aAAa;CAC9B,MAAM,QAAQ,WAAW,GAAG,QAAQ,KAAK,GAAG;CAC5C,OAAO;EACL,SAAS;EACT,MAAM;EACN;EACA;EACA;EACA,UAAU;EACV,WAAW,aAAa,MAAM,mBAAmB,WAAW,WAAW,KAAK;CAC9E;AACF;;AAaA,SAAgB,kBAAkB,OAA2C;CAC3E,OAAO;EACL,cAAc;EACd,aAAa;EACb,gBAAgB,MAAM;EACtB,aAAa,MAAM;EACnB,MAAM;EACN,cAAc,MAAM;CACtB;AACF;;AAWA,SAAgB,0BAA0B,OAA2B,SAAS,OAA+B;CAC3G,MAAM,OAAO,kBAAkB,KAAK;CACpC,IAAI,CAAC,UAAU,MAAM,SAAS,OAAO;CACrC,MAAM,WAAmC;EAAE,GAAG;EAAM,QAAQ;EAAM,eAAe;CAAO;CACxF,OAAO,SAAS;CAChB,OAAO,SAAS;CAChB,OAAO;AACT"}
|
package/dist/button/button.d.ts
CHANGED
|
@@ -58,6 +58,13 @@ export interface ResolvedButtonState {
|
|
|
58
58
|
warning?: "icon-only-block-ignored";
|
|
59
59
|
type: "button" | "submit" | "reset";
|
|
60
60
|
}
|
|
61
|
+
/** 调用方的展开状态与控制目标;Core 只运输,不持有业务状态。 */
|
|
62
|
+
export interface ButtonControlAria {
|
|
63
|
+
/** Caller-owned disclosure state; absence never implies false. */
|
|
64
|
+
"aria-expanded"?: string | boolean | null;
|
|
65
|
+
/** Caller-owned IDREF list; Core does not inspect or generate target ids. */
|
|
66
|
+
"aria-controls"?: string | null;
|
|
67
|
+
}
|
|
61
68
|
/** Core 生成、由适配器最后覆盖到根元素的属性。 */
|
|
62
69
|
export interface ButtonRootProps {
|
|
63
70
|
type: "button" | "submit" | "reset";
|
|
@@ -75,10 +82,16 @@ export interface ButtonRootProps {
|
|
|
75
82
|
"data-block"?: "true";
|
|
76
83
|
"data-loading"?: "true";
|
|
77
84
|
}
|
|
85
|
+
/** 显式调用方 ARIA 输入的运输输出;旧默认根属性契约保持不变。 */
|
|
86
|
+
export interface ButtonControlRootProps extends ButtonRootProps {
|
|
87
|
+
"aria-expanded"?: string | boolean;
|
|
88
|
+
"aria-controls"?: string;
|
|
89
|
+
}
|
|
78
90
|
/** 将公开输入和内容通道归一化为唯一的跨框架状态。 */
|
|
79
91
|
export declare function resolveButtonState(props?: QwButtonProps, presence?: ButtonContentPresence): ResolvedButtonState;
|
|
80
92
|
/**
|
|
81
93
|
* 将归一化结果转成 root 属性。空闲状态不写入 `aria-busy`,让调用方的合法
|
|
82
94
|
* aria 属性继续透传;busy 状态则由 Core 作为安全属性覆盖。
|
|
83
95
|
*/
|
|
96
|
+
export declare function getButtonRootProps(state: ResolvedButtonState, aria: ButtonControlAria | undefined): ButtonControlRootProps;
|
|
84
97
|
export declare function getButtonRootProps(state: ResolvedButtonState): ButtonRootProps;
|
package/dist/button/index.js
CHANGED
|
@@ -76,15 +76,13 @@ function resolveButtonState(props = {}, presence = EMPTY_PRESENCE) {
|
|
|
76
76
|
type: props.type ?? "button"
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
|
-
|
|
80
|
-
* 将归一化结果转成 root 属性。空闲状态不写入 `aria-busy`,让调用方的合法
|
|
81
|
-
* aria 属性继续透传;busy 状态则由 Core 作为安全属性覆盖。
|
|
82
|
-
*/
|
|
83
|
-
function getButtonRootProps(state) {
|
|
79
|
+
function getButtonRootProps(state, aria = {}) {
|
|
84
80
|
return {
|
|
85
81
|
type: state.type,
|
|
86
82
|
disabled: state.effectiveDisabled,
|
|
87
83
|
...state.loading ? { "aria-busy": true } : {},
|
|
84
|
+
...aria["aria-expanded"] != null ? { "aria-expanded": aria["aria-expanded"] } : {},
|
|
85
|
+
...aria["aria-controls"] != null ? { "aria-controls": aria["aria-controls"] } : {},
|
|
88
86
|
"data-scope": "button",
|
|
89
87
|
"data-part": "root",
|
|
90
88
|
"data-variant": state.variant,
|
package/dist/button/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/button/button.ts"],"sourcesContent":["/**\n * Button 的跨框架行为契约。\n *\n * Button 是无状态的 Prototype A:这里仅归一化公开 props 与内容通道,React/Vue\n * 适配器不得复制 icon-only、disabled 或 block 的组合规则。\n */\n\nexport const BUTTON_VARIANTS = [\"solid\", \"soft\", \"outline\", \"ghost\", \"link\"] as const;\nexport const BUTTON_TONES = [\"brand\", \"neutral\", \"danger\"] as const;\nexport const BUTTON_SIZES = [\"mini\", \"xs\", \"s\", \"normal\", \"m\", \"l\"] as const;\nexport const BUTTON_SHAPES = [\"default\", \"square\", \"round\"] as const;\nexport const BUTTON_ICON_POSITIONS = [\"start\", \"end\"] as const;\nexport const BUTTON_PARTS = [\"root\", \"content\", \"icon\", \"label\", \"spinner\"] as const;\n\nexport type ButtonVariant = (typeof BUTTON_VARIANTS)[number];\nexport type ButtonTone = (typeof BUTTON_TONES)[number];\nexport type ButtonSize = (typeof BUTTON_SIZES)[number];\nexport type ButtonShape = (typeof BUTTON_SHAPES)[number];\nexport type ButtonIconPosition = (typeof BUTTON_ICON_POSITIONS)[number];\nexport type ButtonPart = (typeof BUTTON_PARTS)[number];\n\n/** 双栈共享的标量 props;框架特有的内容通道不进入 Core。 */\nexport interface QwButtonProps {\n /** 视觉层级,默认 `solid`。 */\n variant?: ButtonVariant;\n /** 语气,默认 `brand`。 */\n tone?: ButtonTone;\n /** 尺寸,默认 `normal`。 */\n size?: ButtonSize;\n /** 外形,默认 `default`。 */\n shape?: ButtonShape;\n /** 图标与默认内容同时存在时的视觉位置,默认 `start`。 */\n iconPosition?: ButtonIconPosition;\n /** 有默认内容时撑满容器可用宽度。 */\n block?: boolean;\n /** 忙碌时保持内容、显示 spinner 并禁用原生 button。 */\n loading?: boolean;\n /** 原生禁用状态。 */\n disabled?: boolean;\n /** 原生 button 类型,默认 `button`。 */\n type?: \"button\" | \"submit\" | \"reset\";\n}\n\n/** 由各框架的内容通道存在性计算;不检查 DOM 或 VNode 内容。 */\nexport interface ButtonContentPresence {\n hasIcon: boolean;\n hasContent: boolean;\n}\n\n/** 适配器唯一可消费的归一化结果。 */\nexport interface ResolvedButtonState {\n variant: ButtonVariant;\n tone: ButtonTone;\n size: ButtonSize;\n shape: ButtonShape;\n iconPosition: ButtonIconPosition;\n hasIcon: boolean;\n hasContent: boolean;\n iconOnly: boolean;\n loading: boolean;\n effectiveDisabled: boolean;\n effectiveBlock: boolean;\n warning?: \"icon-only-block-ignored\";\n type: \"button\" | \"submit\" | \"reset\";\n}\n\n/** Core 生成、由适配器最后覆盖到根元素的属性。 */\nexport interface ButtonRootProps {\n type: \"button\" | \"submit\" | \"reset\";\n disabled: boolean;\n \"aria-busy\"?: true;\n \"data-scope\": \"button\";\n \"data-part\": \"root\";\n \"data-variant\": ButtonVariant;\n \"data-tone\": ButtonTone;\n \"data-size\": ButtonSize;\n \"data-shape\": ButtonShape;\n \"data-icon-position\": ButtonIconPosition;\n \"data-has-icon\"?: \"true\";\n \"data-icon-only\"?: \"true\";\n \"data-block\"?: \"true\";\n \"data-loading\"?: \"true\";\n}\n\nconst EMPTY_PRESENCE: ButtonContentPresence = { hasIcon: false, hasContent: false };\nconst BUILD_MODE = (import.meta as ImportMeta & { env?: { MODE?: string } }).env?.MODE;\n\n/**\n * 诊断只属于明确的开发环境。Vite 会在浏览器构建中提供 `import.meta.env.MODE`;\n * 未注入 process/env 的已发布浏览器产物默认静默,避免生产控制台噪音。\n */\nfunction isDevelopmentBuild(): boolean {\n if (BUILD_MODE != null) return BUILD_MODE !== \"production\";\n\n const nodeEnv = (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process?.env?.NODE_ENV;\n return nodeEnv === \"development\" || nodeEnv === \"test\";\n}\n\n/** 将公开输入和内容通道归一化为唯一的跨框架状态。 */\nexport function resolveButtonState(\n props: QwButtonProps = {},\n presence: ButtonContentPresence = EMPTY_PRESENCE,\n): ResolvedButtonState {\n const hasIcon = presence.hasIcon;\n const hasContent = presence.hasContent;\n const iconOnly = hasIcon && !hasContent;\n const loading = props.loading ?? false;\n const effectiveDisabled = (props.disabled ?? false) || loading;\n const effectiveBlock = (props.block ?? false) && !iconOnly;\n\n return {\n variant: props.variant ?? \"solid\",\n tone: props.tone ?? \"brand\",\n size: props.size ?? \"normal\",\n shape: props.shape ?? \"default\",\n iconPosition: props.iconPosition ?? \"start\",\n hasIcon,\n hasContent,\n iconOnly,\n loading,\n effectiveDisabled,\n effectiveBlock,\n ...(iconOnly && props.block && isDevelopmentBuild()\n ? { warning: \"icon-only-block-ignored\" as const }\n : {}),\n type: props.type ?? \"button\",\n };\n}\n\n/**\n * 将归一化结果转成 root 属性。空闲状态不写入 `aria-busy`,让调用方的合法\n * aria 属性继续透传;busy 状态则由 Core 作为安全属性覆盖。\n */\nexport function getButtonRootProps(state: ResolvedButtonState): ButtonRootProps {\n return {\n type: state.type,\n disabled: state.effectiveDisabled,\n ...(state.loading ? { \"aria-busy\": true as const } : {}),\n \"data-scope\": \"button\",\n \"data-part\": \"root\",\n \"data-variant\": state.variant,\n \"data-tone\": state.tone,\n \"data-size\": state.size,\n \"data-shape\": state.shape,\n \"data-icon-position\": state.iconPosition,\n ...(state.hasIcon ? { \"data-has-icon\": \"true\" as const } : {}),\n ...(state.iconOnly ? { \"data-icon-only\": \"true\" as const } : {}),\n ...(state.effectiveBlock ? { \"data-block\": \"true\" as const } : {}),\n ...(state.loading ? { \"data-loading\": \"true\" as const } : {}),\n };\n}\n"],"mappings":";;;;;;;AAOA,MAAa,kBAAkB;CAAC;CAAS;CAAQ;CAAW;CAAS;AAAM;AAC3E,MAAa,eAAe;CAAC;CAAS;CAAW;AAAQ;AACzD,MAAa,eAAe;CAAC;CAAQ;CAAM;CAAK;CAAU;CAAK;AAAG;AAClE,MAAa,gBAAgB;CAAC;CAAW;CAAU;AAAO;AAC1D,MAAa,wBAAwB,CAAC,SAAS,KAAK;AACpD,MAAa,eAAe;CAAC;CAAQ;CAAW;CAAQ;CAAS;AAAS;
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/button/button.ts"],"sourcesContent":["/**\n * Button 的跨框架行为契约。\n *\n * Button 是无状态的 Prototype A:这里仅归一化公开 props 与内容通道,React/Vue\n * 适配器不得复制 icon-only、disabled 或 block 的组合规则。\n */\n\nexport const BUTTON_VARIANTS = [\"solid\", \"soft\", \"outline\", \"ghost\", \"link\"] as const;\nexport const BUTTON_TONES = [\"brand\", \"neutral\", \"danger\"] as const;\nexport const BUTTON_SIZES = [\"mini\", \"xs\", \"s\", \"normal\", \"m\", \"l\"] as const;\nexport const BUTTON_SHAPES = [\"default\", \"square\", \"round\"] as const;\nexport const BUTTON_ICON_POSITIONS = [\"start\", \"end\"] as const;\nexport const BUTTON_PARTS = [\"root\", \"content\", \"icon\", \"label\", \"spinner\"] as const;\n\nexport type ButtonVariant = (typeof BUTTON_VARIANTS)[number];\nexport type ButtonTone = (typeof BUTTON_TONES)[number];\nexport type ButtonSize = (typeof BUTTON_SIZES)[number];\nexport type ButtonShape = (typeof BUTTON_SHAPES)[number];\nexport type ButtonIconPosition = (typeof BUTTON_ICON_POSITIONS)[number];\nexport type ButtonPart = (typeof BUTTON_PARTS)[number];\n\n/** 双栈共享的标量 props;框架特有的内容通道不进入 Core。 */\nexport interface QwButtonProps {\n /** 视觉层级,默认 `solid`。 */\n variant?: ButtonVariant;\n /** 语气,默认 `brand`。 */\n tone?: ButtonTone;\n /** 尺寸,默认 `normal`。 */\n size?: ButtonSize;\n /** 外形,默认 `default`。 */\n shape?: ButtonShape;\n /** 图标与默认内容同时存在时的视觉位置,默认 `start`。 */\n iconPosition?: ButtonIconPosition;\n /** 有默认内容时撑满容器可用宽度。 */\n block?: boolean;\n /** 忙碌时保持内容、显示 spinner 并禁用原生 button。 */\n loading?: boolean;\n /** 原生禁用状态。 */\n disabled?: boolean;\n /** 原生 button 类型,默认 `button`。 */\n type?: \"button\" | \"submit\" | \"reset\";\n}\n\n/** 由各框架的内容通道存在性计算;不检查 DOM 或 VNode 内容。 */\nexport interface ButtonContentPresence {\n hasIcon: boolean;\n hasContent: boolean;\n}\n\n/** 适配器唯一可消费的归一化结果。 */\nexport interface ResolvedButtonState {\n variant: ButtonVariant;\n tone: ButtonTone;\n size: ButtonSize;\n shape: ButtonShape;\n iconPosition: ButtonIconPosition;\n hasIcon: boolean;\n hasContent: boolean;\n iconOnly: boolean;\n loading: boolean;\n effectiveDisabled: boolean;\n effectiveBlock: boolean;\n warning?: \"icon-only-block-ignored\";\n type: \"button\" | \"submit\" | \"reset\";\n}\n\n/** 调用方的展开状态与控制目标;Core 只运输,不持有业务状态。 */\nexport interface ButtonControlAria {\n /** Caller-owned disclosure state; absence never implies false. */\n \"aria-expanded\"?: string | boolean | null;\n /** Caller-owned IDREF list; Core does not inspect or generate target ids. */\n \"aria-controls\"?: string | null;\n}\n\n/** Core 生成、由适配器最后覆盖到根元素的属性。 */\nexport interface ButtonRootProps {\n type: \"button\" | \"submit\" | \"reset\";\n disabled: boolean;\n \"aria-busy\"?: true;\n \"data-scope\": \"button\";\n \"data-part\": \"root\";\n \"data-variant\": ButtonVariant;\n \"data-tone\": ButtonTone;\n \"data-size\": ButtonSize;\n \"data-shape\": ButtonShape;\n \"data-icon-position\": ButtonIconPosition;\n \"data-has-icon\"?: \"true\";\n \"data-icon-only\"?: \"true\";\n \"data-block\"?: \"true\";\n \"data-loading\"?: \"true\";\n}\n\n/** 显式调用方 ARIA 输入的运输输出;旧默认根属性契约保持不变。 */\nexport interface ButtonControlRootProps extends ButtonRootProps {\n \"aria-expanded\"?: string | boolean;\n \"aria-controls\"?: string;\n}\n\nconst EMPTY_PRESENCE: ButtonContentPresence = { hasIcon: false, hasContent: false };\nconst BUILD_MODE = (import.meta as ImportMeta & { env?: { MODE?: string } }).env?.MODE;\n\n/**\n * 诊断只属于明确的开发环境。Vite 会在浏览器构建中提供 `import.meta.env.MODE`;\n * 未注入 process/env 的已发布浏览器产物默认静默,避免生产控制台噪音。\n */\nfunction isDevelopmentBuild(): boolean {\n if (BUILD_MODE != null) return BUILD_MODE !== \"production\";\n\n const nodeEnv = (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process?.env?.NODE_ENV;\n return nodeEnv === \"development\" || nodeEnv === \"test\";\n}\n\n/** 将公开输入和内容通道归一化为唯一的跨框架状态。 */\nexport function resolveButtonState(\n props: QwButtonProps = {},\n presence: ButtonContentPresence = EMPTY_PRESENCE,\n): ResolvedButtonState {\n const hasIcon = presence.hasIcon;\n const hasContent = presence.hasContent;\n const iconOnly = hasIcon && !hasContent;\n const loading = props.loading ?? false;\n const effectiveDisabled = (props.disabled ?? false) || loading;\n const effectiveBlock = (props.block ?? false) && !iconOnly;\n\n return {\n variant: props.variant ?? \"solid\",\n tone: props.tone ?? \"brand\",\n size: props.size ?? \"normal\",\n shape: props.shape ?? \"default\",\n iconPosition: props.iconPosition ?? \"start\",\n hasIcon,\n hasContent,\n iconOnly,\n loading,\n effectiveDisabled,\n effectiveBlock,\n ...(iconOnly && props.block && isDevelopmentBuild()\n ? { warning: \"icon-only-block-ignored\" as const }\n : {}),\n type: props.type ?? \"button\",\n };\n}\n\n/**\n * 将归一化结果转成 root 属性。空闲状态不写入 `aria-busy`,让调用方的合法\n * aria 属性继续透传;busy 状态则由 Core 作为安全属性覆盖。\n */\nexport function getButtonRootProps(state: ResolvedButtonState, aria: ButtonControlAria | undefined): ButtonControlRootProps;\nexport function getButtonRootProps(state: ResolvedButtonState): ButtonRootProps;\nexport function getButtonRootProps(state: ResolvedButtonState, aria: ButtonControlAria = {}): ButtonControlRootProps {\n return {\n type: state.type,\n disabled: state.effectiveDisabled,\n ...(state.loading ? { \"aria-busy\": true as const } : {}),\n ...(aria[\"aria-expanded\"] != null ? { \"aria-expanded\": aria[\"aria-expanded\"] } : {}),\n ...(aria[\"aria-controls\"] != null ? { \"aria-controls\": aria[\"aria-controls\"] } : {}),\n \"data-scope\": \"button\",\n \"data-part\": \"root\",\n \"data-variant\": state.variant,\n \"data-tone\": state.tone,\n \"data-size\": state.size,\n \"data-shape\": state.shape,\n \"data-icon-position\": state.iconPosition,\n ...(state.hasIcon ? { \"data-has-icon\": \"true\" as const } : {}),\n ...(state.iconOnly ? { \"data-icon-only\": \"true\" as const } : {}),\n ...(state.effectiveBlock ? { \"data-block\": \"true\" as const } : {}),\n ...(state.loading ? { \"data-loading\": \"true\" as const } : {}),\n };\n}\n"],"mappings":";;;;;;;AAOA,MAAa,kBAAkB;CAAC;CAAS;CAAQ;CAAW;CAAS;AAAM;AAC3E,MAAa,eAAe;CAAC;CAAS;CAAW;AAAQ;AACzD,MAAa,eAAe;CAAC;CAAQ;CAAM;CAAK;CAAU;CAAK;AAAG;AAClE,MAAa,gBAAgB;CAAC;CAAW;CAAU;AAAO;AAC1D,MAAa,wBAAwB,CAAC,SAAS,KAAK;AACpD,MAAa,eAAe;CAAC;CAAQ;CAAW;CAAQ;CAAS;AAAS;AAsF1E,MAAM,iBAAwC;CAAE,SAAS;CAAO,YAAY;AAAM;AAClF,MAAM,aAAc,OAAO,KAAkD,KAAK;;;;;AAMlF,SAAS,qBAA8B;CACrC,IAAI,cAAc,MAAM,OAAO,eAAe;CAE9C,MAAM,UAAW,WAA6D,SAAS,KAAK;CAC5F,OAAO,YAAY,iBAAiB,YAAY;AAClD;;AAGA,SAAgB,mBACd,QAAuB,CAAC,GACxB,WAAkC,gBACb;CACrB,MAAM,UAAU,SAAS;CACzB,MAAM,aAAa,SAAS;CAC5B,MAAM,WAAW,WAAW,CAAC;CAC7B,MAAM,UAAU,MAAM,WAAW;CACjC,MAAM,qBAAqB,MAAM,YAAY,UAAU;CACvD,MAAM,kBAAkB,MAAM,SAAS,UAAU,CAAC;CAElD,OAAO;EACL,SAAS,MAAM,WAAW;EAC1B,MAAM,MAAM,QAAQ;EACpB,MAAM,MAAM,QAAQ;EACpB,OAAO,MAAM,SAAS;EACtB,cAAc,MAAM,gBAAgB;EACpC;EACA;EACA;EACA;EACA;EACA;EACA,GAAI,YAAY,MAAM,SAAS,mBAAmB,IAC9C,EAAE,SAAS,0BAAmC,IAC9C,CAAC;EACL,MAAM,MAAM,QAAQ;CACtB;AACF;AAQA,SAAgB,mBAAmB,OAA4B,OAA0B,CAAC,GAA2B;CACnH,OAAO;EACL,MAAM,MAAM;EACZ,UAAU,MAAM;EAChB,GAAI,MAAM,UAAU,EAAE,aAAa,KAAc,IAAI,CAAC;EACtD,GAAI,KAAK,oBAAoB,OAAO,EAAE,iBAAiB,KAAK,iBAAiB,IAAI,CAAC;EAClF,GAAI,KAAK,oBAAoB,OAAO,EAAE,iBAAiB,KAAK,iBAAiB,IAAI,CAAC;EAClF,cAAc;EACd,aAAa;EACb,gBAAgB,MAAM;EACtB,aAAa,MAAM;EACnB,aAAa,MAAM;EACnB,cAAc,MAAM;EACpB,sBAAsB,MAAM;EAC5B,GAAI,MAAM,UAAU,EAAE,iBAAiB,OAAgB,IAAI,CAAC;EAC5D,GAAI,MAAM,WAAW,EAAE,kBAAkB,OAAgB,IAAI,CAAC;EAC9D,GAAI,MAAM,iBAAiB,EAAE,cAAc,OAAgB,IAAI,CAAC;EAChE,GAAI,MAAM,UAAU,EAAE,gBAAgB,OAAgB,IAAI,CAAC;CAC7D;AACF"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { type Machine, type Service } from "@zag-js/core";
|
|
2
|
+
import type { NormalizeProps, PropTypes } from "@zag-js/types";
|
|
3
|
+
export declare const CALENDAR_PARTS: readonly ["root", "header", "previous-trigger", "heading", "next-trigger", "grid", "row", "column-header", "cell", "day"];
|
|
4
|
+
export type CalendarSelectionMode = "single" | "multiple" | "range";
|
|
5
|
+
export interface CalendarDate {
|
|
6
|
+
year: number;
|
|
7
|
+
month: number;
|
|
8
|
+
day: number;
|
|
9
|
+
}
|
|
10
|
+
export interface CalendarRange {
|
|
11
|
+
start: CalendarDate | null;
|
|
12
|
+
end: CalendarDate | null;
|
|
13
|
+
}
|
|
14
|
+
export type CalendarValue = CalendarDate | CalendarDate[] | CalendarRange | null;
|
|
15
|
+
export interface CalendarValueChangeDetails {
|
|
16
|
+
value: CalendarValue;
|
|
17
|
+
}
|
|
18
|
+
export interface QwCalendarProps {
|
|
19
|
+
id?: string;
|
|
20
|
+
label?: string;
|
|
21
|
+
locale?: string;
|
|
22
|
+
dir?: "ltr" | "rtl";
|
|
23
|
+
mode?: CalendarSelectionMode;
|
|
24
|
+
value?: CalendarValue;
|
|
25
|
+
defaultValue?: CalendarValue;
|
|
26
|
+
min?: CalendarDate;
|
|
27
|
+
max?: CalendarDate;
|
|
28
|
+
disabledDates?: readonly CalendarDate[];
|
|
29
|
+
weekStartsOn?: number;
|
|
30
|
+
today?: CalendarDate;
|
|
31
|
+
onValueChange?: (details: CalendarValueChangeDetails) => void;
|
|
32
|
+
}
|
|
33
|
+
export declare function isValidCalendarDate(value: unknown): value is CalendarDate;
|
|
34
|
+
export declare function daysInMonth(year: number, month: number): number;
|
|
35
|
+
export declare function toDateKey(date: CalendarDate): string;
|
|
36
|
+
export declare function compareCalendarDates(a: CalendarDate, b: CalendarDate): number;
|
|
37
|
+
export declare function addCalendarDays(date: CalendarDate, amount: number): CalendarDate;
|
|
38
|
+
export declare function addCalendarMonths(date: CalendarDate, amount: number): CalendarDate;
|
|
39
|
+
export declare function normalizeCalendarValue(value: CalendarValue | undefined, mode: CalendarSelectionMode): CalendarValue;
|
|
40
|
+
export declare function isCalendarDateDisabled(date: CalendarDate, props: Pick<QwCalendarProps, "min" | "max" | "disabledDates">): boolean;
|
|
41
|
+
export interface CalendarDay {
|
|
42
|
+
date: CalendarDate;
|
|
43
|
+
key: string;
|
|
44
|
+
label: string;
|
|
45
|
+
day: number;
|
|
46
|
+
outside: boolean;
|
|
47
|
+
disabled: boolean;
|
|
48
|
+
selected: boolean;
|
|
49
|
+
inRange: boolean;
|
|
50
|
+
today: boolean;
|
|
51
|
+
focused: boolean;
|
|
52
|
+
}
|
|
53
|
+
export declare function getCalendarMonthDays(view: CalendarDate, props: QwCalendarProps, value: CalendarValue, focused: CalendarDate): CalendarDay[];
|
|
54
|
+
export declare function selectCalendarDate(value: CalendarValue, date: CalendarDate, mode: CalendarSelectionMode): CalendarValue;
|
|
55
|
+
export declare function createCalendarProps(props: QwCalendarProps): QwCalendarProps;
|
|
56
|
+
export interface QwCalendarSchema {
|
|
57
|
+
props: QwCalendarProps;
|
|
58
|
+
context: {
|
|
59
|
+
value: CalendarValue;
|
|
60
|
+
view: CalendarDate;
|
|
61
|
+
focused: CalendarDate;
|
|
62
|
+
};
|
|
63
|
+
state: "idle";
|
|
64
|
+
action: "select" | "focus" | "navigate" | "today";
|
|
65
|
+
event: {
|
|
66
|
+
type: "SELECT";
|
|
67
|
+
date: CalendarDate;
|
|
68
|
+
} | {
|
|
69
|
+
type: "FOCUS";
|
|
70
|
+
date: CalendarDate;
|
|
71
|
+
} | {
|
|
72
|
+
type: "NAVIGATE";
|
|
73
|
+
months: number;
|
|
74
|
+
} | {
|
|
75
|
+
type: "TODAY";
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
export type QwCalendarMachine = Machine<QwCalendarSchema>;
|
|
79
|
+
export type QwCalendarService = Service<QwCalendarSchema>;
|
|
80
|
+
export declare const calendarMachine: QwCalendarMachine;
|
|
81
|
+
export interface QwCalendarApi<T extends PropTypes = PropTypes> {
|
|
82
|
+
label: string;
|
|
83
|
+
heading: string;
|
|
84
|
+
weekdays: string[];
|
|
85
|
+
weeks: CalendarDay[][];
|
|
86
|
+
value: CalendarValue;
|
|
87
|
+
focusDate(date: CalendarDate): void;
|
|
88
|
+
selectDate(date: CalendarDate): void;
|
|
89
|
+
getRootProps(): T["element"];
|
|
90
|
+
getHeaderProps(): T["element"];
|
|
91
|
+
getPreviousTriggerProps(): T["button"];
|
|
92
|
+
getHeadingProps(): T["element"];
|
|
93
|
+
getNextTriggerProps(): T["button"];
|
|
94
|
+
getGridProps(): T["element"];
|
|
95
|
+
getRowProps(): T["element"];
|
|
96
|
+
getColumnHeaderProps(index: number): T["element"];
|
|
97
|
+
getCellProps(day: CalendarDay): T["element"];
|
|
98
|
+
getDayProps(day: CalendarDay): T["button"];
|
|
99
|
+
}
|
|
100
|
+
export declare function connectCalendar<T extends PropTypes>(service: QwCalendarService, normalize: NormalizeProps<T>): QwCalendarApi<T>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./calendar.js";
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as compareCalendarDates, c as daysInMonth, d as isValidCalendarDate, f as normalizeCalendarValue, i as calendarMachine, l as getCalendarMonthDays, m as toDateKey, n as addCalendarDays, o as connectCalendar, p as selectCalendarDate, r as addCalendarMonths, s as createCalendarProps, t as CALENDAR_PARTS, u as isCalendarDateDisabled } from "../calendar-CmpK3stz.js";
|
|
2
|
+
export { CALENDAR_PARTS, addCalendarDays, addCalendarMonths, calendarMachine, compareCalendarDates, connectCalendar, createCalendarProps, daysInMonth, getCalendarMonthDays, isCalendarDateDisabled, isValidCalendarDate, normalizeCalendarValue, selectCalendarDate, toDateKey };
|