@g9tm/lynxcontrols 0.0.0-stage → 1.4.2
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 +29 -2
- package/dist/.tsbuildinfo +1 -0
- package/dist/base/base.css +16 -0
- package/dist/base/base.css.map +1 -0
- package/dist/base/control.d.ts +68 -0
- package/dist/base/control.d.ts.map +1 -0
- package/dist/base/control.jsx +36 -0
- package/dist/base/control.jsx.map +1 -0
- package/dist/base/corner-badge.d.ts +35 -0
- package/dist/base/corner-badge.d.ts.map +1 -0
- package/dist/base/corner-badge.jsx +45 -0
- package/dist/base/corner-badge.jsx.map +1 -0
- package/dist/base/disposer.d.ts +28 -0
- package/dist/base/disposer.d.ts.map +1 -0
- package/dist/base/disposer.jsx +61 -0
- package/dist/base/disposer.jsx.map +1 -0
- package/dist/base/index.d.ts +10 -0
- package/dist/base/index.d.ts.map +1 -0
- package/dist/base/index.jsx +9 -0
- package/dist/base/press.d.ts +38 -0
- package/dist/base/press.d.ts.map +1 -0
- package/dist/base/press.jsx +73 -0
- package/dist/base/press.jsx.map +1 -0
- package/dist/base/pressable.d.ts +25 -0
- package/dist/base/pressable.d.ts.map +1 -0
- package/dist/base/pressable.jsx +38 -0
- package/dist/base/pressable.jsx.map +1 -0
- package/dist/base/selection-item.d.ts +29 -0
- package/dist/base/selection-item.d.ts.map +1 -0
- package/dist/base/selection-item.jsx +6 -0
- package/dist/base/selection-item.jsx.map +1 -0
- package/dist/base/timers.d.ts +7 -0
- package/dist/base/timers.d.ts.map +1 -0
- package/dist/base/timers.jsx +10 -0
- package/dist/base/timers.jsx.map +1 -0
- package/dist/base/use-controllable-state.d.ts +30 -0
- package/dist/base/use-controllable-state.d.ts.map +1 -0
- package/dist/base/use-controllable-state.jsx +49 -0
- package/dist/base/use-controllable-state.jsx.map +1 -0
- package/dist/base/use-stable-callback.d.ts +8 -0
- package/dist/base/use-stable-callback.d.ts.map +1 -0
- package/dist/base/use-stable-callback.jsx +12 -0
- package/dist/base/use-stable-callback.jsx.map +1 -0
- package/dist/button/button.css +162 -0
- package/dist/button/button.css.map +1 -0
- package/dist/button/button.d.ts +52 -0
- package/dist/button/button.d.ts.map +1 -0
- package/dist/button/button.jsx +88 -0
- package/dist/button/button.jsx.map +1 -0
- package/dist/button/header-action-button.d.ts +34 -0
- package/dist/button/header-action-button.d.ts.map +1 -0
- package/dist/button/header-action-button.jsx +51 -0
- package/dist/button/header-action-button.jsx.map +1 -0
- package/dist/button/icon-button.d.ts +46 -0
- package/dist/button/icon-button.d.ts.map +1 -0
- package/dist/button/icon-button.jsx +69 -0
- package/dist/button/icon-button.jsx.map +1 -0
- package/dist/button/index.d.ts +9 -0
- package/dist/button/index.d.ts.map +1 -0
- package/dist/button/index.jsx +8 -0
- package/dist/button/nav-card.d.ts +58 -0
- package/dist/button/nav-card.d.ts.map +1 -0
- package/dist/button/nav-card.jsx +96 -0
- package/dist/button/nav-card.jsx.map +1 -0
- package/dist/button/safe-tap.d.ts +27 -0
- package/dist/button/safe-tap.d.ts.map +1 -0
- package/dist/button/safe-tap.jsx +46 -0
- package/dist/button/safe-tap.jsx.map +1 -0
- package/dist/button/safe.d.ts +84 -0
- package/dist/button/safe.d.ts.map +1 -0
- package/dist/button/safe.jsx +116 -0
- package/dist/button/safe.jsx.map +1 -0
- package/dist/button/vertical-icon-text-button.d.ts +18 -0
- package/dist/button/vertical-icon-text-button.d.ts.map +1 -0
- package/dist/button/vertical-icon-text-button.jsx +21 -0
- package/dist/button/vertical-icon-text-button.jsx.map +1 -0
- package/dist/button/visuals.d.ts +53 -0
- package/dist/button/visuals.d.ts.map +1 -0
- package/dist/button/visuals.jsx +92 -0
- package/dist/button/visuals.jsx.map +1 -0
- package/dist/cascade/cascade-panel.d.ts +80 -0
- package/dist/cascade/cascade-panel.d.ts.map +1 -0
- package/dist/cascade/cascade-panel.jsx +179 -0
- package/dist/cascade/cascade-panel.jsx.map +1 -0
- package/dist/cascade/cascade.css +70 -0
- package/dist/cascade/cascade.css.map +1 -0
- package/dist/cascade/index.d.ts +3 -0
- package/dist/cascade/index.d.ts.map +1 -0
- package/dist/cascade/index.jsx +2 -0
- package/dist/cascade/model.d.ts +68 -0
- package/dist/cascade/model.d.ts.map +1 -0
- package/dist/cascade/model.jsx +161 -0
- package/dist/cascade/model.jsx.map +1 -0
- package/dist/deferred/deferred-content.d.ts +82 -0
- package/dist/deferred/deferred-content.d.ts.map +1 -0
- package/dist/deferred/deferred-content.jsx +263 -0
- package/dist/deferred/deferred-content.jsx.map +1 -0
- package/dist/deferred/deferred.css +62 -0
- package/dist/deferred/deferred.css.map +1 -0
- package/dist/deferred/index.d.ts +3 -0
- package/dist/deferred/index.d.ts.map +1 -0
- package/dist/deferred/index.jsx +2 -0
- package/dist/deferred/readiness-signal.d.ts +16 -0
- package/dist/deferred/readiness-signal.d.ts.map +1 -0
- package/dist/deferred/readiness-signal.jsx +29 -0
- package/dist/deferred/readiness-signal.jsx.map +1 -0
- package/dist/display/activity-indicator.d.ts +21 -0
- package/dist/display/activity-indicator.d.ts.map +1 -0
- package/dist/display/activity-indicator.jsx +22 -0
- package/dist/display/activity-indicator.jsx.map +1 -0
- package/dist/display/culture-date-time-label.d.ts +64 -0
- package/dist/display/culture-date-time-label.d.ts.map +1 -0
- package/dist/display/culture-date-time-label.jsx +73 -0
- package/dist/display/culture-date-time-label.jsx.map +1 -0
- package/dist/display/display.css +217 -0
- package/dist/display/display.css.map +1 -0
- package/dist/display/index.d.ts +7 -0
- package/dist/display/index.d.ts.map +1 -0
- package/dist/display/index.jsx +6 -0
- package/dist/display/progress-bar.d.ts +38 -0
- package/dist/display/progress-bar.d.ts.map +1 -0
- package/dist/display/progress-bar.jsx +57 -0
- package/dist/display/progress-bar.jsx.map +1 -0
- package/dist/display/separator.d.ts +30 -0
- package/dist/display/separator.d.ts.map +1 -0
- package/dist/display/separator.jsx +55 -0
- package/dist/display/separator.jsx.map +1 -0
- package/dist/display/shimmer.d.ts +41 -0
- package/dist/display/shimmer.d.ts.map +1 -0
- package/dist/display/shimmer.jsx +41 -0
- package/dist/display/shimmer.jsx.map +1 -0
- package/dist/display/title-with-line.d.ts +13 -0
- package/dist/display/title-with-line.d.ts.map +1 -0
- package/dist/display/title-with-line.jsx +21 -0
- package/dist/display/title-with-line.jsx.map +1 -0
- package/dist/edge-panel/edge-panel.css +132 -0
- package/dist/edge-panel/edge-panel.css.map +1 -0
- package/dist/edge-panel/edge-panel.d.ts +87 -0
- package/dist/edge-panel/edge-panel.d.ts.map +1 -0
- package/dist/edge-panel/edge-panel.jsx +326 -0
- package/dist/edge-panel/edge-panel.jsx.map +1 -0
- package/dist/edge-panel/helper.d.ts +27 -0
- package/dist/edge-panel/helper.d.ts.map +1 -0
- package/dist/edge-panel/helper.jsx +118 -0
- package/dist/edge-panel/helper.jsx.map +1 -0
- package/dist/edge-panel/index.d.ts +4 -0
- package/dist/edge-panel/index.d.ts.map +1 -0
- package/dist/edge-panel/index.jsx +3 -0
- package/dist/edge-panel/types.d.ts +155 -0
- package/dist/edge-panel/types.d.ts.map +1 -0
- package/dist/edge-panel/types.jsx +139 -0
- package/dist/edge-panel/types.jsx.map +1 -0
- package/dist/expander/expander.css +54 -0
- package/dist/expander/expander.css.map +1 -0
- package/dist/expander/expander.d.ts +46 -0
- package/dist/expander/expander.d.ts.map +1 -0
- package/dist/expander/expander.jsx +112 -0
- package/dist/expander/expander.jsx.map +1 -0
- package/dist/expander/index.d.ts +2 -0
- package/dist/expander/index.d.ts.map +1 -0
- package/dist/expander/index.jsx +1 -0
- package/dist/fields/dictation.d.ts +43 -0
- package/dist/fields/dictation.d.ts.map +1 -0
- package/dist/fields/dictation.jsx +124 -0
- package/dist/fields/dictation.jsx.map +1 -0
- package/dist/fields/editor.d.ts +26 -0
- package/dist/fields/editor.d.ts.map +1 -0
- package/dist/fields/editor.jsx +46 -0
- package/dist/fields/editor.jsx.map +1 -0
- package/dist/fields/fields.css +164 -0
- package/dist/fields/fields.css.map +1 -0
- package/dist/fields/index.d.ts +13 -0
- package/dist/fields/index.d.ts.map +1 -0
- package/dist/fields/index.jsx +12 -0
- package/dist/fields/input-policy.d.ts +48 -0
- package/dist/fields/input-policy.d.ts.map +1 -0
- package/dist/fields/input-policy.jsx +215 -0
- package/dist/fields/input-policy.jsx.map +1 -0
- package/dist/fields/notch.d.ts +10 -0
- package/dist/fields/notch.d.ts.map +1 -0
- package/dist/fields/notch.jsx +9 -0
- package/dist/fields/notch.jsx.map +1 -0
- package/dist/fields/outlined-field.d.ts +152 -0
- package/dist/fields/outlined-field.d.ts.map +1 -0
- package/dist/fields/outlined-field.jsx +199 -0
- package/dist/fields/outlined-field.jsx.map +1 -0
- package/dist/fields/pin-entry.d.ts +65 -0
- package/dist/fields/pin-entry.d.ts.map +1 -0
- package/dist/fields/pin-entry.jsx +294 -0
- package/dist/fields/pin-entry.jsx.map +1 -0
- package/dist/fields/search-entry.d.ts +35 -0
- package/dist/fields/search-entry.d.ts.map +1 -0
- package/dist/fields/search-entry.jsx +118 -0
- package/dist/fields/search-entry.jsx.map +1 -0
- package/dist/fields/slot-layout.d.ts +33 -0
- package/dist/fields/slot-layout.d.ts.map +1 -0
- package/dist/fields/slot-layout.jsx +33 -0
- package/dist/fields/slot-layout.jsx.map +1 -0
- package/dist/fields/text-entry.d.ts +62 -0
- package/dist/fields/text-entry.d.ts.map +1 -0
- package/dist/fields/text-entry.jsx +82 -0
- package/dist/fields/text-entry.jsx.map +1 -0
- package/dist/fields/use-dictation.d.ts +34 -0
- package/dist/fields/use-dictation.d.ts.map +1 -0
- package/dist/fields/use-dictation.jsx +80 -0
- package/dist/fields/use-dictation.jsx.map +1 -0
- package/dist/fields/use-text-input.d.ts +150 -0
- package/dist/fields/use-text-input.d.ts.map +1 -0
- package/dist/fields/use-text-input.jsx +247 -0
- package/dist/fields/use-text-input.jsx.map +1 -0
- package/dist/fields/validator.d.ts +14 -0
- package/dist/fields/validator.d.ts.map +1 -0
- package/dist/fields/validator.jsx +20 -0
- package/dist/fields/validator.jsx.map +1 -0
- package/dist/host/back.d.ts +42 -0
- package/dist/host/back.d.ts.map +1 -0
- package/dist/host/back.jsx +47 -0
- package/dist/host/back.jsx.map +1 -0
- package/dist/host/hooks.d.ts +90 -0
- package/dist/host/hooks.d.ts.map +1 -0
- package/dist/host/hooks.jsx +166 -0
- package/dist/host/hooks.jsx.map +1 -0
- package/dist/host/host.css +81 -0
- package/dist/host/host.css.map +1 -0
- package/dist/host/host.d.ts +70 -0
- package/dist/host/host.d.ts.map +1 -0
- package/dist/host/host.jsx +229 -0
- package/dist/host/host.jsx.map +1 -0
- package/dist/host/index.d.ts +9 -0
- package/dist/host/index.d.ts.map +1 -0
- package/dist/host/index.jsx +8 -0
- package/dist/host/keyboard.d.ts +24 -0
- package/dist/host/keyboard.d.ts.map +1 -0
- package/dist/host/keyboard.jsx +28 -0
- package/dist/host/keyboard.jsx.map +1 -0
- package/dist/host/layers.d.ts +69 -0
- package/dist/host/layers.d.ts.map +1 -0
- package/dist/host/layers.jsx +111 -0
- package/dist/host/layers.jsx.map +1 -0
- package/dist/host/page-loading-overlay.d.ts +17 -0
- package/dist/host/page-loading-overlay.d.ts.map +1 -0
- package/dist/host/page-loading-overlay.jsx +16 -0
- package/dist/host/page-loading-overlay.jsx.map +1 -0
- package/dist/host/readiness.d.ts +57 -0
- package/dist/host/readiness.d.ts.map +1 -0
- package/dist/host/readiness.jsx +138 -0
- package/dist/host/readiness.jsx.map +1 -0
- package/dist/host/registry.d.ts +106 -0
- package/dist/host/registry.d.ts.map +1 -0
- package/dist/host/registry.jsx +93 -0
- package/dist/host/registry.jsx.map +1 -0
- package/dist/icon/icon.css +39 -0
- package/dist/icon/icon.css.map +1 -0
- package/dist/icon/icon.d.ts +57 -0
- package/dist/icon/icon.d.ts.map +1 -0
- package/dist/icon/icon.jsx +115 -0
- package/dist/icon/icon.jsx.map +1 -0
- package/dist/icon/index.d.ts +4 -0
- package/dist/icon/index.d.ts.map +1 -0
- package/dist/icon/index.jsx +3 -0
- package/dist/icon/slot.d.ts +45 -0
- package/dist/icon/slot.d.ts.map +1 -0
- package/dist/icon/slot.jsx +61 -0
- package/dist/icon/slot.jsx.map +1 -0
- package/dist/icon/swatch.d.ts +29 -0
- package/dist/icon/swatch.d.ts.map +1 -0
- package/dist/icon/swatch.jsx +25 -0
- package/dist/icon/swatch.jsx.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.jsx +1 -0
- package/dist/pickers/combo-box.d.ts +42 -0
- package/dist/pickers/combo-box.d.ts.map +1 -0
- package/dist/pickers/combo-box.jsx +129 -0
- package/dist/pickers/combo-box.jsx.map +1 -0
- package/dist/pickers/date-time-picker.d.ts +63 -0
- package/dist/pickers/date-time-picker.d.ts.map +1 -0
- package/dist/pickers/date-time-picker.jsx +141 -0
- package/dist/pickers/date-time-picker.jsx.map +1 -0
- package/dist/pickers/date-time.d.ts +82 -0
- package/dist/pickers/date-time.d.ts.map +1 -0
- package/dist/pickers/date-time.jsx +130 -0
- package/dist/pickers/date-time.jsx.map +1 -0
- package/dist/pickers/index.d.ts +10 -0
- package/dist/pickers/index.d.ts.map +1 -0
- package/dist/pickers/index.jsx +9 -0
- package/dist/pickers/picker-sheet.d.ts +21 -0
- package/dist/pickers/picker-sheet.d.ts.map +1 -0
- package/dist/pickers/picker-sheet.jsx +61 -0
- package/dist/pickers/picker-sheet.jsx.map +1 -0
- package/dist/pickers/picker.d.ts +32 -0
- package/dist/pickers/picker.d.ts.map +1 -0
- package/dist/pickers/picker.jsx +72 -0
- package/dist/pickers/picker.jsx.map +1 -0
- package/dist/pickers/pickers.css +219 -0
- package/dist/pickers/pickers.css.map +1 -0
- package/dist/pickers/timespan-picker.d.ts +36 -0
- package/dist/pickers/timespan-picker.d.ts.map +1 -0
- package/dist/pickers/timespan-picker.jsx +99 -0
- package/dist/pickers/timespan-picker.jsx.map +1 -0
- package/dist/pickers/timespan.d.ts +38 -0
- package/dist/pickers/timespan.d.ts.map +1 -0
- package/dist/pickers/timespan.jsx +49 -0
- package/dist/pickers/timespan.jsx.map +1 -0
- package/dist/pickers/trigger.d.ts +34 -0
- package/dist/pickers/trigger.d.ts.map +1 -0
- package/dist/pickers/trigger.jsx +77 -0
- package/dist/pickers/trigger.jsx.map +1 -0
- package/dist/pickers/wheel-column.d.ts +32 -0
- package/dist/pickers/wheel-column.d.ts.map +1 -0
- package/dist/pickers/wheel-column.jsx +99 -0
- package/dist/pickers/wheel-column.jsx.map +1 -0
- package/dist/plus-button/index.d.ts +3 -0
- package/dist/plus-button/index.d.ts.map +1 -0
- package/dist/plus-button/index.jsx +2 -0
- package/dist/plus-button/model.d.ts +65 -0
- package/dist/plus-button/model.d.ts.map +1 -0
- package/dist/plus-button/model.jsx +86 -0
- package/dist/plus-button/model.jsx.map +1 -0
- package/dist/plus-button/plus-button.css +67 -0
- package/dist/plus-button/plus-button.css.map +1 -0
- package/dist/plus-button/plus-button.d.ts +38 -0
- package/dist/plus-button/plus-button.d.ts.map +1 -0
- package/dist/plus-button/plus-button.jsx +155 -0
- package/dist/plus-button/plus-button.jsx.map +1 -0
- package/dist/popup/frame.d.ts +101 -0
- package/dist/popup/frame.d.ts.map +1 -0
- package/dist/popup/frame.jsx +252 -0
- package/dist/popup/frame.jsx.map +1 -0
- package/dist/popup/index.d.ts +8 -0
- package/dist/popup/index.d.ts.map +1 -0
- package/dist/popup/index.jsx +7 -0
- package/dist/popup/input-form.d.ts +35 -0
- package/dist/popup/input-form.d.ts.map +1 -0
- package/dist/popup/input-form.jsx +160 -0
- package/dist/popup/input-form.jsx.map +1 -0
- package/dist/popup/input.d.ts +175 -0
- package/dist/popup/input.d.ts.map +1 -0
- package/dist/popup/input.jsx +176 -0
- package/dist/popup/input.jsx.map +1 -0
- package/dist/popup/popup-view.d.ts +25 -0
- package/dist/popup/popup-view.d.ts.map +1 -0
- package/dist/popup/popup-view.jsx +67 -0
- package/dist/popup/popup-view.jsx.map +1 -0
- package/dist/popup/popup.css +203 -0
- package/dist/popup/popup.css.map +1 -0
- package/dist/popup/queue.d.ts +90 -0
- package/dist/popup/queue.d.ts.map +1 -0
- package/dist/popup/queue.jsx +309 -0
- package/dist/popup/queue.jsx.map +1 -0
- package/dist/popup/service.d.ts +60 -0
- package/dist/popup/service.d.ts.map +1 -0
- package/dist/popup/service.jsx +350 -0
- package/dist/popup/service.jsx.map +1 -0
- package/dist/popup/types.d.ts +222 -0
- package/dist/popup/types.d.ts.map +1 -0
- package/dist/popup/types.jsx +218 -0
- package/dist/popup/types.jsx.map +1 -0
- package/dist/provider/contexts.d.ts +41 -0
- package/dist/provider/contexts.d.ts.map +1 -0
- package/dist/provider/contexts.jsx +11 -0
- package/dist/provider/contexts.jsx.map +1 -0
- package/dist/provider/global-events.d.ts +8 -0
- package/dist/provider/global-events.d.ts.map +1 -0
- package/dist/provider/global-events.jsx +17 -0
- package/dist/provider/global-events.jsx.map +1 -0
- package/dist/provider/hooks.d.ts +49 -0
- package/dist/provider/hooks.d.ts.map +1 -0
- package/dist/provider/hooks.jsx +72 -0
- package/dist/provider/hooks.jsx.map +1 -0
- package/dist/provider/index.d.ts +5 -0
- package/dist/provider/index.d.ts.map +1 -0
- package/dist/provider/index.jsx +3 -0
- package/dist/provider/provider.css +18 -0
- package/dist/provider/provider.css.map +1 -0
- package/dist/provider/provider.d.ts +51 -0
- package/dist/provider/provider.d.ts.map +1 -0
- package/dist/provider/provider.jsx +290 -0
- package/dist/provider/provider.jsx.map +1 -0
- package/dist/provider/settings.d.ts +99 -0
- package/dist/provider/settings.d.ts.map +1 -0
- package/dist/provider/settings.jsx +45 -0
- package/dist/provider/settings.jsx.map +1 -0
- package/dist/provider/theme-css.d.ts +12 -0
- package/dist/provider/theme-css.d.ts.map +1 -0
- package/dist/provider/theme-css.jsx +19 -0
- package/dist/provider/theme-css.jsx.map +1 -0
- package/dist/provider/theme-root.d.ts +10 -0
- package/dist/provider/theme-root.d.ts.map +1 -0
- package/dist/provider/theme-root.jsx +24 -0
- package/dist/provider/theme-root.jsx.map +1 -0
- package/dist/provider/theme.css +473 -0
- package/dist/provider/theme.css.map +1 -0
- package/dist/range-slider/index.d.ts +3 -0
- package/dist/range-slider/index.d.ts.map +1 -0
- package/dist/range-slider/index.jsx +2 -0
- package/dist/range-slider/math.d.ts +23 -0
- package/dist/range-slider/math.d.ts.map +1 -0
- package/dist/range-slider/math.jsx +71 -0
- package/dist/range-slider/math.jsx.map +1 -0
- package/dist/range-slider/range-slider.css +90 -0
- package/dist/range-slider/range-slider.css.map +1 -0
- package/dist/range-slider/range-slider.d.ts +52 -0
- package/dist/range-slider/range-slider.d.ts.map +1 -0
- package/dist/range-slider/range-slider.jsx +159 -0
- package/dist/range-slider/range-slider.jsx.map +1 -0
- package/dist/selection/index.d.ts +5 -0
- package/dist/selection/index.d.ts.map +1 -0
- package/dist/selection/index.jsx +3 -0
- package/dist/selection/model.d.ts +53 -0
- package/dist/selection/model.d.ts.map +1 -0
- package/dist/selection/model.jsx +69 -0
- package/dist/selection/model.jsx.map +1 -0
- package/dist/selection/selection-sheet.d.ts +80 -0
- package/dist/selection/selection-sheet.d.ts.map +1 -0
- package/dist/selection/selection-sheet.jsx +366 -0
- package/dist/selection/selection-sheet.jsx.map +1 -0
- package/dist/selection/selection.css +76 -0
- package/dist/selection/selection.css.map +1 -0
- package/dist/selection/use-selection-model.d.ts +9 -0
- package/dist/selection/use-selection-model.d.ts.map +1 -0
- package/dist/selection/use-selection-model.jsx +22 -0
- package/dist/selection/use-selection-model.jsx.map +1 -0
- package/dist/sheet/frame.d.ts +47 -0
- package/dist/sheet/frame.d.ts.map +1 -0
- package/dist/sheet/frame.jsx +270 -0
- package/dist/sheet/frame.jsx.map +1 -0
- package/dist/sheet/gesture.d.ts +51 -0
- package/dist/sheet/gesture.d.ts.map +1 -0
- package/dist/sheet/gesture.jsx +107 -0
- package/dist/sheet/gesture.jsx.map +1 -0
- package/dist/sheet/handoff.d.ts +32 -0
- package/dist/sheet/handoff.d.ts.map +1 -0
- package/dist/sheet/handoff.jsx +33 -0
- package/dist/sheet/handoff.jsx.map +1 -0
- package/dist/sheet/header.d.ts +46 -0
- package/dist/sheet/header.d.ts.map +1 -0
- package/dist/sheet/header.jsx +158 -0
- package/dist/sheet/header.jsx.map +1 -0
- package/dist/sheet/height-memo.d.ts +47 -0
- package/dist/sheet/height-memo.d.ts.map +1 -0
- package/dist/sheet/height-memo.jsx +100 -0
- package/dist/sheet/height-memo.jsx.map +1 -0
- package/dist/sheet/index.d.ts +12 -0
- package/dist/sheet/index.d.ts.map +1 -0
- package/dist/sheet/index.jsx +11 -0
- package/dist/sheet/loadable.d.ts +35 -0
- package/dist/sheet/loadable.d.ts.map +1 -0
- package/dist/sheet/loadable.jsx +65 -0
- package/dist/sheet/loadable.jsx.map +1 -0
- package/dist/sheet/motion.d.ts +59 -0
- package/dist/sheet/motion.d.ts.map +1 -0
- package/dist/sheet/motion.jsx +59 -0
- package/dist/sheet/motion.jsx.map +1 -0
- package/dist/sheet/options.d.ts +252 -0
- package/dist/sheet/options.d.ts.map +1 -0
- package/dist/sheet/options.jsx +92 -0
- package/dist/sheet/options.jsx.map +1 -0
- package/dist/sheet/processing.d.ts +22 -0
- package/dist/sheet/processing.d.ts.map +1 -0
- package/dist/sheet/processing.jsx +66 -0
- package/dist/sheet/processing.jsx.map +1 -0
- package/dist/sheet/service.d.ts +55 -0
- package/dist/sheet/service.d.ts.map +1 -0
- package/dist/sheet/service.jsx +143 -0
- package/dist/sheet/service.jsx.map +1 -0
- package/dist/sheet/sheet.css +246 -0
- package/dist/sheet/sheet.css.map +1 -0
- package/dist/sheet/sheet.d.ts +19 -0
- package/dist/sheet/sheet.d.ts.map +1 -0
- package/dist/sheet/sheet.jsx +40 -0
- package/dist/sheet/sheet.jsx.map +1 -0
- package/dist/sheet/sizing.d.ts +87 -0
- package/dist/sheet/sizing.d.ts.map +1 -0
- package/dist/sheet/sizing.jsx +159 -0
- package/dist/sheet/sizing.jsx.map +1 -0
- package/dist/sheet/stack.d.ts +161 -0
- package/dist/sheet/stack.d.ts.map +1 -0
- package/dist/sheet/stack.jsx +378 -0
- package/dist/sheet/stack.jsx.map +1 -0
- package/dist/swipe/index.d.ts +3 -0
- package/dist/swipe/index.d.ts.map +1 -0
- package/dist/swipe/index.jsx +2 -0
- package/dist/swipe/model.d.ts +72 -0
- package/dist/swipe/model.d.ts.map +1 -0
- package/dist/swipe/model.jsx +66 -0
- package/dist/swipe/model.jsx.map +1 -0
- package/dist/swipe/swipe-view.d.ts +40 -0
- package/dist/swipe/swipe-view.d.ts.map +1 -0
- package/dist/swipe/swipe-view.jsx +163 -0
- package/dist/swipe/swipe-view.jsx.map +1 -0
- package/dist/swipe/swipe.css +34 -0
- package/dist/swipe/swipe.css.map +1 -0
- package/dist/tab-bar/index.d.ts +4 -0
- package/dist/tab-bar/index.d.ts.map +1 -0
- package/dist/tab-bar/index.jsx +3 -0
- package/dist/tab-bar/metrics.d.ts +230 -0
- package/dist/tab-bar/metrics.d.ts.map +1 -0
- package/dist/tab-bar/metrics.jsx +221 -0
- package/dist/tab-bar/metrics.jsx.map +1 -0
- package/dist/tab-bar/model.d.ts +170 -0
- package/dist/tab-bar/model.d.ts.map +1 -0
- package/dist/tab-bar/model.jsx +349 -0
- package/dist/tab-bar/model.jsx.map +1 -0
- package/dist/tab-bar/tab-bar.css +173 -0
- package/dist/tab-bar/tab-bar.css.map +1 -0
- package/dist/tab-bar/tab-bar.d.ts +61 -0
- package/dist/tab-bar/tab-bar.d.ts.map +1 -0
- package/dist/tab-bar/tab-bar.jsx +346 -0
- package/dist/tab-bar/tab-bar.jsx.map +1 -0
- package/dist/tabs/index.d.ts +3 -0
- package/dist/tabs/index.d.ts.map +1 -0
- package/dist/tabs/index.jsx +2 -0
- package/dist/tabs/model.d.ts +83 -0
- package/dist/tabs/model.d.ts.map +1 -0
- package/dist/tabs/model.jsx +113 -0
- package/dist/tabs/model.jsx.map +1 -0
- package/dist/tabs/tab-view.d.ts +47 -0
- package/dist/tabs/tab-view.d.ts.map +1 -0
- package/dist/tabs/tab-view.jsx +227 -0
- package/dist/tabs/tab-view.jsx.map +1 -0
- package/dist/tabs/tabs.css +182 -0
- package/dist/tabs/tabs.css.map +1 -0
- package/dist/toast/index.d.ts +3 -0
- package/dist/toast/index.d.ts.map +1 -0
- package/dist/toast/index.jsx +2 -0
- package/dist/toast/service.d.ts +48 -0
- package/dist/toast/service.d.ts.map +1 -0
- package/dist/toast/service.jsx +238 -0
- package/dist/toast/service.jsx.map +1 -0
- package/dist/toast/store.d.ts +176 -0
- package/dist/toast/store.d.ts.map +1 -0
- package/dist/toast/store.jsx +355 -0
- package/dist/toast/store.jsx.map +1 -0
- package/dist/toast/toast.css +159 -0
- package/dist/toast/toast.css.map +1 -0
- package/dist/toggle/checkbox-math.d.ts +52 -0
- package/dist/toggle/checkbox-math.d.ts.map +1 -0
- package/dist/toggle/checkbox-math.jsx +111 -0
- package/dist/toggle/checkbox-math.jsx.map +1 -0
- package/dist/toggle/checkbox.d.ts +56 -0
- package/dist/toggle/checkbox.d.ts.map +1 -0
- package/dist/toggle/checkbox.jsx +152 -0
- package/dist/toggle/checkbox.jsx.map +1 -0
- package/dist/toggle/chip-group.d.ts +50 -0
- package/dist/toggle/chip-group.d.ts.map +1 -0
- package/dist/toggle/chip-group.jsx +107 -0
- package/dist/toggle/chip-group.jsx.map +1 -0
- package/dist/toggle/index.d.ts +5 -0
- package/dist/toggle/index.d.ts.map +1 -0
- package/dist/toggle/index.jsx +4 -0
- package/dist/toggle/switch.d.ts +52 -0
- package/dist/toggle/switch.d.ts.map +1 -0
- package/dist/toggle/switch.jsx +192 -0
- package/dist/toggle/switch.jsx.map +1 -0
- package/dist/toggle/toggle.css +188 -0
- package/dist/toggle/toggle.css.map +1 -0
- package/package.json +155 -4
- package/rspeedy/index.d.ts +21 -0
- package/rspeedy/index.mjs +75 -0
- package/rspeedy/index.test.mjs +52 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fields/search-entry.jsx","sources":["../../src/fields/search-entry.tsx"],"sourcesContent":["import {\n createAbortController,\n type G9AbortController,\n type G9AbortSignal,\n G9StringKey,\n isAbortError,\n} from '@g9tm/lynxcontrols-foundation';\nimport { forwardRef, type ReactNode, useEffect, useImperativeHandle, useRef } from '@lynx-js/react';\nimport { type G9TimerHandle, startTimer, stopTimer } from '../base/timers';\nimport { useControllableState } from '../base/use-controllable-state';\nimport { useG9Diagnostics, useG9Settings, useG9Strings } from '../provider/hooks';\nimport { type G9EntryVariant, type G9TextEntryHandle, type G9TextEntryProps, TextEntryBody } from './text-entry';\nimport type { G9ValueChangeDetails } from './use-text-input';\n\n/** Context of one search (`onSearch`). */\nexport interface G9SearchContext {\n /** Aborted when a newer query fires or the field unmounts: drop this query's results. */\n readonly signal: G9AbortSignal;\n /** Increases with every fired query; compare to discard a stale result. */\n readonly version: number;\n}\n\n/** Props of {@link G9SearchEntry} (MAUI `G9SearchEntry`). */\nexport interface G9SearchEntryProps extends G9TextEntryProps {\n /** Quiet time after the last change before the query fires; `0` fires on every change. Default 250. */\n readonly debounceMs?: number;\n /** The debounced text (MAUI `DebouncedTextChanged`). */\n readonly onDebouncedValueChange?: (value: string) => void;\n /**\n * Runs the search (MAUI `SearchCommand`): after the debounce, on the keyboard's search key and on `submit()`.\n * A newer query aborts the previous one's signal (query versioning). A thrown error or rejected promise (other\n * than an abort) goes to the provider's diagnostics.\n */\n readonly onSearch?: (query: string, context: G9SearchContext) => unknown;\n}\n\n/** Imperative handle of {@link G9SearchEntry}. */\nexport interface G9SearchEntryHandle extends G9TextEntryHandle {\n /** Fires the current text now, skipping the debounce (MAUI `Submit`). */\n submit(): void;\n}\n\n/**\n * Search field (MAUI `G9SearchEntry`): a `G9TextEntry` with a leading search glyph, the clear button, dictation on,\n * the localized `search` placeholder, the floating-label clearance reserved, the keyboard's search key, and a\n * debounced query. Every change of the text (typing, dictation, clear, a new `value` from the parent) restarts the\n * debounce; the search key and `submit()` fire at once. Pending queries never fire after unmount.\n */\nexport const G9SearchEntry = forwardRef<G9SearchEntryHandle, G9SearchEntryProps>(\n function G9SearchEntry(props, ref): ReactNode {\n const glyphs = useG9Settings().glyphs;\n const strings = useG9Strings();\n const diagnostics = useG9Diagnostics();\n const [text, setText] = useControllableState<string, [G9ValueChangeDetails]>({\n value: props.value,\n defaultValue: props.defaultValue ?? '',\n onChange: props.onValueChange,\n name: 'G9SearchEntry.value',\n });\n const latest = useRef({ text, props });\n latest.current = { text, props };\n const timer = useRef<G9TimerHandle | null>(null);\n const current = useRef<G9AbortController | null>(null);\n const version = useRef(0);\n const inner = useRef<G9TextEntryHandle | null>(null);\n\n const stopDebounce = () => {\n if (timer.current !== null) {\n stopTimer(timer.current);\n timer.current = null;\n }\n };\n const report = (error: unknown) => {\n if (isAbortError(error)) return;\n diagnostics.log({ level: 'error', message: 'G9SearchEntry.onSearch failed.', source: 'G9SearchEntry', error });\n };\n const fire = (value: string) => {\n const p = latest.current.props;\n current.current?.abort();\n const controller = createAbortController();\n current.current = controller;\n version.current += 1;\n try {\n p.onDebouncedValueChange?.(value);\n const result = p.onSearch?.(value, { signal: controller.signal, version: version.current });\n if (result && typeof (result as PromiseLike<unknown>).then === 'function') {\n (result as PromiseLike<unknown>).then(undefined, report);\n }\n } catch (error) {\n report(error);\n }\n };\n const submit = () => {\n stopDebounce();\n fire(latest.current.text);\n };\n\n const first = useRef(true);\n useEffect(() => {\n if (first.current) {\n first.current = false;\n return;\n }\n const ms = latest.current.props.debounceMs ?? 250;\n stopDebounce();\n if (ms <= 0) {\n fire(text);\n return;\n }\n timer.current = startTimer(() => {\n timer.current = null;\n fire(latest.current.text);\n }, ms);\n }, [text]);\n\n useEffect(\n () => () => {\n stopDebounce();\n current.current?.abort();\n },\n [],\n );\n\n useImperativeHandle(ref, () => {\n const base = inner.current as G9TextEntryHandle;\n return {\n focus: () => base.focus(),\n blur: () => base.blur(),\n validate: () => base.validate(),\n get isListening() {\n return base.isListening;\n },\n toggleVoice: () => base.toggleVoice(),\n startVoice: () => base.startVoice(),\n stopVoice: () => base.stopVoice(),\n get element() {\n return base.element;\n },\n submit,\n };\n });\n\n const variant: G9EntryVariant = {\n name: 'G9SearchEntry.value',\n restingTone: 'placeholder',\n confirmType: 'search',\n onConfirm: submit,\n };\n return (\n <TextEntryBody\n {...props}\n leadingIcon={props.leadingIcon === undefined ? glyphs.search : props.leadingIcon}\n clearButton={props.clearButton ?? true}\n voiceEnabled={props.voiceEnabled ?? true}\n placeholder={props.placeholder === undefined ? strings.get(G9StringKey.Search) : props.placeholder}\n reserveFloatingLabelClearance={props.reserveFloatingLabelClearance ?? true}\n value={text}\n onValueChange={(value, details) => setText(value, details)}\n variant={variant}\n ref={inner}\n />\n );\n },\n);\n"],"names":["G9SearchEntry","forwardRef","props","ref","_props_defaultValue","_props_clearButton","_props_voiceEnabled","_props_reserveFloatingLabelClearance","glyphs","useG9Settings","strings","useG9Strings","diagnostics","useG9Diagnostics","text","setText","useControllableState","latest","useRef","timer","current","version","inner","stopDebounce","stopTimer","report","error","isAbortError","fire","value","_current_current","p","controller","createAbortController","result","undefined","submit","first","useEffect","_latest_current_props_debounceMs","ms","startTimer","useImperativeHandle","base","variant","TextEntryBody","G9StringKey","details"],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** Inputs of the slot layout. */
|
|
2
|
+
export interface G9FieldSlotLayoutInput {
|
|
3
|
+
readonly hasLeadingIcon: boolean;
|
|
4
|
+
readonly hasTrailingIcon: boolean;
|
|
5
|
+
readonly isRtl: boolean;
|
|
6
|
+
/** Pin the trailing icon to the physical right in both directions. */
|
|
7
|
+
readonly forceTrailingIconRight: boolean;
|
|
8
|
+
/** Pin the leading icon to the physical left in both directions. */
|
|
9
|
+
readonly forceLeadingIconLeft: boolean;
|
|
10
|
+
}
|
|
11
|
+
/** Physical padding (logical pixels). */
|
|
12
|
+
export interface G9PhysicalPadding {
|
|
13
|
+
readonly left: number;
|
|
14
|
+
readonly top: number;
|
|
15
|
+
readonly right: number;
|
|
16
|
+
readonly bottom: number;
|
|
17
|
+
}
|
|
18
|
+
/** Everything the field derives from {@link G9FieldSlotLayoutInput}. */
|
|
19
|
+
export interface G9FieldSlotLayout {
|
|
20
|
+
/** Physical column of the leading icon: 0 (left) or 2 (right). */
|
|
21
|
+
readonly leadingColumn: 0 | 2;
|
|
22
|
+
/** Physical column of the trailing icon: 0 (left) or 2 (right). */
|
|
23
|
+
readonly trailingColumn: 0 | 2;
|
|
24
|
+
/** Inner content padding: 0 on a side with an icon, `InputHorizontalPadding` otherwise, plus the control's own. */
|
|
25
|
+
readonly innerPadding: G9PhysicalPadding;
|
|
26
|
+
/** Label X translation at rest (physical pixels; negative is left). */
|
|
27
|
+
readonly labelRestX: number;
|
|
28
|
+
/** Extra label X translation when floated. */
|
|
29
|
+
readonly labelFloatedX: number;
|
|
30
|
+
}
|
|
31
|
+
/** Resolves the slot layout (MAUI `ResolvePhysical*Column`, `ResolveInnerPadding`, `ResolveLabel*TranslationX`). */
|
|
32
|
+
export declare function resolveFieldSlotLayout(input: G9FieldSlotLayoutInput, perControlPadding?: G9PhysicalPadding): G9FieldSlotLayout;
|
|
33
|
+
//# sourceMappingURL=slot-layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slot-layout.d.ts","sourceRoot":"","sources":["../../src/fields/slot-layout.ts"],"names":[],"mappings":"AAKA,iCAAiC;AACjC,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,sEAAsE;IACtE,QAAQ,CAAC,sBAAsB,EAAE,OAAO,CAAC;IACzC,oEAAoE;IACpE,QAAQ,CAAC,oBAAoB,EAAE,OAAO,CAAC;CACxC;AAED,yCAAyC;AACzC,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,wEAAwE;AACxE,MAAM,WAAW,iBAAiB;IAChC,kEAAkE;IAClE,QAAQ,CAAC,aAAa,EAAE,CAAC,GAAG,CAAC,CAAC;IAC9B,mEAAmE;IACnE,QAAQ,CAAC,cAAc,EAAE,CAAC,GAAG,CAAC,CAAC;IAC/B,mHAAmH;IACnH,QAAQ,CAAC,YAAY,EAAE,iBAAiB,CAAC;IACzC,uEAAuE;IACvE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,8CAA8C;IAC9C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAID,oHAAoH;AACpH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,sBAAsB,EAC7B,iBAAiB,GAAE,iBAAwB,GAC1C,iBAAiB,CA0BnB"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { G9Metrics } from "@g9tm/lynxcontrols-foundation";
|
|
2
|
+
const zero = Object.freeze({
|
|
3
|
+
left: 0,
|
|
4
|
+
top: 0,
|
|
5
|
+
right: 0,
|
|
6
|
+
bottom: 0
|
|
7
|
+
});
|
|
8
|
+
function resolveFieldSlotLayout(input, perControlPadding = zero) {
|
|
9
|
+
const leadingColumn = input.forceLeadingIconLeft ? 0 : input.isRtl ? 2 : 0;
|
|
10
|
+
const trailingColumn = input.forceTrailingIconRight ? 2 : input.isRtl ? 0 : 2;
|
|
11
|
+
const iconLeft = input.hasLeadingIcon && 0 === leadingColumn || input.hasTrailingIcon && 0 === trailingColumn;
|
|
12
|
+
const iconRight = input.hasLeadingIcon && 2 === leadingColumn || input.hasTrailingIcon && 2 === trailingColumn;
|
|
13
|
+
const pad = G9Metrics.InputHorizontalPadding;
|
|
14
|
+
let labelRestX = 0;
|
|
15
|
+
if (input.hasLeadingIcon) {
|
|
16
|
+
if (!(input.isRtl && input.forceLeadingIconLeft)) labelRestX = input.isRtl ? -G9Metrics.InputLabelLeadingIconOffset : G9Metrics.InputLabelLeadingIconOffset;
|
|
17
|
+
} else if (input.isRtl && input.forceTrailingIconRight && input.hasTrailingIcon) labelRestX = -(G9Metrics.TrailingIconSlotWidth - pad);
|
|
18
|
+
return {
|
|
19
|
+
leadingColumn,
|
|
20
|
+
trailingColumn,
|
|
21
|
+
innerPadding: {
|
|
22
|
+
left: (iconLeft ? 0 : pad) + perControlPadding.left,
|
|
23
|
+
top: perControlPadding.top,
|
|
24
|
+
right: (iconRight ? 0 : pad) + perControlPadding.right,
|
|
25
|
+
bottom: perControlPadding.bottom
|
|
26
|
+
},
|
|
27
|
+
labelRestX,
|
|
28
|
+
labelFloatedX: input.isRtl ? -G9Metrics.FloatingLabelFloatedExtraX : G9Metrics.FloatingLabelFloatedExtraX
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export { resolveFieldSlotLayout };
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=slot-layout.jsx.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fields/slot-layout.jsx","sources":["../../src/fields/slot-layout.ts"],"sourcesContent":["import { G9Metrics } from '@g9tm/lynxcontrols-foundation';\n\n// MAUI `G9FieldSlotLayout` (Controls/Shared/G9FieldSlotLayout.cs): where an outlined field's icons sit and how far\n// its inner content and floating label move. Columns are PHYSICAL (0 = left, 2 = right), as in MAUI.\n\n/** Inputs of the slot layout. */\nexport interface G9FieldSlotLayoutInput {\n readonly hasLeadingIcon: boolean;\n readonly hasTrailingIcon: boolean;\n readonly isRtl: boolean;\n /** Pin the trailing icon to the physical right in both directions. */\n readonly forceTrailingIconRight: boolean;\n /** Pin the leading icon to the physical left in both directions. */\n readonly forceLeadingIconLeft: boolean;\n}\n\n/** Physical padding (logical pixels). */\nexport interface G9PhysicalPadding {\n readonly left: number;\n readonly top: number;\n readonly right: number;\n readonly bottom: number;\n}\n\n/** Everything the field derives from {@link G9FieldSlotLayoutInput}. */\nexport interface G9FieldSlotLayout {\n /** Physical column of the leading icon: 0 (left) or 2 (right). */\n readonly leadingColumn: 0 | 2;\n /** Physical column of the trailing icon: 0 (left) or 2 (right). */\n readonly trailingColumn: 0 | 2;\n /** Inner content padding: 0 on a side with an icon, `InputHorizontalPadding` otherwise, plus the control's own. */\n readonly innerPadding: G9PhysicalPadding;\n /** Label X translation at rest (physical pixels; negative is left). */\n readonly labelRestX: number;\n /** Extra label X translation when floated. */\n readonly labelFloatedX: number;\n}\n\nconst zero: G9PhysicalPadding = Object.freeze({ left: 0, top: 0, right: 0, bottom: 0 });\n\n/** Resolves the slot layout (MAUI `ResolvePhysical*Column`, `ResolveInnerPadding`, `ResolveLabel*TranslationX`). */\nexport function resolveFieldSlotLayout(\n input: G9FieldSlotLayoutInput,\n perControlPadding: G9PhysicalPadding = zero,\n): G9FieldSlotLayout {\n const leadingColumn: 0 | 2 = input.forceLeadingIconLeft ? 0 : input.isRtl ? 2 : 0;\n const trailingColumn: 0 | 2 = input.forceTrailingIconRight ? 2 : input.isRtl ? 0 : 2;\n const iconLeft = (input.hasLeadingIcon && leadingColumn === 0) || (input.hasTrailingIcon && trailingColumn === 0);\n const iconRight = (input.hasLeadingIcon && leadingColumn === 2) || (input.hasTrailingIcon && trailingColumn === 2);\n const pad = G9Metrics.InputHorizontalPadding;\n let labelRestX = 0;\n if (input.hasLeadingIcon) {\n if (!(input.isRtl && input.forceLeadingIconLeft)) {\n labelRestX = input.isRtl ? -G9Metrics.InputLabelLeadingIconOffset : G9Metrics.InputLabelLeadingIconOffset;\n }\n } else if (input.isRtl && input.forceTrailingIconRight && input.hasTrailingIcon) {\n labelRestX = -(G9Metrics.TrailingIconSlotWidth - pad);\n }\n return {\n leadingColumn,\n trailingColumn,\n innerPadding: {\n left: (iconLeft ? 0 : pad) + perControlPadding.left,\n top: perControlPadding.top,\n right: (iconRight ? 0 : pad) + perControlPadding.right,\n bottom: perControlPadding.bottom,\n },\n labelRestX,\n labelFloatedX: input.isRtl ? -G9Metrics.FloatingLabelFloatedExtraX : G9Metrics.FloatingLabelFloatedExtraX,\n };\n}\n"],"names":["zero","Object","resolveFieldSlotLayout","input","perControlPadding","leadingColumn","trailingColumn","iconLeft","iconRight","pad","G9Metrics","labelRestX"],"mappings":";AAsCA,MAAMA,OAA0BC,OAAO,MAAM,CAAC;IAAE,MAAM;IAAG,KAAK;IAAG,OAAO;IAAG,QAAQ;AAAE;AAG9E,SAASC,uBACdC,KAA6B,EAC7BC,oBAAuCJ,IAAI;IAE3C,MAAMK,gBAAuBF,MAAM,oBAAoB,GAAG,IAAIA,MAAM,KAAK,GAAG,IAAI;IAChF,MAAMG,iBAAwBH,MAAM,sBAAsB,GAAG,IAAIA,MAAM,KAAK,GAAG,IAAI;IACnF,MAAMI,WAAYJ,MAAM,cAAc,IAAIE,AAAkB,MAAlBA,iBAAyBF,MAAM,eAAe,IAAIG,AAAmB,MAAnBA;IAC5F,MAAME,YAAaL,MAAM,cAAc,IAAIE,AAAkB,MAAlBA,iBAAyBF,MAAM,eAAe,IAAIG,AAAmB,MAAnBA;IAC7F,MAAMG,MAAMC,UAAU,sBAAsB;IAC5C,IAAIC,aAAa;IACjB,IAAIR,MAAM,cAAc,EACtB;QAAA,IAAI,CAAEA,CAAAA,MAAM,KAAK,IAAIA,MAAM,oBAAmB,GAC5CQ,aAAaR,MAAM,KAAK,GAAG,CAACO,UAAU,2BAA2B,GAAGA,UAAU,2BAA2B;IAC3G,OACK,IAAIP,MAAM,KAAK,IAAIA,MAAM,sBAAsB,IAAIA,MAAM,eAAe,EAC7EQ,aAAa,CAAED,CAAAA,UAAU,qBAAqB,GAAGD,GAAE;IAErD,OAAO;QACLJ;QACAC;QACA,cAAc;YACZ,MAAOC,AAAAA,CAAAA,WAAW,IAAIE,GAAE,IAAKL,kBAAkB,IAAI;YACnD,KAAKA,kBAAkB,GAAG;YAC1B,OAAQI,AAAAA,CAAAA,YAAY,IAAIC,GAAE,IAAKL,kBAAkB,KAAK;YACtD,QAAQA,kBAAkB,MAAM;QAClC;QACAO;QACA,eAAeR,MAAM,KAAK,GAAG,CAACO,UAAU,0BAA0B,GAAGA,UAAU,0BAA0B;IAC3G;AACF"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type G9TextInputHandle, type G9TextInputProps } from './use-text-input.js';
|
|
2
|
+
import type { G9TextValidator } from './validator.js';
|
|
3
|
+
/** Props of {@link G9TextEntry} (MAUI `G9TextEntry`). */
|
|
4
|
+
export interface G9TextEntryProps extends G9TextInputProps {
|
|
5
|
+
/** Eye toggle in the trailing slot while there is a value; pins the trailing icon right. Default false. */
|
|
6
|
+
readonly passwordToggle?: boolean;
|
|
7
|
+
/** Mask the value (until the eye reveals it); the text is pinned LTR. Default false. */
|
|
8
|
+
readonly isPassword?: boolean;
|
|
9
|
+
/** Clear (×) button in the trailing slot while there is a value. Default false. */
|
|
10
|
+
readonly clearButton?: boolean;
|
|
11
|
+
/** Extra validation, run before the input-type rule (on blur, `validateOnTextChanged`, `validate()`). */
|
|
12
|
+
readonly validator?: G9TextValidator | null;
|
|
13
|
+
/** Validate on every change, not only on blur. Default false. */
|
|
14
|
+
readonly validateOnTextChanged?: boolean;
|
|
15
|
+
/** Keyboard confirm key. Default `'done'`. */
|
|
16
|
+
readonly confirmType?: 'send' | 'search' | 'go' | 'done' | 'next';
|
|
17
|
+
/** iOS spell checking (`ios-spell-check`; Android has no attribute). Default true. */
|
|
18
|
+
readonly isSpellCheckEnabled?: boolean;
|
|
19
|
+
/** iOS auto-correct / prediction (`ios-auto-correct`). Default true. */
|
|
20
|
+
readonly isTextPredictionEnabled?: boolean;
|
|
21
|
+
}
|
|
22
|
+
/** Imperative handle of {@link G9TextEntry}. */
|
|
23
|
+
export type G9TextEntryHandle = G9TextInputHandle;
|
|
24
|
+
/**
|
|
25
|
+
* Whether the trailing slot shows the microphone (MAUI `ShouldShowVoiceMic`): dictation available, not while the
|
|
26
|
+
* password eye owns the slot, and only on an empty field or during a session (the clear button owns a filled field).
|
|
27
|
+
*/
|
|
28
|
+
export declare function shouldShowEntryMic(state: {
|
|
29
|
+
readonly available: boolean;
|
|
30
|
+
readonly listening: boolean;
|
|
31
|
+
readonly hasValue: boolean;
|
|
32
|
+
readonly passwordToggle: boolean;
|
|
33
|
+
}): boolean;
|
|
34
|
+
/** What `G9SearchEntry` changes in the entry (internal). */
|
|
35
|
+
export interface G9EntryVariant {
|
|
36
|
+
readonly name: string;
|
|
37
|
+
readonly restingTone?: 'outline' | 'placeholder';
|
|
38
|
+
readonly confirmType?: G9TextEntryProps['confirmType'];
|
|
39
|
+
readonly onConfirm?: (value: string) => void;
|
|
40
|
+
}
|
|
41
|
+
interface BodyProps extends G9TextEntryProps {
|
|
42
|
+
readonly variant: G9EntryVariant;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The entry body shared by `G9TextEntry` and `G9SearchEntry` (internal). The inner name must differ from the binding
|
|
46
|
+
* (E20, scripts/check-dist-jsx.mjs): `G9TextEntry` renders it in this module.
|
|
47
|
+
*/
|
|
48
|
+
export declare const TextEntryBody: import("react").ForwardRefExoticComponent<BodyProps & import("react").RefAttributes<G9TextInputHandle>>;
|
|
49
|
+
/**
|
|
50
|
+
* Single-line outlined text field (MAUI `G9TextEntry`): floating label, input-type keyboard/filter/validation,
|
|
51
|
+
* password eye, clear button, optional dictation (`voiceEnabled` + `services.speech`).
|
|
52
|
+
*
|
|
53
|
+
* - Value: `value`/`defaultValue`/`onValueChange(value, { source })`; one call per change.
|
|
54
|
+
* - Validation: on blur when there is a rule (`validator`, email/url, custom pattern), on every change with
|
|
55
|
+
* `validateOnTextChanged`, or through the handle's `validate()`. An error set through `hasError`/`errorText`
|
|
56
|
+
* survives blur on a field without a rule.
|
|
57
|
+
* - Requires the host's `xelement-input` registration (plan/specs/02 §2). Keyboard avoidance: put the form inside
|
|
58
|
+
* lynx-ui `KeyboardAwareRoot`/`KeyboardAwareResponder`; the field reports focus to it.
|
|
59
|
+
*/
|
|
60
|
+
export declare const G9TextEntry: import("react").ForwardRefExoticComponent<G9TextEntryProps & import("react").RefAttributes<G9TextInputHandle>>;
|
|
61
|
+
export {};
|
|
62
|
+
//# sourceMappingURL=text-entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-entry.d.ts","sourceRoot":"","sources":["../../src/fields/text-entry.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAgB,MAAM,kBAAkB,CAAC;AAC/F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,yDAAyD;AACzD,MAAM,WAAW,gBAAiB,SAAQ,gBAAgB;IACxD,2GAA2G;IAC3G,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC,wFAAwF;IACxF,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,mFAAmF;IACnF,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,yGAAyG;IACzG,QAAQ,CAAC,SAAS,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAC5C,iEAAiE;IACjE,QAAQ,CAAC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IACzC,8CAA8C;IAC9C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;IAClE,sFAAsF;IACtF,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IACvC,wEAAwE;IACxE,QAAQ,CAAC,uBAAuB,CAAC,EAAE,OAAO,CAAC;CAC5C;AAED,gDAAgD;AAChD,MAAM,MAAM,iBAAiB,GAAG,iBAAiB,CAAC;AAElD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;CAClC,GAAG,OAAO,CAEV;AAED,4DAA4D;AAC5D,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC;IACjD,QAAQ,CAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC,aAAa,CAAC,CAAC;IACvD,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9C;AAED,UAAU,SAAU,SAAQ,gBAAgB;IAC1C,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;CAClC;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,yGAyFzB,CAAC;AAIF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,WAAW,gHAEtB,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { G9KeyboardType, G9StringKey } from "@g9tm/lynxcontrols-foundation";
|
|
2
|
+
import { forwardRef, useImperativeHandle } from "@lynx-js/react";
|
|
3
|
+
import { useG9Settings, useG9Strings } from "../provider/hooks.jsx";
|
|
4
|
+
import { resolveEffectiveKeyboard, resolveInputElementType } from "./input-policy.jsx";
|
|
5
|
+
import { G9OutlinedField } from "./outlined-field.jsx";
|
|
6
|
+
import { useTextInput } from "./use-text-input.jsx";
|
|
7
|
+
function shouldShowEntryMic(state) {
|
|
8
|
+
return state.available && !(state.passwordToggle && state.hasValue) && (state.listening || !state.hasValue);
|
|
9
|
+
}
|
|
10
|
+
const TextEntryBody = forwardRef(function(props, ref) {
|
|
11
|
+
var _props_validator, _props_keyboardType, _core_errorText, _props_variant_restingTone, _ref, _props_variant_confirmType;
|
|
12
|
+
const glyphs = useG9Settings().glyphs;
|
|
13
|
+
const strings = useG9Strings();
|
|
14
|
+
const passwordToggle = true === props.passwordToggle;
|
|
15
|
+
const core = useTextInput({
|
|
16
|
+
...props,
|
|
17
|
+
...props.variant.onConfirm ? {
|
|
18
|
+
onConfirm: props.variant.onConfirm
|
|
19
|
+
} : {}
|
|
20
|
+
}, {
|
|
21
|
+
name: props.variant.name,
|
|
22
|
+
validator: null != (_props_validator = props.validator) ? _props_validator : null,
|
|
23
|
+
validateOnTextChanged: true === props.validateOnTextChanged,
|
|
24
|
+
isPassword: true === props.isPassword,
|
|
25
|
+
showMic: (s)=>shouldShowEntryMic({
|
|
26
|
+
...s,
|
|
27
|
+
passwordToggle
|
|
28
|
+
})
|
|
29
|
+
});
|
|
30
|
+
useImperativeHandle(ref, ()=>core.handle);
|
|
31
|
+
let affordance = null;
|
|
32
|
+
if (passwordToggle && core.hasValue) affordance = {
|
|
33
|
+
icon: core.passwordVisible ? glyphs.eyeClosed : glyphs.eyeOpen,
|
|
34
|
+
signature: core.passwordVisible ? 'eye-closed' : 'eye-open',
|
|
35
|
+
onPress: ()=>core.setPasswordVisible(!core.passwordVisible)
|
|
36
|
+
};
|
|
37
|
+
else if (core.showMic) affordance = {
|
|
38
|
+
icon: core.dictation.listening ? glyphs.micOff : glyphs.mic,
|
|
39
|
+
color: core.dictation.listening ? 'var(--g9-error)' : 'var(--g9-primary)',
|
|
40
|
+
signature: 'voice',
|
|
41
|
+
onPress: core.pressMic
|
|
42
|
+
};
|
|
43
|
+
else if (true === props.clearButton && core.hasValue) affordance = {
|
|
44
|
+
icon: glyphs.clear,
|
|
45
|
+
label: strings.get(G9StringKey.Clear),
|
|
46
|
+
signature: 'clear',
|
|
47
|
+
onPress: ()=>core.setText('', {
|
|
48
|
+
source: 'clear'
|
|
49
|
+
})
|
|
50
|
+
};
|
|
51
|
+
const masked = true === props.isPassword && !core.passwordVisible;
|
|
52
|
+
const keyboard = resolveEffectiveKeyboard(core.inputType, null != (_props_keyboardType = props.keyboardType) ? _props_keyboardType : G9KeyboardType.Default);
|
|
53
|
+
return <G9OutlinedField {...props} hasError={core.hasError} errorText={null != (_core_errorText = core.errorText) ? _core_errorText : null} forceTrailingIconRight={true === props.forceTrailingIconRight || passwordToggle} focused={core.focused} hasValue={core.hasValue} textLength={core.text.length} trailingAffordance={affordance} restingTone={null != (_props_variant_restingTone = props.variant.restingTone) ? _props_variant_restingTone : 'outline'} onFocusRequest={core.focus}>
|
|
54
|
+
{}
|
|
55
|
+
{true === props.readOnly && !masked ? <text className="g9-field__input g9-field__input--readonly" text-maxline="1" style={{
|
|
56
|
+
direction: core.textDirection,
|
|
57
|
+
textAlign: 'rtl' === core.textDirection ? 'right' : 'left',
|
|
58
|
+
...core.font ? {
|
|
59
|
+
fontFamily: core.font
|
|
60
|
+
} : {},
|
|
61
|
+
color: props.disabled ? 'var(--g9-text-disabled)' : 'var(--g9-text-primary)'
|
|
62
|
+
}}>
|
|
63
|
+
{core.text}
|
|
64
|
+
</text> : <input {...core.elementProps} className="g9-field__input" type={resolveInputElementType(core.inputType, keyboard, masked)} confirm-type={null != (_ref = null != (_props_variant_confirmType = props.variant.confirmType) ? _props_variant_confirmType : props.confirmType) ? _ref : 'done'} ios-spell-check={false !== props.isSpellCheckEnabled} ios-auto-correct={false !== props.isTextPredictionEnabled} style={{
|
|
65
|
+
direction: core.textDirection,
|
|
66
|
+
textAlign: 'rtl' === core.textDirection ? 'right' : 'left',
|
|
67
|
+
...core.font ? {
|
|
68
|
+
fontFamily: core.font
|
|
69
|
+
} : {},
|
|
70
|
+
color: props.disabled ? 'var(--g9-text-disabled)' : 'var(--g9-text-primary)'
|
|
71
|
+
}}/>}
|
|
72
|
+
</G9OutlinedField>;
|
|
73
|
+
});
|
|
74
|
+
const entryVariant = {
|
|
75
|
+
name: 'G9TextEntry.value'
|
|
76
|
+
};
|
|
77
|
+
const text_entry_G9TextEntry = forwardRef(function(props, ref) {
|
|
78
|
+
return <TextEntryBody {...props} variant={entryVariant} ref={ref}/>;
|
|
79
|
+
});
|
|
80
|
+
export { TextEntryBody, shouldShowEntryMic, text_entry_G9TextEntry as G9TextEntry };
|
|
81
|
+
|
|
82
|
+
//# sourceMappingURL=text-entry.jsx.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fields/text-entry.jsx","sources":["../../src/fields/text-entry.tsx"],"sourcesContent":["import { G9KeyboardType, G9StringKey } from '@g9tm/lynxcontrols-foundation';\nimport { forwardRef, type ReactNode, useImperativeHandle } from '@lynx-js/react';\nimport { useG9Settings, useG9Strings } from '../provider/hooks';\nimport { resolveEffectiveKeyboard, resolveInputElementType } from './input-policy';\nimport { G9OutlinedField, type G9TrailingAffordance } from './outlined-field';\nimport { type G9TextInputHandle, type G9TextInputProps, useTextInput } from './use-text-input';\nimport type { G9TextValidator } from './validator';\n\n/** Props of {@link G9TextEntry} (MAUI `G9TextEntry`). */\nexport interface G9TextEntryProps extends G9TextInputProps {\n /** Eye toggle in the trailing slot while there is a value; pins the trailing icon right. Default false. */\n readonly passwordToggle?: boolean;\n /** Mask the value (until the eye reveals it); the text is pinned LTR. Default false. */\n readonly isPassword?: boolean;\n /** Clear (×) button in the trailing slot while there is a value. Default false. */\n readonly clearButton?: boolean;\n /** Extra validation, run before the input-type rule (on blur, `validateOnTextChanged`, `validate()`). */\n readonly validator?: G9TextValidator | null;\n /** Validate on every change, not only on blur. Default false. */\n readonly validateOnTextChanged?: boolean;\n /** Keyboard confirm key. Default `'done'`. */\n readonly confirmType?: 'send' | 'search' | 'go' | 'done' | 'next';\n /** iOS spell checking (`ios-spell-check`; Android has no attribute). Default true. */\n readonly isSpellCheckEnabled?: boolean;\n /** iOS auto-correct / prediction (`ios-auto-correct`). Default true. */\n readonly isTextPredictionEnabled?: boolean;\n}\n\n/** Imperative handle of {@link G9TextEntry}. */\nexport type G9TextEntryHandle = G9TextInputHandle;\n\n/**\n * Whether the trailing slot shows the microphone (MAUI `ShouldShowVoiceMic`): dictation available, not while the\n * password eye owns the slot, and only on an empty field or during a session (the clear button owns a filled field).\n */\nexport function shouldShowEntryMic(state: {\n readonly available: boolean;\n readonly listening: boolean;\n readonly hasValue: boolean;\n readonly passwordToggle: boolean;\n}): boolean {\n return state.available && !(state.passwordToggle && state.hasValue) && (state.listening || !state.hasValue);\n}\n\n/** What `G9SearchEntry` changes in the entry (internal). */\nexport interface G9EntryVariant {\n readonly name: string;\n readonly restingTone?: 'outline' | 'placeholder';\n readonly confirmType?: G9TextEntryProps['confirmType'];\n readonly onConfirm?: (value: string) => void;\n}\n\ninterface BodyProps extends G9TextEntryProps {\n readonly variant: G9EntryVariant;\n}\n\n/**\n * The entry body shared by `G9TextEntry` and `G9SearchEntry` (internal). The inner name must differ from the binding\n * (E20, scripts/check-dist-jsx.mjs): `G9TextEntry` renders it in this module.\n */\nexport const TextEntryBody = forwardRef<G9TextEntryHandle, BodyProps>(\n function TextEntryBodyRender(props, ref): ReactNode {\n const glyphs = useG9Settings().glyphs;\n const strings = useG9Strings();\n const passwordToggle = props.passwordToggle === true;\n const core = useTextInput(\n { ...props, ...(props.variant.onConfirm ? { onConfirm: props.variant.onConfirm } : {}) },\n {\n name: props.variant.name,\n validator: props.validator ?? null,\n validateOnTextChanged: props.validateOnTextChanged === true,\n isPassword: props.isPassword === true,\n showMic: (s) => shouldShowEntryMic({ ...s, passwordToggle }),\n },\n );\n useImperativeHandle(ref, () => core.handle);\n\n let affordance: G9TrailingAffordance | null = null;\n if (passwordToggle && core.hasValue) {\n affordance = {\n icon: core.passwordVisible ? glyphs.eyeClosed : glyphs.eyeOpen,\n signature: core.passwordVisible ? 'eye-closed' : 'eye-open',\n onPress: () => core.setPasswordVisible(!core.passwordVisible),\n };\n } else if (core.showMic) {\n affordance = {\n icon: core.dictation.listening ? glyphs.micOff : glyphs.mic,\n color: core.dictation.listening ? 'var(--g9-error)' : 'var(--g9-primary)',\n signature: 'voice',\n onPress: core.pressMic,\n };\n } else if (props.clearButton === true && core.hasValue) {\n affordance = {\n icon: glyphs.clear,\n label: strings.get(G9StringKey.Clear),\n signature: 'clear',\n onPress: () => core.setText('', { source: 'clear' }),\n };\n }\n\n const masked = props.isPassword === true && !core.passwordVisible;\n const keyboard = resolveEffectiveKeyboard(core.inputType, props.keyboardType ?? G9KeyboardType.Default);\n return (\n <G9OutlinedField\n {...props}\n hasError={core.hasError}\n errorText={core.errorText ?? null}\n forceTrailingIconRight={props.forceTrailingIconRight === true || passwordToggle}\n focused={core.focused}\n hasValue={core.hasValue}\n textLength={core.text.length}\n trailingAffordance={affordance}\n restingTone={props.variant.restingTone ?? 'outline'}\n onFocusRequest={core.focus}\n >\n {/* A read-only (unmasked) field shows its value as text: nobody types into it, and a native read-only\n EditText ignored the value pushed into it (a scan-only barcode field stayed blank). */}\n {props.readOnly === true && !masked ? (\n <text\n className=\"g9-field__input g9-field__input--readonly\"\n text-maxline=\"1\"\n style={{\n direction: core.textDirection,\n textAlign: core.textDirection === 'rtl' ? 'right' : 'left',\n ...(core.font ? { fontFamily: core.font } : {}),\n color: props.disabled ? 'var(--g9-text-disabled)' : 'var(--g9-text-primary)',\n }}\n >\n {core.text}\n </text>\n ) : (\n <input\n {...core.elementProps}\n className=\"g9-field__input\"\n type={resolveInputElementType(core.inputType, keyboard, masked)}\n confirm-type={props.variant.confirmType ?? props.confirmType ?? 'done'}\n ios-spell-check={props.isSpellCheckEnabled !== false}\n ios-auto-correct={props.isTextPredictionEnabled !== false}\n style={{\n direction: core.textDirection,\n textAlign: core.textDirection === 'rtl' ? 'right' : 'left',\n ...(core.font ? { fontFamily: core.font } : {}),\n color: props.disabled ? 'var(--g9-text-disabled)' : 'var(--g9-text-primary)',\n }}\n />\n )}\n </G9OutlinedField>\n );\n },\n);\n\nconst entryVariant: G9EntryVariant = { name: 'G9TextEntry.value' };\n\n/**\n * Single-line outlined text field (MAUI `G9TextEntry`): floating label, input-type keyboard/filter/validation,\n * password eye, clear button, optional dictation (`voiceEnabled` + `services.speech`).\n *\n * - Value: `value`/`defaultValue`/`onValueChange(value, { source })`; one call per change.\n * - Validation: on blur when there is a rule (`validator`, email/url, custom pattern), on every change with\n * `validateOnTextChanged`, or through the handle's `validate()`. An error set through `hasError`/`errorText`\n * survives blur on a field without a rule.\n * - Requires the host's `xelement-input` registration (plan/specs/02 §2). Keyboard avoidance: put the form inside\n * lynx-ui `KeyboardAwareRoot`/`KeyboardAwareResponder`; the field reports focus to it.\n */\nexport const G9TextEntry = forwardRef<G9TextEntryHandle, G9TextEntryProps>(function G9TextEntry(props, ref) {\n return <TextEntryBody {...props} variant={entryVariant} ref={ref} />;\n});\n"],"names":["shouldShowEntryMic","state","TextEntryBody","forwardRef","props","ref","_props_validator","_props_keyboardType","_core_errorText","_props_variant_restingTone","_ref","glyphs","useG9Settings","strings","useG9Strings","passwordToggle","core","useTextInput","s","useImperativeHandle","affordance","G9StringKey","masked","keyboard","resolveEffectiveKeyboard","G9KeyboardType","G9OutlinedField","text","input","resolveInputElementType","entryVariant","G9TextEntry"],"mappings":";;;;;;AAmCO,SAASA,mBAAmBC,KAKlC;IACC,OAAOA,MAAM,SAAS,IAAI,CAAEA,CAAAA,MAAM,cAAc,IAAIA,MAAM,QAAO,KAAOA,CAAAA,MAAM,SAAS,IAAI,CAACA,MAAM,QAAO;AAC3G;AAkBO,MAAMC,gBAAgBC,WAC3B,SAA6BC,KAAK,EAAEC,GAAG;QAQtBC,kBAgC2CC,qBAK3CC,iBAMEC,4BAuBKC,MAAAA;IAzEtB,MAAMC,SAASC,gBAAgB,MAAM;IACrC,MAAMC,UAAUC;IAChB,MAAMC,iBAAiBX,AAAyB,SAAzBA,MAAM,cAAc;IAC3C,MAAMY,OAAOC,aACX;QAAE,GAAGb,KAAK;QAAE,GAAIA,MAAM,OAAO,CAAC,SAAS,GAAG;YAAE,WAAWA,MAAM,OAAO,CAAC,SAAS;QAAC,IAAI,CAAC,CAAC;IAAE,GACvF;QACE,MAAMA,MAAM,OAAO,CAAC,IAAI;QACxB,WAAW,QAAAE,CAAAA,mBAAAA,MAAM,SAAS,AAAD,IAAdA,mBAAmB;QAC9B,uBAAuBF,AAAgC,SAAhCA,MAAM,qBAAqB;QAClD,YAAYA,AAAqB,SAArBA,MAAM,UAAU;QAC5B,SAAS,CAACc,IAAMlB,mBAAmB;gBAAE,GAAGkB,CAAC;gBAAEH;YAAe;IAC5D;IAEFI,oBAAoBd,KAAK,IAAMW,KAAK,MAAM;IAE1C,IAAII,aAA0C;IAC9C,IAAIL,kBAAkBC,KAAK,QAAQ,EACjCI,aAAa;QACX,MAAMJ,KAAK,eAAe,GAAGL,OAAO,SAAS,GAAGA,OAAO,OAAO;QAC9D,WAAWK,KAAK,eAAe,GAAG,eAAe;QACjD,SAAS,IAAMA,KAAK,kBAAkB,CAAC,CAACA,KAAK,eAAe;IAC9D;SACK,IAAIA,KAAK,OAAO,EACrBI,aAAa;QACX,MAAMJ,KAAK,SAAS,CAAC,SAAS,GAAGL,OAAO,MAAM,GAAGA,OAAO,GAAG;QAC3D,OAAOK,KAAK,SAAS,CAAC,SAAS,GAAG,oBAAoB;QACtD,WAAW;QACX,SAASA,KAAK,QAAQ;IACxB;SACK,IAAIZ,AAAsB,SAAtBA,MAAM,WAAW,IAAaY,KAAK,QAAQ,EACpDI,aAAa;QACX,MAAMT,OAAO,KAAK;QAClB,OAAOE,QAAQ,GAAG,CAACQ,YAAY,KAAK;QACpC,WAAW;QACX,SAAS,IAAML,KAAK,OAAO,CAAC,IAAI;gBAAE,QAAQ;YAAQ;IACpD;IAGF,MAAMM,SAASlB,AAAqB,SAArBA,MAAM,UAAU,IAAa,CAACY,KAAK,eAAe;IACjE,MAAMO,WAAWC,yBAAyBR,KAAK,SAAS,EAAE,QAAAT,CAAAA,sBAAAA,MAAM,YAAY,AAAD,IAAjBA,sBAAsBkB,eAAe,OAAO;IACtG,QACGC,iBACE,GAAGtB,KAAK,EACT,UAAUY,KAAK,QAAQ,EACvB,WAAW,QAAAR,CAAAA,kBAAAA,KAAK,SAAS,AAAD,IAAbA,kBAAkB,MAC7B,wBAAwBJ,AAAiC,SAAjCA,MAAM,sBAAsB,IAAaW,gBACjE,SAASC,KAAK,OAAO,EACrB,UAAUA,KAAK,QAAQ,EACvB,YAAYA,KAAK,IAAI,CAAC,MAAM,EAC5B,oBAAoBI,YACpB,aAAa,QAAAX,CAAAA,6BAAAA,MAAM,OAAO,CAAC,WAAW,AAAD,IAAxBA,6BAA6B,WAC1C,gBAAgBO,KAAK,KAAK,EAC3B;QACC,EAC2F;QAC3F,CAACZ,AAAmB,SAAnBA,MAAM,QAAQ,IAAa,CAACkB,UAC1BK,KACC,UAAU,4CACV,aAAa,IACb,OAAO;QACL,WAAWX,KAAK,aAAa;QAC7B,WAAWA,AAAuB,UAAvBA,KAAK,aAAa,GAAa,UAAU;QACpD,GAAIA,KAAK,IAAI,GAAG;YAAE,YAAYA,KAAK,IAAI;QAAC,IAAI,CAAC,CAAC;QAC9C,OAAOZ,MAAM,QAAQ,GAAG,4BAA4B;IACtD,GACD;YACC,CAACY,KAAK,IAAI,CAAC;UACb,EAAEW,SAEDC,OACE,GAAGZ,KAAK,YAAY,EACrB,UAAU,kBACV,MAAMa,wBAAwBb,KAAK,SAAS,EAAEO,UAAUD,SACxD,cAAc,QAAAZ,CAAAA,OAAAA,QAAAA,CAAAA,6BAAAA,MAAM,OAAO,CAAC,WAAW,AAAD,IAAxBA,6BAA6BN,MAAM,WAAW,AAAD,IAA7CM,OAAkD,QAChE,iBAAiBN,AAA8B,UAA9BA,MAAM,mBAAmB,EAC1C,kBAAkBA,AAAkC,UAAlCA,MAAM,uBAAuB,EAC/C,OAAO;QACL,WAAWY,KAAK,aAAa;QAC7B,WAAWA,AAAuB,UAAvBA,KAAK,aAAa,GAAa,UAAU;QACpD,GAAIA,KAAK,IAAI,GAAG;YAAE,YAAYA,KAAK,IAAI;QAAC,IAAI,CAAC,CAAC;QAC9C,OAAOZ,MAAM,QAAQ,GAAG,4BAA4B;IACtD,KAEF;MACJ,EAAEsB;AAEN;AAGF,MAAMI,eAA+B;IAAE,MAAM;AAAoB;AAa1D,MAAMC,yBAAc5B,WAAgD,SAAqBC,KAAK,EAAEC,GAAG;IACxG,QAAQH,eAAe,GAAGE,KAAK,EAAE,SAAS0B,cAAc,KAAKzB;AAC/D"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Options of {@link useDictation}. */
|
|
2
|
+
export interface G9DictationOptions {
|
|
3
|
+
/** Whether the field offers dictation at all (`voiceEnabled`). Availability is not checked while `false`. */
|
|
4
|
+
readonly enabled: boolean;
|
|
5
|
+
/** Locale to recognise; `null`/`undefined` follows the active culture (MAUI `VoiceCulture`). */
|
|
6
|
+
readonly locale?: string | null;
|
|
7
|
+
/** The field's current text. */
|
|
8
|
+
readonly readText: () => string;
|
|
9
|
+
/** Writes recognised text (the field filters it like typed text). */
|
|
10
|
+
readonly writeText: (text: string) => void;
|
|
11
|
+
readonly onListeningStarted?: () => void;
|
|
12
|
+
readonly onListeningEnded?: () => void;
|
|
13
|
+
readonly onFailed?: (message: string) => void;
|
|
14
|
+
}
|
|
15
|
+
/** What {@link useDictation} returns. */
|
|
16
|
+
export interface G9DictationState {
|
|
17
|
+
/** `services.speech` exists, the field enabled dictation and the recogniser reported this locale available. */
|
|
18
|
+
readonly available: boolean;
|
|
19
|
+
/** A session is listening. */
|
|
20
|
+
readonly listening: boolean;
|
|
21
|
+
/** A session exists (listening or waiting for the permission prompt). */
|
|
22
|
+
readonly active: boolean;
|
|
23
|
+
start(): Promise<void>;
|
|
24
|
+
stop(): Promise<void>;
|
|
25
|
+
toggle(): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The dictation session owner shared by `G9TextEntry`, `G9Editor` and `G9SearchEntry` (MAUI `G9VoiceDictation` +
|
|
29
|
+
* `G9Speech.IsAvailable`). Optional service: without `services.speech` the microphone is never shown. Availability
|
|
30
|
+
* is asked once per locale (`isAvailable(locale)`, no prompt); a stale answer for a previous locale is ignored.
|
|
31
|
+
* Permission is requested on every start, from the tap. A running session stops when the field unmounts.
|
|
32
|
+
*/
|
|
33
|
+
export declare function useDictation(options: G9DictationOptions): G9DictationState;
|
|
34
|
+
//# sourceMappingURL=use-dictation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-dictation.d.ts","sourceRoot":"","sources":["../../src/fields/use-dictation.ts"],"names":[],"mappings":"AAIA,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC,6GAA6G;IAC7G,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,gGAAgG;IAChG,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,gCAAgC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,MAAM,CAAC;IAChC,qEAAqE;IACrE,QAAQ,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IACzC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/C;AAED,yCAAyC;AACzC,MAAM,WAAW,gBAAgB;IAC/B,+GAA+G;IAC/G,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,8BAA8B;IAC9B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,yEAAyE;IACzE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,kBAAkB,GAAG,gBAAgB,CA8D1E"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from "@lynx-js/react";
|
|
2
|
+
import { useG9Culture, useG9OptionalService, useG9Strings } from "../provider/hooks.jsx";
|
|
3
|
+
import { G9VoiceDictation } from "./dictation.jsx";
|
|
4
|
+
function useDictation(options) {
|
|
5
|
+
var _options_locale;
|
|
6
|
+
const speech = useG9OptionalService('speech');
|
|
7
|
+
const culture = useG9Culture();
|
|
8
|
+
const strings = useG9Strings();
|
|
9
|
+
const locale = null != (_options_locale = options.locale) ? _options_locale : culture.locale;
|
|
10
|
+
const [, setVersion] = useState(0);
|
|
11
|
+
const [available, setAvailable] = useState(false);
|
|
12
|
+
const latest = useRef({
|
|
13
|
+
options,
|
|
14
|
+
strings,
|
|
15
|
+
locale,
|
|
16
|
+
speech
|
|
17
|
+
});
|
|
18
|
+
latest.current = {
|
|
19
|
+
options,
|
|
20
|
+
strings,
|
|
21
|
+
locale,
|
|
22
|
+
speech
|
|
23
|
+
};
|
|
24
|
+
const dictation = useRef(null);
|
|
25
|
+
if (!dictation.current) dictation.current = new G9VoiceDictation({
|
|
26
|
+
get speech () {
|
|
27
|
+
return latest.current.speech;
|
|
28
|
+
},
|
|
29
|
+
readText: ()=>latest.current.options.readText(),
|
|
30
|
+
writeText: (text)=>latest.current.options.writeText(text),
|
|
31
|
+
onStateChanged: ()=>setVersion((n)=>n + 1),
|
|
32
|
+
strings: ()=>latest.current.strings,
|
|
33
|
+
locale: ()=>latest.current.locale,
|
|
34
|
+
onListeningStarted: ()=>{
|
|
35
|
+
var _latest_current_options_onListeningStarted, _latest_current_options;
|
|
36
|
+
return null == (_latest_current_options_onListeningStarted = (_latest_current_options = latest.current.options).onListeningStarted) ? void 0 : _latest_current_options_onListeningStarted.call(_latest_current_options);
|
|
37
|
+
},
|
|
38
|
+
onListeningEnded: ()=>{
|
|
39
|
+
var _latest_current_options_onListeningEnded, _latest_current_options;
|
|
40
|
+
return null == (_latest_current_options_onListeningEnded = (_latest_current_options = latest.current.options).onListeningEnded) ? void 0 : _latest_current_options_onListeningEnded.call(_latest_current_options);
|
|
41
|
+
},
|
|
42
|
+
onFailed: (message)=>{
|
|
43
|
+
var _latest_current_options_onFailed, _latest_current_options;
|
|
44
|
+
return null == (_latest_current_options_onFailed = (_latest_current_options = latest.current.options).onFailed) ? void 0 : _latest_current_options_onFailed.call(_latest_current_options, message);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
const session = dictation.current;
|
|
48
|
+
useEffect(()=>{
|
|
49
|
+
if (!options.enabled || !speech) return void setAvailable(false);
|
|
50
|
+
let current = true;
|
|
51
|
+
speech.isAvailable(locale).then((ok)=>{
|
|
52
|
+
if (current) setAvailable(true === ok);
|
|
53
|
+
}, ()=>{
|
|
54
|
+
if (current) setAvailable(false);
|
|
55
|
+
});
|
|
56
|
+
return ()=>{
|
|
57
|
+
current = false;
|
|
58
|
+
};
|
|
59
|
+
}, [
|
|
60
|
+
options.enabled,
|
|
61
|
+
speech,
|
|
62
|
+
locale
|
|
63
|
+
]);
|
|
64
|
+
useEffect(()=>()=>{
|
|
65
|
+
session.stop();
|
|
66
|
+
}, [
|
|
67
|
+
session
|
|
68
|
+
]);
|
|
69
|
+
return {
|
|
70
|
+
available: options.enabled && void 0 !== speech && available,
|
|
71
|
+
listening: session.isListening,
|
|
72
|
+
active: session.hasSession,
|
|
73
|
+
start: ()=>session.start(),
|
|
74
|
+
stop: ()=>session.stop(),
|
|
75
|
+
toggle: ()=>session.toggle()
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
export { useDictation };
|
|
79
|
+
|
|
80
|
+
//# sourceMappingURL=use-dictation.jsx.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fields/use-dictation.jsx","sources":["../../src/fields/use-dictation.ts"],"sourcesContent":["import { useEffect, useRef, useState } from '@lynx-js/react';\nimport { useG9Culture, useG9OptionalService, useG9Strings } from '../provider/hooks';\nimport { G9VoiceDictation } from './dictation';\n\n/** Options of {@link useDictation}. */\nexport interface G9DictationOptions {\n /** Whether the field offers dictation at all (`voiceEnabled`). Availability is not checked while `false`. */\n readonly enabled: boolean;\n /** Locale to recognise; `null`/`undefined` follows the active culture (MAUI `VoiceCulture`). */\n readonly locale?: string | null;\n /** The field's current text. */\n readonly readText: () => string;\n /** Writes recognised text (the field filters it like typed text). */\n readonly writeText: (text: string) => void;\n readonly onListeningStarted?: () => void;\n readonly onListeningEnded?: () => void;\n readonly onFailed?: (message: string) => void;\n}\n\n/** What {@link useDictation} returns. */\nexport interface G9DictationState {\n /** `services.speech` exists, the field enabled dictation and the recogniser reported this locale available. */\n readonly available: boolean;\n /** A session is listening. */\n readonly listening: boolean;\n /** A session exists (listening or waiting for the permission prompt). */\n readonly active: boolean;\n start(): Promise<void>;\n stop(): Promise<void>;\n toggle(): Promise<void>;\n}\n\n/**\n * The dictation session owner shared by `G9TextEntry`, `G9Editor` and `G9SearchEntry` (MAUI `G9VoiceDictation` +\n * `G9Speech.IsAvailable`). Optional service: without `services.speech` the microphone is never shown. Availability\n * is asked once per locale (`isAvailable(locale)`, no prompt); a stale answer for a previous locale is ignored.\n * Permission is requested on every start, from the tap. A running session stops when the field unmounts.\n */\nexport function useDictation(options: G9DictationOptions): G9DictationState {\n const speech = useG9OptionalService('speech');\n const culture = useG9Culture();\n const strings = useG9Strings();\n const locale = options.locale ?? culture.locale;\n const [, setVersion] = useState(0);\n const [available, setAvailable] = useState(false);\n const latest = useRef({ options, strings, locale, speech });\n latest.current = { options, strings, locale, speech };\n\n const dictation = useRef<G9VoiceDictation | null>(null);\n if (!dictation.current) {\n dictation.current = new G9VoiceDictation({\n get speech() {\n return latest.current.speech;\n },\n readText: () => latest.current.options.readText(),\n writeText: (text) => latest.current.options.writeText(text),\n onStateChanged: () => setVersion((n) => n + 1),\n strings: () => latest.current.strings,\n locale: () => latest.current.locale,\n onListeningStarted: () => latest.current.options.onListeningStarted?.(),\n onListeningEnded: () => latest.current.options.onListeningEnded?.(),\n onFailed: (message) => latest.current.options.onFailed?.(message),\n });\n }\n const session = dictation.current;\n\n useEffect(() => {\n if (!options.enabled || !speech) {\n setAvailable(false);\n return;\n }\n let current = true;\n speech.isAvailable(locale).then(\n (ok) => {\n if (current) setAvailable(ok === true);\n },\n () => {\n if (current) setAvailable(false);\n },\n );\n return () => {\n current = false;\n };\n }, [options.enabled, speech, locale]);\n\n useEffect(\n () => () => {\n void session.stop();\n },\n [session],\n );\n\n return {\n available: options.enabled && speech !== undefined && available,\n listening: session.isListening,\n active: session.hasSession,\n start: () => session.start(),\n stop: () => session.stop(),\n toggle: () => session.toggle(),\n };\n}\n"],"names":["useDictation","options","_options_locale","speech","useG9OptionalService","culture","useG9Culture","strings","useG9Strings","locale","setVersion","useState","available","setAvailable","latest","useRef","dictation","G9VoiceDictation","text","n","_latest_current_options","message","session","useEffect","current","ok","undefined"],"mappings":";;;AAsCO,SAASA,aAAaC,OAA2B;QAIvCC;IAHf,MAAMC,SAASC,qBAAqB;IACpC,MAAMC,UAAUC;IAChB,MAAMC,UAAUC;IAChB,MAAMC,SAAS,QAAAP,CAAAA,kBAAAA,QAAQ,MAAM,AAAD,IAAbA,kBAAkBG,QAAQ,MAAM;IAC/C,MAAM,GAAGK,WAAW,GAAGC,SAAS;IAChC,MAAM,CAACC,WAAWC,aAAa,GAAGF,SAAS;IAC3C,MAAMG,SAASC,OAAO;QAAEd;QAASM;QAASE;QAAQN;IAAO;IACzDW,OAAO,OAAO,GAAG;QAAEb;QAASM;QAASE;QAAQN;IAAO;IAEpD,MAAMa,YAAYD,OAAgC;IAClD,IAAI,CAACC,UAAU,OAAO,EACpBA,UAAU,OAAO,GAAG,IAAIC,iBAAiB;QACvC,IAAI;YACF,OAAOH,OAAO,OAAO,CAAC,MAAM;QAC9B;QACA,UAAU,IAAMA,OAAO,OAAO,CAAC,OAAO,CAAC,QAAQ;QAC/C,WAAW,CAACI,OAASJ,OAAO,OAAO,CAAC,OAAO,CAAC,SAAS,CAACI;QACtD,gBAAgB,IAAMR,WAAW,CAACS,IAAMA,IAAI;QAC5C,SAAS,IAAML,OAAO,OAAO,CAAC,OAAO;QACrC,QAAQ,IAAMA,OAAO,OAAO,CAAC,MAAM;QACnC,oBAAoB;gBAAMM,4CAAAA;2BAAAA,CAAAA,6CAAAA,AAAAA,CAAAA,0BAAAA,OAAO,OAAO,CAAC,OAAO,AAAD,EAAE,kBAAkB,AAAD,IAAxCA,KAAAA,IAAAA,2CAAAA,IAAAA,CAAAA;;QAC1B,kBAAkB;gBAAMA,0CAAAA;2BAAAA,CAAAA,2CAAAA,AAAAA,CAAAA,0BAAAA,OAAO,OAAO,CAAC,OAAO,AAAD,EAAE,gBAAgB,AAAD,IAAtCA,KAAAA,IAAAA,yCAAAA,IAAAA,CAAAA;;QACxB,UAAU,CAACC;gBAAYD,kCAAAA;2BAAAA,CAAAA,mCAAAA,AAAAA,CAAAA,0BAAAA,OAAO,OAAO,CAAC,OAAO,AAAD,EAAE,QAAQ,AAAD,IAA9BA,KAAAA,IAAAA,iCAAAA,IAAAA,CAAAA,yBAAkCC;;IAC3D;IAEF,MAAMC,UAAUN,UAAU,OAAO;IAEjCO,UAAU;QACR,IAAI,CAACtB,QAAQ,OAAO,IAAI,CAACE,QAAQ,YAC/BU,aAAa;QAGf,IAAIW,UAAU;QACdrB,OAAO,WAAW,CAACM,QAAQ,IAAI,CAC7B,CAACgB;YACC,IAAID,SAASX,aAAaY,AAAO,SAAPA;QAC5B,GACA;YACE,IAAID,SAASX,aAAa;QAC5B;QAEF,OAAO;YACLW,UAAU;QACZ;IACF,GAAG;QAACvB,QAAQ,OAAO;QAAEE;QAAQM;KAAO;IAEpCc,UACE,IAAM;YACCD,QAAQ,IAAI;QACnB,GACA;QAACA;KAAQ;IAGX,OAAO;QACL,WAAWrB,QAAQ,OAAO,IAAIE,AAAWuB,WAAXvB,UAAwBS;QACtD,WAAWU,QAAQ,WAAW;QAC9B,QAAQA,QAAQ,UAAU;QAC1B,OAAO,IAAMA,QAAQ,KAAK;QAC1B,MAAM,IAAMA,QAAQ,IAAI;QACxB,QAAQ,IAAMA,QAAQ,MAAM;IAC9B;AACF"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { G9InputType, type G9KeyboardType, G9TextInputDirection } from '@g9tm/lynxcontrols-foundation';
|
|
2
|
+
import type { NodesRef } from '@lynx-js/types';
|
|
3
|
+
import type { G9OutlinedFieldProps } from './outlined-field.js';
|
|
4
|
+
import { type G9TextValidator } from './validator.js';
|
|
5
|
+
/** Where a value change came from (plan/specs/03 §3). */
|
|
6
|
+
export type G9ValueChangeSource = 'user' | 'dictation' | 'clear' | 'programmatic';
|
|
7
|
+
/** Payload of `onValueChange`. */
|
|
8
|
+
export interface G9ValueChangeDetails {
|
|
9
|
+
readonly source: G9ValueChangeSource;
|
|
10
|
+
}
|
|
11
|
+
/** Props the text inputs (`G9TextEntry`, `G9Editor`, `G9SearchEntry`) share on top of the outlined-field props. */
|
|
12
|
+
export interface G9TextInputProps extends G9OutlinedFieldProps {
|
|
13
|
+
/** The text (controlled; MAUI `Text`). Present, the caller owns it and must apply `onValueChange`. */
|
|
14
|
+
readonly value?: string;
|
|
15
|
+
/** Initial text while uncontrolled. Default `''`. */
|
|
16
|
+
readonly defaultValue?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Once per change of the field's value, with where it came from: `'user'` (typing, paste), `'dictation'`,
|
|
19
|
+
* `'clear'` (the clear button) or `'programmatic'` (the field re-filtered a value it was given, e.g. after an
|
|
20
|
+
* `inputType` change). Never for a value the parent pushed in that needed no filtering.
|
|
21
|
+
*/
|
|
22
|
+
readonly onValueChange?: (value: string, details: G9ValueChangeDetails) => void;
|
|
23
|
+
/** On-screen keyboard; used when `inputType` is `'default'` (any other type picks its own). Default `'default'`. */
|
|
24
|
+
readonly keyboardType?: G9KeyboardType;
|
|
25
|
+
/** Semantic input type: keyboard, live filter and blur validation. Default `'default'`. */
|
|
26
|
+
readonly inputType?: G9InputType;
|
|
27
|
+
/** Per-character filter regex (a single character class) for `inputType: 'custom'`. */
|
|
28
|
+
readonly allowedCharsPattern?: string | null;
|
|
29
|
+
/** Blur validation regex for `inputType: 'custom'`. An invalid pattern fails closed. */
|
|
30
|
+
readonly validationPattern?: string | null;
|
|
31
|
+
/** Message for a failed type validation; default the culture's `invalidEmail` / `invalidUrl` / `invalidValue`. */
|
|
32
|
+
readonly validationErrorText?: string | null;
|
|
33
|
+
/** Direction of the entered text; `'matchParent'` (default) pins numbers, phone, email, URL and passwords LTR. */
|
|
34
|
+
readonly inputTextDirection?: G9TextInputDirection;
|
|
35
|
+
/** Font family of the entered text; default the culture's font. */
|
|
36
|
+
readonly customFont?: string | null;
|
|
37
|
+
/** Offer dictation through `services.speech` (hidden without the service or recogniser). Default false. */
|
|
38
|
+
readonly voiceEnabled?: boolean;
|
|
39
|
+
/** Locale to recognise (MAUI `VoiceCulture`); default the active culture. */
|
|
40
|
+
readonly voiceLocale?: string | null;
|
|
41
|
+
readonly onVoiceListeningStarted?: () => void;
|
|
42
|
+
readonly onVoiceListeningEnded?: () => void;
|
|
43
|
+
/** Dictation could not run or finish; a localized message for a toast. */
|
|
44
|
+
readonly onVoiceFailed?: (message: string) => void;
|
|
45
|
+
/** Validation ran (blur, `validateOnTextChanged` or `validate()`): the message, or `null` when valid. */
|
|
46
|
+
readonly onValidationChange?: (message: string | null) => void;
|
|
47
|
+
readonly onFocus?: () => void;
|
|
48
|
+
readonly onBlur?: () => void;
|
|
49
|
+
/** The keyboard's confirm key was pressed. */
|
|
50
|
+
readonly onConfirm?: (value: string) => void;
|
|
51
|
+
/** Element id of the inner `<input>`/`<textarea>`. */
|
|
52
|
+
readonly inputId?: string;
|
|
53
|
+
}
|
|
54
|
+
/** Imperative handle of the text inputs (MAUI public methods). */
|
|
55
|
+
export interface G9TextInputHandle {
|
|
56
|
+
/** Focuses the inner element (raises the keyboard). */
|
|
57
|
+
focus(): void;
|
|
58
|
+
/** Removes focus (hides the keyboard). */
|
|
59
|
+
blur(): void;
|
|
60
|
+
/** Runs the validator and the type rule now; sets or clears the error; `true` when valid (MAUI `Validate`). */
|
|
61
|
+
validate(): boolean;
|
|
62
|
+
/** `true` while dictating (MAUI `IsListening`). */
|
|
63
|
+
readonly isListening: boolean;
|
|
64
|
+
/** MAUI `ToggleVoiceAsync`. */
|
|
65
|
+
toggleVoice(): Promise<void>;
|
|
66
|
+
/** MAUI `StartVoiceAsync`. */
|
|
67
|
+
startVoice(): Promise<void>;
|
|
68
|
+
/** MAUI `StopVoiceAsync`; safe when nothing runs. */
|
|
69
|
+
stopVoice(): Promise<void>;
|
|
70
|
+
/** The inner element's node ref (MAUI `InnerEntry` / `InnerEditor`), for `invoke` calls G9 does not wrap. */
|
|
71
|
+
readonly element: G9NodeRef | null;
|
|
72
|
+
}
|
|
73
|
+
/** The Lynx node ref of a field's inner element. */
|
|
74
|
+
export type G9NodeRef = NodesRef;
|
|
75
|
+
/** Lynx input event detail. */
|
|
76
|
+
interface InputDetail {
|
|
77
|
+
readonly value?: string;
|
|
78
|
+
readonly isComposing?: boolean;
|
|
79
|
+
}
|
|
80
|
+
/** Resolves the entered text's direction (MAUI `ResolveInputFlowDirection`). */
|
|
81
|
+
export declare function resolveInputTextDirection(inputTextDirection: G9TextInputDirection, inputType: G9InputType, isPassword: boolean, cultureDirection: 'ltr' | 'rtl'): 'ltr' | 'rtl';
|
|
82
|
+
/** Calls a UI method on a node; a missing node or a failing call is ignored (the element is gone). */
|
|
83
|
+
export declare function invokeNode(ref: {
|
|
84
|
+
current: G9NodeRef | null;
|
|
85
|
+
}, method: string, params?: Record<string, unknown>): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* {@link invokeNode}, retried on the next ticks (up to `attempts` times) while the element is not created natively
|
|
88
|
+
* yet, e.g. a focus requested during the first commit.
|
|
89
|
+
*/
|
|
90
|
+
export declare function invokeNodeWhenReady(ref: {
|
|
91
|
+
current: G9NodeRef | null;
|
|
92
|
+
}, method: string, params?: Record<string, unknown>, attempts?: number): void;
|
|
93
|
+
/** Options of {@link useTextInput}. */
|
|
94
|
+
export interface G9TextInputCoreOptions {
|
|
95
|
+
/** Name for the controlled/uncontrolled diagnostic, e.g. `'G9TextEntry.value'`. */
|
|
96
|
+
readonly name: string;
|
|
97
|
+
/** Whether the microphone is shown, given the dictation and value state. */
|
|
98
|
+
readonly showMic: (state: {
|
|
99
|
+
available: boolean;
|
|
100
|
+
listening: boolean;
|
|
101
|
+
hasValue: boolean;
|
|
102
|
+
}) => boolean;
|
|
103
|
+
/** Extra validator (`G9TextEntry.validator`; the editor has none). */
|
|
104
|
+
readonly validator?: G9TextValidator | null;
|
|
105
|
+
/** Validate on every change (`G9TextEntry.validateOnTextChanged`). */
|
|
106
|
+
readonly validateOnTextChanged?: boolean;
|
|
107
|
+
/** A password field (its text is pinned LTR). */
|
|
108
|
+
readonly isPassword?: boolean;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* The state machine behind the text inputs: value ownership, the live filter, the native element sync, focus,
|
|
112
|
+
* validation and dictation. Returns what the input element and the outlined frame need.
|
|
113
|
+
*/
|
|
114
|
+
export declare function useTextInput(props: G9TextInputProps, options: G9TextInputCoreOptions): {
|
|
115
|
+
text: string;
|
|
116
|
+
setText: import("../index.js").G9ControllableSetter<string, [G9ValueChangeDetails]>;
|
|
117
|
+
hasValue: boolean;
|
|
118
|
+
focused: boolean;
|
|
119
|
+
hasError: boolean;
|
|
120
|
+
errorText: string | null | undefined;
|
|
121
|
+
passwordVisible: boolean;
|
|
122
|
+
setPasswordVisible: import("react").Dispatch<import("react").SetStateAction<boolean>>;
|
|
123
|
+
dictation: import("./use-dictation.js").G9DictationState;
|
|
124
|
+
showMic: boolean;
|
|
125
|
+
pressMic: () => void;
|
|
126
|
+
focus: () => void;
|
|
127
|
+
blur: () => boolean;
|
|
128
|
+
handle: G9TextInputHandle;
|
|
129
|
+
inputType: G9InputType;
|
|
130
|
+
/** Element attributes and handlers shared by `<input>` and `<textarea>`. */
|
|
131
|
+
elementProps: {
|
|
132
|
+
'ignore-focus': boolean;
|
|
133
|
+
readonly: boolean;
|
|
134
|
+
disabled: boolean;
|
|
135
|
+
maxlength: number;
|
|
136
|
+
bindinput: (event: {
|
|
137
|
+
detail?: InputDetail;
|
|
138
|
+
}) => void;
|
|
139
|
+
bindfocus: () => void;
|
|
140
|
+
bindblur: () => void;
|
|
141
|
+
bindconfirm: () => void | undefined;
|
|
142
|
+
id?: string;
|
|
143
|
+
ref: (node: NodesRef | null) => void;
|
|
144
|
+
'data-g9keyboard': "target";
|
|
145
|
+
};
|
|
146
|
+
textDirection: "ltr" | "rtl";
|
|
147
|
+
font: string | undefined;
|
|
148
|
+
};
|
|
149
|
+
export {};
|
|
150
|
+
//# sourceMappingURL=use-text-input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-text-input.d.ts","sourceRoot":"","sources":["../../src/fields/use-text-input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,cAAc,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAGvG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAY/C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE7D,OAAO,EAAE,KAAK,eAAe,EAAoB,MAAM,aAAa,CAAC;AAErE,yDAAyD;AACzD,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,WAAW,GAAG,OAAO,GAAG,cAAc,CAAC;AAElF,kCAAkC;AAClC,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;CACtC;AAED,mHAAmH;AACnH,MAAM,WAAW,gBAAiB,SAAQ,oBAAoB;IAC5D,sGAAsG;IACtG,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,qDAAqD;IACrD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAChF,oHAAoH;IACpH,QAAQ,CAAC,YAAY,CAAC,EAAE,cAAc,CAAC;IACvC,2FAA2F;IAC3F,QAAQ,CAAC,SAAS,CAAC,EAAE,WAAW,CAAC;IACjC,uFAAuF;IACvF,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C,wFAAwF;IACxF,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,kHAAkH;IAClH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C,kHAAkH;IAClH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,oBAAoB,CAAC;IACnD,mEAAmE;IACnE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,2GAA2G;IAC3G,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAChC,6EAA6E;IAC7E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9C,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5C,0EAA0E;IAC1E,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,yGAAyG;IACzG,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC/D,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,8CAA8C;IAC9C,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,sDAAsD;IACtD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,kEAAkE;AAClE,MAAM,WAAW,iBAAiB;IAChC,uDAAuD;IACvD,KAAK,IAAI,IAAI,CAAC;IACd,0CAA0C;IAC1C,IAAI,IAAI,IAAI,CAAC;IACb,+GAA+G;IAC/G,QAAQ,IAAI,OAAO,CAAC;IACpB,mDAAmD;IACnD,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,+BAA+B;IAC/B,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,8BAA8B;IAC9B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,qDAAqD;IACrD,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,6GAA6G;IAC7G,QAAQ,CAAC,OAAO,EAAE,SAAS,GAAG,IAAI,CAAC;CACpC;AAED,oDAAoD;AACpD,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC;AAEjC,+BAA+B;AAC/B,UAAU,WAAW;IACnB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,gFAAgF;AAChF,wBAAgB,yBAAyB,CACvC,kBAAkB,EAAE,oBAAoB,EACxC,SAAS,EAAE,WAAW,EACtB,UAAU,EAAE,OAAO,EACnB,gBAAgB,EAAE,KAAK,GAAG,KAAK,GAC9B,KAAK,GAAG,KAAK,CAKf;AAED,sGAAsG;AACtG,wBAAgB,UAAU,CACxB,GAAG,EAAE;IAAE,OAAO,EAAE,SAAS,GAAG,IAAI,CAAA;CAAE,EAClC,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAiBT;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE;IAAE,OAAO,EAAE,SAAS,GAAG,IAAI,CAAA;CAAE,EAClC,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,QAAQ,SAAI,GACX,IAAI,CAGN;AASD,uCAAuC;AACvC,MAAM,WAAW,sBAAsB;IACrC,mFAAmF;IACnF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC;IACpG,sEAAsE;IACtE,QAAQ,CAAC,SAAS,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAC5C,sEAAsE;IACtE,QAAQ,CAAC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IACzC,iDAAiD;IACjD,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,sBAAsB;;;;;;;;;;;;;;;;IAoMjF,4EAA4E;;;;;;2BApGtD;YAAE,MAAM,CAAC,EAAE,WAAW,CAAA;SAAE;;;;;oBAnBnB,QAAQ,GAAG,IAAI;;;;;EAwI7C"}
|