@g9tm/lynxcontrols 1.4.4 → 1.4.7

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.
Files changed (72) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/base/pressable.d.ts.map +1 -1
  3. package/dist/base/pressable.jsx +2 -1
  4. package/dist/base/pressable.jsx.map +1 -1
  5. package/dist/cascade/cascade-panel.d.ts.map +1 -1
  6. package/dist/cascade/cascade-panel.jsx +2 -2
  7. package/dist/cascade/cascade-panel.jsx.map +1 -1
  8. package/dist/edge-panel/edge-panel.jsx +5 -5
  9. package/dist/edge-panel/edge-panel.jsx.map +1 -1
  10. package/dist/expander/expander.d.ts.map +1 -1
  11. package/dist/expander/expander.jsx +2 -1
  12. package/dist/expander/expander.jsx.map +1 -1
  13. package/dist/fields/index.d.ts +1 -1
  14. package/dist/fields/index.d.ts.map +1 -1
  15. package/dist/fields/index.jsx +1 -1
  16. package/dist/fields/use-text-input.d.ts +14 -1
  17. package/dist/fields/use-text-input.d.ts.map +1 -1
  18. package/dist/fields/use-text-input.jsx +17 -3
  19. package/dist/fields/use-text-input.jsx.map +1 -1
  20. package/dist/host/host.css.map +1 -1
  21. package/dist/host/host.d.ts +3 -2
  22. package/dist/host/host.d.ts.map +1 -1
  23. package/dist/host/host.jsx +2 -2
  24. package/dist/host/host.jsx.map +1 -1
  25. package/dist/plus-button/model.d.ts.map +1 -1
  26. package/dist/plus-button/model.jsx +5 -1
  27. package/dist/plus-button/model.jsx.map +1 -1
  28. package/dist/popup/frame.jsx +2 -2
  29. package/dist/popup/frame.jsx.map +1 -1
  30. package/dist/popup/service.d.ts.map +1 -1
  31. package/dist/popup/service.jsx +2 -2
  32. package/dist/popup/service.jsx.map +1 -1
  33. package/dist/provider/provider.css +4 -0
  34. package/dist/provider/provider.css.map +1 -1
  35. package/dist/provider/provider.d.ts.map +1 -1
  36. package/dist/provider/provider.jsx +4 -2
  37. package/dist/provider/provider.jsx.map +1 -1
  38. package/dist/selection/selection-sheet.d.ts +5 -0
  39. package/dist/selection/selection-sheet.d.ts.map +1 -1
  40. package/dist/selection/selection-sheet.jsx +7 -3
  41. package/dist/selection/selection-sheet.jsx.map +1 -1
  42. package/dist/sheet/frame.d.ts.map +1 -1
  43. package/dist/sheet/frame.jsx +30 -8
  44. package/dist/sheet/frame.jsx.map +1 -1
  45. package/dist/sheet/index.d.ts +1 -0
  46. package/dist/sheet/index.d.ts.map +1 -1
  47. package/dist/sheet/index.jsx +1 -0
  48. package/dist/sheet/motion.d.ts.map +1 -1
  49. package/dist/sheet/motion.jsx +14 -0
  50. package/dist/sheet/motion.jsx.map +1 -1
  51. package/dist/sheet/options.d.ts +13 -0
  52. package/dist/sheet/options.d.ts.map +1 -1
  53. package/dist/sheet/options.jsx.map +1 -1
  54. package/dist/sheet/scroll-indicator.d.ts +33 -0
  55. package/dist/sheet/scroll-indicator.d.ts.map +1 -0
  56. package/dist/sheet/scroll-indicator.jsx +84 -0
  57. package/dist/sheet/scroll-indicator.jsx.map +1 -0
  58. package/dist/sheet/sheet.css +14 -0
  59. package/dist/sheet/sheet.css.map +1 -1
  60. package/dist/sheet/sizing.d.ts +1 -1
  61. package/dist/sheet/sizing.d.ts.map +1 -1
  62. package/dist/sheet/sizing.jsx +2 -2
  63. package/dist/sheet/sizing.jsx.map +1 -1
  64. package/dist/tab-bar/tab-bar.d.ts.map +1 -1
  65. package/dist/tab-bar/tab-bar.jsx +11 -6
  66. package/dist/tab-bar/tab-bar.jsx.map +1 -1
  67. package/dist/toast/service.jsx +3 -3
  68. package/dist/toast/service.jsx.map +1 -1
  69. package/dist/toast/store.d.ts.map +1 -1
  70. package/dist/toast/store.jsx +3 -2
  71. package/dist/toast/store.jsx.map +1 -1
  72. package/package.json +3 -3
@@ -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 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 // The decimal separator the FIELD holds is always the ASCII '.', whatever the culture: Lynx's native `digit` input\n // accepts only ASCII digits and '.', and silently dropped the Persian '٫' — 1.6 showed (and would be edited) as 16\n // (AgriPad's harvest weights, 2026-11-02). A typed '٫' still normalises to '.' (filterDecimal); the digits themselves\n // are drawn Persian by the app's font. decimalSeparatorFor stays for callers that format text for display.\n const separator = '.';\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","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":"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"}
1
+ {"version":3,"file":"fields/use-text-input.jsx","sources":["../../src/fields/use-text-input.ts"],"sourcesContent":["import {\n G9InputType,\n type G9KeyboardType,\n G9NumberingSystem,\n G9TextInputDirection,\n} 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 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/** What the native field draws for its ASCII digits: `g9-digits` / `g9-decimal-separator` (lynxcontrols-native). */\nexport interface G9FieldDigits {\n readonly system: G9NumberingSystem;\n readonly decimalSeparator: string;\n}\n\n/**\n * The digits a field DRAWS (MAUI: the culture's FaNum font draws «15» as «۱۵» in every entry): the culture's numbering\n * system, and «٫» for the '.' of a decimal field. The text stays ASCII — what is typed, the value events and what is\n * stored never change (AgriPad owner, 2026-11-02). A custom font or a password draws ASCII, as in MAUI.\n */\nexport function resolveFieldDigits(\n numberingSystem: G9NumberingSystem,\n inputType: G9InputType,\n hasCustomFont: boolean,\n isPassword: boolean,\n): G9FieldDigits {\n if (hasCustomFont || isPassword || numberingSystem === G9NumberingSystem.Latin) {\n return { system: G9NumberingSystem.Latin, decimalSeparator: '' };\n }\n const decimal = inputType === G9InputType.Decimal || inputType === G9InputType.SignedDecimal;\n return { system: numberingSystem, decimalSeparator: decimal ? '٫' : '' };\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 // The decimal separator the FIELD holds is always the ASCII '.', whatever the culture: Lynx's native `digit` input\n // accepts only ASCII digits and '.', and silently dropped the Persian '٫' — 1.6 showed (and would be edited) as 16\n // (AgriPad's harvest weights, 2026-11-02). A typed '٫' still normalises to '.' (filterDecimal); the digits themselves\n // are drawn Persian by the app's font. decimalSeparatorFor stays for callers that format text for display.\n const separator = '.';\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 digits = resolveFieldDigits(\n culture.numberingSystem,\n inputType,\n Boolean(props.customFont && props.customFont.trim() !== ''),\n options.isPassword === true,\n );\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 'g9-digits': digits.system,\n 'g9-decimal-separator': digits.decimalSeparator,\n },\n textDirection: direction,\n font,\n };\n}\n"],"names":["resolveInputTextDirection","inputTextDirection","inputType","isPassword","cultureDirection","G9TextInputDirection","inputTypePrefersLeftToRight","resolveFieldDigits","numberingSystem","hasCustomFont","G9NumberingSystem","decimal","G9InputType","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","separator","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","digits","Boolean","handle","g9KeyboardTargetProps","undefined"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["webpack://./src/host/host.css"],"names":[],"mappings":"AACA;EAAE,sBAAsB;EACtB,OAAO;EACP,WAAW;EACX,YAAY;EACZ,aAAa;EACb,kBAAkB;EAClB,gBAAgB;AAClB;;AAIA;EADE,oBAAoB;EACpB,kBAAkB;EAClB,MAAM;EACN,SAAS;EACT,OAAO;EACP,QAAQ;AACV;;AAIA;EADE,sBAAsB;EACtB,aAAa;EACb,kBAAkB;EAClB,MAAM;EACN,SAAS;EACT,OAAO;EACP,QAAQ;AACV;;AAKA;EAFE,oBAAoB;EACpB,kBAAkB;EAClB,MAAM;EACN,SAAS;EACT,OAAO;EACP,QAAQ;AACV;;AAMA;EAHE,UAAU;EACV,uBAAuB;EACvB,mBAAmB;EACnB,uCAAuC;EACvC,wBAAwB;EACxB,8DAA8D;EAC9D,aAAa;EACb,kBAAkB;EAClB,MAAM;EACN,SAAS;EACT,OAAO;EACP,QAAQ;EACR,mBAAmB;AACrB;;AAMA;EAHE,UAAU;EACV,oBAAoB;AACtB;;AAMA;EAHE,mBAAmB;EACnB,iBAAiB;EACjB,uBAAuB;EACvB,mBAAmB;EACnB,WAAW;EACX,YAAY;EACZ,sCAAsC;AACxC;;AAMA;EAHE;IACE,oBAAoB;EACtB;;EAEA;IACE,yBAAyB;EAC3B;AACF","sourcesContent":["/* G9Host: one page frame. Sibling order below is the z-order (MAUI G9PageTemplate.xaml); nothing uses z-index. */\n.g9-host {\n display: flex;\n flex-direction: column;\n position: relative;\n flex: 1;\n width: 100%;\n height: 100%;\n overflow: hidden;\n}\n\n/* MAUI BackdropHost: behind the content, input-transparent, visible only when a sheet recedes the page. */\n.g9-host__backdrop {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n pointer-events: none;\n}\n\n.g9-host__content {\n display: flex;\n flex-direction: column;\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n}\n\n/* Overlay layers: full-size and input-transparent; items opt back in (pointer-events does not inherit). */\n.g9-host__layer {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n pointer-events: none;\n}\n\n/* The page-loading cover: topmost, input-opaque, centred spinner. */\n.g9-page-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n opacity: 1;\n transform: scale(1);\n transition-property: opacity, transform;\n transition-duration: 200ms;\n transition-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);\n}\n\n.g9-page-loading--exiting {\n opacity: 0;\n transform: scale(0.9);\n}\n\n.g9-page-loading__spinner {\n width: 48px;\n height: 48px;\n border-width: 4px;\n border-style: solid;\n border-radius: 24px;\n border-top-color: transparent;\n animation: g9-spin 900ms linear infinite;\n}\n\n@keyframes g9-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n"],"sourceRoot":""}
1
+ {"version":3,"sources":["webpack://./src/host/host.css"],"names":[],"mappings":"AACA;EAAE,sBAAsB;EACtB,OAAO;EACP,WAAW;EACX,YAAY;EACZ,aAAa;EACb,kBAAkB;EAClB,gBAAgB;AAClB;;AAIA;EADE,oBAAoB;EACpB,kBAAkB;EAClB,MAAM;EACN,SAAS;EACT,OAAO;EACP,QAAQ;AACV;;AAIA;EADE,sBAAsB;EACtB,aAAa;EACb,kBAAkB;EAClB,MAAM;EACN,SAAS;EACT,OAAO;EACP,QAAQ;AACV;;AAOA;EAJE,oBAAoB;EACpB,kBAAkB;EAClB,MAAM;EACN,SAAS;EACT,OAAO;EACP,QAAQ;AACV;;AAQA;EALE,UAAU;EACV,uBAAuB;EACvB,mBAAmB;EACnB,uCAAuC;EACvC,wBAAwB;EACxB,8DAA8D;EAC9D,aAAa;EACb,kBAAkB;EAClB,MAAM;EACN,SAAS;EACT,OAAO;EACP,QAAQ;EACR,mBAAmB;AACrB;;AAQA;EALE,UAAU;EACV,oBAAoB;AACtB;;AAQA;EALE,mBAAmB;EACnB,iBAAiB;EACjB,uBAAuB;EACvB,mBAAmB;EACnB,WAAW;EACX,YAAY;EACZ,sCAAsC;AACxC;;AAQA;EALE;IACE,oBAAoB;EACtB;;EAEA;IACE,yBAAyB;EAC3B;AACF","sourcesContent":["/* G9Host: one page frame. Sibling order below is the z-order (MAUI G9PageTemplate.xaml); nothing uses z-index. */\n.g9-host {\n display: flex;\n flex-direction: column;\n position: relative;\n flex: 1;\n width: 100%;\n height: 100%;\n overflow: hidden;\n}\n\n/* MAUI BackdropHost: behind the content, input-transparent, visible only when a sheet recedes the page. */\n.g9-host__backdrop {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n pointer-events: none;\n}\n\n.g9-host__content {\n display: flex;\n flex-direction: column;\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n}\n\n/* Overlay layers: full-size and input-transparent. Every item MUST opt back in with `pointer-events: auto` on its root:\n Lynx INHERITS pointer-events from the parent element, so an item without it is transparent too — its handlers never\n run and the touch reaches what is under the layer (AgriPad's Initialize cover let a tap open a tab, 2026-11-03). */\n.g9-host__layer {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n pointer-events: none;\n}\n\n/* The page-loading cover: topmost, input-opaque, centred spinner. */\n.g9-page-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n opacity: 1;\n transform: scale(1);\n transition-property: opacity, transform;\n transition-duration: 200ms;\n transition-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);\n}\n\n.g9-page-loading--exiting {\n opacity: 0;\n transform: scale(0.9);\n}\n\n.g9-page-loading__spinner {\n width: 48px;\n height: 48px;\n border-width: 4px;\n border-style: solid;\n border-radius: 24px;\n border-top-color: transparent;\n animation: g9-spin 900ms linear infinite;\n}\n\n@keyframes g9-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n"],"sourceRoot":""}
@@ -63,8 +63,9 @@ export declare const G9HostReadinessContext: import("react").Context<G9HostReadi
63
63
  * stack, readiness and loading cover, safe-area insets, tap-outside keyboard dismissal, and its registration in
64
64
  * `g9Hosts` for code outside the tree. One per page; hosts may nest. Must be inside `G9Provider`.
65
65
  *
66
- * Layers are input-transparent (`pointer-events: none`), so empty areas pass touches to the layers below while each
67
- * item receives its own touches; an empty layer renders nothing.
66
+ * Layers are input-transparent (`pointer-events: none`), so empty areas pass touches to the layers below; each item
67
+ * receives its own touches only when its root sets `pointer-events: auto` — Lynx inherits pointer-events, so an item
68
+ * without it is transparent as well. An empty layer renders nothing.
68
69
  */
69
70
  export declare function G9Host(props: G9HostProps): ReactNode;
70
71
  //# sourceMappingURL=host.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/host/host.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAW,MAAM,+BAA+B,CAAC;AAE5E,OAAO,EAIL,KAAK,SAAS,EAOf,MAAM,gBAAgB,CAAC;AAIxB,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,QAAQ,CAAC;AAE5D,OAAO,EAAuC,KAAK,cAAc,EAAgB,MAAM,UAAU,CAAC;AAElG,OAAO,EAAuB,KAAK,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAClF,OAAO,EAA4B,KAAK,YAAY,EAAE,KAAK,YAAY,EAAgB,MAAM,YAAY,CAAC;AAC1G,OAAO,YAAY,CAAC;AAEpB,oHAAoH;AACpH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,SAAS,CAAC;AAElD,+BAA+B;AAC/B,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC;IAC9B;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,sGAAsG;IACtG,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,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,mGAAmG;IACnG,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,2FAA2F;IAC3F,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,YAAY,GAAG,OAAO,CAAC;IAC/C,oHAAoH;IACpH,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC,oHAAoH;IACpH,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAChC,iHAAiH;IACjH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC,uHAAuH;IACvH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,wHAAwH;IACxH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,2HAA2H;IAC3H,QAAQ,CAAC,2BAA2B,CAAC,EAAE,OAAO,CAAC;IAC/C,iHAAiH;IACjH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAC7E,gHAAgH;IAChH,QAAQ,CAAC,+BAA+B,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3E,0FAA0F;IAC1F,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,+GAA+G;IAC/G,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,mCAAmC;AACnC,eAAO,MAAM,aAAa,8CAA2C,CAAC;AACtE,iCAAiC;AACjC,eAAO,MAAM,mBAAmB,8CAA2C,CAAC;AAC5E,+CAA+C;AAC/C,eAAO,MAAM,sBAAsB,2DAAwD,CAAC;AA+B5F;;;;;;;;GAQG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,SAAS,CAmNpD"}
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/host/host.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAiB,MAAM,+BAA+B,CAAC;AAElF,OAAO,EAIL,KAAK,SAAS,EAOf,MAAM,gBAAgB,CAAC;AAIxB,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,QAAQ,CAAC;AAE5D,OAAO,EAAuC,KAAK,cAAc,EAAgB,MAAM,UAAU,CAAC;AAElG,OAAO,EAAuB,KAAK,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAClF,OAAO,EAA4B,KAAK,YAAY,EAAE,KAAK,YAAY,EAAgB,MAAM,YAAY,CAAC;AAC1G,OAAO,YAAY,CAAC;AAEpB,oHAAoH;AACpH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,SAAS,CAAC;AAElD,+BAA+B;AAC/B,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC;IAC9B;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,sGAAsG;IACtG,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,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,mGAAmG;IACnG,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,2FAA2F;IAC3F,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,YAAY,GAAG,OAAO,CAAC;IAC/C,oHAAoH;IACpH,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC,oHAAoH;IACpH,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAChC,iHAAiH;IACjH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC,uHAAuH;IACvH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,wHAAwH;IACxH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,2HAA2H;IAC3H,QAAQ,CAAC,2BAA2B,CAAC,EAAE,OAAO,CAAC;IAC/C,iHAAiH;IACjH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAC7E,gHAAgH;IAChH,QAAQ,CAAC,+BAA+B,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3E,0FAA0F;IAC1F,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,+GAA+G;IAC/G,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,mCAAmC;AACnC,eAAO,MAAM,aAAa,8CAA2C,CAAC;AACtE,iCAAiC;AACjC,eAAO,MAAM,mBAAmB,8CAA2C,CAAC;AAC5E,+CAA+C;AAC/C,eAAO,MAAM,sBAAsB,2DAAwD,CAAC;AA+B5F;;;;;;;;;GASG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,SAAS,CAmNpD"}
@@ -1,4 +1,4 @@
1
- import { G9Error } from "@g9tm/lynxcontrols-foundation";
1
+ import { G9Error, g9Ms } from "@g9tm/lynxcontrols-foundation";
2
2
  import { OverlayView } from "@lynx-js/lynx-ui-overlay";
3
3
  import { Fragment, createContext, memo, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "@lynx-js/react";
4
4
  import { useStableCallback } from "../base/use-stable-callback.jsx";
@@ -210,7 +210,7 @@ function G9Host(props) {
210
210
  <view className="g9-host__content" style={{
211
211
  backgroundColor: null != (_props_background = props.background) ? _props_background : 'var(--g9-background)',
212
212
  transform: effect ? `translateY(${effect.translateY}px) scale(${effect.scale})` : 'translateY(0px) scale(1)',
213
- transition: `transform ${null != (_ref2 = null == effect ? void 0 : effect.durationMs) ? _ref2 : 300}ms ease-out`
213
+ transition: `transform ${g9Ms(null != (_ref2 = null == effect ? void 0 : effect.durationMs) ? _ref2 : 300)}ms ease-out`
214
214
  }}>
215
215
  {props.children}
216
216
  </view>
@@ -1 +1 @@
1
- {"version":3,"file":"host/host.jsx","sources":["../../src/host/host.tsx"],"sourcesContent":["import { type G9AbortSignal, G9Error } from '@g9tm/lynxcontrols-foundation';\nimport { OverlayView } from '@lynx-js/lynx-ui-overlay';\nimport {\n createContext,\n Fragment,\n memo,\n type ReactNode,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from '@lynx-js/react';\nimport { useStableCallback } from '../base/use-stable-callback';\nimport { G9KeyboardContext } from '../provider/contexts';\nimport { useG9Core, useG9SafeInsets, useG9Settings } from '../provider/hooks';\nimport { createBackStack, type G9BackResult } from './back';\nimport { isKeyboardTarget } from './keyboard';\nimport { createLayerStore, type G9LayerStore, type G9OverlayLayer, g9LayerOrder } from './layers';\nimport { G9PageLoadingOverlay } from './page-loading-overlay';\nimport { createHostReadiness, type G9HostReadinessController } from './readiness';\nimport { type G9HostContentEffect, type G9HostHandle, type G9HostInsets, hostRegistry } from './registry';\nimport './host.css';\n\n/** How a layer is mounted: in the page tree (default) or in a Lynx `<overlay>` above native views (maps, video). */\nexport type G9LayerContainer = 'tree' | 'overlay';\n\n/** Props of {@link G9Host}. */\nexport interface G9HostProps {\n readonly children?: ReactNode;\n /**\n * Whether the page is on screen (MAUI `Loaded`/`Unloaded`, tab activation). Default `true`. An inactive host stays\n * registered and becomes active again when set back to `true`; see `g9Hosts` for the resolution rule.\n */\n readonly active?: boolean;\n /** Names the page in diagnostics (the cover's busy activity is `page:<name>`). Default `'G9Host'`. */\n readonly name?: string;\n /**\n * The page's appearing work (MAUI `OnAppearingAfterParentAsync`), run through the provider's safe executor each time\n * the host becomes active; `signal` aborts when it stops being active or unmounts. On the first appearance the\n * loading cover waits for it (unless `manualRelease`).\n */\n readonly onAppearing?: (context: { readonly signal: G9AbortSignal }) => void | Promise<void>;\n /** Runs each time the host stops being active (MAUI `OnDisappearingAfterParentAsync`), guarded. */\n readonly onDisappearing?: () => void | Promise<void>;\n /** The page's own back handling (MAUI `TryHandleInAppBack`), asked after every overlay. */\n readonly onBack?: () => G9BackResult | boolean;\n /** Swallow every system back press before anything else runs (MAUI `IsHardwareBackSuppressed`). Default `false`. */\n readonly backSuppressed?: boolean;\n /** Show the page-loading cover until the page is ready (MAUI `G9PageLoadingOverlay`, always on). Default `true`. */\n readonly loadingCover?: boolean;\n /** The page releases the cover itself through `useG9HostReady().release()` (MAUI `PageLoadingManualRelease`). */\n readonly manualRelease?: boolean;\n /** Extra delay after ready (MAUI `PageLoadingDismissDelayMs`). Default `settings.pageLoading.dismissDelayMs` (369). */\n readonly dismissDelayMs?: number;\n /** Hard cap on the cover (MAUI `PageLoadingSafetyTimeoutMs`). Default `settings.pageLoading.safetyTimeoutMs` (5000). */\n readonly safetyTimeoutMs?: number;\n /** Dismiss the soft keyboard on a tap outside any keyboard target (MAUI `TapOutsideKeyboardDismisser`). Default `true`. */\n readonly dismissKeyboardOnTapOutside?: boolean;\n /** Per-layer container; a layer over a native view (map, video) needs `'overlay'`. Default `'tree'` for each. */\n readonly layerContainers?: Partial<Record<G9OverlayLayer, G9LayerContainer>>;\n /** MAUI `ComputeBottomSafeAreaWithTabBar`: the bottom inset plus the page's own tab bar. Default: the inset. */\n readonly computeBottomSafeAreaWithTabBar?: (bottomInset: number) => number;\n /** The page background (MAUI `ApplyThemedBackground`). Default `var(--g9-background)`. */\n readonly background?: string;\n /** The colour behind the content, shown when a sheet recedes the page (MAUI `BackdropHost`). Default black. */\n readonly backdropColor?: string;\n readonly className?: string;\n}\n\n/** The nearest host, for hooks. */\nexport const G9HostContext = createContext<G9HostHandle | null>(null);\n/** The nearest host's insets. */\nexport const G9HostInsetsContext = createContext<G9HostInsets | null>(null);\n/** The nearest host's readiness controller. */\nexport const G9HostReadinessContext = createContext<G9HostReadinessController | null>(null);\n\nconst OVERLAY_LAYERS = g9LayerOrder.filter((layer): layer is G9OverlayLayer => layer !== 'content');\nlet hostSequence = 0;\n\n// The inner name must differ from the binding: rslib renames `const X = memo(function X…)` with a module prefix and the\n// in-module `<X>` then compiles as an unknown intrinsic element (E20; scripts/check-dist-jsx.mjs).\nconst HostLayer = memo(function HostLayerRender(props: {\n readonly hostId: string;\n readonly store: G9LayerStore;\n readonly layer: G9OverlayLayer;\n readonly container: G9LayerContainer;\n}): ReactNode {\n const { hostId, store, layer, container } = props;\n const entries = useSyncExternalStore(\n (listener) => store.subscribe(layer, listener),\n () => store.getSnapshot(layer),\n );\n if (entries.length === 0) return null;\n const className = `g9-host__layer g9-host__layer--${layer}`;\n const items = entries.map((entry) => <Fragment key={entry.key}>{entry.element}</Fragment>);\n if (container === 'overlay') {\n return (\n <OverlayView container=\"window\" className={className} id={`${hostId}-${layer}`}>\n {items}\n </OverlayView>\n );\n }\n return <view className={className}>{items}</view>;\n});\n\n/**\n * The page frame (MAUI `G9PageBase` + `G9PageTemplate`): the content and the overlay layers in a fixed z-order\n * (`content` → `edgePanel` → `sheets` → `popups` → `feedback` → `floating`, then the loading cover), the page's back\n * stack, readiness and loading cover, safe-area insets, tap-outside keyboard dismissal, and its registration in\n * `g9Hosts` for code outside the tree. One per page; hosts may nest. Must be inside `G9Provider`.\n *\n * Layers are input-transparent (`pointer-events: none`), so empty areas pass touches to the layers below while each\n * item receives its own touches; an empty layer renders nothing.\n */\nexport function G9Host(props: G9HostProps): ReactNode {\n const core = useG9Core();\n const settings = useG9Settings();\n const parent = useContext(G9HostContext);\n const keyboard = useContext(G9KeyboardContext);\n const providerInsets = useG9SafeInsets();\n const active = props.active ?? true;\n const name = props.name ?? 'G9Host';\n\n const latest = useRef(props);\n latest.current = props;\n\n const bottomWithTabBar = props.computeBottomSafeAreaWithTabBar\n ? props.computeBottomSafeAreaWithTabBar(providerInsets.bottom)\n : providerInsets.bottom;\n const insets = useMemo<G9HostInsets>(\n () => Object.freeze({ ...providerInsets, bottomWithTabBar }),\n [providerInsets, bottomWithTabBar],\n );\n const insetsRef = useRef(insets);\n insetsRef.current = insets;\n\n const [state] = useState(() => {\n hostSequence += 1;\n const id = `g9-host-${hostSequence}`;\n const layers = createLayerStore();\n const back = createBackStack({\n isSuppressed: () => latest.current.backSuppressed === true,\n onHandlerError: (error) =>\n core.diagnostics.log({ level: 'error', message: 'A back handler threw.', source: name, error }),\n });\n const features = new Map<string, unknown>();\n let released = false;\n let contentEffect: G9HostContentEffect | null = null;\n const effectListeners = new Set<() => void>();\n const readiness = createHostReadiness({\n cover: props.loadingCover ?? true,\n manualRelease: props.manualRelease ?? false,\n dismissDelayMs: props.dismissDelayMs ?? settings.pageLoading.dismissDelayMs,\n safetyTimeoutMs: props.safetyTimeoutMs ?? settings.pageLoading.safetyTimeoutMs,\n startActivity: () => {\n const scope = core.diagnostics.activity(`page:${name}`);\n return () => scope.dispose();\n },\n runAppearing: async (signal) => {\n const onAppearing = latest.current.onAppearing;\n if (!onAppearing) return;\n await core.executor.run((context) => onAppearing({ signal: context.signal }), {\n source: name,\n throttleKey: `${id}.onAppearing`,\n enableThrottle: false,\n preventConcurrentExecution: false,\n signal,\n });\n },\n });\n const handle: G9HostHandle = {\n id,\n parent,\n services: core.services,\n layers,\n registerLayerItem(layer, item) {\n if (released) return () => {};\n return layers.register(layer, item);\n },\n removeLayerItem: (layer, key) => layers.remove(layer, key),\n back,\n getInsets: () => insetsRef.current,\n readiness,\n attachFeature(key, value) {\n if (features.has(key)) throw new G9Error('host-feature', `Host feature '${String(key)}' is already attached.`);\n features.set(key, value);\n return () => {\n if (features.get(key) === value) features.delete(key);\n };\n },\n getFeature: (key) => features.get(key) as never,\n get released() {\n return released;\n },\n setContentEffect(effect) {\n if (released || contentEffect === effect) return;\n contentEffect = effect;\n for (const listener of [...effectListeners]) listener();\n },\n getContentEffect: () => contentEffect,\n };\n const effectStore = {\n subscribe(listener: () => void) {\n effectListeners.add(listener);\n return () => {\n effectListeners.delete(listener);\n };\n },\n getSnapshot: () => contentEffect,\n };\n return {\n handle,\n readiness,\n effectStore,\n release() {\n released = true;\n features.clear();\n },\n };\n });\n const { handle, readiness, effectStore } = state;\n\n // Unmount: synchronous unregistration and release of everything the host owns.\n useEffect(\n () => () => {\n hostRegistry.remove(handle);\n readiness.dispose();\n handle.layers.clear();\n handle.back.clear();\n state.release();\n },\n [handle, readiness, state],\n );\n\n // Visibility drives the registry and the appearing/disappearing lifecycle.\n const wasActive = useRef<boolean | null>(null);\n useEffect(() => {\n const previous = wasActive.current;\n wasActive.current = active;\n if (active) {\n hostRegistry.activate(handle);\n readiness.appear();\n return;\n }\n if (previous === null) {\n hostRegistry.register(handle);\n return;\n }\n hostRegistry.markOffScreen(handle);\n readiness.disappear();\n const onDisappearing = latest.current.onDisappearing;\n if (onDisappearing) {\n core.executor.runSafe(() => onDisappearing(), {\n source: name,\n throttleKey: `${handle.id}.onDisappearing`,\n enableThrottle: false,\n preventConcurrentExecution: false,\n });\n }\n }, [active, handle, readiness, core, name]);\n\n // The page's own back handling sits in the content layer, below every overlay.\n const hasOnBack = props.onBack !== undefined;\n useEffect(\n () => (hasOnBack ? handle.back.push(() => latest.current.onBack?.() ?? 'pass') : undefined),\n [hasOnBack, handle],\n );\n\n const keyboardVisible = useRef(false);\n keyboardVisible.current = keyboard?.visible === true;\n const onCaptureTap = useStableCallback((event: { target?: { dataset?: Record<string, unknown> } }) => {\n if (!keyboardVisible.current || isKeyboardTarget(event.target)) return;\n core.services.host.hideKeyboard();\n });\n\n const cover = useSyncExternalStore(readiness.subscribe, readiness.getSnapshot).cover;\n const effect = useSyncExternalStore(effectStore.subscribe, effectStore.getSnapshot);\n const containers = props.layerContainers ?? {};\n const tapOutside = props.dismissKeyboardOnTapOutside ?? true;\n\n return (\n <G9HostContext.Provider value={handle}>\n <G9HostInsetsContext.Provider value={insets}>\n <G9HostReadinessContext.Provider value={readiness}>\n <view\n className={`g9-host${props.className ? ` ${props.className}` : ''}`}\n {...(tapOutside ? { 'capture-bindtap': onCaptureTap } : {})}\n >\n <view\n className=\"g9-host__backdrop\"\n style={{ backgroundColor: effect?.backdropColor ?? props.backdropColor ?? '#000000' }}\n />\n <view\n className=\"g9-host__content\"\n style={{\n backgroundColor: props.background ?? 'var(--g9-background)',\n transform: effect\n ? `translateY(${effect.translateY}px) scale(${effect.scale})`\n : 'translateY(0px) scale(1)',\n transition: `transform ${effect?.durationMs ?? 300}ms ease-out`,\n }}\n >\n {props.children}\n </view>\n {OVERLAY_LAYERS.map((layer) => (\n <HostLayer\n key={layer}\n hostId={handle.id}\n store={handle.layers}\n layer={layer}\n container={containers[layer] ?? 'tree'}\n />\n ))}\n {cover === 'hidden' ? null : (\n <G9PageLoadingOverlay\n exiting={cover === 'exiting'}\n backgroundColor={settings.pageLoading.backgroundColor}\n spinnerColor={settings.pageLoading.spinnerColor}\n />\n )}\n </view>\n </G9HostReadinessContext.Provider>\n </G9HostInsetsContext.Provider>\n </G9HostContext.Provider>\n );\n}\n"],"names":["G9HostContext","createContext","G9HostInsetsContext","G9HostReadinessContext","OVERLAY_LAYERS","g9LayerOrder","layer","hostSequence","HostLayer","memo","props","hostId","store","container","entries","useSyncExternalStore","listener","className","items","entry","Fragment","OverlayView","view","G9Host","_props_active","_props_name","_props_layerContainers","_props_dismissKeyboardOnTapOutside","_ref","_props_background","core","useG9Core","settings","useG9Settings","parent","useContext","keyboard","G9KeyboardContext","providerInsets","useG9SafeInsets","active","name","latest","useRef","bottomWithTabBar","insets","useMemo","Object","insetsRef","state","useState","_props_loadingCover","_props_manualRelease","_props_dismissDelayMs","_props_safetyTimeoutMs","id","layers","createLayerStore","back","createBackStack","error","features","Map","released","contentEffect","effectListeners","Set","readiness","createHostReadiness","scope","signal","onAppearing","context","handle","item","key","value","G9Error","String","effect","effectStore","useEffect","hostRegistry","wasActive","previous","onDisappearing","hasOnBack","undefined","_latest_current","keyboardVisible","onCaptureTap","useStableCallback","event","isKeyboardTarget","cover","containers","tapOutside","_containers_layer","G9PageLoadingOverlay"],"mappings":"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"}
1
+ {"version":3,"file":"host/host.jsx","sources":["../../src/host/host.tsx"],"sourcesContent":["import { type G9AbortSignal, G9Error, g9Ms } from '@g9tm/lynxcontrols-foundation';\nimport { OverlayView } from '@lynx-js/lynx-ui-overlay';\nimport {\n createContext,\n Fragment,\n memo,\n type ReactNode,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from '@lynx-js/react';\nimport { useStableCallback } from '../base/use-stable-callback';\nimport { G9KeyboardContext } from '../provider/contexts';\nimport { useG9Core, useG9SafeInsets, useG9Settings } from '../provider/hooks';\nimport { createBackStack, type G9BackResult } from './back';\nimport { isKeyboardTarget } from './keyboard';\nimport { createLayerStore, type G9LayerStore, type G9OverlayLayer, g9LayerOrder } from './layers';\nimport { G9PageLoadingOverlay } from './page-loading-overlay';\nimport { createHostReadiness, type G9HostReadinessController } from './readiness';\nimport { type G9HostContentEffect, type G9HostHandle, type G9HostInsets, hostRegistry } from './registry';\nimport './host.css';\n\n/** How a layer is mounted: in the page tree (default) or in a Lynx `<overlay>` above native views (maps, video). */\nexport type G9LayerContainer = 'tree' | 'overlay';\n\n/** Props of {@link G9Host}. */\nexport interface G9HostProps {\n readonly children?: ReactNode;\n /**\n * Whether the page is on screen (MAUI `Loaded`/`Unloaded`, tab activation). Default `true`. An inactive host stays\n * registered and becomes active again when set back to `true`; see `g9Hosts` for the resolution rule.\n */\n readonly active?: boolean;\n /** Names the page in diagnostics (the cover's busy activity is `page:<name>`). Default `'G9Host'`. */\n readonly name?: string;\n /**\n * The page's appearing work (MAUI `OnAppearingAfterParentAsync`), run through the provider's safe executor each time\n * the host becomes active; `signal` aborts when it stops being active or unmounts. On the first appearance the\n * loading cover waits for it (unless `manualRelease`).\n */\n readonly onAppearing?: (context: { readonly signal: G9AbortSignal }) => void | Promise<void>;\n /** Runs each time the host stops being active (MAUI `OnDisappearingAfterParentAsync`), guarded. */\n readonly onDisappearing?: () => void | Promise<void>;\n /** The page's own back handling (MAUI `TryHandleInAppBack`), asked after every overlay. */\n readonly onBack?: () => G9BackResult | boolean;\n /** Swallow every system back press before anything else runs (MAUI `IsHardwareBackSuppressed`). Default `false`. */\n readonly backSuppressed?: boolean;\n /** Show the page-loading cover until the page is ready (MAUI `G9PageLoadingOverlay`, always on). Default `true`. */\n readonly loadingCover?: boolean;\n /** The page releases the cover itself through `useG9HostReady().release()` (MAUI `PageLoadingManualRelease`). */\n readonly manualRelease?: boolean;\n /** Extra delay after ready (MAUI `PageLoadingDismissDelayMs`). Default `settings.pageLoading.dismissDelayMs` (369). */\n readonly dismissDelayMs?: number;\n /** Hard cap on the cover (MAUI `PageLoadingSafetyTimeoutMs`). Default `settings.pageLoading.safetyTimeoutMs` (5000). */\n readonly safetyTimeoutMs?: number;\n /** Dismiss the soft keyboard on a tap outside any keyboard target (MAUI `TapOutsideKeyboardDismisser`). Default `true`. */\n readonly dismissKeyboardOnTapOutside?: boolean;\n /** Per-layer container; a layer over a native view (map, video) needs `'overlay'`. Default `'tree'` for each. */\n readonly layerContainers?: Partial<Record<G9OverlayLayer, G9LayerContainer>>;\n /** MAUI `ComputeBottomSafeAreaWithTabBar`: the bottom inset plus the page's own tab bar. Default: the inset. */\n readonly computeBottomSafeAreaWithTabBar?: (bottomInset: number) => number;\n /** The page background (MAUI `ApplyThemedBackground`). Default `var(--g9-background)`. */\n readonly background?: string;\n /** The colour behind the content, shown when a sheet recedes the page (MAUI `BackdropHost`). Default black. */\n readonly backdropColor?: string;\n readonly className?: string;\n}\n\n/** The nearest host, for hooks. */\nexport const G9HostContext = createContext<G9HostHandle | null>(null);\n/** The nearest host's insets. */\nexport const G9HostInsetsContext = createContext<G9HostInsets | null>(null);\n/** The nearest host's readiness controller. */\nexport const G9HostReadinessContext = createContext<G9HostReadinessController | null>(null);\n\nconst OVERLAY_LAYERS = g9LayerOrder.filter((layer): layer is G9OverlayLayer => layer !== 'content');\nlet hostSequence = 0;\n\n// The inner name must differ from the binding: rslib renames `const X = memo(function X…)` with a module prefix and the\n// in-module `<X>` then compiles as an unknown intrinsic element (E20; scripts/check-dist-jsx.mjs).\nconst HostLayer = memo(function HostLayerRender(props: {\n readonly hostId: string;\n readonly store: G9LayerStore;\n readonly layer: G9OverlayLayer;\n readonly container: G9LayerContainer;\n}): ReactNode {\n const { hostId, store, layer, container } = props;\n const entries = useSyncExternalStore(\n (listener) => store.subscribe(layer, listener),\n () => store.getSnapshot(layer),\n );\n if (entries.length === 0) return null;\n const className = `g9-host__layer g9-host__layer--${layer}`;\n const items = entries.map((entry) => <Fragment key={entry.key}>{entry.element}</Fragment>);\n if (container === 'overlay') {\n return (\n <OverlayView container=\"window\" className={className} id={`${hostId}-${layer}`}>\n {items}\n </OverlayView>\n );\n }\n return <view className={className}>{items}</view>;\n});\n\n/**\n * The page frame (MAUI `G9PageBase` + `G9PageTemplate`): the content and the overlay layers in a fixed z-order\n * (`content` → `edgePanel` → `sheets` → `popups` → `feedback` → `floating`, then the loading cover), the page's back\n * stack, readiness and loading cover, safe-area insets, tap-outside keyboard dismissal, and its registration in\n * `g9Hosts` for code outside the tree. One per page; hosts may nest. Must be inside `G9Provider`.\n *\n * Layers are input-transparent (`pointer-events: none`), so empty areas pass touches to the layers below; each item\n * receives its own touches only when its root sets `pointer-events: auto` — Lynx inherits pointer-events, so an item\n * without it is transparent as well. An empty layer renders nothing.\n */\nexport function G9Host(props: G9HostProps): ReactNode {\n const core = useG9Core();\n const settings = useG9Settings();\n const parent = useContext(G9HostContext);\n const keyboard = useContext(G9KeyboardContext);\n const providerInsets = useG9SafeInsets();\n const active = props.active ?? true;\n const name = props.name ?? 'G9Host';\n\n const latest = useRef(props);\n latest.current = props;\n\n const bottomWithTabBar = props.computeBottomSafeAreaWithTabBar\n ? props.computeBottomSafeAreaWithTabBar(providerInsets.bottom)\n : providerInsets.bottom;\n const insets = useMemo<G9HostInsets>(\n () => Object.freeze({ ...providerInsets, bottomWithTabBar }),\n [providerInsets, bottomWithTabBar],\n );\n const insetsRef = useRef(insets);\n insetsRef.current = insets;\n\n const [state] = useState(() => {\n hostSequence += 1;\n const id = `g9-host-${hostSequence}`;\n const layers = createLayerStore();\n const back = createBackStack({\n isSuppressed: () => latest.current.backSuppressed === true,\n onHandlerError: (error) =>\n core.diagnostics.log({ level: 'error', message: 'A back handler threw.', source: name, error }),\n });\n const features = new Map<string, unknown>();\n let released = false;\n let contentEffect: G9HostContentEffect | null = null;\n const effectListeners = new Set<() => void>();\n const readiness = createHostReadiness({\n cover: props.loadingCover ?? true,\n manualRelease: props.manualRelease ?? false,\n dismissDelayMs: props.dismissDelayMs ?? settings.pageLoading.dismissDelayMs,\n safetyTimeoutMs: props.safetyTimeoutMs ?? settings.pageLoading.safetyTimeoutMs,\n startActivity: () => {\n const scope = core.diagnostics.activity(`page:${name}`);\n return () => scope.dispose();\n },\n runAppearing: async (signal) => {\n const onAppearing = latest.current.onAppearing;\n if (!onAppearing) return;\n await core.executor.run((context) => onAppearing({ signal: context.signal }), {\n source: name,\n throttleKey: `${id}.onAppearing`,\n enableThrottle: false,\n preventConcurrentExecution: false,\n signal,\n });\n },\n });\n const handle: G9HostHandle = {\n id,\n parent,\n services: core.services,\n layers,\n registerLayerItem(layer, item) {\n if (released) return () => {};\n return layers.register(layer, item);\n },\n removeLayerItem: (layer, key) => layers.remove(layer, key),\n back,\n getInsets: () => insetsRef.current,\n readiness,\n attachFeature(key, value) {\n if (features.has(key)) throw new G9Error('host-feature', `Host feature '${String(key)}' is already attached.`);\n features.set(key, value);\n return () => {\n if (features.get(key) === value) features.delete(key);\n };\n },\n getFeature: (key) => features.get(key) as never,\n get released() {\n return released;\n },\n setContentEffect(effect) {\n if (released || contentEffect === effect) return;\n contentEffect = effect;\n for (const listener of [...effectListeners]) listener();\n },\n getContentEffect: () => contentEffect,\n };\n const effectStore = {\n subscribe(listener: () => void) {\n effectListeners.add(listener);\n return () => {\n effectListeners.delete(listener);\n };\n },\n getSnapshot: () => contentEffect,\n };\n return {\n handle,\n readiness,\n effectStore,\n release() {\n released = true;\n features.clear();\n },\n };\n });\n const { handle, readiness, effectStore } = state;\n\n // Unmount: synchronous unregistration and release of everything the host owns.\n useEffect(\n () => () => {\n hostRegistry.remove(handle);\n readiness.dispose();\n handle.layers.clear();\n handle.back.clear();\n state.release();\n },\n [handle, readiness, state],\n );\n\n // Visibility drives the registry and the appearing/disappearing lifecycle.\n const wasActive = useRef<boolean | null>(null);\n useEffect(() => {\n const previous = wasActive.current;\n wasActive.current = active;\n if (active) {\n hostRegistry.activate(handle);\n readiness.appear();\n return;\n }\n if (previous === null) {\n hostRegistry.register(handle);\n return;\n }\n hostRegistry.markOffScreen(handle);\n readiness.disappear();\n const onDisappearing = latest.current.onDisappearing;\n if (onDisappearing) {\n core.executor.runSafe(() => onDisappearing(), {\n source: name,\n throttleKey: `${handle.id}.onDisappearing`,\n enableThrottle: false,\n preventConcurrentExecution: false,\n });\n }\n }, [active, handle, readiness, core, name]);\n\n // The page's own back handling sits in the content layer, below every overlay.\n const hasOnBack = props.onBack !== undefined;\n useEffect(\n () => (hasOnBack ? handle.back.push(() => latest.current.onBack?.() ?? 'pass') : undefined),\n [hasOnBack, handle],\n );\n\n const keyboardVisible = useRef(false);\n keyboardVisible.current = keyboard?.visible === true;\n const onCaptureTap = useStableCallback((event: { target?: { dataset?: Record<string, unknown> } }) => {\n if (!keyboardVisible.current || isKeyboardTarget(event.target)) return;\n core.services.host.hideKeyboard();\n });\n\n const cover = useSyncExternalStore(readiness.subscribe, readiness.getSnapshot).cover;\n const effect = useSyncExternalStore(effectStore.subscribe, effectStore.getSnapshot);\n const containers = props.layerContainers ?? {};\n const tapOutside = props.dismissKeyboardOnTapOutside ?? true;\n\n return (\n <G9HostContext.Provider value={handle}>\n <G9HostInsetsContext.Provider value={insets}>\n <G9HostReadinessContext.Provider value={readiness}>\n <view\n className={`g9-host${props.className ? ` ${props.className}` : ''}`}\n {...(tapOutside ? { 'capture-bindtap': onCaptureTap } : {})}\n >\n <view\n className=\"g9-host__backdrop\"\n style={{ backgroundColor: effect?.backdropColor ?? props.backdropColor ?? '#000000' }}\n />\n <view\n className=\"g9-host__content\"\n style={{\n backgroundColor: props.background ?? 'var(--g9-background)',\n transform: effect\n ? `translateY(${effect.translateY}px) scale(${effect.scale})`\n : 'translateY(0px) scale(1)',\n transition: `transform ${g9Ms(effect?.durationMs ?? 300)}ms ease-out`,\n }}\n >\n {props.children}\n </view>\n {OVERLAY_LAYERS.map((layer) => (\n <HostLayer\n key={layer}\n hostId={handle.id}\n store={handle.layers}\n layer={layer}\n container={containers[layer] ?? 'tree'}\n />\n ))}\n {cover === 'hidden' ? null : (\n <G9PageLoadingOverlay\n exiting={cover === 'exiting'}\n backgroundColor={settings.pageLoading.backgroundColor}\n spinnerColor={settings.pageLoading.spinnerColor}\n />\n )}\n </view>\n </G9HostReadinessContext.Provider>\n </G9HostInsetsContext.Provider>\n </G9HostContext.Provider>\n );\n}\n"],"names":["G9HostContext","createContext","G9HostInsetsContext","G9HostReadinessContext","OVERLAY_LAYERS","g9LayerOrder","layer","hostSequence","HostLayer","memo","props","hostId","store","container","entries","useSyncExternalStore","listener","className","items","entry","Fragment","OverlayView","view","G9Host","_props_active","_props_name","_props_layerContainers","_props_dismissKeyboardOnTapOutside","_ref","_props_background","core","useG9Core","settings","useG9Settings","parent","useContext","keyboard","G9KeyboardContext","providerInsets","useG9SafeInsets","active","name","latest","useRef","bottomWithTabBar","insets","useMemo","Object","insetsRef","state","useState","_props_loadingCover","_props_manualRelease","_props_dismissDelayMs","_props_safetyTimeoutMs","id","layers","createLayerStore","back","createBackStack","error","features","Map","released","contentEffect","effectListeners","Set","readiness","createHostReadiness","scope","signal","onAppearing","context","handle","item","key","value","G9Error","String","effect","effectStore","useEffect","hostRegistry","wasActive","previous","onDisappearing","hasOnBack","undefined","_latest_current","keyboardVisible","onCaptureTap","useStableCallback","event","isKeyboardTarget","cover","containers","tapOutside","g9Ms","_containers_layer","G9PageLoadingOverlay"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/plus-button/model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,0EAA0E;AAC1E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IACrC,wGAAwG;IACxG,QAAQ,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvE;AAED,mHAAmH;AACnH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,yBAAyB,EAAE,MAAM,CAAC;IAC3C,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,yBAAyB,EAAE,MAAM,CAAC;IAC3C,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,yBAAyB,EAAE,MAAM,CAAC;IAC3C,QAAQ,CAAC,uBAAuB,EAAE,MAAM,CAAC;IACzC,QAAQ,CAAC,wBAAwB,EAAE,MAAM,CAAC;CAC3C;AAED,wFAAwF;AACxF,eAAO,MAAM,oBAAoB,EAAE,kBAcjC,CAAC;AAEH,6DAA6D;AAC7D,MAAM,WAAW,wBAAwB;IACvC,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE,uDAAuD;IACvD,QAAQ,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACrE,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CACvE;AAED,wHAAwH;AACxH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACrE,QAAQ,CAAC,KAAK,EAAE,SAAS,wBAAwB,EAAE,CAAC;IACpD,2CAA2C;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,oBAAoB,CAwCnH;AAED,qFAAqF;AACrF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,CAExG"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/plus-button/model.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,0EAA0E;AAC1E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IACrC,wGAAwG;IACxG,QAAQ,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvE;AAED,mHAAmH;AACnH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,yBAAyB,EAAE,MAAM,CAAC;IAC3C,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,yBAAyB,EAAE,MAAM,CAAC;IAC3C,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,yBAAyB,EAAE,MAAM,CAAC;IAC3C,QAAQ,CAAC,uBAAuB,EAAE,MAAM,CAAC;IACzC,QAAQ,CAAC,wBAAwB,EAAE,MAAM,CAAC;CAC3C;AAED,wFAAwF;AACxF,eAAO,MAAM,oBAAoB,EAAE,kBAcjC,CAAC;AAEH,6DAA6D;AAC7D,MAAM,WAAW,wBAAwB;IACvC,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE,uDAAuD;IACvD,QAAQ,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACrE,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CACvE;AAED,wHAAwH;AACxH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACrE,QAAQ,CAAC,KAAK,EAAE,SAAS,wBAAwB,EAAE,CAAC;IACpD,2CAA2C;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,oBAAoB,CA2CnH;AAED,qFAAqF;AACrF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,CAExG"}
@@ -1,3 +1,4 @@
1
+ import { g9Ms } from "@g9tm/lynxcontrols-foundation";
1
2
  const g9PlusButtonDefaults = Object.freeze({
2
3
  mainSizeCollapsed: 69,
3
4
  mainSizeExpanded: 49,
@@ -14,7 +15,10 @@ const g9PlusButtonDefaults = Object.freeze({
14
15
  mainIconRotationExpanded: 45
15
16
  });
16
17
  function plusButtonSchedule(timing, count, expand) {
17
- const t = timing;
18
+ const t = Object.fromEntries(Object.entries(timing).map(([k, v])=>[
19
+ k,
20
+ k.endsWith('Ms') ? g9Ms(v) : v
21
+ ]));
18
22
  const items = [];
19
23
  let end = 0;
20
24
  if (expand) {
@@ -1 +1 @@
1
- {"version":3,"file":"plus-button/model.jsx","sources":["../../src/plus-button/model.ts"],"sourcesContent":["import type { G9IconInput } from '../icon/icon';\n\n/** One menu entry of a {@link G9PlusButton} (MAUI `G9PlusButtonItem`). */\nexport interface G9PlusButtonItem {\n readonly icon: G9IconInput;\n readonly text: string;\n /** Close the menu after `onSelected` settles. Default true. */\n readonly closeMenuOnSelect?: boolean;\n /** Runs through the provider's safe executor (errors show the error popup, MAUI `ShowErrorG9Popup`). */\n readonly onSelected: (item: G9PlusButtonItem) => void | Promise<void>;\n}\n\n/** Sizes and timings of the expand / collapse choreography (MAUI `G9PlusButton` properties and their defaults). */\nexport interface G9PlusButtonTiming {\n readonly mainSizeCollapsed: number;\n readonly mainSizeExpanded: number;\n readonly itemVerticalOffset: number;\n readonly textBorderTargetWidth: number;\n readonly itemsStartDelayMs: number;\n readonly itemStaggerMs: number;\n readonly phase1AnimationDurationMs: number;\n readonly phase2DelayDurationMs: number;\n readonly phase2AnimationDurationMs: number;\n readonly phase3DelayDurationMs: number;\n readonly phase3AnimationDurationMs: number;\n readonly mainAnimationDurationMs: number;\n readonly mainIconRotationExpanded: number;\n}\n\n/** The MAUI `G9PlusButton` sizes and timings (px, ms) every plus button starts from. */\nexport const g9PlusButtonDefaults: G9PlusButtonTiming = Object.freeze({\n mainSizeCollapsed: 69,\n mainSizeExpanded: 49,\n itemVerticalOffset: 55,\n textBorderTargetWidth: 139,\n itemsStartDelayMs: 50,\n itemStaggerMs: 40,\n phase1AnimationDurationMs: 200,\n phase2DelayDurationMs: 30,\n phase2AnimationDurationMs: 180,\n phase3DelayDurationMs: 20,\n phase3AnimationDurationMs: 150,\n mainAnimationDurationMs: 180,\n mainIconRotationExpanded: 45,\n});\n\n/** When each part of one item moves (ms from the toggle). */\nexport interface G9PlusButtonItemSchedule {\n /** Phase 1: the item slides to / from its row (translateY). */\n readonly slide: { readonly delay: number; readonly duration: number };\n /** Phase 2: the label pill grows / shrinks (width). */\n readonly pill: { readonly delay: number; readonly duration: number };\n /** Phase 3: the label fades (opacity). */\n readonly label: { readonly delay: number; readonly duration: number };\n}\n\n/** When each part of the expand/collapse sequence starts and how long it runs (ms): the main button, then each item. */\nexport interface G9PlusButtonSchedule {\n readonly main: { readonly delay: number; readonly duration: number };\n readonly items: readonly G9PlusButtonItemSchedule[];\n /** When the whole sequence has settled. */\n readonly totalMs: number;\n}\n\n/**\n * The MAUI choreography as start times. Expand: the main button shrinks and turns, then after `itemsStartDelayMs`\n * each item (staggered by `itemStaggerMs`, first item first) slides up, then its pill grows, then its label fades in.\n * Collapse runs the phases backwards, last item first, and the main button returns last.\n */\nexport function plusButtonSchedule(timing: G9PlusButtonTiming, count: number, expand: boolean): G9PlusButtonSchedule {\n const t = timing;\n const items: G9PlusButtonItemSchedule[] = [];\n let end = 0;\n if (expand) {\n const base = t.mainAnimationDurationMs + t.itemsStartDelayMs;\n for (let i = 0; i < count; i++) {\n const start = base + i * t.itemStaggerMs;\n const pill = start + t.phase1AnimationDurationMs + t.phase2DelayDurationMs;\n const label = pill + t.phase2AnimationDurationMs + t.phase3DelayDurationMs;\n items.push({\n slide: { delay: start, duration: t.phase1AnimationDurationMs },\n pill: { delay: pill, duration: t.phase2AnimationDurationMs },\n label: { delay: label, duration: t.phase3AnimationDurationMs },\n });\n end = Math.max(end, label + t.phase3AnimationDurationMs);\n }\n return {\n main: { delay: 0, duration: t.mainAnimationDurationMs },\n items,\n totalMs: Math.max(end, t.mainAnimationDurationMs),\n };\n }\n for (let i = 0; i < count; i++) {\n const start = (count - 1 - i) * t.itemStaggerMs;\n const pill = start + t.phase3AnimationDurationMs + t.phase3DelayDurationMs;\n const slide = pill + t.phase2AnimationDurationMs + t.phase2DelayDurationMs;\n items.push({\n slide: { delay: slide, duration: t.phase1AnimationDurationMs },\n pill: { delay: pill, duration: t.phase2AnimationDurationMs },\n label: { delay: start, duration: t.phase3AnimationDurationMs },\n });\n end = Math.max(end, slide + t.phase1AnimationDurationMs);\n }\n const mainDelay = (count > 0 ? end : 0) + t.itemsStartDelayMs;\n return {\n main: { delay: mainDelay, duration: t.mainAnimationDurationMs },\n items,\n totalMs: mainDelay + t.mainAnimationDurationMs,\n };\n}\n\n/** Hit-area height: the main button plus, while expanded, the item rows above it. */\nexport function plusButtonHitHeight(timing: G9PlusButtonTiming, count: number, expanded: boolean): number {\n return expanded ? timing.mainSizeCollapsed + count * timing.itemVerticalOffset : timing.mainSizeCollapsed;\n}\n"],"names":["g9PlusButtonDefaults","Object","plusButtonSchedule","timing","count","expand","t","items","end","base","i","start","pill","label","Math","slide","mainDelay","plusButtonHitHeight","expanded"],"mappings":"AA8BO,MAAMA,uBAA2CC,OAAO,MAAM,CAAC;IACpE,mBAAmB;IACnB,kBAAkB;IAClB,oBAAoB;IACpB,uBAAuB;IACvB,mBAAmB;IACnB,eAAe;IACf,2BAA2B;IAC3B,uBAAuB;IACvB,2BAA2B;IAC3B,uBAAuB;IACvB,2BAA2B;IAC3B,yBAAyB;IACzB,0BAA0B;AAC5B;AAyBO,SAASC,mBAAmBC,MAA0B,EAAEC,KAAa,EAAEC,MAAe;IAC3F,MAAMC,IAAIH;IACV,MAAMI,QAAoC,EAAE;IAC5C,IAAIC,MAAM;IACV,IAAIH,QAAQ;QACV,MAAMI,OAAOH,EAAE,uBAAuB,GAAGA,EAAE,iBAAiB;QAC5D,IAAK,IAAII,IAAI,GAAGA,IAAIN,OAAOM,IAAK;YAC9B,MAAMC,QAAQF,OAAOC,IAAIJ,EAAE,aAAa;YACxC,MAAMM,OAAOD,QAAQL,EAAE,yBAAyB,GAAGA,EAAE,qBAAqB;YAC1E,MAAMO,QAAQD,OAAON,EAAE,yBAAyB,GAAGA,EAAE,qBAAqB;YAC1EC,MAAM,IAAI,CAAC;gBACT,OAAO;oBAAE,OAAOI;oBAAO,UAAUL,EAAE,yBAAyB;gBAAC;gBAC7D,MAAM;oBAAE,OAAOM;oBAAM,UAAUN,EAAE,yBAAyB;gBAAC;gBAC3D,OAAO;oBAAE,OAAOO;oBAAO,UAAUP,EAAE,yBAAyB;gBAAC;YAC/D;YACAE,MAAMM,KAAK,GAAG,CAACN,KAAKK,QAAQP,EAAE,yBAAyB;QACzD;QACA,OAAO;YACL,MAAM;gBAAE,OAAO;gBAAG,UAAUA,EAAE,uBAAuB;YAAC;YACtDC;YACA,SAASO,KAAK,GAAG,CAACN,KAAKF,EAAE,uBAAuB;QAClD;IACF;IACA,IAAK,IAAII,IAAI,GAAGA,IAAIN,OAAOM,IAAK;QAC9B,MAAMC,QAASP,AAAAA,CAAAA,QAAQ,IAAIM,CAAAA,IAAKJ,EAAE,aAAa;QAC/C,MAAMM,OAAOD,QAAQL,EAAE,yBAAyB,GAAGA,EAAE,qBAAqB;QAC1E,MAAMS,QAAQH,OAAON,EAAE,yBAAyB,GAAGA,EAAE,qBAAqB;QAC1EC,MAAM,IAAI,CAAC;YACT,OAAO;gBAAE,OAAOQ;gBAAO,UAAUT,EAAE,yBAAyB;YAAC;YAC7D,MAAM;gBAAE,OAAOM;gBAAM,UAAUN,EAAE,yBAAyB;YAAC;YAC3D,OAAO;gBAAE,OAAOK;gBAAO,UAAUL,EAAE,yBAAyB;YAAC;QAC/D;QACAE,MAAMM,KAAK,GAAG,CAACN,KAAKO,QAAQT,EAAE,yBAAyB;IACzD;IACA,MAAMU,YAAaZ,AAAAA,CAAAA,QAAQ,IAAII,MAAM,KAAKF,EAAE,iBAAiB;IAC7D,OAAO;QACL,MAAM;YAAE,OAAOU;YAAW,UAAUV,EAAE,uBAAuB;QAAC;QAC9DC;QACA,SAASS,YAAYV,EAAE,uBAAuB;IAChD;AACF;AAGO,SAASW,oBAAoBd,MAA0B,EAAEC,KAAa,EAAEc,QAAiB;IAC9F,OAAOA,WAAWf,OAAO,iBAAiB,GAAGC,QAAQD,OAAO,kBAAkB,GAAGA,OAAO,iBAAiB;AAC3G"}
1
+ {"version":3,"file":"plus-button/model.jsx","sources":["../../src/plus-button/model.ts"],"sourcesContent":["import { g9Ms } from '@g9tm/lynxcontrols-foundation';\nimport type { G9IconInput } from '../icon/icon';\n\n/** One menu entry of a {@link G9PlusButton} (MAUI `G9PlusButtonItem`). */\nexport interface G9PlusButtonItem {\n readonly icon: G9IconInput;\n readonly text: string;\n /** Close the menu after `onSelected` settles. Default true. */\n readonly closeMenuOnSelect?: boolean;\n /** Runs through the provider's safe executor (errors show the error popup, MAUI `ShowErrorG9Popup`). */\n readonly onSelected: (item: G9PlusButtonItem) => void | Promise<void>;\n}\n\n/** Sizes and timings of the expand / collapse choreography (MAUI `G9PlusButton` properties and their defaults). */\nexport interface G9PlusButtonTiming {\n readonly mainSizeCollapsed: number;\n readonly mainSizeExpanded: number;\n readonly itemVerticalOffset: number;\n readonly textBorderTargetWidth: number;\n readonly itemsStartDelayMs: number;\n readonly itemStaggerMs: number;\n readonly phase1AnimationDurationMs: number;\n readonly phase2DelayDurationMs: number;\n readonly phase2AnimationDurationMs: number;\n readonly phase3DelayDurationMs: number;\n readonly phase3AnimationDurationMs: number;\n readonly mainAnimationDurationMs: number;\n readonly mainIconRotationExpanded: number;\n}\n\n/** The MAUI `G9PlusButton` sizes and timings (px, ms) every plus button starts from. */\nexport const g9PlusButtonDefaults: G9PlusButtonTiming = Object.freeze({\n mainSizeCollapsed: 69,\n mainSizeExpanded: 49,\n itemVerticalOffset: 55,\n textBorderTargetWidth: 139,\n itemsStartDelayMs: 50,\n itemStaggerMs: 40,\n phase1AnimationDurationMs: 200,\n phase2DelayDurationMs: 30,\n phase2AnimationDurationMs: 180,\n phase3DelayDurationMs: 20,\n phase3AnimationDurationMs: 150,\n mainAnimationDurationMs: 180,\n mainIconRotationExpanded: 45,\n});\n\n/** When each part of one item moves (ms from the toggle). */\nexport interface G9PlusButtonItemSchedule {\n /** Phase 1: the item slides to / from its row (translateY). */\n readonly slide: { readonly delay: number; readonly duration: number };\n /** Phase 2: the label pill grows / shrinks (width). */\n readonly pill: { readonly delay: number; readonly duration: number };\n /** Phase 3: the label fades (opacity). */\n readonly label: { readonly delay: number; readonly duration: number };\n}\n\n/** When each part of the expand/collapse sequence starts and how long it runs (ms): the main button, then each item. */\nexport interface G9PlusButtonSchedule {\n readonly main: { readonly delay: number; readonly duration: number };\n readonly items: readonly G9PlusButtonItemSchedule[];\n /** When the whole sequence has settled. */\n readonly totalMs: number;\n}\n\n/**\n * The MAUI choreography as start times. Expand: the main button shrinks and turns, then after `itemsStartDelayMs`\n * each item (staggered by `itemStaggerMs`, first item first) slides up, then its pill grows, then its label fades in.\n * Collapse runs the phases backwards, last item first, and the main button returns last.\n */\nexport function plusButtonSchedule(timing: G9PlusButtonTiming, count: number, expand: boolean): G9PlusButtonSchedule {\n // every phase, delay and stagger (the `…Ms` fields; never a size) at the motion scale (foundation g9Ms): at 0 the menu opens at once\n const t = Object.fromEntries(\n Object.entries(timing).map(([k, v]) => [k, k.endsWith('Ms') ? g9Ms(v as number) : v]),\n ) as unknown as G9PlusButtonTiming;\n const items: G9PlusButtonItemSchedule[] = [];\n let end = 0;\n if (expand) {\n const base = t.mainAnimationDurationMs + t.itemsStartDelayMs;\n for (let i = 0; i < count; i++) {\n const start = base + i * t.itemStaggerMs;\n const pill = start + t.phase1AnimationDurationMs + t.phase2DelayDurationMs;\n const label = pill + t.phase2AnimationDurationMs + t.phase3DelayDurationMs;\n items.push({\n slide: { delay: start, duration: t.phase1AnimationDurationMs },\n pill: { delay: pill, duration: t.phase2AnimationDurationMs },\n label: { delay: label, duration: t.phase3AnimationDurationMs },\n });\n end = Math.max(end, label + t.phase3AnimationDurationMs);\n }\n return {\n main: { delay: 0, duration: t.mainAnimationDurationMs },\n items,\n totalMs: Math.max(end, t.mainAnimationDurationMs),\n };\n }\n for (let i = 0; i < count; i++) {\n const start = (count - 1 - i) * t.itemStaggerMs;\n const pill = start + t.phase3AnimationDurationMs + t.phase3DelayDurationMs;\n const slide = pill + t.phase2AnimationDurationMs + t.phase2DelayDurationMs;\n items.push({\n slide: { delay: slide, duration: t.phase1AnimationDurationMs },\n pill: { delay: pill, duration: t.phase2AnimationDurationMs },\n label: { delay: start, duration: t.phase3AnimationDurationMs },\n });\n end = Math.max(end, slide + t.phase1AnimationDurationMs);\n }\n const mainDelay = (count > 0 ? end : 0) + t.itemsStartDelayMs;\n return {\n main: { delay: mainDelay, duration: t.mainAnimationDurationMs },\n items,\n totalMs: mainDelay + t.mainAnimationDurationMs,\n };\n}\n\n/** Hit-area height: the main button plus, while expanded, the item rows above it. */\nexport function plusButtonHitHeight(timing: G9PlusButtonTiming, count: number, expanded: boolean): number {\n return expanded ? timing.mainSizeCollapsed + count * timing.itemVerticalOffset : timing.mainSizeCollapsed;\n}\n"],"names":["g9PlusButtonDefaults","Object","plusButtonSchedule","timing","count","expand","t","k","v","g9Ms","items","end","base","i","start","pill","label","Math","slide","mainDelay","plusButtonHitHeight","expanded"],"mappings":";AA+BO,MAAMA,uBAA2CC,OAAO,MAAM,CAAC;IACpE,mBAAmB;IACnB,kBAAkB;IAClB,oBAAoB;IACpB,uBAAuB;IACvB,mBAAmB;IACnB,eAAe;IACf,2BAA2B;IAC3B,uBAAuB;IACvB,2BAA2B;IAC3B,uBAAuB;IACvB,2BAA2B;IAC3B,yBAAyB;IACzB,0BAA0B;AAC5B;AAyBO,SAASC,mBAAmBC,MAA0B,EAAEC,KAAa,EAAEC,MAAe;IAE3F,MAAMC,IAAIL,OAAO,WAAW,CAC1BA,OAAO,OAAO,CAACE,QAAQ,GAAG,CAAC,CAAC,CAACI,GAAGC,EAAE,GAAK;YAACD;YAAGA,EAAE,QAAQ,CAAC,QAAQE,KAAKD,KAAeA;SAAE;IAEtF,MAAME,QAAoC,EAAE;IAC5C,IAAIC,MAAM;IACV,IAAIN,QAAQ;QACV,MAAMO,OAAON,EAAE,uBAAuB,GAAGA,EAAE,iBAAiB;QAC5D,IAAK,IAAIO,IAAI,GAAGA,IAAIT,OAAOS,IAAK;YAC9B,MAAMC,QAAQF,OAAOC,IAAIP,EAAE,aAAa;YACxC,MAAMS,OAAOD,QAAQR,EAAE,yBAAyB,GAAGA,EAAE,qBAAqB;YAC1E,MAAMU,QAAQD,OAAOT,EAAE,yBAAyB,GAAGA,EAAE,qBAAqB;YAC1EI,MAAM,IAAI,CAAC;gBACT,OAAO;oBAAE,OAAOI;oBAAO,UAAUR,EAAE,yBAAyB;gBAAC;gBAC7D,MAAM;oBAAE,OAAOS;oBAAM,UAAUT,EAAE,yBAAyB;gBAAC;gBAC3D,OAAO;oBAAE,OAAOU;oBAAO,UAAUV,EAAE,yBAAyB;gBAAC;YAC/D;YACAK,MAAMM,KAAK,GAAG,CAACN,KAAKK,QAAQV,EAAE,yBAAyB;QACzD;QACA,OAAO;YACL,MAAM;gBAAE,OAAO;gBAAG,UAAUA,EAAE,uBAAuB;YAAC;YACtDI;YACA,SAASO,KAAK,GAAG,CAACN,KAAKL,EAAE,uBAAuB;QAClD;IACF;IACA,IAAK,IAAIO,IAAI,GAAGA,IAAIT,OAAOS,IAAK;QAC9B,MAAMC,QAASV,AAAAA,CAAAA,QAAQ,IAAIS,CAAAA,IAAKP,EAAE,aAAa;QAC/C,MAAMS,OAAOD,QAAQR,EAAE,yBAAyB,GAAGA,EAAE,qBAAqB;QAC1E,MAAMY,QAAQH,OAAOT,EAAE,yBAAyB,GAAGA,EAAE,qBAAqB;QAC1EI,MAAM,IAAI,CAAC;YACT,OAAO;gBAAE,OAAOQ;gBAAO,UAAUZ,EAAE,yBAAyB;YAAC;YAC7D,MAAM;gBAAE,OAAOS;gBAAM,UAAUT,EAAE,yBAAyB;YAAC;YAC3D,OAAO;gBAAE,OAAOQ;gBAAO,UAAUR,EAAE,yBAAyB;YAAC;QAC/D;QACAK,MAAMM,KAAK,GAAG,CAACN,KAAKO,QAAQZ,EAAE,yBAAyB;IACzD;IACA,MAAMa,YAAaf,AAAAA,CAAAA,QAAQ,IAAIO,MAAM,KAAKL,EAAE,iBAAiB;IAC7D,OAAO;QACL,MAAM;YAAE,OAAOa;YAAW,UAAUb,EAAE,uBAAuB;QAAC;QAC9DI;QACA,SAASS,YAAYb,EAAE,uBAAuB;IAChD;AACF;AAGO,SAASc,oBAAoBjB,MAA0B,EAAEC,KAAa,EAAEiB,QAAiB;IAC9F,OAAOA,WAAWlB,OAAO,iBAAiB,GAAGC,QAAQD,OAAO,kBAAkB,GAAGA,OAAO,iBAAiB;AAC3G"}
@@ -1,5 +1,5 @@
1
1
  import "./popup.css";
2
- import { formatColor, resolveThemeColor, withAlpha } from "@g9tm/lynxcontrols-foundation";
2
+ import { formatColor, g9Ms, resolveThemeColor, withAlpha } from "@g9tm/lynxcontrols-foundation";
3
3
  import { createContext, useContext, useEffect, useRef, useState } from "@lynx-js/react";
4
4
  import { g9SafeId } from "../base/control.jsx";
5
5
  import { g9FieldNotchStyle } from "../fields/notch.jsx";
@@ -128,7 +128,7 @@ function PopupFrame(props) {
128
128
  const notch = g9FieldNotchStyle(resolveThemeColor(null != (_o_cardBackground = o.cardBackground) ? _o_cardBackground : 'var(--g9-surface)', palette));
129
129
  const scrimColor = formatColor(withAlpha(resolveThemeColor(null != (_o_overlayColor = o.overlayColor) ? _o_overlayColor : 'var(--g9-scrim)', palette), 1));
130
130
  const animation = null != (_o_animation = o.animation) ? _o_animation : 'slideUp';
131
- const duration = null != (_o_animationDuration = o.animationDuration) ? _o_animationDuration : 240;
131
+ const duration = g9Ms(null != (_o_animationDuration = o.animationDuration) ? _o_animationDuration : 240);
132
132
  const mode = null != (_o_overlayMode = o.overlayMode) ? _o_overlayMode : 'transparent';
133
133
  const [size, setSize] = useState({
134
134
  width: 0,
@@ -1 +1 @@
1
- {"version":3,"file":"popup/frame.jsx","sources":["../../src/popup/frame.tsx"],"sourcesContent":["import './popup.css';\nimport { formatColor, resolveThemeColor, withAlpha } from '@g9tm/lynxcontrols-foundation';\nimport { createContext, type ReactNode, useContext, useEffect, useRef, useState } from '@lynx-js/react';\nimport { g9SafeId } from '../base/control';\nimport { g9FieldNotchStyle } from '../fields/notch';\nimport { useG9Theme } from '../provider/hooks';\nimport type {\n G9PopupAnimationEasing,\n G9PopupAnimationType,\n G9PopupAutoSizeMode,\n G9PopupBlurIntensity,\n G9PopupOverlayMode,\n G9PopupRelativePosition,\n} from './types';\nimport { popupScrimOpacity } from './types';\n\n/** A rectangle in host coordinates (px), e.g. an anchor's `boundingClientRect`. */\nexport interface G9Rect {\n readonly left: number;\n readonly top: number;\n readonly width: number;\n readonly height: number;\n}\n\n/** How one popup card opens (MAUI `G9PopupViewOpenOptions`). */\nexport interface G9PopupViewOpenOptions {\n /** Card width (px); unset = the auto-size mode decides (90 % of the host for centred `height` mode). */\n readonly width?: number | null;\n readonly height?: number | null;\n /** Default 16. */\n readonly cornerRadius?: number;\n /** `[left, top, right, bottom]`. Default `[20, 16, 20, 12]`. */\n readonly padding?: readonly [number, number, number, number];\n /** Default `'height'`. */\n readonly autoSizeMode?: G9PopupAutoSizeMode;\n readonly cardBackground?: string | null;\n readonly borderColor?: string | null;\n /** Default `'transparent'`; `'none'` = non-modal (no scrim, taps pass through). */\n readonly overlayMode?: G9PopupOverlayMode;\n readonly blurIntensity?: G9PopupBlurIntensity;\n /** Scrim colour (its opacity is `overlayOpacity`). Default the `Scrim` token. */\n readonly overlayColor?: string | null;\n /** Default 0.45. */\n readonly overlayOpacity?: number;\n /** Default false. */\n readonly closeOnBackgroundTap?: boolean;\n /** Default true. */\n readonly closeOnBackButton?: boolean;\n /** Default `'slideUp'`. */\n readonly animation?: G9PopupAnimationType;\n /** Default `'sinOut'`. */\n readonly animationEasing?: G9PopupAnimationEasing;\n /** Default 240 ms. */\n readonly animationDuration?: number;\n /** Close after this many ms; 0 = never. */\n readonly autoCloseDuration?: number;\n /** Anchor rectangle (MAUI `RelativeView`'s bounds); with `relativePosition`. */\n readonly relativeRect?: G9Rect | null;\n readonly relativePosition?: G9PopupRelativePosition | null;\n /** Extra offset added to the relative placement. */\n readonly relativeAbsoluteX?: number;\n readonly relativeAbsoluteY?: number;\n /** Absolute card position (host px). */\n readonly absoluteX?: number | null;\n readonly absoluteY?: number | null;\n /** The card can be dragged: by a `<G9PopupDragHandle>` inside it, or anywhere when there is none. */\n readonly isDraggable?: boolean;\n}\n\n/**\n * The size every MAUI popup RESTS at: `G9PopupView` builds its card container with `ScaleX = ScaleY = 0.92` and its\n * open animations only ever set `Scale` (which multiplies them), so the card, its text and its buttons all show at\n * 92 % — a 403 dp card measures 371 dp on screen (MAUI 6.2.36, Pixel 9 Pro XL). The port reproduces what users see.\n */\nexport const g9PopupRestingScale = 0.92;\n\n/** The pose a card starts from / leaves to, per motion (MAUI `G9PopupView` animation table). */\nexport function popupMotionPose(\n animation: G9PopupAnimationType,\n phase: 'enter' | 'exit',\n): {\n opacity: number;\n transform: string;\n} {\n switch (animation) {\n case 'none':\n return { opacity: phase === 'enter' ? 1 : 0, transform: 'translateY(0px) scale(1)' };\n case 'fadeIn':\n return { opacity: 0, transform: 'translateY(0px) scale(1)' };\n case 'zoomIn':\n return { opacity: 0, transform: 'translateY(0px) scale(0.92)' };\n case 'dropIn':\n return { opacity: 0, transform: 'translateY(-40px) scale(1)' };\n case 'bounce':\n // Opens from 0.6 with the bounce easing; closes like ZoomIn (MAUI).\n return { opacity: 0, transform: `translateY(0px) scale(${phase === 'enter' ? 0.6 : 0.92})` };\n default:\n return { opacity: 0, transform: 'translateY(40px) scale(1)' };\n }\n}\n\n/** CSS timing function of an easing (bounce approximated with an overshoot curve; CSS has no bounce). */\nexport function popupEasingCss(easing: G9PopupAnimationEasing): string {\n switch (easing) {\n case 'linear':\n return 'linear';\n case 'sinIn':\n return 'cubic-bezier(0.47, 0, 0.745, 0.715)';\n case 'sinInOut':\n return 'cubic-bezier(0.445, 0.05, 0.55, 0.95)';\n case 'cubicOut':\n return 'cubic-bezier(0.215, 0.61, 0.355, 1)';\n case 'bounceOut':\n return 'cubic-bezier(0.34, 1.56, 0.64, 1)';\n default:\n return 'cubic-bezier(0.39, 0.575, 0.565, 1)';\n }\n}\n\n/**\n * Where the card's top-left goes (host px) for a relative placement (MAUI `ShowRelativeToView`); `null` when the\n * anchor or the card has no size yet (the card is then centred, and the next layout corrects it).\n */\nexport function relativePopupPlacement(\n anchor: G9Rect | null | undefined,\n position: G9PopupRelativePosition | null | undefined,\n card: { width: number; height: number },\n offset: { x: number; y: number } = { x: 0, y: 0 },\n): { left: number; top: number } | null {\n if (!anchor || !position || anchor.width <= 0 || anchor.height <= 0 || card.width <= 0 || card.height <= 0)\n return null;\n const right = anchor.left + anchor.width;\n const bottom = anchor.top + anchor.height;\n const cx = anchor.left + (anchor.width - card.width) / 2;\n const cy = anchor.top + (anchor.height - card.height) / 2;\n const at = (left: number, top: number) => ({ left: left + offset.x, top: top + offset.y });\n switch (position) {\n case 'alignTop':\n return at(cx, anchor.top);\n case 'alignBottom':\n return at(cx, bottom - card.height);\n case 'alignLeft':\n return at(anchor.left, cy);\n case 'alignRight':\n return at(right - card.width, cy);\n case 'alignTopLeft':\n return at(anchor.left, anchor.top);\n case 'alignTopRight':\n return at(right - card.width, anchor.top);\n case 'alignBottomLeft':\n return at(anchor.left, bottom - card.height);\n case 'alignBottomRight':\n return at(right - card.width, bottom - card.height);\n case 'alignToLeftOf':\n return at(anchor.left - card.width, cy);\n case 'alignToRightOf':\n return at(right, cy);\n case 'alignToTopOf':\n return at(cx, anchor.top - card.height);\n default:\n return at(cx, bottom);\n }\n}\n\ninterface DragApi {\n readonly onStart: (x: number, y: number) => void;\n readonly onMove: (x: number, y: number) => void;\n readonly register: () => () => void;\n}\n\nconst DragContext = createContext<DragApi | null>(null);\n\ntype TouchEvent = { touches?: Array<{ clientX?: number; clientY?: number; pageX?: number; pageY?: number }> };\nconst point = (e: TouchEvent) => {\n const t = e.touches?.[0];\n return { x: t?.clientX ?? t?.pageX ?? 0, y: t?.clientY ?? t?.pageY ?? 0 };\n};\n\n/**\n * The grip of a draggable popup (MAUI `DragHandle`): put the header inside it so taps in the body keep working.\n * Without one, a draggable card drags from anywhere.\n */\nexport function G9PopupDragHandle(props: { readonly children?: ReactNode; readonly className?: string }): ReactNode {\n const drag = useContext(DragContext);\n useEffect(() => drag?.register(), [drag !== null]);\n return (\n <view\n className={`g9-popup__drag-handle${props.className ? ` ${props.className}` : ''}`}\n bindtouchstart={(e: TouchEvent) => {\n const p = point(e);\n drag?.onStart(p.x, p.y);\n }}\n bindtouchmove={(e: TouchEvent) => {\n const p = point(e);\n drag?.onMove(p.x, p.y);\n }}\n >\n {props.children}\n </view>\n );\n}\n\n/** Props of {@link PopupFrame}. */\nexport interface PopupFrameProps {\n readonly options: G9PopupViewOpenOptions;\n /** `enter` = start pose (no transition), `open` = in place, `leave` = exit pose. */\n readonly phase: 'enter' | 'open' | 'leave';\n readonly hostWidth: number;\n readonly onBackgroundTap?: () => void;\n readonly children?: ReactNode;\n readonly testId?: string;\n}\n\n/**\n * Scrim + card (MAUI `G9PopupView` visuals): the scrim fades on its own (also when the card has no motion); the card\n * runs one compound transition (opacity with transform) between its pose and identity; no shadow, the stroke\n * separates it. Placement: absolute, relative to an anchor, or centred (90 % wide in `height` mode). Non-modal\n * (`overlayMode: 'none'`): no scrim and the layer lets taps through.\n */\nexport function PopupFrame(props: PopupFrameProps): ReactNode {\n const o = props.options;\n // Fields on the card hide their outline under a floated label with the card's colour.\n const palette = useG9Theme().palette;\n const notch = g9FieldNotchStyle(resolveThemeColor(o.cardBackground ?? 'var(--g9-surface)', palette));\n // MAUI ResolveOverlayColor: the colour's hue with the overlay opacity as its alpha (Colors.Black.WithAlpha by default) —\n // the Scrim token's own alpha (0.6) does not multiply in, or the 0.45 dim reads as 0.27.\n const scrimColor = formatColor(withAlpha(resolveThemeColor(o.overlayColor ?? 'var(--g9-scrim)', palette), 1));\n const animation = o.animation ?? 'slideUp';\n const duration = o.animationDuration ?? 240;\n const mode = o.overlayMode ?? 'transparent';\n const [size, setSize] = useState({ width: 0, height: 0 });\n const [offset, setOffset] = useState({ x: 0, y: 0 });\n const drag = useRef({ x: 0, y: 0, ox: 0, oy: 0 });\n const [handles, setHandles] = useState(0);\n const dragApi: DragApi = {\n onStart: (x, y) => {\n drag.current = { ...drag.current, x, y, ox: offset.x, oy: offset.y };\n },\n onMove: (x, y) => {\n if (!o.isDraggable) return;\n setOffset({ x: drag.current.ox + x - drag.current.x, y: drag.current.oy + y - drag.current.y });\n },\n register: () => {\n setHandles((n) => n + 1);\n return () => setHandles((n) => n - 1);\n },\n };\n const pose =\n props.phase === 'open'\n ? { opacity: 1, transform: 'translateY(0px) scale(1)' }\n : popupMotionPose(animation, props.phase === 'enter' ? 'enter' : 'exit');\n const easing =\n animation === 'bounce' && props.phase !== 'leave'\n ? popupEasingCss('bounceOut')\n : popupEasingCss(o.animationEasing ?? 'sinOut');\n const transition =\n props.phase === 'enter' || animation === 'none'\n ? 'none'\n : `opacity ${duration}ms ${easing}, transform ${duration}ms ${easing}`;\n const autoSize = o.autoSizeMode ?? 'height';\n const placed =\n o.absoluteX != null || o.absoluteY != null\n ? { left: o.absoluteX ?? 0, top: o.absoluteY ?? 0 }\n : relativePopupPlacement(o.relativeRect, o.relativePosition, size, {\n x: o.relativeAbsoluteX ?? 0,\n y: o.relativeAbsoluteY ?? 0,\n });\n const width =\n o.width != null && autoSize !== 'both' && autoSize !== 'width'\n ? `${o.width}px`\n : !placed && autoSize === 'height'\n ? `${Math.round(props.hostWidth * 0.9)}px`\n : undefined;\n const height = o.height != null && (autoSize === 'none' || autoSize === 'width') ? `${o.height}px` : undefined;\n const pad = o.padding ?? [20, 16, 20, 12];\n const scrimOpacity = popupScrimOpacity(mode, o.overlayOpacity ?? 0.45, o.blurIntensity ?? 'none');\n const dragTranslate = o.isDraggable ? `translate(${offset.x}px, ${offset.y}px) ` : '';\n const wholeCardDrags = o.isDraggable === true && handles === 0;\n return (\n <view\n className={`g9-popup${mode === 'none' ? ' g9-popup--nonmodal' : ''}${placed ? ' g9-popup--placed' : ''}`}\n {...(mode === 'none' ? { 'event-through': true } : {})}\n >\n {mode !== 'none' ? (\n <view\n // Never flattened (see the sheet scrim): over a native SurfaceView a flattened dim is painted underneath it.\n flatten={false}\n className=\"g9-popup__scrim\"\n style={{\n backgroundColor: scrimColor,\n opacity: props.phase === 'open' ? scrimOpacity : 0,\n transition: props.phase === 'enter' ? 'none' : `opacity ${duration}ms`,\n }}\n bindtap={() => props.onBackgroundTap?.()}\n />\n ) : null}\n <view\n className=\"g9-popup__card\"\n {...(props.testId ? { 'data-testid': props.testId, id: g9SafeId(props.testId) } : {})}\n event-through={false}\n style={{\n ...(placed ? { position: 'absolute', left: `${placed.left}px`, top: `${placed.top}px` } : {}),\n ...(width ? { width } : {}),\n ...(height ? { height } : {}),\n borderRadius: `${o.cornerRadius ?? 16}px`,\n backgroundColor: o.cardBackground ?? 'var(--g9-surface)',\n borderColor: o.borderColor ?? 'var(--g9-surface)',\n padding: `${pad[1]}px ${pad[2]}px ${pad[3]}px ${pad[0]}px`,\n ...notch,\n opacity: pose.opacity,\n transform: `${dragTranslate}${pose.transform} scale(${g9PopupRestingScale})`,\n transition,\n }}\n bindlayoutchange={(e: { detail?: { width?: number; height?: number } }) => {\n const w = e.detail?.width ?? 0;\n const h = e.detail?.height ?? 0;\n if (w > 0 && h > 0 && (w !== size.width || h !== size.height)) setSize({ width: w, height: h });\n }}\n {...(wholeCardDrags\n ? {\n bindtouchstart: (e: TouchEvent) => {\n const p = point(e);\n dragApi.onStart(p.x, p.y);\n },\n bindtouchmove: (e: TouchEvent) => {\n const p = point(e);\n dragApi.onMove(p.x, p.y);\n },\n }\n : {})}\n >\n <DragContext.Provider value={dragApi}>{props.children}</DragContext.Provider>\n </view>\n </view>\n );\n}\n"],"names":["g9PopupRestingScale","popupMotionPose","animation","phase","popupEasingCss","easing","relativePopupPlacement","anchor","position","card","offset","right","bottom","cx","cy","at","left","top","DragContext","createContext","point","e","_ref","_ref2","_e_touches","t","G9PopupDragHandle","props","drag","useContext","useEffect","view","p","PopupFrame","_o_cardBackground","_o_overlayColor","_o_animation","_o_animationDuration","_o_overlayMode","_o_animationEasing","_o_autoSizeMode","_o_absoluteX","_o_absoluteY","_o_relativeAbsoluteX","_o_relativeAbsoluteY","_o_padding","_o_overlayOpacity","_o_blurIntensity","_o_cornerRadius","_o_cardBackground1","_o_borderColor","o","palette","useG9Theme","notch","g9FieldNotchStyle","resolveThemeColor","scrimColor","formatColor","withAlpha","duration","mode","size","setSize","useState","setOffset","useRef","handles","setHandles","dragApi","x","y","n","pose","transition","autoSize","placed","width","undefined","Math","height","pad","scrimOpacity","popupScrimOpacity","dragTranslate","wholeCardDrags","g9SafeId","_e_detail","_e_detail1","w","h"],"mappings":"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"}
1
+ {"version":3,"file":"popup/frame.jsx","sources":["../../src/popup/frame.tsx"],"sourcesContent":["import './popup.css';\nimport { formatColor, g9Ms, resolveThemeColor, withAlpha } from '@g9tm/lynxcontrols-foundation';\nimport { createContext, type ReactNode, useContext, useEffect, useRef, useState } from '@lynx-js/react';\nimport { g9SafeId } from '../base/control';\nimport { g9FieldNotchStyle } from '../fields/notch';\nimport { useG9Theme } from '../provider/hooks';\nimport type {\n G9PopupAnimationEasing,\n G9PopupAnimationType,\n G9PopupAutoSizeMode,\n G9PopupBlurIntensity,\n G9PopupOverlayMode,\n G9PopupRelativePosition,\n} from './types';\nimport { popupScrimOpacity } from './types';\n\n/** A rectangle in host coordinates (px), e.g. an anchor's `boundingClientRect`. */\nexport interface G9Rect {\n readonly left: number;\n readonly top: number;\n readonly width: number;\n readonly height: number;\n}\n\n/** How one popup card opens (MAUI `G9PopupViewOpenOptions`). */\nexport interface G9PopupViewOpenOptions {\n /** Card width (px); unset = the auto-size mode decides (90 % of the host for centred `height` mode). */\n readonly width?: number | null;\n readonly height?: number | null;\n /** Default 16. */\n readonly cornerRadius?: number;\n /** `[left, top, right, bottom]`. Default `[20, 16, 20, 12]`. */\n readonly padding?: readonly [number, number, number, number];\n /** Default `'height'`. */\n readonly autoSizeMode?: G9PopupAutoSizeMode;\n readonly cardBackground?: string | null;\n readonly borderColor?: string | null;\n /** Default `'transparent'`; `'none'` = non-modal (no scrim, taps pass through). */\n readonly overlayMode?: G9PopupOverlayMode;\n readonly blurIntensity?: G9PopupBlurIntensity;\n /** Scrim colour (its opacity is `overlayOpacity`). Default the `Scrim` token. */\n readonly overlayColor?: string | null;\n /** Default 0.45. */\n readonly overlayOpacity?: number;\n /** Default false. */\n readonly closeOnBackgroundTap?: boolean;\n /** Default true. */\n readonly closeOnBackButton?: boolean;\n /** Default `'slideUp'`. */\n readonly animation?: G9PopupAnimationType;\n /** Default `'sinOut'`. */\n readonly animationEasing?: G9PopupAnimationEasing;\n /** Default 240 ms. */\n readonly animationDuration?: number;\n /** Close after this many ms; 0 = never. */\n readonly autoCloseDuration?: number;\n /** Anchor rectangle (MAUI `RelativeView`'s bounds); with `relativePosition`. */\n readonly relativeRect?: G9Rect | null;\n readonly relativePosition?: G9PopupRelativePosition | null;\n /** Extra offset added to the relative placement. */\n readonly relativeAbsoluteX?: number;\n readonly relativeAbsoluteY?: number;\n /** Absolute card position (host px). */\n readonly absoluteX?: number | null;\n readonly absoluteY?: number | null;\n /** The card can be dragged: by a `<G9PopupDragHandle>` inside it, or anywhere when there is none. */\n readonly isDraggable?: boolean;\n}\n\n/**\n * The size every MAUI popup RESTS at: `G9PopupView` builds its card container with `ScaleX = ScaleY = 0.92` and its\n * open animations only ever set `Scale` (which multiplies them), so the card, its text and its buttons all show at\n * 92 % — a 403 dp card measures 371 dp on screen (MAUI 6.2.36, Pixel 9 Pro XL). The port reproduces what users see.\n */\nexport const g9PopupRestingScale = 0.92;\n\n/** The pose a card starts from / leaves to, per motion (MAUI `G9PopupView` animation table). */\nexport function popupMotionPose(\n animation: G9PopupAnimationType,\n phase: 'enter' | 'exit',\n): {\n opacity: number;\n transform: string;\n} {\n switch (animation) {\n case 'none':\n return { opacity: phase === 'enter' ? 1 : 0, transform: 'translateY(0px) scale(1)' };\n case 'fadeIn':\n return { opacity: 0, transform: 'translateY(0px) scale(1)' };\n case 'zoomIn':\n return { opacity: 0, transform: 'translateY(0px) scale(0.92)' };\n case 'dropIn':\n return { opacity: 0, transform: 'translateY(-40px) scale(1)' };\n case 'bounce':\n // Opens from 0.6 with the bounce easing; closes like ZoomIn (MAUI).\n return { opacity: 0, transform: `translateY(0px) scale(${phase === 'enter' ? 0.6 : 0.92})` };\n default:\n return { opacity: 0, transform: 'translateY(40px) scale(1)' };\n }\n}\n\n/** CSS timing function of an easing (bounce approximated with an overshoot curve; CSS has no bounce). */\nexport function popupEasingCss(easing: G9PopupAnimationEasing): string {\n switch (easing) {\n case 'linear':\n return 'linear';\n case 'sinIn':\n return 'cubic-bezier(0.47, 0, 0.745, 0.715)';\n case 'sinInOut':\n return 'cubic-bezier(0.445, 0.05, 0.55, 0.95)';\n case 'cubicOut':\n return 'cubic-bezier(0.215, 0.61, 0.355, 1)';\n case 'bounceOut':\n return 'cubic-bezier(0.34, 1.56, 0.64, 1)';\n default:\n return 'cubic-bezier(0.39, 0.575, 0.565, 1)';\n }\n}\n\n/**\n * Where the card's top-left goes (host px) for a relative placement (MAUI `ShowRelativeToView`); `null` when the\n * anchor or the card has no size yet (the card is then centred, and the next layout corrects it).\n */\nexport function relativePopupPlacement(\n anchor: G9Rect | null | undefined,\n position: G9PopupRelativePosition | null | undefined,\n card: { width: number; height: number },\n offset: { x: number; y: number } = { x: 0, y: 0 },\n): { left: number; top: number } | null {\n if (!anchor || !position || anchor.width <= 0 || anchor.height <= 0 || card.width <= 0 || card.height <= 0)\n return null;\n const right = anchor.left + anchor.width;\n const bottom = anchor.top + anchor.height;\n const cx = anchor.left + (anchor.width - card.width) / 2;\n const cy = anchor.top + (anchor.height - card.height) / 2;\n const at = (left: number, top: number) => ({ left: left + offset.x, top: top + offset.y });\n switch (position) {\n case 'alignTop':\n return at(cx, anchor.top);\n case 'alignBottom':\n return at(cx, bottom - card.height);\n case 'alignLeft':\n return at(anchor.left, cy);\n case 'alignRight':\n return at(right - card.width, cy);\n case 'alignTopLeft':\n return at(anchor.left, anchor.top);\n case 'alignTopRight':\n return at(right - card.width, anchor.top);\n case 'alignBottomLeft':\n return at(anchor.left, bottom - card.height);\n case 'alignBottomRight':\n return at(right - card.width, bottom - card.height);\n case 'alignToLeftOf':\n return at(anchor.left - card.width, cy);\n case 'alignToRightOf':\n return at(right, cy);\n case 'alignToTopOf':\n return at(cx, anchor.top - card.height);\n default:\n return at(cx, bottom);\n }\n}\n\ninterface DragApi {\n readonly onStart: (x: number, y: number) => void;\n readonly onMove: (x: number, y: number) => void;\n readonly register: () => () => void;\n}\n\nconst DragContext = createContext<DragApi | null>(null);\n\ntype TouchEvent = { touches?: Array<{ clientX?: number; clientY?: number; pageX?: number; pageY?: number }> };\nconst point = (e: TouchEvent) => {\n const t = e.touches?.[0];\n return { x: t?.clientX ?? t?.pageX ?? 0, y: t?.clientY ?? t?.pageY ?? 0 };\n};\n\n/**\n * The grip of a draggable popup (MAUI `DragHandle`): put the header inside it so taps in the body keep working.\n * Without one, a draggable card drags from anywhere.\n */\nexport function G9PopupDragHandle(props: { readonly children?: ReactNode; readonly className?: string }): ReactNode {\n const drag = useContext(DragContext);\n useEffect(() => drag?.register(), [drag !== null]);\n return (\n <view\n className={`g9-popup__drag-handle${props.className ? ` ${props.className}` : ''}`}\n bindtouchstart={(e: TouchEvent) => {\n const p = point(e);\n drag?.onStart(p.x, p.y);\n }}\n bindtouchmove={(e: TouchEvent) => {\n const p = point(e);\n drag?.onMove(p.x, p.y);\n }}\n >\n {props.children}\n </view>\n );\n}\n\n/** Props of {@link PopupFrame}. */\nexport interface PopupFrameProps {\n readonly options: G9PopupViewOpenOptions;\n /** `enter` = start pose (no transition), `open` = in place, `leave` = exit pose. */\n readonly phase: 'enter' | 'open' | 'leave';\n readonly hostWidth: number;\n readonly onBackgroundTap?: () => void;\n readonly children?: ReactNode;\n readonly testId?: string;\n}\n\n/**\n * Scrim + card (MAUI `G9PopupView` visuals): the scrim fades on its own (also when the card has no motion); the card\n * runs one compound transition (opacity with transform) between its pose and identity; no shadow, the stroke\n * separates it. Placement: absolute, relative to an anchor, or centred (90 % wide in `height` mode). Non-modal\n * (`overlayMode: 'none'`): no scrim and the layer lets taps through.\n */\nexport function PopupFrame(props: PopupFrameProps): ReactNode {\n const o = props.options;\n // Fields on the card hide their outline under a floated label with the card's colour.\n const palette = useG9Theme().palette;\n const notch = g9FieldNotchStyle(resolveThemeColor(o.cardBackground ?? 'var(--g9-surface)', palette));\n // MAUI ResolveOverlayColor: the colour's hue with the overlay opacity as its alpha (Colors.Black.WithAlpha by default) —\n // the Scrim token's own alpha (0.6) does not multiply in, or the 0.45 dim reads as 0.27.\n const scrimColor = formatColor(withAlpha(resolveThemeColor(o.overlayColor ?? 'var(--g9-scrim)', palette), 1));\n const animation = o.animation ?? 'slideUp';\n const duration = g9Ms(o.animationDuration ?? 240);\n const mode = o.overlayMode ?? 'transparent';\n const [size, setSize] = useState({ width: 0, height: 0 });\n const [offset, setOffset] = useState({ x: 0, y: 0 });\n const drag = useRef({ x: 0, y: 0, ox: 0, oy: 0 });\n const [handles, setHandles] = useState(0);\n const dragApi: DragApi = {\n onStart: (x, y) => {\n drag.current = { ...drag.current, x, y, ox: offset.x, oy: offset.y };\n },\n onMove: (x, y) => {\n if (!o.isDraggable) return;\n setOffset({ x: drag.current.ox + x - drag.current.x, y: drag.current.oy + y - drag.current.y });\n },\n register: () => {\n setHandles((n) => n + 1);\n return () => setHandles((n) => n - 1);\n },\n };\n const pose =\n props.phase === 'open'\n ? { opacity: 1, transform: 'translateY(0px) scale(1)' }\n : popupMotionPose(animation, props.phase === 'enter' ? 'enter' : 'exit');\n const easing =\n animation === 'bounce' && props.phase !== 'leave'\n ? popupEasingCss('bounceOut')\n : popupEasingCss(o.animationEasing ?? 'sinOut');\n const transition =\n props.phase === 'enter' || animation === 'none'\n ? 'none'\n : `opacity ${duration}ms ${easing}, transform ${duration}ms ${easing}`;\n const autoSize = o.autoSizeMode ?? 'height';\n const placed =\n o.absoluteX != null || o.absoluteY != null\n ? { left: o.absoluteX ?? 0, top: o.absoluteY ?? 0 }\n : relativePopupPlacement(o.relativeRect, o.relativePosition, size, {\n x: o.relativeAbsoluteX ?? 0,\n y: o.relativeAbsoluteY ?? 0,\n });\n const width =\n o.width != null && autoSize !== 'both' && autoSize !== 'width'\n ? `${o.width}px`\n : !placed && autoSize === 'height'\n ? `${Math.round(props.hostWidth * 0.9)}px`\n : undefined;\n const height = o.height != null && (autoSize === 'none' || autoSize === 'width') ? `${o.height}px` : undefined;\n const pad = o.padding ?? [20, 16, 20, 12];\n const scrimOpacity = popupScrimOpacity(mode, o.overlayOpacity ?? 0.45, o.blurIntensity ?? 'none');\n const dragTranslate = o.isDraggable ? `translate(${offset.x}px, ${offset.y}px) ` : '';\n const wholeCardDrags = o.isDraggable === true && handles === 0;\n return (\n <view\n className={`g9-popup${mode === 'none' ? ' g9-popup--nonmodal' : ''}${placed ? ' g9-popup--placed' : ''}`}\n {...(mode === 'none' ? { 'event-through': true } : {})}\n >\n {mode !== 'none' ? (\n <view\n // Never flattened (see the sheet scrim): over a native SurfaceView a flattened dim is painted underneath it.\n flatten={false}\n className=\"g9-popup__scrim\"\n style={{\n backgroundColor: scrimColor,\n opacity: props.phase === 'open' ? scrimOpacity : 0,\n transition: props.phase === 'enter' ? 'none' : `opacity ${duration}ms`,\n }}\n bindtap={() => props.onBackgroundTap?.()}\n />\n ) : null}\n <view\n className=\"g9-popup__card\"\n {...(props.testId ? { 'data-testid': props.testId, id: g9SafeId(props.testId) } : {})}\n event-through={false}\n style={{\n ...(placed ? { position: 'absolute', left: `${placed.left}px`, top: `${placed.top}px` } : {}),\n ...(width ? { width } : {}),\n ...(height ? { height } : {}),\n borderRadius: `${o.cornerRadius ?? 16}px`,\n backgroundColor: o.cardBackground ?? 'var(--g9-surface)',\n borderColor: o.borderColor ?? 'var(--g9-surface)',\n padding: `${pad[1]}px ${pad[2]}px ${pad[3]}px ${pad[0]}px`,\n ...notch,\n opacity: pose.opacity,\n transform: `${dragTranslate}${pose.transform} scale(${g9PopupRestingScale})`,\n transition,\n }}\n bindlayoutchange={(e: { detail?: { width?: number; height?: number } }) => {\n const w = e.detail?.width ?? 0;\n const h = e.detail?.height ?? 0;\n if (w > 0 && h > 0 && (w !== size.width || h !== size.height)) setSize({ width: w, height: h });\n }}\n {...(wholeCardDrags\n ? {\n bindtouchstart: (e: TouchEvent) => {\n const p = point(e);\n dragApi.onStart(p.x, p.y);\n },\n bindtouchmove: (e: TouchEvent) => {\n const p = point(e);\n dragApi.onMove(p.x, p.y);\n },\n }\n : {})}\n >\n <DragContext.Provider value={dragApi}>{props.children}</DragContext.Provider>\n </view>\n </view>\n );\n}\n"],"names":["g9PopupRestingScale","popupMotionPose","animation","phase","popupEasingCss","easing","relativePopupPlacement","anchor","position","card","offset","right","bottom","cx","cy","at","left","top","DragContext","createContext","point","e","_ref","_ref2","_e_touches","t","G9PopupDragHandle","props","drag","useContext","useEffect","view","p","PopupFrame","_o_cardBackground","_o_overlayColor","_o_animation","_o_animationDuration","_o_overlayMode","_o_animationEasing","_o_autoSizeMode","_o_absoluteX","_o_absoluteY","_o_relativeAbsoluteX","_o_relativeAbsoluteY","_o_padding","_o_overlayOpacity","_o_blurIntensity","_o_cornerRadius","_o_cardBackground1","_o_borderColor","o","palette","useG9Theme","notch","g9FieldNotchStyle","resolveThemeColor","scrimColor","formatColor","withAlpha","duration","g9Ms","mode","size","setSize","useState","setOffset","useRef","handles","setHandles","dragApi","x","y","n","pose","transition","autoSize","placed","width","undefined","Math","height","pad","scrimOpacity","popupScrimOpacity","dragTranslate","wholeCardDrags","g9SafeId","_e_detail","_e_detail1","w","h"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/popup/service.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/popup/service.tsx"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import "./popup.css";
2
- import { G9StringKey, createCulture, createStrings } from "@g9tm/lynxcontrols-foundation";
2
+ import { G9StringKey, createCulture, createStrings, g9Ms } from "@g9tm/lynxcontrols-foundation";
3
3
  import { useEffect, useRef, useState, useSyncExternalStore } from "@lynx-js/react";
4
4
  import { g9RowStyle, g9SafeId, g9TextStart } from "../base/control.jsx";
5
5
  import { useG9Press } from "../base/press.jsx";
@@ -178,7 +178,7 @@ function createPopupService(host) {
178
178
  clearTimer: (h)=>stopTimer(h),
179
179
  closeDurationMs: (d)=>{
180
180
  var _resolvePopupSettings_animationDuration;
181
- return 'none' === resolvePopupSettings(d, state.defaults).animation ? 0 : null != (_resolvePopupSettings_animationDuration = resolvePopupSettings(d, state.defaults).animationDuration) ? _resolvePopupSettings_animationDuration : 240;
181
+ return 'none' === resolvePopupSettings(d, state.defaults).animation ? 0 : g9Ms(null != (_resolvePopupSettings_animationDuration = resolvePopupSettings(d, state.defaults).animationDuration) ? _resolvePopupSettings_animationDuration : 240);
182
182
  },
183
183
  autoCloseMs: (d)=>{
184
184
  var _resolvePopupSettings_autoCloseDuration;