@qw-ui/core 0.3.0-next.40 → 0.3.0-next.43
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 +9 -0
- package/dist/badge/index.js +14 -1
- package/dist/badge/index.js.map +1 -1
- 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 +32 -3
- package/dist/dialog/index.js +58 -3
- 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 +107 -14
- package/dist/index.js +148 -14
- 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/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 +3 -1
- package/dist/search-bar/index.js.map +1 -1
- package/dist/search-bar/search-bar.d.ts +4 -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/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.js +62 -3
- package/dist/stepper/index.js.map +1 -1
- package/dist/stepper/stepper.d.ts +44 -4
- 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.js +135 -10
- package/dist/switch/index.js.map +1 -1
- package/dist/switch/switch.d.ts +93 -6
- package/dist/tabbar/index.js +46 -1
- package/dist/tabbar/index.js.map +1 -1
- package/dist/tabbar/tabbar.d.ts +50 -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 +165 -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 +6 -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 +399 -50
- 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":"textarea-qbnruDUG.js","names":[],"sources":["../src/textarea/textarea.ts","../src/textarea/platform.ts"],"sourcesContent":["import { createMachine } from \"@zag-js/core\";\nimport type { MachineSchema, Service } from \"@zag-js/core\";\nimport type { PropTypes, NormalizeProps } from \"@zag-js/types\";\nimport { compact } from \"@zag-js/utils\";\n\n/**\n * 平台快照与 sink。字段与 `contracts/platform.md` 逐字一致。\n * 平台模块可以各自声明同结构类型;这里是 Core 侧事实源。\n */\nexport type TextAreaBoxSizing = \"border-box\" | \"content-box\";\n\nexport type TextAreaClipboardFailure = \"unsupported\" | \"denied\" | \"aborted\" | \"stale\";\n\nexport interface TextAreaControlSnapshot {\n /** 当前 textarea.value,原样返回。 */\n readonly value: string;\n /**\n * 控件自身的 disabled 属性结果,含 fieldset 与第一个 legend 的例外。\n * 不解释 readOnly、maxLength 或是否接受该值。\n */\n readonly disabled: boolean;\n}\n\nexport interface TextAreaSizeSnapshot {\n /** height 临时为 auto 时读到的 scrollHeight。含 padding,不含 border。 */\n readonly scrollHeight: number;\n /** 行内可用尺寸,单位 px。为 0 表示尚未布局。 */\n readonly inlineSize: number;\n /** 已解析成 px 的行高。关键字未能解析时视为无效度量。 */\n readonly lineHeight: number;\n readonly paddingBlockSize: number;\n readonly borderBlockSize: number;\n readonly boxSizing: TextAreaBoxSizing;\n /** display 不是 none,且具有非零布局盒。 */\n readonly visible: boolean;\n}\n\nexport interface TextAreaEditEvent {\n readonly type: \"input\" | \"composition-start\" | \"composition-update\" | \"composition-end\";\n readonly value: string;\n}\n\nexport interface TextAreaResetNotice {\n /** 必须是该次 reset 派发完全结束后的值。 */\n readonly defaultPrevented: boolean;\n}\n\nexport interface TextAreaPlatformClient {\n readControl(): TextAreaControlSnapshot;\n measureIntrinsic(): TextAreaSizeSnapshot;\n writeValue(value: string, defaultValue: string): void;\n writeHeight(height: number | undefined): void;\n focus(): void;\n blur(): void;\n readClipboardText(): Promise<string>;\n}\n\nexport interface TextAreaPlatformSink {\n commit(client: TextAreaPlatformClient): void;\n changed(): void;\n edit(event: TextAreaEditEvent): void;\n focusChanged(focused: boolean): void;\n reset(notice: TextAreaResetNotice): void;\n detach(): void;\n}\n\nexport interface TextAreaHeightInput {\n readonly autoSize: boolean;\n /** 缺省与非法值由 Core 先规范成不小于 1 的整数,缺省 4。 */\n readonly rows: number;\n /**\n * 可选上限。缺省、非有限,或 floor 后不大于 0 时不封顶。\n * floor 后小于 rows 时,有效上限等于 rows。只在 autoSize 时参与计算。\n */\n readonly maxRows?: number;\n readonly metrics: TextAreaSizeSnapshot | undefined;\n}\n\nexport interface TextAreaPasteDetail {\n value: string;\n status: \"accepted\" | \"unavailable\";\n reason?: TextAreaClipboardFailure;\n}\n\n/** 原生事件 detail。框架 onChange 仍是字符串;这些回调只给原生传输。 */\ninterface TextAreaNativeCallbacks {\n onTextareaValue?: (detail: { value: string }) => void;\n onTextareaChange?: (detail: { value: string }) => void;\n onTextareaClear?: (detail: { value: \"\" }) => void;\n onTextareaPaste?: (detail: TextAreaPasteDetail) => void;\n onTextareaFocus?: (detail: { focused: boolean }) => void;\n}\n\n/**\n * TextArea 公共 props 契约(双栈共享)。\n * autoSize 保持布尔。可选 maxRows 只在自动高度时封顶。\n */\nexport interface QwTextAreaProps {\n /** 唯一 id 前缀。 */\n id?: string;\n /** 受控值。传入任意字符串(含 \"\")即为受控。 */\n value?: string;\n /** 非受控初始值,也是 reset 目标。 */\n defaultValue?: string;\n /** 占位符。 */\n placeholder?: string;\n /** 最大字符数。仅有限整数 > 0 时生效。 */\n maxLength?: number;\n /** 最小长度。仅有限整数 > 0 时反射为 minlength。 */\n minLength?: number;\n /** 禁用态。 */\n disabled?: boolean;\n /** 只读态。可聚焦、可选择、可提交,不可编辑。 */\n readOnly?: boolean;\n /** 可视行数(最小高度)。小于 1 或非有限时按 4。 */\n rows?: number;\n /**\n * 自动高度的行数上限。仅 autoSize 为 true 且 floor 后大于 0 时生效。\n * 小于 rows 时高度仍不低于 rows。缺省或非法值不封顶。\n */\n maxRows?: number;\n /** 自适应高度。布尔,不接受 { minRows, maxRows } 对象。 */\n autoSize?: boolean;\n /** 显示底部操作按钮。 */\n showActions?: boolean;\n /** name 属性。 */\n name?: string;\n /** 外部 form 的 id。 */\n form?: string;\n /** 内层 textarea required。 */\n required?: boolean;\n /** 为 true 时写 aria-invalid。 */\n invalid?: boolean;\n /** textarea aria-label。 */\n accessibleLabel?: string;\n /** textarea aria-labelledby。 */\n labelledBy?: string;\n /** 并入 textarea aria-describedby。 */\n describedBy?: string;\n /** textarea aria-errormessage。 */\n errorId?: string;\n /** 清除按钮 aria-label,默认「清除内容」。 */\n clearLabel?: string;\n /** 粘贴按钮 aria-label,默认「粘贴并识别」。 */\n pasteLabel?: string;\n /** 清除按钮可见文字,默认「一键清除」。 */\n clearText?: string;\n /** 识别按钮可见文字,默认「粘贴并识别」。 */\n pasteText?: string;\n /** 仅 final commit。 */\n onChange?: (value: string) => void;\n /** 清空成功时。 */\n onClear?: () => void;\n /** 仅识别成功。参数是替换用的文本。 */\n onPasteRecognize?: (value: string) => void;\n /** 识别失败或 ticket 过期。 */\n onPasteError?: (reason: TextAreaClipboardFailure) => void;\n /** 聚焦回调。 */\n onFocus?: () => void;\n /** 失焦回调。 */\n onBlur?: () => void;\n}\n\ninterface TextAreaSchema extends MachineSchema {\n props: QwTextAreaProps & TextAreaNativeCallbacks;\n context: {\n uncontrolled: string;\n focused: boolean;\n composing: boolean;\n draft: string;\n controlDisabled: boolean;\n };\n computed: {\n charCount: number;\n hasMaxLength: boolean;\n showClear: boolean;\n };\n state: \"idle\";\n event: { type: \"NOP\" };\n action: \"noop\";\n}\n\nexport type { TextAreaSchema };\n\ntype CommitSource = \"input\" | \"clear\" | \"paste\" | \"reset\";\n\ninterface TextAreaSession {\n client?: TextAreaPlatformClient;\n epoch: number;\n ticket: number;\n ticketSeq: number;\n suppressRaw?: string;\n suppressAccepted?: string;\n autoApplied: boolean;\n writebackQueued: boolean;\n sink?: TextAreaPlatformSink;\n}\n\nconst sessions = new Map<string, TextAreaSession & { service?: Service<TextAreaSchema> }>();\n\nfunction sessionOf(service: Service<TextAreaSchema>): TextAreaSession & { service?: Service<TextAreaSchema> } {\n // React/Vue 每次渲染都会换一个 context 对象,但 id 稳定。用 id 记住平台 client。\n const id = service.prop(\"id\") ?? \"\";\n let session = sessions.get(id);\n if (!session) {\n session = { epoch: 0, ticket: 0, ticketSeq: 0, autoApplied: false, writebackQueued: false, service };\n sessions.set(id, session);\n }\n session.service = service;\n return session;\n}\n\nfunction stripUndefined<T extends object>(props: T): Partial<T> {\n return Object.fromEntries(Object.entries(props).filter(([, value]) => value !== undefined)) as Partial<T>;\n}\n\n/** 缺省与非法 rows 收成不小于 1 的整数,缺省 4。 */\nfunction normalizeRows(rows: number | undefined): number {\n if (typeof rows !== \"number\" || !Number.isFinite(rows) || rows < 1) return 4;\n return Math.floor(rows);\n}\n\n/** 只有 floor 后仍大于 0 的有限数才成为上限或 minlength。 */\nfunction positiveInt(value: number | undefined): number | undefined {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return undefined;\n const limit = Math.floor(value);\n return limit > 0 ? limit : undefined;\n}\n\n/**\n * 有效行数上限。非法 maxRows 表示不封顶。\n * 小于已规范化的 rows 时抬到 rows,避免高度缩到下限以下。\n */\nfunction effectiveRowCap(rows: number, maxRows: number | undefined): number | undefined {\n const max = positiveInt(maxRows);\n if (max === undefined) return undefined;\n return Math.max(rows, max);\n}\n\n/** show-actions 只有显式 false / \"false\" 才关闭。 */\nfunction showActionsEnabled(value: unknown): boolean {\n return value !== false && value !== \"false\";\n}\n\n/**\n * 决议 (c) 的唯一落点:显式识别整段替换。\n * 若改为按光标插入,只改这个函数。\n */\nfunction recognizedNextValue(text: string): string {\n return text;\n}\n\n/**\n * UTF-16 安全截断。maxLength 为空、非有限,或 floor 后不大于 0 时原样返回。\n */\nexport function clampUtf16(value: string, maxLength: number | undefined): string {\n const limitOrNone = positiveInt(maxLength);\n if (limitOrNone === undefined) return value;\n let limit = limitOrNone;\n if (value.length <= limit) return value;\n const boundary = value.charCodeAt(limit - 1);\n const next = value.charCodeAt(limit);\n if (boundary >= 0xd800 && boundary <= 0xdbff && next >= 0xdc00 && next <= 0xdfff) limit -= 1;\n return value.slice(0, Math.max(0, limit));\n}\n\nfunction metricsUsable(metrics: TextAreaSizeSnapshot | undefined): metrics is TextAreaSizeSnapshot {\n if (!metrics || metrics.visible === false) return false;\n if (!(metrics.inlineSize > 0) || !(metrics.lineHeight > 0)) return false;\n const numbers = [metrics.scrollHeight, metrics.inlineSize, metrics.lineHeight, metrics.paddingBlockSize, metrics.borderBlockSize];\n return numbers.every((value) => typeof value === \"number\" && Number.isFinite(value));\n}\n\n/**\n * 自动高度像素。下限是 rows;有效 maxRows 把 border-box 再夹住。\n * 无法度量时返回 undefined,调用方不得写成 0。不读取 DOM。\n */\nexport function computeTextAreaHeight(input: TextAreaHeightInput): number | undefined {\n if (!input.autoSize || !metricsUsable(input.metrics)) return undefined;\n const metrics = input.metrics;\n const minBorder = input.rows * metrics.lineHeight + metrics.paddingBlockSize + metrics.borderBlockSize;\n const measuredBorder = metrics.scrollHeight + metrics.borderBlockSize;\n let borderBox = Math.max(minBorder, measuredBorder);\n const cap = effectiveRowCap(input.rows, input.maxRows);\n if (cap !== undefined) {\n const maxBorder = cap * metrics.lineHeight + metrics.paddingBlockSize + metrics.borderBlockSize;\n borderBox = Math.min(borderBox, maxBorder);\n }\n const height = metrics.boxSizing === \"content-box\"\n ? Math.max(0, borderBox - metrics.paddingBlockSize - metrics.borderBlockSize)\n : borderBox;\n return Math.ceil(height);\n}\n\nfunction readCommitted(service: Service<TextAreaSchema>): string {\n const controlled = service.prop(\"value\");\n return controlled !== undefined ? controlled : service.context.get(\"uncontrolled\");\n}\n\nfunction isControlled(service: Service<TextAreaSchema>): boolean {\n return service.prop(\"value\") !== undefined;\n}\n\nfunction guarded(service: Service<TextAreaSchema>): boolean {\n return !!service.prop(\"disabled\") || !!service.prop(\"readOnly\") || !!service.context.get(\"controlDisabled\");\n}\n\nfunction defaultValueOf(service: Service<TextAreaSchema>): string {\n return service.prop(\"defaultValue\") ?? \"\";\n}\n\nfunction alignDom(service: Service<TextAreaSchema>, accepted: string): void {\n const session = sessionOf(service);\n const client = session.client;\n if (!client) return;\n const shown = readCommitted(service);\n const dom = client.readControl().value;\n if (dom === shown || !isControlled(service) || shown === accepted) {\n client.writeValue(shown, defaultValueOf(service));\n return;\n }\n // 受控且本次调用栈里 prop 还没跟上:留给 React 刷新,再写回拒绝后的值。\n if (session.writebackQueued) return;\n session.writebackQueued = true;\n const epoch = session.epoch;\n queueMicrotask(() => {\n session.writebackQueued = false;\n if (session.epoch !== epoch || !session.client || service.context.get(\"composing\")) return;\n session.client.writeValue(readCommitted(service), defaultValueOf(service));\n });\n}\n\nfunction syncHeight(service: Service<TextAreaSchema>): void {\n const session = sessionOf(service);\n const client = session.client;\n if (!client) return;\n const auto = !!service.prop(\"autoSize\");\n if (!auto) {\n if (session.autoApplied) client.writeHeight(undefined);\n session.autoApplied = false;\n return;\n }\n session.autoApplied = true;\n const height = computeTextAreaHeight({\n autoSize: true,\n rows: normalizeRows(service.prop(\"rows\")),\n maxRows: service.prop(\"maxRows\"),\n metrics: client.measureIntrinsic(),\n });\n if (typeof height === \"number\") client.writeHeight(height);\n}\n\nfunction publish(service: Service<TextAreaSchema>, raw: string, source: CommitSource): string {\n if (source !== \"reset\" && guarded(service)) {\n const current = readCommitted(service);\n alignDom(service, current);\n return current;\n }\n const text = source === \"paste\" ? recognizedNextValue(raw) : raw;\n const accepted = clampUtf16(text, service.prop(\"maxLength\"));\n const changed = accepted !== readCommitted(service);\n if (!isControlled(service) && changed) service.context.set(\"uncontrolled\", accepted);\n if (changed) {\n service.prop(\"onChange\")?.(accepted);\n service.prop(\"onTextareaValue\")?.({ value: accepted });\n service.prop(\"onTextareaChange\")?.({ value: accepted });\n }\n alignDom(service, accepted);\n return accepted;\n}\n\n/**\n * 决议 (b) 的唯一落点:失败只走 onPasteError / textarea-paste,不调用 onPasteRecognize。\n */\nfunction reportPasteFailure(service: Service<TextAreaSchema>, reason: TextAreaClipboardFailure): void {\n service.prop(\"onPasteError\")?.(reason);\n service.prop(\"onTextareaPaste\")?.({ value: readCommitted(service), status: \"unavailable\", reason });\n}\n\nfunction clipboardFailure(error: unknown): Exclude<TextAreaClipboardFailure, \"stale\"> {\n if (error && typeof error === \"object\" && \"reason\" in error) {\n const reason = (error as { reason: unknown }).reason;\n if (reason === \"unsupported\" || reason === \"denied\" || reason === \"aborted\") return reason;\n }\n return \"denied\";\n}\n\n/** 后续编辑、清空、重置或新的显式替换使进行中的读取变为 stale。不推进 epoch,避免打断受控写回。 */\nfunction invalidateClipboardTicket(session: TextAreaSession): void {\n session.ticket = ++session.ticketSeq;\n}\n\nfunction edit(service: Service<TextAreaSchema>, event: TextAreaEditEvent): void {\n const session = sessionOf(service);\n invalidateClipboardTicket(session);\n const drafting = event.type === \"composition-start\"\n || event.type === \"composition-update\"\n || (event.type === \"input\" && service.context.get(\"composing\"));\n if (drafting) {\n // 决议 (a):草稿不截断、不 onChange、不写回 DOM。\n service.context.set(\"composing\", true);\n service.context.set(\"draft\", event.value);\n return;\n }\n if (event.type === \"composition-end\") {\n const accepted = publish(service, event.value, \"input\");\n service.context.set(\"composing\", false);\n service.context.set(\"draft\", \"\");\n session.suppressRaw = event.value;\n session.suppressAccepted = accepted;\n return;\n }\n if (session.suppressRaw !== undefined || session.suppressAccepted !== undefined) {\n const raw = session.suppressRaw;\n const accepted = session.suppressAccepted;\n session.suppressRaw = undefined;\n session.suppressAccepted = undefined;\n if (event.value === raw || event.value === accepted) return;\n }\n publish(service, event.value, \"input\");\n}\n\nfunction clearValue(service: Service<TextAreaSchema>): void {\n if (guarded(service)) {\n const current = readCommitted(service);\n alignDom(service, current);\n return;\n }\n invalidateClipboardTicket(sessionOf(service));\n publish(service, \"\", \"clear\");\n service.prop(\"onClear\")?.();\n service.prop(\"onTextareaClear\")?.({ value: \"\" });\n}\n\nfunction pasteRecognize(service: Service<TextAreaSchema>, explicit?: string): void {\n if (guarded(service)) return;\n if (typeof explicit === \"string\") {\n invalidateClipboardTicket(sessionOf(service));\n const accepted = publish(service, explicit, \"paste\");\n service.prop(\"onPasteRecognize\")?.(accepted);\n service.prop(\"onTextareaPaste\")?.({ value: accepted, status: \"accepted\" });\n return;\n }\n const session = sessionOf(service);\n const client = session.client;\n if (!client) {\n reportPasteFailure(service, \"unsupported\");\n return;\n }\n const epoch = session.epoch;\n const ticket = ++session.ticketSeq;\n session.ticket = ticket;\n client.readClipboardText().then(\n (text) => {\n if (session.epoch !== epoch || session.ticket !== ticket || guarded(service)) {\n reportPasteFailure(service, \"stale\");\n return;\n }\n const accepted = publish(service, text, \"paste\");\n service.prop(\"onPasteRecognize\")?.(accepted);\n service.prop(\"onTextareaPaste\")?.({ value: accepted, status: \"accepted\" });\n },\n (error: unknown) => {\n if (session.epoch !== epoch || session.ticket !== ticket) {\n reportPasteFailure(service, \"stale\");\n return;\n }\n reportPasteFailure(service, clipboardFailure(error));\n },\n );\n}\n\nfunction focusChanged(service: Service<TextAreaSchema>, focused: boolean): void {\n if (service.context.get(\"focused\") === focused) return;\n service.context.set(\"focused\", focused);\n if (focused) service.prop(\"onFocus\")?.();\n else service.prop(\"onBlur\")?.();\n service.prop(\"onTextareaFocus\")?.({ focused });\n}\n\nfunction resetValue(service: Service<TextAreaSchema>, notice: TextAreaResetNotice): void {\n if (notice.defaultPrevented) return;\n invalidateClipboardTicket(sessionOf(service));\n publish(service, service.prop(\"defaultValue\") ?? \"\", \"reset\");\n}\n\nfunction project(service: Service<TextAreaSchema>): void {\n const session = sessionOf(service);\n const client = session.client;\n if (!client) return;\n service.context.set(\"controlDisabled\", client.readControl().disabled);\n if (!service.context.get(\"composing\")) client.writeValue(readCommitted(service), defaultValueOf(service));\n syncHeight(service);\n}\n\nfunction sinkFor(service: Service<TextAreaSchema>): TextAreaPlatformSink {\n const session = sessionOf(service);\n if (session.sink) return session.sink;\n const live = () => session.service ?? service;\n const sink: TextAreaPlatformSink = {\n commit(client) {\n const current = live();\n session.client = client;\n session.epoch += 1;\n session.suppressRaw = undefined;\n session.suppressAccepted = undefined;\n current.context.set(\"controlDisabled\", client.readControl().disabled);\n if (!current.context.get(\"composing\")) client.writeValue(readCommitted(current), defaultValueOf(current));\n syncHeight(current);\n },\n changed() {\n const current = live();\n const client = session.client;\n if (!client) return;\n current.context.set(\"controlDisabled\", client.readControl().disabled);\n syncHeight(current);\n },\n edit(event) {\n edit(live(), event);\n },\n focusChanged(focused) {\n focusChanged(live(), focused);\n },\n reset(notice) {\n resetValue(live(), notice);\n },\n detach() {\n session.epoch += 1;\n session.client = undefined;\n session.autoApplied = false;\n },\n };\n session.sink = sink;\n return sink;\n}\n\n/**\n * TextArea zag.js machine。\n * 值、草稿、ticket 与高度结论都在这里;没有第二份 value watcher。\n */\nexport const machine = createMachine<TextAreaSchema>({\n props({ props }) {\n return {\n ...stripUndefined(props),\n defaultValue: props.defaultValue ?? \"\",\n disabled: !!props.disabled,\n readOnly: !!props.readOnly,\n showActions: showActionsEnabled(props.showActions),\n autoSize: !!props.autoSize,\n rows: normalizeRows(props.rows),\n clearLabel: props.clearLabel ?? \"清除内容\",\n pasteLabel: props.pasteLabel ?? \"粘贴并识别\",\n clearText: props.clearText ?? \"一键清除\",\n pasteText: props.pasteText ?? \"粘贴并识别\",\n };\n },\n\n initialState() {\n return \"idle\";\n },\n\n context({ bindable, prop }) {\n return {\n uncontrolled: bindable<string>(() => ({\n defaultValue: prop(\"defaultValue\") ?? \"\",\n })),\n focused: bindable<boolean>(() => ({ defaultValue: false })),\n composing: bindable<boolean>(() => ({ defaultValue: false })),\n draft: bindable<string>(() => ({ defaultValue: \"\" })),\n controlDisabled: bindable<boolean>(() => ({ defaultValue: false })),\n };\n },\n\n computed: {\n charCount({ context, prop }) {\n if (context.get(\"composing\")) return context.get(\"draft\").length;\n const controlled = prop(\"value\");\n return (controlled !== undefined ? controlled : context.get(\"uncontrolled\")).length;\n },\n hasMaxLength({ prop }) {\n return positiveInt(prop(\"maxLength\")) !== undefined;\n },\n showClear({ context, prop }) {\n const controlled = prop(\"value\");\n const value = controlled !== undefined ? controlled : context.get(\"uncontrolled\");\n return value.length > 0 && !prop(\"disabled\") && !prop(\"readOnly\") && !context.get(\"controlDisabled\");\n },\n },\n\n states: {\n idle: {},\n },\n\n implementations: {\n actions: {\n noop() {},\n },\n },\n});\n\n/** connect 返回的业务 api。 */\nexport interface TextAreaApi<T extends PropTypes = PropTypes> {\n /** 已提交值。 */\n value: string;\n /** 组合期间为草稿,否则为已提交值。供原生视图投影,不替代 writeValue。 */\n displayValue: string;\n /** field 是否聚焦。 */\n focused: boolean;\n /** 是否处于草稿阶段。 */\n composing: boolean;\n /** 草稿阶段用草稿的 UTF-16 长度,否则用已提交值。 */\n charCount: number;\n /** 是否存在有限正整数上限。 */\n hasMaxLength: boolean;\n /** 已提交值非空,且未禁用、非只读。 */\n showClear: boolean;\n /** 规范化后的正整数上限;没有上限时为 undefined。 */\n limit: number | undefined;\n showActions: boolean;\n clearText: string;\n pasteText: string;\n fieldId: string;\n counterId: string;\n /** 把已提交值和高度投影到平台。组合期间不写值。 */\n project(): void;\n /** 平台 sink。同一 service 返回同一对象。 */\n getPlatformSink(): TextAreaPlatformSink;\n clear(): void;\n /** 传入字符串则直接按识别提交;不传则读剪贴板。 */\n pasteRecognize(value?: string): void;\n getRootProps(): T[\"element\"];\n getTextareaProps(): T[\"textarea\"];\n getBottomBarProps(): T[\"element\"];\n getCounterProps(): T[\"element\"];\n getClearButtonProps(): T[\"button\"];\n getPasteButtonProps(): T[\"button\"];\n}\n\nfunction describedByValue(service: Service<TextAreaSchema>, counterId: string, hasMaxLength: boolean): string | undefined {\n const parts = [service.prop(\"describedBy\"), hasMaxLength ? counterId : undefined].filter((item): item is string => !!item);\n return parts.length > 0 ? parts.join(\" \") : undefined;\n}\n\n/**\n * connect:把 service 接成 prop-getter。适配层不在这里之外做接受与否的判断。\n */\nexport function connect<T extends PropTypes>(service: Service<TextAreaSchema>, normalizeProps: NormalizeProps<T>): TextAreaApi<T> {\n sessionOf(service);\n const { context, computed, prop } = service;\n const value = readCommitted(service);\n const composing = !!context.get(\"composing\");\n const displayValue = composing ? context.get(\"draft\") : value;\n const focused = !!context.get(\"focused\");\n const charCount = computed(\"charCount\");\n const hasMaxLength = !!computed(\"hasMaxLength\");\n const showClear = !!computed(\"showClear\");\n const disabled = !!prop(\"disabled\");\n const readOnly = !!prop(\"readOnly\");\n const controlDisabled = !!context.get(\"controlDisabled\");\n const blocked = disabled || readOnly || controlDisabled;\n const showActions = showActionsEnabled(prop(\"showActions\"));\n const autoSize = !!prop(\"autoSize\");\n const limit = positiveInt(prop(\"maxLength\"));\n const minLength = positiveInt(prop(\"minLength\"));\n const rows = normalizeRows(prop(\"rows\"));\n const rowCap = autoSize ? effectiveRowCap(rows, prop(\"maxRows\")) : undefined;\n const id = prop(\"id\") ?? \"\";\n const fieldId = `textarea:${id}:field`;\n const counterId = `textarea:${id}:counter`;\n const describedBy = describedByValue(service, counterId, hasMaxLength);\n const isEmpty = value.length === 0;\n\n return {\n value,\n displayValue,\n focused,\n composing,\n charCount,\n hasMaxLength,\n showClear,\n limit,\n showActions,\n clearText: prop(\"clearText\") ?? \"一键清除\",\n pasteText: prop(\"pasteText\") ?? \"粘贴并识别\",\n fieldId,\n counterId,\n project() {\n project(service);\n },\n getPlatformSink() {\n return sinkFor(service);\n },\n clear() {\n clearValue(service);\n },\n pasteRecognize(explicit?: string) {\n pasteRecognize(service, explicit);\n },\n getRootProps() {\n return normalizeProps.element(\n compact({\n \"data-scope\": \"textarea\",\n \"data-part\": \"root\",\n \"data-focused\": focused ? \"true\" : undefined,\n \"data-disabled\": disabled || controlDisabled ? \"true\" : undefined,\n \"data-readonly\": readOnly ? \"true\" : undefined,\n \"data-show-actions\": showActions ? \"true\" : \"false\",\n \"data-auto-size\": autoSize ? \"true\" : undefined,\n \"data-max-rows\": rowCap !== undefined ? String(rowCap) : undefined,\n \"data-empty\": isEmpty ? \"true\" : \"false\",\n }),\n );\n },\n getTextareaProps() {\n return normalizeProps.textarea(\n compact({\n id: fieldId,\n \"data-scope\": \"textarea\",\n \"data-part\": \"textarea\",\n placeholder: prop(\"placeholder\"),\n disabled: disabled ? true : undefined,\n readOnly: readOnly ? true : undefined,\n required: prop(\"required\") ? true : undefined,\n maxLength: limit,\n minLength,\n rows,\n name: prop(\"name\"),\n form: prop(\"form\"),\n \"aria-label\": prop(\"accessibleLabel\"),\n \"aria-labelledby\": prop(\"labelledBy\"),\n \"aria-describedby\": describedBy,\n \"aria-invalid\": prop(\"invalid\") ? (\"true\" as const) : undefined,\n \"aria-errormessage\": prop(\"errorId\"),\n \"aria-disabled\": disabled ? (\"true\" as const) : undefined,\n \"aria-readonly\": readOnly ? (\"true\" as const) : undefined,\n }),\n );\n },\n getBottomBarProps() {\n return normalizeProps.element(\n compact({\n \"data-scope\": \"textarea\",\n \"data-part\": \"bottom-bar\",\n \"data-show-actions\": showActions ? \"true\" : \"false\",\n }),\n );\n },\n getCounterProps() {\n return normalizeProps.element(\n compact({\n id: counterId,\n \"data-scope\": \"textarea\",\n \"data-part\": \"counter\",\n \"data-has-max-length\": hasMaxLength ? \"true\" : undefined,\n \"aria-live\": \"polite\" as const,\n }),\n );\n },\n getClearButtonProps() {\n return normalizeProps.button(\n compact({\n \"data-scope\": \"textarea\",\n \"data-part\": \"clear-button\",\n type: \"button\" as const,\n disabled: !showClear || blocked ? true : undefined,\n \"aria-label\": prop(\"clearLabel\") ?? \"清除内容\",\n onClick() {\n clearValue(service);\n },\n }),\n );\n },\n getPasteButtonProps() {\n return normalizeProps.button(\n compact({\n \"data-scope\": \"textarea\",\n \"data-part\": \"paste-button\",\n type: \"button\" as const,\n disabled: blocked ? true : undefined,\n \"aria-label\": prop(\"pasteLabel\") ?? \"粘贴并识别\",\n onClick() {\n pasteRecognize(service);\n },\n }),\n );\n },\n };\n}\n\n/**\n * 把 QwTextAreaProps 转成 machine props(默认值收口)。\n * 缺省文案是 zh-CN;适配层传入的 locale 优先。\n */\nexport function createTextAreaProps(props: QwTextAreaProps = {}): Partial<QwTextAreaProps> {\n return {\n ...stripUndefined(props),\n defaultValue: props.defaultValue ?? \"\",\n disabled: props.disabled ?? false,\n readOnly: props.readOnly ?? false,\n showActions: showActionsEnabled(props.showActions),\n autoSize: props.autoSize ?? false,\n rows: normalizeRows(props.rows),\n clearLabel: props.clearLabel ?? \"清除内容\",\n pasteLabel: props.pasteLabel ?? \"粘贴并识别\",\n clearText: props.clearText ?? \"一键清除\",\n pasteText: props.pasteText ?? \"粘贴并识别\",\n };\n}\n","import type {\n TextAreaClipboardFailure,\n TextAreaPlatformClient,\n TextAreaPlatformSink,\n TextAreaSizeSnapshot,\n} from \"./textarea.js\";\n\n/**\n * TextArea 的平台装配:ref 之后的监听、测量和写回。\n * 不判断接受、截断或组合 —— 那些仍然只在 Core 的 TextArea 状态机里。\n * 各栈适配层只保留自己的生命周期胶水(React 的 ref callback、Vue 的 watch)。\n */\n\ntype ClipboardReason = Exclude<TextAreaClipboardFailure, \"stale\">;\n\n/** 平台拒绝。`stale` 只由 Core 在 ticket 过期时产生。 */\nexport class TextAreaClipboardReadError extends Error {\n readonly reason: ClipboardReason;\n constructor(reason: ClipboardReason) {\n super(reason);\n this.name = \"TextAreaClipboardReadError\";\n this.reason = reason;\n }\n}\n\n/** 宿主栈自己的写值前置动作。React 需要先推进它内部的 value tracker;其它栈不需要。 */\nexport interface TextAreaPlatformHost {\n trackValue?(target: HTMLTextAreaElement, value: string): void;\n}\n\nfunction controlDisabled(target: HTMLTextAreaElement): boolean {\n return target.matches(\":disabled\");\n}\n\nfunction px(value: string): number {\n const parsed = Number.parseFloat(value);\n return Number.isFinite(parsed) ? parsed : Number.NaN;\n}\n\nfunction clipboardReason(error: unknown): ClipboardReason {\n const name = error && typeof error === \"object\" && \"name\" in error ? String((error as { name: unknown }).name) : \"\";\n return name === \"AbortError\" ? \"aborted\" : \"denied\";\n}\n\n/**\n * 只做 ref 之后的监听、测量和写回。不判断接受、截断或组合。\n * 调用方在 target 与 sink 都可用之后再进入这里。\n */\nexport function attachTextAreaPlatform(target: HTMLTextAreaElement, getSink: () => TextAreaPlatformSink, host?: TextAreaPlatformHost): () => void {\n const sink = getSink();\n const view = target.ownerDocument.defaultView ?? globalThis;\n let disposed = false;\n let form: HTMLFormElement | null = null;\n let lastInline = target.getBoundingClientRect().width;\n let ignoreOwnResize = false;\n let ignoreToken = 0;\n let callerCaptured = false;\n let callerHeight = \"\";\n let callerPriority = \"\";\n let wroteNumber = false;\n let lastWritten: number | undefined;\n let wasIntersecting = target.getClientRects().length > 0;\n\n const armIgnore = () => {\n ignoreOwnResize = true;\n const token = ++ignoreToken;\n view.requestAnimationFrame?.(() => {\n if (!disposed && token === ignoreToken) ignoreOwnResize = false;\n });\n };\n\n const notify = () => {\n if (!disposed) sink.changed();\n };\n\n const client: TextAreaPlatformClient = {\n readControl: () => ({ value: target.value, disabled: controlDisabled(target) }),\n measureIntrinsic(): TextAreaSizeSnapshot {\n const previous = target.style.getPropertyValue(\"height\");\n const priority = target.style.getPropertyPriority(\"height\");\n armIgnore();\n target.style.setProperty(\"height\", \"auto\");\n try {\n const style = view.getComputedStyle(target);\n const rect = target.getBoundingClientRect();\n return {\n scrollHeight: target.scrollHeight,\n inlineSize: rect.width,\n lineHeight: px(style.lineHeight),\n paddingBlockSize: px(style.paddingTop) + px(style.paddingBottom),\n borderBlockSize: px(style.borderTopWidth) + px(style.borderBottomWidth),\n boxSizing: style.boxSizing === \"border-box\" ? \"border-box\" : \"content-box\",\n visible: style.display !== \"none\" && rect.width > 0 && rect.height > 0,\n };\n } finally {\n if (previous) target.style.setProperty(\"height\", previous, priority);\n else target.style.removeProperty(\"height\");\n }\n },\n writeValue(value, defaultValue) {\n target.defaultValue = defaultValue;\n host?.trackValue?.(target, value);\n if (target.value !== value) target.value = value;\n },\n writeHeight(height) {\n if (typeof height === \"number\" && Number.isFinite(height)) {\n if (wroteNumber && lastWritten === height) return;\n if (!callerCaptured) {\n callerHeight = target.style.getPropertyValue(\"height\");\n callerPriority = target.style.getPropertyPriority(\"height\");\n callerCaptured = true;\n }\n armIgnore();\n target.style.setProperty(\"height\", `${height}px`);\n lastWritten = height;\n wroteNumber = true;\n return;\n }\n if (!wroteNumber) return;\n armIgnore();\n if (callerHeight) target.style.setProperty(\"height\", callerHeight, callerPriority);\n else target.style.removeProperty(\"height\");\n callerCaptured = false;\n wroteNumber = false;\n lastWritten = undefined;\n },\n focus() {\n target.focus();\n },\n blur() {\n target.blur();\n },\n readClipboardText() {\n const clipboard = view.navigator?.clipboard;\n const readText = clipboard?.readText;\n if (!clipboard || typeof readText !== \"function\") return Promise.reject(new TextAreaClipboardReadError(\"unsupported\"));\n return Promise.resolve()\n .then(() => readText.call(clipboard))\n .then((text) => {\n if (typeof text !== \"string\") throw new TextAreaClipboardReadError(\"denied\");\n return text;\n })\n .catch((error: unknown) => {\n if (error instanceof TextAreaClipboardReadError) throw error;\n throw new TextAreaClipboardReadError(clipboardReason(error));\n });\n },\n };\n\n const onReset = (event: Event) => {\n const notice = event;\n queueMicrotask(() => {\n if (!disposed) sink.reset({ defaultPrevented: notice.defaultPrevented });\n });\n };\n const syncForm = () => {\n const next = target.form;\n if (next === form) return;\n form?.removeEventListener(\"reset\", onReset);\n form = next;\n form?.addEventListener(\"reset\", onReset);\n };\n const tree = new view.MutationObserver(() => {\n syncForm();\n watchTree();\n queueMicrotask(() => {\n if (disposed) return;\n syncForm();\n watchTree();\n });\n });\n const fields = new view.MutationObserver(() => {\n syncForm();\n notify();\n });\n // form 内容属性不变时,被引用 form 的 id 仍会改写 textarea.form。同一棵树里的 id 变化后重绑 reset。\n const formOwner = new view.MutationObserver(() => syncForm());\n const watchTree = () => {\n tree.disconnect();\n fields.disconnect();\n formOwner.disconnect();\n const parent = target.parentElement;\n if (parent) tree.observe(parent, { childList: true });\n let node = target.parentElement;\n while (node) {\n if (node.tagName === \"FIELDSET\" || node.tagName === \"FORM\") {\n fields.observe(node, { attributes: true, attributeFilter: [\"disabled\"] });\n }\n node = node.parentElement;\n }\n const root = target.getRootNode();\n const scope = root === target.ownerDocument ? target.ownerDocument.documentElement : root;\n if (scope) formOwner.observe(scope, { subtree: true, attributes: true, attributeFilter: [\"id\"] });\n };\n const formAttribute = new view.MutationObserver(() => syncForm());\n formAttribute.observe(target, { attributes: true, attributeFilter: [\"form\"] });\n syncForm();\n watchTree();\n\n const editTypes = { input: \"input\", compositionstart: \"composition-start\", compositionupdate: \"composition-update\", compositionend: \"composition-end\" } as const;\n const onEdit = (event: Event) => {\n syncForm();\n if (!disposed) sink.edit({ type: editTypes[event.type as keyof typeof editTypes], value: target.value });\n };\n const listeners: Record<string, EventListener> = {\n input: onEdit, compositionstart: onEdit, compositionupdate: onEdit, compositionend: onEdit,\n focus: () => { if (!disposed) sink.focusChanged(true); },\n blur: () => { if (!disposed) sink.focusChanged(false); },\n };\n for (const [name, listener] of Object.entries(listeners)) target.addEventListener(name, listener);\n\n let resize: ResizeObserver | undefined;\n let intersect: IntersectionObserver | undefined;\n if (typeof view.ResizeObserver === \"function\") {\n resize = new view.ResizeObserver((entries) => {\n const width = entries[0]?.contentRect?.width;\n const widthChanged = typeof width === \"number\" && width !== lastInline;\n if (typeof width === \"number\") lastInline = width;\n if (ignoreOwnResize) {\n ignoreOwnResize = false;\n if (!widthChanged) return;\n }\n notify();\n });\n resize.observe(target);\n }\n if (typeof view.IntersectionObserver === \"function\") {\n intersect = new view.IntersectionObserver((entries) => {\n const intersecting = entries.some((entry) => entry.isIntersecting);\n if (intersecting === wasIntersecting) return;\n wasIntersecting = intersecting;\n notify();\n });\n intersect.observe(target);\n }\n const fonts = target.ownerDocument.fonts;\n const onFonts = () => notify();\n if (fonts && typeof fonts.addEventListener === \"function\") fonts.addEventListener(\"loadingdone\", onFonts);\n if (fonts?.ready) void fonts.ready.then(onFonts);\n\n sink.commit(client);\n return () => {\n disposed = true;\n for (const [name, listener] of Object.entries(listeners)) target.removeEventListener(name, listener);\n form?.removeEventListener(\"reset\", onReset);\n form = null;\n formAttribute.disconnect();\n tree.disconnect();\n fields.disconnect();\n formOwner.disconnect();\n resize?.disconnect();\n intersect?.disconnect();\n if (fonts && typeof fonts.removeEventListener === \"function\") fonts.removeEventListener(\"loadingdone\", onFonts);\n sink.detach();\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./time-picker.js";
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { createMachine } from "@zag-js/core";
|
|
2
|
+
//#region src/time-picker/time-picker.ts
|
|
3
|
+
const TIME_PICKER_COLUMN_TYPES = [
|
|
4
|
+
"hour",
|
|
5
|
+
"minute",
|
|
6
|
+
"second"
|
|
7
|
+
];
|
|
8
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
9
|
+
const seconds = (p) => p.hour * 3600 + p.minute * 60 + p.second;
|
|
10
|
+
function parseTimePickerValue(value) {
|
|
11
|
+
if (typeof value !== "string" || !/^([01]\d|2[0-3])(?::[0-5]\d){0,2}$/.test(value)) return void 0;
|
|
12
|
+
const [hour = 0, minute = 0, second = 0] = value.split(":").map(Number);
|
|
13
|
+
return {
|
|
14
|
+
hour,
|
|
15
|
+
minute,
|
|
16
|
+
second
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function resolveTimePickerPrecision(value) {
|
|
20
|
+
return value === "hour" || value === "second" ? value : "minute";
|
|
21
|
+
}
|
|
22
|
+
function formatTimePickerValue(parts, precision = "minute") {
|
|
23
|
+
return [
|
|
24
|
+
pad(parts.hour),
|
|
25
|
+
...precision !== "hour" ? [pad(parts.minute)] : [],
|
|
26
|
+
...precision === "second" ? [pad(parts.second)] : []
|
|
27
|
+
].join(":");
|
|
28
|
+
}
|
|
29
|
+
const typesOf = (precision) => TIME_PICKER_COLUMN_TYPES.slice(0, TIME_PICKER_COLUMN_TYPES.indexOf(precision) + 1);
|
|
30
|
+
const detail = (parts, precision) => ({
|
|
31
|
+
value: formatTimePickerValue(parts, precision),
|
|
32
|
+
parts: { ...parts }
|
|
33
|
+
});
|
|
34
|
+
/** Build enabled combinations once per Core render. At most 86400 plain time records; no Date objects. */
|
|
35
|
+
function getTimePickerCandidates(props) {
|
|
36
|
+
const precision = resolveTimePickerPrecision(props.precision), types = typesOf(precision);
|
|
37
|
+
let min = seconds(parseTimePickerValue(props.min) ?? {
|
|
38
|
+
hour: 0,
|
|
39
|
+
minute: 0,
|
|
40
|
+
second: 0
|
|
41
|
+
});
|
|
42
|
+
let max = seconds(parseTimePickerValue(props.max) ?? {
|
|
43
|
+
hour: 23,
|
|
44
|
+
minute: 59,
|
|
45
|
+
second: 59
|
|
46
|
+
});
|
|
47
|
+
if (min > max) [min, max] = [max, min];
|
|
48
|
+
const step = (type) => Number.isInteger(props.steps?.[type]) && props.steps[type] > 0 ? Math.min(type === "hour" ? 24 : 60, props.steps[type]) : 1;
|
|
49
|
+
const result = [];
|
|
50
|
+
for (let hour = 0; hour < 24; hour += step("hour")) for (let minute = 0; minute < (types.includes("minute") ? 60 : 1); minute += step("minute")) for (let second = 0; second < (types.includes("second") ? 60 : 1); second += step("second")) {
|
|
51
|
+
const parts = {
|
|
52
|
+
hour,
|
|
53
|
+
minute,
|
|
54
|
+
second
|
|
55
|
+
}, time = seconds(parts);
|
|
56
|
+
if (time >= min && time <= max && !props.disabledTime?.(parts)) result.push(parts);
|
|
57
|
+
}
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
function nearest(candidates, input) {
|
|
61
|
+
const target = seconds(parseTimePickerValue(input) ?? {
|
|
62
|
+
hour: 0,
|
|
63
|
+
minute: 0,
|
|
64
|
+
second: 0
|
|
65
|
+
});
|
|
66
|
+
return candidates.reduce((best, p) => !best || Math.abs(seconds(p) - target) < Math.abs(seconds(best) - target) ? p : best, void 0);
|
|
67
|
+
}
|
|
68
|
+
function createTimePickerProps(props) {
|
|
69
|
+
return {
|
|
70
|
+
...props,
|
|
71
|
+
precision: resolveTimePickerPrecision(props.precision)
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function candidatesOf({ prop, refs }) {
|
|
75
|
+
const props = {
|
|
76
|
+
precision: prop("precision"),
|
|
77
|
+
min: prop("min"),
|
|
78
|
+
max: prop("max"),
|
|
79
|
+
steps: prop("steps"),
|
|
80
|
+
disabledTime: prop("disabledTime")
|
|
81
|
+
};
|
|
82
|
+
const key = JSON.stringify([
|
|
83
|
+
props.precision,
|
|
84
|
+
props.min,
|
|
85
|
+
props.max,
|
|
86
|
+
...TIME_PICKER_COLUMN_TYPES.map((type) => props.steps?.[type])
|
|
87
|
+
]);
|
|
88
|
+
const cache = refs.get("candidates");
|
|
89
|
+
if (cache?.key === key && cache.predicate === props.disabledTime) return cache.value;
|
|
90
|
+
const value = getTimePickerCandidates(props);
|
|
91
|
+
refs.set("candidates", {
|
|
92
|
+
key,
|
|
93
|
+
predicate: props.disabledTime,
|
|
94
|
+
value
|
|
95
|
+
});
|
|
96
|
+
return value;
|
|
97
|
+
}
|
|
98
|
+
const timePickerMachine = createMachine({
|
|
99
|
+
props: ({ props }) => createTimePickerProps(props),
|
|
100
|
+
initialState: () => "idle",
|
|
101
|
+
states: { idle: {} },
|
|
102
|
+
context: ({ bindable, prop }) => ({
|
|
103
|
+
value: bindable(() => ({
|
|
104
|
+
defaultValue: prop("defaultValue") ?? "00:00",
|
|
105
|
+
value: prop("value")
|
|
106
|
+
})),
|
|
107
|
+
preview: bindable(() => ({
|
|
108
|
+
defaultValue: [],
|
|
109
|
+
hash: JSON.stringify
|
|
110
|
+
})),
|
|
111
|
+
base: bindable(() => ({ defaultValue: "" }))
|
|
112
|
+
}),
|
|
113
|
+
refs: () => ({ candidates: void 0 }),
|
|
114
|
+
on: {
|
|
115
|
+
PREVIEW: { actions: ["preview"] },
|
|
116
|
+
COMMIT: { actions: ["commit"] },
|
|
117
|
+
RESET: { actions: ["reset"] }
|
|
118
|
+
},
|
|
119
|
+
implementations: { actions: {
|
|
120
|
+
reset({ context }) {
|
|
121
|
+
context.set("preview", []);
|
|
122
|
+
context.set("base", "");
|
|
123
|
+
},
|
|
124
|
+
preview({ context, prop, refs, event }) {
|
|
125
|
+
if (event.type !== "PREVIEW") return;
|
|
126
|
+
const p = nearest(candidatesOf({
|
|
127
|
+
prop,
|
|
128
|
+
refs
|
|
129
|
+
}), event.value.map((v) => pad(Number(v))).join(":"));
|
|
130
|
+
context.set("base", context.get("value"));
|
|
131
|
+
context.set("preview", [...event.value]);
|
|
132
|
+
if (p) prop("onPreviewChange")?.(detail(p, resolveTimePickerPrecision(prop("precision"))));
|
|
133
|
+
},
|
|
134
|
+
commit({ context, prop, refs, event }) {
|
|
135
|
+
if (event.type !== "COMMIT") return;
|
|
136
|
+
const p = nearest(candidatesOf({
|
|
137
|
+
prop,
|
|
138
|
+
refs
|
|
139
|
+
}), event.value.map((v) => pad(Number(v))).join(":"));
|
|
140
|
+
if (!p) return;
|
|
141
|
+
const change = detail(p, resolveTimePickerPrecision(prop("precision")));
|
|
142
|
+
context.set("value", change.value);
|
|
143
|
+
context.set("preview", []);
|
|
144
|
+
prop("onValueChange")?.(change);
|
|
145
|
+
}
|
|
146
|
+
} }
|
|
147
|
+
});
|
|
148
|
+
function connectTimePicker(service, props) {
|
|
149
|
+
const precision = resolveTimePickerPrecision(props.precision), types = typesOf(precision), candidates = candidatesOf(service);
|
|
150
|
+
const committed = nearest(candidates, service.context.get("value")), value = committed ? formatTimePickerValue(committed, precision) : "";
|
|
151
|
+
const raw = service.context.get("base") === service.context.get("value") ? service.context.get("preview") : [];
|
|
152
|
+
const preview = nearest(candidates, raw.length ? raw.map((v) => pad(Number(v))).join(":") : value);
|
|
153
|
+
const columns = types.map((type, index) => {
|
|
154
|
+
const values = [...new Set(candidates.filter((p) => types.slice(0, index).every((key) => p[key] === preview?.[key])).map((p) => p[type]))];
|
|
155
|
+
return {
|
|
156
|
+
label: props.columnLabels?.[type] ?? {
|
|
157
|
+
hour: "时",
|
|
158
|
+
minute: "分",
|
|
159
|
+
second: "秒"
|
|
160
|
+
}[type],
|
|
161
|
+
options: values.map((n) => ({
|
|
162
|
+
value: String(n),
|
|
163
|
+
label: props.formatter?.(type, n) ?? pad(n)
|
|
164
|
+
}))
|
|
165
|
+
};
|
|
166
|
+
});
|
|
167
|
+
const notifyPreview = (v) => service.send({
|
|
168
|
+
type: "PREVIEW",
|
|
169
|
+
value: [...v]
|
|
170
|
+
});
|
|
171
|
+
const notifyCommit = (v) => service.send({
|
|
172
|
+
type: "COMMIT",
|
|
173
|
+
value: [...v]
|
|
174
|
+
});
|
|
175
|
+
const rest = { ...props };
|
|
176
|
+
for (const key of [
|
|
177
|
+
"value",
|
|
178
|
+
"defaultValue",
|
|
179
|
+
"precision",
|
|
180
|
+
"min",
|
|
181
|
+
"max",
|
|
182
|
+
"steps",
|
|
183
|
+
"disabledTime",
|
|
184
|
+
"formatter",
|
|
185
|
+
"columnLabels",
|
|
186
|
+
"name",
|
|
187
|
+
"onValueChange",
|
|
188
|
+
"onPreviewChange"
|
|
189
|
+
]) delete rest[key];
|
|
190
|
+
return {
|
|
191
|
+
value,
|
|
192
|
+
valid: !!committed,
|
|
193
|
+
previewValue: preview ? formatTimePickerValue(preview, precision) : "",
|
|
194
|
+
columns,
|
|
195
|
+
pickerProps: {
|
|
196
|
+
...rest,
|
|
197
|
+
id: props.id ? `${props.id}-picker` : void 0,
|
|
198
|
+
ariaLabel: props.ariaLabel ?? "选择时间",
|
|
199
|
+
columns,
|
|
200
|
+
value: committed ? types.map((type) => String(committed[type])) : types.map(() => null),
|
|
201
|
+
onValueChange: (d) => notifyCommit(d.value),
|
|
202
|
+
onPreviewChange: (d) => notifyPreview(d.value),
|
|
203
|
+
onOpenChange: (open) => {
|
|
204
|
+
if (open) service.send({ type: "RESET" });
|
|
205
|
+
props.onOpenChange?.(open);
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
notifyPreview,
|
|
209
|
+
notifyCommit,
|
|
210
|
+
getRootProps: () => ({
|
|
211
|
+
lang: props.lang,
|
|
212
|
+
dir: props.dir,
|
|
213
|
+
"data-scope": "time-picker",
|
|
214
|
+
"data-part": "root",
|
|
215
|
+
"data-visual-target": "time-picker-root"
|
|
216
|
+
}),
|
|
217
|
+
getInputProps: () => ({
|
|
218
|
+
type: "hidden",
|
|
219
|
+
name: props.name,
|
|
220
|
+
value,
|
|
221
|
+
disabled: !committed
|
|
222
|
+
})
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
//#endregion
|
|
226
|
+
export { TIME_PICKER_COLUMN_TYPES, connectTimePicker, createTimePickerProps, formatTimePickerValue, getTimePickerCandidates, parseTimePickerValue, resolveTimePickerPrecision, timePickerMachine };
|
|
227
|
+
|
|
228
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/time-picker/time-picker.ts"],"sourcesContent":["import { createMachine, type Machine, type Service } from \"@zag-js/core\";\nimport type { QwPickerProps } from \"../picker/picker.js\";\nimport type { PickerColumn, PickerValue } from \"../picker/selection-model.js\";\n\nexport const TIME_PICKER_COLUMN_TYPES = [\"hour\", \"minute\", \"second\"] as const;\nexport type TimePickerColumnType = (typeof TIME_PICKER_COLUMN_TYPES)[number];\nexport type TimePickerPrecision = TimePickerColumnType;\n/** A time of day without date, offset, timezone or daylight-saving interpretation. */\nexport interface TimePickerParts { hour: number; minute: number; second: number }\nexport interface TimePickerChangeDetails { value: string; parts: TimePickerParts }\nexport interface QwTimePickerProps extends Omit<QwPickerProps, \"columns\" | \"value\" | \"defaultValue\" | \"onValueChange\" | \"onPreviewChange\"> {\n value?: string;\n /** Explicit locale boundary copied by the real Picker portal. */\n lang?: string;\n dir?: string;\n defaultValue?: string;\n precision?: TimePickerPrecision;\n min?: string;\n max?: string;\n steps?: Partial<Record<TimePickerColumnType, number>>;\n disabledTime?: (parts: TimePickerParts) => boolean;\n formatter?: (type: TimePickerColumnType, value: number) => string;\n columnLabels?: Partial<Record<TimePickerColumnType, string>>;\n /** Optional native form field. Empty when no valid combination exists. */\n name?: string;\n onValueChange?: (details: TimePickerChangeDetails) => void;\n onPreviewChange?: (details: TimePickerChangeDetails) => void;\n}\nconst pad = (n: number) => String(n).padStart(2, \"0\");\nconst seconds = (p: TimePickerParts) => p.hour * 3600 + p.minute * 60 + p.second;\nexport function parseTimePickerValue(value: unknown): TimePickerParts | undefined {\n if (typeof value !== \"string\" || !/^([01]\\d|2[0-3])(?::[0-5]\\d){0,2}$/.test(value)) return undefined;\n const [hour = 0, minute = 0, second = 0] = value.split(\":\").map(Number);\n return { hour, minute, second };\n}\nexport function resolveTimePickerPrecision(value: unknown): TimePickerPrecision {\n return value === \"hour\" || value === \"second\" ? value : \"minute\";\n}\nexport function formatTimePickerValue(parts: TimePickerParts, precision: TimePickerPrecision = \"minute\"): string {\n return [pad(parts.hour), ...(precision !== \"hour\" ? [pad(parts.minute)] : []), ...(precision === \"second\" ? [pad(parts.second)] : [])].join(\":\");\n}\nconst typesOf = (precision: TimePickerPrecision) => TIME_PICKER_COLUMN_TYPES.slice(0, TIME_PICKER_COLUMN_TYPES.indexOf(precision) + 1);\nconst detail = (parts: TimePickerParts, precision: TimePickerPrecision): TimePickerChangeDetails => ({ value: formatTimePickerValue(parts, precision), parts: { ...parts } });\n/** Build enabled combinations once per Core render. At most 86400 plain time records; no Date objects. */\nexport function getTimePickerCandidates(props: QwTimePickerProps): TimePickerParts[] {\n const precision = resolveTimePickerPrecision(props.precision), types = typesOf(precision);\n let min = seconds(parseTimePickerValue(props.min) ?? { hour: 0, minute: 0, second: 0 });\n let max = seconds(parseTimePickerValue(props.max) ?? { hour: 23, minute: 59, second: 59 });\n if (min > max) [min, max] = [max, min];\n const step = (type: TimePickerColumnType) => Number.isInteger(props.steps?.[type]) && props.steps![type]! > 0 ? Math.min(type === \"hour\" ? 24 : 60, props.steps![type]!) : 1;\n const result: TimePickerParts[] = [];\n for (let hour = 0; hour < 24; hour += step(\"hour\")) {\n for (let minute = 0; minute < (types.includes(\"minute\") ? 60 : 1); minute += step(\"minute\")) {\n for (let second = 0; second < (types.includes(\"second\") ? 60 : 1); second += step(\"second\")) {\n const parts = { hour, minute, second }, time = seconds(parts);\n if (time >= min && time <= max && !props.disabledTime?.(parts)) result.push(parts);\n }\n }\n }\n return result;\n}\nfunction nearest(candidates: TimePickerParts[], input: unknown): TimePickerParts | undefined {\n const target = seconds(parseTimePickerValue(input) ?? { hour: 0, minute: 0, second: 0 });\n return candidates.reduce<TimePickerParts | undefined>((best, p) => !best || Math.abs(seconds(p) - target) < Math.abs(seconds(best) - target) ? p : best, undefined);\n}\nexport interface QwTimePickerSchema {\n props: QwTimePickerProps;\n context: { value: string; preview: PickerValue; base: string };\n refs: { candidates: { key: string; predicate: QwTimePickerProps[\"disabledTime\"]; value: TimePickerParts[] } | undefined };\n state: \"idle\";\n action: \"preview\" | \"commit\" | \"reset\";\n event: { type: \"PREVIEW\" | \"COMMIT\"; value: PickerValue } | { type: \"RESET\" };\n}\nexport type QwTimePickerMachine = Machine<QwTimePickerSchema>;\nexport type QwTimePickerService = Service<QwTimePickerSchema>;\nexport function createTimePickerProps(props: QwTimePickerProps): QwTimePickerProps { return { ...props, precision: resolveTimePickerPrecision(props.precision) }; }\ntype CandidateReader = Pick<QwTimePickerService, \"prop\" | \"refs\">;\nfunction candidatesOf({ prop, refs }: CandidateReader): TimePickerParts[] {\n const props: QwTimePickerProps = { precision: prop(\"precision\"), min: prop(\"min\"), max: prop(\"max\"), steps: prop(\"steps\"), disabledTime: prop(\"disabledTime\") };\n const key = JSON.stringify([props.precision, props.min, props.max, ...TIME_PICKER_COLUMN_TYPES.map(type => props.steps?.[type])]);\n const cache = refs.get(\"candidates\");\n if (cache?.key === key && cache.predicate === props.disabledTime) return cache.value;\n const value = getTimePickerCandidates(props);\n refs.set(\"candidates\", { key, predicate: props.disabledTime, value });\n return value;\n}\nexport const timePickerMachine: QwTimePickerMachine = createMachine<QwTimePickerSchema>({\n props: ({ props }) => createTimePickerProps(props), initialState: () => \"idle\", states: { idle: {} },\n context: ({ bindable, prop }) => ({\n value: bindable(() => ({ defaultValue: prop(\"defaultValue\") ?? \"00:00\", value: prop(\"value\") })),\n preview: bindable<PickerValue>(() => ({ defaultValue: [], hash: JSON.stringify })),\n base: bindable(() => ({ defaultValue: \"\" })),\n }),\n refs: () => ({ candidates: undefined }),\n on: { PREVIEW: { actions: [\"preview\"] }, COMMIT: { actions: [\"commit\"] }, RESET: { actions: [\"reset\"] } },\n implementations: { actions: {\n reset({ context }) { context.set(\"preview\", []); context.set(\"base\", \"\"); },\n preview({ context, prop, refs, event }) {\n if (event.type !== \"PREVIEW\") return;\n const p = nearest(candidatesOf({ prop, refs }), event.value.map(v => pad(Number(v))).join(\":\"));\n context.set(\"base\", context.get(\"value\")); context.set(\"preview\", [...event.value]);\n if (p) prop(\"onPreviewChange\")?.(detail(p, resolveTimePickerPrecision(prop(\"precision\"))));\n },\n commit({ context, prop, refs, event }) {\n if (event.type !== \"COMMIT\") return;\n const p = nearest(candidatesOf({ prop, refs }), event.value.map(v => pad(Number(v))).join(\":\"));\n if (!p) return;\n const change = detail(p, resolveTimePickerPrecision(prop(\"precision\"))); context.set(\"value\", change.value); context.set(\"preview\", []); prop(\"onValueChange\")?.(change);\n },\n } },\n});\nexport interface QwTimePickerApi {\n value: string;\n previewValue: string;\n valid: boolean;\n columns: PickerColumn[];\n pickerProps: QwPickerProps;\n notifyPreview(value: PickerValue): void;\n notifyCommit(value: PickerValue): void;\n getRootProps(): Record<string, string | undefined>;\n getInputProps(): { type: \"hidden\"; name: string | undefined; value: string; disabled: boolean };\n}\nexport function connectTimePicker(service: QwTimePickerService, props: QwTimePickerProps): QwTimePickerApi {\n const precision = resolveTimePickerPrecision(props.precision), types = typesOf(precision), candidates = candidatesOf(service);\n const committed = nearest(candidates, service.context.get(\"value\")), value = committed ? formatTimePickerValue(committed, precision) : \"\";\n const raw = service.context.get(\"base\") === service.context.get(\"value\") ? service.context.get(\"preview\") : [];\n const wanted = raw.length ? raw.map(v => pad(Number(v))).join(\":\") : value;\n const preview = nearest(candidates, wanted);\n const columns = types.map((type, index): PickerColumn => {\n const values = [...new Set(candidates.filter(p => types.slice(0, index).every(key => p[key] === preview?.[key])).map(p => p[type]))];\n return { label: props.columnLabels?.[type] ?? ({ hour: \"时\", minute: \"分\", second: \"秒\" })[type], options: values.map(n => ({ value: String(n), label: props.formatter?.(type, n) ?? pad(n) })) };\n });\n const notifyPreview = (v: PickerValue) => service.send({ type: \"PREVIEW\", value: [...v] });\n const notifyCommit = (v: PickerValue) => service.send({ type: \"COMMIT\", value: [...v] });\n const rest: Record<string, unknown> = { ...props };\n for (const key of [\"value\", \"defaultValue\", \"precision\", \"min\", \"max\", \"steps\", \"disabledTime\", \"formatter\", \"columnLabels\", \"name\", \"onValueChange\", \"onPreviewChange\"]) delete rest[key];\n return { value, valid: !!committed, previewValue: preview ? formatTimePickerValue(preview, precision) : \"\", columns,\n pickerProps: { ...rest, id: props.id ? `${props.id}-picker` : undefined, ariaLabel: props.ariaLabel ?? \"选择时间\", columns, value: committed ? types.map(type => String(committed[type])) : types.map(() => null), onValueChange: d => notifyCommit(d.value), onPreviewChange: d => notifyPreview(d.value), onOpenChange: open => { if (open) service.send({ type: \"RESET\" }); props.onOpenChange?.(open); } },\n notifyPreview, notifyCommit,\n getRootProps: () => ({ lang: props.lang, dir: props.dir, \"data-scope\": \"time-picker\", \"data-part\": \"root\", \"data-visual-target\": \"time-picker-root\" }),\n getInputProps: () => ({ type: \"hidden\", name: props.name, value, disabled: !committed }),\n };\n}\n"],"mappings":";;AAIA,MAAa,2BAA2B;CAAC;CAAQ;CAAU;AAAQ;AAwBnE,MAAM,OAAO,MAAc,OAAO,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;AACpD,MAAM,WAAW,MAAuB,EAAE,OAAO,OAAO,EAAE,SAAS,KAAK,EAAE;AAC1E,SAAgB,qBAAqB,OAA6C;CAChF,IAAI,OAAO,UAAU,YAAY,CAAC,qCAAqC,KAAK,KAAK,GAAG,OAAO,KAAA;CAC3F,MAAM,CAAC,OAAO,GAAG,SAAS,GAAG,SAAS,KAAK,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI,MAAM;CACtE,OAAO;EAAE;EAAM;EAAQ;CAAO;AAChC;AACA,SAAgB,2BAA2B,OAAqC;CAC9E,OAAO,UAAU,UAAU,UAAU,WAAW,QAAQ;AAC1D;AACA,SAAgB,sBAAsB,OAAwB,YAAiC,UAAkB;CAC/G,OAAO;EAAC,IAAI,MAAM,IAAI;EAAG,GAAI,cAAc,SAAS,CAAC,IAAI,MAAM,MAAM,CAAC,IAAI,CAAC;EAAI,GAAI,cAAc,WAAW,CAAC,IAAI,MAAM,MAAM,CAAC,IAAI,CAAC;CAAE,CAAC,CAAC,KAAK,GAAG;AACjJ;AACA,MAAM,WAAW,cAAmC,yBAAyB,MAAM,GAAG,yBAAyB,QAAQ,SAAS,IAAI,CAAC;AACrI,MAAM,UAAU,OAAwB,eAA6D;CAAE,OAAO,sBAAsB,OAAO,SAAS;CAAG,OAAO,EAAE,GAAG,MAAM;AAAE;;AAE3K,SAAgB,wBAAwB,OAA6C;CACnF,MAAM,YAAY,2BAA2B,MAAM,SAAS,GAAG,QAAQ,QAAQ,SAAS;CACxF,IAAI,MAAM,QAAQ,qBAAqB,MAAM,GAAG,KAAK;EAAE,MAAM;EAAG,QAAQ;EAAG,QAAQ;CAAE,CAAC;CACtF,IAAI,MAAM,QAAQ,qBAAqB,MAAM,GAAG,KAAK;EAAE,MAAM;EAAI,QAAQ;EAAI,QAAQ;CAAG,CAAC;CACzF,IAAI,MAAM,KAAK,CAAC,KAAK,OAAO,CAAC,KAAK,GAAG;CACrC,MAAM,QAAQ,SAA+B,OAAO,UAAU,MAAM,QAAQ,KAAK,KAAK,MAAM,MAAO,QAAS,IAAI,KAAK,IAAI,SAAS,SAAS,KAAK,IAAI,MAAM,MAAO,KAAM,IAAI;CAC3K,MAAM,SAA4B,CAAC;CACnC,KAAK,IAAI,OAAO,GAAG,OAAO,IAAI,QAAQ,KAAK,MAAM,GAC/C,KAAK,IAAI,SAAS,GAAG,UAAU,MAAM,SAAS,QAAQ,IAAI,KAAK,IAAI,UAAU,KAAK,QAAQ,GACxF,KAAK,IAAI,SAAS,GAAG,UAAU,MAAM,SAAS,QAAQ,IAAI,KAAK,IAAI,UAAU,KAAK,QAAQ,GAAG;EAC3F,MAAM,QAAQ;GAAE;GAAM;GAAQ;EAAO,GAAG,OAAO,QAAQ,KAAK;EAC5D,IAAI,QAAQ,OAAO,QAAQ,OAAO,CAAC,MAAM,eAAe,KAAK,GAAG,OAAO,KAAK,KAAK;CACnF;CAGJ,OAAO;AACT;AACA,SAAS,QAAQ,YAA+B,OAA6C;CAC3F,MAAM,SAAS,QAAQ,qBAAqB,KAAK,KAAK;EAAE,MAAM;EAAG,QAAQ;EAAG,QAAQ;CAAE,CAAC;CACvF,OAAO,WAAW,QAAqC,MAAM,MAAM,CAAC,QAAQ,KAAK,IAAI,QAAQ,CAAC,IAAI,MAAM,IAAI,KAAK,IAAI,QAAQ,IAAI,IAAI,MAAM,IAAI,IAAI,MAAM,KAAA,CAAS;AACpK;AAWA,SAAgB,sBAAsB,OAA6C;CAAE,OAAO;EAAE,GAAG;EAAO,WAAW,2BAA2B,MAAM,SAAS;CAAE;AAAG;AAElK,SAAS,aAAa,EAAE,MAAM,QAA4C;CACxE,MAAM,QAA2B;EAAE,WAAW,KAAK,WAAW;EAAG,KAAK,KAAK,KAAK;EAAG,KAAK,KAAK,KAAK;EAAG,OAAO,KAAK,OAAO;EAAG,cAAc,KAAK,cAAc;CAAE;CAC9J,MAAM,MAAM,KAAK,UAAU;EAAC,MAAM;EAAW,MAAM;EAAK,MAAM;EAAK,GAAG,yBAAyB,KAAI,SAAQ,MAAM,QAAQ,KAAK;CAAC,CAAC;CAChI,MAAM,QAAQ,KAAK,IAAI,YAAY;CACnC,IAAI,OAAO,QAAQ,OAAO,MAAM,cAAc,MAAM,cAAc,OAAO,MAAM;CAC/E,MAAM,QAAQ,wBAAwB,KAAK;CAC3C,KAAK,IAAI,cAAc;EAAE;EAAK,WAAW,MAAM;EAAc;CAAM,CAAC;CACpE,OAAO;AACT;AACA,MAAa,oBAAyC,cAAkC;CACtF,QAAQ,EAAE,YAAY,sBAAsB,KAAK;CAAG,oBAAoB;CAAQ,QAAQ,EAAE,MAAM,CAAC,EAAE;CACnG,UAAU,EAAE,UAAU,YAAY;EAChC,OAAO,gBAAgB;GAAE,cAAc,KAAK,cAAc,KAAK;GAAS,OAAO,KAAK,OAAO;EAAE,EAAE;EAC/F,SAAS,gBAA6B;GAAE,cAAc,CAAC;GAAG,MAAM,KAAK;EAAU,EAAE;EACjF,MAAM,gBAAgB,EAAE,cAAc,GAAG,EAAE;CAC7C;CACA,aAAa,EAAE,YAAY,KAAA,EAAU;CACrC,IAAI;EAAE,SAAS,EAAE,SAAS,CAAC,SAAS,EAAE;EAAG,QAAQ,EAAE,SAAS,CAAC,QAAQ,EAAE;EAAG,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE;CAAE;CACxG,iBAAiB,EAAE,SAAS;EAC1B,MAAM,EAAE,WAAW;GAAE,QAAQ,IAAI,WAAW,CAAC,CAAC;GAAG,QAAQ,IAAI,QAAQ,EAAE;EAAG;EAC1E,QAAQ,EAAE,SAAS,MAAM,MAAM,SAAS;GACtC,IAAI,MAAM,SAAS,WAAW;GAC9B,MAAM,IAAI,QAAQ,aAAa;IAAE;IAAM;GAAK,CAAC,GAAG,MAAM,MAAM,KAAI,MAAK,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC;GAC9F,QAAQ,IAAI,QAAQ,QAAQ,IAAI,OAAO,CAAC;GAAG,QAAQ,IAAI,WAAW,CAAC,GAAG,MAAM,KAAK,CAAC;GAClF,IAAI,GAAG,KAAK,iBAAiB,CAAC,GAAG,OAAO,GAAG,2BAA2B,KAAK,WAAW,CAAC,CAAC,CAAC;EAC3F;EACA,OAAO,EAAE,SAAS,MAAM,MAAM,SAAS;GACrC,IAAI,MAAM,SAAS,UAAU;GAC7B,MAAM,IAAI,QAAQ,aAAa;IAAE;IAAM;GAAK,CAAC,GAAG,MAAM,MAAM,KAAI,MAAK,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC;GAC9F,IAAI,CAAC,GAAG;GACR,MAAM,SAAS,OAAO,GAAG,2BAA2B,KAAK,WAAW,CAAC,CAAC;GAAG,QAAQ,IAAI,SAAS,OAAO,KAAK;GAAG,QAAQ,IAAI,WAAW,CAAC,CAAC;GAAG,KAAK,eAAe,CAAC,GAAG,MAAM;EACzK;CACF,EAAE;AACJ,CAAC;AAYD,SAAgB,kBAAkB,SAA8B,OAA2C;CACzG,MAAM,YAAY,2BAA2B,MAAM,SAAS,GAAG,QAAQ,QAAQ,SAAS,GAAG,aAAa,aAAa,OAAO;CAC5H,MAAM,YAAY,QAAQ,YAAY,QAAQ,QAAQ,IAAI,OAAO,CAAC,GAAG,QAAQ,YAAY,sBAAsB,WAAW,SAAS,IAAI;CACvI,MAAM,MAAM,QAAQ,QAAQ,IAAI,MAAM,MAAM,QAAQ,QAAQ,IAAI,OAAO,IAAI,QAAQ,QAAQ,IAAI,SAAS,IAAI,CAAC;CAE7G,MAAM,UAAU,QAAQ,YADT,IAAI,SAAS,IAAI,KAAI,MAAK,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,KAC3B;CAC1C,MAAM,UAAU,MAAM,KAAK,MAAM,UAAwB;EACvD,MAAM,SAAS,CAAC,GAAG,IAAI,IAAI,WAAW,QAAO,MAAK,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,OAAM,QAAO,EAAE,SAAS,UAAU,IAAI,CAAC,CAAC,CAAC,KAAI,MAAK,EAAE,KAAK,CAAC,CAAC;EACnI,OAAO;GAAE,OAAO,MAAM,eAAe,SAAU;IAAE,MAAM;IAAK,QAAQ;IAAK,QAAQ;GAAI,EAAG;GAAO,SAAS,OAAO,KAAI,OAAM;IAAE,OAAO,OAAO,CAAC;IAAG,OAAO,MAAM,YAAY,MAAM,CAAC,KAAK,IAAI,CAAC;GAAE,EAAE;EAAE;CAC/L,CAAC;CACD,MAAM,iBAAiB,MAAmB,QAAQ,KAAK;EAAE,MAAM;EAAW,OAAO,CAAC,GAAG,CAAC;CAAE,CAAC;CACzF,MAAM,gBAAgB,MAAmB,QAAQ,KAAK;EAAE,MAAM;EAAU,OAAO,CAAC,GAAG,CAAC;CAAE,CAAC;CACvF,MAAM,OAAgC,EAAE,GAAG,MAAM;CACjD,KAAK,MAAM,OAAO;EAAC;EAAS;EAAgB;EAAa;EAAO;EAAO;EAAS;EAAgB;EAAa;EAAgB;EAAQ;EAAiB;CAAiB,GAAG,OAAO,KAAK;CACtL,OAAO;EAAE;EAAO,OAAO,CAAC,CAAC;EAAW,cAAc,UAAU,sBAAsB,SAAS,SAAS,IAAI;EAAI;EAC1G,aAAa;GAAE,GAAG;GAAM,IAAI,MAAM,KAAK,GAAG,MAAM,GAAG,WAAW,KAAA;GAAW,WAAW,MAAM,aAAa;GAAQ;GAAS,OAAO,YAAY,MAAM,KAAI,SAAQ,OAAO,UAAU,KAAK,CAAC,IAAI,MAAM,UAAU,IAAI;GAAG,gBAAe,MAAK,aAAa,EAAE,KAAK;GAAG,kBAAiB,MAAK,cAAc,EAAE,KAAK;GAAG,eAAc,SAAQ;IAAE,IAAI,MAAM,QAAQ,KAAK,EAAE,MAAM,QAAQ,CAAC;IAAG,MAAM,eAAe,IAAI;GAAG;EAAE;EACzY;EAAe;EACf,qBAAqB;GAAE,MAAM,MAAM;GAAM,KAAK,MAAM;GAAK,cAAc;GAAe,aAAa;GAAQ,sBAAsB;EAAmB;EACpJ,sBAAsB;GAAE,MAAM;GAAU,MAAM,MAAM;GAAM;GAAO,UAAU,CAAC;EAAU;CACxF;AACF"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { type Machine, type Service } from "@zag-js/core";
|
|
2
|
+
import type { QwPickerProps } from "../picker/picker.js";
|
|
3
|
+
import type { PickerColumn, PickerValue } from "../picker/selection-model.js";
|
|
4
|
+
export declare const TIME_PICKER_COLUMN_TYPES: readonly ["hour", "minute", "second"];
|
|
5
|
+
export type TimePickerColumnType = (typeof TIME_PICKER_COLUMN_TYPES)[number];
|
|
6
|
+
export type TimePickerPrecision = TimePickerColumnType;
|
|
7
|
+
/** A time of day without date, offset, timezone or daylight-saving interpretation. */
|
|
8
|
+
export interface TimePickerParts {
|
|
9
|
+
hour: number;
|
|
10
|
+
minute: number;
|
|
11
|
+
second: number;
|
|
12
|
+
}
|
|
13
|
+
export interface TimePickerChangeDetails {
|
|
14
|
+
value: string;
|
|
15
|
+
parts: TimePickerParts;
|
|
16
|
+
}
|
|
17
|
+
export interface QwTimePickerProps extends Omit<QwPickerProps, "columns" | "value" | "defaultValue" | "onValueChange" | "onPreviewChange"> {
|
|
18
|
+
value?: string;
|
|
19
|
+
/** Explicit locale boundary copied by the real Picker portal. */
|
|
20
|
+
lang?: string;
|
|
21
|
+
dir?: string;
|
|
22
|
+
defaultValue?: string;
|
|
23
|
+
precision?: TimePickerPrecision;
|
|
24
|
+
min?: string;
|
|
25
|
+
max?: string;
|
|
26
|
+
steps?: Partial<Record<TimePickerColumnType, number>>;
|
|
27
|
+
disabledTime?: (parts: TimePickerParts) => boolean;
|
|
28
|
+
formatter?: (type: TimePickerColumnType, value: number) => string;
|
|
29
|
+
columnLabels?: Partial<Record<TimePickerColumnType, string>>;
|
|
30
|
+
/** Optional native form field. Empty when no valid combination exists. */
|
|
31
|
+
name?: string;
|
|
32
|
+
onValueChange?: (details: TimePickerChangeDetails) => void;
|
|
33
|
+
onPreviewChange?: (details: TimePickerChangeDetails) => void;
|
|
34
|
+
}
|
|
35
|
+
export declare function parseTimePickerValue(value: unknown): TimePickerParts | undefined;
|
|
36
|
+
export declare function resolveTimePickerPrecision(value: unknown): TimePickerPrecision;
|
|
37
|
+
export declare function formatTimePickerValue(parts: TimePickerParts, precision?: TimePickerPrecision): string;
|
|
38
|
+
/** Build enabled combinations once per Core render. At most 86400 plain time records; no Date objects. */
|
|
39
|
+
export declare function getTimePickerCandidates(props: QwTimePickerProps): TimePickerParts[];
|
|
40
|
+
export interface QwTimePickerSchema {
|
|
41
|
+
props: QwTimePickerProps;
|
|
42
|
+
context: {
|
|
43
|
+
value: string;
|
|
44
|
+
preview: PickerValue;
|
|
45
|
+
base: string;
|
|
46
|
+
};
|
|
47
|
+
refs: {
|
|
48
|
+
candidates: {
|
|
49
|
+
key: string;
|
|
50
|
+
predicate: QwTimePickerProps["disabledTime"];
|
|
51
|
+
value: TimePickerParts[];
|
|
52
|
+
} | undefined;
|
|
53
|
+
};
|
|
54
|
+
state: "idle";
|
|
55
|
+
action: "preview" | "commit" | "reset";
|
|
56
|
+
event: {
|
|
57
|
+
type: "PREVIEW" | "COMMIT";
|
|
58
|
+
value: PickerValue;
|
|
59
|
+
} | {
|
|
60
|
+
type: "RESET";
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export type QwTimePickerMachine = Machine<QwTimePickerSchema>;
|
|
64
|
+
export type QwTimePickerService = Service<QwTimePickerSchema>;
|
|
65
|
+
export declare function createTimePickerProps(props: QwTimePickerProps): QwTimePickerProps;
|
|
66
|
+
export declare const timePickerMachine: QwTimePickerMachine;
|
|
67
|
+
export interface QwTimePickerApi {
|
|
68
|
+
value: string;
|
|
69
|
+
previewValue: string;
|
|
70
|
+
valid: boolean;
|
|
71
|
+
columns: PickerColumn[];
|
|
72
|
+
pickerProps: QwPickerProps;
|
|
73
|
+
notifyPreview(value: PickerValue): void;
|
|
74
|
+
notifyCommit(value: PickerValue): void;
|
|
75
|
+
getRootProps(): Record<string, string | undefined>;
|
|
76
|
+
getInputProps(): {
|
|
77
|
+
type: "hidden";
|
|
78
|
+
name: string | undefined;
|
|
79
|
+
value: string;
|
|
80
|
+
disabled: boolean;
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
export declare function connectTimePicker(service: QwTimePickerService, props: QwTimePickerProps): QwTimePickerApi;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./timeline.js";
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { visuallyHiddenStyle } from "@zag-js/dom-query";
|
|
2
|
+
//#region src/timeline/timeline.ts
|
|
3
|
+
/** Ordered event history. Status is always expressed by marker shape and text, never color alone. */
|
|
4
|
+
const TIMELINE_STATUSES = [
|
|
5
|
+
"finished",
|
|
6
|
+
"process",
|
|
7
|
+
"wait",
|
|
8
|
+
"error"
|
|
9
|
+
];
|
|
10
|
+
const TIMELINE_PARTS = [
|
|
11
|
+
"root",
|
|
12
|
+
"item",
|
|
13
|
+
"marker",
|
|
14
|
+
"content",
|
|
15
|
+
"header",
|
|
16
|
+
"title",
|
|
17
|
+
"time",
|
|
18
|
+
"description",
|
|
19
|
+
"status"
|
|
20
|
+
];
|
|
21
|
+
const TIMELINE_DEFAULT_STATUS_LABELS = Object.freeze({
|
|
22
|
+
finished: "已完成",
|
|
23
|
+
process: "进行中",
|
|
24
|
+
wait: "未开始",
|
|
25
|
+
error: "异常"
|
|
26
|
+
});
|
|
27
|
+
/** Decorative marker glyphs; each status has a distinct shape in addition to its color role. */
|
|
28
|
+
const TIMELINE_MARKER_GLYPHS = Object.freeze({
|
|
29
|
+
finished: "✓",
|
|
30
|
+
process: "",
|
|
31
|
+
wait: "",
|
|
32
|
+
error: "!"
|
|
33
|
+
});
|
|
34
|
+
function normalizeCurrent(value) {
|
|
35
|
+
return typeof value === "number" && Number.isFinite(value) ? Math.floor(value) : void 0;
|
|
36
|
+
}
|
|
37
|
+
function isStatus(value) {
|
|
38
|
+
return TIMELINE_STATUSES.includes(value);
|
|
39
|
+
}
|
|
40
|
+
function resolveTimelineState(props) {
|
|
41
|
+
const items = props.items ?? [];
|
|
42
|
+
const current = normalizeCurrent(props.current);
|
|
43
|
+
const labels = {
|
|
44
|
+
...TIMELINE_DEFAULT_STATUS_LABELS,
|
|
45
|
+
...Object.fromEntries(Object.entries(props.statusLabels ?? {}).filter(([, text]) => typeof text === "string" && text !== ""))
|
|
46
|
+
};
|
|
47
|
+
const statuses = items.map((item, index) => isStatus(item.status) ? item.status : current === void 0 ? "finished" : index < current ? "finished" : index === current ? "process" : "wait");
|
|
48
|
+
const currentIndex = current !== void 0 ? current >= 0 && current < items.length ? current : -1 : statuses.indexOf("process");
|
|
49
|
+
const resolved = items.map((item, index) => {
|
|
50
|
+
const status = statuses[index];
|
|
51
|
+
return {
|
|
52
|
+
...item,
|
|
53
|
+
index,
|
|
54
|
+
status,
|
|
55
|
+
current: index === currentIndex,
|
|
56
|
+
statusText: labels[status],
|
|
57
|
+
glyph: TIMELINE_MARKER_GLYPHS[status],
|
|
58
|
+
last: false
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
const ordered = props.reverse === true ? resolved.reverse() : resolved;
|
|
62
|
+
if (ordered.length) ordered[ordered.length - 1].last = true;
|
|
63
|
+
return {
|
|
64
|
+
current,
|
|
65
|
+
reverse: props.reverse === true,
|
|
66
|
+
showStatus: props.showStatus === true,
|
|
67
|
+
items: ordered
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const part = (name) => ({
|
|
71
|
+
"data-scope": "timeline",
|
|
72
|
+
"data-part": name
|
|
73
|
+
});
|
|
74
|
+
function getTimelineRootProps(state) {
|
|
75
|
+
return {
|
|
76
|
+
...part("root"),
|
|
77
|
+
...state.reverse ? { "data-reverse": "true" } : {}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function getTimelineItemProps(item) {
|
|
81
|
+
return {
|
|
82
|
+
...part("item"),
|
|
83
|
+
"data-value": item.id,
|
|
84
|
+
"data-status": item.status,
|
|
85
|
+
...item.current ? {
|
|
86
|
+
"data-current": "true",
|
|
87
|
+
"aria-current": "step"
|
|
88
|
+
} : {},
|
|
89
|
+
...item.last ? { "data-last": "true" } : {}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function getTimelineMarkerProps(item) {
|
|
93
|
+
return {
|
|
94
|
+
...part("marker"),
|
|
95
|
+
"data-status": item.status,
|
|
96
|
+
"aria-hidden": "true"
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/** Status text precedes the title in reading order; visually hidden unless showStatus. */
|
|
100
|
+
function getTimelineStatusProps(state, item) {
|
|
101
|
+
return {
|
|
102
|
+
...part("status"),
|
|
103
|
+
"data-status": item.status,
|
|
104
|
+
"data-visible": state.showStatus ? "true" : "false",
|
|
105
|
+
...state.showStatus ? {} : { style: { ...visuallyHiddenStyle } }
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function getTimelineTimeProps(item) {
|
|
109
|
+
return {
|
|
110
|
+
...part("time"),
|
|
111
|
+
...item.dateTime ? { dateTime: item.dateTime } : {},
|
|
112
|
+
...item.time ? {} : { hidden: true }
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function getTimelineDescriptionProps(item) {
|
|
116
|
+
return {
|
|
117
|
+
...part("description"),
|
|
118
|
+
...item.description ? {} : { hidden: true }
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function getTimelinePartProps(name) {
|
|
122
|
+
return part(name);
|
|
123
|
+
}
|
|
124
|
+
/** Hidden status text carries a separator so "异常,配送失败" reads naturally; visible text is the bare label. */
|
|
125
|
+
function getTimelineStatusText(state, item) {
|
|
126
|
+
return state.showStatus ? item.statusText : `${item.statusText},`;
|
|
127
|
+
}
|
|
128
|
+
//#endregion
|
|
129
|
+
export { TIMELINE_DEFAULT_STATUS_LABELS, TIMELINE_MARKER_GLYPHS, TIMELINE_PARTS, TIMELINE_STATUSES, getTimelineDescriptionProps, getTimelineItemProps, getTimelineMarkerProps, getTimelinePartProps, getTimelineRootProps, getTimelineStatusProps, getTimelineStatusText, getTimelineTimeProps, resolveTimelineState };
|
|
130
|
+
|
|
131
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/timeline/timeline.ts"],"sourcesContent":["import { visuallyHiddenStyle } from \"@zag-js/dom-query\";\n\n/** Ordered event history. Status is always expressed by marker shape and text, never color alone. */\nexport const TIMELINE_STATUSES = [\"finished\", \"process\", \"wait\", \"error\"] as const;\nexport const TIMELINE_PARTS = [\"root\", \"item\", \"marker\", \"content\", \"header\", \"title\", \"time\", \"description\", \"status\"] as const;\nexport type TimelineStatus = (typeof TIMELINE_STATUSES)[number];\nexport type TimelinePart = (typeof TIMELINE_PARTS)[number];\nexport const TIMELINE_DEFAULT_STATUS_LABELS: Readonly<Record<TimelineStatus, string>> = Object.freeze({ finished: \"已完成\", process: \"进行中\", wait: \"未开始\", error: \"异常\" });\n/** Decorative marker glyphs; each status has a distinct shape in addition to its color role. */\nexport const TIMELINE_MARKER_GLYPHS: Readonly<Record<TimelineStatus, string>> = Object.freeze({ finished: \"✓\", process: \"\", wait: \"\", error: \"!\" });\n\nexport interface TimelineItem {\n id: string;\n title: string;\n description?: string;\n /** Visible time text. */\n time?: string;\n /** Machine-readable datetime for the <time> element. */\n dateTime?: string;\n status?: TimelineStatus;\n}\nexport interface QwTimelineProps {\n items: readonly TimelineItem[];\n /** Zero-based current index. Omitted: items default to finished and the first process item is current. */\n current?: number;\n /** Render newest first; indices and current identity stay those of `items`. */\n reverse?: boolean;\n /** Show the status text visibly instead of visually hidden. */\n showStatus?: boolean;\n statusLabels?: Partial<Record<TimelineStatus, string>>;\n}\nexport interface ResolvedTimelineItem extends TimelineItem {\n index: number;\n status: TimelineStatus;\n current: boolean;\n statusText: string;\n glyph: string;\n last: boolean;\n}\nexport interface ResolvedTimelineState {\n current: number | undefined;\n reverse: boolean;\n showStatus: boolean;\n /** Display order (reversed when `reverse`). */\n items: ResolvedTimelineItem[];\n}\n\nfunction normalizeCurrent(value: unknown): number | undefined {\n return typeof value === \"number\" && Number.isFinite(value) ? Math.floor(value) : undefined;\n}\nfunction isStatus(value: unknown): value is TimelineStatus {\n return TIMELINE_STATUSES.includes(value as TimelineStatus);\n}\n\nexport function resolveTimelineState(props: QwTimelineProps): ResolvedTimelineState {\n const items = props.items ?? [];\n const current = normalizeCurrent(props.current);\n const labels = { ...TIMELINE_DEFAULT_STATUS_LABELS, ...Object.fromEntries(Object.entries(props.statusLabels ?? {}).filter(([, text]) => typeof text === \"string\" && text !== \"\")) };\n const statuses = items.map((item, index): TimelineStatus => isStatus(item.status) ? item.status\n : current === undefined ? \"finished\" : index < current ? \"finished\" : index === current ? \"process\" : \"wait\");\n const currentIndex = current !== undefined ? (current >= 0 && current < items.length ? current : -1) : statuses.indexOf(\"process\");\n const resolved = items.map((item, index): ResolvedTimelineItem => {\n const status = statuses[index]!;\n return { ...item, index, status, current: index === currentIndex, statusText: labels[status], glyph: TIMELINE_MARKER_GLYPHS[status], last: false };\n });\n const ordered = props.reverse === true ? resolved.reverse() : resolved;\n if (ordered.length) ordered[ordered.length - 1]!.last = true;\n return { current, reverse: props.reverse === true, showStatus: props.showStatus === true, items: ordered };\n}\n\ntype Part<P extends TimelinePart> = { \"data-scope\": \"timeline\"; \"data-part\": P };\nconst part = <P extends TimelinePart>(name: P): Part<P> => ({ \"data-scope\": \"timeline\", \"data-part\": name });\n\nexport function getTimelineRootProps(state: ResolvedTimelineState): Part<\"root\"> & { \"data-reverse\"?: \"true\" } {\n return { ...part(\"root\"), ...(state.reverse ? { \"data-reverse\": \"true\" as const } : {}) };\n}\nexport function getTimelineItemProps(item: ResolvedTimelineItem): Part<\"item\"> & { \"data-value\": string; \"data-status\": TimelineStatus; \"data-current\"?: \"true\"; \"data-last\"?: \"true\"; \"aria-current\"?: \"step\" } {\n return { ...part(\"item\"), \"data-value\": item.id, \"data-status\": item.status,\n ...(item.current ? { \"data-current\": \"true\" as const, \"aria-current\": \"step\" as const } : {}),\n ...(item.last ? { \"data-last\": \"true\" as const } : {}) };\n}\nexport function getTimelineMarkerProps(item: ResolvedTimelineItem): Part<\"marker\"> & { \"data-status\": TimelineStatus; \"aria-hidden\": \"true\" } {\n return { ...part(\"marker\"), \"data-status\": item.status, \"aria-hidden\": \"true\" };\n}\n/** Status text precedes the title in reading order; visually hidden unless showStatus. */\nexport function getTimelineStatusProps(state: ResolvedTimelineState, item: ResolvedTimelineItem): Part<\"status\"> & { \"data-status\": TimelineStatus; \"data-visible\": \"true\" | \"false\"; style?: Record<string, string> } {\n return { ...part(\"status\"), \"data-status\": item.status, \"data-visible\": state.showStatus ? \"true\" : \"false\",\n ...(state.showStatus ? {} : { style: { ...(visuallyHiddenStyle as Record<string, string>) } }) };\n}\nexport function getTimelineTimeProps(item: ResolvedTimelineItem): Part<\"time\"> & { dateTime?: string; hidden?: true } {\n return { ...part(\"time\"), ...(item.dateTime ? { dateTime: item.dateTime } : {}), ...(item.time ? {} : { hidden: true as const }) };\n}\nexport function getTimelineDescriptionProps(item: ResolvedTimelineItem): Part<\"description\"> & { hidden?: true } {\n return { ...part(\"description\"), ...(item.description ? {} : { hidden: true as const }) };\n}\nexport function getTimelinePartProps<P extends \"content\" | \"header\" | \"title\">(name: P): Part<P> { return part(name); }\n/** Hidden status text carries a separator so \"异常,配送失败\" reads naturally; visible text is the bare label. */\nexport function getTimelineStatusText(state: ResolvedTimelineState, item: ResolvedTimelineItem): string { return state.showStatus ? item.statusText : `${item.statusText},`; }\n"],"mappings":"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"}
|