@g9tm/lynxcontrols 1.4.5 → 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.
- package/dist/.tsbuildinfo +1 -1
- package/dist/base/pressable.d.ts.map +1 -1
- package/dist/base/pressable.jsx +2 -1
- package/dist/base/pressable.jsx.map +1 -1
- package/dist/cascade/cascade-panel.d.ts.map +1 -1
- package/dist/cascade/cascade-panel.jsx +2 -2
- package/dist/cascade/cascade-panel.jsx.map +1 -1
- package/dist/edge-panel/edge-panel.jsx +5 -5
- package/dist/edge-panel/edge-panel.jsx.map +1 -1
- package/dist/expander/expander.d.ts.map +1 -1
- package/dist/expander/expander.jsx +2 -1
- package/dist/expander/expander.jsx.map +1 -1
- package/dist/host/host.css.map +1 -1
- package/dist/host/host.d.ts +3 -2
- package/dist/host/host.d.ts.map +1 -1
- package/dist/host/host.jsx +2 -2
- package/dist/host/host.jsx.map +1 -1
- package/dist/plus-button/model.d.ts.map +1 -1
- package/dist/plus-button/model.jsx +5 -1
- package/dist/plus-button/model.jsx.map +1 -1
- package/dist/popup/frame.jsx +2 -2
- package/dist/popup/frame.jsx.map +1 -1
- package/dist/popup/service.d.ts.map +1 -1
- package/dist/popup/service.jsx +2 -2
- package/dist/popup/service.jsx.map +1 -1
- package/dist/provider/provider.css +4 -0
- package/dist/provider/provider.css.map +1 -1
- package/dist/provider/provider.d.ts.map +1 -1
- package/dist/provider/provider.jsx +4 -2
- package/dist/provider/provider.jsx.map +1 -1
- package/dist/selection/selection-sheet.d.ts +5 -0
- package/dist/selection/selection-sheet.d.ts.map +1 -1
- package/dist/selection/selection-sheet.jsx +7 -3
- package/dist/selection/selection-sheet.jsx.map +1 -1
- package/dist/sheet/frame.d.ts.map +1 -1
- package/dist/sheet/frame.jsx +30 -8
- package/dist/sheet/frame.jsx.map +1 -1
- package/dist/sheet/index.d.ts +1 -0
- package/dist/sheet/index.d.ts.map +1 -1
- package/dist/sheet/index.jsx +1 -0
- package/dist/sheet/motion.d.ts.map +1 -1
- package/dist/sheet/motion.jsx +14 -0
- package/dist/sheet/motion.jsx.map +1 -1
- package/dist/sheet/options.d.ts +6 -0
- package/dist/sheet/options.d.ts.map +1 -1
- package/dist/sheet/options.jsx.map +1 -1
- package/dist/sheet/scroll-indicator.d.ts +33 -0
- package/dist/sheet/scroll-indicator.d.ts.map +1 -0
- package/dist/sheet/scroll-indicator.jsx +84 -0
- package/dist/sheet/scroll-indicator.jsx.map +1 -0
- package/dist/sheet/sheet.css +14 -0
- package/dist/sheet/sheet.css.map +1 -1
- package/dist/tab-bar/tab-bar.d.ts.map +1 -1
- package/dist/tab-bar/tab-bar.jsx +11 -6
- package/dist/tab-bar/tab-bar.jsx.map +1 -1
- package/dist/toast/service.jsx +3 -3
- package/dist/toast/service.jsx.map +1 -1
- package/dist/toast/store.d.ts.map +1 -1
- package/dist/toast/store.jsx +3 -2
- package/dist/toast/store.jsx.map +1 -1
- package/package.json +3 -3
package/dist/host/host.jsx.map
CHANGED
|
@@ -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":"
|
|
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":"
|
|
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"}
|
package/dist/popup/frame.jsx
CHANGED
|
@@ -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,
|
package/dist/popup/frame.jsx.map
CHANGED
|
@@ -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":"AAAA,OAAO,aAAa,CAAC;AACrB,OAAO,
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/popup/service.tsx"],"names":[],"mappings":"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"}
|
package/dist/popup/service.jsx
CHANGED
|
@@ -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;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"popup/service.jsx","sources":["../../src/popup/service.tsx"],"sourcesContent":["import './popup.css';\nimport { createCulture, createStrings, type G9ErrorPopupRequest, G9StringKey } from '@g9tm/lynxcontrols-foundation';\nimport { type ReactNode, useEffect, useRef, useState, useSyncExternalStore } from '@lynx-js/react';\nimport { g9RowStyle, g9SafeId, g9TextStart } from '../base/control';\nimport { useG9Press } from '../base/press';\nimport { startTimer, stopTimer } from '../base/timers';\nimport { G9ActivityIndicator } from '../display/activity-indicator';\nimport { useG9Host } from '../host/hooks';\nimport { type G9HostHandle, g9Hosts } from '../host/registry';\nimport { G9IconSlot } from '../icon/slot';\nimport { useG9Diagnostics, useG9Direction, useG9Settings, useG9Strings, useG9Window } from '../provider/hooks';\nimport { g9DefaultErrorPresenter } from '../provider/settings';\nimport { type G9PopupViewOpenOptions, PopupFrame } from './frame';\nimport { type G9PopupInputOptions, type G9PopupInputResult, g9PopupInputResult } from './input';\nimport { createPopupFormStore, PopupInputForm } from './input-form';\nimport { type G9PopupEntry, type G9PopupOutcome, G9PopupQueue } from './queue';\nimport {\n createPopupVisualProfile,\n customPopup,\n type G9PopupAnimationType,\n type G9PopupButton,\n type G9PopupDescriptor,\n type G9PopupResult,\n type G9PopupSettings,\n type G9PopupType,\n type G9PopupVisualProfile,\n g9PopupResult,\n presetPopup,\n resolvePopupSettings,\n} from './types';\n\n/** Most buttons a `row` footer shows (MAUI); more are dropped with a warning. */\nexport const g9PopupRowButtonLimit = 3;\n\n/** Options of `showConfirm` (MAUI `ShowConfirmAsync`). */\nexport interface G9ConfirmOptions {\n readonly title?: string | null;\n readonly okCallback?: ((context: { readonly aborted: boolean }) => unknown) | null;\n readonly cancelCallback?: ((context: { readonly aborted: boolean }) => unknown) | null;\n /** Default `'information'`; `'warning'` for a lossy confirm (sign out, discard). */\n readonly type?: G9PopupType;\n readonly okText?: string;\n readonly cancelText?: string;\n}\n\n/** The popups of a host (MAUI `G9PopupHelper`). */\nexport interface G9PopupService {\n /** Information popup (MAUI `ShowG9PopupAsync`); resolves the result of the button that closed it. */\n show(\n message: string,\n title?: string | null,\n buttons?: ReadonlyArray<G9PopupButton> | null,\n settings?: G9PopupSettings | null,\n animation?: G9PopupAnimationType | null,\n ): Promise<G9PopupResult>;\n showSuccess(\n message: string,\n title?: string | null,\n buttons?: ReadonlyArray<G9PopupButton> | null,\n settings?: G9PopupSettings | null,\n animation?: G9PopupAnimationType | null,\n ): Promise<G9PopupResult>;\n showWarning(\n message: string,\n title?: string | null,\n buttons?: ReadonlyArray<G9PopupButton> | null,\n settings?: G9PopupSettings | null,\n animation?: G9PopupAnimationType | null,\n ): Promise<G9PopupResult>;\n showError(\n message: string,\n title?: string | null,\n buttons?: ReadonlyArray<G9PopupButton> | null,\n settings?: G9PopupSettings | null,\n animation?: G9PopupAnimationType | null,\n ): Promise<G9PopupResult>;\n /** Any content in the body (MAUI `ShowCustomG9PopupAsync`). */\n showCustom(\n content: ReactNode | (() => ReactNode),\n title?: string | null,\n buttons?: ReadonlyArray<G9PopupButton> | null,\n settings?: G9PopupSettings | null,\n animation?: G9PopupAnimationType | null,\n ): Promise<G9PopupResult>;\n /** Any descriptor; resolves how it ended. */\n showDescriptor(descriptor: G9PopupDescriptor): Promise<G9PopupOutcome>;\n /** A validated form (MAUI `ShowInputG9PopupAsync`). */\n showInput(options: G9PopupInputOptions): Promise<G9PopupInputResult>;\n /** OK/Cancel: `true` only for OK; every other exit is `false` (MAUI `ShowConfirmAsync`). */\n showConfirm(message: string, options?: G9ConfirmOptions): Promise<boolean>;\n /** Hardware back: `true` when a popup is on screen (closed unless `closeOnBackButton: false`). */\n handleHardwareBack(): boolean;\n /** Closes the popup on screen. */\n closeActive(): void;\n /** Drops waiting popups; the one on screen stays. */\n clearQueue(): void;\n /** Closes everything. */\n dismissAll(): void;\n readonly queue: G9PopupQueue;\n}\n\nconst FEATURE = 'g9.popups';\n\ninterface State {\n service: G9PopupService;\n defaults: G9PopupSettings;\n /** Strings and diagnostics of the provider; refreshed by the layer on every render. */\n strings: (key: G9StringKey) => string;\n warn?: (message: string) => void;\n report?: (error: unknown) => void;\n}\n\nconst fallbackStrings = createStrings({ culture: createCulture('en') });\n\nfunction PopupButtonView(props: {\n readonly button: G9PopupButton;\n /** Element id: the button's `testId` made selector-safe, else `G9Popup_Button_<index>`. */\n readonly id: string;\n readonly profile: G9PopupVisualProfile;\n readonly busy: boolean;\n readonly stacked: boolean;\n readonly onPress: () => void;\n}): ReactNode {\n const { button, profile } = props;\n const primary = button.isPrimary !== false;\n const press = useG9Press(props.onPress, { source: 'G9Popup', guardMs: 0 });\n const background = button.backgroundColor ?? (primary ? profile.buttonBackground : 'transparent');\n const color = button.textColor ?? (primary ? profile.buttonTextColor : 'var(--g9-on-surface)');\n return (\n <view\n className={`g9-popup__button${primary ? ' g9-popup__button--primary' : ' g9-popup__button--outline'}${props.stacked ? ' g9-popup__button--stacked' : ''}${props.busy ? ' g9-popup__button--busy' : ''}`}\n style={{ backgroundColor: background }}\n accessibility-element={true}\n accessibility-traits=\"button\"\n accessibility-label={button.text}\n {...(button.testId ? { 'data-testid': button.testId } : {})}\n id={props.id}\n bindtap={press}\n >\n {button.icon || button.iconImage ? (\n <G9IconSlot icon={button.icon} image={button.iconImage ?? null} size={18} color={color} />\n ) : null}\n <text className=\"g9-popup__button-text\" style={{ color }}>\n {button.text}\n </text>\n </view>\n );\n}\n\n/** Header, body and footer of a queued popup (MAUI helper templates). */\nfunction PopupCardContent(props: {\n readonly entry: G9PopupEntry;\n readonly settings: G9PopupSettings;\n readonly profile: G9PopupVisualProfile;\n readonly state: State;\n}): ReactNode {\n const { entry, settings, profile, state } = props;\n const strings = useG9Strings();\n const d = entry.descriptor;\n const close = useG9Press(() => state.service.queue.closeActive(), { source: 'G9Popup', guardMs: 0 });\n const glyphs = useG9Settings().glyphs;\n const buttons = d.buttons;\n const stacked = settings.footerButtonLayout === 'stacked';\n const shown = stacked ? buttons : buttons.slice(0, g9PopupRowButtonLimit);\n const warned = useRef(false);\n if (!stacked && buttons.length > g9PopupRowButtonLimit && !warned.current) {\n warned.current = true;\n state.warn?.(\n `A row footer shows at most ${g9PopupRowButtonLimit} buttons; ${buttons.length - g9PopupRowButtonLimit} dropped.`,\n );\n }\n const title = d.title?.trim()\n ? d.title\n : strings.get(\n d.type === 'success'\n ? G9StringKey.Success\n : d.type === 'warning'\n ? G9StringKey.Warning\n : d.type === 'error'\n ? G9StringKey.Error\n : G9StringKey.Information,\n );\n const content = typeof d.content === 'function' ? (d.content as () => ReactNode)() : d.content;\n const direction = useG9Direction();\n const row = g9RowStyle(direction);\n return (\n <view className=\"g9-popup__content\">\n {settings.showHeader !== false ? (\n <view className=\"g9-popup__header\" style={row}>\n <view className=\"g9-popup__badge\" accessibility-label={profile.semanticIconDescription}>\n <view className=\"g9-popup__badge-tint\" style={{ backgroundColor: profile.iconColor }} />\n <G9IconSlot icon={profile.icon} size={17} color={profile.iconColor} />\n </view>\n <text\n className=\"g9-popup__title\"\n text-maxline=\"1\"\n style={{ color: profile.titleColor, ...g9TextStart(direction) }}\n >\n {title}\n </text>\n {settings.showCloseButton ? (\n <view\n className=\"g9-popup__close\"\n accessibility-element={true}\n accessibility-traits=\"button\"\n accessibility-label={strings.get(G9StringKey.Close)}\n bindtap={close}\n >\n <G9IconSlot icon={glyphs.clear} size={20} color=\"var(--g9-on-surface-variant)\" />\n </view>\n ) : null}\n </view>\n ) : null}\n {settings.showHeader !== false ? <view className=\"g9-popup__divider\" /> : null}\n {d.message ? (\n <text className=\"g9-popup__message\" style={{ color: profile.messageColor, ...g9TextStart(direction) }}>\n {d.message}\n </text>\n ) : null}\n {content !== null && content !== undefined ? <view className=\"g9-popup__body\">{content}</view> : null}\n {settings.showFooter !== false ? (\n <view className={`g9-popup__footer${stacked ? ' g9-popup__footer--stacked' : ''}`} style={stacked ? {} : row}>\n {shown.map((button, i) => (\n <PopupButtonView\n key={i}\n id={button.testId ? g9SafeId(button.testId) : `G9Popup_Button_${i}`}\n button={button}\n profile={profile}\n busy={entry.busy}\n stacked={stacked}\n onPress={() => void state.service.queue.press(entry.id, i)}\n />\n ))}\n {entry.busy ? <G9ActivityIndicator running size={18} /> : null}\n </view>\n ) : null}\n </view>\n );\n}\n\n/** The popup layer: the active popup's frame; motion phases from the queue phase. */\nfunction PopupLayer(props: { readonly state: State }): ReactNode {\n const { state } = props;\n const settingsAll = useG9Settings();\n const diagnostics = useG9Diagnostics();\n state.defaults = settingsAll.popups;\n const glyphs = settingsAll.glyphs;\n const strings = useG9Strings();\n state.strings = (k) => strings.get(k);\n state.warn = (message) => diagnostics.log({ level: 'warning', message, source: 'G9Popup' });\n state.report = (error) =>\n diagnostics.log({ level: 'error', message: 'A popup callback failed.', source: 'G9Popup', error });\n const win = useG9Window();\n const queue = state.service.queue;\n const entry = useSyncExternalStore(\n (l) => queue.subscribe(l),\n () => queue.getSnapshot(),\n );\n // `enter` for one frame per show, then `open` (the transition runs), `leave` while closing.\n const [entered, setEntered] = useState<string | null>(null);\n const showKey = entry ? `${entry.id}:${entry.showCount}` : null;\n useEffect(() => {\n if (!showKey) return;\n const t = startTimer(() => setEntered(showKey), 16);\n return () => stopTimer(t);\n }, [showKey]);\n const settings = entry ? resolvePopupSettings(entry.descriptor, state.defaults) : null;\n const duration = settings?.animationDuration ?? 240;\n useEffect(() => {\n if (!entry || entered !== showKey || entry.phase !== 'opening') return;\n const t = startTimer(() => queue.markOpened(entry.id), duration);\n return () => stopTimer(t);\n }, [entered, showKey, entry?.phase]);\n useEffect(() => () => queue.dispose(), [queue]);\n if (!entry || !settings) return null;\n const profile = createPopupVisualProfile(entry.descriptor, settings, glyphs, (k) =>\n strings.get(\n k === 'success'\n ? G9StringKey.Success\n : k === 'warning'\n ? G9StringKey.Warning\n : k === 'error'\n ? G9StringKey.Error\n : G9StringKey.Information,\n ),\n );\n const options: G9PopupViewOpenOptions = {\n width: profile.width,\n height: profile.height,\n cornerRadius: profile.cornerRadius,\n padding: profile.padding,\n autoSizeMode: settings.autoSizeMode ?? 'height',\n cardBackground: profile.cardBackground,\n borderColor: profile.borderColor,\n overlayMode: settings.overlayMode ?? 'transparent',\n blurIntensity: settings.blurIntensity ?? 'none',\n overlayColor: profile.overlayColor,\n overlayOpacity: profile.overlayOpacity,\n animation: profile.animation,\n animationEasing: settings.animationEasing ?? 'sinOut',\n animationDuration: duration,\n };\n const phase = entry.phase === 'closing' ? 'leave' : entered === showKey ? 'open' : 'enter';\n return (\n <PopupFrame\n key={showKey as string}\n options={options}\n phase={phase}\n hostWidth={win.width}\n onBackgroundTap={() => queue.backgroundTap(entry.id)}\n >\n <PopupCardContent entry={entry} settings={settings} profile={profile} state={state} />\n </PopupFrame>\n );\n}\n\nfunction createPopupService(host: G9HostHandle): State {\n const state = { defaults: {}, strings: fallbackStrings.get } as unknown as State;\n const strings = (k: G9StringKey) => state.strings(k);\n const queue = new G9PopupQueue({\n setTimer: (cb, ms) => startTimer(cb, ms),\n clearTimer: (h) => stopTimer(h as never),\n closeDurationMs: (d) =>\n resolvePopupSettings(d, state.defaults).animation === 'none'\n ? 0\n : (resolvePopupSettings(d, state.defaults).animationDuration ?? 240),\n autoCloseMs: (d) => resolvePopupSettings(d, state.defaults).autoCloseDuration ?? 0,\n closesOnBack: (d) => resolvePopupSettings(d, state.defaults).closeOnBackButton !== false,\n closesOnBackgroundTap: (d) => resolvePopupSettings(d, state.defaults).closeOnBackgroundClick === true,\n onError: (error) => state.report?.(error),\n });\n // A popup without buttons gets an OK button (MAUI presets).\n const withOk = (d: G9PopupDescriptor): G9PopupDescriptor =>\n d.buttons.length > 0 ? d : { ...d, buttons: [{ text: strings(G9StringKey.Ok), isPrimary: true }] };\n const preset =\n (type: G9PopupType) =>\n (\n message: string,\n title?: string | null,\n buttons?: ReadonlyArray<G9PopupButton> | null,\n settings?: G9PopupSettings | null,\n animation?: G9PopupAnimationType | null,\n ) =>\n queue.show(withOk(presetPopup(type, message, title, buttons, settings, animation ?? null))).then((o) => o.result);\n const service: G9PopupService = {\n queue,\n show: preset('information'),\n showSuccess: preset('success'),\n showWarning: preset('warning'),\n showError: preset('error'),\n showCustom: (content, title, buttons, settings, animation) =>\n queue.show(withOk(customPopup(content, title, buttons, settings, animation ?? null))).then((o) => o.result),\n showDescriptor: (descriptor) => queue.show(withOk(descriptor)),\n async showInput(options) {\n const store = createPopupFormStore(options.fields);\n let result = g9PopupInputResult.cancel();\n const cancel: G9PopupButton = {\n ...(options.cancelButton ?? { text: options.cancelButtonText ?? strings(G9StringKey.Cancel) }),\n isPrimary: false,\n callback: () => {\n result = g9PopupInputResult.cancel();\n return g9PopupResult.close();\n },\n };\n const submit: G9PopupButton = {\n ...(options.submitButton ?? { text: options.submitButtonText ?? strings(G9StringKey.Save) }),\n isPrimary: true,\n callback: () => {\n const v = store.validate({\n requiredSuffix: strings(G9StringKey.RequiredSuffix),\n invalidEmail: strings(G9StringKey.InvalidEmail),\n });\n result = v.valid\n ? g9PopupInputResult.submit(v.values, v.arrayValues)\n : g9PopupInputResult.validationFailed(v.values, v.arrayValues, v.errors);\n return v.valid ? g9PopupResult.close() : g9PopupResult.noAction();\n },\n };\n const settings: G9PopupSettings = {\n showHeader: true,\n showFooter: true,\n showCloseButton: false,\n closeOnBackgroundClick: false,\n autoSizeMode: 'height',\n padding: [20, 12, 20, 8],\n ...Object.fromEntries(Object.entries(options.settings ?? {}).filter(([, v]) => v !== undefined && v !== null)),\n };\n await queue.show({\n type: options.type ?? 'information',\n title: options.title ?? null,\n message: options.message ?? null,\n content: () => <PopupInputForm store={store} focusFirst={options.focusFirstFieldOnOpen !== false} />,\n buttons: [cancel, submit],\n settings,\n animation: options.animation ?? null,\n form: {\n fieldKeys: options.fields.map((f) => f.key),\n setText: (key, value) => store.setText(key, value),\n getText: (key) => store.getState().form.text[key] ?? null,\n },\n });\n return result;\n },\n async showConfirm(message, options = {}) {\n let ok = false;\n await queue.show(\n presetPopup(options.type ?? 'information', message, options.title ?? null, [\n {\n text: options.cancelText ?? strings(G9StringKey.Cancel),\n isPrimary: false,\n callback: async (c) => {\n await options.cancelCallback?.(c);\n return g9PopupResult.close();\n },\n },\n {\n text: options.okText ?? strings(G9StringKey.Ok),\n isPrimary: true,\n callback: async (c) => {\n await options.okCallback?.(c);\n ok = true;\n return g9PopupResult.close();\n },\n },\n ]),\n );\n return ok;\n },\n handleHardwareBack: () => queue.handleBack(),\n closeActive: () => queue.closeActive(),\n clearQueue: () => queue.clearQueue(),\n dismissAll: () => queue.dismissAll(),\n };\n state.service = service;\n host.attachFeature(FEATURE, state);\n host.registerLayerItem('popups', { key: FEATURE, element: <PopupLayer state={state} />, order: 0 });\n host.back.push(() => (queue.handleBack() ? 'handled' : 'pass'), { layer: 'popups' });\n return state;\n}\n\n/** The popup service of a host (created once as a host feature). */\nexport function popupServiceOf(host: G9HostHandle): G9PopupService {\n const existing = host.getFeature(FEATURE) as State | undefined;\n return (existing ?? createPopupService(host)).service;\n}\n\n/** The popups of the nearest `G9Host` (MAUI `G9PopupHelper`): one card at a time, FIFO, in the `popups` layer. */\nexport function useG9Popups(): G9PopupService {\n return popupServiceOf(useG9Host());\n}\n\n/** The popups of the active host, for code outside components. Throws `host-missing` without a host. */\nexport function g9Popups(): G9PopupService {\n return popupServiceOf(g9Hosts.require());\n}\n\n/**\n * The default error presenter (installed when this module loads): the executor's error popup as an error-type popup\n * on the active host, with More details when diagnostics are available. Without a host it does nothing.\n */\nexport function presentErrorPopup(request: G9ErrorPopupRequest): Promise<void> | undefined {\n const host = g9Hosts.active();\n if (!host) return undefined;\n const popups = popupServiceOf(host);\n const buttons: G9PopupButton[] = [];\n if (request.moreDetails) {\n const more = request.moreDetails;\n buttons.push({ text: more.text, isPrimary: false, callback: async () => void (await more.open()) });\n }\n buttons.push({ text: request.okText, isPrimary: true });\n return popups.showError(request.message, request.title, buttons).then(() => undefined);\n}\n\ng9DefaultErrorPresenter.current = presentErrorPopup;\n"],"names":["g9PopupRowButtonLimit","FEATURE","fallbackStrings","createStrings","createCulture","PopupButtonView","props","_button_backgroundColor","_button_textColor","_button_iconImage","button","profile","primary","press","useG9Press","background","color","view","G9IconSlot","text","PopupCardContent","_d_title","entry","settings","state","strings","useG9Strings","d","close","glyphs","useG9Settings","buttons","stacked","shown","warned","useRef","title","G9StringKey","content","direction","useG9Direction","row","g9RowStyle","g9TextStart","i","g9SafeId","G9ActivityIndicator","PopupLayer","_settings_autoSizeMode","_settings_overlayMode","_settings_blurIntensity","_settings_animationEasing","settingsAll","diagnostics","useG9Diagnostics","k","message","error","win","useG9Window","queue","useSyncExternalStore","l","entered","setEntered","useState","showKey","useEffect","t","startTimer","stopTimer","resolvePopupSettings","duration","createPopupVisualProfile","options","phase","PopupFrame","createPopupService","host","G9PopupQueue","cb","ms","h","_resolvePopupSettings_animationDuration","_resolvePopupSettings_autoCloseDuration","withOk","preset","type","animation","presetPopup","o","service","customPopup","descriptor","_options_cancelButton","_options_cancelButtonText","_options_submitButton","_options_submitButtonText","_options_settings","_options_type","_options_title","_options_message","_options_animation","store","createPopupFormStore","result","g9PopupInputResult","cancel","g9PopupResult","submit","v","Object","PopupInputForm","f","key","value","_store_getState_form_text_key","_options_cancelText","_options_okText","ok","c","popupServiceOf","existing","useG9Popups","useG9Host","g9Popups","g9Hosts","presentErrorPopup","request","popups","more","undefined","g9DefaultErrorPresenter"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"popup/service.jsx","sources":["../../src/popup/service.tsx"],"sourcesContent":["import './popup.css';\nimport {\n createCulture,\n createStrings,\n type G9ErrorPopupRequest,\n G9StringKey,\n g9Ms,\n} from '@g9tm/lynxcontrols-foundation';\nimport { type ReactNode, useEffect, useRef, useState, useSyncExternalStore } from '@lynx-js/react';\nimport { g9RowStyle, g9SafeId, g9TextStart } from '../base/control';\nimport { useG9Press } from '../base/press';\nimport { startTimer, stopTimer } from '../base/timers';\nimport { G9ActivityIndicator } from '../display/activity-indicator';\nimport { useG9Host } from '../host/hooks';\nimport { type G9HostHandle, g9Hosts } from '../host/registry';\nimport { G9IconSlot } from '../icon/slot';\nimport { useG9Diagnostics, useG9Direction, useG9Settings, useG9Strings, useG9Window } from '../provider/hooks';\nimport { g9DefaultErrorPresenter } from '../provider/settings';\nimport { type G9PopupViewOpenOptions, PopupFrame } from './frame';\nimport { type G9PopupInputOptions, type G9PopupInputResult, g9PopupInputResult } from './input';\nimport { createPopupFormStore, PopupInputForm } from './input-form';\nimport { type G9PopupEntry, type G9PopupOutcome, G9PopupQueue } from './queue';\nimport {\n createPopupVisualProfile,\n customPopup,\n type G9PopupAnimationType,\n type G9PopupButton,\n type G9PopupDescriptor,\n type G9PopupResult,\n type G9PopupSettings,\n type G9PopupType,\n type G9PopupVisualProfile,\n g9PopupResult,\n presetPopup,\n resolvePopupSettings,\n} from './types';\n\n/** Most buttons a `row` footer shows (MAUI); more are dropped with a warning. */\nexport const g9PopupRowButtonLimit = 3;\n\n/** Options of `showConfirm` (MAUI `ShowConfirmAsync`). */\nexport interface G9ConfirmOptions {\n readonly title?: string | null;\n readonly okCallback?: ((context: { readonly aborted: boolean }) => unknown) | null;\n readonly cancelCallback?: ((context: { readonly aborted: boolean }) => unknown) | null;\n /** Default `'information'`; `'warning'` for a lossy confirm (sign out, discard). */\n readonly type?: G9PopupType;\n readonly okText?: string;\n readonly cancelText?: string;\n}\n\n/** The popups of a host (MAUI `G9PopupHelper`). */\nexport interface G9PopupService {\n /** Information popup (MAUI `ShowG9PopupAsync`); resolves the result of the button that closed it. */\n show(\n message: string,\n title?: string | null,\n buttons?: ReadonlyArray<G9PopupButton> | null,\n settings?: G9PopupSettings | null,\n animation?: G9PopupAnimationType | null,\n ): Promise<G9PopupResult>;\n showSuccess(\n message: string,\n title?: string | null,\n buttons?: ReadonlyArray<G9PopupButton> | null,\n settings?: G9PopupSettings | null,\n animation?: G9PopupAnimationType | null,\n ): Promise<G9PopupResult>;\n showWarning(\n message: string,\n title?: string | null,\n buttons?: ReadonlyArray<G9PopupButton> | null,\n settings?: G9PopupSettings | null,\n animation?: G9PopupAnimationType | null,\n ): Promise<G9PopupResult>;\n showError(\n message: string,\n title?: string | null,\n buttons?: ReadonlyArray<G9PopupButton> | null,\n settings?: G9PopupSettings | null,\n animation?: G9PopupAnimationType | null,\n ): Promise<G9PopupResult>;\n /** Any content in the body (MAUI `ShowCustomG9PopupAsync`). */\n showCustom(\n content: ReactNode | (() => ReactNode),\n title?: string | null,\n buttons?: ReadonlyArray<G9PopupButton> | null,\n settings?: G9PopupSettings | null,\n animation?: G9PopupAnimationType | null,\n ): Promise<G9PopupResult>;\n /** Any descriptor; resolves how it ended. */\n showDescriptor(descriptor: G9PopupDescriptor): Promise<G9PopupOutcome>;\n /** A validated form (MAUI `ShowInputG9PopupAsync`). */\n showInput(options: G9PopupInputOptions): Promise<G9PopupInputResult>;\n /** OK/Cancel: `true` only for OK; every other exit is `false` (MAUI `ShowConfirmAsync`). */\n showConfirm(message: string, options?: G9ConfirmOptions): Promise<boolean>;\n /** Hardware back: `true` when a popup is on screen (closed unless `closeOnBackButton: false`). */\n handleHardwareBack(): boolean;\n /** Closes the popup on screen. */\n closeActive(): void;\n /** Drops waiting popups; the one on screen stays. */\n clearQueue(): void;\n /** Closes everything. */\n dismissAll(): void;\n readonly queue: G9PopupQueue;\n}\n\nconst FEATURE = 'g9.popups';\n\ninterface State {\n service: G9PopupService;\n defaults: G9PopupSettings;\n /** Strings and diagnostics of the provider; refreshed by the layer on every render. */\n strings: (key: G9StringKey) => string;\n warn?: (message: string) => void;\n report?: (error: unknown) => void;\n}\n\nconst fallbackStrings = createStrings({ culture: createCulture('en') });\n\nfunction PopupButtonView(props: {\n readonly button: G9PopupButton;\n /** Element id: the button's `testId` made selector-safe, else `G9Popup_Button_<index>`. */\n readonly id: string;\n readonly profile: G9PopupVisualProfile;\n readonly busy: boolean;\n readonly stacked: boolean;\n readonly onPress: () => void;\n}): ReactNode {\n const { button, profile } = props;\n const primary = button.isPrimary !== false;\n const press = useG9Press(props.onPress, { source: 'G9Popup', guardMs: 0 });\n const background = button.backgroundColor ?? (primary ? profile.buttonBackground : 'transparent');\n const color = button.textColor ?? (primary ? profile.buttonTextColor : 'var(--g9-on-surface)');\n return (\n <view\n className={`g9-popup__button${primary ? ' g9-popup__button--primary' : ' g9-popup__button--outline'}${props.stacked ? ' g9-popup__button--stacked' : ''}${props.busy ? ' g9-popup__button--busy' : ''}`}\n style={{ backgroundColor: background }}\n accessibility-element={true}\n accessibility-traits=\"button\"\n accessibility-label={button.text}\n {...(button.testId ? { 'data-testid': button.testId } : {})}\n id={props.id}\n bindtap={press}\n >\n {button.icon || button.iconImage ? (\n <G9IconSlot icon={button.icon} image={button.iconImage ?? null} size={18} color={color} />\n ) : null}\n <text className=\"g9-popup__button-text\" style={{ color }}>\n {button.text}\n </text>\n </view>\n );\n}\n\n/** Header, body and footer of a queued popup (MAUI helper templates). */\nfunction PopupCardContent(props: {\n readonly entry: G9PopupEntry;\n readonly settings: G9PopupSettings;\n readonly profile: G9PopupVisualProfile;\n readonly state: State;\n}): ReactNode {\n const { entry, settings, profile, state } = props;\n const strings = useG9Strings();\n const d = entry.descriptor;\n const close = useG9Press(() => state.service.queue.closeActive(), { source: 'G9Popup', guardMs: 0 });\n const glyphs = useG9Settings().glyphs;\n const buttons = d.buttons;\n const stacked = settings.footerButtonLayout === 'stacked';\n const shown = stacked ? buttons : buttons.slice(0, g9PopupRowButtonLimit);\n const warned = useRef(false);\n if (!stacked && buttons.length > g9PopupRowButtonLimit && !warned.current) {\n warned.current = true;\n state.warn?.(\n `A row footer shows at most ${g9PopupRowButtonLimit} buttons; ${buttons.length - g9PopupRowButtonLimit} dropped.`,\n );\n }\n const title = d.title?.trim()\n ? d.title\n : strings.get(\n d.type === 'success'\n ? G9StringKey.Success\n : d.type === 'warning'\n ? G9StringKey.Warning\n : d.type === 'error'\n ? G9StringKey.Error\n : G9StringKey.Information,\n );\n const content = typeof d.content === 'function' ? (d.content as () => ReactNode)() : d.content;\n const direction = useG9Direction();\n const row = g9RowStyle(direction);\n return (\n <view className=\"g9-popup__content\">\n {settings.showHeader !== false ? (\n <view className=\"g9-popup__header\" style={row}>\n <view className=\"g9-popup__badge\" accessibility-label={profile.semanticIconDescription}>\n <view className=\"g9-popup__badge-tint\" style={{ backgroundColor: profile.iconColor }} />\n <G9IconSlot icon={profile.icon} size={17} color={profile.iconColor} />\n </view>\n <text\n className=\"g9-popup__title\"\n text-maxline=\"1\"\n style={{ color: profile.titleColor, ...g9TextStart(direction) }}\n >\n {title}\n </text>\n {settings.showCloseButton ? (\n <view\n className=\"g9-popup__close\"\n accessibility-element={true}\n accessibility-traits=\"button\"\n accessibility-label={strings.get(G9StringKey.Close)}\n bindtap={close}\n >\n <G9IconSlot icon={glyphs.clear} size={20} color=\"var(--g9-on-surface-variant)\" />\n </view>\n ) : null}\n </view>\n ) : null}\n {settings.showHeader !== false ? <view className=\"g9-popup__divider\" /> : null}\n {d.message ? (\n <text className=\"g9-popup__message\" style={{ color: profile.messageColor, ...g9TextStart(direction) }}>\n {d.message}\n </text>\n ) : null}\n {content !== null && content !== undefined ? <view className=\"g9-popup__body\">{content}</view> : null}\n {settings.showFooter !== false ? (\n <view className={`g9-popup__footer${stacked ? ' g9-popup__footer--stacked' : ''}`} style={stacked ? {} : row}>\n {shown.map((button, i) => (\n <PopupButtonView\n key={i}\n id={button.testId ? g9SafeId(button.testId) : `G9Popup_Button_${i}`}\n button={button}\n profile={profile}\n busy={entry.busy}\n stacked={stacked}\n onPress={() => void state.service.queue.press(entry.id, i)}\n />\n ))}\n {entry.busy ? <G9ActivityIndicator running size={18} /> : null}\n </view>\n ) : null}\n </view>\n );\n}\n\n/** The popup layer: the active popup's frame; motion phases from the queue phase. */\nfunction PopupLayer(props: { readonly state: State }): ReactNode {\n const { state } = props;\n const settingsAll = useG9Settings();\n const diagnostics = useG9Diagnostics();\n state.defaults = settingsAll.popups;\n const glyphs = settingsAll.glyphs;\n const strings = useG9Strings();\n state.strings = (k) => strings.get(k);\n state.warn = (message) => diagnostics.log({ level: 'warning', message, source: 'G9Popup' });\n state.report = (error) =>\n diagnostics.log({ level: 'error', message: 'A popup callback failed.', source: 'G9Popup', error });\n const win = useG9Window();\n const queue = state.service.queue;\n const entry = useSyncExternalStore(\n (l) => queue.subscribe(l),\n () => queue.getSnapshot(),\n );\n // `enter` for one frame per show, then `open` (the transition runs), `leave` while closing.\n const [entered, setEntered] = useState<string | null>(null);\n const showKey = entry ? `${entry.id}:${entry.showCount}` : null;\n useEffect(() => {\n if (!showKey) return;\n const t = startTimer(() => setEntered(showKey), 16);\n return () => stopTimer(t);\n }, [showKey]);\n const settings = entry ? resolvePopupSettings(entry.descriptor, state.defaults) : null;\n const duration = settings?.animationDuration ?? 240;\n useEffect(() => {\n if (!entry || entered !== showKey || entry.phase !== 'opening') return;\n const t = startTimer(() => queue.markOpened(entry.id), duration);\n return () => stopTimer(t);\n }, [entered, showKey, entry?.phase]);\n useEffect(() => () => queue.dispose(), [queue]);\n if (!entry || !settings) return null;\n const profile = createPopupVisualProfile(entry.descriptor, settings, glyphs, (k) =>\n strings.get(\n k === 'success'\n ? G9StringKey.Success\n : k === 'warning'\n ? G9StringKey.Warning\n : k === 'error'\n ? G9StringKey.Error\n : G9StringKey.Information,\n ),\n );\n const options: G9PopupViewOpenOptions = {\n width: profile.width,\n height: profile.height,\n cornerRadius: profile.cornerRadius,\n padding: profile.padding,\n autoSizeMode: settings.autoSizeMode ?? 'height',\n cardBackground: profile.cardBackground,\n borderColor: profile.borderColor,\n overlayMode: settings.overlayMode ?? 'transparent',\n blurIntensity: settings.blurIntensity ?? 'none',\n overlayColor: profile.overlayColor,\n overlayOpacity: profile.overlayOpacity,\n animation: profile.animation,\n animationEasing: settings.animationEasing ?? 'sinOut',\n animationDuration: duration,\n };\n const phase = entry.phase === 'closing' ? 'leave' : entered === showKey ? 'open' : 'enter';\n return (\n <PopupFrame\n key={showKey as string}\n options={options}\n phase={phase}\n hostWidth={win.width}\n onBackgroundTap={() => queue.backgroundTap(entry.id)}\n >\n <PopupCardContent entry={entry} settings={settings} profile={profile} state={state} />\n </PopupFrame>\n );\n}\n\nfunction createPopupService(host: G9HostHandle): State {\n const state = { defaults: {}, strings: fallbackStrings.get } as unknown as State;\n const strings = (k: G9StringKey) => state.strings(k);\n const queue = new G9PopupQueue({\n setTimer: (cb, ms) => startTimer(cb, ms),\n clearTimer: (h) => stopTimer(h as never),\n closeDurationMs: (d) =>\n resolvePopupSettings(d, state.defaults).animation === 'none'\n ? 0\n : g9Ms(resolvePopupSettings(d, state.defaults).animationDuration ?? 240),\n autoCloseMs: (d) => resolvePopupSettings(d, state.defaults).autoCloseDuration ?? 0,\n closesOnBack: (d) => resolvePopupSettings(d, state.defaults).closeOnBackButton !== false,\n closesOnBackgroundTap: (d) => resolvePopupSettings(d, state.defaults).closeOnBackgroundClick === true,\n onError: (error) => state.report?.(error),\n });\n // A popup without buttons gets an OK button (MAUI presets).\n const withOk = (d: G9PopupDescriptor): G9PopupDescriptor =>\n d.buttons.length > 0 ? d : { ...d, buttons: [{ text: strings(G9StringKey.Ok), isPrimary: true }] };\n const preset =\n (type: G9PopupType) =>\n (\n message: string,\n title?: string | null,\n buttons?: ReadonlyArray<G9PopupButton> | null,\n settings?: G9PopupSettings | null,\n animation?: G9PopupAnimationType | null,\n ) =>\n queue.show(withOk(presetPopup(type, message, title, buttons, settings, animation ?? null))).then((o) => o.result);\n const service: G9PopupService = {\n queue,\n show: preset('information'),\n showSuccess: preset('success'),\n showWarning: preset('warning'),\n showError: preset('error'),\n showCustom: (content, title, buttons, settings, animation) =>\n queue.show(withOk(customPopup(content, title, buttons, settings, animation ?? null))).then((o) => o.result),\n showDescriptor: (descriptor) => queue.show(withOk(descriptor)),\n async showInput(options) {\n const store = createPopupFormStore(options.fields);\n let result = g9PopupInputResult.cancel();\n const cancel: G9PopupButton = {\n ...(options.cancelButton ?? { text: options.cancelButtonText ?? strings(G9StringKey.Cancel) }),\n isPrimary: false,\n callback: () => {\n result = g9PopupInputResult.cancel();\n return g9PopupResult.close();\n },\n };\n const submit: G9PopupButton = {\n ...(options.submitButton ?? { text: options.submitButtonText ?? strings(G9StringKey.Save) }),\n isPrimary: true,\n callback: () => {\n const v = store.validate({\n requiredSuffix: strings(G9StringKey.RequiredSuffix),\n invalidEmail: strings(G9StringKey.InvalidEmail),\n });\n result = v.valid\n ? g9PopupInputResult.submit(v.values, v.arrayValues)\n : g9PopupInputResult.validationFailed(v.values, v.arrayValues, v.errors);\n return v.valid ? g9PopupResult.close() : g9PopupResult.noAction();\n },\n };\n const settings: G9PopupSettings = {\n showHeader: true,\n showFooter: true,\n showCloseButton: false,\n closeOnBackgroundClick: false,\n autoSizeMode: 'height',\n padding: [20, 12, 20, 8],\n ...Object.fromEntries(Object.entries(options.settings ?? {}).filter(([, v]) => v !== undefined && v !== null)),\n };\n await queue.show({\n type: options.type ?? 'information',\n title: options.title ?? null,\n message: options.message ?? null,\n content: () => <PopupInputForm store={store} focusFirst={options.focusFirstFieldOnOpen !== false} />,\n buttons: [cancel, submit],\n settings,\n animation: options.animation ?? null,\n form: {\n fieldKeys: options.fields.map((f) => f.key),\n setText: (key, value) => store.setText(key, value),\n getText: (key) => store.getState().form.text[key] ?? null,\n },\n });\n return result;\n },\n async showConfirm(message, options = {}) {\n let ok = false;\n await queue.show(\n presetPopup(options.type ?? 'information', message, options.title ?? null, [\n {\n text: options.cancelText ?? strings(G9StringKey.Cancel),\n isPrimary: false,\n callback: async (c) => {\n await options.cancelCallback?.(c);\n return g9PopupResult.close();\n },\n },\n {\n text: options.okText ?? strings(G9StringKey.Ok),\n isPrimary: true,\n callback: async (c) => {\n await options.okCallback?.(c);\n ok = true;\n return g9PopupResult.close();\n },\n },\n ]),\n );\n return ok;\n },\n handleHardwareBack: () => queue.handleBack(),\n closeActive: () => queue.closeActive(),\n clearQueue: () => queue.clearQueue(),\n dismissAll: () => queue.dismissAll(),\n };\n state.service = service;\n host.attachFeature(FEATURE, state);\n host.registerLayerItem('popups', { key: FEATURE, element: <PopupLayer state={state} />, order: 0 });\n host.back.push(() => (queue.handleBack() ? 'handled' : 'pass'), { layer: 'popups' });\n return state;\n}\n\n/** The popup service of a host (created once as a host feature). */\nexport function popupServiceOf(host: G9HostHandle): G9PopupService {\n const existing = host.getFeature(FEATURE) as State | undefined;\n return (existing ?? createPopupService(host)).service;\n}\n\n/** The popups of the nearest `G9Host` (MAUI `G9PopupHelper`): one card at a time, FIFO, in the `popups` layer. */\nexport function useG9Popups(): G9PopupService {\n return popupServiceOf(useG9Host());\n}\n\n/** The popups of the active host, for code outside components. Throws `host-missing` without a host. */\nexport function g9Popups(): G9PopupService {\n return popupServiceOf(g9Hosts.require());\n}\n\n/**\n * The default error presenter (installed when this module loads): the executor's error popup as an error-type popup\n * on the active host, with More details when diagnostics are available. Without a host it does nothing.\n */\nexport function presentErrorPopup(request: G9ErrorPopupRequest): Promise<void> | undefined {\n const host = g9Hosts.active();\n if (!host) return undefined;\n const popups = popupServiceOf(host);\n const buttons: G9PopupButton[] = [];\n if (request.moreDetails) {\n const more = request.moreDetails;\n buttons.push({ text: more.text, isPrimary: false, callback: async () => void (await more.open()) });\n }\n buttons.push({ text: request.okText, isPrimary: true });\n return popups.showError(request.message, request.title, buttons).then(() => undefined);\n}\n\ng9DefaultErrorPresenter.current = presentErrorPopup;\n"],"names":["g9PopupRowButtonLimit","FEATURE","fallbackStrings","createStrings","createCulture","PopupButtonView","props","_button_backgroundColor","_button_textColor","_button_iconImage","button","profile","primary","press","useG9Press","background","color","view","G9IconSlot","text","PopupCardContent","_d_title","entry","settings","state","strings","useG9Strings","d","close","glyphs","useG9Settings","buttons","stacked","shown","warned","useRef","title","G9StringKey","content","direction","useG9Direction","row","g9RowStyle","g9TextStart","i","g9SafeId","G9ActivityIndicator","PopupLayer","_settings_autoSizeMode","_settings_overlayMode","_settings_blurIntensity","_settings_animationEasing","settingsAll","diagnostics","useG9Diagnostics","k","message","error","win","useG9Window","queue","useSyncExternalStore","l","entered","setEntered","useState","showKey","useEffect","t","startTimer","stopTimer","resolvePopupSettings","duration","createPopupVisualProfile","options","phase","PopupFrame","createPopupService","host","G9PopupQueue","cb","ms","h","_resolvePopupSettings_animationDuration","g9Ms","_resolvePopupSettings_autoCloseDuration","withOk","preset","type","animation","presetPopup","o","service","customPopup","descriptor","_options_cancelButton","_options_cancelButtonText","_options_submitButton","_options_submitButtonText","_options_settings","_options_type","_options_title","_options_message","_options_animation","store","createPopupFormStore","result","g9PopupInputResult","cancel","g9PopupResult","submit","v","Object","PopupInputForm","f","key","value","_store_getState_form_text_key","_options_cancelText","_options_okText","ok","c","popupServiceOf","existing","useG9Popups","useG9Host","g9Popups","g9Hosts","presentErrorPopup","request","popups","more","undefined","g9DefaultErrorPresenter"],"mappings":"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"}
|
|
@@ -14,5 +14,9 @@
|
|
|
14
14
|
direction: rtl;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
.g9-motion-off .g9-deferred__cover, .g9-motion-off .g9-progress__fill, .g9-motion-off .g9-expander__chevron, .g9-motion-off .g9-expander__clip, .g9-motion-off .g9-field__label, .g9-motion-off .g9-page-loading, .g9-motion-off .g9-toast__fill, .g9-motion-off .g9-switch__track, .g9-motion-off .g9-switch__thumb, .g9-motion-off .g9-chip, .g9-motion-off .g9-chip__check {
|
|
18
|
+
transition-duration: 0s;
|
|
19
|
+
}
|
|
20
|
+
|
|
17
21
|
|
|
18
22
|
/*# sourceMappingURL=provider.css.map */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["webpack://./src/provider/provider.css"],"names":[],"mappings":"AACA;EAAE,sBAAsB;EACtB,OAAO;EACP,WAAW;EACX,YAAY;EACZ,aAAa;AACf;;AAIA;EADE,cAAc;AAChB;;AAIA;EADE,cAAc;AAChB","sourcesContent":["/* G9Provider root: fills the LynxView and carries the theme variables (set inline / with setProperty). */\n.g9-provider {\n display: flex;\n flex-direction: column;\n flex: 1;\n width: 100%;\n height: 100%;\n}\n\n/* direction does not inherit in Lynx (plan/specs/02 §2): every G9 root sets it; these are the provider's. */\n.g9-dir-ltr {\n direction: ltr;\n}\n\n.g9-dir-rtl {\n direction: rtl;\n}\n"],"sourceRoot":""}
|
|
1
|
+
{"version":3,"sources":["webpack://./src/provider/provider.css"],"names":[],"mappings":"AACA;EAAE,sBAAsB;EACtB,OAAO;EACP,WAAW;EACX,YAAY;EACZ,aAAa;AACf;;AAIA;EADE,cAAc;AAChB;;AAIA;EADE,cAAc;AAChB;;AAOA;EAJE,uBAAuB;AACzB","sourcesContent":["/* G9Provider root: fills the LynxView and carries the theme variables (set inline / with setProperty). */\n.g9-provider {\n display: flex;\n flex-direction: column;\n flex: 1;\n width: 100%;\n height: 100%;\n}\n\n/* direction does not inherit in Lynx (plan/specs/02 §2): every G9 root sets it; these are the provider's. */\n.g9-dir-ltr {\n direction: ltr;\n}\n\n.g9-dir-rtl {\n direction: rtl;\n}\n\n/* Reduced motion (setG9MotionScale(0), the provider's `g9-motion-off`): every CSS transition of the kit ends at once, as\n the JS-timed motion does. Listed one by one (no universal selector); a new transition in a component belongs here too\n (provider-motion.test.ts checks); another package lists its own in its own stylesheet (progress-overlay.css). The infinite spinners keep turning: they say «busy», they move nothing a test waits for. */\n.g9-motion-off .g9-deferred__cover,\n.g9-motion-off .g9-progress__fill,\n.g9-motion-off .g9-expander__chevron,\n.g9-motion-off .g9-expander__clip,\n.g9-motion-off .g9-field__label,\n.g9-motion-off .g9-page-loading,\n.g9-motion-off .g9-toast__fill,\n.g9-motion-off .g9-switch__track,\n.g9-motion-off .g9-switch__thumb,\n.g9-motion-off .g9-chip,\n.g9-motion-off .g9-chip__check {\n transition-duration: 0ms;\n}\n"],"sourceRoot":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/provider/provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,cAAc,EACnB,KAAK,aAAa,EAElB,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,aAAa,EAGlB,KAAK,cAAc,EACnB,KAAK,YAAY,
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/provider/provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,cAAc,EACnB,KAAK,aAAa,EAElB,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,aAAa,EAGlB,KAAK,cAAc,EACnB,KAAK,YAAY,EAMlB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,KAAK,SAAS,EAA8D,MAAM,gBAAgB,CAAC;AAgB5G,OAAO,EAAE,KAAK,UAAU,EAA4C,MAAM,YAAY,CAAC;AAEvF,OAAO,gBAAgB,CAAC;AACxB,OAAO,aAAa,CAAC;AAErB,mCAAmC;AACnC,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAC3C;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,SAAS,GAAG,MAAM,CAAC;IACvD;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,GAAG,cAAc,CAAC;IAC/C,kHAAkH;IAClH,QAAQ,CAAC,YAAY,CAAC,EAAE,aAAa,CAAC;IACtC;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAChC,8EAA8E;IAC9E,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC;IAC/B,gEAAgE;IAChE,QAAQ,CAAC,WAAW,CAAC,EAAE,aAAa,CAAC;IACrC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC;CAC/B;AA6BD;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,SAAS,CAmO5D"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { assertRequiredCapabilities, createCultureStore, createDiagnostics, createIconFontRegistry, createPreferences, createSafeExecutor, createStrings, createThemeStore, toCssVariables, toLayoutCssVariables, toMetricCssVariables } from "@g9tm/lynxcontrols-foundation";
|
|
1
|
+
import { assertRequiredCapabilities, createCultureStore, createDiagnostics, createIconFontRegistry, createPreferences, createSafeExecutor, createStrings, createThemeStore, g9MotionScale, subscribeG9Motion, toCssVariables, toLayoutCssVariables, toMetricCssVariables } from "@g9tm/lynxcontrols-foundation";
|
|
2
2
|
import { useEffect, useMemo, useRef, useState, useSyncExternalStore } from "@lynx-js/react";
|
|
3
3
|
import { useStableCallback } from "../base/use-stable-callback.jsx";
|
|
4
4
|
import { g9Hosts } from "../host/registry.jsx";
|
|
@@ -265,6 +265,8 @@ function G9Provider(props) {
|
|
|
265
265
|
settings.backEventName,
|
|
266
266
|
onBack
|
|
267
267
|
]);
|
|
268
|
+
const [motionOff, setMotionOff] = useState(()=>0 === g9MotionScale());
|
|
269
|
+
useEffect(()=>subscribeG9Motion((s)=>setMotionOff(0 === s)), []);
|
|
268
270
|
const rootStyle = null != fallbackVariables ? fallbackVariables : initialVariables;
|
|
269
271
|
const directionClass = 'rtl' === culture.direction ? 'g9-dir-rtl' : 'g9-dir-ltr';
|
|
270
272
|
return <G9CoreContext.Provider value={core}>
|
|
@@ -274,7 +276,7 @@ function G9Provider(props) {
|
|
|
274
276
|
<G9KeyboardContext.Provider value={keyboard}>
|
|
275
277
|
<G9WindowContext.Provider value={windowState}>
|
|
276
278
|
<G9InsetsContext.Provider value={insets}>
|
|
277
|
-
<view id={rootId} className={`g9-provider g9-theme-${initialScheme} ${directionClass}${props.className ? ` ${props.className}` : ''}`} style={rootStyle}>
|
|
279
|
+
<view id={rootId} className={`g9-provider g9-theme-${initialScheme} ${directionClass}${motionOff ? ' g9-motion-off' : ''}${props.className ? ` ${props.className}` : ''}`} style={rootStyle}>
|
|
278
280
|
{props.children}
|
|
279
281
|
</view>
|
|
280
282
|
</G9InsetsContext.Provider>
|