@hjmds/react-native 1.17.2 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/dist/actions.d.ts +3 -23
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +8 -11
- package/dist/actions.js.map +1 -1
- package/dist/activity-chip.d.ts +29 -0
- package/dist/activity-chip.d.ts.map +1 -0
- package/dist/activity-chip.js +54 -0
- package/dist/activity-chip.js.map +1 -0
- package/dist/agreement.d.ts +1 -7
- package/dist/agreement.d.ts.map +1 -1
- package/dist/agreement.js +21 -15
- package/dist/agreement.js.map +1 -1
- package/dist/asset.d.ts +2 -13
- package/dist/asset.d.ts.map +1 -1
- package/dist/asset.js +4 -7
- package/dist/asset.js.map +1 -1
- package/dist/bottom-info.d.ts +1 -7
- package/dist/bottom-info.d.ts.map +1 -1
- package/dist/bottom-info.js +2 -4
- package/dist/bottom-info.js.map +1 -1
- package/dist/carousel-motion.d.ts +1 -0
- package/dist/carousel-motion.d.ts.map +1 -1
- package/dist/carousel-motion.js +5 -3
- package/dist/carousel-motion.js.map +1 -1
- package/dist/carousel.d.ts +1 -7
- package/dist/carousel.d.ts.map +1 -1
- package/dist/carousel.js +14 -6
- package/dist/carousel.js.map +1 -1
- package/dist/collapsible.d.ts +1 -7
- package/dist/collapsible.d.ts.map +1 -1
- package/dist/collapsible.js +4 -4
- package/dist/collapsible.js.map +1 -1
- package/dist/content-transition.d.ts +2 -1
- package/dist/content-transition.d.ts.map +1 -1
- package/dist/content-transition.js +3 -3
- package/dist/content-transition.js.map +1 -1
- package/dist/data-display.d.ts +23 -154
- package/dist/data-display.d.ts.map +1 -1
- package/dist/data-display.js +86 -92
- package/dist/data-display.js.map +1 -1
- package/dist/date-entry.d.ts +1 -0
- package/dist/date-entry.d.ts.map +1 -1
- package/dist/date-entry.js +22 -20
- package/dist/date-entry.js.map +1 -1
- package/dist/date-picker.d.ts +1 -7
- package/dist/date-picker.d.ts.map +1 -1
- package/dist/date-picker.js +19 -11
- package/dist/date-picker.js.map +1 -1
- package/dist/duration-field.d.ts +1 -1
- package/dist/duration-field.d.ts.map +1 -1
- package/dist/duration-field.js +11 -9
- package/dist/duration-field.js.map +1 -1
- package/dist/evidence.d.ts +1 -1
- package/dist/evidence.js +1 -1
- package/dist/feedback.d.ts +9 -88
- package/dist/feedback.d.ts.map +1 -1
- package/dist/feedback.js +124 -81
- package/dist/feedback.js.map +1 -1
- package/dist/field-group.d.ts +3 -2
- package/dist/field-group.d.ts.map +1 -1
- package/dist/field-group.js +7 -4
- package/dist/field-group.js.map +1 -1
- package/dist/file-picker.d.ts +1 -7
- package/dist/file-picker.d.ts.map +1 -1
- package/dist/file-picker.js +21 -11
- package/dist/file-picker.js.map +1 -1
- package/dist/forms.d.ts +6 -21
- package/dist/forms.d.ts.map +1 -1
- package/dist/forms.js +29 -35
- package/dist/forms.js.map +1 -1
- package/dist/gravity-letters.d.ts.map +1 -1
- package/dist/gravity-letters.js +13 -5
- package/dist/gravity-letters.js.map +1 -1
- package/dist/grid-reveal.d.ts.map +1 -1
- package/dist/grid-reveal.js +10 -2
- package/dist/grid-reveal.js.map +1 -1
- package/dist/heading.d.ts +1 -7
- package/dist/heading.d.ts.map +1 -1
- package/dist/heading.js +1 -4
- package/dist/heading.js.map +1 -1
- package/dist/image-viewer.d.ts.map +1 -1
- package/dist/image-viewer.js +2 -1
- package/dist/image-viewer.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/inline-confirm.d.ts.map +1 -1
- package/dist/inline-confirm.js +5 -1
- package/dist/inline-confirm.js.map +1 -1
- package/dist/inputs.d.ts +4 -71
- package/dist/inputs.d.ts.map +1 -1
- package/dist/inputs.js +52 -67
- package/dist/inputs.js.map +1 -1
- package/dist/internal/accessible-focus.d.ts +3 -0
- package/dist/internal/accessible-focus.d.ts.map +1 -0
- package/dist/internal/accessible-focus.js +15 -0
- package/dist/internal/accessible-focus.js.map +1 -0
- package/dist/internal/diagnostics.d.ts +7 -0
- package/dist/internal/diagnostics.d.ts.map +1 -0
- package/dist/internal/diagnostics.js +20 -0
- package/dist/internal/diagnostics.js.map +1 -0
- package/dist/internal/document-resource.d.ts.map +1 -1
- package/dist/internal/document-resource.js +2 -2
- package/dist/internal/document-resource.js.map +1 -1
- package/dist/internal/recipe-button.js +1 -1
- package/dist/internal/recipe-button.js.map +1 -1
- package/dist/internal/spinner.d.ts +1 -7
- package/dist/internal/spinner.d.ts.map +1 -1
- package/dist/internal/spinner.js +2 -4
- package/dist/internal/spinner.js.map +1 -1
- package/dist/masonry.d.ts.map +1 -1
- package/dist/masonry.js +2 -1
- package/dist/masonry.js.map +1 -1
- package/dist/mentions.d.ts +1 -7
- package/dist/mentions.d.ts.map +1 -1
- package/dist/mentions.js +11 -7
- package/dist/mentions.js.map +1 -1
- package/dist/navigation.d.ts +4 -74
- package/dist/navigation.d.ts.map +1 -1
- package/dist/navigation.js +86 -45
- package/dist/navigation.js.map +1 -1
- package/dist/number-field.d.ts +1 -21
- package/dist/number-field.d.ts.map +1 -1
- package/dist/number-field.js +6 -5
- package/dist/number-field.js.map +1 -1
- package/dist/overlays.d.ts +7 -16
- package/dist/overlays.d.ts.map +1 -1
- package/dist/overlays.js +220 -213
- package/dist/overlays.js.map +1 -1
- package/dist/primitives.d.ts +3 -18
- package/dist/primitives.d.ts.map +1 -1
- package/dist/primitives.js +8 -10
- package/dist/primitives.js.map +1 -1
- package/dist/provider-button.d.ts +1 -7
- package/dist/provider-button.d.ts.map +1 -1
- package/dist/provider-button.js +1 -4
- package/dist/provider-button.js.map +1 -1
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +9 -1
- package/dist/provider.js.map +1 -1
- package/dist/saved-items.d.ts.map +1 -1
- package/dist/saved-items.js +6 -1
- package/dist/saved-items.js.map +1 -1
- package/dist/screen-flows.d.ts +1 -2
- package/dist/screen-flows.d.ts.map +1 -1
- package/dist/screen-flows.js +60 -16
- package/dist/screen-flows.js.map +1 -1
- package/dist/screens.d.ts +1 -1
- package/dist/screens.d.ts.map +1 -1
- package/dist/screens.js +32 -15
- package/dist/screens.js.map +1 -1
- package/dist/sheet-gesture.d.ts.map +1 -1
- package/dist/sheet-gesture.js +6 -3
- package/dist/sheet-gesture.js.map +1 -1
- package/dist/slider.d.ts +1 -21
- package/dist/slider.d.ts.map +1 -1
- package/dist/slider.js +3 -5
- package/dist/slider.js.map +1 -1
- package/dist/sortable.d.ts.map +1 -1
- package/dist/sortable.js +2 -1
- package/dist/sortable.js.map +1 -1
- package/dist/status-text.d.ts +17 -0
- package/dist/status-text.d.ts.map +1 -0
- package/dist/status-text.js +18 -0
- package/dist/status-text.js.map +1 -0
- package/dist/steps.d.ts +1 -7
- package/dist/steps.d.ts.map +1 -1
- package/dist/steps.js +2 -4
- package/dist/steps.js.map +1 -1
- package/dist/swipe-actions.d.ts.map +1 -1
- package/dist/swipe-actions.js +13 -2
- package/dist/swipe-actions.js.map +1 -1
- package/dist/tags-input.d.ts +1 -7
- package/dist/tags-input.d.ts.map +1 -1
- package/dist/tags-input.js +2 -4
- package/dist/tags-input.js.map +1 -1
- package/dist/toggle-group.d.ts +1 -7
- package/dist/toggle-group.d.ts.map +1 -1
- package/dist/toggle-group.js +10 -5
- package/dist/toggle-group.js.map +1 -1
- package/dist/top.d.ts +1 -7
- package/dist/top.d.ts.map +1 -1
- package/dist/top.js +1 -4
- package/dist/top.js.map +1 -1
- package/dist/transfer-list.d.ts +2 -8
- package/dist/transfer-list.d.ts.map +1 -1
- package/dist/transfer-list.js +30 -11
- package/dist/transfer-list.js.map +1 -1
- package/dist/upload-item.d.ts +1 -7
- package/dist/upload-item.d.ts.map +1 -1
- package/dist/upload-item.js +2 -4
- package/dist/upload-item.js.map +1 -1
- package/dist/virtual-list.d.ts.map +1 -1
- package/dist/virtual-list.js +2 -1
- package/dist/virtual-list.js.map +1 -1
- package/docs/liquid-toast.md +20 -0
- package/package.json +17 -4
- package/dist/internal/deprecated-style.d.ts +0 -8
- package/dist/internal/deprecated-style.d.ts.map +0 -1
- package/dist/internal/deprecated-style.js +0 -34
- package/dist/internal/deprecated-style.js.map +0 -1
package/dist/overlays.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { resolveOriginTransition } from "@hjmds/design-contracts/content-transition";
|
|
3
|
+
import { focusAccessibleHost } from "./internal/accessible-focus.js";
|
|
3
4
|
import { createAlertDialogSession, getAlertDialogInitialFocus, validateAlertDialogRequest, } from "@hjmds/design-contracts/components/alert-dialog";
|
|
4
|
-
import {
|
|
5
|
+
import {} from "./composition-style.js";
|
|
5
6
|
import { canDismissSheet, createSheetLifecycle, sheetBehaviorDefaults, } from "@hjmds/design-contracts/components/sheet";
|
|
6
7
|
import { resolveColorReference } from "@hjmds/design-contracts/color-references";
|
|
7
8
|
import { backdrop, easing, glyph, spacing } from "@hjmds/design-contracts/foundations";
|
|
8
9
|
import { alertDialogRecipe, dialogRecipe, sheetRecipe, } from "@hjmds/design-contracts/recipes";
|
|
9
10
|
import { useCallback, useEffect, useRef, useState, useSyncExternalStore, } from "react";
|
|
10
|
-
import {
|
|
11
|
+
import { Animated, Easing, Keyboard, Modal, Platform, ScrollView, Pressable, View, useWindowDimensions, } from "react-native";
|
|
11
12
|
import { Button, IconButton } from "./actions.js";
|
|
12
13
|
import { scheduleAfterNativeModalTeardown, shouldAwaitNativeModalDismiss, } from "./internal/modal-lifecycle.js";
|
|
13
|
-
import { isDevelopment
|
|
14
|
+
import { isDevelopment } from "./internal/diagnostics.js";
|
|
14
15
|
import { FixedGlyph } from "./internal/fixed-glyph.js";
|
|
15
16
|
import { minimumTargetStyle } from "./internal/styles.js";
|
|
16
17
|
import { Text } from "./primitives.js";
|
|
@@ -20,6 +21,12 @@ import { resolveNativeShadowElevation } from "./internal/styles.js";
|
|
|
20
21
|
function CloseGlyph() {
|
|
21
22
|
return _jsx(FixedGlyph, { fontSize: glyph.sm, children: "\u00D7" });
|
|
22
23
|
}
|
|
24
|
+
// Keep interaction visibility off native-driven animation hosts. In iOS 26.5,
|
|
25
|
+
// Dialog/AlertDialog/Sheet lost their AX descendants on a second presentation
|
|
26
|
+
// while still painting; a non-animated boundary preserves reopen accessibility.
|
|
27
|
+
function ModalInteractionBoundary({ visible, children }) {
|
|
28
|
+
return _jsx(View, { accessibilityElementsHidden: !visible, importantForAccessibility: visible ? "auto" : "no-hide-descendants", pointerEvents: visible ? "auto" : "none", style: { flex: 1 }, children: children });
|
|
29
|
+
}
|
|
23
30
|
// BT-QA-027: maximum text made a centered BurnTok confirmation taller than the
|
|
24
31
|
// window, putting its title/cancel off-screen. Keep full copy in a bounded scroll
|
|
25
32
|
// and actions outside it; capping fonts or clipping copy would hide the decision.
|
|
@@ -28,6 +35,47 @@ function DialogScrollBody({ children, gap }) {
|
|
|
28
35
|
// Positioner owns safe-area clearance.
|
|
29
36
|
automaticallyAdjustContentInsets: false, automaticallyAdjustKeyboardInsets: false, children: children });
|
|
30
37
|
}
|
|
38
|
+
// Dialog input QA on iOS 26.5 exposed a Save action behind the keyboard.
|
|
39
|
+
// Share Sheet's measured viewport math so centered modals also avoid double
|
|
40
|
+
// clearance on Android adjustResize and ignore undocked/floating keyboards.
|
|
41
|
+
function useModalKeyboardViewport(active, enabled = true) {
|
|
42
|
+
const { width: windowWidth, height: windowHeight } = useWindowDimensions();
|
|
43
|
+
const [modalHeight, setModalHeight] = useState(null);
|
|
44
|
+
const [keyboardFrame, setKeyboardFrame] = useState(null);
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
if (!active || !enabled) {
|
|
47
|
+
setKeyboardFrame(null);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
// A modal may open while an input elsewhere already owns the keyboard. Event-only
|
|
51
|
+
// tracking misses that case; metrics also restores the correct state on reopen.
|
|
52
|
+
// RN Web has no metrics() API; its keyboard events can still update the frame.
|
|
53
|
+
setKeyboardFrame(Keyboard.metrics?.() ?? null);
|
|
54
|
+
const change = (event) => setKeyboardFrame(event.endCoordinates);
|
|
55
|
+
const hide = () => setKeyboardFrame(null);
|
|
56
|
+
const subscriptions = [
|
|
57
|
+
Keyboard.addListener("keyboardDidShow", change),
|
|
58
|
+
Keyboard.addListener("keyboardDidHide", hide),
|
|
59
|
+
...(Platform.OS === "ios" ? [
|
|
60
|
+
Keyboard.addListener("keyboardWillChangeFrame", change),
|
|
61
|
+
Keyboard.addListener("keyboardWillHide", hide),
|
|
62
|
+
] : []),
|
|
63
|
+
];
|
|
64
|
+
return () => subscriptions.forEach((subscription) => subscription.remove());
|
|
65
|
+
}, [enabled, active]);
|
|
66
|
+
// Modal owns a full-screen coordinate space (statusBarTranslucent). Measure its
|
|
67
|
+
// actual height so Android adjustResize does not subtract the keyboard twice.
|
|
68
|
+
const viewportHeight = modalHeight ?? windowHeight;
|
|
69
|
+
const dockedKeyboard = enabled && keyboardFrame !== null
|
|
70
|
+
// Android converts IME pixels to float dp independently from window dimensions;
|
|
71
|
+
// exact width comparison rejected a full-width keyboard by 0.000013 dp on API 36.
|
|
72
|
+
&& keyboardFrame.height > 0 && Math.abs(keyboardFrame.screenX) <= 1
|
|
73
|
+
&& keyboardFrame.width >= windowWidth - 1;
|
|
74
|
+
const keyboardInset = dockedKeyboard
|
|
75
|
+
? Math.max(0, viewportHeight - keyboardFrame.screenY)
|
|
76
|
+
: 0;
|
|
77
|
+
return { viewportHeight, keyboardInset, dockedKeyboard, setModalHeight };
|
|
78
|
+
}
|
|
31
79
|
function useDialogViewportPadding() {
|
|
32
80
|
const insets = useHjmNativeSafeAreaInsets();
|
|
33
81
|
// Missing insets count as zero.
|
|
@@ -64,11 +112,7 @@ function useReasonedOpenState({ open, defaultOpen = false, onOpenChange, }) {
|
|
|
64
112
|
return [visible, changeOpen];
|
|
65
113
|
}
|
|
66
114
|
function focusNativeTarget(target) {
|
|
67
|
-
|
|
68
|
-
return;
|
|
69
|
-
const handle = findNodeHandle(target.current);
|
|
70
|
-
if (handle !== null)
|
|
71
|
-
AccessibilityInfo.setAccessibilityFocus(handle);
|
|
115
|
+
focusAccessibleHost(target?.current);
|
|
72
116
|
}
|
|
73
117
|
function Scrim() {
|
|
74
118
|
return (_jsx(View, { accessible: false, importantForAccessibility: "no-hide-descendants", style: {
|
|
@@ -131,6 +175,7 @@ export function Dialog({ open, defaultOpen, onOpenChange, title, accessibilityTi
|
|
|
131
175
|
const visibleRef = useRef(visible);
|
|
132
176
|
visibleRef.current = visible;
|
|
133
177
|
const [nativeVisible, setNativeVisible] = useState(visible);
|
|
178
|
+
const keyboardViewport = useModalKeyboardViewport(nativeVisible);
|
|
134
179
|
const nativeVisibleRef = useRef(visible);
|
|
135
180
|
nativeVisibleRef.current = nativeVisible;
|
|
136
181
|
const nativeShownRef = useRef(false);
|
|
@@ -323,67 +368,58 @@ export function Dialog({ open, defaultOpen, onOpenChange, title, accessibilityTi
|
|
|
323
368
|
nativeShownRef.current = true;
|
|
324
369
|
startEnter();
|
|
325
370
|
onShow?.(event);
|
|
326
|
-
}, statusBarTranslucent: true, transparent: true, visible: nativeVisible, children:
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
* 1.x keeps AlertDialog/Sheet `contentStyle` wide; warn only on visual keys (layout use is supported).
|
|
375
|
-
*/
|
|
376
|
-
function warnVisualContentStyle(component, contentStyle) {
|
|
377
|
-
if (contentStyle === undefined || contentStyle === null)
|
|
378
|
-
return;
|
|
379
|
-
const flattened = StyleSheet.flatten(contentStyle) ?? {};
|
|
380
|
-
const hasVisualKey = Object.keys(flattened).some(key => !compositionKeys.has(key));
|
|
381
|
-
warnDeprecatedStyleProps(component, { contentStyle: hasVisualKey ? contentStyle : undefined }, "layout-only keys in contentStyle and size/placement for appearance");
|
|
371
|
+
}, statusBarTranslucent: true, transparent: true, visible: nativeVisible, children: _jsx(ModalInteractionBoundary, { visible: visible, children: _jsxs(Animated.View, { onLayout: (event) => keyboardViewport.setModalHeight(event.nativeEvent.layout.height), style: {
|
|
372
|
+
flex: 1,
|
|
373
|
+
justifyContent: "center",
|
|
374
|
+
opacity: motionProgress,
|
|
375
|
+
...viewportPadding,
|
|
376
|
+
paddingBottom: keyboardViewport.dockedKeyboard
|
|
377
|
+
? spacing.md + keyboardViewport.keyboardInset
|
|
378
|
+
: viewportPadding.paddingBottom,
|
|
379
|
+
}, children: [_jsx(Scrim, {}), dismissible ? (_jsx(Pressable, { accessible: false, importantForAccessibility: "no-hide-descendants", onPress: () => requestClose("outside"), style: { bottom: 0, left: 0, position: "absolute", right: 0, top: 0 } })) : null, _jsxs(Animated.View, { ref: originContentRef, onLayout: (event) => {
|
|
380
|
+
const { width, height } = event.nativeEvent.layout;
|
|
381
|
+
const previous = originLayout.current;
|
|
382
|
+
originLayout.current = { width, height };
|
|
383
|
+
// Error copy, keyboard or rotation may change the destination after entry.
|
|
384
|
+
// Fade instead of returning through stale dimensions; a later open remeasures.
|
|
385
|
+
if (previous && (previous.width !== width || previous.height !== height))
|
|
386
|
+
setOriginTransform(null);
|
|
387
|
+
}, accessibilityLabel: [accessibleTitle, description].filter(Boolean).join(", "), accessibilityState: { busy }, accessibilityViewIsModal: true, importantForAccessibility: "yes", role: "dialog", style: [
|
|
388
|
+
{
|
|
389
|
+
alignSelf: "center",
|
|
390
|
+
backgroundColor: contentBackground,
|
|
391
|
+
borderColor: contentBorder,
|
|
392
|
+
borderRadius: tokens.radius[dialogRecipe.content.radius],
|
|
393
|
+
borderWidth: dialogRecipe.content.borderWidth,
|
|
394
|
+
...resolveNativeShadowElevation(surfaceShadow, designProfile !== undefined, 8),
|
|
395
|
+
gap: dialogRecipe.content.gap,
|
|
396
|
+
maxWidth: sizeRecipe.maxWidth,
|
|
397
|
+
maxHeight: "100%",
|
|
398
|
+
flexShrink: 1,
|
|
399
|
+
padding: sizeRecipe.padding,
|
|
400
|
+
shadowColor: surfaceShadow.color,
|
|
401
|
+
shadowOffset: { width: 0, height: surfaceShadow.offsetY },
|
|
402
|
+
shadowOpacity: surfaceShadow.opacity,
|
|
403
|
+
shadowRadius: surfaceShadow.radius,
|
|
404
|
+
width: "100%",
|
|
405
|
+
},
|
|
406
|
+
originTransform && !environment.reducedMotion ? { transform: [
|
|
407
|
+
{ translateX: motionProgress.interpolate({ inputRange: [0, 1], outputRange: [originTransform.translateX, 0] }) },
|
|
408
|
+
{ translateY: motionProgress.interpolate({ inputRange: [0, 1], outputRange: [originTransform.translateY, 0] }) },
|
|
409
|
+
{ scaleX: motionProgress.interpolate({ inputRange: [0, 1], outputRange: [originTransform.scaleX, 1] }) },
|
|
410
|
+
{ scaleY: motionProgress.interpolate({ inputRange: [0, 1], outputRange: [originTransform.scaleY, 1] }) },
|
|
411
|
+
] } : undefined,
|
|
412
|
+
contentStyle,
|
|
413
|
+
], children: [_jsxs(View, { style: { flexShrink: 1, gap: description ? spacing.xs : dialogRecipe.content.gap }, children: [_jsxs(View, { style: {
|
|
414
|
+
alignItems: "flex-start",
|
|
415
|
+
direction: environment.direction,
|
|
416
|
+
flexDirection: "row",
|
|
417
|
+
gap: spacing.sm,
|
|
418
|
+
}, children: [_jsx(View, { style: { flex: 1 }, children: _jsx(Text, { accessibilityRole: "header", tone: "primary", variant: "title", children: title }) }), dismissible ? (_jsx(IconButton, { disabled: busy, label: closeLabel, onPress: () => requestClose("close-action"), children: _jsx(CloseGlyph, {}) })) : null] }), description || children ? (_jsxs(DialogScrollBody, { gap: dialogRecipe.content.gap, children: [description ? _jsx(Text, { tone: "muted", children: description }) : null, children] })) : null] }), _jsx(OverlayActions, { busy: busy, onAction: runAction, pendingAction: actionPending, stacked: stackActions, ...(primaryAction === undefined ? {} : { primaryAction }), ...(secondaryAction === undefined ? {} : { secondaryAction }) })] })] }) }) }));
|
|
382
419
|
}
|
|
383
420
|
/** Contract session owns duplicate confirms, busy dismissal, error and settlement. */
|
|
384
|
-
export function AlertDialog({ open, defaultOpen, onOpenChange, request, returnFocusRef, onResult, contentStyle, onShow, ...modalProps }) {
|
|
421
|
+
export function AlertDialog({ open, defaultOpen, onOpenChange, request, size = alertDialogRecipe.defaults.size, returnFocusRef, onResult, contentStyle, onShow, ...modalProps }) {
|
|
385
422
|
validateAlertDialogRequest(request);
|
|
386
|
-
warnVisualContentStyle("AlertDialog", contentStyle);
|
|
387
423
|
const viewportPadding = useDialogViewportPadding();
|
|
388
424
|
const { colors, environment, palette, tokens, designProfile } = useHjmNativeTheme();
|
|
389
425
|
// The profile floating role is shared with Web. Modal lifecycle, inset and
|
|
@@ -403,6 +439,7 @@ export function AlertDialog({ open, defaultOpen, onOpenChange, request, returnFo
|
|
|
403
439
|
const visibleRef = useRef(visible);
|
|
404
440
|
visibleRef.current = visible;
|
|
405
441
|
const [nativeVisible, setNativeVisible] = useState(visible);
|
|
442
|
+
const keyboardViewport = useModalKeyboardViewport(nativeVisible);
|
|
406
443
|
const nativeVisibleRef = useRef(visible);
|
|
407
444
|
nativeVisibleRef.current = nativeVisible;
|
|
408
445
|
const nativeShownRef = useRef(false);
|
|
@@ -586,7 +623,7 @@ export function AlertDialog({ open, defaultOpen, onOpenChange, request, returnFo
|
|
|
586
623
|
};
|
|
587
624
|
const resolvedTone = request.tone ?? alertDialogRecipe.defaults.tone;
|
|
588
625
|
const toneRecipe = alertDialogRecipe.tones[resolvedTone];
|
|
589
|
-
const sizeRecipe = alertDialogRecipe.sizes[
|
|
626
|
+
const sizeRecipe = alertDialogRecipe.sizes[size];
|
|
590
627
|
const stackActions = windowWidth < alertDialogRecipe.actions.stackBelow ||
|
|
591
628
|
environment.textScale >= 1.6;
|
|
592
629
|
const contentBackground = resolveColorReference(alertDialogRecipe.content.background, palette);
|
|
@@ -612,62 +649,64 @@ export function AlertDialog({ open, defaultOpen, onOpenChange, request, returnFo
|
|
|
612
649
|
const pending = pendingExitSessions.current[0];
|
|
613
650
|
if (pending)
|
|
614
651
|
completeExit(pending.session);
|
|
615
|
-
}, onRequestClose: () => cancel("back"), onShow: focusLeastDestructive, statusBarTranslucent: true, transparent: true, visible: nativeVisible, children:
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
652
|
+
}, onRequestClose: () => cancel("back"), onShow: focusLeastDestructive, statusBarTranslucent: true, transparent: true, visible: nativeVisible, children: _jsx(ModalInteractionBoundary, { visible: visible, children: _jsxs(Animated.View, { onLayout: (event) => keyboardViewport.setModalHeight(event.nativeEvent.layout.height), style: {
|
|
653
|
+
flex: 1,
|
|
654
|
+
justifyContent: "center",
|
|
655
|
+
opacity: motionProgress,
|
|
656
|
+
...viewportPadding,
|
|
657
|
+
paddingBottom: keyboardViewport.dockedKeyboard
|
|
658
|
+
? spacing.md + keyboardViewport.keyboardInset
|
|
659
|
+
: viewportPadding.paddingBottom,
|
|
660
|
+
}, children: [_jsx(Scrim, {}), _jsxs(View, { accessibilityLabel: `${request.title}, ${request.description}`, accessibilityState: { busy }, accessibilityViewIsModal: true, importantForAccessibility: "yes", role: "alertdialog", style: [
|
|
661
|
+
{
|
|
662
|
+
alignSelf: "center",
|
|
663
|
+
backgroundColor: contentBackground,
|
|
664
|
+
borderColor: contentBorder,
|
|
665
|
+
borderRadius: tokens.radius[alertDialogRecipe.content.radius],
|
|
666
|
+
borderWidth: alertDialogRecipe.content.borderWidth,
|
|
667
|
+
...resolveNativeShadowElevation(surfaceShadow, designProfile !== undefined, 8),
|
|
668
|
+
gap: alertDialogRecipe.content.gap,
|
|
669
|
+
maxWidth: sizeRecipe.maxWidth,
|
|
670
|
+
maxHeight: "100%",
|
|
671
|
+
flexShrink: 1,
|
|
672
|
+
padding: sizeRecipe.padding,
|
|
673
|
+
shadowColor: surfaceShadow.color,
|
|
674
|
+
shadowOffset: {
|
|
675
|
+
width: 0,
|
|
676
|
+
height: surfaceShadow.offsetY,
|
|
677
|
+
},
|
|
678
|
+
shadowOpacity: surfaceShadow.opacity,
|
|
679
|
+
shadowRadius: surfaceShadow.radius,
|
|
680
|
+
width: "100%",
|
|
637
681
|
},
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
opacity: busy ? 0.5 : pressed ? 0.86 : 1,
|
|
664
|
-
paddingHorizontal: spacing.md,
|
|
665
|
-
},
|
|
666
|
-
], children: _jsx(Text, { variant: "label", children: request.cancelLabel }) })) : null, stackActions ? null : confirmAction] })] })] }) }));
|
|
682
|
+
contentStyle,
|
|
683
|
+
], children: [_jsxs(DialogScrollBody, { gap: spacing.xs, children: [_jsx(Text, { accessibilityRole: "header", tone: "primary", variant: "title", children: request.title }), _jsx(Text, { tone: "muted", children: request.description }), error ? (_jsx(Text, { accessibilityLiveRegion: "assertive", accessibilityRole: "alert", style: { color: errorColor }, children: error })) : null] }), _jsxs(View, { style: {
|
|
684
|
+
direction: environment.direction,
|
|
685
|
+
flexDirection: stackActions ? "column" : "row",
|
|
686
|
+
gap: stackActions
|
|
687
|
+
? alertDialogRecipe.actions.stackedGap
|
|
688
|
+
: alertDialogRecipe.actions.gap,
|
|
689
|
+
}, children: [stackActions ? confirmAction : null, request.mode === "confirm" ? (_jsx(Pressable, { ref: cancelRef, accessibilityLabel: request.cancelLabel, accessibilityRole: "button", accessibilityState: { disabled: busy }, disabled: busy, onPress: () => cancel("cancel-action"), style: ({ pressed }) => [
|
|
690
|
+
minimumTargetStyle,
|
|
691
|
+
{
|
|
692
|
+
alignItems: "center",
|
|
693
|
+
// The cancel action is a quiet outline on the dialog surface. surfaceAlt
|
|
694
|
+
// turned it into a tinted slab wherever a product brands that token
|
|
695
|
+
// (BurnTok's pale blue, 2026-09-27), competing with the confirm fill.
|
|
696
|
+
backgroundColor: colors.bg,
|
|
697
|
+
borderColor: colors.border,
|
|
698
|
+
borderRadius: tokens.radius.md,
|
|
699
|
+
borderWidth: 1,
|
|
700
|
+
flex: stackActions ? undefined : 1,
|
|
701
|
+
justifyContent: "center",
|
|
702
|
+
minWidth: alertDialogRecipe.actions.minButtonWidth,
|
|
703
|
+
opacity: busy ? 0.5 : pressed ? 0.86 : 1,
|
|
704
|
+
paddingHorizontal: spacing.md,
|
|
705
|
+
},
|
|
706
|
+
], children: _jsx(Text, { variant: "label", children: request.cancelLabel }) })) : null, stackActions ? null : confirmAction] })] })] }) }) }));
|
|
667
707
|
}
|
|
668
708
|
/** Native Sheet applies policy before emitting a concrete dismissal reason. */
|
|
669
709
|
export function Sheet({ open, defaultOpen, onOpenChange, title, accessibilityTitle, description, children, footer, placement = "bottom", size = sheetRecipe.defaults.size, busy = false, dismissPolicy, closeLabel, returnFocusRef, safeAreaInsets: suppliedSafeAreaInsets, onDismissComplete, contentStyle, keyboardAvoidance = false, scrollable = false, onShow, ...modalProps }) {
|
|
670
|
-
warnVisualContentStyle("Sheet", contentStyle);
|
|
671
710
|
const { environment, palette, tokens, designProfile } = useHjmNativeTheme();
|
|
672
711
|
// The profile floating role is shared with Web. Modal lifecycle, inset and
|
|
673
712
|
// action state remain recipe-owned; changing decoration must not replace them.
|
|
@@ -683,8 +722,6 @@ export function Sheet({ open, defaultOpen, onOpenChange, title, accessibilityTit
|
|
|
683
722
|
};
|
|
684
723
|
const accessibleTitle = resolveOverlayAccessibleTitle(title, accessibilityTitle);
|
|
685
724
|
const { width: windowWidth, height: windowHeight } = useWindowDimensions();
|
|
686
|
-
const [modalHeight, setModalHeight] = useState(null);
|
|
687
|
-
const [keyboardFrame, setKeyboardFrame] = useState(null);
|
|
688
725
|
const sizeRatio = sheetRecipe.sizes[size];
|
|
689
726
|
const policy = { ...sheetBehaviorDefaults, ...dismissPolicy };
|
|
690
727
|
const [visible, changeOpen] = useReasonedOpenState({
|
|
@@ -697,6 +734,7 @@ export function Sheet({ open, defaultOpen, onOpenChange, title, accessibilityTit
|
|
|
697
734
|
const visibleRef = useRef(visible);
|
|
698
735
|
visibleRef.current = visible;
|
|
699
736
|
const [nativeVisible, setNativeVisible] = useState(visible);
|
|
737
|
+
const { viewportHeight, keyboardInset, dockedKeyboard, setModalHeight } = useModalKeyboardViewport(nativeVisible, keyboardAvoidance);
|
|
700
738
|
const nativeVisibleRef = useRef(visible);
|
|
701
739
|
nativeVisibleRef.current = nativeVisible;
|
|
702
740
|
const nativeShownRef = useRef(false);
|
|
@@ -720,37 +758,6 @@ export function Sheet({ open, defaultOpen, onOpenChange, title, accessibilityTit
|
|
|
720
758
|
throw new RangeError(`Sheet safeAreaInsets.${edge} must be non-negative`);
|
|
721
759
|
}
|
|
722
760
|
}
|
|
723
|
-
useEffect(() => {
|
|
724
|
-
if (!nativeVisible || !keyboardAvoidance) {
|
|
725
|
-
setKeyboardFrame(null);
|
|
726
|
-
return;
|
|
727
|
-
}
|
|
728
|
-
// A sheet may open while an input elsewhere already owns the keyboard. Event-only
|
|
729
|
-
// tracking misses that case; metrics also restores the correct state on reopen.
|
|
730
|
-
setKeyboardFrame(Keyboard.metrics() ?? null);
|
|
731
|
-
const change = (event) => setKeyboardFrame(event.endCoordinates);
|
|
732
|
-
const hide = () => setKeyboardFrame(null);
|
|
733
|
-
const subscriptions = [
|
|
734
|
-
Keyboard.addListener("keyboardDidShow", change),
|
|
735
|
-
Keyboard.addListener("keyboardDidHide", hide),
|
|
736
|
-
...(Platform.OS === "ios" ? [
|
|
737
|
-
Keyboard.addListener("keyboardWillChangeFrame", change),
|
|
738
|
-
Keyboard.addListener("keyboardWillHide", hide),
|
|
739
|
-
] : []),
|
|
740
|
-
];
|
|
741
|
-
return () => subscriptions.forEach((subscription) => subscription.remove());
|
|
742
|
-
}, [keyboardAvoidance, nativeVisible]);
|
|
743
|
-
// Modal owns a full-screen coordinate space (statusBarTranslucent). Measure its
|
|
744
|
-
// actual height so Android adjustResize does not subtract the keyboard twice.
|
|
745
|
-
const viewportHeight = modalHeight ?? windowHeight;
|
|
746
|
-
const dockedKeyboard = keyboardAvoidance && keyboardFrame !== null
|
|
747
|
-
// Android converts IME pixels to float dp independently from window dimensions;
|
|
748
|
-
// exact width comparison rejected a full-width keyboard by 0.000013 dp on API 36.
|
|
749
|
-
&& keyboardFrame.height > 0 && Math.abs(keyboardFrame.screenX) <= 1
|
|
750
|
-
&& keyboardFrame.width >= windowWidth - 1;
|
|
751
|
-
const keyboardInset = dockedKeyboard
|
|
752
|
-
? Math.max(0, viewportHeight - keyboardFrame.screenY)
|
|
753
|
-
: 0;
|
|
754
761
|
const availableHeight = Math.max(0, viewportHeight - keyboardInset - insets.top);
|
|
755
762
|
const bottomInset = dockedKeyboard ? 0 : insets.bottom;
|
|
756
763
|
const cancelDismissFallback = useCallback(() => {
|
|
@@ -925,68 +932,68 @@ export function Sheet({ open, defaultOpen, onOpenChange, title, accessibilityTit
|
|
|
925
932
|
nativeShownRef.current = true;
|
|
926
933
|
startEnter();
|
|
927
934
|
onShow?.(event);
|
|
928
|
-
}, statusBarTranslucent: true, transparent: true, visible: nativeVisible, children:
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
935
|
+
}, statusBarTranslucent: true, transparent: true, visible: nativeVisible, children: _jsx(ModalInteractionBoundary, { visible: visible, children: _jsxs(Animated.View, { onLayout: (event) => setModalHeight(event.nativeEvent.layout.height), style: {
|
|
936
|
+
alignItems: physicalPlacement === "right" ? "flex-end" : "flex-start",
|
|
937
|
+
flex: 1,
|
|
938
|
+
justifyContent: physicalPlacement === "bottom" ? "flex-end" : "flex-start",
|
|
939
|
+
opacity: motionProgress,
|
|
940
|
+
paddingTop: insets.top,
|
|
941
|
+
paddingBottom: keyboardInset,
|
|
942
|
+
}, children: [_jsx(Scrim, {}), policy.dismissible && policy.outsideDismiss ? (_jsx(Pressable, { accessible: false, importantForAccessibility: "no-hide-descendants", onPress: () => requestClose("outside"), style: { bottom: 0, left: 0, position: "absolute", right: 0, top: 0 } })) : null, _jsxs(Animated.View, { accessibilityLabel: [accessibleTitle, description].filter(Boolean).join(", "), accessibilityState: { busy }, accessibilityViewIsModal: true, importantForAccessibility: "yes", role: "dialog", style: [
|
|
943
|
+
{
|
|
944
|
+
backgroundColor: contentBackground,
|
|
945
|
+
borderColor: contentBorder,
|
|
946
|
+
borderRadius: tokens.radius[sheetRecipe.content.radius],
|
|
947
|
+
borderBottomLeftRadius: physicalPlacement === "bottom" ? 0 : tokens.radius[sheetRecipe.content.radius],
|
|
948
|
+
borderBottomRightRadius: physicalPlacement === "bottom" ? 0 : tokens.radius[sheetRecipe.content.radius],
|
|
949
|
+
borderWidth: sheetRecipe.content.borderWidth,
|
|
950
|
+
...resolveNativeShadowElevation(surfaceShadow, designProfile !== undefined, 8),
|
|
951
|
+
gap: sheetRecipe.body.gap,
|
|
952
|
+
// A fixed size ratio drives the height; `auto` lets the content decide
|
|
953
|
+
// and the recipe's maxHeightRatio caps it.
|
|
954
|
+
height: side
|
|
955
|
+
? availableHeight
|
|
956
|
+
: sizeRatio === null
|
|
957
|
+
? undefined
|
|
958
|
+
: Math.min(viewportHeight * sizeRatio, availableHeight),
|
|
959
|
+
maxWidth: side ? 420 : undefined,
|
|
960
|
+
// maxHeightRatio caps only `auto`. A fixed size is already bounded by availableHeight
|
|
961
|
+
// (viewport − top inset − keyboard); capping it too stopped `full` at 90% (2026-10-06 follow-up).
|
|
962
|
+
maxHeight: side || sizeRatio !== null
|
|
963
|
+
? availableHeight
|
|
964
|
+
: Math.min(availableHeight, viewportHeight * sheetRecipe.content.maxHeightRatio),
|
|
965
|
+
paddingBottom: sheetRecipe.content.paddingBottom + bottomInset,
|
|
966
|
+
paddingLeft: sheetRecipe.content.paddingHorizontal + insets.left,
|
|
967
|
+
paddingRight: sheetRecipe.content.paddingHorizontal + insets.right,
|
|
968
|
+
// The top safe area limits the viewport, rather than adding a second
|
|
969
|
+
// notch-sized gap inside a sheet anchored to the bottom.
|
|
970
|
+
paddingTop: sheetRecipe.content.paddingTop,
|
|
971
|
+
shadowColor: surfaceShadow.color,
|
|
972
|
+
shadowOffset: {
|
|
973
|
+
width: 0,
|
|
974
|
+
height: surfaceShadow.offsetY,
|
|
975
|
+
},
|
|
976
|
+
shadowOpacity: surfaceShadow.opacity,
|
|
977
|
+
shadowRadius: surfaceShadow.radius,
|
|
978
|
+
transform: environment.reducedMotion
|
|
950
979
|
? undefined
|
|
951
|
-
:
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
maxHeight: side || sizeRatio !== null
|
|
956
|
-
? availableHeight
|
|
957
|
-
: Math.min(availableHeight, viewportHeight * sheetRecipe.content.maxHeightRatio),
|
|
958
|
-
paddingBottom: sheetRecipe.content.paddingBottom + bottomInset,
|
|
959
|
-
paddingLeft: sheetRecipe.content.paddingHorizontal + insets.left,
|
|
960
|
-
paddingRight: sheetRecipe.content.paddingHorizontal + insets.right,
|
|
961
|
-
// The top safe area limits the viewport, rather than adding a second
|
|
962
|
-
// notch-sized gap inside a sheet anchored to the bottom.
|
|
963
|
-
paddingTop: sheetRecipe.content.paddingTop,
|
|
964
|
-
shadowColor: surfaceShadow.color,
|
|
965
|
-
shadowOffset: {
|
|
966
|
-
width: 0,
|
|
967
|
-
height: surfaceShadow.offsetY,
|
|
980
|
+
: side
|
|
981
|
+
? [{ translateX: translate }]
|
|
982
|
+
: [{ translateY: translate }],
|
|
983
|
+
width: side ? "88%" : "100%",
|
|
968
984
|
},
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
:
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
flexShrink: 0,
|
|
983
|
-
direction: environment.direction,
|
|
984
|
-
flexDirection: "row",
|
|
985
|
-
gap: spacing.sm,
|
|
986
|
-
}, children: [_jsxs(View, { style: { flex: 1, gap: spacing.xs }, children: [_jsx(Text, { accessibilityRole: "header", tone: "primary", variant: "title", children: title }), description ? _jsx(Text, { tone: "muted", children: description }) : null] }), policy.dismissible ? (_jsx(IconButton, { disabled: busy && !policy.dismissWhileBusy, label: closeLabel, onPress: () => requestClose("close-action"), children: _jsx(CloseGlyph, {}) })) : null] }), scrollable ? (_jsx(ScrollView, { style: { flexShrink: 1, minHeight: 0, ...bodyFill }, contentContainerStyle: { gap: sheetRecipe.body.gap }, keyboardShouldPersistTaps: "handled", keyboardDismissMode: Platform.OS === "ios" ? "interactive" : "on-drag", automaticallyAdjustKeyboardInsets: false, children: children })) : _jsx(View, { style: { gap: sheetRecipe.body.gap, flexShrink: 1, ...bodyFill }, children: children }), footer ? (_jsx(View, { style: {
|
|
987
|
-
gap: sheetRecipe.footer.gap,
|
|
988
|
-
flexShrink: 0,
|
|
989
|
-
paddingTop: sheetRecipe.footer.paddingTop,
|
|
990
|
-
}, children: footer })) : null] })] }) }));
|
|
985
|
+
contentStyle,
|
|
986
|
+
], children: [_jsxs(View, { style: {
|
|
987
|
+
alignItems: "center",
|
|
988
|
+
minHeight: sheetRecipe.header.minHeight,
|
|
989
|
+
flexShrink: 0,
|
|
990
|
+
direction: environment.direction,
|
|
991
|
+
flexDirection: "row",
|
|
992
|
+
gap: spacing.sm,
|
|
993
|
+
}, children: [_jsxs(View, { style: { flex: 1, gap: spacing.xs }, children: [_jsx(Text, { accessibilityRole: "header", tone: "primary", variant: "title", children: title }), description ? _jsx(Text, { tone: "muted", children: description }) : null] }), policy.dismissible ? (_jsx(IconButton, { disabled: busy && !policy.dismissWhileBusy, label: closeLabel, onPress: () => requestClose("close-action"), children: _jsx(CloseGlyph, {}) })) : null] }), scrollable ? (_jsx(ScrollView, { style: { flexShrink: 1, minHeight: 0, ...bodyFill }, contentContainerStyle: { gap: sheetRecipe.body.gap }, keyboardShouldPersistTaps: "handled", keyboardDismissMode: Platform.OS === "ios" ? "interactive" : "on-drag", automaticallyAdjustKeyboardInsets: false, children: children })) : _jsx(View, { style: { gap: sheetRecipe.body.gap, flexShrink: 1, ...bodyFill }, children: children }), footer ? (_jsx(View, { style: {
|
|
994
|
+
gap: sheetRecipe.footer.gap,
|
|
995
|
+
flexShrink: 0,
|
|
996
|
+
paddingTop: sheetRecipe.footer.paddingTop,
|
|
997
|
+
}, children: footer })) : null] })] }) }) }));
|
|
991
998
|
}
|
|
992
999
|
//# sourceMappingURL=overlays.js.map
|