@octane-xplat/ui 0.7.2 → 0.9.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 +4 -3
- package/dist/native/Button.tsrx.js +1 -1
- package/dist/native/CommandPalette.tsrx.js +7 -1
- package/dist/native/Grid.tsrx.js +31 -2
- package/dist/native/KeyboardAvoiding.mobile.tsrx.js +2 -2
- package/dist/native/Markdown.tsrx.js +233 -0
- package/dist/native/Overlay.tsrx.js +15 -26
- package/dist/native/Pagination.tsrx.js +15 -12
- package/dist/native/PinInput.tsrx.js +25 -7
- package/dist/native/Popover.tsrx.js +33 -23
- package/dist/native/Pressable.tsrx.js +4 -1
- package/dist/native/Screen.tsrx.js +1 -1
- package/dist/native/SearchInput.tsrx.js +6 -3
- package/dist/native/Sheet.tsrx.js +23 -38
- package/dist/native/Slider.tsrx.js +23 -14
- package/dist/native/Text.tsrx.js +16 -0
- package/dist/native/TextArea.tsrx.js +6 -3
- package/dist/native/TextInput.tsrx.js +6 -3
- package/dist/native/VirtualList.tsrx.js +305 -121
- package/dist/native/WebView.tsrx.js +17 -2
- package/dist/native/_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorate.js +9 -0
- package/dist/native/escape-props.js +2 -0
- package/dist/native/grid-auto-placement.js +83 -0
- package/dist/native/grid-placement.js +20 -0
- package/dist/native/index.shared.js +7 -5
- package/dist/native/keyboard-inset.mobile.js +5 -5
- package/dist/native/navigation-request.js +26 -0
- package/dist/native/octane-client-build.json +1 -1
- package/dist/native/overlay-lifetime.mobile.js +65 -0
- package/dist/native/pan.tsrx.js +16 -2
- package/dist/native/route-table.js +90 -10
- package/dist/native/route.js +26 -16
- package/dist/native/shared.js +7 -5
- package/dist/native/sheet-service.js +2 -2
- package/dist/native/svg.mobile.js +1 -1
- package/dist/native/{tap-to-blur.mobile.js → tap-to-blur.ios.js} +20 -32
- package/dist/native/text-focus.js +10 -0
- package/dist/native/text-write.js +18 -11
- package/dist/native/toast-anchor.tsrx.js +1 -1
- package/dist/native/ui.js +7 -6
- package/dist/native/useMeasure.tsrx.js +17 -18
- package/dist/native/vendor/ui-svg/index.android.js +2 -2
- package/dist/native/vendor/ui-svg/index.ios.js +2 -2
- package/dist/native/vendor/ui-svg/{index.common.js → src/index.common.js} +1 -1
- package/dist/native/virtual-list-cell-pool.js +63 -0
- package/dist/web/Button.web.tsrx.js +1 -1
- package/dist/web/KeyboardAvoiding.web.tsrx.js +78 -0
- package/dist/web/Markdown.tsrx.js +98 -0
- package/dist/web/Overlay.web.tsrx.js +81 -32
- package/dist/web/PinInput.web.tsrx.js +24 -10
- package/dist/web/Pressable.web.tsrx.js +169 -53
- package/dist/web/SearchInput.web.tsrx.js +2 -2
- package/dist/web/Sheet.web.tsrx.js +20 -7
- package/dist/web/TextArea.web.tsrx.js +22 -17
- package/dist/web/TextInput.web.tsrx.js +2 -2
- package/dist/web/VirtualList.web.tsrx.js +220 -109
- package/dist/web/WebView.web.tsrx.js +3 -3
- package/dist/web/{index.shared.js → index.shared.web.js} +7 -5
- package/dist/web/modal-focus.web.js +95 -0
- package/dist/web/navigation-request.js +26 -0
- package/dist/web/octane-client-build.json +1 -1
- package/dist/web/pan.web.tsrx.js +27 -10
- package/dist/web/route-table.js +90 -10
- package/dist/web/route.web.js +88 -22
- package/dist/web/sheet-service.web.js +8 -0
- package/dist/web/theme/colorScheme.web.js +31 -4
- package/dist/web/ui.js +8 -6
- package/dist/web/virtual-list-cell-pool.js +63 -0
- package/package.json +21 -19
- package/platforms/android/native-api-usage.json +7 -7
- package/src/CommandPalette.tsrx +8 -1
- package/src/Grid.tsrx +32 -1
- package/src/Icon.macos.tsrx +1 -0
- package/src/KeyboardAvoiding.macos.tsrx +7 -1
- package/src/KeyboardAvoiding.mobile.tsrx +2 -2
- package/src/KeyboardAvoiding.tsrx +15 -0
- package/src/KeyboardAvoiding.web.tsrx +15 -0
- package/src/Markdown.tsrx +121 -0
- package/src/Meter.tsrx +1 -0
- package/src/Overlay.tsrx +15 -30
- package/src/Overlay.web.tsrx +12 -3
- package/src/Pagination.tsrx +6 -4
- package/src/PinInput.macos.tsrx +20 -6
- package/src/PinInput.mobile.test.ts +107 -0
- package/src/PinInput.tsrx +20 -6
- package/src/PinInput.web.test.tsrx +42 -0
- package/src/PinInput.web.tsrx +20 -6
- package/src/Popover.tsrx +36 -22
- package/src/Pressable.tsrx +1 -1
- package/src/Pressable.web.test.tsrx +36 -0
- package/src/Pressable.web.tsrx +37 -6
- package/src/RouteHost.macos.tsrx +1 -0
- package/src/Screen.tsrx +1 -1
- package/src/SearchInput.tsrx +4 -3
- package/src/SearchInput.web.tsrx +1 -1
- package/src/Sheet.tsrx +21 -42
- package/src/Sheet.web.tsrx +9 -1
- package/src/Slider.tsrx +13 -11
- package/src/Text.tsrx +36 -0
- package/src/TextArea.tsrx +6 -5
- package/src/TextArea.web.test.tsrx +39 -0
- package/src/TextArea.web.tsrx +7 -5
- package/src/TextInput.tsrx +6 -6
- package/src/TextInput.web.tsrx +1 -1
- package/src/VirtualList.macos.tsrx +93 -6
- package/src/VirtualList.mobile.test.tsrx +232 -0
- package/src/VirtualList.tsrx +285 -81
- package/src/VirtualList.web.tsrx +131 -25
- package/src/WebView.tsrx +20 -10
- package/src/WebView.web.tsrx +3 -0
- package/src/android/BottomNavigationView.android.tsrx +1 -0
- package/src/android/MaterialDialog.android.tsrx +1 -0
- package/src/anim.macos.tsrx +1 -0
- package/src/apply-native-modifiers.native.ts +4 -1
- package/src/child-array.ts +12 -7
- package/src/colorScheme.macos.ts +1 -0
- package/src/controls.macos.tsrx +4 -1
- package/src/data-driver.mobile.test.ts +120 -0
- package/src/data-lifecycle.mobile.test.ts +251 -0
- package/src/escape-props.ts +13 -1
- package/src/grid-auto-placement.ts +163 -0
- package/src/grid-placement.ts +29 -0
- package/src/hosted-unsupported.macos.tsrx +1 -0
- package/src/index.macos.ts +23 -3
- package/src/index.mobile.ts +0 -1
- package/src/index.shared.ts +22 -1
- package/src/index.shared.web.ts +291 -0
- package/src/index.web.ts +1 -1
- package/src/input-readiness.web.test.tsrx +82 -0
- package/src/ios/UITabBar.ios.tsrx +1 -0
- package/src/keyboard-inset.mobile.test.ts +62 -0
- package/src/keyboard-inset.mobile.ts +63 -43
- package/src/layout-shells.macos.tsrx +1 -5
- package/src/macos-extras.macos.tsrx +2 -0
- package/src/modal-focus.web.test.tsrx +63 -0
- package/src/modal-focus.web.ts +162 -0
- package/src/navigation-request.ts +37 -0
- package/src/overlay-lifecycle.mobile.test.ts +316 -0
- package/src/overlay-lifetime.mobile.ts +107 -0
- package/src/pan.mobile.test.tsrx +116 -0
- package/src/pan.tsrx +20 -2
- package/src/pan.web.tsrx +35 -7
- package/src/platformProps.ts +1 -0
- package/src/popover.mobile.test.ts +9 -1
- package/src/pressable-accessibility.mobile.test.ts +30 -0
- package/src/props.ts +163 -3
- package/src/refresh.ts +6 -1
- package/src/refresh.web.test.ts +77 -77
- package/src/route-android.test.ts +162 -0
- package/src/route-history.web.test.ts +80 -0
- package/src/route-navigation.web.test.ts +173 -0
- package/src/route-table.test.ts +188 -9
- package/src/route-table.ts +138 -10
- package/src/route.macos.ts +56 -13
- package/src/route.ts +54 -24
- package/src/route.web.ts +141 -24
- package/src/sheet-detents.ts +5 -3
- package/src/sheet-service.macos.ts +5 -1
- package/src/sheet-service.ts +1 -1
- package/src/sheet-service.web.ts +8 -0
- package/src/sheet-snap.test.ts +23 -23
- package/src/sheet-snap.ts +6 -1
- package/src/svg.mobile.ts +9 -3
- package/src/tap-to-blur.ios.ts +106 -0
- package/src/tap-to-blur.mobile.ts +21 -95
- package/src/text-focus.ts +12 -0
- package/src/text-input.mobile.test.ts +89 -0
- package/src/text-write.ts +21 -11
- package/src/theme/colorScheme.linux.ts +2 -4
- package/src/theme/colorScheme.web.ts +51 -4
- package/src/theme/theme-scheme.macos.ts +8 -2
- package/src/theme/tokens.css +1740 -1718
- package/src/translate.macos.ts +4 -1
- package/src/useMeasure.tsrx +20 -21
- package/src/virtual-list-cell-pool.test.ts +53 -0
- package/src/virtual-list-cell-pool.ts +81 -0
- package/src/virtual-list-layout.test.ts +11 -8
- package/src/virtual-list-layout.ts +4 -8
- package/src/windows.linux.ts +7 -2
- package/src/windows.macos.ts +1 -0
- package/types/generated/.tsrx-typegen-manifest.json +16 -3
- package/types/generated/Grid.d.ts +0 -1
- package/types/generated/KeyboardAvoiding.d.ts +3 -0
- package/types/generated/KeyboardAvoiding.web.d.ts +2 -0
- package/types/generated/Markdown.d.ts +59 -0
- package/types/generated/TextArea.d.ts +2 -2
- package/types/generated/TextArea.web.d.ts +1 -1
- package/types/generated/TextInput.d.ts +2 -3
- package/types/generated/VirtualList.d.ts +3 -3
- package/types/generated/escape-props.d.ts +4 -0
- package/types/generated/grid-auto-placement.d.ts +13 -0
- package/types/generated/grid-placement.d.ts +5 -0
- package/types/generated/index.mobile.d.ts +0 -1
- package/types/generated/index.shared.d.ts +6 -3
- package/types/generated/index.shared.web.d.ts +114 -0
- package/types/generated/index.web.d.ts +1 -1
- package/types/generated/modal-focus.web.d.ts +3 -0
- package/types/generated/navigation-request.d.ts +10 -0
- package/types/generated/overlay-lifetime.mobile.d.ts +10 -0
- package/types/generated/props.d.ts +111 -3
- package/types/generated/route-table.d.ts +14 -3
- package/types/generated/svg.mobile.d.ts +2 -2
- package/types/generated/tap-to-blur.ios.d.ts +13 -0
- package/types/generated/tap-to-blur.mobile.d.ts +1 -15
- package/types/generated/text-focus.d.ts +3 -0
- package/types/generated/text-write.d.ts +3 -1
- package/types/generated/theme/colorScheme.web.d.ts +5 -0
- package/types/generated/virtual-list-cell-pool.d.ts +18 -0
- package/types/index.macos.d.ts +15 -3
- /package/src/vendor/ui-svg/{index.android.ts → src/index.android.ts} +0 -0
- /package/src/vendor/ui-svg/{index.common.ts → src/index.common.ts} +0 -0
- /package/src/vendor/ui-svg/{index.ios.ts → src/index.ios.ts} +0 -0
- /package/src/vendor/ui-svg/{index.ts → src/index.ts} +0 -0
- /package/src/vendor/ui-svg/{typings → src/typings}/SVGKit.d.ts +0 -0
- /package/src/vendor/ui-svg/{typings → src/typings}/android.d.ts +0 -0
- /package/src/vendor/ui-svg/{typings → src/typings}/ios.d.ts +0 -0
- /package/types/generated/vendor/ui-svg/{index.common.d.ts → src/index.common.d.ts} +0 -0
- /package/types/generated/vendor/ui-svg/{index.d.ts → src/index.d.ts} +0 -0
- /package/types/generated/vendor/ui-svg/{index.ios.d.ts → src/index.ios.d.ts} +0 -0
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
// Generated by scripts/sync-ui-barrels.mjs from index.shared.ts. Do not edit.
|
|
2
|
+
// Foundations and common controls
|
|
3
|
+
export { View } from './View'
|
|
4
|
+
export { View as Column } from './View'
|
|
5
|
+
export { Row } from './Row'
|
|
6
|
+
export { Grid } from './Grid'
|
|
7
|
+
export { Stack } from './Stack'
|
|
8
|
+
export { Absolute } from './Absolute'
|
|
9
|
+
export type { PanEvent, SwipeEvent, SetTranslate } from './props'
|
|
10
|
+
export { setTranslate } from './translate.web'
|
|
11
|
+
export { Spacer } from './Spacer'
|
|
12
|
+
export { Text } from './Text'
|
|
13
|
+
export { Markdown, MarkdownScreen } from './Markdown'
|
|
14
|
+
export type { MdDoc, MdNode, MdInline } from './Markdown'
|
|
15
|
+
export { RichText, RichTextSpan } from './RichText'
|
|
16
|
+
export { Pressable } from './Pressable'
|
|
17
|
+
export { Button } from './Button'
|
|
18
|
+
export { Collapsible } from './Collapsible'
|
|
19
|
+
export { Accordion } from './Accordion'
|
|
20
|
+
export { Checkbox } from './Checkbox'
|
|
21
|
+
export { RadioGroup } from './RadioGroup'
|
|
22
|
+
export { DropdownMenu } from './DropdownMenu'
|
|
23
|
+
export { ContextMenu } from './ContextMenu'
|
|
24
|
+
export { Badge } from './Badge'
|
|
25
|
+
export { Separator } from './Separator'
|
|
26
|
+
export { Skeleton } from './Skeleton'
|
|
27
|
+
export { Avatar } from './Avatar'
|
|
28
|
+
export { AvatarGroup } from './AvatarGroup'
|
|
29
|
+
export type {
|
|
30
|
+
AccordionItemSpec,
|
|
31
|
+
AccordionProps,
|
|
32
|
+
AvatarGroupProps,
|
|
33
|
+
AvatarProps,
|
|
34
|
+
BadgeProps,
|
|
35
|
+
ButtonProps,
|
|
36
|
+
CheckboxProps,
|
|
37
|
+
CollapsibleProps,
|
|
38
|
+
ContextMenuProps,
|
|
39
|
+
DropdownMenuProps,
|
|
40
|
+
MenuItem,
|
|
41
|
+
RadioGroupProps,
|
|
42
|
+
RadioOption,
|
|
43
|
+
SegmentedControlProps,
|
|
44
|
+
SeparatorProps,
|
|
45
|
+
SkeletonProps,
|
|
46
|
+
} from './props'
|
|
47
|
+
|
|
48
|
+
// Forms and data entry
|
|
49
|
+
export { FormField } from './FormField'
|
|
50
|
+
export { FieldGroup } from './FieldGroup'
|
|
51
|
+
export { ListItem } from './ListItem'
|
|
52
|
+
export { InputNumber } from './InputNumber'
|
|
53
|
+
export { PinInput } from './PinInput'
|
|
54
|
+
export { Select } from './Select'
|
|
55
|
+
export { SelectMenu, Combobox, InputMenu } from './aliases'
|
|
56
|
+
export { InputTags } from './InputTags'
|
|
57
|
+
export { InputRating } from './InputRating'
|
|
58
|
+
export { CheckboxGroup } from './CheckboxGroup'
|
|
59
|
+
export type {
|
|
60
|
+
CheckboxGroupProps,
|
|
61
|
+
FieldGroupProps,
|
|
62
|
+
ListItemComponent,
|
|
63
|
+
ListItemProps,
|
|
64
|
+
ListItemSlotProps,
|
|
65
|
+
FormFieldProps,
|
|
66
|
+
InputNumberProps,
|
|
67
|
+
InputRatingProps,
|
|
68
|
+
InputTagsProps,
|
|
69
|
+
PinInputProps,
|
|
70
|
+
SelectOption,
|
|
71
|
+
SelectProps,
|
|
72
|
+
} from './props'
|
|
73
|
+
|
|
74
|
+
// Navigation and command surfaces
|
|
75
|
+
export { Breadcrumb } from './Breadcrumb'
|
|
76
|
+
export { Pagination } from './Pagination'
|
|
77
|
+
export { Stepper } from './Stepper'
|
|
78
|
+
export { NavigationMenu } from './NavigationMenu'
|
|
79
|
+
export { CommandPalette } from './CommandPalette'
|
|
80
|
+
export type {
|
|
81
|
+
BreadcrumbItem,
|
|
82
|
+
BreadcrumbProps,
|
|
83
|
+
CommandPaletteProps,
|
|
84
|
+
NavigationMenuItem,
|
|
85
|
+
NavigationMenuProps,
|
|
86
|
+
PaginationProps,
|
|
87
|
+
StepperProps,
|
|
88
|
+
StepperStep,
|
|
89
|
+
} from './props'
|
|
90
|
+
|
|
91
|
+
// Content and display
|
|
92
|
+
export { Table } from './Table'
|
|
93
|
+
export { Timeline } from './Timeline'
|
|
94
|
+
export { Tree } from './Tree'
|
|
95
|
+
export { Alert } from './Alert'
|
|
96
|
+
export { Card } from './Card'
|
|
97
|
+
export { Chip } from './Chip'
|
|
98
|
+
export { Kbd } from './Kbd'
|
|
99
|
+
export { Empty } from './Empty'
|
|
100
|
+
export { Banner } from './Banner'
|
|
101
|
+
export { User } from './User'
|
|
102
|
+
export { ProgressGroup } from './ProgressGroup'
|
|
103
|
+
export type {
|
|
104
|
+
AlertProps,
|
|
105
|
+
BannerProps,
|
|
106
|
+
CardProps,
|
|
107
|
+
ChipProps,
|
|
108
|
+
EmptyProps,
|
|
109
|
+
KbdProps,
|
|
110
|
+
ProgressGroupProps,
|
|
111
|
+
TableColumn,
|
|
112
|
+
TableProps,
|
|
113
|
+
TimelineItem,
|
|
114
|
+
TimelineProps,
|
|
115
|
+
TreeNode,
|
|
116
|
+
TreeProps,
|
|
117
|
+
UserProps,
|
|
118
|
+
} from './props'
|
|
119
|
+
|
|
120
|
+
// Links, input, scrolling, media, and overlays
|
|
121
|
+
export { Link } from './Link'
|
|
122
|
+
export { NavLink } from './NavLink'
|
|
123
|
+
export { TextInput } from './TextInput'
|
|
124
|
+
export { TextArea } from './TextArea'
|
|
125
|
+
export { SearchInput } from './SearchInput'
|
|
126
|
+
export { SegmentedControl } from './SegmentedControl'
|
|
127
|
+
export { ScrollBox } from './ScrollBox'
|
|
128
|
+
export { ScrollView } from './ScrollView'
|
|
129
|
+
export { VirtualList } from './VirtualList'
|
|
130
|
+
export type { VirtualListProps } from './props'
|
|
131
|
+
export { Image } from './Image'
|
|
132
|
+
export { WebView } from './WebView'
|
|
133
|
+
export type { WebViewContentSize, WebViewHandle, WebViewLoadEvent, WebViewProps } from './props'
|
|
134
|
+
export { Overlay } from './Overlay'
|
|
135
|
+
export { Popover } from './Popover'
|
|
136
|
+
export { Hoverable } from './Hoverable'
|
|
137
|
+
export { Tooltip } from './Tooltip'
|
|
138
|
+
export { showToast } from './toast-anchor'
|
|
139
|
+
export type {
|
|
140
|
+
HoverableProps,
|
|
141
|
+
OverlayProps,
|
|
142
|
+
PopoverAnchorRef,
|
|
143
|
+
PopoverProps,
|
|
144
|
+
PopoverPlacement,
|
|
145
|
+
ToastContent,
|
|
146
|
+
ToastOptions,
|
|
147
|
+
ToastPosition,
|
|
148
|
+
TooltipProps,
|
|
149
|
+
} from './props'
|
|
150
|
+
|
|
151
|
+
// Animation, theme, styling, and host services
|
|
152
|
+
export { useAnimation } from './anim'
|
|
153
|
+
export type { AnimatedValue } from './anim'
|
|
154
|
+
export {
|
|
155
|
+
useThemeScheme,
|
|
156
|
+
getThemeScheme,
|
|
157
|
+
setThemePreference,
|
|
158
|
+
getThemePreference,
|
|
159
|
+
themeSchemeClasses,
|
|
160
|
+
onThemeSchemeChange,
|
|
161
|
+
applyThemeClasses,
|
|
162
|
+
} from './theme/theme-scheme'
|
|
163
|
+
|
|
164
|
+
export { useColorScheme, getColorScheme } from './theme/colorScheme.web'
|
|
165
|
+
export type { ColorScheme } from './theme/colorScheme.web'
|
|
166
|
+
export { styled } from './styled'
|
|
167
|
+
export { openWindow } from './windows.web'
|
|
168
|
+
|
|
169
|
+
// Screens, visual controls, and icons
|
|
170
|
+
export { Screen } from './Screen'
|
|
171
|
+
export { Tabs } from './Tabs'
|
|
172
|
+
export type { TabSpec } from './Tabs'
|
|
173
|
+
export { Switch } from './Switch'
|
|
174
|
+
export { SafeArea } from './SafeArea'
|
|
175
|
+
export { KeyboardAvoiding } from './KeyboardAvoiding'
|
|
176
|
+
export { Drawer } from './Drawer'
|
|
177
|
+
export { useSafeAreaInsets } from './safeAreaInsets'
|
|
178
|
+
export type { SafeAreaInsets } from './safeAreaInsets'
|
|
179
|
+
export { useMeasure } from './useMeasure'
|
|
180
|
+
export type { MeasureBounds, MeasureResult, UseMeasureOptions } from './props'
|
|
181
|
+
export { ActivityIndicator } from './ActivityIndicator'
|
|
182
|
+
export { Meter } from './Meter'
|
|
183
|
+
export { Slider } from './Slider'
|
|
184
|
+
export { Icon } from './Icon'
|
|
185
|
+
export { Heading } from './Heading'
|
|
186
|
+
export { registerIcon, registerIcons } from './icons'
|
|
187
|
+
export type { IconGlyph } from './icons'
|
|
188
|
+
export type {
|
|
189
|
+
ActivityIndicatorProps,
|
|
190
|
+
HeadingProps,
|
|
191
|
+
IconProps,
|
|
192
|
+
MeterProps,
|
|
193
|
+
RefreshProps,
|
|
194
|
+
SearchInputProps,
|
|
195
|
+
SliderProps,
|
|
196
|
+
} from './props'
|
|
197
|
+
|
|
198
|
+
// Platform state and routing
|
|
199
|
+
export { isNative } from './platform.web'
|
|
200
|
+
export { registerStack, getStack, stackEntries } from './stacks.web'
|
|
201
|
+
export {
|
|
202
|
+
pushRoute,
|
|
203
|
+
popRoute,
|
|
204
|
+
routeStacks,
|
|
205
|
+
pushDeepLink,
|
|
206
|
+
routeFor,
|
|
207
|
+
currentRoute,
|
|
208
|
+
currentModalRoute,
|
|
209
|
+
canGoBack,
|
|
210
|
+
useCanGoBack,
|
|
211
|
+
useRoute,
|
|
212
|
+
useModalRoute,
|
|
213
|
+
redirect,
|
|
214
|
+
addBackInterceptor,
|
|
215
|
+
registerScreens,
|
|
216
|
+
registerRoutes,
|
|
217
|
+
addRoutes,
|
|
218
|
+
screenFor,
|
|
219
|
+
hrefFor,
|
|
220
|
+
layoutsForRoute,
|
|
221
|
+
} from './route.web'
|
|
222
|
+
|
|
223
|
+
export { useBackInterceptor } from './use-back'
|
|
224
|
+
|
|
225
|
+
export {
|
|
226
|
+
deriveRouteManifest,
|
|
227
|
+
defineRoutes,
|
|
228
|
+
mergeRouteManifests,
|
|
229
|
+
manifestToJson,
|
|
230
|
+
} from './route-table'
|
|
231
|
+
|
|
232
|
+
export type {
|
|
233
|
+
BeforeLoad,
|
|
234
|
+
BeforeLoadArgs,
|
|
235
|
+
LinkProps,
|
|
236
|
+
NavLinkProps,
|
|
237
|
+
Route,
|
|
238
|
+
RouteContext,
|
|
239
|
+
RouteHead,
|
|
240
|
+
RouteHeadExport,
|
|
241
|
+
RouteMeta,
|
|
242
|
+
RouteManifest,
|
|
243
|
+
RouteManifestJson,
|
|
244
|
+
RouteJson,
|
|
245
|
+
RouteDataMode,
|
|
246
|
+
RouteNameOfPath,
|
|
247
|
+
RouteParamsFromSpecs,
|
|
248
|
+
RoutePathParams,
|
|
249
|
+
RoutePresentationsFromSpecs,
|
|
250
|
+
RouteSpec,
|
|
251
|
+
RouteSpecSet,
|
|
252
|
+
ManifestRouteNames,
|
|
253
|
+
ManifestRouteParams,
|
|
254
|
+
ManifestRoutePresentations,
|
|
255
|
+
SpecRouteInfo,
|
|
256
|
+
ScreenTable,
|
|
257
|
+
ModalOpenResult,
|
|
258
|
+
OpenWindowOptions,
|
|
259
|
+
} from './props'
|
|
260
|
+
|
|
261
|
+
// Stores, sheets, and shared prop types
|
|
262
|
+
export { createStore } from './store'
|
|
263
|
+
export type { Store, ReadableStore } from './store'
|
|
264
|
+
export { useStore } from './use-store'
|
|
265
|
+
export { Sheet } from './Sheet'
|
|
266
|
+
export { openSheet, closeSheet } from './sheet-service.web'
|
|
267
|
+
export type { SheetProps, SheetOpenOptions, OpenSheet } from './props'
|
|
268
|
+
export type {
|
|
269
|
+
AbsoluteProps,
|
|
270
|
+
DrawerProps,
|
|
271
|
+
GridProps,
|
|
272
|
+
ImageProps,
|
|
273
|
+
KeyboardAvoidingProps,
|
|
274
|
+
LayoutChildProps,
|
|
275
|
+
PressableProps,
|
|
276
|
+
RichTextProps,
|
|
277
|
+
RichTextSpanProps,
|
|
278
|
+
RowProps,
|
|
279
|
+
ScreenProps,
|
|
280
|
+
SafeAreaProps,
|
|
281
|
+
ScrollBoxProps,
|
|
282
|
+
ScrollViewProps,
|
|
283
|
+
SpacerProps,
|
|
284
|
+
StackProps,
|
|
285
|
+
SwitchProps,
|
|
286
|
+
TabsProps,
|
|
287
|
+
TextAreaProps,
|
|
288
|
+
TextInputProps,
|
|
289
|
+
TextProps,
|
|
290
|
+
ViewProps,
|
|
291
|
+
} from './props'
|
package/src/index.web.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from './index.shared'
|
|
1
|
+
export * from './index.shared.web'
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import { act, createRoot } from 'octane';
|
|
4
|
+
import { Pressable } from './Pressable.web.tsrx';
|
|
5
|
+
import { TextInput } from './TextInput.web.tsrx';
|
|
6
|
+
import { TextArea } from './TextArea.web.tsrx';
|
|
7
|
+
import { SearchInput } from './SearchInput.web.tsrx';
|
|
8
|
+
|
|
9
|
+
describe('keyboard access', () => {
|
|
10
|
+
it('cancels a held long press when disabled before its timer fires', () => {
|
|
11
|
+
vi.useFakeTimers();
|
|
12
|
+
try {
|
|
13
|
+
const host = document.createElement('div');
|
|
14
|
+
const root = createRoot(host);
|
|
15
|
+
const hold = vi.fn();
|
|
16
|
+
act(() => root.render(<Pressable onLongPress={hold}>Hold</Pressable>));
|
|
17
|
+
act(() => host.firstElementChild!.dispatchEvent(new Event('pointerdown', { bubbles: true })));
|
|
18
|
+
act(() => root.render(<Pressable onLongPress={hold} disabled>Hold</Pressable>));
|
|
19
|
+
act(() => vi.advanceTimersByTime(600));
|
|
20
|
+
expect(hold).not.toHaveBeenCalled();
|
|
21
|
+
root.unmount();
|
|
22
|
+
} finally {
|
|
23
|
+
vi.useRealTimers();
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('makes actionable Pressables keyboard reachable and activates once per key', () => {
|
|
28
|
+
const host = document.createElement('div');
|
|
29
|
+
document.body.appendChild(host);
|
|
30
|
+
const root = createRoot(host);
|
|
31
|
+
const press = vi.fn();
|
|
32
|
+
act(() => root.render(<Pressable onPress={press}>Save</Pressable>));
|
|
33
|
+
const button = host.firstElementChild as HTMLElement;
|
|
34
|
+
expect(button.tabIndex).toBe(0);
|
|
35
|
+
act(() => {
|
|
36
|
+
button.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
|
|
37
|
+
button.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', repeat: true, bubbles: true }));
|
|
38
|
+
button.dispatchEvent(new KeyboardEvent('keyup', { key: 'Enter', bubbles: true }));
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
expect(press).toHaveBeenCalledTimes(1);
|
|
42
|
+
act(() => {
|
|
43
|
+
button.dispatchEvent(new KeyboardEvent('keydown', { key: ' ', bubbles: true }));
|
|
44
|
+
button.dispatchEvent(new KeyboardEvent('keyup', { key: ' ', bubbles: true }));
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
expect(press).toHaveBeenCalledTimes(2);
|
|
48
|
+
act(() => root.render(<Pressable onPress={press} disabled>Save</Pressable>));
|
|
49
|
+
expect(button.tabIndex).toBe(-1);
|
|
50
|
+
act(() => button.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true })));
|
|
51
|
+
expect(press).toHaveBeenCalledTimes(2);
|
|
52
|
+
root.unmount();
|
|
53
|
+
host.remove();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
for (const Component of [TextInput, TextArea, SearchInput]) {
|
|
57
|
+
it(`does not submit ${Component.name} while Enter confirms composition`, () => {
|
|
58
|
+
const host = document.createElement('div');
|
|
59
|
+
const root = createRoot(host);
|
|
60
|
+
const submit = vi.fn();
|
|
61
|
+
act(() => root.render(<Component onSubmit={submit} />));
|
|
62
|
+
const input = host.querySelector('input,textarea')!;
|
|
63
|
+
act(() => input.dispatchEvent(new KeyboardEvent('keydown', {
|
|
64
|
+
key: 'Enter', ctrlKey: true, isComposing: true, bubbles: true,
|
|
65
|
+
})));
|
|
66
|
+
|
|
67
|
+
expect(submit).not.toHaveBeenCalled();
|
|
68
|
+
// Some engines report composition-confirming Enter as keyCode 229.
|
|
69
|
+
act(() => input.dispatchEvent(new KeyboardEvent('keydown', {
|
|
70
|
+
key: 'Enter', ctrlKey: true, keyCode: 229, bubbles: true,
|
|
71
|
+
})));
|
|
72
|
+
|
|
73
|
+
expect(submit).not.toHaveBeenCalled();
|
|
74
|
+
act(() => input.dispatchEvent(new KeyboardEvent('keydown', {
|
|
75
|
+
key: 'Enter', ctrlKey: true, bubbles: true,
|
|
76
|
+
})));
|
|
77
|
+
|
|
78
|
+
expect(submit).toHaveBeenCalledTimes(1);
|
|
79
|
+
root.unmount();
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest'
|
|
2
|
+
|
|
3
|
+
vi.mock('@nativescript/core', () => ({
|
|
4
|
+
Application: {
|
|
5
|
+
android: {
|
|
6
|
+
foregroundActivity: {
|
|
7
|
+
getWindow: () => ({
|
|
8
|
+
getAttributes: () => ({ softInputMode: 0 }),
|
|
9
|
+
getDecorView: () => ({}),
|
|
10
|
+
}),
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
Utils: { layout: { toDeviceIndependentPixels: (px: number) => px / 2 } },
|
|
15
|
+
}))
|
|
16
|
+
|
|
17
|
+
import { bindBottomInsetToKeyboard } from './keyboard-inset.mobile'
|
|
18
|
+
|
|
19
|
+
describe('Android overlay keyboard inset', () => {
|
|
20
|
+
it('converts physical IME pixels to NativeScript transform dips', () => {
|
|
21
|
+
let listener: any
|
|
22
|
+
vi.stubGlobal('android', {
|
|
23
|
+
view: {
|
|
24
|
+
WindowManager: {
|
|
25
|
+
LayoutParams: { SOFT_INPUT_MASK_ADJUST: 240, SOFT_INPUT_ADJUST_RESIZE: 16 },
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
vi.stubGlobal('androidx', {
|
|
31
|
+
core: {
|
|
32
|
+
view: {
|
|
33
|
+
ViewCompat: {
|
|
34
|
+
OnApplyWindowInsetsListener: class {
|
|
35
|
+
onApplyWindowInsets: any
|
|
36
|
+
constructor(value: any) {
|
|
37
|
+
this.onApplyWindowInsets = value.onApplyWindowInsets
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
setOnApplyWindowInsetsListener: (_view: any, value: any) => {
|
|
41
|
+
listener = value
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
WindowInsetsCompat: { Type: { ime: () => 'ime', systemBars: () => 'bars' } },
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const host = { translateY: 0 }
|
|
51
|
+
const unbind = bindBottomInsetToKeyboard(host)
|
|
52
|
+
const insets = { getInsets: (type: string) => ({ bottom: type === 'ime' ? 600 : 100 }) }
|
|
53
|
+
expect(listener.onApplyWindowInsets({}, insets)).toBe(insets)
|
|
54
|
+
expect(host.translateY).toBe(-250)
|
|
55
|
+
unbind()
|
|
56
|
+
expect(host.translateY).toBe(0)
|
|
57
|
+
expect(listener).toBe(null)
|
|
58
|
+
} finally {
|
|
59
|
+
vi.unstubAllGlobals()
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
})
|
|
@@ -1,23 +1,25 @@
|
|
|
1
|
-
import { Application } from '@nativescript/core'
|
|
1
|
+
import { Application, Utils } from '@nativescript/core'
|
|
2
2
|
|
|
3
3
|
// One shared observer tracks the keyboard's current bottom inset — a sheet
|
|
4
4
|
// opened while the keyboard is ALREADY up must lift immediately (a
|
|
5
5
|
// WillChangeFrame observer only learns about changes after binding), and a
|
|
6
6
|
// focused field keeps the inset live across sheet swaps.
|
|
7
|
-
const bound = new Set<any>()
|
|
8
|
-
let inset = 0
|
|
9
|
-
let wired = false
|
|
7
|
+
const bound = new Set<any>()
|
|
8
|
+
let inset = 0
|
|
9
|
+
let wired = false
|
|
10
10
|
|
|
11
11
|
const apply = () => {
|
|
12
12
|
bound.forEach((host) => {
|
|
13
|
-
host.translateY = -inset
|
|
14
|
-
})
|
|
15
|
-
}
|
|
16
|
-
|
|
13
|
+
host.translateY = -inset
|
|
14
|
+
})
|
|
15
|
+
}
|
|
17
16
|
|
|
18
17
|
const wireIos = () => {
|
|
19
|
-
if (wired) {
|
|
20
|
-
|
|
18
|
+
if (wired) {
|
|
19
|
+
return
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
wired = true
|
|
21
23
|
NSNotificationCenter.defaultCenter.addObserverForNameObjectQueueUsingBlock(
|
|
22
24
|
UIKeyboardWillChangeFrameNotification,
|
|
23
25
|
null,
|
|
@@ -25,14 +27,19 @@ const wireIos = () => {
|
|
|
25
27
|
(note: any) => {
|
|
26
28
|
// UIKeyboardFrameEndUserInfoKey arrives boxed as NSValue whose
|
|
27
29
|
// `CGRectValue` marshals to a plain CGRect object (not a call).
|
|
28
|
-
const raw = note.userInfo.objectForKey(UIKeyboardFrameEndUserInfoKey)
|
|
29
|
-
const boxed = raw?.CGRectValue
|
|
30
|
-
const frame = typeof boxed === 'function' ? raw.CGRectValue() : (boxed ?? raw)
|
|
31
|
-
inset = Math.max(
|
|
32
|
-
|
|
30
|
+
const raw = note.userInfo.objectForKey(UIKeyboardFrameEndUserInfoKey)
|
|
31
|
+
const boxed = raw?.CGRectValue
|
|
32
|
+
const frame = typeof boxed === 'function' ? raw.CGRectValue() : (boxed ?? raw)
|
|
33
|
+
inset = Math.max(
|
|
34
|
+
0,
|
|
35
|
+
UIScreen.mainScreen.bounds.size.height -
|
|
36
|
+
(frame?.origin?.y ?? UIScreen.mainScreen.bounds.size.height),
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
apply()
|
|
33
40
|
},
|
|
34
|
-
)
|
|
35
|
-
}
|
|
41
|
+
)
|
|
42
|
+
}
|
|
36
43
|
|
|
37
44
|
/** Lift a bottom-anchored overlay host above the software keyboard.
|
|
38
45
|
* iOS: a shared UIKeyboardWillChangeFrame observer tracks the inset and
|
|
@@ -45,45 +52,58 @@ const wireIos = () => {
|
|
|
45
52
|
* restores the transform — call it when the host detaches. */
|
|
46
53
|
export function bindBottomInsetToKeyboard(host: any): () => void {
|
|
47
54
|
if (Application.ios) {
|
|
48
|
-
wireIos()
|
|
49
|
-
bound.add(host)
|
|
50
|
-
host.translateY = -inset
|
|
55
|
+
wireIos()
|
|
56
|
+
bound.add(host)
|
|
57
|
+
host.translateY = -inset
|
|
51
58
|
return () => {
|
|
52
|
-
bound.delete(host)
|
|
53
|
-
host.translateY = 0
|
|
54
|
-
}
|
|
59
|
+
bound.delete(host)
|
|
60
|
+
host.translateY = 0
|
|
61
|
+
}
|
|
55
62
|
}
|
|
56
63
|
|
|
57
64
|
if (Application.android) {
|
|
58
|
-
const nativeWindow = Application.android.foregroundActivity?.
|
|
59
|
-
if (!nativeWindow) {
|
|
60
|
-
|
|
61
|
-
|
|
65
|
+
const nativeWindow = Application.android.foregroundActivity?.getWindow()
|
|
66
|
+
if (!nativeWindow) {
|
|
67
|
+
return () => {}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const params = (globalThis as any).android?.view?.WindowManager?.LayoutParams
|
|
71
|
+
if (!params) {
|
|
72
|
+
return () => {}
|
|
73
|
+
}
|
|
74
|
+
|
|
62
75
|
// adjustResize resizes the RootLayout for us — an extra offset would
|
|
63
76
|
// double-lift the host.
|
|
64
|
-
if (
|
|
65
|
-
|
|
77
|
+
if (
|
|
78
|
+
(nativeWindow.getAttributes().softInputMode & params.SOFT_INPUT_MASK_ADJUST) ===
|
|
79
|
+
params.SOFT_INPUT_ADJUST_RESIZE
|
|
80
|
+
) {
|
|
81
|
+
return () => {}
|
|
66
82
|
}
|
|
67
83
|
|
|
68
|
-
const ViewCompat = (globalThis as any).androidx?.core?.view?.ViewCompat
|
|
69
|
-
const WindowInsetsCompat = (globalThis as any).androidx?.core?.view?.WindowInsetsCompat
|
|
70
|
-
if (!ViewCompat || !WindowInsetsCompat) {
|
|
71
|
-
|
|
84
|
+
const ViewCompat = (globalThis as any).androidx?.core?.view?.ViewCompat
|
|
85
|
+
const WindowInsetsCompat = (globalThis as any).androidx?.core?.view?.WindowInsetsCompat
|
|
86
|
+
if (!ViewCompat || !WindowInsetsCompat) {
|
|
87
|
+
return () => {}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const decorView = nativeWindow.getDecorView()
|
|
72
91
|
const listener = new ViewCompat.OnApplyWindowInsetsListener({
|
|
73
92
|
onApplyWindowInsets: (v: any, insets: any) => {
|
|
74
|
-
const ime = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
|
|
75
|
-
const nav = insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom
|
|
76
|
-
|
|
77
|
-
|
|
93
|
+
const ime = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
|
|
94
|
+
const nav = insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom
|
|
95
|
+
// Insets are physical pixels; NativeScript transforms are dips.
|
|
96
|
+
host.translateY = -Utils.layout.toDeviceIndependentPixels(Math.max(0, ime - nav))
|
|
97
|
+
return insets
|
|
78
98
|
},
|
|
79
|
-
})
|
|
99
|
+
})
|
|
80
100
|
|
|
81
|
-
ViewCompat.setOnApplyWindowInsetsListener(decorView, listener)
|
|
101
|
+
ViewCompat.setOnApplyWindowInsetsListener(decorView, listener)
|
|
82
102
|
return () => {
|
|
83
|
-
host.translateY = 0
|
|
84
|
-
ViewCompat.setOnApplyWindowInsetsListener(decorView, null)
|
|
85
|
-
}
|
|
103
|
+
host.translateY = 0
|
|
104
|
+
ViewCompat.setOnApplyWindowInsetsListener(decorView, null)
|
|
105
|
+
}
|
|
86
106
|
}
|
|
87
107
|
|
|
88
|
-
return () => {}
|
|
108
|
+
return () => {}
|
|
89
109
|
}
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
/** @jsxImportSource @xplat/macos/renderer */
|
|
2
|
-
import type {
|
|
2
|
+
import type { SafeAreaProps } from './props'
|
|
3
3
|
|
|
4
4
|
export function SafeArea(props: SafeAreaProps) @{
|
|
5
5
|
<flexboxlayout flexDirection="column" className={props.className} style={props.style}>{props.children}</flexboxlayout>
|
|
6
6
|
}
|
|
7
|
-
|
|
8
|
-
export function KeyboardAvoiding(props: KeyboardAvoidingProps) @{
|
|
9
|
-
<flexboxlayout flexDirection="column" className={props.className} style={props.style}>{props.children}</flexboxlayout>
|
|
10
|
-
}
|
|
@@ -5,6 +5,7 @@ import { cx } from './cx'
|
|
|
5
5
|
export function Meter(props: MeterProps) @{
|
|
6
6
|
const size = props.size ?? 24
|
|
7
7
|
const strokeWidth = Math.max(0, Math.min(props.strokeWidth ?? 3, size))
|
|
8
|
+
|
|
8
9
|
// Track ring via layer chrome; the progress arc itself needs a stroked
|
|
9
10
|
// CAShapeLayer — not bridged yet, so the ring renders unfilled.
|
|
10
11
|
<flexboxlayout
|
|
@@ -28,6 +29,7 @@ export function Meter(props: MeterProps) @{
|
|
|
28
29
|
|
|
29
30
|
export function Heading(props: HeadingProps) @{
|
|
30
31
|
const level = props.level ?? 2
|
|
32
|
+
|
|
31
33
|
<label
|
|
32
34
|
id={props.id}
|
|
33
35
|
className={cx('vx-heading', `vx-h${level}`, props.className)}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import { act, createRoot } from 'octane';
|
|
4
|
+
vi.mock('./theme/theme-scheme', () => ({ useThemeScheme: () => 'light' }));
|
|
5
|
+
import { Sheet } from './Sheet.web.tsrx';
|
|
6
|
+
import { Overlay } from './Overlay.web.tsrx';
|
|
7
|
+
import { isolateModalFocus } from './modal-focus.web';
|
|
8
|
+
|
|
9
|
+
describe('modal focus isolation', () => {
|
|
10
|
+
for (const [name, Component] of [['Sheet', Sheet], ['Overlay', Overlay]] as const) {
|
|
11
|
+
it(`${name} isolates background focus and restores its trigger on close`, () => {
|
|
12
|
+
const host = document.createElement('div');
|
|
13
|
+
document.body.appendChild(host);
|
|
14
|
+
const root = createRoot(host);
|
|
15
|
+
act(() => root.render(<><button id="trigger">Open</button><Component open={false} shadeCover><button id="inside">Close</button></Component></>));
|
|
16
|
+
const trigger = host.querySelector('#trigger') as HTMLElement;
|
|
17
|
+
trigger.focus();
|
|
18
|
+
act(() => root.render(<><button id="trigger">Open</button><Component open shadeCover><button id="inside">Close</button></Component></>));
|
|
19
|
+
expect(host.hasAttribute('inert')).toBe(true);
|
|
20
|
+
expect(document.activeElement?.id).toBe('inside');
|
|
21
|
+
act(() => root.render(<><button id="trigger">Open</button><Component open={false} shadeCover><button id="inside">Close</button></Component></>));
|
|
22
|
+
expect(host.hasAttribute('inert')).toBe(false);
|
|
23
|
+
expect(document.activeElement).toBe(trigger);
|
|
24
|
+
act(() => root.render(<><button id="trigger">Open</button><Component open shadeCover><button id="inside">Close</button></Component></>));
|
|
25
|
+
expect(host.hasAttribute('inert')).toBe(true);
|
|
26
|
+
expect(document.activeElement?.id).toBe('inside');
|
|
27
|
+
root.unmount();
|
|
28
|
+
host.remove();
|
|
29
|
+
}, 30000);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
it('preserves nested isolation when the lower modal closes first', async () => {
|
|
33
|
+
const host = document.createElement('div');
|
|
34
|
+
host.innerHTML = '<button id="return">Return</button>';
|
|
35
|
+
const existing = document.createElement('div');
|
|
36
|
+
existing.setAttribute('inert', '');
|
|
37
|
+
document.body.append(host, existing);
|
|
38
|
+
const trigger = host.firstElementChild as HTMLElement;
|
|
39
|
+
trigger.focus();
|
|
40
|
+
const outer = document.createElement('div');
|
|
41
|
+
outer.innerHTML = '<button>Outer</button>';
|
|
42
|
+
document.body.append(outer);
|
|
43
|
+
const closeOuter = isolateModalFocus(outer, outer, () => {});
|
|
44
|
+
const inner = document.createElement('div');
|
|
45
|
+
inner.innerHTML = '<button>Inner</button>';
|
|
46
|
+
document.body.append(inner);
|
|
47
|
+
await Promise.resolve(); // outer modal's observer sees the new portal
|
|
48
|
+
expect(inner.hasAttribute('inert')).toBe(true);
|
|
49
|
+
const closeInner = isolateModalFocus(inner, inner, () => {});
|
|
50
|
+
expect(outer.hasAttribute('inert')).toBe(true);
|
|
51
|
+
closeOuter();
|
|
52
|
+
outer.remove();
|
|
53
|
+
expect(host.hasAttribute('inert')).toBe(true);
|
|
54
|
+
expect(document.activeElement).toBe(inner.firstElementChild);
|
|
55
|
+
closeInner();
|
|
56
|
+
inner.remove();
|
|
57
|
+
expect(document.activeElement).toBe(trigger);
|
|
58
|
+
expect(host.hasAttribute('inert')).toBe(false);
|
|
59
|
+
expect(existing.hasAttribute('inert')).toBe(true);
|
|
60
|
+
host.remove();
|
|
61
|
+
existing.remove();
|
|
62
|
+
}, 30000);
|
|
63
|
+
});
|