@g9tm/lynxcontrols 1.4.0 → 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 +7 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/base/control.d.ts +24 -0
- package/dist/base/control.d.ts.map +1 -1
- package/dist/base/control.jsx +14 -2
- package/dist/base/control.jsx.map +1 -1
- package/dist/base/index.d.ts +1 -1
- package/dist/base/index.d.ts.map +1 -1
- package/dist/base/index.jsx +1 -1
- package/dist/base/pressable.d.ts.map +1 -1
- package/dist/base/pressable.jsx +1 -1
- package/dist/base/pressable.jsx.map +1 -1
- package/dist/button/button.d.ts.map +1 -1
- package/dist/button/button.jsx +4 -3
- package/dist/button/button.jsx.map +1 -1
- package/dist/button/header-action-button.d.ts.map +1 -1
- package/dist/button/header-action-button.jsx +1 -1
- package/dist/button/header-action-button.jsx.map +1 -1
- package/dist/button/icon-button.d.ts.map +1 -1
- package/dist/button/icon-button.jsx +1 -1
- package/dist/button/icon-button.jsx.map +1 -1
- package/dist/button/nav-card.d.ts.map +1 -1
- package/dist/button/nav-card.jsx +6 -5
- package/dist/button/nav-card.jsx.map +1 -1
- package/dist/button/vertical-icon-text-button.d.ts.map +1 -1
- package/dist/button/vertical-icon-text-button.jsx +1 -1
- package/dist/button/vertical-icon-text-button.jsx.map +1 -1
- package/dist/display/culture-date-time-label.d.ts.map +1 -1
- package/dist/display/culture-date-time-label.jsx +3 -1
- package/dist/display/culture-date-time-label.jsx.map +1 -1
- package/dist/display/progress-bar.jsx +1 -1
- package/dist/display/progress-bar.jsx.map +1 -1
- package/dist/display/separator.jsx +2 -2
- package/dist/display/separator.jsx.map +1 -1
- package/dist/display/title-with-line.jsx +1 -1
- package/dist/display/title-with-line.jsx.map +1 -1
- package/dist/expander/expander.d.ts.map +1 -1
- package/dist/expander/expander.jsx +6 -4
- package/dist/expander/expander.jsx.map +1 -1
- package/dist/fields/fields.css +12 -4
- package/dist/fields/fields.css.map +1 -1
- package/dist/fields/index.d.ts +1 -0
- package/dist/fields/index.d.ts.map +1 -1
- package/dist/fields/index.jsx +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 +7 -1
- package/dist/fields/outlined-field.d.ts.map +1 -1
- package/dist/fields/outlined-field.jsx +8 -5
- package/dist/fields/outlined-field.jsx.map +1 -1
- package/dist/fields/pin-entry.d.ts +2 -0
- package/dist/fields/pin-entry.d.ts.map +1 -1
- package/dist/fields/pin-entry.jsx +2 -1
- package/dist/fields/pin-entry.jsx.map +1 -1
- package/dist/fields/text-entry.d.ts.map +1 -1
- package/dist/fields/text-entry.jsx +12 -2
- package/dist/fields/text-entry.jsx.map +1 -1
- package/dist/fields/use-text-input.d.ts.map +1 -1
- package/dist/fields/use-text-input.jsx +11 -1
- package/dist/fields/use-text-input.jsx.map +1 -1
- package/dist/host/hooks.d.ts +5 -0
- package/dist/host/hooks.d.ts.map +1 -1
- package/dist/host/hooks.jsx +4 -1
- package/dist/host/hooks.jsx.map +1 -1
- package/dist/host/index.d.ts +1 -1
- package/dist/host/index.d.ts.map +1 -1
- package/dist/host/index.jsx +1 -1
- package/dist/popup/frame.d.ts.map +1 -1
- package/dist/popup/frame.jsx +11 -3
- package/dist/popup/frame.jsx.map +1 -1
- package/dist/popup/index.d.ts +1 -1
- package/dist/popup/index.d.ts.map +1 -1
- package/dist/popup/popup.css +1 -1
- package/dist/popup/popup.css.map +1 -1
- package/dist/popup/service.d.ts.map +1 -1
- package/dist/popup/service.jsx +12 -4
- package/dist/popup/service.jsx.map +1 -1
- package/dist/popup/types.d.ts +11 -0
- package/dist/popup/types.d.ts.map +1 -1
- package/dist/popup/types.jsx.map +1 -1
- package/dist/selection/selection-sheet.d.ts.map +1 -1
- package/dist/selection/selection-sheet.jsx +7 -3
- package/dist/selection/selection-sheet.jsx.map +1 -1
- package/dist/selection/selection.css +1 -0
- package/dist/selection/selection.css.map +1 -1
- package/dist/sheet/frame.d.ts +2 -0
- package/dist/sheet/frame.d.ts.map +1 -1
- package/dist/sheet/frame.jsx +134 -69
- package/dist/sheet/frame.jsx.map +1 -1
- 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 +12 -1
- package/dist/sheet/header.d.ts.map +1 -1
- package/dist/sheet/header.jsx +42 -29
- package/dist/sheet/header.jsx.map +1 -1
- package/dist/sheet/index.d.ts +3 -2
- package/dist/sheet/index.d.ts.map +1 -1
- package/dist/sheet/index.jsx +3 -2
- 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 +34 -2
- package/dist/sheet/options.d.ts.map +1 -1
- package/dist/sheet/options.jsx +2 -1
- package/dist/sheet/options.jsx.map +1 -1
- package/dist/sheet/service.d.ts.map +1 -1
- package/dist/sheet/service.jsx +1 -1
- package/dist/sheet/service.jsx.map +1 -1
- package/dist/sheet/sheet.css +52 -1
- package/dist/sheet/sheet.css.map +1 -1
- package/dist/sheet/sizing.d.ts +21 -3
- package/dist/sheet/sizing.d.ts.map +1 -1
- package/dist/sheet/sizing.jsx +15 -2
- package/dist/sheet/sizing.jsx.map +1 -1
- package/dist/tab-bar/tab-bar.d.ts +5 -0
- package/dist/tab-bar/tab-bar.d.ts.map +1 -1
- package/dist/tab-bar/tab-bar.jsx +5 -2
- package/dist/tab-bar/tab-bar.jsx.map +1 -1
- package/dist/toast/service.d.ts.map +1 -1
- package/dist/toast/service.jsx +58 -21
- package/dist/toast/service.jsx.map +1 -1
- package/dist/toast/store.d.ts +2 -0
- package/dist/toast/store.d.ts.map +1 -1
- package/dist/toast/store.jsx +4 -2
- package/dist/toast/store.jsx.map +1 -1
- package/dist/toast/toast.css +20 -13
- package/dist/toast/toast.css.map +1 -1
- package/dist/toggle/checkbox.d.ts.map +1 -1
- package/dist/toggle/checkbox.jsx +1 -1
- package/dist/toggle/checkbox.jsx.map +1 -1
- package/dist/toggle/chip-group.d.ts.map +1 -1
- package/dist/toggle/chip-group.jsx +5 -5
- package/dist/toggle/chip-group.jsx.map +1 -1
- package/dist/toggle/switch.d.ts.map +1 -1
- package/dist/toggle/switch.jsx +2 -2
- package/dist/toggle/switch.jsx.map +1 -1
- package/dist/toggle/toggle.css +1 -2
- package/dist/toggle/toggle.css.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pin-entry.d.ts","sourceRoot":"","sources":["../../src/fields/pin-entry.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pin-entry.d.ts","sourceRoot":"","sources":["../../src/fields/pin-entry.tsx"],"names":[],"mappings":"AACA,OAAO,cAAc,CAAC;AACtB,OAAO,EAAa,cAAc,EAAoB,MAAM,+BAA+B,CAAC;AAiB5F,uDAAuD;AACvD,MAAM,WAAW,eAAe;IAC9B,iGAAiG;IACjG,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,4EAA4E;IAC5E,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,2CAA2C;IAC3C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,qDAAqD;IACrD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,oHAAoH;IACpH,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,kHAAkH;IAClH,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,oFAAoF;IACpF,QAAQ,CAAC,IAAI,CAAC,EAAE,cAAc,CAAC;IAC/B,mDAAmD;IACnD,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,6CAA6C;IAC7C,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,kHAAkH;IAClH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,0CAA0C;IAC1C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,yDAAyD;IACzD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,2DAA2D;IAC3D,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,8CAA8C;IAC9C,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,qFAAqF;IACrF,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,+CAA+C;AAC/C,MAAM,WAAW,gBAAgB;IAC/B,kGAAkG;IAClG,eAAe,IAAI,IAAI,CAAC;IACxB,yCAAyC;IACzC,KAAK,IAAI,IAAI,CAAC;IACd,gDAAgD;IAChD,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAC9B;AAED,iHAAiH;AACjH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,EAAE,CAU3E;AAED,0DAA0D;AAC1D,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAE9E;AAoCD,oHAAoH;AACpH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAS1E;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CASrG;AAgBD;;;;;GAKG;AACH,eAAO,MAAM,UAAU,8GA+KrB,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { g9IdProps } from "../base/control.jsx";
|
|
1
2
|
import "./fields.css";
|
|
2
3
|
import { G9Metrics, G9PinEntryType, normalizeToAscii } from "@g9tm/lynxcontrols-foundation";
|
|
3
4
|
import { KeyboardAwareTriggerContext } from "@lynx-js/lynx-ui-input";
|
|
@@ -275,7 +276,7 @@ const pin_entry_G9PinEntry = forwardRef(function(props, ref) {
|
|
|
275
276
|
inGroup = 0;
|
|
276
277
|
}
|
|
277
278
|
}
|
|
278
|
-
return <view {...g9KeyboardTargetProps} className={`g9-pin g9-dir-ltr${props.disabled ? ' g9-pin--disabled' : ''}${complete ? ' g9-pin--complete' : ''}${props.className ? ` ${props.className}` : ''}`} accessibility-element={true} accessibility-label={`${props.accessibilityLabel ? `${props.accessibilityLabel}, ` : ''}${chars.length} / ${cells}`} bindtap={focus}>
|
|
279
|
+
return <view {...g9KeyboardTargetProps} className={`g9-pin g9-dir-ltr${props.disabled ? ' g9-pin--disabled' : ''}${complete ? ' g9-pin--complete' : ''}${props.className ? ` ${props.className}` : ''}`} {...g9IdProps(props.id)} accessibility-element={true} accessibility-label={`${props.accessibilityLabel ? `${props.accessibilityLabel}, ` : ''}${chars.length} / ${cells}`} bindtap={focus}>
|
|
279
280
|
{row}
|
|
280
281
|
<input {...g9KeyboardTargetProps} ref={attach} className="g9-pin__input" android-fullscreen-mode={false} ignore-focus={true} confirm-type="done" disabled={true === props.disabled} maxlength={cells} ios-auto-correct={false} ios-spell-check={false} type={type === G9PinEntryType.Number || type === G9PinEntryType.Password ? 'number' : 'text'} style={hiddenInputStyle} bindinput={onInput} bindfocus={()=>{
|
|
281
282
|
var _keyboardAware_onInputFocused;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fields/pin-entry.jsx","sources":["../../src/fields/pin-entry.tsx"],"sourcesContent":["import './fields.css';\nimport { G9Metrics, G9PinEntryType, normalizeToAscii } from '@g9tm/lynxcontrols-foundation';\nimport { KeyboardAwareTriggerContext } from '@lynx-js/lynx-ui-input';\nimport {\n forwardRef,\n type ReactNode,\n useContext,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from '@lynx-js/react';\nimport type { NodesRef } from '@lynx-js/types';\nimport { startTimer } from '../base/timers';\nimport { useControllableState } from '../base/use-controllable-state';\nimport { g9KeyboardTargetProps } from '../host/keyboard';\nimport { invokeNode, invokeNodeWhenReady } from './use-text-input';\n\n/** Props of {@link G9PinEntry} (MAUI `G9PinEntry`). */\nexport interface G9PinEntryProps {\n /** Number of cells when `groupSizes` is not set (at least 1). Default 4. */\n readonly length?: number;\n /** The code (controlled; MAUI `Value`). */\n readonly value?: string;\n /** Initial code while uncontrolled. Default `''`. */\n readonly defaultValue?: string;\n /** Once per change of the code (MAUI `ValueChanged`): typing, paste, `clear()`, a re-filter after a type change. */\n readonly onValueChange?: (value: string) => void;\n /** Once each time the code becomes complete (MAUI `Completed`); not for a complete value the parent pushes in. */\n readonly onComplete?: (value: string) => void;\n /** Accepted characters; `'password'` is digits shown masked. Default `'number'`. */\n readonly type?: G9PinEntryType;\n /** Filler glyph of an empty cell. Default none. */\n readonly placeholder?: string | null;\n /** Glyph of a masked cell. Default `'●'`. */\n readonly maskCharacter?: string;\n /** Cell groups such as `'4-4-4-4'`; when set, their sum is the cell count and `separator` sits between groups. */\n readonly groupSizes?: string | null;\n /** Text between groups. Default `'-'`. */\n readonly separator?: string | null;\n /** Cell width. Default 44 (`G9Metrics.PinCellWidth`). */\n readonly cellWidth?: number;\n /** Cell height. Default 52 (`G9Metrics.PinCellHeight`). */\n readonly cellHeight?: number;\n /** Focus once when mounted. Default false. */\n readonly autoFocus?: boolean;\n readonly disabled?: boolean;\n /** Accessibility label of the row (the progress `n / total` is always announced). */\n readonly accessibilityLabel?: string;\n readonly className?: string;\n}\n\n/** Imperative handle of {@link G9PinEntry}. */\nexport interface G9PinEntryHandle {\n /** Focuses the hidden input; typing appends after the last character (MAUI `FocusFirstEmpty`). */\n focusFirstEmpty(): void;\n /** Empties every cell (MAUI `Clear`). */\n clear(): void;\n /** Every cell is filled (MAUI `IsComplete`). */\n readonly isComplete: boolean;\n}\n\n/** Parses `'4-3-3-2'` into positive group sizes; blanks and non-numbers are skipped (MAUI `ParseGroupSizes`). */\nexport function parsePinGroupSizes(raw: string | null | undefined): number[] {\n if (raw == null || raw.trim() === '') return [];\n const out: number[] = [];\n for (const part of raw.split('-')) {\n const trimmed = part.trim();\n if (!/^[+]?\\d+$/.test(trimmed)) continue;\n const n = Number(trimmed);\n if (n > 0) out.push(n);\n }\n return out;\n}\n\n/** Cell count: the groups' sum, else `max(1, length)`. */\nexport function pinCellCount(length: number, groups: readonly number[]): number {\n return groups.length > 0 ? groups.reduce((a, b) => a + b, 0) : Math.max(1, length);\n}\n\n// Lynx's JavaScript engine rejects Unicode property escapes (`/\\p{Nd}/u`), so `char.IsDigit` / `char.IsLetter` are\n// spelled out: the zero code points of every BMP decimal-digit block (Unicode category Nd), and \"letter\" as a cased\n// character or one of the uncased letter blocks forms meet (Arabic/Persian, Hebrew, Indic, Thai, CJK, kana, Hangul).\nconst digitZeros = [\n 0x30, 0x660, 0x6f0, 0x7c0, 0x966, 0x9e6, 0xa66, 0xae6, 0xb66, 0xbe6, 0xc66, 0xce6, 0xd66, 0xde6, 0xe50, 0xed0, 0xf20,\n 0x1040, 0x1090, 0x17e0, 0x1810, 0x1946, 0x19d0, 0x1a80, 0x1a90, 0x1b50, 0x1bb0, 0x1c40, 0x1c50, 0xa620, 0xa8d0,\n 0xa900, 0xa9d0, 0xa9f0, 0xaa50, 0xabf0, 0xff10,\n];\nconst uncasedLetterRanges: ReadonlyArray<readonly [number, number]> = [\n [0x5d0, 0x5ea],\n [0x620, 0x64a],\n [0x66e, 0x6d3],\n [0x6fa, 0x6ff],\n [0x904, 0x939],\n [0xe01, 0xe30],\n [0x3041, 0x30ff],\n [0x3400, 0x4dbf],\n [0x4e00, 0x9fff],\n [0xac00, 0xd7a3],\n];\n\nfunction isUnicodeDigit(ch: string): boolean {\n const c = ch.charCodeAt(0);\n for (const zero of digitZeros) if (c >= zero && c <= zero + 9) return true;\n return false;\n}\n\nfunction isUnicodeLetter(ch: string): boolean {\n if (ch.toLowerCase() !== ch.toUpperCase()) return true;\n const c = ch.charCodeAt(0);\n for (const [from, to] of uncasedLetterRanges) if (c >= from && c <= to) return true;\n return false;\n}\n\n/** Whether the PIN type accepts a character (MAUI `IsAllowed`: `char.IsDigit` / `IsLetter` / `IsLetterOrDigit`). */\nexport function isPinCharAllowed(type: G9PinEntryType, ch: string): boolean {\n switch (type) {\n case G9PinEntryType.Letters:\n return isUnicodeLetter(ch);\n case G9PinEntryType.Alphanumeric:\n return isUnicodeLetter(ch) || isUnicodeDigit(ch);\n default:\n return isUnicodeDigit(ch);\n }\n}\n\n/**\n * Filters and clamps a code (MAUI `FilterAndClamp`): Persian and Arabic-Indic digits become ASCII, disallowed\n * characters are dropped, the rest is cut to `cells`.\n */\nexport function filterPin(raw: string | null | undefined, type: G9PinEntryType, cells: number): string {\n if (!raw) return '';\n let out = '';\n for (const typed of Array.from(raw)) {\n if (Array.from(out).length >= cells) break;\n const ch = normalizeToAscii(typed);\n if (isPinCharAllowed(type, ch)) out += ch;\n }\n return out;\n}\n\nconst hiddenInputStyle = {\n position: 'absolute',\n top: '0px',\n left: '0px',\n width: '1px',\n height: '1px',\n padding: '0px',\n borderWidth: '0px',\n opacity: 0,\n color: 'transparent',\n caretColor: 'transparent',\n backgroundColor: 'transparent',\n} as const;\n\n/**\n * One-time-code / PIN entry (MAUI `G9PinEntry`): a row of cells over one hidden `<input>` (the lynx-ui `InputOTP`\n * pattern). Append-only: typing fills the next cell, backspace empties the last, a tap anywhere focuses the end.\n * Paste is filtered and clamped. Digits are stored as ASCII whatever keyboard produced them. Masked with\n * `type: 'password'`. Requires the host's `xelement-input` registration.\n */\nexport const G9PinEntry = forwardRef<G9PinEntryHandle, G9PinEntryProps>(function G9PinEntry(props, ref): ReactNode {\n const keyboardAware = useContext(KeyboardAwareTriggerContext);\n const type = props.type ?? G9PinEntryType.Number;\n const groups = parsePinGroupSizes(props.groupSizes);\n const cells = pinCellCount(props.length ?? 4, groups);\n const [value, setValue] = useControllableState<string>({\n value: props.value,\n defaultValue: props.defaultValue ?? '',\n onChange: props.onValueChange,\n name: 'G9PinEntry.value',\n });\n const clean = filterPin(value, type, cells);\n const chars = Array.from(clean);\n const complete = chars.length === cells;\n const [focused, setFocused] = useState(false);\n const inputRef = useRef<NodesRef | null>(null);\n const native = useRef('');\n const completedFired = useRef(complete);\n const latest = useRef(clean);\n latest.current = clean;\n const [, bump] = useState(0);\n\n // A pushed value the filter rejects is replaced once; a pushed complete value never fires `onComplete`.\n const refiltered = useRef<string | null>(null);\n useEffect(() => {\n if (clean !== value && refiltered.current !== value) {\n refiltered.current = value;\n setValue(clean);\n }\n });\n const lastSeen = useRef(clean);\n if (lastSeen.current !== clean) {\n lastSeen.current = clean;\n if (!complete) completedFired.current = false;\n }\n const retries = useRef(0);\n const sync = () => {\n const current = latest.current;\n if (native.current === current) return;\n if (invokeNode(inputRef, 'setValue', { value: current })) {\n native.current = current;\n retries.current = 0;\n } else if (inputRef.current && retries.current < 5) {\n retries.current += 1;\n startTimer(() => syncRef.current(), 0);\n }\n };\n const syncRef = useRef(sync);\n syncRef.current = sync;\n const attach = useRef((node: NodesRef | null) => {\n inputRef.current = node;\n if (node) syncRef.current();\n }).current;\n useEffect(() => {\n sync();\n });\n\n const focus = () => {\n if (props.disabled) return;\n invokeNode(inputRef, 'focus');\n invokeNode(inputRef, 'setSelectionRange', { selectionStart: chars.length, selectionEnd: chars.length });\n };\n const clear = () => {\n latest.current = '';\n completedFired.current = false;\n setValue('');\n bump((n) => n + 1);\n };\n useImperativeHandle(ref, () => ({\n focusFirstEmpty: focus,\n clear,\n get isComplete() {\n return Array.from(latest.current).length === cells;\n },\n }));\n\n const autoFocused = useRef(false);\n useEffect(() => {\n if (props.autoFocus && !autoFocused.current && !props.disabled) {\n autoFocused.current = true;\n invokeNodeWhenReady(inputRef, 'focus');\n }\n });\n\n const onInput = (event: { detail?: { value?: string } }) => {\n const raw = event.detail?.value ?? '';\n native.current = raw;\n const next = filterPin(raw, type, cells);\n latest.current = next;\n lastSeen.current = next;\n setValue(next);\n const ready = Array.from(next).length === cells;\n if (ready && !completedFired.current) {\n completedFired.current = true;\n props.onComplete?.(next);\n } else if (!ready) {\n completedFired.current = false;\n }\n bump((n) => n + 1);\n };\n\n const cellWidth = props.cellWidth && props.cellWidth > 0 ? props.cellWidth : G9Metrics.PinCellWidth;\n const cellHeight = props.cellHeight && props.cellHeight > 0 ? props.cellHeight : G9Metrics.PinCellHeight;\n const active = focused ? Math.min(chars.length, cells - 1) : -1;\n const separator = props.separator ?? '';\n const row: ReactNode[] = [];\n let groupIndex = 0;\n let inGroup = 0;\n for (let i = 0; i < cells; i++) {\n const ch = chars[i];\n const state = i === active ? 'active' : ch !== undefined ? 'filled' : 'empty';\n row.push(\n <view\n key={`c${i}`}\n className={`g9-pin__cell g9-pin__cell--${state}`}\n style={{ width: `${cellWidth}px`, height: `${cellHeight}px` }}\n >\n <text className={ch !== undefined ? 'g9-pin__char' : 'g9-pin__placeholder'}>\n {ch !== undefined\n ? type === G9PinEntryType.Password\n ? (props.maskCharacter ?? '●')\n : ch\n : (props.placeholder ?? '')}\n </text>\n </view>,\n );\n inGroup++;\n if (groups.length > 0 && groupIndex < groups.length - 1 && inGroup === groups[groupIndex]) {\n if (separator !== '') {\n row.push(\n <text key={`s${groupIndex}`} className=\"g9-pin__separator\">\n {separator}\n </text>,\n );\n }\n groupIndex++;\n inGroup = 0;\n }\n }\n\n return (\n <view\n {...g9KeyboardTargetProps}\n className={`g9-pin g9-dir-ltr${props.disabled ? ' g9-pin--disabled' : ''}${complete ? ' g9-pin--complete' : ''}${props.className ? ` ${props.className}` : ''}`}\n accessibility-element={true}\n accessibility-label={`${props.accessibilityLabel ? `${props.accessibilityLabel}, ` : ''}${chars.length} / ${cells}`}\n bindtap={focus}\n >\n {row}\n <input\n {...g9KeyboardTargetProps}\n ref={attach}\n className=\"g9-pin__input\"\n android-fullscreen-mode={false}\n ignore-focus={true}\n confirm-type=\"done\"\n disabled={props.disabled === true}\n maxlength={cells}\n ios-auto-correct={false}\n ios-spell-check={false}\n type={type === G9PinEntryType.Number || type === G9PinEntryType.Password ? 'number' : 'text'}\n style={hiddenInputStyle}\n bindinput={onInput}\n bindfocus={() => {\n setFocused(true);\n keyboardAware.onInputFocused?.();\n }}\n bindblur={() => {\n setFocused(false);\n keyboardAware.onInputBlurred?.();\n }}\n />\n </view>\n );\n});\n"],"names":["parsePinGroupSizes","raw","out","part","trimmed","n","Number","pinCellCount","length","groups","a","b","Math","digitZeros","uncasedLetterRanges","isUnicodeDigit","ch","c","zero","isUnicodeLetter","from","to","isPinCharAllowed","type","G9PinEntryType","filterPin","cells","typed","Array","normalizeToAscii","hiddenInputStyle","G9PinEntry","forwardRef","props","ref","_props_type","_props_length","_props_defaultValue","_props_separator","keyboardAware","useContext","KeyboardAwareTriggerContext","value","setValue","useControllableState","clean","chars","complete","focused","setFocused","useState","inputRef","useRef","native","completedFired","latest","bump","refiltered","useEffect","lastSeen","retries","sync","current","invokeNode","startTimer","syncRef","attach","node","focus","clear","useImperativeHandle","autoFocused","invokeNodeWhenReady","onInput","event","_event_detail","next","ready","cellWidth","G9Metrics","cellHeight","active","separator","row","groupIndex","inGroup","i","_props_maskCharacter","_props_placeholder","state","undefined","view","text","g9KeyboardTargetProps","input"],"mappings":";;;;;;;;AA+DO,SAASA,mBAAmBC,GAA8B;IAC/D,IAAIA,AAAO,QAAPA,OAAeA,AAAe,OAAfA,IAAI,IAAI,IAAW,OAAO,EAAE;IAC/C,MAAMC,MAAgB,EAAE;IACxB,KAAK,MAAMC,QAAQF,IAAI,KAAK,CAAC,KAAM;QACjC,MAAMG,UAAUD,KAAK,IAAI;QACzB,IAAI,CAAC,YAAY,IAAI,CAACC,UAAU;QAChC,MAAMC,IAAIC,OAAOF;QACjB,IAAIC,IAAI,GAAGH,IAAI,IAAI,CAACG;IACtB;IACA,OAAOH;AACT;AAGO,SAASK,aAAaC,MAAc,EAAEC,MAAyB;IACpE,OAAOA,OAAO,MAAM,GAAG,IAAIA,OAAO,MAAM,CAAC,CAACC,GAAGC,IAAMD,IAAIC,GAAG,KAAKC,KAAK,GAAG,CAAC,GAAGJ;AAC7E;AAKA,MAAMK,aAAa;IACjB;IAAM;IAAO;IAAO;IAAO;IAAO;IAAO;IAAO;IAAO;IAAO;IAAO;IAAO;IAAO;IAAO;IAAO;IAAO;IAAO;IAC/G;IAAQ;IAAQ;IAAQ;IAAQ;IAAQ;IAAQ;IAAQ;IAAQ;IAAQ;IAAQ;IAAQ;IAAQ;IAAQ;IACxG;IAAQ;IAAQ;IAAQ;IAAQ;IAAQ;CACzC;AACD,MAAMC,sBAAgE;IACpE;QAAC;QAAO;KAAM;IACd;QAAC;QAAO;KAAM;IACd;QAAC;QAAO;KAAM;IACd;QAAC;QAAO;KAAM;IACd;QAAC;QAAO;KAAM;IACd;QAAC;QAAO;KAAM;IACd;QAAC;QAAQ;KAAO;IAChB;QAAC;QAAQ;KAAO;IAChB;QAAC;QAAQ;KAAO;IAChB;QAAC;QAAQ;KAAO;CACjB;AAED,SAASC,eAAeC,EAAU;IAChC,MAAMC,IAAID,GAAG,UAAU,CAAC;IACxB,KAAK,MAAME,QAAQL,WAAY,IAAII,KAAKC,QAAQD,KAAKC,OAAO,GAAG,OAAO;IACtE,OAAO;AACT;AAEA,SAASC,gBAAgBH,EAAU;IACjC,IAAIA,GAAG,WAAW,OAAOA,GAAG,WAAW,IAAI,OAAO;IAClD,MAAMC,IAAID,GAAG,UAAU,CAAC;IACxB,KAAK,MAAM,CAACI,MAAMC,GAAG,IAAIP,oBAAqB,IAAIG,KAAKG,QAAQH,KAAKI,IAAI,OAAO;IAC/E,OAAO;AACT;AAGO,SAASC,iBAAiBC,IAAoB,EAAEP,EAAU;IAC/D,OAAQO;QACN,KAAKC,eAAe,OAAO;YACzB,OAAOL,gBAAgBH;QACzB,KAAKQ,eAAe,YAAY;YAC9B,OAAOL,gBAAgBH,OAAOD,eAAeC;QAC/C;YACE,OAAOD,eAAeC;IAC1B;AACF;AAMO,SAASS,UAAUxB,GAA8B,EAAEsB,IAAoB,EAAEG,KAAa;IAC3F,IAAI,CAACzB,KAAK,OAAO;IACjB,IAAIC,MAAM;IACV,KAAK,MAAMyB,SAASC,MAAM,IAAI,CAAC3B,KAAM;QACnC,IAAI2B,MAAM,IAAI,CAAC1B,KAAK,MAAM,IAAIwB,OAAO;QACrC,MAAMV,KAAKa,iBAAiBF;QAC5B,IAAIL,iBAAiBC,MAAMP,KAAKd,OAAOc;IACzC;IACA,OAAOd;AACT;AAEA,MAAM4B,mBAAmB;IACvB,UAAU;IACV,KAAK;IACL,MAAM;IACN,OAAO;IACP,QAAQ;IACR,SAAS;IACT,aAAa;IACb,SAAS;IACT,OAAO;IACP,YAAY;IACZ,iBAAiB;AACnB;AAQO,MAAMC,uBAAaC,WAA8C,SAAoBC,KAAK,EAAEC,GAAG;QAEvFC,aAEcC,eAGXC,qBAiGEC;IAvGlB,MAAMC,gBAAgBC,WAAWC;IACjC,MAAMlB,OAAO,QAAAY,CAAAA,cAAAA,MAAM,IAAI,AAAD,IAATA,cAAcX,eAAe,MAAM;IAChD,MAAMf,SAAST,mBAAmBiC,MAAM,UAAU;IAClD,MAAMP,QAAQnB,aAAa,QAAA6B,CAAAA,gBAAAA,MAAM,MAAM,AAAD,IAAXA,gBAAgB,GAAG3B;IAC9C,MAAM,CAACiC,OAAOC,SAAS,GAAGC,qBAA6B;QACrD,OAAOX,MAAM,KAAK;QAClB,cAAc,QAAAI,CAAAA,sBAAAA,MAAM,YAAY,AAAD,IAAjBA,sBAAsB;QACpC,UAAUJ,MAAM,aAAa;QAC7B,MAAM;IACR;IACA,MAAMY,QAAQpB,UAAUiB,OAAOnB,MAAMG;IACrC,MAAMoB,QAAQlB,MAAM,IAAI,CAACiB;IACzB,MAAME,WAAWD,MAAM,MAAM,KAAKpB;IAClC,MAAM,CAACsB,SAASC,WAAW,GAAGC,SAAS;IACvC,MAAMC,WAAWC,OAAwB;IACzC,MAAMC,SAASD,OAAO;IACtB,MAAME,iBAAiBF,OAAOL;IAC9B,MAAMQ,SAASH,OAAOP;IACtBU,OAAO,OAAO,GAAGV;IACjB,MAAM,GAAGW,KAAK,GAAGN,SAAS;IAG1B,MAAMO,aAAaL,OAAsB;IACzCM,UAAU;QACR,IAAIb,UAAUH,SAASe,WAAW,OAAO,KAAKf,OAAO;YACnDe,WAAW,OAAO,GAAGf;YACrBC,SAASE;QACX;IACF;IACA,MAAMc,WAAWP,OAAOP;IACxB,IAAIc,SAAS,OAAO,KAAKd,OAAO;QAC9Bc,SAAS,OAAO,GAAGd;QACnB,IAAI,CAACE,UAAUO,eAAe,OAAO,GAAG;IAC1C;IACA,MAAMM,UAAUR,OAAO;IACvB,MAAMS,OAAO;QACX,MAAMC,UAAUP,OAAO,OAAO;QAC9B,IAAIF,OAAO,OAAO,KAAKS,SAAS;QAChC,IAAIC,WAAWZ,UAAU,YAAY;YAAE,OAAOW;QAAQ,IAAI;YACxDT,OAAO,OAAO,GAAGS;YACjBF,QAAQ,OAAO,GAAG;QACpB,OAAO,IAAIT,SAAS,OAAO,IAAIS,QAAQ,OAAO,GAAG,GAAG;YAClDA,QAAQ,OAAO,IAAI;YACnBI,WAAW,IAAMC,QAAQ,OAAO,IAAI;QACtC;IACF;IACA,MAAMA,UAAUb,OAAOS;IACvBI,QAAQ,OAAO,GAAGJ;IAClB,MAAMK,SAASd,OAAO,CAACe;QACrBhB,SAAS,OAAO,GAAGgB;QACnB,IAAIA,MAAMF,QAAQ,OAAO;IAC3B,GAAG,OAAO;IACVP,UAAU;QACRG;IACF;IAEA,MAAMO,QAAQ;QACZ,IAAInC,MAAM,QAAQ,EAAE;QACpB8B,WAAWZ,UAAU;QACrBY,WAAWZ,UAAU,qBAAqB;YAAE,gBAAgBL,MAAM,MAAM;YAAE,cAAcA,MAAM,MAAM;QAAC;IACvG;IACA,MAAMuB,QAAQ;QACZd,OAAO,OAAO,GAAG;QACjBD,eAAe,OAAO,GAAG;QACzBX,SAAS;QACTa,KAAK,CAACnD,IAAMA,IAAI;IAClB;IACAiE,oBAAoBpC,KAAK,IAAO;YAC9B,iBAAiBkC;YACjBC;YACA,IAAI;gBACF,OAAOzC,MAAM,IAAI,CAAC2B,OAAO,OAAO,EAAE,MAAM,KAAK7B;YAC/C;QACF;IAEA,MAAM6C,cAAcnB,OAAO;IAC3BM,UAAU;QACR,IAAIzB,MAAM,SAAS,IAAI,CAACsC,YAAY,OAAO,IAAI,CAACtC,MAAM,QAAQ,EAAE;YAC9DsC,YAAY,OAAO,GAAG;YACtBC,oBAAoBrB,UAAU;QAChC;IACF;IAEA,MAAMsB,UAAU,CAACC;;YACHC;QAAZ,MAAM1E,MAAM,QAANA,CAAAA,OAAAA,QAAM0E,CAAAA,gBAAAA,MAAM,MAAM,AAAD,IAAXA,KAAAA,IAAAA,cAAc,KAAK,AAAD,IAAC,OAAI;QACnCtB,OAAO,OAAO,GAAGpD;QACjB,MAAM2E,OAAOnD,UAAUxB,KAAKsB,MAAMG;QAClC6B,OAAO,OAAO,GAAGqB;QACjBjB,SAAS,OAAO,GAAGiB;QACnBjC,SAASiC;QACT,MAAMC,QAAQjD,MAAM,IAAI,CAACgD,MAAM,MAAM,KAAKlD;QAC1C,IAAImD,SAAS,CAACvB,eAAe,OAAO,EAAE;gBAEpCrB;YADAqB,eAAe,OAAO,GAAG;oBACzBrB,CAAAA,oBAAAA,MAAM,UAAU,AAAD,KAAfA,kBAAAA,IAAAA,CAAAA,OAAmB2C;QACrB,OAAO,IAAI,CAACC,OACVvB,eAAe,OAAO,GAAG;QAE3BE,KAAK,CAACnD,IAAMA,IAAI;IAClB;IAEA,MAAMyE,YAAY7C,MAAM,SAAS,IAAIA,MAAM,SAAS,GAAG,IAAIA,MAAM,SAAS,GAAG8C,UAAU,YAAY;IACnG,MAAMC,aAAa/C,MAAM,UAAU,IAAIA,MAAM,UAAU,GAAG,IAAIA,MAAM,UAAU,GAAG8C,UAAU,aAAa;IACxG,MAAME,SAASjC,UAAUpC,KAAK,GAAG,CAACkC,MAAM,MAAM,EAAEpB,QAAQ,KAAK;IAC7D,MAAMwD,YAAY,QAAA5C,CAAAA,mBAAAA,MAAM,SAAS,AAAD,IAAdA,mBAAmB;IACrC,MAAM6C,MAAmB,EAAE;IAC3B,IAAIC,aAAa;IACjB,IAAIC,UAAU;IACd,IAAK,IAAIC,IAAI,GAAGA,IAAI5D,OAAO4D,IAAK;YAYjBC,sBAEFC;QAbX,MAAMxE,KAAK8B,KAAK,CAACwC,EAAE;QACnB,MAAMG,QAAQH,MAAML,SAAS,WAAWjE,AAAO0E,WAAP1E,KAAmB,WAAW;QACtEmE,IAAI,IAAI,EACLQ,KACC,KAAK,CAAC,CAAC,EAAEL,GAAG,EACZ,WAAW,CAAC,2BAA2B,EAAEG,OAAO,EAChD,OAAO;YAAE,OAAO,GAAGX,UAAU,EAAE,CAAC;YAAE,QAAQ,GAAGE,WAAW,EAAE,CAAC;QAAC,GAC7D;QACC,CAACY,KAAK,WAAW5E,AAAO0E,WAAP1E,KAAmB,iBAAiB,uBAAuB;UAC1E,CAACA,AAAO0E,WAAP1E,KACGO,SAASC,eAAe,QAAQ,WAC7B+D,CAAAA,uBAAAA,MAAM,aAAa,AAAD,IAAlBA,uBAAuB,MACxBvE,KAAAA,QACDwE,CAAAA,qBAAAA,MAAM,WAAW,AAAD,IAAhBA,qBAAqB,GAAI;QAChC,EAAEI,KAAK;MACT,EAAED;QAEJN;QACA,IAAI5E,OAAO,MAAM,GAAG,KAAK2E,aAAa3E,OAAO,MAAM,GAAG,KAAK4E,YAAY5E,MAAM,CAAC2E,WAAW,EAAE;YACzF,IAAIF,AAAc,OAAdA,WACFC,IAAI,IAAI,EACLS,KAAK,KAAK,CAAC,CAAC,EAAER,YAAY,EAAE,UAAU,oBAAoB;YACzD,CAACF,UAAU;UACb,EAAEU;YAGNR;YACAC,UAAU;QACZ;IACF;IAEA,QACGM,MACE,GAAGE,qBAAqB,EACzB,WAAW,CAAC,iBAAiB,EAAE5D,MAAM,QAAQ,GAAG,sBAAsB,KAAKc,WAAW,sBAAsB,KAAKd,MAAM,SAAS,GAAG,CAAC,CAAC,EAAEA,MAAM,SAAS,EAAE,GAAG,IAAI,EAC/J,uBAAuB,MACvB,qBAAqB,GAAGA,MAAM,kBAAkB,GAAG,GAAGA,MAAM,kBAAkB,CAAC,EAAE,CAAC,GAAG,KAAKa,MAAM,MAAM,CAAC,GAAG,EAAEpB,OAAO,EACnH,SAAS0C,OACV;MACC,CAACe,IAAI;MACL,CAACW,OACE,GAAGD,qBAAqB,EACzB,KAAK3B,QACL,UAAU,gBACV,yBAAyB,OACzB,cAAc,MACd,aAAa,OACb,UAAUjC,AAAmB,SAAnBA,MAAM,QAAQ,EACxB,WAAWP,OACX,kBAAkB,OAClB,iBAAiB,OACjB,MAAMH,SAASC,eAAe,MAAM,IAAID,SAASC,eAAe,QAAQ,GAAG,WAAW,QACtF,OAAOM,kBACP,WAAW2C,SACX,WAAW;YAETlC;QADAU,WAAW;gBACXV,CAAAA,gCAAAA,cAAc,cAAc,AAAD,KAA3BA,8BAAAA,IAAAA,CAAAA;IACF,GACA,UAAU;YAERA;QADAU,WAAW;gBACXV,CAAAA,gCAAAA,cAAc,cAAc,AAAD,KAA3BA,8BAAAA,IAAAA,CAAAA;IACF,IACA;IACJ,EAAEoD;AAEN"}
|
|
1
|
+
{"version":3,"file":"fields/pin-entry.jsx","sources":["../../src/fields/pin-entry.tsx"],"sourcesContent":["import { g9IdProps } from '../base/control';\nimport './fields.css';\nimport { G9Metrics, G9PinEntryType, normalizeToAscii } from '@g9tm/lynxcontrols-foundation';\nimport { KeyboardAwareTriggerContext } from '@lynx-js/lynx-ui-input';\nimport {\n forwardRef,\n type ReactNode,\n useContext,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from '@lynx-js/react';\nimport type { NodesRef } from '@lynx-js/types';\nimport { startTimer } from '../base/timers';\nimport { useControllableState } from '../base/use-controllable-state';\nimport { g9KeyboardTargetProps } from '../host/keyboard';\nimport { invokeNode, invokeNodeWhenReady } from './use-text-input';\n\n/** Props of {@link G9PinEntry} (MAUI `G9PinEntry`). */\nexport interface G9PinEntryProps {\n /** Element `id` of the root (MAUI `AutomationId`). Used verbatim: keep it to `[A-Za-z0-9_-]`. */\n readonly id?: string;\n /** Number of cells when `groupSizes` is not set (at least 1). Default 4. */\n readonly length?: number;\n /** The code (controlled; MAUI `Value`). */\n readonly value?: string;\n /** Initial code while uncontrolled. Default `''`. */\n readonly defaultValue?: string;\n /** Once per change of the code (MAUI `ValueChanged`): typing, paste, `clear()`, a re-filter after a type change. */\n readonly onValueChange?: (value: string) => void;\n /** Once each time the code becomes complete (MAUI `Completed`); not for a complete value the parent pushes in. */\n readonly onComplete?: (value: string) => void;\n /** Accepted characters; `'password'` is digits shown masked. Default `'number'`. */\n readonly type?: G9PinEntryType;\n /** Filler glyph of an empty cell. Default none. */\n readonly placeholder?: string | null;\n /** Glyph of a masked cell. Default `'●'`. */\n readonly maskCharacter?: string;\n /** Cell groups such as `'4-4-4-4'`; when set, their sum is the cell count and `separator` sits between groups. */\n readonly groupSizes?: string | null;\n /** Text between groups. Default `'-'`. */\n readonly separator?: string | null;\n /** Cell width. Default 44 (`G9Metrics.PinCellWidth`). */\n readonly cellWidth?: number;\n /** Cell height. Default 52 (`G9Metrics.PinCellHeight`). */\n readonly cellHeight?: number;\n /** Focus once when mounted. Default false. */\n readonly autoFocus?: boolean;\n readonly disabled?: boolean;\n /** Accessibility label of the row (the progress `n / total` is always announced). */\n readonly accessibilityLabel?: string;\n readonly className?: string;\n}\n\n/** Imperative handle of {@link G9PinEntry}. */\nexport interface G9PinEntryHandle {\n /** Focuses the hidden input; typing appends after the last character (MAUI `FocusFirstEmpty`). */\n focusFirstEmpty(): void;\n /** Empties every cell (MAUI `Clear`). */\n clear(): void;\n /** Every cell is filled (MAUI `IsComplete`). */\n readonly isComplete: boolean;\n}\n\n/** Parses `'4-3-3-2'` into positive group sizes; blanks and non-numbers are skipped (MAUI `ParseGroupSizes`). */\nexport function parsePinGroupSizes(raw: string | null | undefined): number[] {\n if (raw == null || raw.trim() === '') return [];\n const out: number[] = [];\n for (const part of raw.split('-')) {\n const trimmed = part.trim();\n if (!/^[+]?\\d+$/.test(trimmed)) continue;\n const n = Number(trimmed);\n if (n > 0) out.push(n);\n }\n return out;\n}\n\n/** Cell count: the groups' sum, else `max(1, length)`. */\nexport function pinCellCount(length: number, groups: readonly number[]): number {\n return groups.length > 0 ? groups.reduce((a, b) => a + b, 0) : Math.max(1, length);\n}\n\n// Lynx's JavaScript engine rejects Unicode property escapes (`/\\p{Nd}/u`), so `char.IsDigit` / `char.IsLetter` are\n// spelled out: the zero code points of every BMP decimal-digit block (Unicode category Nd), and \"letter\" as a cased\n// character or one of the uncased letter blocks forms meet (Arabic/Persian, Hebrew, Indic, Thai, CJK, kana, Hangul).\nconst digitZeros = [\n 0x30, 0x660, 0x6f0, 0x7c0, 0x966, 0x9e6, 0xa66, 0xae6, 0xb66, 0xbe6, 0xc66, 0xce6, 0xd66, 0xde6, 0xe50, 0xed0, 0xf20,\n 0x1040, 0x1090, 0x17e0, 0x1810, 0x1946, 0x19d0, 0x1a80, 0x1a90, 0x1b50, 0x1bb0, 0x1c40, 0x1c50, 0xa620, 0xa8d0,\n 0xa900, 0xa9d0, 0xa9f0, 0xaa50, 0xabf0, 0xff10,\n];\nconst uncasedLetterRanges: ReadonlyArray<readonly [number, number]> = [\n [0x5d0, 0x5ea],\n [0x620, 0x64a],\n [0x66e, 0x6d3],\n [0x6fa, 0x6ff],\n [0x904, 0x939],\n [0xe01, 0xe30],\n [0x3041, 0x30ff],\n [0x3400, 0x4dbf],\n [0x4e00, 0x9fff],\n [0xac00, 0xd7a3],\n];\n\nfunction isUnicodeDigit(ch: string): boolean {\n const c = ch.charCodeAt(0);\n for (const zero of digitZeros) if (c >= zero && c <= zero + 9) return true;\n return false;\n}\n\nfunction isUnicodeLetter(ch: string): boolean {\n if (ch.toLowerCase() !== ch.toUpperCase()) return true;\n const c = ch.charCodeAt(0);\n for (const [from, to] of uncasedLetterRanges) if (c >= from && c <= to) return true;\n return false;\n}\n\n/** Whether the PIN type accepts a character (MAUI `IsAllowed`: `char.IsDigit` / `IsLetter` / `IsLetterOrDigit`). */\nexport function isPinCharAllowed(type: G9PinEntryType, ch: string): boolean {\n switch (type) {\n case G9PinEntryType.Letters:\n return isUnicodeLetter(ch);\n case G9PinEntryType.Alphanumeric:\n return isUnicodeLetter(ch) || isUnicodeDigit(ch);\n default:\n return isUnicodeDigit(ch);\n }\n}\n\n/**\n * Filters and clamps a code (MAUI `FilterAndClamp`): Persian and Arabic-Indic digits become ASCII, disallowed\n * characters are dropped, the rest is cut to `cells`.\n */\nexport function filterPin(raw: string | null | undefined, type: G9PinEntryType, cells: number): string {\n if (!raw) return '';\n let out = '';\n for (const typed of Array.from(raw)) {\n if (Array.from(out).length >= cells) break;\n const ch = normalizeToAscii(typed);\n if (isPinCharAllowed(type, ch)) out += ch;\n }\n return out;\n}\n\nconst hiddenInputStyle = {\n position: 'absolute',\n top: '0px',\n left: '0px',\n width: '1px',\n height: '1px',\n padding: '0px',\n borderWidth: '0px',\n opacity: 0,\n color: 'transparent',\n caretColor: 'transparent',\n backgroundColor: 'transparent',\n} as const;\n\n/**\n * One-time-code / PIN entry (MAUI `G9PinEntry`): a row of cells over one hidden `<input>` (the lynx-ui `InputOTP`\n * pattern). Append-only: typing fills the next cell, backspace empties the last, a tap anywhere focuses the end.\n * Paste is filtered and clamped. Digits are stored as ASCII whatever keyboard produced them. Masked with\n * `type: 'password'`. Requires the host's `xelement-input` registration.\n */\nexport const G9PinEntry = forwardRef<G9PinEntryHandle, G9PinEntryProps>(function G9PinEntry(props, ref): ReactNode {\n const keyboardAware = useContext(KeyboardAwareTriggerContext);\n const type = props.type ?? G9PinEntryType.Number;\n const groups = parsePinGroupSizes(props.groupSizes);\n const cells = pinCellCount(props.length ?? 4, groups);\n const [value, setValue] = useControllableState<string>({\n value: props.value,\n defaultValue: props.defaultValue ?? '',\n onChange: props.onValueChange,\n name: 'G9PinEntry.value',\n });\n const clean = filterPin(value, type, cells);\n const chars = Array.from(clean);\n const complete = chars.length === cells;\n const [focused, setFocused] = useState(false);\n const inputRef = useRef<NodesRef | null>(null);\n const native = useRef('');\n const completedFired = useRef(complete);\n const latest = useRef(clean);\n latest.current = clean;\n const [, bump] = useState(0);\n\n // A pushed value the filter rejects is replaced once; a pushed complete value never fires `onComplete`.\n const refiltered = useRef<string | null>(null);\n useEffect(() => {\n if (clean !== value && refiltered.current !== value) {\n refiltered.current = value;\n setValue(clean);\n }\n });\n const lastSeen = useRef(clean);\n if (lastSeen.current !== clean) {\n lastSeen.current = clean;\n if (!complete) completedFired.current = false;\n }\n const retries = useRef(0);\n const sync = () => {\n const current = latest.current;\n if (native.current === current) return;\n if (invokeNode(inputRef, 'setValue', { value: current })) {\n native.current = current;\n retries.current = 0;\n } else if (inputRef.current && retries.current < 5) {\n retries.current += 1;\n startTimer(() => syncRef.current(), 0);\n }\n };\n const syncRef = useRef(sync);\n syncRef.current = sync;\n const attach = useRef((node: NodesRef | null) => {\n inputRef.current = node;\n if (node) syncRef.current();\n }).current;\n useEffect(() => {\n sync();\n });\n\n const focus = () => {\n if (props.disabled) return;\n invokeNode(inputRef, 'focus');\n invokeNode(inputRef, 'setSelectionRange', { selectionStart: chars.length, selectionEnd: chars.length });\n };\n const clear = () => {\n latest.current = '';\n completedFired.current = false;\n setValue('');\n bump((n) => n + 1);\n };\n useImperativeHandle(ref, () => ({\n focusFirstEmpty: focus,\n clear,\n get isComplete() {\n return Array.from(latest.current).length === cells;\n },\n }));\n\n const autoFocused = useRef(false);\n useEffect(() => {\n if (props.autoFocus && !autoFocused.current && !props.disabled) {\n autoFocused.current = true;\n invokeNodeWhenReady(inputRef, 'focus');\n }\n });\n\n const onInput = (event: { detail?: { value?: string } }) => {\n const raw = event.detail?.value ?? '';\n native.current = raw;\n const next = filterPin(raw, type, cells);\n latest.current = next;\n lastSeen.current = next;\n setValue(next);\n const ready = Array.from(next).length === cells;\n if (ready && !completedFired.current) {\n completedFired.current = true;\n props.onComplete?.(next);\n } else if (!ready) {\n completedFired.current = false;\n }\n bump((n) => n + 1);\n };\n\n const cellWidth = props.cellWidth && props.cellWidth > 0 ? props.cellWidth : G9Metrics.PinCellWidth;\n const cellHeight = props.cellHeight && props.cellHeight > 0 ? props.cellHeight : G9Metrics.PinCellHeight;\n const active = focused ? Math.min(chars.length, cells - 1) : -1;\n const separator = props.separator ?? '';\n const row: ReactNode[] = [];\n let groupIndex = 0;\n let inGroup = 0;\n for (let i = 0; i < cells; i++) {\n const ch = chars[i];\n const state = i === active ? 'active' : ch !== undefined ? 'filled' : 'empty';\n row.push(\n <view\n key={`c${i}`}\n className={`g9-pin__cell g9-pin__cell--${state}`}\n style={{ width: `${cellWidth}px`, height: `${cellHeight}px` }}\n >\n <text className={ch !== undefined ? 'g9-pin__char' : 'g9-pin__placeholder'}>\n {ch !== undefined\n ? type === G9PinEntryType.Password\n ? (props.maskCharacter ?? '●')\n : ch\n : (props.placeholder ?? '')}\n </text>\n </view>,\n );\n inGroup++;\n if (groups.length > 0 && groupIndex < groups.length - 1 && inGroup === groups[groupIndex]) {\n if (separator !== '') {\n row.push(\n <text key={`s${groupIndex}`} className=\"g9-pin__separator\">\n {separator}\n </text>,\n );\n }\n groupIndex++;\n inGroup = 0;\n }\n }\n\n return (\n <view\n {...g9KeyboardTargetProps}\n className={`g9-pin g9-dir-ltr${props.disabled ? ' g9-pin--disabled' : ''}${complete ? ' g9-pin--complete' : ''}${props.className ? ` ${props.className}` : ''}`}\n {...g9IdProps(props.id)}\n accessibility-element={true}\n accessibility-label={`${props.accessibilityLabel ? `${props.accessibilityLabel}, ` : ''}${chars.length} / ${cells}`}\n bindtap={focus}\n >\n {row}\n <input\n {...g9KeyboardTargetProps}\n ref={attach}\n className=\"g9-pin__input\"\n android-fullscreen-mode={false}\n ignore-focus={true}\n confirm-type=\"done\"\n disabled={props.disabled === true}\n maxlength={cells}\n ios-auto-correct={false}\n ios-spell-check={false}\n type={type === G9PinEntryType.Number || type === G9PinEntryType.Password ? 'number' : 'text'}\n style={hiddenInputStyle}\n bindinput={onInput}\n bindfocus={() => {\n setFocused(true);\n keyboardAware.onInputFocused?.();\n }}\n bindblur={() => {\n setFocused(false);\n keyboardAware.onInputBlurred?.();\n }}\n />\n </view>\n );\n});\n"],"names":["parsePinGroupSizes","raw","out","part","trimmed","n","Number","pinCellCount","length","groups","a","b","Math","digitZeros","uncasedLetterRanges","isUnicodeDigit","ch","c","zero","isUnicodeLetter","from","to","isPinCharAllowed","type","G9PinEntryType","filterPin","cells","typed","Array","normalizeToAscii","hiddenInputStyle","G9PinEntry","forwardRef","props","ref","_props_type","_props_length","_props_defaultValue","_props_separator","keyboardAware","useContext","KeyboardAwareTriggerContext","value","setValue","useControllableState","clean","chars","complete","focused","setFocused","useState","inputRef","useRef","native","completedFired","latest","bump","refiltered","useEffect","lastSeen","retries","sync","current","invokeNode","startTimer","syncRef","attach","node","focus","clear","useImperativeHandle","autoFocused","invokeNodeWhenReady","onInput","event","_event_detail","next","ready","cellWidth","G9Metrics","cellHeight","active","separator","row","groupIndex","inGroup","i","_props_maskCharacter","_props_placeholder","state","undefined","view","text","g9KeyboardTargetProps","g9IdProps","input"],"mappings":";;;;;;;;;AAkEO,SAASA,mBAAmBC,GAA8B;IAC/D,IAAIA,AAAO,QAAPA,OAAeA,AAAe,OAAfA,IAAI,IAAI,IAAW,OAAO,EAAE;IAC/C,MAAMC,MAAgB,EAAE;IACxB,KAAK,MAAMC,QAAQF,IAAI,KAAK,CAAC,KAAM;QACjC,MAAMG,UAAUD,KAAK,IAAI;QACzB,IAAI,CAAC,YAAY,IAAI,CAACC,UAAU;QAChC,MAAMC,IAAIC,OAAOF;QACjB,IAAIC,IAAI,GAAGH,IAAI,IAAI,CAACG;IACtB;IACA,OAAOH;AACT;AAGO,SAASK,aAAaC,MAAc,EAAEC,MAAyB;IACpE,OAAOA,OAAO,MAAM,GAAG,IAAIA,OAAO,MAAM,CAAC,CAACC,GAAGC,IAAMD,IAAIC,GAAG,KAAKC,KAAK,GAAG,CAAC,GAAGJ;AAC7E;AAKA,MAAMK,aAAa;IACjB;IAAM;IAAO;IAAO;IAAO;IAAO;IAAO;IAAO;IAAO;IAAO;IAAO;IAAO;IAAO;IAAO;IAAO;IAAO;IAAO;IAC/G;IAAQ;IAAQ;IAAQ;IAAQ;IAAQ;IAAQ;IAAQ;IAAQ;IAAQ;IAAQ;IAAQ;IAAQ;IAAQ;IACxG;IAAQ;IAAQ;IAAQ;IAAQ;IAAQ;CACzC;AACD,MAAMC,sBAAgE;IACpE;QAAC;QAAO;KAAM;IACd;QAAC;QAAO;KAAM;IACd;QAAC;QAAO;KAAM;IACd;QAAC;QAAO;KAAM;IACd;QAAC;QAAO;KAAM;IACd;QAAC;QAAO;KAAM;IACd;QAAC;QAAQ;KAAO;IAChB;QAAC;QAAQ;KAAO;IAChB;QAAC;QAAQ;KAAO;IAChB;QAAC;QAAQ;KAAO;CACjB;AAED,SAASC,eAAeC,EAAU;IAChC,MAAMC,IAAID,GAAG,UAAU,CAAC;IACxB,KAAK,MAAME,QAAQL,WAAY,IAAII,KAAKC,QAAQD,KAAKC,OAAO,GAAG,OAAO;IACtE,OAAO;AACT;AAEA,SAASC,gBAAgBH,EAAU;IACjC,IAAIA,GAAG,WAAW,OAAOA,GAAG,WAAW,IAAI,OAAO;IAClD,MAAMC,IAAID,GAAG,UAAU,CAAC;IACxB,KAAK,MAAM,CAACI,MAAMC,GAAG,IAAIP,oBAAqB,IAAIG,KAAKG,QAAQH,KAAKI,IAAI,OAAO;IAC/E,OAAO;AACT;AAGO,SAASC,iBAAiBC,IAAoB,EAAEP,EAAU;IAC/D,OAAQO;QACN,KAAKC,eAAe,OAAO;YACzB,OAAOL,gBAAgBH;QACzB,KAAKQ,eAAe,YAAY;YAC9B,OAAOL,gBAAgBH,OAAOD,eAAeC;QAC/C;YACE,OAAOD,eAAeC;IAC1B;AACF;AAMO,SAASS,UAAUxB,GAA8B,EAAEsB,IAAoB,EAAEG,KAAa;IAC3F,IAAI,CAACzB,KAAK,OAAO;IACjB,IAAIC,MAAM;IACV,KAAK,MAAMyB,SAASC,MAAM,IAAI,CAAC3B,KAAM;QACnC,IAAI2B,MAAM,IAAI,CAAC1B,KAAK,MAAM,IAAIwB,OAAO;QACrC,MAAMV,KAAKa,iBAAiBF;QAC5B,IAAIL,iBAAiBC,MAAMP,KAAKd,OAAOc;IACzC;IACA,OAAOd;AACT;AAEA,MAAM4B,mBAAmB;IACvB,UAAU;IACV,KAAK;IACL,MAAM;IACN,OAAO;IACP,QAAQ;IACR,SAAS;IACT,aAAa;IACb,SAAS;IACT,OAAO;IACP,YAAY;IACZ,iBAAiB;AACnB;AAQO,MAAMC,uBAAaC,WAA8C,SAAoBC,KAAK,EAAEC,GAAG;QAEvFC,aAEcC,eAGXC,qBAiGEC;IAvGlB,MAAMC,gBAAgBC,WAAWC;IACjC,MAAMlB,OAAO,QAAAY,CAAAA,cAAAA,MAAM,IAAI,AAAD,IAATA,cAAcX,eAAe,MAAM;IAChD,MAAMf,SAAST,mBAAmBiC,MAAM,UAAU;IAClD,MAAMP,QAAQnB,aAAa,QAAA6B,CAAAA,gBAAAA,MAAM,MAAM,AAAD,IAAXA,gBAAgB,GAAG3B;IAC9C,MAAM,CAACiC,OAAOC,SAAS,GAAGC,qBAA6B;QACrD,OAAOX,MAAM,KAAK;QAClB,cAAc,QAAAI,CAAAA,sBAAAA,MAAM,YAAY,AAAD,IAAjBA,sBAAsB;QACpC,UAAUJ,MAAM,aAAa;QAC7B,MAAM;IACR;IACA,MAAMY,QAAQpB,UAAUiB,OAAOnB,MAAMG;IACrC,MAAMoB,QAAQlB,MAAM,IAAI,CAACiB;IACzB,MAAME,WAAWD,MAAM,MAAM,KAAKpB;IAClC,MAAM,CAACsB,SAASC,WAAW,GAAGC,SAAS;IACvC,MAAMC,WAAWC,OAAwB;IACzC,MAAMC,SAASD,OAAO;IACtB,MAAME,iBAAiBF,OAAOL;IAC9B,MAAMQ,SAASH,OAAOP;IACtBU,OAAO,OAAO,GAAGV;IACjB,MAAM,GAAGW,KAAK,GAAGN,SAAS;IAG1B,MAAMO,aAAaL,OAAsB;IACzCM,UAAU;QACR,IAAIb,UAAUH,SAASe,WAAW,OAAO,KAAKf,OAAO;YACnDe,WAAW,OAAO,GAAGf;YACrBC,SAASE;QACX;IACF;IACA,MAAMc,WAAWP,OAAOP;IACxB,IAAIc,SAAS,OAAO,KAAKd,OAAO;QAC9Bc,SAAS,OAAO,GAAGd;QACnB,IAAI,CAACE,UAAUO,eAAe,OAAO,GAAG;IAC1C;IACA,MAAMM,UAAUR,OAAO;IACvB,MAAMS,OAAO;QACX,MAAMC,UAAUP,OAAO,OAAO;QAC9B,IAAIF,OAAO,OAAO,KAAKS,SAAS;QAChC,IAAIC,WAAWZ,UAAU,YAAY;YAAE,OAAOW;QAAQ,IAAI;YACxDT,OAAO,OAAO,GAAGS;YACjBF,QAAQ,OAAO,GAAG;QACpB,OAAO,IAAIT,SAAS,OAAO,IAAIS,QAAQ,OAAO,GAAG,GAAG;YAClDA,QAAQ,OAAO,IAAI;YACnBI,WAAW,IAAMC,QAAQ,OAAO,IAAI;QACtC;IACF;IACA,MAAMA,UAAUb,OAAOS;IACvBI,QAAQ,OAAO,GAAGJ;IAClB,MAAMK,SAASd,OAAO,CAACe;QACrBhB,SAAS,OAAO,GAAGgB;QACnB,IAAIA,MAAMF,QAAQ,OAAO;IAC3B,GAAG,OAAO;IACVP,UAAU;QACRG;IACF;IAEA,MAAMO,QAAQ;QACZ,IAAInC,MAAM,QAAQ,EAAE;QACpB8B,WAAWZ,UAAU;QACrBY,WAAWZ,UAAU,qBAAqB;YAAE,gBAAgBL,MAAM,MAAM;YAAE,cAAcA,MAAM,MAAM;QAAC;IACvG;IACA,MAAMuB,QAAQ;QACZd,OAAO,OAAO,GAAG;QACjBD,eAAe,OAAO,GAAG;QACzBX,SAAS;QACTa,KAAK,CAACnD,IAAMA,IAAI;IAClB;IACAiE,oBAAoBpC,KAAK,IAAO;YAC9B,iBAAiBkC;YACjBC;YACA,IAAI;gBACF,OAAOzC,MAAM,IAAI,CAAC2B,OAAO,OAAO,EAAE,MAAM,KAAK7B;YAC/C;QACF;IAEA,MAAM6C,cAAcnB,OAAO;IAC3BM,UAAU;QACR,IAAIzB,MAAM,SAAS,IAAI,CAACsC,YAAY,OAAO,IAAI,CAACtC,MAAM,QAAQ,EAAE;YAC9DsC,YAAY,OAAO,GAAG;YACtBC,oBAAoBrB,UAAU;QAChC;IACF;IAEA,MAAMsB,UAAU,CAACC;;YACHC;QAAZ,MAAM1E,MAAM,QAANA,CAAAA,OAAAA,QAAM0E,CAAAA,gBAAAA,MAAM,MAAM,AAAD,IAAXA,KAAAA,IAAAA,cAAc,KAAK,AAAD,IAAC,OAAI;QACnCtB,OAAO,OAAO,GAAGpD;QACjB,MAAM2E,OAAOnD,UAAUxB,KAAKsB,MAAMG;QAClC6B,OAAO,OAAO,GAAGqB;QACjBjB,SAAS,OAAO,GAAGiB;QACnBjC,SAASiC;QACT,MAAMC,QAAQjD,MAAM,IAAI,CAACgD,MAAM,MAAM,KAAKlD;QAC1C,IAAImD,SAAS,CAACvB,eAAe,OAAO,EAAE;gBAEpCrB;YADAqB,eAAe,OAAO,GAAG;oBACzBrB,CAAAA,oBAAAA,MAAM,UAAU,AAAD,KAAfA,kBAAAA,IAAAA,CAAAA,OAAmB2C;QACrB,OAAO,IAAI,CAACC,OACVvB,eAAe,OAAO,GAAG;QAE3BE,KAAK,CAACnD,IAAMA,IAAI;IAClB;IAEA,MAAMyE,YAAY7C,MAAM,SAAS,IAAIA,MAAM,SAAS,GAAG,IAAIA,MAAM,SAAS,GAAG8C,UAAU,YAAY;IACnG,MAAMC,aAAa/C,MAAM,UAAU,IAAIA,MAAM,UAAU,GAAG,IAAIA,MAAM,UAAU,GAAG8C,UAAU,aAAa;IACxG,MAAME,SAASjC,UAAUpC,KAAK,GAAG,CAACkC,MAAM,MAAM,EAAEpB,QAAQ,KAAK;IAC7D,MAAMwD,YAAY,QAAA5C,CAAAA,mBAAAA,MAAM,SAAS,AAAD,IAAdA,mBAAmB;IACrC,MAAM6C,MAAmB,EAAE;IAC3B,IAAIC,aAAa;IACjB,IAAIC,UAAU;IACd,IAAK,IAAIC,IAAI,GAAGA,IAAI5D,OAAO4D,IAAK;YAYjBC,sBAEFC;QAbX,MAAMxE,KAAK8B,KAAK,CAACwC,EAAE;QACnB,MAAMG,QAAQH,MAAML,SAAS,WAAWjE,AAAO0E,WAAP1E,KAAmB,WAAW;QACtEmE,IAAI,IAAI,EACLQ,KACC,KAAK,CAAC,CAAC,EAAEL,GAAG,EACZ,WAAW,CAAC,2BAA2B,EAAEG,OAAO,EAChD,OAAO;YAAE,OAAO,GAAGX,UAAU,EAAE,CAAC;YAAE,QAAQ,GAAGE,WAAW,EAAE,CAAC;QAAC,GAC7D;QACC,CAACY,KAAK,WAAW5E,AAAO0E,WAAP1E,KAAmB,iBAAiB,uBAAuB;UAC1E,CAACA,AAAO0E,WAAP1E,KACGO,SAASC,eAAe,QAAQ,WAC7B+D,CAAAA,uBAAAA,MAAM,aAAa,AAAD,IAAlBA,uBAAuB,MACxBvE,KAAAA,QACDwE,CAAAA,qBAAAA,MAAM,WAAW,AAAD,IAAhBA,qBAAqB,GAAI;QAChC,EAAEI,KAAK;MACT,EAAED;QAEJN;QACA,IAAI5E,OAAO,MAAM,GAAG,KAAK2E,aAAa3E,OAAO,MAAM,GAAG,KAAK4E,YAAY5E,MAAM,CAAC2E,WAAW,EAAE;YACzF,IAAIF,AAAc,OAAdA,WACFC,IAAI,IAAI,EACLS,KAAK,KAAK,CAAC,CAAC,EAAER,YAAY,EAAE,UAAU,oBAAoB;YACzD,CAACF,UAAU;UACb,EAAEU;YAGNR;YACAC,UAAU;QACZ;IACF;IAEA,QACGM,MACE,GAAGE,qBAAqB,EACzB,WAAW,CAAC,iBAAiB,EAAE5D,MAAM,QAAQ,GAAG,sBAAsB,KAAKc,WAAW,sBAAsB,KAAKd,MAAM,SAAS,GAAG,CAAC,CAAC,EAAEA,MAAM,SAAS,EAAE,GAAG,IAAI,GAC9J,GAAG6D,UAAU7D,MAAM,EAAE,CAAC,EACvB,uBAAuB,MACvB,qBAAqB,GAAGA,MAAM,kBAAkB,GAAG,GAAGA,MAAM,kBAAkB,CAAC,EAAE,CAAC,GAAG,KAAKa,MAAM,MAAM,CAAC,GAAG,EAAEpB,OAAO,EACnH,SAAS0C,OACV;MACC,CAACe,IAAI;MACL,CAACY,OACE,GAAGF,qBAAqB,EACzB,KAAK3B,QACL,UAAU,gBACV,yBAAyB,OACzB,cAAc,MACd,aAAa,OACb,UAAUjC,AAAmB,SAAnBA,MAAM,QAAQ,EACxB,WAAWP,OACX,kBAAkB,OAClB,iBAAiB,OACjB,MAAMH,SAASC,eAAe,MAAM,IAAID,SAASC,eAAe,QAAQ,GAAG,WAAW,QACtF,OAAOM,kBACP,WAAW2C,SACX,WAAW;YAETlC;QADAU,WAAW;gBACXV,CAAAA,gCAAAA,cAAc,cAAc,AAAD,KAA3BA,8BAAAA,IAAAA,CAAAA;IACF,GACA,UAAU;YAERA;QADAU,WAAW;gBACXV,CAAAA,gCAAAA,cAAc,cAAc,AAAD,KAA3BA,8BAAAA,IAAAA,CAAAA;IACF,IACA;IACJ,EAAEoD;AAEN"}
|
|
@@ -1 +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,
|
|
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"}
|
|
@@ -51,14 +51,24 @@ const TextEntryBody = forwardRef(function(props, ref) {
|
|
|
51
51
|
const masked = true === props.isPassword && !core.passwordVisible;
|
|
52
52
|
const keyboard = resolveEffectiveKeyboard(core.inputType, null != (_props_keyboardType = props.keyboardType) ? _props_keyboardType : G9KeyboardType.Default);
|
|
53
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
|
-
|
|
54
|
+
{}
|
|
55
|
+
{true === props.readOnly && !masked ? <text className="g9-field__input g9-field__input--readonly" text-maxline="1" style={{
|
|
55
56
|
direction: core.textDirection,
|
|
56
57
|
textAlign: 'rtl' === core.textDirection ? 'right' : 'left',
|
|
57
58
|
...core.font ? {
|
|
58
59
|
fontFamily: core.font
|
|
59
60
|
} : {},
|
|
60
61
|
color: props.disabled ? 'var(--g9-text-disabled)' : 'var(--g9-text-primary)'
|
|
61
|
-
}}
|
|
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
|
+
}}/>}
|
|
62
72
|
</G9OutlinedField>;
|
|
63
73
|
});
|
|
64
74
|
const entryVariant = {
|
|
@@ -1 +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 <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 </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","input","resolveInputElementType","entryVariant","G9TextEntry"],"mappings":"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"}
|
|
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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-text-input.d.ts","sourceRoot":"","sources":["../../src/fields/use-text-input.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"use-text-input.d.ts","sourceRoot":"","sources":["../../src/fields/use-text-input.ts"],"names":[],"mappings":"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"}
|
|
@@ -54,6 +54,7 @@ function useTextInput(props, options) {
|
|
|
54
54
|
latestText.current = display;
|
|
55
55
|
const elementRef = useRef(null);
|
|
56
56
|
const native = useRef('');
|
|
57
|
+
const composingRef = useRef(false);
|
|
57
58
|
const [focused, setFocused] = useState(false);
|
|
58
59
|
const focusedRef = useRef(false);
|
|
59
60
|
const [passwordVisible, setPasswordVisible] = useState(false);
|
|
@@ -137,8 +138,17 @@ function useTextInput(props, options) {
|
|
|
137
138
|
var _ref;
|
|
138
139
|
var _event_detail, _event_detail1;
|
|
139
140
|
const raw = null != (_ref = null == (_event_detail = event.detail) ? void 0 : _event_detail.value) ? _ref : '';
|
|
141
|
+
if (true === props.readOnly) {
|
|
142
|
+
native.current = raw;
|
|
143
|
+
if (raw !== latestText.current) syncRef.current();
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const composing = (null == (_event_detail1 = event.detail) ? void 0 : _event_detail1.isComposing) === true;
|
|
147
|
+
const echo = !composing && !composingRef.current && raw === native.current;
|
|
148
|
+
composingRef.current = composing;
|
|
149
|
+
if (echo) return;
|
|
140
150
|
native.current = raw;
|
|
141
|
-
if (
|
|
151
|
+
if (composing) return;
|
|
142
152
|
const clean = sanitize(raw);
|
|
143
153
|
latestText.current = clean;
|
|
144
154
|
setText(clean, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fields/use-text-input.jsx","sources":["../../src/fields/use-text-input.ts"],"sourcesContent":["import { G9InputType, type G9KeyboardType, G9TextInputDirection } from '@g9tm/lynxcontrols-foundation';\nimport { KeyboardAwareTriggerContext } from '@lynx-js/lynx-ui-input';\nimport { useContext, useEffect, useRef, useState } from '@lynx-js/react';\nimport type { NodesRef } from '@lynx-js/types';\nimport { startTimer } from '../base/timers';\nimport { useControllableState } from '../base/use-controllable-state';\nimport { g9KeyboardTargetProps } from '../host/keyboard';\nimport { useG9Culture, useG9Strings } from '../provider/hooks';\nimport {\n decimalSeparatorFor,\n inputTypeHasValidationRule,\n inputTypePrefersLeftToRight,\n sanitizeInputText,\n validateInputText,\n} from './input-policy';\nimport type { G9OutlinedFieldProps } from './outlined-field';\nimport { useDictation } from './use-dictation';\nimport { type G9TextValidator, runTextValidator } from './validator';\n\n/** Where a value change came from (plan/specs/03 §3). */\nexport type G9ValueChangeSource = 'user' | 'dictation' | 'clear' | 'programmatic';\n\n/** Payload of `onValueChange`. */\nexport interface G9ValueChangeDetails {\n readonly source: G9ValueChangeSource;\n}\n\n/** Props the text inputs (`G9TextEntry`, `G9Editor`, `G9SearchEntry`) share on top of the outlined-field props. */\nexport interface G9TextInputProps extends G9OutlinedFieldProps {\n /** The text (controlled; MAUI `Text`). Present, the caller owns it and must apply `onValueChange`. */\n readonly value?: string;\n /** Initial text while uncontrolled. Default `''`. */\n readonly defaultValue?: string;\n /**\n * Once per change of the field's value, with where it came from: `'user'` (typing, paste), `'dictation'`,\n * `'clear'` (the clear button) or `'programmatic'` (the field re-filtered a value it was given, e.g. after an\n * `inputType` change). Never for a value the parent pushed in that needed no filtering.\n */\n readonly onValueChange?: (value: string, details: G9ValueChangeDetails) => void;\n /** On-screen keyboard; used when `inputType` is `'default'` (any other type picks its own). Default `'default'`. */\n readonly keyboardType?: G9KeyboardType;\n /** Semantic input type: keyboard, live filter and blur validation. Default `'default'`. */\n readonly inputType?: G9InputType;\n /** Per-character filter regex (a single character class) for `inputType: 'custom'`. */\n readonly allowedCharsPattern?: string | null;\n /** Blur validation regex for `inputType: 'custom'`. An invalid pattern fails closed. */\n readonly validationPattern?: string | null;\n /** Message for a failed type validation; default the culture's `invalidEmail` / `invalidUrl` / `invalidValue`. */\n readonly validationErrorText?: string | null;\n /** Direction of the entered text; `'matchParent'` (default) pins numbers, phone, email, URL and passwords LTR. */\n readonly inputTextDirection?: G9TextInputDirection;\n /** Font family of the entered text; default the culture's font. */\n readonly customFont?: string | null;\n /** Offer dictation through `services.speech` (hidden without the service or recogniser). Default false. */\n readonly voiceEnabled?: boolean;\n /** Locale to recognise (MAUI `VoiceCulture`); default the active culture. */\n readonly voiceLocale?: string | null;\n readonly onVoiceListeningStarted?: () => void;\n readonly onVoiceListeningEnded?: () => void;\n /** Dictation could not run or finish; a localized message for a toast. */\n readonly onVoiceFailed?: (message: string) => void;\n /** Validation ran (blur, `validateOnTextChanged` or `validate()`): the message, or `null` when valid. */\n readonly onValidationChange?: (message: string | null) => void;\n readonly onFocus?: () => void;\n readonly onBlur?: () => void;\n /** The keyboard's confirm key was pressed. */\n readonly onConfirm?: (value: string) => void;\n /** Element id of the inner `<input>`/`<textarea>`. */\n readonly inputId?: string;\n}\n\n/** Imperative handle of the text inputs (MAUI public methods). */\nexport interface G9TextInputHandle {\n /** Focuses the inner element (raises the keyboard). */\n focus(): void;\n /** Removes focus (hides the keyboard). */\n blur(): void;\n /** Runs the validator and the type rule now; sets or clears the error; `true` when valid (MAUI `Validate`). */\n validate(): boolean;\n /** `true` while dictating (MAUI `IsListening`). */\n readonly isListening: boolean;\n /** MAUI `ToggleVoiceAsync`. */\n toggleVoice(): Promise<void>;\n /** MAUI `StartVoiceAsync`. */\n startVoice(): Promise<void>;\n /** MAUI `StopVoiceAsync`; safe when nothing runs. */\n stopVoice(): Promise<void>;\n /** The inner element's node ref (MAUI `InnerEntry` / `InnerEditor`), for `invoke` calls G9 does not wrap. */\n readonly element: G9NodeRef | null;\n}\n\n/** The Lynx node ref of a field's inner element. */\nexport type G9NodeRef = NodesRef;\n\n/** Lynx input event detail. */\ninterface InputDetail {\n readonly value?: string;\n readonly isComposing?: boolean;\n}\n\n/** Resolves the entered text's direction (MAUI `ResolveInputFlowDirection`). */\nexport function resolveInputTextDirection(\n inputTextDirection: G9TextInputDirection,\n inputType: G9InputType,\n isPassword: boolean,\n cultureDirection: 'ltr' | 'rtl',\n): 'ltr' | 'rtl' {\n if (inputTextDirection === G9TextInputDirection.LeftToRight) return 'ltr';\n if (inputTextDirection === G9TextInputDirection.RightToLeft) return 'rtl';\n if (inputTypePrefersLeftToRight(inputType) || isPassword) return 'ltr';\n return cultureDirection;\n}\n\n/** Calls a UI method on a node; a missing node or a failing call is ignored (the element is gone). */\nexport function invokeNode(\n ref: { current: G9NodeRef | null },\n method: string,\n params?: Record<string, unknown>,\n): boolean {\n const node = ref.current;\n if (!node) return false;\n try {\n node\n .invoke({\n method,\n ...(params ? { params } : {}),\n success: () => {},\n fail: () => {},\n })\n .exec();\n } catch {\n // The element was unmounted between the call and its execution.\n return false;\n }\n return true;\n}\n\n/**\n * {@link invokeNode}, retried on the next ticks (up to `attempts` times) while the element is not created natively\n * yet, e.g. a focus requested during the first commit.\n */\nexport function invokeNodeWhenReady(\n ref: { current: G9NodeRef | null },\n method: string,\n params?: Record<string, unknown>,\n attempts = 5,\n): void {\n if (invokeNode(ref, method, params) || attempts <= 0) return;\n startTimer(() => invokeNodeWhenReady(ref, method, params, attempts - 1), 0);\n}\n\ninterface ValidationResult {\n readonly message: string | null;\n // The external error props this result overrides; new props from the parent win again.\n readonly hasError: boolean | undefined;\n readonly errorText: string | null | undefined;\n}\n\n/** Options of {@link useTextInput}. */\nexport interface G9TextInputCoreOptions {\n /** Name for the controlled/uncontrolled diagnostic, e.g. `'G9TextEntry.value'`. */\n readonly name: string;\n /** Whether the microphone is shown, given the dictation and value state. */\n readonly showMic: (state: { available: boolean; listening: boolean; hasValue: boolean }) => boolean;\n /** Extra validator (`G9TextEntry.validator`; the editor has none). */\n readonly validator?: G9TextValidator | null;\n /** Validate on every change (`G9TextEntry.validateOnTextChanged`). */\n readonly validateOnTextChanged?: boolean;\n /** A password field (its text is pinned LTR). */\n readonly isPassword?: boolean;\n}\n\n/**\n * The state machine behind the text inputs: value ownership, the live filter, the native element sync, focus,\n * validation and dictation. Returns what the input element and the outlined frame need.\n */\nexport function useTextInput(props: G9TextInputProps, options: G9TextInputCoreOptions) {\n const culture = useG9Culture();\n const strings = useG9Strings();\n const keyboardAware = useContext(KeyboardAwareTriggerContext);\n const inputType = props.inputType ?? G9InputType.Default;\n const separator = decimalSeparatorFor(culture.numberingSystem);\n const sanitize = (raw: string) => sanitizeInputText(inputType, raw, props.allowedCharsPattern, separator);\n\n const [text, setText] = useControllableState<string, [G9ValueChangeDetails]>({\n value: props.value,\n defaultValue: props.defaultValue ?? '',\n onChange: props.onValueChange,\n name: options.name,\n });\n const display = sanitize(text);\n const latestText = useRef(display);\n latestText.current = display;\n\n const elementRef = useRef<NodesRef | null>(null);\n const native = useRef('');\n const [focused, setFocused] = useState(false);\n const focusedRef = useRef(false);\n const [passwordVisible, setPasswordVisible] = useState(false);\n const [, bump] = useState(0);\n const [validation, setValidation] = useState<ValidationResult | null>(null);\n const hasValue = display !== '';\n\n const runValidation = (value: string): boolean => {\n const message =\n runTextValidator(options.validator, value) ??\n validateInputText(inputType, value, props.validationPattern, props.validationErrorText, strings);\n setValidation({ message, hasError: props.hasError, errorText: props.errorText });\n props.onValidationChange?.(message);\n return message === null;\n };\n const hasRule = options.validator != null || inputTypeHasValidationRule(inputType, props.validationPattern);\n\n const dictation = useDictation({\n enabled: props.voiceEnabled === true,\n locale: props.voiceLocale ?? null,\n readText: () => latestText.current,\n writeText: (value) => {\n setText(sanitize(value), { source: 'dictation' });\n },\n ...(props.onVoiceListeningStarted ? { onListeningStarted: props.onVoiceListeningStarted } : {}),\n ...(props.onVoiceListeningEnded ? { onListeningEnded: props.onVoiceListeningEnded } : {}),\n ...(props.onVoiceFailed ? { onFailed: props.onVoiceFailed } : {}),\n });\n\n // A value the field was given that its filter rejects is replaced once (MAUI OnTextChanged writes it back).\n const refiltered = useRef<string | null>(null);\n useEffect(() => {\n if (display !== text && refiltered.current !== text) {\n refiltered.current = text;\n setText(display, { source: 'programmatic' });\n }\n });\n\n // Keep the native element showing the field's value (lynx-ui pattern: `invoke('setValue')`). The node ref can\n // attach after the first effect, so attaching syncs too.\n const retries = useRef(0);\n const sync = () => {\n const value = latestText.current;\n if (native.current === value) return;\n if (invokeNode(elementRef, 'setValue', { value })) {\n native.current = value;\n retries.current = 0;\n } else if (elementRef.current && retries.current < 5) {\n // The element is not created natively yet (first commit): try again on the next tick.\n retries.current += 1;\n startTimer(() => syncRef.current(), 0);\n }\n };\n const syncRef = useRef(sync);\n syncRef.current = sync;\n const attach = useRef((node: NodesRef | null) => {\n elementRef.current = node;\n if (node) syncRef.current();\n }).current;\n useEffect(() => {\n sync();\n });\n\n // Clearing the value re-masks a revealed password (MAUI OnTextChanged).\n useEffect(() => {\n if (!hasValue && passwordVisible) setPasswordVisible(false);\n }, [hasValue, passwordVisible]);\n\n // New external error props win over an earlier validation result.\n const validationCurrent =\n validation !== null && validation.hasError === props.hasError && validation.errorText === props.errorText;\n const hasError = validationCurrent ? validation.message !== null : props.hasError === true;\n const errorText = validationCurrent && validation.message !== null ? validation.message : props.errorText;\n\n const onInput = (event: { detail?: InputDetail }) => {\n const raw = event.detail?.value ?? '';\n native.current = raw;\n // IME composition is never interrupted: the composed text is filtered when it is committed.\n if (event.detail?.isComposing) return;\n const clean = sanitize(raw);\n latestText.current = clean;\n setText(clean, { source: 'user' });\n if (options.validateOnTextChanged) runValidation(clean);\n bump((n) => n + 1);\n };\n const onFocus = () => {\n focusedRef.current = true;\n setFocused(true);\n keyboardAware.onInputFocused?.();\n // Tapping the field while dictating means typing: end the session (ADR-0024).\n if (dictation.listening) void dictation.stop();\n props.onFocus?.();\n };\n const onBlur = () => {\n focusedRef.current = false;\n setFocused(false);\n keyboardAware.onInputBlurred?.();\n // Only fields with a rule validate on blur, so an externally set error survives.\n if (hasRule && latestText.current !== '') runValidation(latestText.current);\n props.onBlur?.();\n };\n const onConfirm = () => props.onConfirm?.(latestText.current);\n\n const focus = () => {\n if (props.disabled) return;\n invokeNode(elementRef, 'focus');\n };\n const blur = () => invokeNode(elementRef, 'blur');\n\n const showMic = options.showMic({ available: dictation.available, listening: dictation.listening, hasValue });\n const pressMic = () => {\n // The microphone never focuses the field, and starting takes the keyboard down (ADR-0024).\n if (!dictation.listening && focusedRef.current) blur();\n void dictation.toggle();\n };\n\n const direction = resolveInputTextDirection(\n props.inputTextDirection ?? G9TextInputDirection.MatchParent,\n inputType,\n options.isPassword === true,\n culture.direction,\n );\n const font =\n props.customFont && props.customFont.trim() !== ''\n ? props.customFont\n : culture.direction === 'rtl'\n ? culture.rtlFontFamily\n : culture.ltrFontFamily;\n\n const handle: G9TextInputHandle = {\n focus,\n blur,\n validate: () => runValidation(latestText.current),\n get isListening() {\n return dictation.listening;\n },\n toggleVoice: () => dictation.toggle(),\n startVoice: () => dictation.start(),\n stopVoice: () => dictation.stop(),\n get element() {\n return elementRef.current;\n },\n };\n\n return {\n text: display,\n setText,\n hasValue,\n focused,\n hasError,\n errorText,\n passwordVisible,\n setPasswordVisible,\n dictation,\n showMic,\n pressMic,\n focus,\n blur,\n handle,\n inputType,\n /** Element attributes and handlers shared by `<input>` and `<textarea>`. */\n elementProps: {\n ...g9KeyboardTargetProps,\n ref: attach,\n ...(props.inputId ? { id: props.inputId } : {}),\n 'ignore-focus': true,\n readonly: props.readOnly === true,\n disabled: props.disabled === true,\n maxlength: props.maxLength !== undefined && props.maxLength > 0 ? props.maxLength : 2147483647,\n bindinput: onInput,\n bindfocus: onFocus,\n bindblur: onBlur,\n bindconfirm: onConfirm,\n },\n textDirection: direction,\n font,\n };\n}\n"],"names":["resolveInputTextDirection","inputTextDirection","inputType","isPassword","cultureDirection","G9TextInputDirection","inputTypePrefersLeftToRight","invokeNode","ref","method","params","node","invokeNodeWhenReady","attempts","startTimer","useTextInput","props","options","_props_inputType","_props_defaultValue","_props_voiceLocale","_props_inputTextDirection","culture","useG9Culture","strings","useG9Strings","keyboardAware","useContext","KeyboardAwareTriggerContext","G9InputType","separator","decimalSeparatorFor","sanitize","raw","sanitizeInputText","text","setText","useControllableState","display","latestText","useRef","elementRef","native","focused","setFocused","useState","focusedRef","passwordVisible","setPasswordVisible","bump","validation","setValidation","hasValue","runValidation","value","_runTextValidator","message","validateInputText","hasRule","inputTypeHasValidationRule","dictation","useDictation","refiltered","useEffect","retries","sync","syncRef","attach","validationCurrent","hasError","errorText","onInput","event","_event_detail","_event_detail1","clean","n","onFocus","onBlur","onConfirm","focus","blur","showMic","pressMic","direction","font","handle","g9KeyboardTargetProps","undefined"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fields/use-text-input.jsx","sources":["../../src/fields/use-text-input.ts"],"sourcesContent":["import { G9InputType, type G9KeyboardType, G9TextInputDirection } from '@g9tm/lynxcontrols-foundation';\nimport { KeyboardAwareTriggerContext } from '@lynx-js/lynx-ui-input';\nimport { useContext, useEffect, useRef, useState } from '@lynx-js/react';\nimport type { NodesRef } from '@lynx-js/types';\nimport { startTimer } from '../base/timers';\nimport { useControllableState } from '../base/use-controllable-state';\nimport { g9KeyboardTargetProps } from '../host/keyboard';\nimport { useG9Culture, useG9Strings } from '../provider/hooks';\nimport {\n decimalSeparatorFor,\n inputTypeHasValidationRule,\n inputTypePrefersLeftToRight,\n sanitizeInputText,\n validateInputText,\n} from './input-policy';\nimport type { G9OutlinedFieldProps } from './outlined-field';\nimport { useDictation } from './use-dictation';\nimport { type G9TextValidator, runTextValidator } from './validator';\n\n/** Where a value change came from (plan/specs/03 §3). */\nexport type G9ValueChangeSource = 'user' | 'dictation' | 'clear' | 'programmatic';\n\n/** Payload of `onValueChange`. */\nexport interface G9ValueChangeDetails {\n readonly source: G9ValueChangeSource;\n}\n\n/** Props the text inputs (`G9TextEntry`, `G9Editor`, `G9SearchEntry`) share on top of the outlined-field props. */\nexport interface G9TextInputProps extends G9OutlinedFieldProps {\n /** The text (controlled; MAUI `Text`). Present, the caller owns it and must apply `onValueChange`. */\n readonly value?: string;\n /** Initial text while uncontrolled. Default `''`. */\n readonly defaultValue?: string;\n /**\n * Once per change of the field's value, with where it came from: `'user'` (typing, paste), `'dictation'`,\n * `'clear'` (the clear button) or `'programmatic'` (the field re-filtered a value it was given, e.g. after an\n * `inputType` change). Never for a value the parent pushed in that needed no filtering.\n */\n readonly onValueChange?: (value: string, details: G9ValueChangeDetails) => void;\n /** On-screen keyboard; used when `inputType` is `'default'` (any other type picks its own). Default `'default'`. */\n readonly keyboardType?: G9KeyboardType;\n /** Semantic input type: keyboard, live filter and blur validation. Default `'default'`. */\n readonly inputType?: G9InputType;\n /** Per-character filter regex (a single character class) for `inputType: 'custom'`. */\n readonly allowedCharsPattern?: string | null;\n /** Blur validation regex for `inputType: 'custom'`. An invalid pattern fails closed. */\n readonly validationPattern?: string | null;\n /** Message for a failed type validation; default the culture's `invalidEmail` / `invalidUrl` / `invalidValue`. */\n readonly validationErrorText?: string | null;\n /** Direction of the entered text; `'matchParent'` (default) pins numbers, phone, email, URL and passwords LTR. */\n readonly inputTextDirection?: G9TextInputDirection;\n /** Font family of the entered text; default the culture's font. */\n readonly customFont?: string | null;\n /** Offer dictation through `services.speech` (hidden without the service or recogniser). Default false. */\n readonly voiceEnabled?: boolean;\n /** Locale to recognise (MAUI `VoiceCulture`); default the active culture. */\n readonly voiceLocale?: string | null;\n readonly onVoiceListeningStarted?: () => void;\n readonly onVoiceListeningEnded?: () => void;\n /** Dictation could not run or finish; a localized message for a toast. */\n readonly onVoiceFailed?: (message: string) => void;\n /** Validation ran (blur, `validateOnTextChanged` or `validate()`): the message, or `null` when valid. */\n readonly onValidationChange?: (message: string | null) => void;\n readonly onFocus?: () => void;\n readonly onBlur?: () => void;\n /** The keyboard's confirm key was pressed. */\n readonly onConfirm?: (value: string) => void;\n /** Element id of the inner `<input>`/`<textarea>`. */\n readonly inputId?: string;\n}\n\n/** Imperative handle of the text inputs (MAUI public methods). */\nexport interface G9TextInputHandle {\n /** Focuses the inner element (raises the keyboard). */\n focus(): void;\n /** Removes focus (hides the keyboard). */\n blur(): void;\n /** Runs the validator and the type rule now; sets or clears the error; `true` when valid (MAUI `Validate`). */\n validate(): boolean;\n /** `true` while dictating (MAUI `IsListening`). */\n readonly isListening: boolean;\n /** MAUI `ToggleVoiceAsync`. */\n toggleVoice(): Promise<void>;\n /** MAUI `StartVoiceAsync`. */\n startVoice(): Promise<void>;\n /** MAUI `StopVoiceAsync`; safe when nothing runs. */\n stopVoice(): Promise<void>;\n /** The inner element's node ref (MAUI `InnerEntry` / `InnerEditor`), for `invoke` calls G9 does not wrap. */\n readonly element: G9NodeRef | null;\n}\n\n/** The Lynx node ref of a field's inner element. */\nexport type G9NodeRef = NodesRef;\n\n/** Lynx input event detail. */\ninterface InputDetail {\n readonly value?: string;\n readonly isComposing?: boolean;\n}\n\n/** Resolves the entered text's direction (MAUI `ResolveInputFlowDirection`). */\nexport function resolveInputTextDirection(\n inputTextDirection: G9TextInputDirection,\n inputType: G9InputType,\n isPassword: boolean,\n cultureDirection: 'ltr' | 'rtl',\n): 'ltr' | 'rtl' {\n if (inputTextDirection === G9TextInputDirection.LeftToRight) return 'ltr';\n if (inputTextDirection === G9TextInputDirection.RightToLeft) return 'rtl';\n if (inputTypePrefersLeftToRight(inputType) || isPassword) return 'ltr';\n return cultureDirection;\n}\n\n/** Calls a UI method on a node; a missing node or a failing call is ignored (the element is gone). */\nexport function invokeNode(\n ref: { current: G9NodeRef | null },\n method: string,\n params?: Record<string, unknown>,\n): boolean {\n const node = ref.current;\n if (!node) return false;\n try {\n node\n .invoke({\n method,\n ...(params ? { params } : {}),\n success: () => {},\n fail: () => {},\n })\n .exec();\n } catch {\n // The element was unmounted between the call and its execution.\n return false;\n }\n return true;\n}\n\n/**\n * {@link invokeNode}, retried on the next ticks (up to `attempts` times) while the element is not created natively\n * yet, e.g. a focus requested during the first commit.\n */\nexport function invokeNodeWhenReady(\n ref: { current: G9NodeRef | null },\n method: string,\n params?: Record<string, unknown>,\n attempts = 5,\n): void {\n if (invokeNode(ref, method, params) || attempts <= 0) return;\n startTimer(() => invokeNodeWhenReady(ref, method, params, attempts - 1), 0);\n}\n\ninterface ValidationResult {\n readonly message: string | null;\n // The external error props this result overrides; new props from the parent win again.\n readonly hasError: boolean | undefined;\n readonly errorText: string | null | undefined;\n}\n\n/** Options of {@link useTextInput}. */\nexport interface G9TextInputCoreOptions {\n /** Name for the controlled/uncontrolled diagnostic, e.g. `'G9TextEntry.value'`. */\n readonly name: string;\n /** Whether the microphone is shown, given the dictation and value state. */\n readonly showMic: (state: { available: boolean; listening: boolean; hasValue: boolean }) => boolean;\n /** Extra validator (`G9TextEntry.validator`; the editor has none). */\n readonly validator?: G9TextValidator | null;\n /** Validate on every change (`G9TextEntry.validateOnTextChanged`). */\n readonly validateOnTextChanged?: boolean;\n /** A password field (its text is pinned LTR). */\n readonly isPassword?: boolean;\n}\n\n/**\n * The state machine behind the text inputs: value ownership, the live filter, the native element sync, focus,\n * validation and dictation. Returns what the input element and the outlined frame need.\n */\nexport function useTextInput(props: G9TextInputProps, options: G9TextInputCoreOptions) {\n const culture = useG9Culture();\n const strings = useG9Strings();\n const keyboardAware = useContext(KeyboardAwareTriggerContext);\n const inputType = props.inputType ?? G9InputType.Default;\n const separator = decimalSeparatorFor(culture.numberingSystem);\n const sanitize = (raw: string) => sanitizeInputText(inputType, raw, props.allowedCharsPattern, separator);\n\n const [text, setText] = useControllableState<string, [G9ValueChangeDetails]>({\n value: props.value,\n defaultValue: props.defaultValue ?? '',\n onChange: props.onValueChange,\n name: options.name,\n });\n const display = sanitize(text);\n const latestText = useRef(display);\n latestText.current = display;\n\n const elementRef = useRef<NodesRef | null>(null);\n const native = useRef('');\n /** The last native input event was an IME composition (its commit may repeat the composed text). */\n const composingRef = useRef(false);\n const [focused, setFocused] = useState(false);\n const focusedRef = useRef(false);\n const [passwordVisible, setPasswordVisible] = useState(false);\n const [, bump] = useState(0);\n const [validation, setValidation] = useState<ValidationResult | null>(null);\n const hasValue = display !== '';\n\n const runValidation = (value: string): boolean => {\n const message =\n runTextValidator(options.validator, value) ??\n validateInputText(inputType, value, props.validationPattern, props.validationErrorText, strings);\n setValidation({ message, hasError: props.hasError, errorText: props.errorText });\n props.onValidationChange?.(message);\n return message === null;\n };\n const hasRule = options.validator != null || inputTypeHasValidationRule(inputType, props.validationPattern);\n\n const dictation = useDictation({\n enabled: props.voiceEnabled === true,\n locale: props.voiceLocale ?? null,\n readText: () => latestText.current,\n writeText: (value) => {\n setText(sanitize(value), { source: 'dictation' });\n },\n ...(props.onVoiceListeningStarted ? { onListeningStarted: props.onVoiceListeningStarted } : {}),\n ...(props.onVoiceListeningEnded ? { onListeningEnded: props.onVoiceListeningEnded } : {}),\n ...(props.onVoiceFailed ? { onFailed: props.onVoiceFailed } : {}),\n });\n\n // A value the field was given that its filter rejects is replaced once (MAUI OnTextChanged writes it back).\n const refiltered = useRef<string | null>(null);\n useEffect(() => {\n if (display !== text && refiltered.current !== text) {\n refiltered.current = text;\n setText(display, { source: 'programmatic' });\n }\n });\n\n // Keep the native element showing the field's value (lynx-ui pattern: `invoke('setValue')`). The node ref can\n // attach after the first effect, so attaching syncs too.\n const retries = useRef(0);\n const sync = () => {\n const value = latestText.current;\n if (native.current === value) return;\n if (invokeNode(elementRef, 'setValue', { value })) {\n native.current = value;\n retries.current = 0;\n } else if (elementRef.current && retries.current < 5) {\n // The element is not created natively yet (first commit): try again on the next tick.\n retries.current += 1;\n startTimer(() => syncRef.current(), 0);\n }\n };\n const syncRef = useRef(sync);\n syncRef.current = sync;\n const attach = useRef((node: NodesRef | null) => {\n elementRef.current = node;\n if (node) syncRef.current();\n }).current;\n useEffect(() => {\n sync();\n });\n\n // Clearing the value re-masks a revealed password (MAUI OnTextChanged).\n useEffect(() => {\n if (!hasValue && passwordVisible) setPasswordVisible(false);\n }, [hasValue, passwordVisible]);\n\n // New external error props win over an earlier validation result.\n const validationCurrent =\n validation !== null && validation.hasError === props.hasError && validation.errorText === props.errorText;\n const hasError = validationCurrent ? validation.message !== null : props.hasError === true;\n const errorText = validationCurrent && validation.message !== null ? validation.message : props.errorText;\n\n const onInput = (event: { detail?: InputDetail }) => {\n const raw = event.detail?.value ?? '';\n // Not an edit: the native element reports what it already holds (Android emits an empty `input` when a read-only\n // field is created, before `setValue` lands), or the user cannot type here at all. Forwarding it would wipe a\n // controlled value (a barcode field opened on an existing code came up empty).\n if (props.readOnly === true) {\n // Nobody types here: the native element drifted (Android clears a read-only input it just created) — show the\n // field's value again.\n native.current = raw;\n if (raw !== latestText.current) syncRef.current();\n return;\n }\n const composing = event.detail?.isComposing === true;\n const echo = !composing && !composingRef.current && raw === native.current;\n composingRef.current = composing;\n if (echo) return;\n native.current = raw;\n // IME composition is never interrupted: the composed text is filtered when it is committed.\n if (composing) return;\n const clean = sanitize(raw);\n latestText.current = clean;\n setText(clean, { source: 'user' });\n if (options.validateOnTextChanged) runValidation(clean);\n bump((n) => n + 1);\n };\n const onFocus = () => {\n focusedRef.current = true;\n setFocused(true);\n keyboardAware.onInputFocused?.();\n // Tapping the field while dictating means typing: end the session (ADR-0024).\n if (dictation.listening) void dictation.stop();\n props.onFocus?.();\n };\n const onBlur = () => {\n focusedRef.current = false;\n setFocused(false);\n keyboardAware.onInputBlurred?.();\n // Only fields with a rule validate on blur, so an externally set error survives.\n if (hasRule && latestText.current !== '') runValidation(latestText.current);\n props.onBlur?.();\n };\n const onConfirm = () => props.onConfirm?.(latestText.current);\n\n const focus = () => {\n if (props.disabled) return;\n invokeNode(elementRef, 'focus');\n };\n const blur = () => invokeNode(elementRef, 'blur');\n\n const showMic = options.showMic({ available: dictation.available, listening: dictation.listening, hasValue });\n const pressMic = () => {\n // The microphone never focuses the field, and starting takes the keyboard down (ADR-0024).\n if (!dictation.listening && focusedRef.current) blur();\n void dictation.toggle();\n };\n\n const direction = resolveInputTextDirection(\n props.inputTextDirection ?? G9TextInputDirection.MatchParent,\n inputType,\n options.isPassword === true,\n culture.direction,\n );\n const font =\n props.customFont && props.customFont.trim() !== ''\n ? props.customFont\n : culture.direction === 'rtl'\n ? culture.rtlFontFamily\n : culture.ltrFontFamily;\n\n const handle: G9TextInputHandle = {\n focus,\n blur,\n validate: () => runValidation(latestText.current),\n get isListening() {\n return dictation.listening;\n },\n toggleVoice: () => dictation.toggle(),\n startVoice: () => dictation.start(),\n stopVoice: () => dictation.stop(),\n get element() {\n return elementRef.current;\n },\n };\n\n return {\n text: display,\n setText,\n hasValue,\n focused,\n hasError,\n errorText,\n passwordVisible,\n setPasswordVisible,\n dictation,\n showMic,\n pressMic,\n focus,\n blur,\n handle,\n inputType,\n /** Element attributes and handlers shared by `<input>` and `<textarea>`. */\n elementProps: {\n ...g9KeyboardTargetProps,\n ref: attach,\n ...(props.inputId ? { id: props.inputId } : {}),\n 'ignore-focus': true,\n readonly: props.readOnly === true,\n disabled: props.disabled === true,\n maxlength: props.maxLength !== undefined && props.maxLength > 0 ? props.maxLength : 2147483647,\n bindinput: onInput,\n bindfocus: onFocus,\n bindblur: onBlur,\n bindconfirm: onConfirm,\n },\n textDirection: direction,\n font,\n };\n}\n"],"names":["resolveInputTextDirection","inputTextDirection","inputType","isPassword","cultureDirection","G9TextInputDirection","inputTypePrefersLeftToRight","invokeNode","ref","method","params","node","invokeNodeWhenReady","attempts","startTimer","useTextInput","props","options","_props_inputType","_props_defaultValue","_props_voiceLocale","_props_inputTextDirection","culture","useG9Culture","strings","useG9Strings","keyboardAware","useContext","KeyboardAwareTriggerContext","G9InputType","separator","decimalSeparatorFor","sanitize","raw","sanitizeInputText","text","setText","useControllableState","display","latestText","useRef","elementRef","native","composingRef","focused","setFocused","useState","focusedRef","passwordVisible","setPasswordVisible","bump","validation","setValidation","hasValue","runValidation","value","_runTextValidator","message","validateInputText","hasRule","inputTypeHasValidationRule","dictation","useDictation","refiltered","useEffect","retries","sync","syncRef","attach","validationCurrent","hasError","errorText","onInput","event","_event_detail","_event_detail1","composing","echo","clean","n","onFocus","onBlur","onConfirm","focus","blur","showMic","pressMic","direction","font","handle","g9KeyboardTargetProps","undefined"],"mappings":";;;;;;;;;;AAqGO,SAASA,0BACdC,kBAAwC,EACxCC,SAAsB,EACtBC,UAAmB,EACnBC,gBAA+B;IAE/B,IAAIH,uBAAuBI,qBAAqB,WAAW,EAAE,OAAO;IACpE,IAAIJ,uBAAuBI,qBAAqB,WAAW,EAAE,OAAO;IACpE,IAAIC,4BAA4BJ,cAAcC,YAAY,OAAO;IACjE,OAAOC;AACT;AAGO,SAASG,WACdC,GAAkC,EAClCC,MAAc,EACdC,MAAgC;IAEhC,MAAMC,OAAOH,IAAI,OAAO;IACxB,IAAI,CAACG,MAAM,OAAO;IAClB,IAAI;QACFA,KACG,MAAM,CAAC;YACNF;YACA,GAAIC,SAAS;gBAAEA;YAAO,IAAI,CAAC,CAAC;YAC5B,SAAS,KAAO;YAChB,MAAM,KAAO;QACf,GACC,IAAI;IACT,EAAE,OAAM;QAEN,OAAO;IACT;IACA,OAAO;AACT;AAMO,SAASE,oBACdJ,GAAkC,EAClCC,MAAc,EACdC,MAAgC,EAChCG,WAAW,CAAC;IAEZ,IAAIN,WAAWC,KAAKC,QAAQC,WAAWG,YAAY,GAAG;IACtDC,WAAW,IAAMF,oBAAoBJ,KAAKC,QAAQC,QAAQG,WAAW,IAAI;AAC3E;AA2BO,SAASE,aAAaC,KAAuB,EAAEC,OAA+B;QAIjEC,kBAMFC,qBA+BNC,oBAgHRC;IAxJF,MAAMC,UAAUC;IAChB,MAAMC,UAAUC;IAChB,MAAMC,gBAAgBC,WAAWC;IACjC,MAAM1B,YAAY,QAAAgB,CAAAA,mBAAAA,MAAM,SAAS,AAAD,IAAdA,mBAAmBW,YAAY,OAAO;IACxD,MAAMC,YAAYC,oBAAoBT,QAAQ,eAAe;IAC7D,MAAMU,WAAW,CAACC,MAAgBC,kBAAkBhC,WAAW+B,KAAKjB,MAAM,mBAAmB,EAAEc;IAE/F,MAAM,CAACK,MAAMC,QAAQ,GAAGC,qBAAqD;QAC3E,OAAOrB,MAAM,KAAK;QAClB,cAAc,QAAAG,CAAAA,sBAAAA,MAAM,YAAY,AAAD,IAAjBA,sBAAsB;QACpC,UAAUH,MAAM,aAAa;QAC7B,MAAMC,QAAQ,IAAI;IACpB;IACA,MAAMqB,UAAUN,SAASG;IACzB,MAAMI,aAAaC,OAAOF;IAC1BC,WAAW,OAAO,GAAGD;IAErB,MAAMG,aAAaD,OAAwB;IAC3C,MAAME,SAASF,OAAO;IAEtB,MAAMG,eAAeH,OAAO;IAC5B,MAAM,CAACI,SAASC,WAAW,GAAGC,SAAS;IACvC,MAAMC,aAAaP,OAAO;IAC1B,MAAM,CAACQ,iBAAiBC,mBAAmB,GAAGH,SAAS;IACvD,MAAM,GAAGI,KAAK,GAAGJ,SAAS;IAC1B,MAAM,CAACK,YAAYC,cAAc,GAAGN,SAAkC;IACtE,MAAMO,WAAWf,AAAY,OAAZA;IAEjB,MAAMgB,gBAAgB,CAACC;YAEnBC;YAGFxC;QAJA,MAAMyC,UAAAA,QACJD,CAAAA,oBAAAA,iBAAiBvC,QAAQ,SAAS,EAAEsC,MAAK,IAAzCC,oBACAE,kBAAkBxD,WAAWqD,OAAOvC,MAAM,iBAAiB,EAAEA,MAAM,mBAAmB,EAAEQ;QAC1F4B,cAAc;YAAEK;YAAS,UAAUzC,MAAM,QAAQ;YAAE,WAAWA,MAAM,SAAS;QAAC;gBAC9EA,CAAAA,4BAAAA,MAAM,kBAAkB,AAAD,KAAvBA,0BAAAA,IAAAA,CAAAA,OAA2ByC;QAC3B,OAAOA,AAAY,SAAZA;IACT;IACA,MAAME,UAAU1C,AAAqB,QAArBA,QAAQ,SAAS,IAAY2C,2BAA2B1D,WAAWc,MAAM,iBAAiB;IAE1G,MAAM6C,YAAYC,aAAa;QAC7B,SAAS9C,AAAuB,SAAvBA,MAAM,YAAY;QAC3B,QAAQ,QAAAI,CAAAA,qBAAAA,MAAM,WAAW,AAAD,IAAhBA,qBAAqB;QAC7B,UAAU,IAAMmB,WAAW,OAAO;QAClC,WAAW,CAACgB;YACVnB,QAAQJ,SAASuB,QAAQ;gBAAE,QAAQ;YAAY;QACjD;QACA,GAAIvC,MAAM,uBAAuB,GAAG;YAAE,oBAAoBA,MAAM,uBAAuB;QAAC,IAAI,CAAC,CAAC;QAC9F,GAAIA,MAAM,qBAAqB,GAAG;YAAE,kBAAkBA,MAAM,qBAAqB;QAAC,IAAI,CAAC,CAAC;QACxF,GAAIA,MAAM,aAAa,GAAG;YAAE,UAAUA,MAAM,aAAa;QAAC,IAAI,CAAC,CAAC;IAClE;IAGA,MAAM+C,aAAavB,OAAsB;IACzCwB,UAAU;QACR,IAAI1B,YAAYH,QAAQ4B,WAAW,OAAO,KAAK5B,MAAM;YACnD4B,WAAW,OAAO,GAAG5B;YACrBC,QAAQE,SAAS;gBAAE,QAAQ;YAAe;QAC5C;IACF;IAIA,MAAM2B,UAAUzB,OAAO;IACvB,MAAM0B,OAAO;QACX,MAAMX,QAAQhB,WAAW,OAAO;QAChC,IAAIG,OAAO,OAAO,KAAKa,OAAO;QAC9B,IAAIhD,WAAWkC,YAAY,YAAY;YAAEc;QAAM,IAAI;YACjDb,OAAO,OAAO,GAAGa;YACjBU,QAAQ,OAAO,GAAG;QACpB,OAAO,IAAIxB,WAAW,OAAO,IAAIwB,QAAQ,OAAO,GAAG,GAAG;YAEpDA,QAAQ,OAAO,IAAI;YACnBnD,WAAW,IAAMqD,QAAQ,OAAO,IAAI;QACtC;IACF;IACA,MAAMA,UAAU3B,OAAO0B;IACvBC,QAAQ,OAAO,GAAGD;IAClB,MAAME,SAAS5B,OAAO,CAAC7B;QACrB8B,WAAW,OAAO,GAAG9B;QACrB,IAAIA,MAAMwD,QAAQ,OAAO;IAC3B,GAAG,OAAO;IACVH,UAAU;QACRE;IACF;IAGAF,UAAU;QACR,IAAI,CAACX,YAAYL,iBAAiBC,mBAAmB;IACvD,GAAG;QAACI;QAAUL;KAAgB;IAG9B,MAAMqB,oBACJlB,AAAe,SAAfA,cAAuBA,WAAW,QAAQ,KAAKnC,MAAM,QAAQ,IAAImC,WAAW,SAAS,KAAKnC,MAAM,SAAS;IAC3G,MAAMsD,WAAWD,oBAAoBlB,AAAuB,SAAvBA,WAAW,OAAO,GAAYnC,AAAmB,SAAnBA,MAAM,QAAQ;IACjF,MAAMuD,YAAYF,qBAAqBlB,AAAuB,SAAvBA,WAAW,OAAO,GAAYA,WAAW,OAAO,GAAGnC,MAAM,SAAS;IAEzG,MAAMwD,UAAU,CAACC;;YACHC,eAWMC;QAXlB,MAAM1C,MAAM,QAANA,CAAAA,OAAAA,QAAMyC,CAAAA,gBAAAA,MAAM,MAAM,AAAD,IAAXA,KAAAA,IAAAA,cAAc,KAAK,AAAD,IAAC,OAAI;QAInC,IAAI1D,AAAmB,SAAnBA,MAAM,QAAQ,EAAW;YAG3B0B,OAAO,OAAO,GAAGT;YACjB,IAAIA,QAAQM,WAAW,OAAO,EAAE4B,QAAQ,OAAO;YAC/C;QACF;QACA,MAAMS,YAAYD,AAAAA,SAAAA,CAAAA,iBAAAA,MAAM,MAAM,AAAD,IAAXA,KAAAA,IAAAA,eAAc,WAAW,AAAD,MAAM;QAChD,MAAME,OAAO,CAACD,aAAa,CAACjC,aAAa,OAAO,IAAIV,QAAQS,OAAO,OAAO;QAC1EC,aAAa,OAAO,GAAGiC;QACvB,IAAIC,MAAM;QACVnC,OAAO,OAAO,GAAGT;QAEjB,IAAI2C,WAAW;QACf,MAAME,QAAQ9C,SAASC;QACvBM,WAAW,OAAO,GAAGuC;QACrB1C,QAAQ0C,OAAO;YAAE,QAAQ;QAAO;QAChC,IAAI7D,QAAQ,qBAAqB,EAAEqC,cAAcwB;QACjD5B,KAAK,CAAC6B,IAAMA,IAAI;IAClB;IACA,MAAMC,UAAU;YAGdtD,+BAGAV;QALA+B,WAAW,OAAO,GAAG;QACrBF,WAAW;gBACXnB,CAAAA,gCAAAA,cAAc,cAAc,AAAD,KAA3BA,8BAAAA,IAAAA,CAAAA;QAEA,IAAImC,UAAU,SAAS,EAAOA,UAAU,IAAI;gBAC5C7C,CAAAA,iBAAAA,MAAM,OAAO,AAAD,KAAZA,eAAAA,IAAAA,CAAAA;IACF;IACA,MAAMiE,SAAS;YAGbvD,+BAGAV;QALA+B,WAAW,OAAO,GAAG;QACrBF,WAAW;gBACXnB,CAAAA,gCAAAA,cAAc,cAAc,AAAD,KAA3BA,8BAAAA,IAAAA,CAAAA;QAEA,IAAIiC,WAAWpB,AAAuB,OAAvBA,WAAW,OAAO,EAASe,cAAcf,WAAW,OAAO;gBAC1EvB,CAAAA,gBAAAA,MAAM,MAAM,AAAD,KAAXA,cAAAA,IAAAA,CAAAA;IACF;IACA,MAAMkE,YAAY;YAAMlE;uBAAAA,CAAAA,mBAAAA,MAAM,SAAS,AAAD,IAAdA,KAAAA,IAAAA,iBAAAA,IAAAA,CAAAA,OAAkBuB,WAAW,OAAO;;IAE5D,MAAM4C,QAAQ;QACZ,IAAInE,MAAM,QAAQ,EAAE;QACpBT,WAAWkC,YAAY;IACzB;IACA,MAAM2C,OAAO,IAAM7E,WAAWkC,YAAY;IAE1C,MAAM4C,UAAUpE,QAAQ,OAAO,CAAC;QAAE,WAAW4C,UAAU,SAAS;QAAE,WAAWA,UAAU,SAAS;QAAER;IAAS;IAC3G,MAAMiC,WAAW;QAEf,IAAI,CAACzB,UAAU,SAAS,IAAId,WAAW,OAAO,EAAEqC;QAC3CvB,UAAU,MAAM;IACvB;IAEA,MAAM0B,YAAYvF,0BAA0B,QAC1CqB,CAAAA,4BAAAA,MAAM,kBAAkB,AAAD,IAAvBA,4BAA4BhB,qBAAqB,WAAW,EAC5DH,WACAe,AAAuB,SAAvBA,QAAQ,UAAU,EAClBK,QAAQ,SAAS;IAEnB,MAAMkE,OACJxE,MAAM,UAAU,IAAIA,AAA4B,OAA5BA,MAAM,UAAU,CAAC,IAAI,KACrCA,MAAM,UAAU,GAChBM,AAAsB,UAAtBA,QAAQ,SAAS,GACfA,QAAQ,aAAa,GACrBA,QAAQ,aAAa;IAE7B,MAAMmE,SAA4B;QAChCN;QACAC;QACA,UAAU,IAAM9B,cAAcf,WAAW,OAAO;QAChD,IAAI;YACF,OAAOsB,UAAU,SAAS;QAC5B;QACA,aAAa,IAAMA,UAAU,MAAM;QACnC,YAAY,IAAMA,UAAU,KAAK;QACjC,WAAW,IAAMA,UAAU,IAAI;QAC/B,IAAI;YACF,OAAOpB,WAAW,OAAO;QAC3B;IACF;IAEA,OAAO;QACL,MAAMH;QACNF;QACAiB;QACAT;QACA0B;QACAC;QACAvB;QACAC;QACAY;QACAwB;QACAC;QACAH;QACAC;QACAK;QACAvF;QAEA,cAAc;YACZ,GAAGwF,qBAAqB;YACxB,KAAKtB;YACL,GAAIpD,MAAM,OAAO,GAAG;gBAAE,IAAIA,MAAM,OAAO;YAAC,IAAI,CAAC,CAAC;YAC9C,gBAAgB;YAChB,UAAUA,AAAmB,SAAnBA,MAAM,QAAQ;YACxB,UAAUA,AAAmB,SAAnBA,MAAM,QAAQ;YACxB,WAAWA,AAAoB2E,WAApB3E,MAAM,SAAS,IAAkBA,MAAM,SAAS,GAAG,IAAIA,MAAM,SAAS,GAAG;YACpF,WAAWwD;YACX,WAAWQ;YACX,UAAUC;YACV,aAAaC;QACf;QACA,eAAeK;QACfC;IACF;AACF"}
|
package/dist/host/hooks.d.ts
CHANGED
|
@@ -8,6 +8,11 @@ import type { G9HostHandle, G9HostInsets } from './registry.js';
|
|
|
8
8
|
export declare function useG9Host(): G9HostHandle;
|
|
9
9
|
/** Insets of the nearest host (MAUI `TopSafeAreaInset` … `BottomSafeAreaWithTabBar`). Re-renders when they change. */
|
|
10
10
|
export declare function useG9HostInsets(): G9HostInsets;
|
|
11
|
+
/**
|
|
12
|
+
* Insets of the nearest host, or null outside one — for controls that may be shown both inside a host (edge-to-edge,
|
|
13
|
+
* so they must clear the system bars) and without one (a gallery, a test): `G9IntroCarousel`'s chrome.
|
|
14
|
+
*/
|
|
15
|
+
export declare function useG9HostInsetsOrNull(): G9HostInsets | null;
|
|
11
16
|
/** Readiness of the nearest host, plus `release` (MAUI `ReleasePageLoadingOverlay`) and `whenDismissed`. */
|
|
12
17
|
export interface G9HostReadyState extends G9HostReadinessSnapshot {
|
|
13
18
|
release(): void;
|
package/dist/host/hooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/host/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,aAAa,EAEnB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,KAAK,SAAS,EAAiE,MAAM,gBAAgB,CAAC;AAG/G,OAAO,KAAK,EAAE,aAAa,EAAgB,MAAM,QAAQ,CAAC;AAG1D,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAM7D,+DAA+D;AAC/D,wBAAgB,SAAS,IAAI,YAAY,CAIxC;AAED,sHAAsH;AACtH,wBAAgB,eAAe,IAAI,YAAY,CAI9C;AAED,4GAA4G;AAC5G,MAAM,WAAW,gBAAiB,SAAQ,uBAAuB;IAC/D,OAAO,IAAI,IAAI,CAAC;IAChB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,gBAAgB,CAKjD;AAED,oCAAoC;AACpC,MAAM,WAAW,gBAAgB;IAC/B,4GAA4G;IAC5G,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,kDAAkD;IAClD,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,GAAE,gBAAqB,GAAG,IAAI,CAStF;AAED,yCAAyC;AACzC,MAAM,WAAW,qBAAqB;IACpC,iEAAiE;IACjE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,cAAc,EACrB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,SAAS,EAClB,OAAO,GAAE,qBAA0B,GAClC,IAAI,CAQN;AAED,oEAAoE;AACpE,MAAM,WAAW,mBAAmB;IAClC,wGAAwG;IACxG,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,kFAAkF;IAClF,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;KAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClG,mFAAmF;IACnF,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;KAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7F,0FAA0F;IAC1F,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IACpC,4GAA4G;IAC5G,QAAQ,CAAC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IAC5C,uFAAuF;IACvF,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAChC,kEAAkE;IAClE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,mBAAmB,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAiE1F;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,UAAO,GAAG,IAAI,CAG1D;AAED,mHAAmH;AACnH,wBAAgB,iBAAiB,IAAI,MAAM,IAAI,CAG9C"}
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/host/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,aAAa,EAEnB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,KAAK,SAAS,EAAiE,MAAM,gBAAgB,CAAC;AAG/G,OAAO,KAAK,EAAE,aAAa,EAAgB,MAAM,QAAQ,CAAC;AAG1D,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAM7D,+DAA+D;AAC/D,wBAAgB,SAAS,IAAI,YAAY,CAIxC;AAED,sHAAsH;AACtH,wBAAgB,eAAe,IAAI,YAAY,CAI9C;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,YAAY,GAAG,IAAI,CAE3D;AAED,4GAA4G;AAC5G,MAAM,WAAW,gBAAiB,SAAQ,uBAAuB;IAC/D,OAAO,IAAI,IAAI,CAAC;IAChB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,gBAAgB,CAKjD;AAED,oCAAoC;AACpC,MAAM,WAAW,gBAAgB;IAC/B,4GAA4G;IAC5G,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,kDAAkD;IAClD,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,GAAE,gBAAqB,GAAG,IAAI,CAStF;AAED,yCAAyC;AACzC,MAAM,WAAW,qBAAqB;IACpC,iEAAiE;IACjE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,cAAc,EACrB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,SAAS,EAClB,OAAO,GAAE,qBAA0B,GAClC,IAAI,CAQN;AAED,oEAAoE;AACpE,MAAM,WAAW,mBAAmB;IAClC,wGAAwG;IACxG,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,kFAAkF;IAClF,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;KAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClG,mFAAmF;IACnF,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;KAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7F,0FAA0F;IAC1F,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IACpC,4GAA4G;IAC5G,QAAQ,CAAC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IAC5C,uFAAuF;IACvF,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAChC,kEAAkE;IAClE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,mBAAmB,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAiE1F;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,UAAO,GAAG,IAAI,CAG1D;AAED,mHAAmH;AACnH,wBAAgB,iBAAiB,IAAI,MAAM,IAAI,CAG9C"}
|
package/dist/host/hooks.jsx
CHANGED
|
@@ -17,6 +17,9 @@ function useG9HostInsets() {
|
|
|
17
17
|
if (!insets) throw hostMissing('useG9HostInsets');
|
|
18
18
|
return insets;
|
|
19
19
|
}
|
|
20
|
+
function useG9HostInsetsOrNull() {
|
|
21
|
+
return useContext(G9HostInsetsContext);
|
|
22
|
+
}
|
|
20
23
|
function useG9HostReady() {
|
|
21
24
|
const readiness = useContext(G9HostReadinessContext);
|
|
22
25
|
if (!readiness) throw hostMissing('useG9HostReady');
|
|
@@ -158,6 +161,6 @@ function useG9HideKeyboard() {
|
|
|
158
161
|
const host = useG9Core().services.host;
|
|
159
162
|
return useStableCallback(()=>host.hideKeyboard());
|
|
160
163
|
}
|
|
161
|
-
export { useG9Activation, useG9Back, useG9HideKeyboard, useG9Host, useG9HostInsets, useG9HostReady, useG9LayerItem, useG9PanSoftInputMode };
|
|
164
|
+
export { useG9Activation, useG9Back, useG9HideKeyboard, useG9Host, useG9HostInsets, useG9HostInsetsOrNull, useG9HostReady, useG9LayerItem, useG9PanSoftInputMode };
|
|
162
165
|
|
|
163
166
|
//# sourceMappingURL=hooks.jsx.map
|
package/dist/host/hooks.jsx.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host/hooks.jsx","sources":["../../src/host/hooks.ts"],"sourcesContent":["import {\n createAbortController,\n type G9AbortController,\n type G9AbortSignal,\n G9Error,\n} from '@g9tm/lynxcontrols-foundation';\nimport { type ReactNode, useContext, useEffect, useRef, useState, useSyncExternalStore } from '@lynx-js/react';\nimport { useStableCallback } from '../base/use-stable-callback';\nimport { useG9Core, useG9Settings } from '../provider/hooks';\nimport type { G9BackHandler, G9BackResult } from './back';\nimport { G9HostContext, G9HostInsetsContext, G9HostReadinessContext } from './host';\nimport { acquirePanSoftInputMode } from './keyboard';\nimport type { G9Layer, G9OverlayLayer } from './layers';\nimport type { G9HostReadinessSnapshot } from './readiness';\nimport type { G9HostHandle, G9HostInsets } from './registry';\n\nfunction hostMissing(hook: string): G9Error {\n return new G9Error('host-missing', `${hook} must be used inside <G9Host>.`);\n}\n\n/** The nearest `G9Host`. Throws `host-missing` outside one. */\nexport function useG9Host(): G9HostHandle {\n const host = useContext(G9HostContext);\n if (!host) throw hostMissing('useG9Host');\n return host;\n}\n\n/** Insets of the nearest host (MAUI `TopSafeAreaInset` … `BottomSafeAreaWithTabBar`). Re-renders when they change. */\nexport function useG9HostInsets(): G9HostInsets {\n const insets = useContext(G9HostInsetsContext);\n if (!insets) throw hostMissing('useG9HostInsets');\n return insets;\n}\n\n/** Readiness of the nearest host, plus `release` (MAUI `ReleasePageLoadingOverlay`) and `whenDismissed`. */\nexport interface G9HostReadyState extends G9HostReadinessSnapshot {\n release(): void;\n whenDismissed(): Promise<void>;\n}\n\n/**\n * The nearest host's ready state and loading cover (MAUI `ReleasePageLoadingOverlay`, `PageLoadingOverlayDismissed`,\n * `G9ContentViewBase.ReleaseHostPageLoadingOverlay`). A page with `manualRelease` calls `release()` when its first\n * meaningful frame is ready.\n */\nexport function useG9HostReady(): G9HostReadyState {\n const readiness = useContext(G9HostReadinessContext);\n if (!readiness) throw hostMissing('useG9HostReady');\n const snapshot = useSyncExternalStore(readiness.subscribe, readiness.getSnapshot);\n return { ...snapshot, release: readiness.release, whenDismissed: readiness.whenDismissed };\n}\n\n/** Options of {@link useG9Back}. */\nexport interface G9UseBackOptions {\n /** The layer the handler belongs to (overlays pass theirs so they are asked first). Default `'content'`. */\n readonly layer?: G9Layer;\n /** Register only while `true`. Default `true`. */\n readonly enabled?: boolean;\n}\n\n/**\n * Registers a back handler on the nearest host while mounted (and enabled). Handlers of higher layers run first, then\n * newest first; returning `'handled'` (or `true`) consumes the press, `'pass'` lets it continue. When nothing handles\n * it, the provider calls `services.host.exit()`. The latest `handler` is always called.\n */\nexport function useG9Back(handler: G9BackHandler, options: G9UseBackOptions = {}): void {\n const host = useG9Host();\n const stable = useStableCallback(handler);\n const enabled = options.enabled ?? true;\n const layer = options.layer ?? 'content';\n useEffect(\n () => (enabled ? host.back.push(() => stable() as G9BackResult | boolean, { layer }) : undefined),\n [host, stable, enabled, layer],\n );\n}\n\n/** Options of {@link useG9LayerItem}. */\nexport interface G9UseLayerItemOptions {\n /** Ordering inside the layer (lower paints below). Default 0. */\n readonly order?: number;\n /** Mount only while `true`. Default `true`. */\n readonly enabled?: boolean;\n}\n\n/**\n * Mounts `element` into an overlay layer of the nearest host while the calling component is mounted (and enabled),\n * keeping it in step with `element`. The key must be unique within the layer.\n */\nexport function useG9LayerItem(\n layer: G9OverlayLayer,\n key: string,\n element: ReactNode,\n options: G9UseLayerItemOptions = {},\n): void {\n const host = useG9Host();\n const enabled = options.enabled ?? true;\n const order = options.order ?? 0;\n useEffect(\n () => (enabled ? host.registerLayerItem(layer, { key, element, order }) : undefined),\n [host, layer, key, element, order, enabled],\n );\n}\n\n/** Inputs of {@link useG9Activation} (MAUI `G9ContentViewBase`). */\nexport interface G9ActivationOptions {\n /** Whether this view is the active one (MAUI `Activate` / `Deactivate`, driven by the hosting page). */\n readonly active: boolean;\n /** First activation only (MAUI `OnFirstActivatedAsync`): heavy one-shot setup. */\n readonly onFirstActivated?: (context: { readonly signal: G9AbortSignal }) => void | Promise<void>;\n /** Every activation, after the first-activation work (MAUI `OnActivatedAsync`). */\n readonly onActivated?: (context: { readonly signal: G9AbortSignal }) => void | Promise<void>;\n /** Every deactivation, after the activation signal was aborted (MAUI `OnDeactivated`). */\n readonly onDeactivated?: () => void;\n /** Ask the app to pause background work while active (MAUI `SuppressesBackgroundWork`). Default `false`. */\n readonly suppressesBackgroundWork?: boolean;\n /** Back handling while active (MAUI `OnHardwareBackPressed`); asked after overlays. */\n readonly onBack?: G9BackHandler;\n /** Names the view in diagnostics. Default `'G9ActivatedView'`. */\n readonly name?: string;\n}\n\n/**\n * Activation lifecycle of a view kept alive across tab switches (MAUI `G9ContentViewBase`): a fresh abort signal per\n * activation (aborted on deactivation and unmount), first-activation and every-activation work run through the\n * provider's safe executor, the app's background-work pause held while active\n * (`settings.backgroundWorkSuppression`), and back handling while active. Unmounting while active deactivates too\n * (MAUI handler teardown: signal aborted, pause released, `onDeactivated` called). Returns whether the view is active.\n */\nexport function useG9Activation(options: G9ActivationOptions): { readonly active: boolean } {\n const core = useG9Core();\n const settings = useG9Settings();\n const latest = useRef(options);\n latest.current = options;\n const name = options.name ?? 'G9ActivatedView';\n const [session] = useState(() => ({\n firstDone: false,\n controller: null as G9AbortController | null,\n suppression: null as (() => void) | null,\n }));\n\n const deactivate = useStableCallback(() => {\n const controller = session.controller;\n if (!controller) return;\n session.controller = null;\n const suppression = session.suppression;\n session.suppression = null;\n suppression?.();\n controller.abort();\n const onDeactivated = latest.current.onDeactivated;\n if (onDeactivated) {\n void core.executor.run(() => onDeactivated(), {\n source: name,\n throttleKey: `${name}.deactivate`,\n enableThrottle: false,\n preventConcurrentExecution: false,\n });\n }\n });\n\n useEffect(() => {\n if (!options.active) {\n deactivate();\n return;\n }\n if (session.controller) return;\n const controller = createAbortController();\n session.controller = controller;\n if (latest.current.suppressesBackgroundWork) session.suppression = settings.backgroundWorkSuppression?.() ?? null;\n core.executor.runSafe(\n async (context) => {\n const signal = controller.signal;\n if (!session.firstDone) {\n session.firstDone = true;\n await latest.current.onFirstActivated?.({ signal });\n if (signal.aborted || context.signal.aborted) return;\n }\n await latest.current.onActivated?.({ signal });\n },\n { source: name, throttleKey: `${name}.activate`, enableThrottle: false, preventConcurrentExecution: false },\n );\n }, [options.active, session, core, settings, name, deactivate]);\n\n // Unmount while active: MAUI's handler teardown ran the same deactivation (without hiding the view).\n useEffect(() => () => deactivate(), [deactivate]);\n\n const host = useContext(G9HostContext);\n const onBack = useStableCallback(() => latest.current.onBack?.() ?? 'pass');\n const hasBack = options.onBack !== undefined;\n useEffect(\n () => (host && options.active && hasBack ? host.back.push(() => onBack() ?? 'pass') : undefined),\n [host, options.active, hasBack, onBack],\n );\n return { active: options.active };\n}\n\n/**\n * Holds Android's pan soft-input mode while `enabled` (MAUI `G9KeyboardHelper.UseAndroidPanSoftInputMode` scoped to\n * a sheet or page); restores on disable and unmount.\n */\nexport function useG9PanSoftInputMode(enabled = true): void {\n const host = useG9Core().services.host;\n useEffect(() => (enabled ? acquirePanSoftInputMode(host) : undefined), [enabled, host]);\n}\n\n/** The keyboard dismiss path (MAUI `G9KeyboardHelper.HideKeyboardAndClearFocus`): `services.host.hideKeyboard`. */\nexport function useG9HideKeyboard(): () => void {\n const host = useG9Core().services.host;\n return useStableCallback(() => host.hideKeyboard()) as () => void;\n}\n"],"names":["hostMissing","hook","G9Error","useG9Host","host","useContext","G9HostContext","useG9HostInsets","insets","G9HostInsetsContext","useG9HostReady","readiness","G9HostReadinessContext","snapshot","useSyncExternalStore","useG9Back","handler","options","_options_enabled","_options_layer","stable","useStableCallback","enabled","layer","useEffect","undefined","useG9LayerItem","key","element","_options_order","order","useG9Activation","_options_name","core","useG9Core","settings","useG9Settings","latest","useRef","name","session","useState","deactivate","controller","suppression","onDeactivated","createAbortController","context","_latest_current","signal","_latest_current1","onBack","hasBack","_onBack","useG9PanSoftInputMode","acquirePanSoftInputMode","useG9HideKeyboard"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"host/hooks.jsx","sources":["../../src/host/hooks.ts"],"sourcesContent":["import {\n createAbortController,\n type G9AbortController,\n type G9AbortSignal,\n G9Error,\n} from '@g9tm/lynxcontrols-foundation';\nimport { type ReactNode, useContext, useEffect, useRef, useState, useSyncExternalStore } from '@lynx-js/react';\nimport { useStableCallback } from '../base/use-stable-callback';\nimport { useG9Core, useG9Settings } from '../provider/hooks';\nimport type { G9BackHandler, G9BackResult } from './back';\nimport { G9HostContext, G9HostInsetsContext, G9HostReadinessContext } from './host';\nimport { acquirePanSoftInputMode } from './keyboard';\nimport type { G9Layer, G9OverlayLayer } from './layers';\nimport type { G9HostReadinessSnapshot } from './readiness';\nimport type { G9HostHandle, G9HostInsets } from './registry';\n\nfunction hostMissing(hook: string): G9Error {\n return new G9Error('host-missing', `${hook} must be used inside <G9Host>.`);\n}\n\n/** The nearest `G9Host`. Throws `host-missing` outside one. */\nexport function useG9Host(): G9HostHandle {\n const host = useContext(G9HostContext);\n if (!host) throw hostMissing('useG9Host');\n return host;\n}\n\n/** Insets of the nearest host (MAUI `TopSafeAreaInset` … `BottomSafeAreaWithTabBar`). Re-renders when they change. */\nexport function useG9HostInsets(): G9HostInsets {\n const insets = useContext(G9HostInsetsContext);\n if (!insets) throw hostMissing('useG9HostInsets');\n return insets;\n}\n\n/**\n * Insets of the nearest host, or null outside one — for controls that may be shown both inside a host (edge-to-edge,\n * so they must clear the system bars) and without one (a gallery, a test): `G9IntroCarousel`'s chrome.\n */\nexport function useG9HostInsetsOrNull(): G9HostInsets | null {\n return useContext(G9HostInsetsContext);\n}\n\n/** Readiness of the nearest host, plus `release` (MAUI `ReleasePageLoadingOverlay`) and `whenDismissed`. */\nexport interface G9HostReadyState extends G9HostReadinessSnapshot {\n release(): void;\n whenDismissed(): Promise<void>;\n}\n\n/**\n * The nearest host's ready state and loading cover (MAUI `ReleasePageLoadingOverlay`, `PageLoadingOverlayDismissed`,\n * `G9ContentViewBase.ReleaseHostPageLoadingOverlay`). A page with `manualRelease` calls `release()` when its first\n * meaningful frame is ready.\n */\nexport function useG9HostReady(): G9HostReadyState {\n const readiness = useContext(G9HostReadinessContext);\n if (!readiness) throw hostMissing('useG9HostReady');\n const snapshot = useSyncExternalStore(readiness.subscribe, readiness.getSnapshot);\n return { ...snapshot, release: readiness.release, whenDismissed: readiness.whenDismissed };\n}\n\n/** Options of {@link useG9Back}. */\nexport interface G9UseBackOptions {\n /** The layer the handler belongs to (overlays pass theirs so they are asked first). Default `'content'`. */\n readonly layer?: G9Layer;\n /** Register only while `true`. Default `true`. */\n readonly enabled?: boolean;\n}\n\n/**\n * Registers a back handler on the nearest host while mounted (and enabled). Handlers of higher layers run first, then\n * newest first; returning `'handled'` (or `true`) consumes the press, `'pass'` lets it continue. When nothing handles\n * it, the provider calls `services.host.exit()`. The latest `handler` is always called.\n */\nexport function useG9Back(handler: G9BackHandler, options: G9UseBackOptions = {}): void {\n const host = useG9Host();\n const stable = useStableCallback(handler);\n const enabled = options.enabled ?? true;\n const layer = options.layer ?? 'content';\n useEffect(\n () => (enabled ? host.back.push(() => stable() as G9BackResult | boolean, { layer }) : undefined),\n [host, stable, enabled, layer],\n );\n}\n\n/** Options of {@link useG9LayerItem}. */\nexport interface G9UseLayerItemOptions {\n /** Ordering inside the layer (lower paints below). Default 0. */\n readonly order?: number;\n /** Mount only while `true`. Default `true`. */\n readonly enabled?: boolean;\n}\n\n/**\n * Mounts `element` into an overlay layer of the nearest host while the calling component is mounted (and enabled),\n * keeping it in step with `element`. The key must be unique within the layer.\n */\nexport function useG9LayerItem(\n layer: G9OverlayLayer,\n key: string,\n element: ReactNode,\n options: G9UseLayerItemOptions = {},\n): void {\n const host = useG9Host();\n const enabled = options.enabled ?? true;\n const order = options.order ?? 0;\n useEffect(\n () => (enabled ? host.registerLayerItem(layer, { key, element, order }) : undefined),\n [host, layer, key, element, order, enabled],\n );\n}\n\n/** Inputs of {@link useG9Activation} (MAUI `G9ContentViewBase`). */\nexport interface G9ActivationOptions {\n /** Whether this view is the active one (MAUI `Activate` / `Deactivate`, driven by the hosting page). */\n readonly active: boolean;\n /** First activation only (MAUI `OnFirstActivatedAsync`): heavy one-shot setup. */\n readonly onFirstActivated?: (context: { readonly signal: G9AbortSignal }) => void | Promise<void>;\n /** Every activation, after the first-activation work (MAUI `OnActivatedAsync`). */\n readonly onActivated?: (context: { readonly signal: G9AbortSignal }) => void | Promise<void>;\n /** Every deactivation, after the activation signal was aborted (MAUI `OnDeactivated`). */\n readonly onDeactivated?: () => void;\n /** Ask the app to pause background work while active (MAUI `SuppressesBackgroundWork`). Default `false`. */\n readonly suppressesBackgroundWork?: boolean;\n /** Back handling while active (MAUI `OnHardwareBackPressed`); asked after overlays. */\n readonly onBack?: G9BackHandler;\n /** Names the view in diagnostics. Default `'G9ActivatedView'`. */\n readonly name?: string;\n}\n\n/**\n * Activation lifecycle of a view kept alive across tab switches (MAUI `G9ContentViewBase`): a fresh abort signal per\n * activation (aborted on deactivation and unmount), first-activation and every-activation work run through the\n * provider's safe executor, the app's background-work pause held while active\n * (`settings.backgroundWorkSuppression`), and back handling while active. Unmounting while active deactivates too\n * (MAUI handler teardown: signal aborted, pause released, `onDeactivated` called). Returns whether the view is active.\n */\nexport function useG9Activation(options: G9ActivationOptions): { readonly active: boolean } {\n const core = useG9Core();\n const settings = useG9Settings();\n const latest = useRef(options);\n latest.current = options;\n const name = options.name ?? 'G9ActivatedView';\n const [session] = useState(() => ({\n firstDone: false,\n controller: null as G9AbortController | null,\n suppression: null as (() => void) | null,\n }));\n\n const deactivate = useStableCallback(() => {\n const controller = session.controller;\n if (!controller) return;\n session.controller = null;\n const suppression = session.suppression;\n session.suppression = null;\n suppression?.();\n controller.abort();\n const onDeactivated = latest.current.onDeactivated;\n if (onDeactivated) {\n void core.executor.run(() => onDeactivated(), {\n source: name,\n throttleKey: `${name}.deactivate`,\n enableThrottle: false,\n preventConcurrentExecution: false,\n });\n }\n });\n\n useEffect(() => {\n if (!options.active) {\n deactivate();\n return;\n }\n if (session.controller) return;\n const controller = createAbortController();\n session.controller = controller;\n if (latest.current.suppressesBackgroundWork) session.suppression = settings.backgroundWorkSuppression?.() ?? null;\n core.executor.runSafe(\n async (context) => {\n const signal = controller.signal;\n if (!session.firstDone) {\n session.firstDone = true;\n await latest.current.onFirstActivated?.({ signal });\n if (signal.aborted || context.signal.aborted) return;\n }\n await latest.current.onActivated?.({ signal });\n },\n { source: name, throttleKey: `${name}.activate`, enableThrottle: false, preventConcurrentExecution: false },\n );\n }, [options.active, session, core, settings, name, deactivate]);\n\n // Unmount while active: MAUI's handler teardown ran the same deactivation (without hiding the view).\n useEffect(() => () => deactivate(), [deactivate]);\n\n const host = useContext(G9HostContext);\n const onBack = useStableCallback(() => latest.current.onBack?.() ?? 'pass');\n const hasBack = options.onBack !== undefined;\n useEffect(\n () => (host && options.active && hasBack ? host.back.push(() => onBack() ?? 'pass') : undefined),\n [host, options.active, hasBack, onBack],\n );\n return { active: options.active };\n}\n\n/**\n * Holds Android's pan soft-input mode while `enabled` (MAUI `G9KeyboardHelper.UseAndroidPanSoftInputMode` scoped to\n * a sheet or page); restores on disable and unmount.\n */\nexport function useG9PanSoftInputMode(enabled = true): void {\n const host = useG9Core().services.host;\n useEffect(() => (enabled ? acquirePanSoftInputMode(host) : undefined), [enabled, host]);\n}\n\n/** The keyboard dismiss path (MAUI `G9KeyboardHelper.HideKeyboardAndClearFocus`): `services.host.hideKeyboard`. */\nexport function useG9HideKeyboard(): () => void {\n const host = useG9Core().services.host;\n return useStableCallback(() => host.hideKeyboard()) as () => void;\n}\n"],"names":["hostMissing","hook","G9Error","useG9Host","host","useContext","G9HostContext","useG9HostInsets","insets","G9HostInsetsContext","useG9HostInsetsOrNull","useG9HostReady","readiness","G9HostReadinessContext","snapshot","useSyncExternalStore","useG9Back","handler","options","_options_enabled","_options_layer","stable","useStableCallback","enabled","layer","useEffect","undefined","useG9LayerItem","key","element","_options_order","order","useG9Activation","_options_name","core","useG9Core","settings","useG9Settings","latest","useRef","name","session","useState","deactivate","controller","suppression","onDeactivated","createAbortController","context","_latest_current","signal","_latest_current1","onBack","hasBack","_onBack","useG9PanSoftInputMode","acquirePanSoftInputMode","useG9HideKeyboard"],"mappings":"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"}
|
package/dist/host/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { createBackStack, type G9BackHandler, type G9BackOptions, type G9BackResult, type G9BackStack, type G9BackStackOptions, } from './back.js';
|
|
2
|
-
export { type G9ActivationOptions, type G9HostReadyState, type G9UseBackOptions, type G9UseLayerItemOptions, useG9Activation, useG9Back, useG9HideKeyboard, useG9Host, useG9HostInsets, useG9HostReady, useG9LayerItem, useG9PanSoftInputMode, } from './hooks.js';
|
|
2
|
+
export { type G9ActivationOptions, type G9HostReadyState, type G9UseBackOptions, type G9UseLayerItemOptions, useG9Activation, useG9Back, useG9HideKeyboard, useG9Host, useG9HostInsets, useG9HostInsetsOrNull, useG9HostReady, useG9LayerItem, useG9PanSoftInputMode, } from './hooks.js';
|
|
3
3
|
export { G9Host, type G9HostProps, type G9LayerContainer } from './host.js';
|
|
4
4
|
export { acquirePanSoftInputMode, g9KeyboardTargetProps, isKeyboardTarget } from './keyboard.js';
|
|
5
5
|
export { createLayerStore, G9Layer, type G9LayerEntry, type G9LayerItem, type G9LayerStore, type G9OverlayLayer, g9LayerOrder, layerRank, } from './layers.js';
|
package/dist/host/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/host/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,kBAAkB,GACxB,MAAM,QAAQ,CAAC;AAChB,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,eAAe,EACf,SAAS,EACT,iBAAiB,EACjB,SAAS,EACT,eAAe,EACf,cAAc,EACd,cAAc,EACd,qBAAqB,GACtB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9F,OAAO,EACL,gBAAgB,EAChB,OAAO,EACP,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,YAAY,EACZ,SAAS,GACV,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,oBAAoB,EAAE,KAAK,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAC9F,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,uBAAuB,EAC5B,mBAAmB,EACnB,6BAA6B,GAC9B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,OAAO,GACR,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/host/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,kBAAkB,GACxB,MAAM,QAAQ,CAAC;AAChB,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,eAAe,EACf,SAAS,EACT,iBAAiB,EACjB,SAAS,EACT,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,qBAAqB,GACtB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9F,OAAO,EACL,gBAAgB,EAChB,OAAO,EACP,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,YAAY,EACZ,SAAS,GACV,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,oBAAoB,EAAE,KAAK,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAC9F,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,uBAAuB,EAC5B,mBAAmB,EACnB,6BAA6B,GAC9B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,OAAO,GACR,MAAM,YAAY,CAAC"}
|
package/dist/host/index.jsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { createBackStack } from "./back.jsx";
|
|
2
|
-
export { useG9Activation, useG9Back, useG9HideKeyboard, useG9Host, useG9HostInsets, useG9HostReady, useG9LayerItem, useG9PanSoftInputMode } from "./hooks.jsx";
|
|
2
|
+
export { useG9Activation, useG9Back, useG9HideKeyboard, useG9Host, useG9HostInsets, useG9HostInsetsOrNull, useG9HostReady, useG9LayerItem, useG9PanSoftInputMode } from "./hooks.jsx";
|
|
3
3
|
export { G9Host } from "./host.jsx";
|
|
4
4
|
export { acquirePanSoftInputMode, g9KeyboardTargetProps, isKeyboardTarget } from "./keyboard.jsx";
|
|
5
5
|
export { G9Layer, createLayerStore, g9LayerOrder, layerRank } from "./layers.jsx";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frame.d.ts","sourceRoot":"","sources":["../../src/popup/frame.tsx"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"frame.d.ts","sourceRoot":"","sources":["../../src/popup/frame.tsx"],"names":[],"mappings":"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"}
|