@kerfjs/ui 5.0.0-beta.104 → 5.0.0-beta.106
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 +155 -116
- package/ai/application-ui-profile.defaults.json +125 -4
- package/ai/compile-time-contracts-v1.json +11 -11
- package/ai/component-catalog.json +2606 -628
- package/ai/component-composition-rules.json +10 -10
- package/ai/component-composition.json +1688 -300
- package/ai/components/README.md +66 -48
- package/ai/components/application-tabs.md +4 -4
- package/ai/components/badge.md +1 -0
- package/ai/components/button.md +91 -0
- package/ai/components/checkbox.md +89 -0
- package/ai/components/choice-chips.md +9 -3
- package/ai/components/color-field.md +92 -0
- package/ai/components/color-picker.md +90 -0
- package/ai/components/color-swatches.md +82 -0
- package/ai/components/combobox.md +6 -4
- package/ai/components/content-item.md +5 -2
- package/ai/components/disclosure.md +83 -0
- package/ai/components/file-picker.md +1 -0
- package/ai/components/foundation.md +1 -1
- package/ai/components/list-action-row.md +3 -3
- package/ai/components/list-detail-dialog.md +90 -0
- package/ai/components/list.md +2 -0
- package/ai/components/lucide-icon.md +2 -0
- package/ai/components/{composer.md → message-composer.md} +17 -16
- package/ai/components/pane.md +3 -1
- package/ai/components/popup-menu.md +12 -9
- package/ai/components/progress-bar.md +82 -0
- package/ai/components/progress-ring.md +80 -0
- package/ai/components/radio-group.md +88 -0
- package/ai/components/recipe-list-detail-dialog.md +5 -5
- package/ai/components/{token-search-field.md → search-field.md} +23 -23
- package/ai/components/select.md +15 -13
- package/ai/components/slider.md +84 -0
- package/ai/components/surface-scaffold.md +16 -13
- package/ai/components/switch.md +81 -0
- package/ai/components/tab-bar.md +6 -6
- package/ai/components/tab-navigator.md +2 -2
- package/ai/components/tabs.md +7 -7
- package/ai/components/tag-field.md +86 -0
- package/ai/components/text-field.md +98 -0
- package/ai/components/text.md +1 -0
- package/ai/components/toast.md +85 -0
- package/ai/components/toolbar-control-group.md +3 -3
- package/ai/components/tooltip.md +81 -0
- package/ai/components/wa-accordion-item.md +11 -5
- package/ai/components/wa-accordion.md +11 -5
- package/ai/components/wa-animated-image.md +2 -1
- package/ai/components/wa-animation.md +1 -0
- package/ai/components/wa-avatar.md +1 -0
- package/ai/components/wa-badge.md +10 -3
- package/ai/components/wa-breadcrumb-item.md +1 -0
- package/ai/components/wa-breadcrumb.md +1 -0
- package/ai/components/wa-button-group.md +6 -4
- package/ai/components/wa-button.md +7 -5
- package/ai/components/wa-callout.md +7 -5
- package/ai/components/wa-card.md +12 -4
- package/ai/components/wa-carousel-item.md +1 -0
- package/ai/components/wa-carousel.md +1 -0
- package/ai/components/wa-checkbox-group.md +11 -4
- package/ai/components/wa-checkbox.md +10 -4
- package/ai/components/wa-color-picker.md +13 -5
- package/ai/components/wa-comparison.md +2 -1
- package/ai/components/wa-copy-button.md +1 -0
- package/ai/components/wa-details.md +11 -5
- package/ai/components/wa-dialog.md +10 -4
- package/ai/components/wa-divider.md +1 -0
- package/ai/components/wa-drawer.md +12 -5
- package/ai/components/wa-dropdown-item.md +8 -6
- package/ai/components/wa-dropdown.md +8 -6
- package/ai/components/wa-format-bytes.md +1 -0
- package/ai/components/wa-format-date.md +1 -0
- package/ai/components/wa-format-number.md +1 -0
- package/ai/components/wa-icon.md +2 -1
- package/ai/components/wa-include.md +6 -4
- package/ai/components/wa-input.md +9 -6
- package/ai/components/wa-intersection-observer.md +1 -0
- package/ai/components/wa-known-date.md +1 -0
- package/ai/components/wa-markdown.md +1 -0
- package/ai/components/wa-mutation-observer.md +1 -0
- package/ai/components/wa-number-input.md +1 -0
- package/ai/components/wa-option.md +7 -5
- package/ai/components/wa-otp-input.md +1 -0
- package/ai/components/wa-page.md +13 -4
- package/ai/components/wa-pagination.md +1 -0
- package/ai/components/wa-popover.md +11 -5
- package/ai/components/wa-popup.md +11 -4
- package/ai/components/wa-progress-bar.md +11 -4
- package/ai/components/wa-progress-ring.md +11 -4
- package/ai/components/wa-qr-code.md +1 -0
- package/ai/components/wa-radio-group.md +12 -4
- package/ai/components/wa-radio.md +10 -4
- package/ai/components/wa-random-content.md +1 -0
- package/ai/components/wa-rating.md +1 -0
- package/ai/components/wa-relative-time.md +1 -0
- package/ai/components/wa-resize-observer.md +1 -0
- package/ai/components/wa-scroller.md +12 -4
- package/ai/components/wa-select.md +7 -5
- package/ai/components/wa-skeleton.md +10 -3
- package/ai/components/wa-slider.md +11 -5
- package/ai/components/wa-spinner.md +7 -5
- package/ai/components/wa-split-panel.md +7 -5
- package/ai/components/wa-step.md +56 -0
- package/ai/components/wa-stepper.md +56 -0
- package/ai/components/wa-switch.md +10 -3
- package/ai/components/wa-tab-group.md +8 -6
- package/ai/components/wa-tab-panel.md +7 -5
- package/ai/components/wa-tab.md +8 -6
- package/ai/components/wa-tag-input.md +62 -0
- package/ai/components/wa-tag.md +9 -6
- package/ai/components/wa-textarea.md +10 -3
- package/ai/components/wa-time-input.md +1 -0
- package/ai/components/wa-toast-item.md +9 -7
- package/ai/components/wa-toast.md +9 -7
- package/ai/components/wa-tooltip.md +11 -5
- package/ai/components/wa-tree-item.md +2 -1
- package/ai/components/wa-tree.md +2 -1
- package/ai/components/wa-zoomable-frame.md +2 -1
- package/ai/components/workbench-dialog.md +90 -0
- package/ai/public-api-signatures-v1.md +1579 -247
- package/ai/skill.md +83 -50
- package/ai/webawesome-jsx-signatures-v1.md +4 -1
- package/dist/badge.d.ts +9 -1
- package/dist/badge.js +1 -1
- package/dist/browser/button.js +5 -0
- package/dist/browser/catalog.js +3 -2
- package/dist/browser/{icon-button.js → checkbox.js} +2 -2
- package/dist/browser/color-field.js +4 -0
- package/dist/browser/color-picker.js +5 -0
- package/dist/browser/color-swatches.js +3 -0
- package/dist/browser/disclosure.js +5 -0
- package/dist/browser/list-action-row.js +1 -0
- package/dist/browser/list-detail-dialog.js +14 -0
- package/dist/browser/message-composer.js +5 -0
- package/dist/browser/popup-menu.js +1 -0
- package/dist/browser/progress-bar.js +3 -0
- package/dist/browser/progress-ring.js +3 -0
- package/dist/browser/radio-group.js +3 -0
- package/dist/browser/search-field.js +4 -0
- package/dist/browser/slider.js +3 -0
- package/dist/browser/surface-scaffold.js +1 -0
- package/dist/browser/switch.js +3 -0
- package/dist/browser/tab-bar-item.js +4 -0
- package/dist/browser/tag-field.js +5 -0
- package/dist/browser/text-field.js +4 -0
- package/dist/browser/workbench-dialog.js +15 -0
- package/dist/button.d.ts +108 -0
- package/dist/button.js +7 -0
- package/dist/button.js.map +1 -0
- package/dist/catalog-resources.d.ts +1 -1
- package/dist/catalog.d.ts +3 -3
- package/dist/catalog.js +57 -27
- package/dist/catalog.js.map +1 -1
- package/dist/checkbox.d.ts +45 -0
- package/dist/checkbox.js +6 -0
- package/dist/checkbox.js.map +1 -0
- package/dist/choice-chips.d.ts +49 -15
- package/dist/choice-chips.js +1 -1
- package/dist/chunk-23PPPNH6.js +93 -0
- package/dist/chunk-23PPPNH6.js.map +1 -0
- package/dist/{chunk-FNZQOUZ5.js → chunk-2FW7D4IG.js} +2 -2
- package/dist/{chunk-FNZQOUZ5.js.map → chunk-2FW7D4IG.js.map} +1 -1
- package/dist/{chunk-ZYU5WRC3.js → chunk-3GLYIIFR.js} +2 -2
- package/dist/{chunk-ZYU5WRC3.js.map → chunk-3GLYIIFR.js.map} +1 -1
- package/dist/{chunk-5NQF35VO.js → chunk-4RECPEHI.js} +2 -2
- package/dist/{chunk-5NQF35VO.js.map → chunk-4RECPEHI.js.map} +1 -1
- package/dist/{chunk-7IUEBNCO.js → chunk-5USKCWGL.js} +8 -3
- package/dist/chunk-5USKCWGL.js.map +1 -0
- package/dist/chunk-6VVIW7VB.js +69 -0
- package/dist/chunk-6VVIW7VB.js.map +1 -0
- package/dist/{chunk-LL45C7BB.js → chunk-7K6U6FCN.js} +1 -1
- package/dist/chunk-7K6U6FCN.js.map +1 -0
- package/dist/{chunk-HQZYKJ56.js → chunk-7W3GKMN4.js} +110 -74
- package/dist/chunk-7W3GKMN4.js.map +1 -0
- package/dist/chunk-ACUKTVS3.js +371 -0
- package/dist/chunk-ACUKTVS3.js.map +1 -0
- package/dist/{chunk-YQ2AC4E2.js → chunk-AMIHGFLP.js} +2 -2
- package/dist/{chunk-YQ2AC4E2.js.map → chunk-AMIHGFLP.js.map} +1 -1
- package/dist/chunk-ATGAJVZ6.js +268 -0
- package/dist/chunk-ATGAJVZ6.js.map +1 -0
- package/dist/chunk-AYPGXR2E.js +20 -0
- package/dist/chunk-AYPGXR2E.js.map +1 -0
- package/dist/{chunk-ETCWQLJV.js → chunk-BKUMG2KB.js} +38 -28
- package/dist/chunk-BKUMG2KB.js.map +1 -0
- package/dist/chunk-C26Q6P4Q.js +76 -0
- package/dist/chunk-C26Q6P4Q.js.map +1 -0
- package/dist/chunk-C3RLKKFQ.js +452 -0
- package/dist/chunk-C3RLKKFQ.js.map +1 -0
- package/dist/{chunk-T5BJBMW7.js → chunk-CIAUILRR.js} +5 -5
- package/dist/chunk-CIAUILRR.js.map +1 -0
- package/dist/chunk-CNM6ZWP2.js +38 -0
- package/dist/chunk-CNM6ZWP2.js.map +1 -0
- package/dist/{chunk-LPHU44S3.js → chunk-CTQUDCY5.js} +3 -1
- package/dist/chunk-CTQUDCY5.js.map +1 -0
- package/dist/{chunk-MXNIVEVL.js → chunk-D4MXSAMI.js} +5 -3
- package/dist/chunk-D4MXSAMI.js.map +1 -0
- package/dist/{chunk-YBWQR2OK.js → chunk-DDSCVEO5.js} +10 -9
- package/dist/chunk-DDSCVEO5.js.map +1 -0
- package/dist/{chunk-SIW64V65.js → chunk-DF2YKGIX.js} +3 -3
- package/dist/{chunk-SIW64V65.js.map → chunk-DF2YKGIX.js.map} +1 -1
- package/dist/{chunk-3SKAEPPZ.js → chunk-ECFCAKWE.js} +4 -4
- package/dist/{chunk-3SKAEPPZ.js.map → chunk-ECFCAKWE.js.map} +1 -1
- package/dist/chunk-EKBMUXFV.js +298 -0
- package/dist/chunk-EKBMUXFV.js.map +1 -0
- package/dist/{chunk-IXLUZHGT.js → chunk-FG6U7KQQ.js} +5 -5
- package/dist/{chunk-IXLUZHGT.js.map → chunk-FG6U7KQQ.js.map} +1 -1
- package/dist/chunk-FKKJHGN5.js +147 -0
- package/dist/chunk-FKKJHGN5.js.map +1 -0
- package/dist/{chunk-FDZNYD4C.js → chunk-GCAK23PU.js} +34 -3
- package/dist/chunk-GCAK23PU.js.map +1 -0
- package/dist/chunk-GXSX6Q6O.js +42 -0
- package/dist/chunk-GXSX6Q6O.js.map +1 -0
- package/dist/{chunk-LOSRXZAH.js → chunk-HJXVVFBT.js} +14 -6
- package/dist/chunk-HJXVVFBT.js.map +1 -0
- package/dist/{chunk-M5KZ26VV.js → chunk-HQZG3OFL.js} +11 -1
- package/dist/chunk-HQZG3OFL.js.map +1 -0
- package/dist/{chunk-ELCMSQNJ.js → chunk-HTERKONR.js} +8 -8
- package/dist/chunk-HTERKONR.js.map +1 -0
- package/dist/chunk-HYORKKYP.js +8 -0
- package/dist/chunk-HYORKKYP.js.map +1 -0
- package/dist/chunk-IO27YTL3.js +73 -0
- package/dist/chunk-IO27YTL3.js.map +1 -0
- package/dist/chunk-ITUQC4FW.js +163 -0
- package/dist/chunk-ITUQC4FW.js.map +1 -0
- package/dist/chunk-K57NINLH.js +137 -0
- package/dist/chunk-K57NINLH.js.map +1 -0
- package/dist/chunk-KC6WUSNS.js +34 -0
- package/dist/chunk-KC6WUSNS.js.map +1 -0
- package/dist/{chunk-W4IK7AWD.js → chunk-KDQZ3E5C.js} +3 -1
- package/dist/chunk-KDQZ3E5C.js.map +1 -0
- package/dist/{chunk-2MSPNRWJ.js → chunk-KK3S5OTW.js} +27 -11
- package/dist/chunk-KK3S5OTW.js.map +1 -0
- package/dist/chunk-LTBVP6VN.js +59 -0
- package/dist/chunk-LTBVP6VN.js.map +1 -0
- package/dist/chunk-OHPYT2BH.js +82 -0
- package/dist/chunk-OHPYT2BH.js.map +1 -0
- package/dist/{chunk-HZPHCSCS.js → chunk-OY2MXIBB.js} +8 -2
- package/dist/chunk-OY2MXIBB.js.map +1 -0
- package/dist/chunk-PE2KPZDW.js +85 -0
- package/dist/chunk-PE2KPZDW.js.map +1 -0
- package/dist/{chunk-QTSMHH5J.js → chunk-QPTJ5DOO.js} +5 -3
- package/dist/chunk-QPTJ5DOO.js.map +1 -0
- package/dist/{chunk-JOR5LGYE.js → chunk-RFLW4FPL.js} +1 -1
- package/dist/chunk-RFLW4FPL.js.map +1 -0
- package/dist/{chunk-U6QYTMDB.js → chunk-RMWNO6BA.js} +6 -2
- package/dist/chunk-RMWNO6BA.js.map +1 -0
- package/dist/{chunk-TDMHA7C3.js → chunk-SQ2Q3OQI.js} +112 -63
- package/dist/chunk-SQ2Q3OQI.js.map +1 -0
- package/dist/{chunk-K4AT3V3J.js → chunk-T74YB76U.js} +13 -11
- package/dist/chunk-T74YB76U.js.map +1 -0
- package/dist/{chunk-BYFTHA4I.js → chunk-TAHR457X.js} +53 -6
- package/dist/chunk-TAHR457X.js.map +1 -0
- package/dist/{chunk-3VXDSIBJ.js → chunk-TKNVL53O.js} +2 -2
- package/dist/{chunk-3VXDSIBJ.js.map → chunk-TKNVL53O.js.map} +1 -1
- package/dist/chunk-TNJLNLVE.js +115 -0
- package/dist/chunk-TNJLNLVE.js.map +1 -0
- package/dist/chunk-TUID42UE.js +15 -0
- package/dist/chunk-TUID42UE.js.map +1 -0
- package/dist/{chunk-CR5U5FV6.js → chunk-UMNHJSIO.js} +93 -80
- package/dist/chunk-UMNHJSIO.js.map +1 -0
- package/dist/chunk-UTCAOOXU.js +116 -0
- package/dist/chunk-UTCAOOXU.js.map +1 -0
- package/dist/{chunk-ZJC5ND3M.js → chunk-VEME3D7K.js} +35 -35
- package/dist/chunk-VEME3D7K.js.map +1 -0
- package/dist/{chunk-HLDRH23D.js → chunk-WJKHLOP5.js} +2 -2
- package/dist/{chunk-HLDRH23D.js.map → chunk-WJKHLOP5.js.map} +1 -1
- package/dist/chunk-WU57BYYM.js +115 -0
- package/dist/chunk-WU57BYYM.js.map +1 -0
- package/dist/{chunk-TGLUDQP2.js → chunk-ZCDRLN3B.js} +11 -11
- package/dist/chunk-ZCDRLN3B.js.map +1 -0
- package/dist/chunk-ZX2QQJXD.js +249 -0
- package/dist/chunk-ZX2QQJXD.js.map +1 -0
- package/dist/{chunk-6E2H2E5A.js → chunk-ZXZAECHZ.js} +6 -6
- package/dist/{chunk-6E2H2E5A.js.map → chunk-ZXZAECHZ.js.map} +1 -1
- package/dist/collapsible-panel.js +3 -3
- package/dist/color-field.d.ts +51 -0
- package/dist/color-field.js +92 -0
- package/dist/color-field.js.map +1 -0
- package/dist/color-picker.d.ts +88 -0
- package/dist/color-picker.js +8 -0
- package/dist/color-picker.js.map +1 -0
- package/dist/color-swatches.d.ts +56 -0
- package/dist/color-swatches.js +4 -0
- package/dist/color-swatches.js.map +1 -0
- package/dist/combobox.js +1 -1
- package/dist/content-item.d.ts +13 -1
- package/dist/content-item.js +1 -1
- package/dist/disclosure-arrow.js +1 -1
- package/dist/disclosure.d.ts +57 -0
- package/dist/disclosure.js +51 -0
- package/dist/disclosure.js.map +1 -0
- package/dist/file-picker.d.ts +7 -0
- package/dist/file-picker.js +1 -1
- package/dist/help-tags-register.d.ts +8 -8
- package/dist/help-tags-register.js +3 -2
- package/dist/help-tags-register.js.map +1 -1
- package/dist/index.d.ts +16 -9
- package/dist/index.js +58 -46
- package/dist/list-action-row.js +4 -1
- package/dist/list-detail-dialog.d.ts +117 -0
- package/dist/list-detail-dialog.js +165 -0
- package/dist/list-detail-dialog.js.map +1 -0
- package/dist/list-header.js +1 -1
- package/dist/list-item.js +1 -1
- package/dist/list.d.ts +17 -2
- package/dist/list.js +1 -1
- package/dist/lucide-icon.d.ts +9 -1
- package/dist/lucide-icon.js +1 -1
- package/dist/{composer.d.ts → message-composer.d.ts} +20 -12
- package/dist/message-composer.js +6 -0
- package/dist/message-composer.js.map +1 -0
- package/dist/nav-stack.js +1 -1
- package/dist/pane.d.ts +36 -3
- package/dist/pane.js +1 -1
- package/dist/popup-menu-register.d.ts +6 -5
- package/dist/popup-menu-register.js +3 -326
- package/dist/popup-menu-register.js.map +1 -1
- package/dist/popup-menu.d.ts +41 -23
- package/dist/popup-menu.js +5 -1
- package/dist/progress-bar.d.ts +52 -0
- package/dist/progress-bar.js +68 -0
- package/dist/progress-bar.js.map +1 -0
- package/dist/progress-ring.d.ts +44 -0
- package/dist/progress-ring.js +73 -0
- package/dist/progress-ring.js.map +1 -0
- package/dist/radio-group.d.ts +62 -0
- package/dist/radio-group.js +4 -0
- package/dist/radio-group.js.map +1 -0
- package/dist/row.js +1 -1
- package/dist/{token-search-model-JA1i8z4D.d.ts → search-field-CrGTN5sa.d.ts} +45 -45
- package/dist/search-field-model.d.ts +3 -0
- package/dist/search-field-model.js +3 -0
- package/dist/search-field-model.js.map +1 -0
- package/dist/search-field.d.ts +3 -0
- package/dist/search-field.js +5 -0
- package/dist/search-field.js.map +1 -0
- package/dist/select-register.d.ts +6 -3
- package/dist/select-register.js +383 -241
- package/dist/select-register.js.map +1 -1
- package/dist/select.d.ts +30 -6
- package/dist/select.js +3 -1
- package/dist/selection.d.ts +54 -0
- package/dist/selection.js +3 -0
- package/dist/selection.js.map +1 -0
- package/dist/slider.d.ts +74 -0
- package/dist/slider.js +103 -0
- package/dist/slider.js.map +1 -0
- package/dist/split-button.js +1 -1
- package/dist/split-view.d.ts +5 -2
- package/dist/split-view.js +18 -159
- package/dist/split-view.js.map +1 -1
- package/dist/state-banner.js +1 -1
- package/dist/styles/badge.css +18 -6
- package/dist/styles/button.css +230 -0
- package/dist/styles/catalog/components/catalog-example.css +13 -4
- package/dist/styles/checkbox.css +121 -0
- package/dist/styles/choice-chips.css +58 -7
- package/dist/styles/color-field.css +125 -0
- package/dist/styles/color-picker.css +331 -0
- package/dist/styles/color-swatches.css +122 -0
- package/dist/styles/combobox.css +7 -5
- package/dist/styles/components/actions/button/button.css +230 -0
- package/dist/styles/components/actions/popup-menu/popup-menu.css +326 -198
- package/dist/styles/components/actions/toolbar/toolbar.css +10 -3
- package/dist/styles/components/actions/toolbar-control-group/toolbar-control-group.css +67 -104
- package/dist/styles/components/actions/toolbar-text/toolbar-text.css +5 -18
- package/dist/styles/components/collections/list/list.css +37 -0
- package/dist/styles/components/feedback/badge/badge.css +18 -6
- package/dist/styles/components/feedback/progress-bar/progress-bar.css +168 -0
- package/dist/styles/components/feedback/progress-ring/progress-ring.css +91 -0
- package/dist/styles/components/feedback/state-banner/state-banner.css +18 -3
- package/dist/styles/components/forms/checkbox/checkbox.css +121 -0
- package/dist/styles/components/forms/choice-chips/choice-chips.css +58 -7
- package/dist/styles/components/forms/color-field/color-field.css +125 -0
- package/dist/styles/components/forms/color-picker/color-picker.css +331 -0
- package/dist/styles/components/forms/color-swatches/color-swatches.css +122 -0
- package/dist/styles/components/forms/combobox/combobox.css +7 -5
- package/dist/styles/components/forms/{composer/composer.css → message-composer/message-composer.css} +17 -33
- package/dist/styles/components/forms/radio-group/radio-group.css +156 -0
- package/dist/styles/{token-search-field.css → components/forms/search-field/search-field.css} +111 -102
- package/dist/styles/components/forms/select/select.css +370 -249
- package/dist/styles/components/forms/slider/slider.css +241 -0
- package/dist/styles/components/forms/switch/switch.css +132 -0
- package/dist/styles/components/forms/tag-field/tag-field.css +8 -0
- package/dist/styles/components/forms/text-field/text-field.css +193 -0
- package/dist/styles/components/layout/pane/pane.css +254 -0
- package/dist/styles/components/layout/resizable-region/resizable-region.css +3 -2
- package/dist/styles/components/layout/row/row.css +11 -0
- package/dist/styles/components/layout/split-view/split-view.css +25 -0
- package/dist/styles/components/layout/workbench/workbench.css +12 -4
- package/dist/styles/components/navigation/disclosure-arrow/disclosure-arrow.css +20 -0
- package/dist/styles/components/navigation/tab-bar/tab-bar.css +7 -7
- package/dist/styles/components/navigation/{app-tab/app-tab.css → tab-bar-item/tab-bar-item.css} +95 -90
- package/dist/styles/components/surfaces/disclosure/disclosure.css +98 -0
- package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +263 -116
- package/dist/styles/components/typography/text/text.css +14 -12
- package/dist/styles/disclosure-arrow.css +20 -0
- package/dist/styles/disclosure.css +98 -0
- package/dist/styles/foundation.css +6 -4
- package/dist/styles/list-detail-dialog.css +11 -0
- package/dist/styles/list.css +37 -0
- package/dist/styles/{composer.css → message-composer.css} +17 -33
- package/dist/styles/overlay-toast.css +149 -0
- package/dist/styles/overlay-tooltip.css +55 -0
- package/dist/styles/pane.css +254 -0
- package/dist/styles/popup-menu.css +326 -198
- package/dist/styles/progress-bar.css +168 -0
- package/dist/styles/progress-ring.css +91 -0
- package/dist/styles/radio-group.css +156 -0
- package/dist/styles/resizable-region.css +3 -2
- package/dist/styles/row.css +11 -0
- package/dist/styles/{components/forms/token-search-field/token-search-field.css → search-field.css} +111 -102
- package/dist/styles/select.css +370 -249
- package/dist/styles/slider.css +241 -0
- package/dist/styles/split-view.css +25 -0
- package/dist/styles/state-banner.css +18 -3
- package/dist/styles/styles.css +16 -5
- package/dist/styles/surface-scaffold.css +263 -116
- package/dist/styles/switch.css +132 -0
- package/dist/styles/{app-tab.css → tab-bar-item.css} +95 -90
- package/dist/styles/tab-bar.css +7 -7
- package/dist/styles/tag-field.css +8 -0
- package/dist/styles/text-field.css +193 -0
- package/dist/styles/text.css +14 -12
- package/dist/styles/toolbar-control-group.css +67 -104
- package/dist/styles/toolbar-text.css +5 -18
- package/dist/styles/toolbar.css +10 -3
- package/dist/styles/webawesome.css +9 -0
- package/dist/styles/workbench-dialog.css +10 -0
- package/dist/styles/workbench.css +12 -4
- package/dist/surface-scaffold-register.d.ts +7 -5
- package/dist/surface-scaffold-register.js +2 -246
- package/dist/surface-scaffold-register.js.map +1 -1
- package/dist/surface-scaffold.d.ts +70 -7
- package/dist/surface-scaffold.js +5 -1
- package/dist/switch.d.ts +38 -0
- package/dist/switch.js +4 -0
- package/dist/switch.js.map +1 -0
- package/dist/{app-tab.d.ts → tab-bar-item.d.ts} +11 -11
- package/dist/tab-bar-item.js +6 -0
- package/dist/tab-bar-item.js.map +1 -0
- package/dist/tab-bar.d.ts +3 -3
- package/dist/tab-bar.js +1 -1
- package/dist/tab-navigator.js +1 -1
- package/dist/tag-field.d.ts +52 -0
- package/dist/tag-field.js +6 -0
- package/dist/tag-field.js.map +1 -0
- package/dist/text-field.d.ts +83 -0
- package/dist/text-field.js +6 -0
- package/dist/text-field.js.map +1 -0
- package/dist/text.d.ts +6 -1
- package/dist/text.js +1 -1
- package/dist/{types-CVgIwSdq.d.ts → types-DmHWkSd6.d.ts} +19 -1
- package/dist/webawesome.d.ts +3 -0
- package/dist/wire-catalog.d.ts +8 -2
- package/dist/wire-catalog.js +16 -4
- package/dist/wire-catalog.js.map +1 -1
- package/dist/wire-checkboxes.d.ts +10 -0
- package/dist/wire-checkboxes.js +3 -0
- package/dist/{wire-composers.js.map → wire-checkboxes.js.map} +1 -1
- package/dist/wire-choice-chips.d.ts +17 -0
- package/dist/wire-choice-chips.js +4 -0
- package/dist/{wire-token-search-fields.js.map → wire-choice-chips.js.map} +1 -1
- package/dist/wire-color-fields.d.ts +33 -0
- package/dist/wire-color-fields.js +82 -0
- package/dist/wire-color-fields.js.map +1 -0
- package/dist/wire-color-pickers.d.ts +34 -0
- package/dist/wire-color-pickers.js +9 -0
- package/dist/wire-color-pickers.js.map +1 -0
- package/dist/wire-comboboxes.js +2 -1
- package/dist/wire-content-items.d.ts +5 -1
- package/dist/wire-content-items.js +84 -15
- package/dist/wire-content-items.js.map +1 -1
- package/dist/wire-file-pickers.d.ts +3 -2
- package/dist/wire-file-pickers.js +1 -1
- package/dist/{wire-composers.d.ts → wire-message-composers.d.ts} +5 -4
- package/dist/wire-message-composers.js +3 -0
- package/dist/wire-message-composers.js.map +1 -0
- package/dist/wire-overlay-sheets.js +1 -1
- package/dist/wire-pane-chrome.d.ts +21 -0
- package/dist/wire-pane-chrome.js +67 -0
- package/dist/wire-pane-chrome.js.map +1 -0
- package/dist/{wire-token-search-fields.d.ts → wire-search-fields.d.ts} +25 -25
- package/dist/wire-search-fields.js +6 -0
- package/dist/wire-search-fields.js.map +1 -0
- package/dist/wire-sliders.d.ts +12 -0
- package/dist/wire-sliders.js +31 -0
- package/dist/wire-sliders.js.map +1 -0
- package/dist/wire-tab-bars.js +1 -1
- package/dist/wire-tag-fields.d.ts +41 -0
- package/dist/wire-tag-fields.js +258 -0
- package/dist/wire-tag-fields.js.map +1 -0
- package/dist/wire-text-fields.d.ts +12 -0
- package/dist/wire-text-fields.js +3 -0
- package/dist/wire-text-fields.js.map +1 -0
- package/dist/workbench-dialog.d.ts +97 -0
- package/dist/workbench-dialog.js +124 -0
- package/dist/workbench-dialog.js.map +1 -0
- package/dist/workbench.d.ts +5 -0
- package/dist/workbench.js +1 -1
- package/docs/accessibility.md +181 -97
- package/docs/anchored-surface.md +8 -7
- package/docs/app-layouts.md +28 -0
- package/docs/catalog.md +14 -5
- package/docs/color-field.md +65 -0
- package/docs/color-picker.md +71 -0
- package/docs/color-swatches.md +46 -0
- package/docs/component-contract.md +31 -32
- package/docs/component-selection.md +228 -164
- package/docs/design/templates/button/emphasis-dark.svg +1 -0
- package/docs/design/templates/button/emphasis.svg +1 -0
- package/docs/design/templates/button/icons-dark.svg +1 -0
- package/docs/design/templates/button/icons.svg +1 -0
- package/docs/design/templates/button/pill-dark.svg +1 -0
- package/docs/design/templates/button/pill.svg +1 -0
- package/docs/design/templates/button/states-dark.svg +1 -0
- package/docs/design/templates/button/states.svg +1 -0
- package/docs/design/templates/button/toggles-dark.svg +1 -0
- package/docs/design/templates/button/toggles.svg +1 -0
- package/docs/design/templates/button/tones-dark.svg +1 -0
- package/docs/design/templates/button/tones.svg +1 -0
- package/docs/design/templates/button-dark.svg +1 -0
- package/docs/design/templates/button.svg +1 -0
- package/docs/design/templates/checkbox/compact-dark.svg +1 -0
- package/docs/design/templates/checkbox/compact.svg +1 -0
- package/docs/design/templates/checkbox/error-dark.svg +1 -0
- package/docs/design/templates/checkbox/error.svg +1 -0
- package/docs/design/templates/checkbox/mixed-dark.svg +1 -0
- package/docs/design/templates/checkbox/mixed.svg +1 -0
- package/docs/design/templates/checkbox/states-dark.svg +1 -0
- package/docs/design/templates/checkbox/states.svg +1 -0
- package/docs/design/templates/checkbox-dark.svg +1 -0
- package/docs/design/templates/checkbox.svg +1 -0
- package/docs/design/templates/choice-chips/color-palette-dark.svg +1 -1
- package/docs/design/templates/choice-chips/color-palette.svg +1 -1
- package/docs/design/templates/choice-chips/compact-icons-dark.svg +1 -1
- package/docs/design/templates/choice-chips/compact-icons.svg +1 -1
- package/docs/design/templates/choice-chips/multiple-dark.svg +1 -1
- package/docs/design/templates/choice-chips/multiple.svg +1 -1
- package/docs/design/templates/choice-chips-dark.svg +1 -1
- package/docs/design/templates/choice-chips.svg +1 -1
- package/docs/design/templates/color-field/compact-dark.svg +1 -0
- package/docs/design/templates/color-field/compact.svg +1 -0
- package/docs/design/templates/color-field/error-dark.svg +1 -0
- package/docs/design/templates/color-field/error.svg +1 -0
- package/docs/design/templates/color-field/hint-dark.svg +1 -0
- package/docs/design/templates/color-field/hint.svg +1 -0
- package/docs/design/templates/color-field-dark.svg +1 -0
- package/docs/design/templates/color-field.svg +1 -0
- package/docs/design/templates/color-picker/gray-dark.svg +1 -0
- package/docs/design/templates/color-picker/gray.svg +1 -0
- package/docs/design/templates/color-picker/rgb-dark.svg +1 -0
- package/docs/design/templates/color-picker/rgb.svg +1 -0
- package/docs/design/templates/color-picker-dark.svg +1 -0
- package/docs/design/templates/color-picker.svg +1 -0
- package/docs/design/templates/color-swatches/palette-dark.svg +1 -0
- package/docs/design/templates/color-swatches/palette.svg +1 -0
- package/docs/design/templates/color-swatches-dark.svg +1 -0
- package/docs/design/templates/color-swatches.svg +1 -0
- package/docs/design/templates/disclosure/framed-sunken-dark.svg +1 -0
- package/docs/design/templates/disclosure/framed-sunken.svg +1 -0
- package/docs/design/templates/disclosure/plain-dark.svg +1 -0
- package/docs/design/templates/disclosure/plain.svg +1 -0
- package/docs/design/templates/disclosure-dark.svg +1 -0
- package/docs/design/templates/disclosure.svg +1 -0
- package/docs/design/templates/list-header/size-l-dark.svg +1 -1
- package/docs/design/templates/list-header/size-l.svg +1 -1
- package/docs/design/templates/list-header/size-m-dark.svg +1 -1
- package/docs/design/templates/list-header/size-m.svg +1 -1
- package/docs/design/templates/list-header/size-xl-dark.svg +1 -1
- package/docs/design/templates/list-header/size-xl.svg +1 -1
- package/docs/design/templates/list-header-dark.svg +1 -1
- package/docs/design/templates/list-header.svg +1 -1
- package/docs/design/templates/message-composer/chat-dark.svg +1 -0
- package/docs/design/templates/message-composer/chat.svg +1 -0
- package/docs/design/templates/{composer → message-composer}/prompt-dark.svg +1 -1
- package/docs/design/templates/{composer → message-composer}/prompt.svg +1 -1
- package/docs/design/templates/message-composer-dark.svg +1 -0
- package/docs/design/templates/message-composer.svg +1 -0
- package/docs/design/templates/progress-bar/determinate-dark.svg +1 -0
- package/docs/design/templates/progress-bar/determinate.svg +1 -0
- package/docs/design/templates/progress-bar/tones-dark.svg +1 -0
- package/docs/design/templates/progress-bar/tones.svg +1 -0
- package/docs/design/templates/progress-bar-dark.svg +1 -0
- package/docs/design/templates/progress-bar.svg +1 -0
- package/docs/design/templates/progress-ring/sizes-dark.svg +1 -0
- package/docs/design/templates/progress-ring/sizes.svg +1 -0
- package/docs/design/templates/progress-ring/tones-dark.svg +1 -0
- package/docs/design/templates/progress-ring/tones.svg +1 -0
- package/docs/design/templates/progress-ring-dark.svg +1 -0
- package/docs/design/templates/progress-ring.svg +1 -0
- package/docs/design/templates/radio-group/horizontal-dark.svg +1 -0
- package/docs/design/templates/radio-group/horizontal.svg +1 -0
- package/docs/design/templates/radio-group/vertical-dark.svg +1 -0
- package/docs/design/templates/radio-group/vertical.svg +1 -0
- package/docs/design/templates/radio-group-dark.svg +1 -0
- package/docs/design/templates/radio-group.svg +1 -0
- package/docs/design/templates/segmented-control/equal-dark.svg +1 -1
- package/docs/design/templates/segmented-control/equal.svg +1 -1
- package/docs/design/templates/segmented-control/pill-small-dark.svg +1 -1
- package/docs/design/templates/segmented-control/pill-small.svg +1 -1
- package/docs/design/templates/segmented-control-dark.svg +1 -1
- package/docs/design/templates/segmented-control.svg +1 -1
- package/docs/design/templates/select/compact-dark.svg +1 -0
- package/docs/design/templates/select/compact.svg +1 -0
- package/docs/design/templates/select/form-dark.svg +1 -0
- package/docs/design/templates/select/form.svg +1 -0
- package/docs/design/templates/select/icons-dark.svg +1 -0
- package/docs/design/templates/select/icons.svg +1 -0
- package/docs/design/templates/select-dark.svg +1 -0
- package/docs/design/templates/select.svg +1 -0
- package/docs/design/templates/slider/compact-dark.svg +1 -0
- package/docs/design/templates/slider/compact.svg +1 -0
- package/docs/design/templates/slider/readout-dark.svg +1 -0
- package/docs/design/templates/slider/readout.svg +1 -0
- package/docs/design/templates/slider/ticks-dark.svg +1 -0
- package/docs/design/templates/slider/ticks.svg +1 -0
- package/docs/design/templates/slider-dark.svg +1 -0
- package/docs/design/templates/slider.svg +1 -0
- package/docs/design/templates/switch/compact-dark.svg +1 -0
- package/docs/design/templates/switch/compact.svg +1 -0
- package/docs/design/templates/switch/states-dark.svg +1 -0
- package/docs/design/templates/switch/states.svg +1 -0
- package/docs/design/templates/switch-dark.svg +1 -0
- package/docs/design/templates/switch.svg +1 -0
- package/docs/design/templates/tag-field/error-dark.svg +1 -0
- package/docs/design/templates/tag-field/error.svg +1 -0
- package/docs/design/templates/tag-field/tags-dark.svg +1 -0
- package/docs/design/templates/tag-field/tags.svg +1 -0
- package/docs/design/templates/tag-field-dark.svg +1 -0
- package/docs/design/templates/tag-field.svg +1 -0
- package/docs/design/templates/text-field/compact-dark.svg +1 -0
- package/docs/design/templates/text-field/compact.svg +1 -0
- package/docs/design/templates/text-field/error-dark.svg +1 -0
- package/docs/design/templates/text-field/error.svg +1 -0
- package/docs/design/templates/text-field/labeled-dark.svg +1 -0
- package/docs/design/templates/text-field/labeled.svg +1 -0
- package/docs/design/templates/text-field/multiline-dark.svg +1 -0
- package/docs/design/templates/text-field/multiline.svg +1 -0
- package/docs/design/templates/text-field/search-dark.svg +1 -0
- package/docs/design/templates/text-field/search.svg +1 -0
- package/docs/design/templates/text-field-dark.svg +1 -0
- package/docs/design/templates/text-field.svg +1 -0
- package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -1
- package/docs/design/templates/toolbar/title-and-actions.svg +1 -1
- package/docs/design/templates/toolbar/width-visibility-320-dark.svg +1 -1
- package/docs/design/templates/toolbar/width-visibility-320.svg +1 -1
- package/docs/design/templates/toolbar/width-visibility-600-dark.svg +1 -1
- package/docs/design/templates/toolbar/width-visibility-600.svg +1 -1
- package/docs/design/templates/toolbar-dark.svg +1 -1
- package/docs/design/templates/toolbar.svg +1 -1
- package/docs/design/templates/value-table/details-dark.svg +1 -1
- package/docs/design/templates/value-table/details.svg +1 -1
- package/docs/design/templates/value-table-dark.svg +1 -1
- package/docs/design/templates/value-table.svg +1 -1
- package/docs/design/templates.md +19 -6
- package/docs/design-philosophy.md +6 -6
- package/docs/disclosure.md +63 -0
- package/docs/examples/component-catalog-extension.json +2 -2
- package/docs/layout.md +16 -7
- package/docs/list-detail-dialog.md +96 -0
- package/docs/manual-test-plan.md +1 -1
- package/docs/{composer.md → message-composer.md} +41 -28
- package/docs/overlay-toast.md +62 -0
- package/docs/overlay-tooltip.md +53 -0
- package/docs/progress.md +62 -0
- package/docs/recipes.md +15 -21
- package/docs/slider.md +64 -0
- package/docs/surface-scaffold.md +155 -88
- package/docs/tag-field.md +66 -0
- package/docs/type-contracts.md +8 -8
- package/docs/ui-analyzer.md +1 -1
- package/docs/ui-doctor.md +11 -6
- package/docs/ux-demo.md +6 -6
- package/docs/webawesome-migration.md +80 -0
- package/docs/webawesome-theme.md +57 -35
- package/docs/workbench-dialog.md +85 -0
- package/docs/workbench.md +10 -6
- package/docs/writing.md +10 -8
- package/doctor/copy-capitalization-checks.mjs +18 -9
- package/llms.txt +127 -57
- package/package.json +156 -39
- package/ux-demo/recipes/composer-form.tsx +18 -19
- package/ux-demo/recipes/list-detail-dialog.tsx +55 -162
- package/ux-demo/recipes/mount-recipe.ts +7 -6
- package/ux-demo/recipes/types.ts +1 -0
- package/ai/components/icon-button.md +0 -82
- package/ai/components/icon-toggle-button.md +0 -80
- package/dist/app-tab.js +0 -6
- package/dist/app-tab.js.map +0 -1
- package/dist/browser/app-tab.js +0 -4
- package/dist/browser/composer.js +0 -4
- package/dist/browser/icon-toggle-button.js +0 -4
- package/dist/browser/token-search-field.js +0 -4
- package/dist/chunk-2MSPNRWJ.js.map +0 -1
- package/dist/chunk-7IUEBNCO.js.map +0 -1
- package/dist/chunk-AV7CPAPT.js +0 -82
- package/dist/chunk-AV7CPAPT.js.map +0 -1
- package/dist/chunk-BYFTHA4I.js.map +0 -1
- package/dist/chunk-CA7LNX3J.js +0 -44
- package/dist/chunk-CA7LNX3J.js.map +0 -1
- package/dist/chunk-CR5U5FV6.js.map +0 -1
- package/dist/chunk-ELCMSQNJ.js.map +0 -1
- package/dist/chunk-ETCWQLJV.js.map +0 -1
- package/dist/chunk-FDZNYD4C.js.map +0 -1
- package/dist/chunk-FR76ZJQC.js +0 -90
- package/dist/chunk-FR76ZJQC.js.map +0 -1
- package/dist/chunk-HQZYKJ56.js.map +0 -1
- package/dist/chunk-HZPHCSCS.js.map +0 -1
- package/dist/chunk-JOR5LGYE.js.map +0 -1
- package/dist/chunk-K4AT3V3J.js.map +0 -1
- package/dist/chunk-LL45C7BB.js.map +0 -1
- package/dist/chunk-LOSRXZAH.js.map +0 -1
- package/dist/chunk-LPHU44S3.js.map +0 -1
- package/dist/chunk-M5KZ26VV.js.map +0 -1
- package/dist/chunk-MXNIVEVL.js.map +0 -1
- package/dist/chunk-NS762OVM.js +0 -222
- package/dist/chunk-NS762OVM.js.map +0 -1
- package/dist/chunk-QTSMHH5J.js.map +0 -1
- package/dist/chunk-T5BJBMW7.js.map +0 -1
- package/dist/chunk-TDMHA7C3.js.map +0 -1
- package/dist/chunk-TGLUDQP2.js.map +0 -1
- package/dist/chunk-U6QYTMDB.js.map +0 -1
- package/dist/chunk-VFYO3UGZ.js +0 -45
- package/dist/chunk-VFYO3UGZ.js.map +0 -1
- package/dist/chunk-W4IK7AWD.js.map +0 -1
- package/dist/chunk-YBWQR2OK.js.map +0 -1
- package/dist/chunk-ZJC5ND3M.js.map +0 -1
- package/dist/composer.js +0 -5
- package/dist/composer.js.map +0 -1
- package/dist/icon-button.d.ts +0 -46
- package/dist/icon-button.js +0 -6
- package/dist/icon-button.js.map +0 -1
- package/dist/icon-toggle-button.d.ts +0 -42
- package/dist/icon-toggle-button.js +0 -6
- package/dist/icon-toggle-button.js.map +0 -1
- package/dist/styles/components/actions/icon-button/icon-button.css +0 -22
- package/dist/styles/components/actions/icon-toggle-button/icon-toggle-button.css +0 -83
- package/dist/styles/icon-button.css +0 -22
- package/dist/styles/icon-toggle-button.css +0 -83
- package/dist/token-search-field.d.ts +0 -3
- package/dist/token-search-field.js +0 -5
- package/dist/token-search-field.js.map +0 -1
- package/dist/token-search-model.d.ts +0 -3
- package/dist/token-search-model.js +0 -3
- package/dist/token-search-model.js.map +0 -1
- package/dist/wire-composers.js +0 -3
- package/dist/wire-token-search-fields.js +0 -6
- package/docs/design/templates/composer/chat-dark.svg +0 -1
- package/docs/design/templates/composer/chat.svg +0 -1
- package/docs/design/templates/composer-dark.svg +0 -1
- package/docs/design/templates/composer.svg +0 -1
- /package/docs/design/templates/{token-search-field → search-field}/empty-dark.svg +0 -0
- /package/docs/design/templates/{token-search-field → search-field}/empty.svg +0 -0
- /package/docs/design/templates/{token-search-field → search-field}/tokens-dark.svg +0 -0
- /package/docs/design/templates/{token-search-field → search-field}/tokens.svg +0 -0
- /package/docs/design/templates/{token-search-field-dark.svg → search-field-dark.svg} +0 -0
- /package/docs/design/templates/{token-search-field.svg → search-field.svg} +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { Signal } from 'kerfjs';
|
|
2
|
-
import {
|
|
2
|
+
import { b as SearchFieldModel } from './search-field-CrGTN5sa.js';
|
|
3
3
|
import './semantic-content-BbzjvSu9.js';
|
|
4
4
|
|
|
5
|
-
interface
|
|
5
|
+
interface SearchFieldSubmit {
|
|
6
6
|
id: string;
|
|
7
7
|
editor: HTMLElement;
|
|
8
8
|
}
|
|
9
|
-
/** Reported to {@link
|
|
10
|
-
interface
|
|
9
|
+
/** Reported to {@link WireSearchFieldsOptions.onEdit} on every editor input. */
|
|
10
|
+
interface SearchFieldEdit extends SearchFieldSubmit {
|
|
11
11
|
/**
|
|
12
12
|
* The `InputEvent` that mutated the editor — read `event.inputType` / `event.data`
|
|
13
13
|
* to gate commit behavior (e.g. only parse a chip on whitespace-terminated input)
|
|
@@ -16,7 +16,7 @@ interface TokenSearchEdit extends TokenSearchSubmit {
|
|
|
16
16
|
event: InputEvent;
|
|
17
17
|
}
|
|
18
18
|
/** Reported when adjacent-token keyboard deletion asks the app to drop a chip. */
|
|
19
|
-
interface
|
|
19
|
+
interface SearchFieldTokenRemoval {
|
|
20
20
|
id: string;
|
|
21
21
|
/** The `data-token-value` of the token the app should remove from its state. */
|
|
22
22
|
value: string;
|
|
@@ -27,11 +27,11 @@ interface TokenSearchTokenRemoval {
|
|
|
27
27
|
/**
|
|
28
28
|
* Opt-in keyboard behavior for the atomic token chips. Off unless `keyboard` is
|
|
29
29
|
* set; each piece defaults on once opted in. The helper never mutates app state:
|
|
30
|
-
* a removal is reported through {@link
|
|
30
|
+
* a removal is reported through {@link SearchFieldKeyboardOptions.onRemoveToken}
|
|
31
31
|
* for the caller to apply, while caret movement past a chip is a pure ephemeral
|
|
32
32
|
* mechanic the helper performs itself.
|
|
33
33
|
*/
|
|
34
|
-
interface
|
|
34
|
+
interface SearchFieldKeyboardBaseOptions {
|
|
35
35
|
/**
|
|
36
36
|
* From a collapsed caret with no selection, Backspace removes the token
|
|
37
37
|
* immediately before it and Delete the token immediately after — reported via
|
|
@@ -43,20 +43,20 @@ interface TokenSearchKeyboardBaseOptions {
|
|
|
43
43
|
*/
|
|
44
44
|
moveCaretPastToken?: boolean;
|
|
45
45
|
}
|
|
46
|
-
type
|
|
46
|
+
type SearchFieldKeyboardOptions = SearchFieldKeyboardBaseOptions & ({
|
|
47
47
|
removeAdjacentToken?: true;
|
|
48
48
|
/** Apply the reported removal to your controlled state, then re-render. */
|
|
49
|
-
onRemoveToken: (removal:
|
|
49
|
+
onRemoveToken: (removal: SearchFieldTokenRemoval) => void;
|
|
50
50
|
} | {
|
|
51
51
|
removeAdjacentToken: false;
|
|
52
52
|
onRemoveToken?: never;
|
|
53
53
|
});
|
|
54
54
|
/**
|
|
55
|
-
* Managed collapsible behavior for the iconic
|
|
55
|
+
* Managed collapsible behavior for the iconic SearchField. Every piece is on
|
|
56
56
|
* by default; disable a specific one to own it in the app. Provide `signals` to
|
|
57
57
|
* drive app-owned `expanded` signals per field id instead of helper-created ones.
|
|
58
58
|
*/
|
|
59
|
-
interface
|
|
59
|
+
interface SearchFieldCollapsibleOptions {
|
|
60
60
|
/** Expand the field and focus its editor when the iconic trigger is activated. Default: true. */
|
|
61
61
|
expandOnActivate?: boolean;
|
|
62
62
|
/** Collapse the field when focus leaves it while it is empty. Default: true. */
|
|
@@ -69,7 +69,7 @@ interface TokenSearchCollapsibleOptions {
|
|
|
69
69
|
* Keep an empty field expanded when focus moves to a caller-owned surface
|
|
70
70
|
* rendered outside the field — a suggestions dropdown, date picker, or help
|
|
71
71
|
* popover shown beside it. Return true for any focus target that must NOT
|
|
72
|
-
* trigger collapse-on-empty-blur. An element carrying `data-
|
|
72
|
+
* trigger collapse-on-empty-blur. An element carrying `data-search-field-keep-open`
|
|
73
73
|
* (or any node inside one) is always exempt, so this predicate is only needed
|
|
74
74
|
* for surfaces you cannot mark declaratively.
|
|
75
75
|
*/
|
|
@@ -77,24 +77,24 @@ interface TokenSearchCollapsibleOptions {
|
|
|
77
77
|
/** App-owned `expanded` signals keyed by field id; adopted instead of helper-created. */
|
|
78
78
|
signals?: Readonly<Record<string, Signal<boolean>>>;
|
|
79
79
|
}
|
|
80
|
-
interface
|
|
81
|
-
/** Optional automatic grammar/suggestion models, keyed by
|
|
82
|
-
models?: Readonly<Record<string,
|
|
83
|
-
onSubmit?: (submission:
|
|
80
|
+
interface WireSearchFieldsOptions {
|
|
81
|
+
/** Optional automatic grammar/suggestion models, keyed by SearchField id. */
|
|
82
|
+
models?: Readonly<Record<string, SearchFieldModel>>;
|
|
83
|
+
onSubmit?: (submission: SearchFieldSubmit) => void;
|
|
84
84
|
/** Fired on every editor `input`, after the browser mutates it, so a caller can drop its own `input` listener. */
|
|
85
|
-
onEdit?: (edit:
|
|
85
|
+
onEdit?: (edit: SearchFieldEdit) => void;
|
|
86
86
|
/** Managed collapsible transient behavior. `true`/omitted = on with defaults; `false` = fully off. */
|
|
87
|
-
collapsible?: boolean |
|
|
87
|
+
collapsible?: boolean | SearchFieldCollapsibleOptions;
|
|
88
88
|
/** Opt-in atomic-chip keyboard behavior (off by default). */
|
|
89
|
-
keyboard?: false |
|
|
89
|
+
keyboard?: false | SearchFieldKeyboardOptions;
|
|
90
90
|
}
|
|
91
91
|
/**
|
|
92
|
-
* The value returned from {@link
|
|
92
|
+
* The value returned from {@link wireSearchFields}: call it (or `dispose()`) to
|
|
93
93
|
* tear down. When collapsible behavior is managed, it also exposes the transient
|
|
94
94
|
* `expanded` state per field id so the app can read it in render, hand in its own
|
|
95
95
|
* signal, or drive it imperatively.
|
|
96
96
|
*/
|
|
97
|
-
interface
|
|
97
|
+
interface SearchFieldsHandle {
|
|
98
98
|
(): void;
|
|
99
99
|
dispose(): void;
|
|
100
100
|
/** The managed `expanded` signal for a field id (adopted or helper-created); undefined when unmanaged. */
|
|
@@ -105,11 +105,11 @@ interface TokenSearchFieldsHandle {
|
|
|
105
105
|
close(id: string): void;
|
|
106
106
|
}
|
|
107
107
|
/**
|
|
108
|
-
* Wire every
|
|
108
|
+
* Wire every SearchField under `root`: submit on Enter, preserve the caret across
|
|
109
109
|
* controlled token deletion, and (by default) manage the collapsible field's transient
|
|
110
|
-
* expand/collapse/focus. Returns a {@link
|
|
110
|
+
* expand/collapse/focus. Returns a {@link SearchFieldsHandle} — a disposer that also
|
|
111
111
|
* exposes the managed `expanded` state per field id.
|
|
112
112
|
*/
|
|
113
|
-
declare function
|
|
113
|
+
declare function wireSearchFields(root: HTMLElement, { models, onSubmit, onEdit, collapsible, keyboard, }?: WireSearchFieldsOptions): SearchFieldsHandle;
|
|
114
114
|
|
|
115
|
-
export { type
|
|
115
|
+
export { type SearchFieldCollapsibleOptions, type SearchFieldEdit, type SearchFieldKeyboardOptions, type SearchFieldSubmit, type SearchFieldTokenRemoval, type SearchFieldsHandle, type WireSearchFieldsOptions, wireSearchFields };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"wire-search-fields.js"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keep every Slider under `root` in step with a drag before the app
|
|
3
|
+
* re-renders: one delegated `input` listener updates the track fill, the
|
|
4
|
+
* `<output>` readout, and the spoken value text from the live value. Returns
|
|
5
|
+
* a disposer. The app still owns the value (read it on `input` or `change`
|
|
6
|
+
* through the Slider's `action`) and re-renders with it.
|
|
7
|
+
*/
|
|
8
|
+
declare function wireSliders(root?: Element | Document): () => void;
|
|
9
|
+
/** Recompute one Slider's fill, readout, and value text from its input. */
|
|
10
|
+
declare function syncSlider(input: HTMLInputElement): void;
|
|
11
|
+
|
|
12
|
+
export { syncSlider, wireSliders };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// src/components/forms/slider/wiring/wire-sliders.ts
|
|
2
|
+
function wireSliders(root = document) {
|
|
3
|
+
const onInput = (event) => {
|
|
4
|
+
const input = event.target;
|
|
5
|
+
if (!(input instanceof HTMLInputElement) || !input.classList.contains("kui-slider__input"))
|
|
6
|
+
return;
|
|
7
|
+
syncSlider(input);
|
|
8
|
+
};
|
|
9
|
+
root.addEventListener("input", onInput);
|
|
10
|
+
return () => root.removeEventListener("input", onInput);
|
|
11
|
+
}
|
|
12
|
+
function syncSlider(input) {
|
|
13
|
+
const min = Number(input.min || 0);
|
|
14
|
+
const max = Number(input.max || 100);
|
|
15
|
+
const value = Number(input.value);
|
|
16
|
+
const fraction = max === min ? 0 : (value - min) / (max - min);
|
|
17
|
+
input.style.setProperty(
|
|
18
|
+
"--_kui-slider-fill",
|
|
19
|
+
`${Number((fraction * 100).toFixed(4))}%`
|
|
20
|
+
);
|
|
21
|
+
const slider = input.closest(".kui-slider");
|
|
22
|
+
const unit = slider?.dataset.unit ?? "";
|
|
23
|
+
const text = `${input.value}${unit}`;
|
|
24
|
+
if (unit) input.setAttribute("aria-valuetext", text);
|
|
25
|
+
const output = slider?.querySelector(".kui-slider__value");
|
|
26
|
+
if (output) output.textContent = text;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { syncSlider, wireSliders };
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=wire-sliders.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/forms/slider/wiring/wire-sliders.ts"],"names":[],"mappings":";AAOO,SAAS,WAAA,CAAY,OAA2B,QAAA,EAAsB;AAC3E,EAAA,MAAM,OAAA,GAAU,CAAC,KAAA,KAAiB;AAChC,IAAA,MAAM,QAAQ,KAAA,CAAM,MAAA;AACpB,IAAA,IACE,EAAE,KAAA,YAAiB,gBAAA,CAAA,IACnB,CAAC,KAAA,CAAM,SAAA,CAAU,SAAS,mBAAmB,CAAA;AAE7C,MAAA;AACF,IAAA,UAAA,CAAW,KAAK,CAAA;AAAA,EAClB,CAAA;AACA,EAAA,IAAA,CAAK,gBAAA,CAAiB,SAAS,OAAO,CAAA;AACtC,EAAA,OAAO,MAAM,IAAA,CAAK,mBAAA,CAAoB,OAAA,EAAS,OAAO,CAAA;AACxD;AAGO,SAAS,WAAW,KAAA,EAA+B;AACxD,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,KAAA,CAAM,GAAA,IAAO,CAAC,CAAA;AACjC,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,KAAA,CAAM,GAAA,IAAO,GAAG,CAAA;AACnC,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,KAAK,CAAA;AAChC,EAAA,MAAM,WAAW,GAAA,KAAQ,GAAA,GAAM,CAAA,GAAA,CAAK,KAAA,GAAQ,QAAQ,GAAA,GAAM,GAAA,CAAA;AAC1D,EAAA,KAAA,CAAM,KAAA,CAAM,WAAA;AAAA,IACV,oBAAA;AAAA,IACA,GAAG,MAAA,CAAA,CAAQ,QAAA,GAAW,KAAK,OAAA,CAAQ,CAAC,CAAC,CAAC,CAAA,CAAA;AAAA,GACxC;AACA,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,OAAA,CAAqB,aAAa,CAAA;AACvD,EAAA,MAAM,IAAA,GAAO,MAAA,EAAQ,OAAA,CAAQ,IAAA,IAAQ,EAAA;AACrC,EAAA,MAAM,IAAA,GAAO,CAAA,EAAG,KAAA,CAAM,KAAK,GAAG,IAAI,CAAA,CAAA;AAClC,EAAA,IAAI,IAAA,EAAM,KAAA,CAAM,YAAA,CAAa,gBAAA,EAAkB,IAAI,CAAA;AACnD,EAAA,MAAM,MAAA,GAAS,MAAA,EAAQ,aAAA,CAAc,oBAAoB,CAAA;AACzD,EAAA,IAAI,MAAA,SAAe,WAAA,GAAc,IAAA;AACnC","file":"wire-sliders.js","sourcesContent":["/**\n * Keep every Slider under `root` in step with a drag before the app\n * re-renders: one delegated `input` listener updates the track fill, the\n * `<output>` readout, and the spoken value text from the live value. Returns\n * a disposer. The app still owns the value (read it on `input` or `change`\n * through the Slider's `action`) and re-renders with it.\n */\nexport function wireSliders(root: Element | Document = document): () => void {\n const onInput = (event: Event) => {\n const input = event.target;\n if (\n !(input instanceof HTMLInputElement) ||\n !input.classList.contains('kui-slider__input')\n )\n return;\n syncSlider(input);\n };\n root.addEventListener('input', onInput);\n return () => root.removeEventListener('input', onInput);\n}\n\n/** Recompute one Slider's fill, readout, and value text from its input. */\nexport function syncSlider(input: HTMLInputElement): void {\n const min = Number(input.min || 0);\n const max = Number(input.max || 100);\n const value = Number(input.value);\n const fraction = max === min ? 0 : (value - min) / (max - min);\n input.style.setProperty(\n '--_kui-slider-fill',\n `${Number((fraction * 100).toFixed(4))}%`,\n );\n const slider = input.closest<HTMLElement>('.kui-slider');\n const unit = slider?.dataset.unit ?? '';\n const text = `${input.value}${unit}`;\n if (unit) input.setAttribute('aria-valuetext', text);\n const output = slider?.querySelector('.kui-slider__value');\n if (output) output.textContent = text;\n}\n"]}
|
package/dist/wire-tab-bars.js
CHANGED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** Reported to {@link WireTagFieldsOptions.onChange} with the field's next tags. */
|
|
2
|
+
interface TagFieldChange {
|
|
3
|
+
id: string;
|
|
4
|
+
tags: string[];
|
|
5
|
+
}
|
|
6
|
+
/** Why a typed value did not become a tag. */
|
|
7
|
+
type TagFieldRejection = 'duplicate' | 'max' | 'invalid';
|
|
8
|
+
interface WireTagFieldsOptions {
|
|
9
|
+
/** Apply the next tag list to your state, then re-render the TagField. */
|
|
10
|
+
onChange: (change: TagFieldChange) => void;
|
|
11
|
+
/** Report a value that was not added (to show an `error`, for example). */
|
|
12
|
+
onReject?: (rejection: {
|
|
13
|
+
id: string;
|
|
14
|
+
value: string;
|
|
15
|
+
reason: TagFieldRejection;
|
|
16
|
+
}) => void;
|
|
17
|
+
/** Keys besides Enter that add the typed tag (default `[',']`). */
|
|
18
|
+
delimiters?: readonly string[];
|
|
19
|
+
/** Accept a tag already in the list (default false). */
|
|
20
|
+
allowDuplicates?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Clean up a typed value, or return `undefined` to refuse it as invalid
|
|
23
|
+
* (default: trim, refusing an empty value).
|
|
24
|
+
*/
|
|
25
|
+
normalize?: (value: string, id: string) => string | undefined;
|
|
26
|
+
/** Add the typed text when focus leaves the editor for anything but its own chips (default true). */
|
|
27
|
+
commitOnBlur?: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Wire every TagField under `root`: Enter or a delimiter adds the typed text
|
|
31
|
+
* as a tag (several at once when pasted text holds delimiters), leaving focus
|
|
32
|
+
* adds it too, a chip's × or Backspace at the start removes a tag, a chip's
|
|
33
|
+
* label moves it back into the editor to edit, the clear button empties the
|
|
34
|
+
* list, and ArrowLeft / ArrowRight move between the chips and the editor.
|
|
35
|
+
* Duplicates, the field's `max`, and `normalize` are enforced before
|
|
36
|
+
* `onChange`. It also wires the SearchField editor mechanics the TagField is
|
|
37
|
+
* built on. Returns a disposer.
|
|
38
|
+
*/
|
|
39
|
+
declare function wireTagFields(root: HTMLElement, { onChange, onReject, delimiters, allowDuplicates, normalize, commitOnBlur, }: WireTagFieldsOptions): () => void;
|
|
40
|
+
|
|
41
|
+
export { type TagFieldChange, type TagFieldRejection, type WireTagFieldsOptions, wireTagFields };
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { tagFieldActions } from './chunk-6VVIW7VB.js';
|
|
2
|
+
import { wireSearchFields } from './chunk-UMNHJSIO.js';
|
|
3
|
+
import { placeSearchFieldCaret, readSearchField } from './chunk-VEME3D7K.js';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
import { delegateCapture, delegate } from 'kerfjs';
|
|
7
|
+
|
|
8
|
+
var defaultNormalize = (value) => value.trim() || void 0;
|
|
9
|
+
var idOf = (field) => field.dataset.tagFieldId;
|
|
10
|
+
var tokenOf = (element) => element.dataset.tokenValue;
|
|
11
|
+
function tagFieldOf(element) {
|
|
12
|
+
return element.closest('[data-component="tag-field"]');
|
|
13
|
+
}
|
|
14
|
+
function tagsOf(field) {
|
|
15
|
+
return [
|
|
16
|
+
...field.querySelectorAll(
|
|
17
|
+
'[data-component="search-field-token"]'
|
|
18
|
+
)
|
|
19
|
+
].map(tokenOf);
|
|
20
|
+
}
|
|
21
|
+
function editorOf(field) {
|
|
22
|
+
return field.querySelector("[data-tag-field-editor]");
|
|
23
|
+
}
|
|
24
|
+
function textBeforeCaret(editor) {
|
|
25
|
+
const selection = globalThis.getSelection();
|
|
26
|
+
if (!selection || selection.rangeCount === 0 || !selection.isCollapsed)
|
|
27
|
+
return void 0;
|
|
28
|
+
const caret = selection.getRangeAt(0);
|
|
29
|
+
if (!editor.contains(caret.startContainer)) return void 0;
|
|
30
|
+
const range = document.createRange();
|
|
31
|
+
range.selectNodeContents(editor);
|
|
32
|
+
range.setEnd(caret.startContainer, caret.startOffset);
|
|
33
|
+
const fragment = range.cloneContents();
|
|
34
|
+
for (const chip of fragment.querySelectorAll(
|
|
35
|
+
'[data-component="search-field-token"]'
|
|
36
|
+
))
|
|
37
|
+
chip.remove();
|
|
38
|
+
return fragment.textContent.replaceAll("\u200B", "");
|
|
39
|
+
}
|
|
40
|
+
function wireTagFields(root, {
|
|
41
|
+
onChange,
|
|
42
|
+
onReject,
|
|
43
|
+
delimiters = [","],
|
|
44
|
+
allowDuplicates = false,
|
|
45
|
+
normalize = defaultNormalize,
|
|
46
|
+
commitOnBlur = true
|
|
47
|
+
}) {
|
|
48
|
+
const pendingEdits = /* @__PURE__ */ new Map();
|
|
49
|
+
const fieldById = (id) => root.querySelector(`[data-tag-field-id="${CSS.escape(id)}"]`);
|
|
50
|
+
const change = (id, tags) => {
|
|
51
|
+
const typing = fieldById(id)?.querySelector("[data-tag-field-editor]")?.contains(document.activeElement);
|
|
52
|
+
onChange({ id, tags });
|
|
53
|
+
const text = pendingEdits.get(id);
|
|
54
|
+
pendingEdits.delete(id);
|
|
55
|
+
if (text === void 0 && !typing) return;
|
|
56
|
+
globalThis.queueMicrotask(() => {
|
|
57
|
+
const field = fieldById(id);
|
|
58
|
+
const editor = field && editorOf(field);
|
|
59
|
+
if (!editor) return;
|
|
60
|
+
if (text === void 0) {
|
|
61
|
+
if (!editor.contains(document.activeElement))
|
|
62
|
+
placeSearchFieldCaret(editor);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const span = editor.querySelector(
|
|
66
|
+
"[data-search-field-text]:last-of-type"
|
|
67
|
+
) ?? editor;
|
|
68
|
+
span.textContent = text;
|
|
69
|
+
editor.dispatchEvent(
|
|
70
|
+
new InputEvent("input", { bubbles: true, inputType: "insertText" })
|
|
71
|
+
);
|
|
72
|
+
placeSearchFieldCaret(editor);
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
const commit = (field, editor) => {
|
|
76
|
+
const id = idOf(field);
|
|
77
|
+
const text = readSearchField(editor).query;
|
|
78
|
+
const parts = delimiters.reduce(
|
|
79
|
+
(pieces, delimiter) => pieces.flatMap((piece) => piece.split(delimiter)),
|
|
80
|
+
[text]
|
|
81
|
+
);
|
|
82
|
+
const tags = tagsOf(field);
|
|
83
|
+
const max = field.dataset.max === void 0 ? Infinity : Number(field.dataset.max);
|
|
84
|
+
let added = false;
|
|
85
|
+
for (const part of parts) {
|
|
86
|
+
if (part.trim() === "") continue;
|
|
87
|
+
const value = normalize(part, id);
|
|
88
|
+
if (value === void 0) {
|
|
89
|
+
onReject?.({ id, value: part.trim(), reason: "invalid" });
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (!allowDuplicates && tags.includes(value)) {
|
|
93
|
+
onReject?.({ id, value, reason: "duplicate" });
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (tags.length >= max) {
|
|
97
|
+
onReject?.({ id, value, reason: "max" });
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
tags.push(value);
|
|
101
|
+
added = true;
|
|
102
|
+
}
|
|
103
|
+
if (added) change(id, tags);
|
|
104
|
+
return added;
|
|
105
|
+
};
|
|
106
|
+
const stopSearchFields = wireSearchFields(root, { collapsible: false });
|
|
107
|
+
const stopKeys = delegateCapture(
|
|
108
|
+
root,
|
|
109
|
+
"keydown",
|
|
110
|
+
'[data-component="tag-field"]',
|
|
111
|
+
(event, element) => {
|
|
112
|
+
const key = event;
|
|
113
|
+
if (key.isComposing) return;
|
|
114
|
+
const field = element;
|
|
115
|
+
const editor = editorOf(field);
|
|
116
|
+
if (!editor) return;
|
|
117
|
+
const target = key.target;
|
|
118
|
+
const chips = [
|
|
119
|
+
...field.querySelectorAll(
|
|
120
|
+
`[data-action="${tagFieldActions.edit}"]`
|
|
121
|
+
)
|
|
122
|
+
];
|
|
123
|
+
const forward = globalThis.getComputedStyle(field).direction === "rtl" ? "ArrowLeft" : "ArrowRight";
|
|
124
|
+
const backward = forward === "ArrowRight" ? "ArrowLeft" : "ArrowRight";
|
|
125
|
+
const index = chips.indexOf(target);
|
|
126
|
+
if (index === -1 && (target === editor || editor.contains(target))) {
|
|
127
|
+
if (key.key === "Enter" || delimiters.includes(key.key)) {
|
|
128
|
+
key.preventDefault();
|
|
129
|
+
commit(field, editor);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (key.key === "Tab" && commitOnBlur) {
|
|
133
|
+
commit(field, editor);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (key.key === "Backspace" && textBeforeCaret(editor) === "") {
|
|
137
|
+
const run = globalThis.getSelection()?.getRangeAt(0).startContainer.parentElement?.closest("[data-search-field-text]");
|
|
138
|
+
const chip = run?.previousElementSibling ?? editor.querySelector(
|
|
139
|
+
'[data-component="search-field-token"]:last-of-type'
|
|
140
|
+
);
|
|
141
|
+
if (!chip?.matches('[data-component="search-field-token"]')) return;
|
|
142
|
+
key.preventDefault();
|
|
143
|
+
const value = tokenOf(chip);
|
|
144
|
+
change(
|
|
145
|
+
idOf(field),
|
|
146
|
+
tagsOf(field).filter((tag) => tag !== value)
|
|
147
|
+
);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (key.key === backward && chips.length > 0 && textBeforeCaret(editor) === "") {
|
|
151
|
+
key.preventDefault();
|
|
152
|
+
chips.at(-1).focus();
|
|
153
|
+
}
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (index === -1) return;
|
|
157
|
+
if (key.key === backward) {
|
|
158
|
+
key.preventDefault();
|
|
159
|
+
chips[Math.max(0, index - 1)].focus();
|
|
160
|
+
} else if (key.key === forward) {
|
|
161
|
+
key.preventDefault();
|
|
162
|
+
if (index === chips.length - 1) placeSearchFieldCaret(editor);
|
|
163
|
+
else chips[index + 1].focus();
|
|
164
|
+
} else if (key.key === "Backspace" || key.key === "Delete") {
|
|
165
|
+
key.preventDefault();
|
|
166
|
+
const value = tokenOf(target);
|
|
167
|
+
change(
|
|
168
|
+
idOf(field),
|
|
169
|
+
tagsOf(field).filter((tag) => tag !== value)
|
|
170
|
+
);
|
|
171
|
+
globalThis.queueMicrotask(() => {
|
|
172
|
+
const next = [
|
|
173
|
+
...field.querySelectorAll(
|
|
174
|
+
`[data-action="${tagFieldActions.edit}"]`
|
|
175
|
+
)
|
|
176
|
+
];
|
|
177
|
+
const live = editorOf(field);
|
|
178
|
+
if (next.length === 0 && live) placeSearchFieldCaret(live);
|
|
179
|
+
else next[Math.min(index, next.length - 1)]?.focus();
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
);
|
|
184
|
+
const stopPaste = delegate(
|
|
185
|
+
root,
|
|
186
|
+
"input",
|
|
187
|
+
"[data-tag-field-editor]",
|
|
188
|
+
(event, element) => {
|
|
189
|
+
const input = event;
|
|
190
|
+
if (input.inputType !== "insertFromPaste") return;
|
|
191
|
+
const editor = element;
|
|
192
|
+
const field = tagFieldOf(editor);
|
|
193
|
+
if (field) commit(field, editor);
|
|
194
|
+
}
|
|
195
|
+
);
|
|
196
|
+
const stopBlur = delegate(
|
|
197
|
+
root,
|
|
198
|
+
"focusout",
|
|
199
|
+
"[data-tag-field-editor]",
|
|
200
|
+
(event, element) => {
|
|
201
|
+
if (!commitOnBlur) return;
|
|
202
|
+
const editor = element;
|
|
203
|
+
const field = tagFieldOf(editor);
|
|
204
|
+
const next = event.relatedTarget;
|
|
205
|
+
if (!field || next instanceof Node && editor.contains(next)) return;
|
|
206
|
+
commit(field, editor);
|
|
207
|
+
}
|
|
208
|
+
);
|
|
209
|
+
const stopClicks = delegate(
|
|
210
|
+
root,
|
|
211
|
+
"click",
|
|
212
|
+
`[data-component="tag-field"] [data-action]`,
|
|
213
|
+
(_event, element) => {
|
|
214
|
+
const button = element;
|
|
215
|
+
const field = tagFieldOf(button);
|
|
216
|
+
if (!field) return;
|
|
217
|
+
const id = idOf(field);
|
|
218
|
+
const value = tokenOf(button);
|
|
219
|
+
switch (button.dataset.action) {
|
|
220
|
+
case tagFieldActions.remove:
|
|
221
|
+
change(
|
|
222
|
+
id,
|
|
223
|
+
tagsOf(field).filter((tag) => tag !== value)
|
|
224
|
+
);
|
|
225
|
+
globalThis.queueMicrotask(() => {
|
|
226
|
+
const live = editorOf(field);
|
|
227
|
+
if (live) placeSearchFieldCaret(live);
|
|
228
|
+
});
|
|
229
|
+
return;
|
|
230
|
+
case tagFieldActions.edit:
|
|
231
|
+
pendingEdits.set(id, value);
|
|
232
|
+
change(
|
|
233
|
+
id,
|
|
234
|
+
tagsOf(field).filter((tag) => tag !== value)
|
|
235
|
+
);
|
|
236
|
+
return;
|
|
237
|
+
case tagFieldActions.clear:
|
|
238
|
+
change(id, []);
|
|
239
|
+
globalThis.queueMicrotask(() => {
|
|
240
|
+
const live = editorOf(field);
|
|
241
|
+
if (live) placeSearchFieldCaret(live);
|
|
242
|
+
});
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
);
|
|
247
|
+
return () => {
|
|
248
|
+
stopSearchFields();
|
|
249
|
+
stopKeys();
|
|
250
|
+
stopPaste();
|
|
251
|
+
stopBlur();
|
|
252
|
+
stopClicks();
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export { wireTagFields };
|
|
257
|
+
|
|
258
|
+
//# sourceMappingURL=wire-tag-fields.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/forms/tag-field/wiring/wire-tag-fields.ts"],"names":[],"mappings":"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","file":"wire-tag-fields.js","sourcesContent":["import { delegate, delegateCapture } from 'kerfjs';\n\nimport {\n placeSearchFieldCaret,\n readSearchField,\n} from '../../search-field/search-field.js';\nimport { wireSearchFields } from '../../search-field/wiring/wire-search-fields.js';\nimport { tagFieldActions } from '../tag-field.js';\n\n/** Reported to {@link WireTagFieldsOptions.onChange} with the field's next tags. */\nexport interface TagFieldChange {\n id: string;\n tags: string[];\n}\n\n/** Why a typed value did not become a tag. */\nexport type TagFieldRejection = 'duplicate' | 'max' | 'invalid';\n\nexport interface WireTagFieldsOptions {\n /** Apply the next tag list to your state, then re-render the TagField. */\n onChange: (change: TagFieldChange) => void;\n /** Report a value that was not added (to show an `error`, for example). */\n onReject?: (rejection: {\n id: string;\n value: string;\n reason: TagFieldRejection;\n }) => void;\n /** Keys besides Enter that add the typed tag (default `[',']`). */\n delimiters?: readonly string[];\n /** Accept a tag already in the list (default false). */\n allowDuplicates?: boolean;\n /**\n * Clean up a typed value, or return `undefined` to refuse it as invalid\n * (default: trim, refusing an empty value).\n */\n normalize?: (value: string, id: string) => string | undefined;\n /** Add the typed text when focus leaves the editor for anything but its own chips (default true). */\n commitOnBlur?: boolean;\n}\n\nconst defaultNormalize = (value: string) => value.trim() || undefined;\n\n/** The field's id and a chip's value: attributes the render always writes. */\nconst idOf = (field: HTMLElement) => field.dataset.tagFieldId!;\nconst tokenOf = (element: HTMLElement) => element.dataset.tokenValue!;\n\nfunction tagFieldOf(element: Element): HTMLElement | null {\n return element.closest<HTMLElement>('[data-component=\"tag-field\"]');\n}\n\nfunction tagsOf(field: HTMLElement): string[] {\n return [\n ...field.querySelectorAll<HTMLElement>(\n '[data-component=\"search-field-token\"]',\n ),\n ].map(tokenOf);\n}\n\nfunction editorOf(field: HTMLElement): HTMLElement | null {\n return field.querySelector<HTMLElement>('[data-tag-field-editor]');\n}\n\n/** The text before the caret in an editor, or undefined without a caret in it. */\nfunction textBeforeCaret(editor: HTMLElement): string | undefined {\n const selection = globalThis.getSelection();\n if (!selection || selection.rangeCount === 0 || !selection.isCollapsed)\n return undefined;\n const caret = selection.getRangeAt(0);\n if (!editor.contains(caret.startContainer)) return undefined;\n const range = document.createRange();\n range.selectNodeContents(editor);\n range.setEnd(caret.startContainer, caret.startOffset);\n const fragment = range.cloneContents();\n for (const chip of fragment.querySelectorAll(\n '[data-component=\"search-field-token\"]',\n ))\n chip.remove();\n return fragment.textContent!.replaceAll('', '');\n}\n\n/**\n * Wire every TagField under `root`: Enter or a delimiter adds the typed text\n * as a tag (several at once when pasted text holds delimiters), leaving focus\n * adds it too, a chip's × or Backspace at the start removes a tag, a chip's\n * label moves it back into the editor to edit, the clear button empties the\n * list, and ArrowLeft / ArrowRight move between the chips and the editor.\n * Duplicates, the field's `max`, and `normalize` are enforced before\n * `onChange`. It also wires the SearchField editor mechanics the TagField is\n * built on. Returns a disposer.\n */\nexport function wireTagFields(\n root: HTMLElement,\n {\n onChange,\n onReject,\n delimiters = [','],\n allowDuplicates = false,\n normalize = defaultNormalize,\n commitOnBlur = true,\n }: WireTagFieldsOptions,\n): () => void {\n // Text to place in an editor once the app re-renders it (editing a tag).\n const pendingEdits = new Map<string, string>();\n\n const fieldById = (id: string) =>\n root.querySelector<HTMLElement>(`[data-tag-field-id=\"${CSS.escape(id)}\"]`);\n\n const change = (id: string, tags: string[]) => {\n // A tag change rebuilds the editor, which drops focus from the old one:\n // return the caret to the new editor when the person was typing in it.\n const typing = fieldById(id)\n ?.querySelector('[data-tag-field-editor]')\n ?.contains(document.activeElement);\n onChange({ id, tags });\n const text = pendingEdits.get(id);\n pendingEdits.delete(id);\n if (text === undefined && !typing) return;\n globalThis.queueMicrotask(() => {\n const field = fieldById(id);\n const editor = field && editorOf(field);\n if (!editor) return;\n if (text === undefined) {\n if (!editor.contains(document.activeElement))\n placeSearchFieldCaret(editor);\n return;\n }\n const span =\n editor.querySelector<HTMLElement>(\n '[data-search-field-text]:last-of-type',\n ) ?? editor;\n span.textContent = text;\n editor.dispatchEvent(\n new InputEvent('input', { bubbles: true, inputType: 'insertText' }),\n );\n placeSearchFieldCaret(editor);\n });\n };\n\n /** Add the editor's text as tags; returns whether any text was taken. */\n const commit = (field: HTMLElement, editor: HTMLElement): boolean => {\n const id = idOf(field);\n const text = readSearchField(editor).query;\n const parts = delimiters.reduce<string[]>(\n (pieces, delimiter) => pieces.flatMap((piece) => piece.split(delimiter)),\n [text],\n );\n const tags = tagsOf(field);\n const max =\n field.dataset.max === undefined ? Infinity : Number(field.dataset.max);\n let added = false;\n for (const part of parts) {\n if (part.trim() === '') continue;\n const value = normalize(part, id);\n if (value === undefined) {\n onReject?.({ id, value: part.trim(), reason: 'invalid' });\n continue;\n }\n if (!allowDuplicates && tags.includes(value)) {\n onReject?.({ id, value, reason: 'duplicate' });\n continue;\n }\n if (tags.length >= max) {\n onReject?.({ id, value, reason: 'max' });\n continue;\n }\n tags.push(value);\n added = true;\n }\n if (added) change(id, tags);\n return added;\n };\n\n // The SearchField editor mechanics (empty-text normalization, the\n // placeholder) the TagField is built on; its keys are handled below.\n const stopSearchFields = wireSearchFields(root, { collapsible: false });\n\n const stopKeys = delegateCapture(\n root,\n 'keydown',\n '[data-component=\"tag-field\"]',\n (event, element) => {\n const key = event as KeyboardEvent;\n if (key.isComposing) return;\n const field = element as HTMLElement;\n const editor = editorOf(field);\n if (!editor) return;\n const target = key.target as HTMLElement;\n const chips = [\n ...field.querySelectorAll<HTMLElement>(\n `[data-action=\"${tagFieldActions.edit}\"]`,\n ),\n ];\n const forward =\n globalThis.getComputedStyle(field).direction === 'rtl'\n ? 'ArrowLeft'\n : 'ArrowRight';\n const backward = forward === 'ArrowRight' ? 'ArrowLeft' : 'ArrowRight';\n const index = chips.indexOf(target);\n // The chips sit inside the editor, so test for a chip first.\n if (index === -1 && (target === editor || editor.contains(target))) {\n if (key.key === 'Enter' || delimiters.includes(key.key)) {\n key.preventDefault();\n commit(field, editor);\n return;\n }\n // Tab may move focus onto a chip inside the editor (which a blur\n // would not count as leaving), so it adds the typed text itself.\n if (key.key === 'Tab' && commitOnBlur) {\n commit(field, editor);\n return;\n }\n if (key.key === 'Backspace' && textBeforeCaret(editor) === '') {\n // Remove the tag just before the caret: the chip ahead of the\n // text run the caret is in.\n const run = globalThis\n .getSelection()\n ?.getRangeAt(0)\n .startContainer.parentElement?.closest('[data-search-field-text]');\n const chip = (run?.previousElementSibling ??\n editor.querySelector(\n '[data-component=\"search-field-token\"]:last-of-type',\n )) as HTMLElement | null;\n if (!chip?.matches('[data-component=\"search-field-token\"]')) return;\n key.preventDefault();\n const value = tokenOf(chip);\n change(\n idOf(field),\n tagsOf(field).filter((tag) => tag !== value),\n );\n return;\n }\n if (\n key.key === backward &&\n chips.length > 0 &&\n textBeforeCaret(editor) === ''\n ) {\n key.preventDefault();\n chips.at(-1)!.focus();\n }\n return;\n }\n if (index === -1) return;\n if (key.key === backward) {\n key.preventDefault();\n chips[Math.max(0, index - 1)]!.focus();\n } else if (key.key === forward) {\n key.preventDefault();\n if (index === chips.length - 1) placeSearchFieldCaret(editor);\n else chips[index + 1]!.focus();\n } else if (key.key === 'Backspace' || key.key === 'Delete') {\n key.preventDefault();\n const value = tokenOf(target);\n change(\n idOf(field),\n tagsOf(field).filter((tag) => tag !== value),\n );\n globalThis.queueMicrotask(() => {\n const next = [\n ...field.querySelectorAll<HTMLElement>(\n `[data-action=\"${tagFieldActions.edit}\"]`,\n ),\n ];\n const live = editorOf(field);\n if (next.length === 0 && live) placeSearchFieldCaret(live);\n else next[Math.min(index, next.length - 1)]?.focus();\n });\n }\n },\n );\n\n const stopPaste = delegate(\n root,\n 'input',\n '[data-tag-field-editor]',\n (event, element) => {\n const input = event as InputEvent;\n if (input.inputType !== 'insertFromPaste') return;\n const editor = element as HTMLElement;\n const field = tagFieldOf(editor);\n if (field) commit(field, editor);\n },\n );\n\n const stopBlur = delegate(\n root,\n 'focusout',\n '[data-tag-field-editor]',\n (event, element) => {\n if (!commitOnBlur) return;\n const editor = element as HTMLElement;\n const field = tagFieldOf(editor);\n const next = (event as FocusEvent).relatedTarget;\n // Focus moving within the editor (onto one of its chips) keeps editing.\n if (!field || (next instanceof Node && editor.contains(next))) return;\n commit(field, editor);\n },\n );\n\n const stopClicks = delegate(\n root,\n 'click',\n `[data-component=\"tag-field\"] [data-action]`,\n (_event, element) => {\n const button = element as HTMLElement;\n const field = tagFieldOf(button);\n if (!field) return;\n const id = idOf(field);\n const value = tokenOf(button);\n switch (button.dataset.action) {\n case tagFieldActions.remove:\n change(\n id,\n tagsOf(field).filter((tag) => tag !== value),\n );\n globalThis.queueMicrotask(() => {\n const live = editorOf(field);\n if (live) placeSearchFieldCaret(live);\n });\n return;\n case tagFieldActions.edit:\n pendingEdits.set(id, value);\n change(\n id,\n tagsOf(field).filter((tag) => tag !== value),\n );\n return;\n case tagFieldActions.clear:\n change(id, []);\n globalThis.queueMicrotask(() => {\n const live = editorOf(field);\n if (live) placeSearchFieldCaret(live);\n });\n return;\n }\n },\n );\n\n return () => {\n stopSearchFields();\n stopKeys();\n stopPaste();\n stopBlur();\n stopClicks();\n };\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type Root = HTMLElement | Document;
|
|
2
|
+
/**
|
|
3
|
+
* Make every clearable `TextField` below root clear itself: its clear button
|
|
4
|
+
* empties the field, announces the change with bubbling `input` and `change`
|
|
5
|
+
* events (as typing would), and returns focus to the field. The button hides
|
|
6
|
+
* itself while the field is empty. A field with `showCount` keeps its
|
|
7
|
+
* `count / maxLength` current as people type. Dispose with the owning
|
|
8
|
+
* application.
|
|
9
|
+
*/
|
|
10
|
+
declare function wireTextFields(root: Root): () => void;
|
|
11
|
+
|
|
12
|
+
export { wireTextFields };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"wire-text-fields.js"}
|