@multiplatform.one/components 7.80.0 → 7.81.1
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/cjs/Accordion/index.native.js +1 -1
- package/dist/cjs/Accordion/index.native.js.map +1 -1
- package/dist/cjs/Alert/index.native.js.map +1 -1
- package/dist/cjs/AnimateHeight/index.native.js.map +1 -1
- package/dist/cjs/Avatar/getInitials.native.js.map +1 -1
- package/dist/cjs/Avatar/index.native.js.map +1 -1
- package/dist/cjs/Badge/index.native.js.map +1 -1
- package/dist/cjs/Button.native.js.map +1 -1
- package/dist/cjs/Card.native.js.map +1 -1
- package/dist/cjs/CardFooter.native.js.map +1 -1
- package/dist/cjs/CardHeader.native.js.map +1 -1
- package/dist/cjs/Carousel/index.native.js +3 -3
- package/dist/cjs/Carousel/index.native.js.map +1 -1
- package/dist/cjs/CheckGlyph/MenuCheckColumn.cjs +56 -0
- package/dist/cjs/CheckGlyph/MenuCheckColumn.native.js +60 -0
- package/dist/cjs/CheckGlyph/MenuCheckColumn.native.js.map +1 -0
- package/dist/cjs/CheckGlyph/index.cjs +40 -0
- package/dist/cjs/CheckGlyph/index.native.js +44 -0
- package/dist/cjs/CheckGlyph/index.native.js.map +1 -0
- package/dist/cjs/Chip/index.native.js.map +1 -1
- package/dist/cjs/Collapsible.native.js.map +1 -1
- package/dist/cjs/ContextMenu/index.cjs +5 -22
- package/dist/cjs/ContextMenu/index.native.js +7 -25
- package/dist/cjs/ContextMenu/index.native.js.map +1 -1
- package/dist/cjs/CopyField/CopyMenuButton.native.js +1 -1
- package/dist/cjs/CopyField/CopyMenuButton.native.js.map +1 -1
- package/dist/cjs/CopyField/index.native.js.map +1 -1
- package/dist/cjs/Dialog.native.js.map +1 -1
- package/dist/cjs/Diff/diff.native.js.map +1 -1
- package/dist/cjs/Diff/index.native.js.map +1 -1
- package/dist/cjs/DotIndicator/index.native.js.map +1 -1
- package/dist/cjs/DropdownMenu/index.cjs +5 -17
- package/dist/cjs/DropdownMenu/index.native.js +7 -19
- package/dist/cjs/DropdownMenu/index.native.js.map +1 -1
- package/dist/cjs/DropdownMenu/menuSettle.native.js.map +1 -1
- package/dist/cjs/ElapsedProgress/index.native.js.map +1 -1
- package/dist/cjs/ErrorBoundary/index.native.js.map +1 -1
- package/dist/cjs/Heading.native.js.map +1 -1
- package/dist/cjs/Kbd/index.native.js.map +1 -1
- package/dist/cjs/Kbd/keys.native.js.map +1 -1
- package/dist/cjs/Lightbox/MediaControl.native.js.map +1 -1
- package/dist/cjs/Lightbox/index.gnome.native.js.map +1 -1
- package/dist/cjs/Lightbox/index.native.js +1 -1
- package/dist/cjs/Lightbox/shared.native.js.map +1 -1
- package/dist/cjs/Lightbox/useLightbox.native.js.map +1 -1
- package/dist/cjs/MachineLiteral/index.native.js.map +1 -1
- package/dist/cjs/Material/index.native.js.map +1 -1
- package/dist/cjs/Meter/index.native.js +1 -1
- package/dist/cjs/Meter/index.native.js.map +1 -1
- package/dist/cjs/Meter/meter.native.js.map +1 -1
- package/dist/cjs/OverflowRow/index.native.js +1 -1
- package/dist/cjs/OverflowRow/index.native.js.map +1 -1
- package/dist/cjs/Pagination.native.js +1 -1
- package/dist/cjs/Pagination.native.js.map +1 -1
- package/dist/cjs/Popover.cjs +2 -2
- package/dist/cjs/Popover.native.js +3 -3
- package/dist/cjs/Popover.native.js.map +1 -1
- package/dist/cjs/ProgressSteps/index.native.js.map +1 -1
- package/dist/cjs/Quote/index.native.js.map +1 -1
- package/dist/cjs/SchemeToggle/index.cjs +2 -2
- package/dist/cjs/SchemeToggle/index.native.js +3 -3
- package/dist/cjs/SchemeToggle/index.native.js.map +1 -1
- package/dist/cjs/ScrollView/revealFocusedField.native.js.map +1 -1
- package/dist/cjs/Separator/index.native.js.map +1 -1
- package/dist/cjs/Sheet.native.js.map +1 -1
- package/dist/cjs/SheetModal/SheetHeader.native.js.map +1 -1
- package/dist/cjs/SheetModal/SheetNavigation.native.js.map +1 -1
- package/dist/cjs/SheetModal/detents.native.js.map +1 -1
- package/dist/cjs/SheetModal/index.cjs +5 -10
- package/dist/cjs/SheetModal/index.native.js +8 -12
- package/dist/cjs/SheetModal/index.native.js.map +1 -1
- package/dist/cjs/SheetModal/useSheetFrameFocus.native.js.map +1 -1
- package/dist/cjs/Skeleton/index.native.js.map +1 -1
- package/dist/cjs/SkipLink/index.native.js.map +1 -1
- package/dist/cjs/SortableList/SortableHandle.native.js.map +1 -1
- package/dist/cjs/SortableList/index.native.js.map +1 -1
- package/dist/cjs/SortableList/useSortableRows.native.js.map +1 -1
- package/dist/cjs/SortableList/useUserOrder.native.js.map +1 -1
- package/dist/cjs/Tabs/index.native.js +1 -1
- package/dist/cjs/Tabs/index.native.js.map +1 -1
- package/dist/cjs/Text.native.js.map +1 -1
- package/dist/cjs/ThemePresetPicker/index.native.js +2 -2
- package/dist/cjs/ThemePresetPicker/index.native.js.map +1 -1
- package/dist/cjs/Toast/index.native.js.map +1 -1
- package/dist/cjs/Toast/store.native.js.map +1 -1
- package/dist/cjs/Tooltip/nativePress.native.js.map +1 -1
- package/dist/cjs/Tooltip/tooltipShared.native.js.map +1 -1
- package/dist/cjs/TreeSelect/index.cjs +2 -6
- package/dist/cjs/TreeSelect/index.native.js +3 -7
- package/dist/cjs/TreeSelect/index.native.js.map +1 -1
- package/dist/cjs/TreeSelect/treeSelectModel.native.js.map +1 -1
- package/dist/cjs/Video/PlayerChrome.native.js.map +1 -1
- package/dist/cjs/Video/VideoFrame.native.js.map +1 -1
- package/dist/cjs/Video/types.native.js.map +1 -1
- package/dist/cjs/Wheel/index.native.js.map +1 -1
- package/dist/cjs/Wizard/index.native.js +2 -2
- package/dist/cjs/Wizard/index.native.js.map +1 -1
- package/dist/cjs/actions/ActionBar.native.js.map +1 -1
- package/dist/cjs/actions/DangerSection.native.js.map +1 -1
- package/dist/cjs/actions/DestructiveAction.native.js.map +1 -1
- package/dist/cjs/actions/HeaderActions.native.js +2 -2
- package/dist/cjs/actions/HeaderActions.native.js.map +1 -1
- package/dist/cjs/actions/StandardAction.native.js +1 -1
- package/dist/cjs/actions/StandardAction.native.js.map +1 -1
- package/dist/cjs/actions/devWarn.native.js.map +1 -1
- package/dist/cjs/actions/index.native.js.map +1 -1
- package/dist/cjs/actions/severity.native.js.map +1 -1
- package/dist/cjs/appShell/AppShell.cjs +31 -17
- package/dist/cjs/appShell/AppShell.native.js +37 -23
- package/dist/cjs/appShell/AppShell.native.js.map +1 -1
- package/dist/cjs/appShell/Dock.native.js.map +1 -1
- package/dist/cjs/appShell/MpoTabHost.native.js.map +1 -1
- package/dist/cjs/appShell/ScopeMenu.cjs +39 -16
- package/dist/cjs/appShell/ScopeMenu.native.js +43 -17
- package/dist/cjs/appShell/ScopeMenu.native.js.map +1 -1
- package/dist/cjs/appShell/SettingsSplit.native.js +1 -1
- package/dist/cjs/appShell/SettingsSplit.native.js.map +1 -1
- package/dist/cjs/appShell/Springboard.native.js +1 -1
- package/dist/cjs/appShell/Springboard.native.js.map +1 -1
- package/dist/cjs/appShell/SystemBar.native.js.map +1 -1
- package/dist/cjs/appShell/TabBar.native.js +1 -1
- package/dist/cjs/appShell/TabBar.native.js.map +1 -1
- package/dist/cjs/appShell/TabHost.native.js +48 -11
- package/dist/cjs/appShell/TabHost.native.js.map +1 -1
- package/dist/cjs/appShell/appTile.native.js +1 -1
- package/dist/cjs/appShell/appTile.native.js.map +1 -1
- package/dist/cjs/appShell/bottomChrome.cjs +12 -1
- package/dist/cjs/appShell/bottomChrome.native.js +13 -1
- package/dist/cjs/appShell/bottomChrome.native.js.map +1 -1
- package/dist/cjs/appShell/index.native.js.map +1 -1
- package/dist/cjs/charts/Axis.native.js.map +1 -1
- package/dist/cjs/charts/BarChart.native.js.map +1 -1
- package/dist/cjs/charts/ChartDataView.native.js +1 -1
- package/dist/cjs/charts/ChartDataView.native.js.map +1 -1
- package/dist/cjs/charts/ChartSurface.native.js.map +1 -1
- package/dist/cjs/charts/LineChart.native.js.map +1 -1
- package/dist/cjs/charts/PieChart.native.js.map +1 -1
- package/dist/cjs/charts/Sparkline.native.js.map +1 -1
- package/dist/cjs/charts/accessibility.native.js.map +1 -1
- package/dist/cjs/charts/chartHeight.native.js.map +1 -1
- package/dist/cjs/charts/composeChart.native.js.map +1 -1
- package/dist/cjs/charts/index.native.js.map +1 -1
- package/dist/cjs/charts/math.native.js.map +1 -1
- package/dist/cjs/charts/series.native.js.map +1 -1
- package/dist/cjs/charts/svg.native.js.map +1 -1
- package/dist/cjs/charts/types.native.js.map +1 -1
- package/dist/cjs/charts/useChartTheme.native.js.map +1 -1
- package/dist/cjs/code/Code/index.native.js.map +1 -1
- package/dist/cjs/code/CodeBlock/index.native.js +7 -7
- package/dist/cjs/code/CodeBlock/index.native.js.map +1 -1
- package/dist/cjs/code/HighlightedCode/index.native.js.map +1 -1
- package/dist/cjs/code/Highlighter/houseSyntaxTheme.native.js.map +1 -1
- package/dist/cjs/code/Highlighter/index.native.js.map +1 -1
- package/dist/cjs/code/Highlighter/namedGroupMatchAll.native.js.map +1 -1
- package/dist/cjs/code/Pre/index.native.js.map +1 -1
- package/dist/cjs/code/index.native.js +5 -5
- package/dist/cjs/code/index.native.js.map +1 -1
- package/dist/cjs/componentColors.native.js.map +1 -1
- package/dist/cjs/feedback/ConfirmDialog.native.js.map +1 -1
- package/dist/cjs/feedback/NotifyHost.native.js +2 -2
- package/dist/cjs/feedback/NotifyHost.native.js.map +1 -1
- package/dist/cjs/feedback/copy.native.js.map +1 -1
- package/dist/cjs/feedback/index.native.js.map +1 -1
- package/dist/cjs/feedback/notify.native.js.map +1 -1
- package/dist/cjs/feedback/route.native.js.map +1 -1
- package/dist/cjs/feedback/store.native.js.map +1 -1
- package/dist/cjs/formLayouts/FormLayouts.native.js +1 -1
- package/dist/cjs/formLayouts/FormLayouts.native.js.map +1 -1
- package/dist/cjs/formLayouts/PreferencePanel.native.js +2 -2
- package/dist/cjs/formLayouts/PreferencePanel.native.js.map +1 -1
- package/dist/cjs/formLayouts/index.native.js.map +1 -1
- package/dist/cjs/hooks/index.native.js +1 -1
- package/dist/cjs/hooks/index.native.js.map +1 -1
- package/dist/cjs/hooks/useClipboard.native.js.map +1 -1
- package/dist/cjs/hooks/useDocumentTitle.native.js.map +1 -1
- package/dist/cjs/hooks/useHoldCue.native.js.map +1 -1
- package/dist/cjs/icons/CheckRegular.native.js.map +1 -1
- package/dist/cjs/icons/MinusRegular.native.js.map +1 -1
- package/dist/cjs/icons/index.native.js.map +1 -1
- package/dist/cjs/icons/lucide.native.js.map +1 -1
- package/dist/cjs/icons/themed.native.js.map +1 -1
- package/dist/cjs/images/Image/ImageFrame.native.js +1 -1
- package/dist/cjs/images/Image/ImageFrame.native.js.map +1 -1
- package/dist/cjs/images/Image/framing.native.js.map +1 -1
- package/dist/cjs/images/Image/index.native.js +1 -1
- package/dist/cjs/images/Image/mediaRadius.native.js.map +1 -1
- package/dist/cjs/images/Image/shared.native.js +1 -1
- package/dist/cjs/images/Image/shared.native.js.map +1 -1
- package/dist/cjs/images/Image/types.native.js.map +1 -1
- package/dist/cjs/images/index.native.js.map +1 -1
- package/dist/cjs/index.native.js +39 -39
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/knobImmuneExports.native.js.map +1 -1
- package/dist/cjs/layouts/AsyncBoundary.native.js +2 -2
- package/dist/cjs/layouts/AsyncBoundary.native.js.map +1 -1
- package/dist/cjs/layouts/Debug/index.native.js.map +1 -1
- package/dist/cjs/layouts/EmptyState.native.js.map +1 -1
- package/dist/cjs/layouts/IdentityPlate.native.js.map +1 -1
- package/dist/cjs/layouts/KeyboardAvoidingWrapper/behavior.native.js.map +1 -1
- package/dist/cjs/layouts/PageTemplates.native.js.map +1 -1
- package/dist/cjs/layouts/PaneScaffold.native.js.map +1 -1
- package/dist/cjs/layouts/SafeAreaWrapper/insets.native.js.map +1 -1
- package/dist/cjs/layouts/StatusDot.native.js.map +1 -1
- package/dist/cjs/layouts/StatusGlyphStrip.native.js +1 -1
- package/dist/cjs/layouts/StatusGlyphStrip.native.js.map +1 -1
- package/dist/cjs/layouts/ViewSwitcher.native.js.map +1 -1
- package/dist/cjs/layouts/attachments.native.js +1 -1
- package/dist/cjs/layouts/attachments.native.js.map +1 -1
- package/dist/cjs/layouts/bottomAccessory.native.js.map +1 -1
- package/dist/cjs/layouts/breadcrumbs.native.js.map +1 -1
- package/dist/cjs/layouts/index.native.js +3 -3
- package/dist/cjs/layouts/index.native.js.map +1 -1
- package/dist/cjs/layouts/page.native.js +2 -2
- package/dist/cjs/layouts/page.native.js.map +1 -1
- package/dist/cjs/layouts/pageHeadingScope.native.js.map +1 -1
- package/dist/cjs/layouts/screenScroll.native.js.map +1 -1
- package/dist/cjs/layouts/shellSidebarSlot.native.js.map +1 -1
- package/dist/cjs/layouts/sidebar.cjs +29 -8
- package/dist/cjs/layouts/sidebar.native.js +31 -9
- package/dist/cjs/layouts/sidebar.native.js.map +1 -1
- package/dist/cjs/layouts/tags.native.js +2 -2
- package/dist/cjs/layouts/tags.native.js.map +1 -1
- package/dist/cjs/layouts/timeline.native.js +2 -2
- package/dist/cjs/layouts/timeline.native.js.map +1 -1
- package/dist/cjs/layouts/toolbar.native.js +1 -1
- package/dist/cjs/layouts/toolbar.native.js.map +1 -1
- package/dist/cjs/shared/actionScan.native.js.map +1 -1
- package/dist/cjs/shared/i18n.native.js.map +1 -1
- package/dist/cjs/shared/restoreRetries.native.js.map +1 -1
- package/dist/cjs/shared/t.native.js.map +1 -1
- package/dist/cjs/shared/textRidesText.native.js.map +1 -1
- package/dist/cjs/shared/useReturnFocusOnClose.native.js.map +1 -1
- package/dist/cjs/surfaces.native.js +1 -1
- package/dist/cjs/surfaces.native.js.map +1 -1
- package/dist/cjs/tamagui.native.js +1 -1
- package/dist/cjs/tamagui.native.js.map +1 -1
- package/dist/cjs/testSetup.native.js.map +1 -1
- package/dist/cjs/utils/setTinted.native.js.map +1 -1
- package/dist/cjs/utils/unwrapText.native.js.map +1 -1
- package/dist/cjs/views/Calendar.native.js +1 -1
- package/dist/cjs/views/Calendar.native.js.map +1 -1
- package/dist/cjs/views/Dashboard.native.js +2 -2
- package/dist/cjs/views/Dashboard.native.js.map +1 -1
- package/dist/cjs/views/Gantt.native.js +2 -2
- package/dist/cjs/views/Gantt.native.js.map +1 -1
- package/dist/cjs/views/GanttDateGrip.native.js.map +1 -1
- package/dist/cjs/views/ImageGrid.native.js +2 -2
- package/dist/cjs/views/ImageGrid.native.js.map +1 -1
- package/dist/cjs/views/Kanban.native.js +1 -1
- package/dist/cjs/views/List.native.js.map +1 -1
- package/dist/cjs/views/ListGroup.native.js.map +1 -1
- package/dist/cjs/views/ListRow.native.js.map +1 -1
- package/dist/cjs/views/Matrix.native.js +2 -2
- package/dist/cjs/views/Matrix.native.js.map +1 -1
- package/dist/cjs/views/ReportBuilder.native.js +2 -2
- package/dist/cjs/views/ReportBuilder.native.js.map +1 -1
- package/dist/cjs/views/ShortcutCard.native.js.map +1 -1
- package/dist/cjs/views/TreeView.native.js.map +1 -1
- package/dist/cjs/views/calendarMath.native.js.map +1 -1
- package/dist/cjs/views/ganttIntervals.native.js.map +1 -1
- package/dist/cjs/views/ganttMath.native.js.map +1 -1
- package/dist/cjs/views/index.native.js +1 -1
- package/dist/cjs/views/index.native.js.map +1 -1
- package/dist/cjs/views/kanbanDnd.native.js.map +1 -1
- package/dist/cjs/views/matrixMath.native.js.map +1 -1
- package/dist/cjs/views/sameNameScope.native.js.map +1 -1
- package/dist/cjs/views/treeViewDnd.native.js.map +1 -1
- package/dist/cjs/views/treeViewLayout.native.js.map +1 -1
- package/dist/cjs/views/treeViewMotion.native.js.map +1 -1
- package/dist/cjs/views/treeViewReveal.native.js.map +1 -1
- package/dist/cjs/views/usePageFlowLoadMore.native.js.map +1 -1
- package/dist/cjs/views/widgetChrome.native.js.map +1 -1
- package/dist/esm/Accordion/index.native.js.map +1 -1
- package/dist/esm/AnimateHeight/index.native.js.map +1 -1
- package/dist/esm/Avatar/getInitials.native.js.map +1 -1
- package/dist/esm/Avatar/index.native.js.map +1 -1
- package/dist/esm/Badge/index.native.js.map +1 -1
- package/dist/esm/Button.native.js.map +1 -1
- package/dist/esm/Carousel/index.native.js.map +1 -1
- package/dist/esm/CheckGlyph/MenuCheckColumn.mjs +31 -0
- package/dist/esm/CheckGlyph/MenuCheckColumn.mjs.map +1 -0
- package/dist/esm/CheckGlyph/MenuCheckColumn.native.js +32 -0
- package/dist/esm/CheckGlyph/MenuCheckColumn.native.js.map +1 -0
- package/dist/esm/CheckGlyph/index.mjs +15 -0
- package/dist/esm/CheckGlyph/index.mjs.map +1 -0
- package/dist/esm/CheckGlyph/index.native.js +16 -0
- package/dist/esm/CheckGlyph/index.native.js.map +1 -0
- package/dist/esm/Chip/index.native.js.map +1 -1
- package/dist/esm/Collapsible.native.js.map +1 -1
- package/dist/esm/ContextMenu/index.mjs +6 -23
- package/dist/esm/ContextMenu/index.mjs.map +1 -1
- package/dist/esm/ContextMenu/index.native.js +8 -26
- package/dist/esm/ContextMenu/index.native.js.map +1 -1
- package/dist/esm/CopyField/CopyMenuButton.native.js.map +1 -1
- package/dist/esm/CopyField/index.native.js.map +1 -1
- package/dist/esm/Dialog.native.js.map +1 -1
- package/dist/esm/Diff/diff.native.js.map +1 -1
- package/dist/esm/Diff/index.native.js.map +1 -1
- package/dist/esm/DotIndicator/index.native.js.map +1 -1
- package/dist/esm/DropdownMenu/index.mjs +6 -18
- package/dist/esm/DropdownMenu/index.mjs.map +1 -1
- package/dist/esm/DropdownMenu/index.native.js +8 -20
- package/dist/esm/DropdownMenu/index.native.js.map +1 -1
- package/dist/esm/DropdownMenu/menuSettle.native.js.map +1 -1
- package/dist/esm/ElapsedProgress/index.native.js.map +1 -1
- package/dist/esm/ErrorBoundary/index.native.js.map +1 -1
- package/dist/esm/Heading.native.js.map +1 -1
- package/dist/esm/Kbd/index.native.js.map +1 -1
- package/dist/esm/Kbd/keys.native.js.map +1 -1
- package/dist/esm/Lightbox/MediaControl.native.js.map +1 -1
- package/dist/esm/Lightbox/index.gnome.native.js.map +1 -1
- package/dist/esm/Lightbox/shared.native.js.map +1 -1
- package/dist/esm/Lightbox/useLightbox.native.js.map +1 -1
- package/dist/esm/MachineLiteral/index.native.js.map +1 -1
- package/dist/esm/Material/index.native.js.map +1 -1
- package/dist/esm/Meter/index.native.js.map +1 -1
- package/dist/esm/Meter/meter.native.js.map +1 -1
- package/dist/esm/OverflowRow/index.native.js.map +1 -1
- package/dist/esm/Pagination.native.js.map +1 -1
- package/dist/esm/Popover.mjs +2 -2
- package/dist/esm/Popover.mjs.map +1 -1
- package/dist/esm/Popover.native.js +2 -2
- package/dist/esm/Popover.native.js.map +1 -1
- package/dist/esm/ProgressSteps/index.native.js.map +1 -1
- package/dist/esm/Quote/index.native.js.map +1 -1
- package/dist/esm/SchemeToggle/index.mjs +3 -3
- package/dist/esm/SchemeToggle/index.mjs.map +1 -1
- package/dist/esm/SchemeToggle/index.native.js +3 -3
- package/dist/esm/SchemeToggle/index.native.js.map +1 -1
- package/dist/esm/ScrollView/revealFocusedField.native.js.map +1 -1
- package/dist/esm/Separator/index.native.js.map +1 -1
- package/dist/esm/Sheet.native.js.map +1 -1
- package/dist/esm/SheetModal/SheetHeader.native.js.map +1 -1
- package/dist/esm/SheetModal/SheetNavigation.native.js.map +1 -1
- package/dist/esm/SheetModal/detents.native.js.map +1 -1
- package/dist/esm/SheetModal/index.mjs +6 -11
- package/dist/esm/SheetModal/index.mjs.map +1 -1
- package/dist/esm/SheetModal/index.native.js +9 -13
- package/dist/esm/SheetModal/index.native.js.map +1 -1
- package/dist/esm/SheetModal/useSheetFrameFocus.native.js.map +1 -1
- package/dist/esm/Skeleton/index.native.js.map +1 -1
- package/dist/esm/SkipLink/index.native.js.map +1 -1
- package/dist/esm/SortableList/SortableHandle.native.js.map +1 -1
- package/dist/esm/SortableList/index.native.js.map +1 -1
- package/dist/esm/SortableList/useSortableRows.native.js.map +1 -1
- package/dist/esm/SortableList/useUserOrder.native.js.map +1 -1
- package/dist/esm/Tabs/index.native.js.map +1 -1
- package/dist/esm/Text.native.js.map +1 -1
- package/dist/esm/ThemePresetPicker/index.native.js.map +1 -1
- package/dist/esm/Toast/index.native.js.map +1 -1
- package/dist/esm/Toast/store.native.js.map +1 -1
- package/dist/esm/Tooltip/nativePress.native.js.map +1 -1
- package/dist/esm/Tooltip/tooltipShared.native.js.map +1 -1
- package/dist/esm/TreeSelect/index.mjs +4 -8
- package/dist/esm/TreeSelect/index.mjs.map +1 -1
- package/dist/esm/TreeSelect/index.native.js +4 -8
- package/dist/esm/TreeSelect/index.native.js.map +1 -1
- package/dist/esm/TreeSelect/treeSelectModel.native.js.map +1 -1
- package/dist/esm/Video/PlayerChrome.native.js.map +1 -1
- package/dist/esm/Video/VideoFrame.native.js.map +1 -1
- package/dist/esm/Video/types.native.js.map +1 -1
- package/dist/esm/Wheel/index.native.js.map +1 -1
- package/dist/esm/Wizard/index.native.js.map +1 -1
- package/dist/esm/actions/ActionBar.native.js.map +1 -1
- package/dist/esm/actions/DangerSection.native.js.map +1 -1
- package/dist/esm/actions/DestructiveAction.native.js.map +1 -1
- package/dist/esm/actions/HeaderActions.native.js.map +1 -1
- package/dist/esm/actions/StandardAction.native.js.map +1 -1
- package/dist/esm/actions/devWarn.native.js.map +1 -1
- package/dist/esm/actions/index.native.js.map +1 -1
- package/dist/esm/actions/severity.native.js.map +1 -1
- package/dist/esm/appShell/AppShell.mjs +32 -18
- package/dist/esm/appShell/AppShell.mjs.map +1 -1
- package/dist/esm/appShell/AppShell.native.js +37 -23
- package/dist/esm/appShell/AppShell.native.js.map +1 -1
- package/dist/esm/appShell/Dock.native.js.map +1 -1
- package/dist/esm/appShell/MpoTabHost.native.js.map +1 -1
- package/dist/esm/appShell/ScopeMenu.mjs +43 -20
- package/dist/esm/appShell/ScopeMenu.mjs.map +1 -1
- package/dist/esm/appShell/ScopeMenu.native.js +47 -21
- package/dist/esm/appShell/ScopeMenu.native.js.map +1 -1
- package/dist/esm/appShell/SettingsSplit.native.js.map +1 -1
- package/dist/esm/appShell/Springboard.native.js.map +1 -1
- package/dist/esm/appShell/SystemBar.native.js.map +1 -1
- package/dist/esm/appShell/TabBar.mjs.map +1 -1
- package/dist/esm/appShell/TabBar.native.js.map +1 -1
- package/dist/esm/appShell/TabHost.native.js +48 -13
- package/dist/esm/appShell/TabHost.native.js.map +1 -1
- package/dist/esm/appShell/appTile.native.js.map +1 -1
- package/dist/esm/appShell/bottomChrome.mjs +13 -3
- package/dist/esm/appShell/bottomChrome.mjs.map +1 -1
- package/dist/esm/appShell/bottomChrome.native.js +14 -3
- package/dist/esm/appShell/bottomChrome.native.js.map +1 -1
- package/dist/esm/appShell/index.native.js.map +1 -1
- package/dist/esm/charts/Axis.native.js.map +1 -1
- package/dist/esm/charts/BarChart.native.js.map +1 -1
- package/dist/esm/charts/ChartDataView.native.js.map +1 -1
- package/dist/esm/charts/ChartSurface.native.js.map +1 -1
- package/dist/esm/charts/LineChart.native.js.map +1 -1
- package/dist/esm/charts/PieChart.native.js.map +1 -1
- package/dist/esm/charts/Sparkline.native.js.map +1 -1
- package/dist/esm/charts/accessibility.native.js.map +1 -1
- package/dist/esm/charts/chartHeight.native.js.map +1 -1
- package/dist/esm/charts/composeChart.native.js.map +1 -1
- package/dist/esm/charts/index.native.js.map +1 -1
- package/dist/esm/charts/math.native.js.map +1 -1
- package/dist/esm/charts/series.native.js.map +1 -1
- package/dist/esm/charts/svg.native.js.map +1 -1
- package/dist/esm/charts/types.native.js.map +1 -1
- package/dist/esm/charts/useChartTheme.native.js.map +1 -1
- package/dist/esm/code/Code/index.native.js.map +1 -1
- package/dist/esm/code/CodeBlock/index.native.js.map +1 -1
- package/dist/esm/code/HighlightedCode/index.native.js.map +1 -1
- package/dist/esm/code/Highlighter/houseSyntaxTheme.native.js.map +1 -1
- package/dist/esm/code/Highlighter/index.native.js.map +1 -1
- package/dist/esm/code/Highlighter/namedGroupMatchAll.native.js.map +1 -1
- package/dist/esm/code/Pre/index.native.js.map +1 -1
- package/dist/esm/code/index.native.js.map +1 -1
- package/dist/esm/componentColors.native.js.map +1 -1
- package/dist/esm/feedback/ConfirmDialog.native.js.map +1 -1
- package/dist/esm/feedback/NotifyHost.native.js.map +1 -1
- package/dist/esm/feedback/copy.native.js.map +1 -1
- package/dist/esm/feedback/index.native.js.map +1 -1
- package/dist/esm/feedback/notify.native.js.map +1 -1
- package/dist/esm/feedback/route.native.js.map +1 -1
- package/dist/esm/feedback/store.native.js.map +1 -1
- package/dist/esm/formLayouts/FormLayouts.native.js.map +1 -1
- package/dist/esm/formLayouts/PreferencePanel.native.js.map +1 -1
- package/dist/esm/formLayouts/index.native.js.map +1 -1
- package/dist/esm/hooks/index.native.js.map +1 -1
- package/dist/esm/hooks/useClipboard.native.js.map +1 -1
- package/dist/esm/hooks/useDocumentTitle.native.js.map +1 -1
- package/dist/esm/hooks/useHoldCue.native.js.map +1 -1
- package/dist/esm/icons/CheckRegular.native.js.map +1 -1
- package/dist/esm/icons/MinusRegular.native.js.map +1 -1
- package/dist/esm/icons/index.native.js.map +1 -1
- package/dist/esm/icons/lucide.native.js.map +1 -1
- package/dist/esm/icons/themed.native.js.map +1 -1
- package/dist/esm/images/Image/ImageFrame.native.js.map +1 -1
- package/dist/esm/images/Image/framing.native.js.map +1 -1
- package/dist/esm/images/Image/mediaRadius.native.js.map +1 -1
- package/dist/esm/images/Image/shared.native.js.map +1 -1
- package/dist/esm/images/Image/types.native.js.map +1 -1
- package/dist/esm/images/index.native.js.map +1 -1
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/knobImmuneExports.native.js.map +1 -1
- package/dist/esm/layouts/AsyncBoundary.native.js.map +1 -1
- package/dist/esm/layouts/Debug/index.native.js.map +1 -1
- package/dist/esm/layouts/EmptyState.native.js.map +1 -1
- package/dist/esm/layouts/IdentityPlate.native.js.map +1 -1
- package/dist/esm/layouts/KeyboardAvoidingWrapper/behavior.native.js.map +1 -1
- package/dist/esm/layouts/PageTemplates.native.js.map +1 -1
- package/dist/esm/layouts/PaneScaffold.native.js.map +1 -1
- package/dist/esm/layouts/SafeAreaWrapper/insets.native.js.map +1 -1
- package/dist/esm/layouts/StatusDot.native.js.map +1 -1
- package/dist/esm/layouts/StatusGlyphStrip.native.js.map +1 -1
- package/dist/esm/layouts/ViewSwitcher.native.js.map +1 -1
- package/dist/esm/layouts/attachments.native.js.map +1 -1
- package/dist/esm/layouts/bottomAccessory.native.js.map +1 -1
- package/dist/esm/layouts/breadcrumbs.native.js.map +1 -1
- package/dist/esm/layouts/index.native.js.map +1 -1
- package/dist/esm/layouts/page.native.js.map +1 -1
- package/dist/esm/layouts/pageHeadingScope.native.js.map +1 -1
- package/dist/esm/layouts/screenScroll.native.js.map +1 -1
- package/dist/esm/layouts/shellSidebarSlot.native.js.map +1 -1
- package/dist/esm/layouts/sidebar.mjs +31 -10
- package/dist/esm/layouts/sidebar.mjs.map +1 -1
- package/dist/esm/layouts/sidebar.native.js +32 -10
- package/dist/esm/layouts/sidebar.native.js.map +1 -1
- package/dist/esm/layouts/tags.native.js.map +1 -1
- package/dist/esm/layouts/timeline.native.js.map +1 -1
- package/dist/esm/layouts/toolbar.native.js.map +1 -1
- package/dist/esm/shared/actionScan.native.js.map +1 -1
- package/dist/esm/shared/i18n.native.js.map +1 -1
- package/dist/esm/shared/restoreRetries.native.js.map +1 -1
- package/dist/esm/shared/t.native.js.map +1 -1
- package/dist/esm/shared/textRidesText.native.js.map +1 -1
- package/dist/esm/shared/useReturnFocusOnClose.native.js.map +1 -1
- package/dist/esm/surfaces.native.js.map +1 -1
- package/dist/esm/tamagui.native.js.map +1 -1
- package/dist/esm/testSetup.native.js.map +1 -1
- package/dist/esm/utils/setTinted.native.js.map +1 -1
- package/dist/esm/utils/unwrapText.native.js.map +1 -1
- package/dist/esm/views/Calendar.native.js.map +1 -1
- package/dist/esm/views/Dashboard.native.js.map +1 -1
- package/dist/esm/views/Gantt.native.js.map +1 -1
- package/dist/esm/views/GanttDateGrip.native.js.map +1 -1
- package/dist/esm/views/ImageGrid.native.js.map +1 -1
- package/dist/esm/views/List.native.js.map +1 -1
- package/dist/esm/views/ListGroup.native.js.map +1 -1
- package/dist/esm/views/ListRow.native.js.map +1 -1
- package/dist/esm/views/Matrix.native.js.map +1 -1
- package/dist/esm/views/ReportBuilder.native.js.map +1 -1
- package/dist/esm/views/ShortcutCard.native.js.map +1 -1
- package/dist/esm/views/TreeView.native.js.map +1 -1
- package/dist/esm/views/calendarMath.native.js.map +1 -1
- package/dist/esm/views/ganttIntervals.native.js.map +1 -1
- package/dist/esm/views/ganttMath.native.js.map +1 -1
- package/dist/esm/views/index.native.js.map +1 -1
- package/dist/esm/views/kanbanDnd.native.js.map +1 -1
- package/dist/esm/views/matrixMath.native.js.map +1 -1
- package/dist/esm/views/sameNameScope.native.js.map +1 -1
- package/dist/esm/views/treeViewDnd.native.js.map +1 -1
- package/dist/esm/views/treeViewLayout.native.js.map +1 -1
- package/dist/esm/views/treeViewMotion.native.js.map +1 -1
- package/dist/esm/views/treeViewReveal.native.js.map +1 -1
- package/dist/esm/views/usePageFlowLoadMore.native.js.map +1 -1
- package/dist/esm/views/widgetChrome.native.js.map +1 -1
- package/dist/jsx/CheckGlyph/MenuCheckColumn.mjs +31 -0
- package/dist/jsx/CheckGlyph/MenuCheckColumn.mjs.map +1 -0
- package/dist/jsx/CheckGlyph/MenuCheckColumn.native.js +60 -0
- package/dist/jsx/CheckGlyph/MenuCheckColumn.native.js.map +1 -0
- package/dist/jsx/CheckGlyph/index.mjs +15 -0
- package/dist/jsx/CheckGlyph/index.mjs.map +1 -0
- package/dist/jsx/CheckGlyph/index.native.js +44 -0
- package/dist/jsx/CheckGlyph/index.native.js.map +1 -0
- package/dist/jsx/ContextMenu/index.mjs +6 -23
- package/dist/jsx/ContextMenu/index.mjs.map +1 -1
- package/dist/jsx/ContextMenu/index.native.js +7 -25
- package/dist/jsx/ContextMenu/index.native.js.map +1 -1
- package/dist/jsx/DropdownMenu/index.mjs +6 -18
- package/dist/jsx/DropdownMenu/index.mjs.map +1 -1
- package/dist/jsx/DropdownMenu/index.native.js +7 -19
- package/dist/jsx/DropdownMenu/index.native.js.map +1 -1
- package/dist/jsx/Popover.mjs +2 -2
- package/dist/jsx/Popover.mjs.map +1 -1
- package/dist/jsx/Popover.native.js +2 -2
- package/dist/jsx/Popover.native.js.map +1 -1
- package/dist/jsx/SchemeToggle/index.mjs +3 -3
- package/dist/jsx/SchemeToggle/index.mjs.map +1 -1
- package/dist/jsx/SchemeToggle/index.native.js +2 -2
- package/dist/jsx/SchemeToggle/index.native.js.map +1 -1
- package/dist/jsx/SheetModal/index.mjs +6 -11
- package/dist/jsx/SheetModal/index.mjs.map +1 -1
- package/dist/jsx/SheetModal/index.native.js +8 -12
- package/dist/jsx/SheetModal/index.native.js.map +1 -1
- package/dist/jsx/TreeSelect/index.mjs +4 -8
- package/dist/jsx/TreeSelect/index.mjs.map +1 -1
- package/dist/jsx/TreeSelect/index.native.js +2 -6
- package/dist/jsx/TreeSelect/index.native.js.map +1 -1
- package/dist/jsx/appShell/AppShell.mjs +32 -18
- package/dist/jsx/appShell/AppShell.mjs.map +1 -1
- package/dist/jsx/appShell/AppShell.native.js +36 -22
- package/dist/jsx/appShell/AppShell.native.js.map +1 -1
- package/dist/jsx/appShell/ScopeMenu.mjs +43 -20
- package/dist/jsx/appShell/ScopeMenu.mjs.map +1 -1
- package/dist/jsx/appShell/ScopeMenu.native.js +43 -17
- package/dist/jsx/appShell/ScopeMenu.native.js.map +1 -1
- package/dist/jsx/appShell/TabBar.mjs.map +1 -1
- package/dist/jsx/appShell/TabBar.native.js.map +1 -1
- package/dist/jsx/appShell/TabHost.native.js +48 -11
- package/dist/jsx/appShell/TabHost.native.js.map +1 -1
- package/dist/jsx/appShell/bottomChrome.mjs +13 -3
- package/dist/jsx/appShell/bottomChrome.mjs.map +1 -1
- package/dist/jsx/appShell/bottomChrome.native.js +13 -1
- package/dist/jsx/appShell/bottomChrome.native.js.map +1 -1
- package/dist/jsx/layouts/sidebar.mjs +31 -10
- package/dist/jsx/layouts/sidebar.mjs.map +1 -1
- package/dist/jsx/layouts/sidebar.native.js +30 -8
- package/dist/jsx/layouts/sidebar.native.js.map +1 -1
- package/package.json +9 -9
- package/src/CheckGlyph/CheckGlyph.spec.tsx +46 -0
- package/src/CheckGlyph/MenuCheckColumn.tsx +32 -0
- package/src/CheckGlyph/index.tsx +12 -0
- package/src/ContextMenu/ContextMenu.spec.tsx +46 -1
- package/src/ContextMenu/index.tsx +5 -22
- package/src/DropdownMenu/DropdownMenu.avatarTrigger.spec.tsx +6 -9
- package/src/DropdownMenu/index.tsx +5 -18
- package/src/Popover.coverTrigger.spec.tsx +3 -3
- package/src/Popover.tsx +5 -5
- package/src/SchemeToggle/SchemeToggle.spec.tsx +5 -11
- package/src/SchemeToggle/SchemeToggle.stories.tsx +21 -0
- package/src/SchemeToggle/index.tsx +2 -1
- package/src/ScrollView/ScrollView.native.spec.tsx +14 -2
- package/src/SheetFrame.stories.tsx +2 -8
- package/src/SheetModal/SheetModal.grabber.spec.tsx +51 -0
- package/src/SheetModal/index.native.tsx +15 -18
- package/src/SheetModal/index.tsx +12 -15
- package/src/TreeSelect/index.tsx +2 -4
- package/src/appShell/AppShell.spec.tsx +51 -0
- package/src/appShell/AppShell.tsx +30 -14
- package/src/appShell/ScopeMenu.spec.tsx +22 -0
- package/src/appShell/ScopeMenu.tsx +57 -18
- package/src/appShell/TabBar.tsx +13 -3
- package/src/appShell/TabHost.native.spec.tsx +63 -6
- package/src/appShell/TabHost.native.tsx +56 -15
- package/src/appShell/TabHost.stories.tsx +72 -0
- package/src/appShell/bottomChrome.ts +24 -3
- package/src/layouts/PageHeader.stories.tsx +3 -3
- package/src/layouts/Sidebar.spec.tsx +61 -1
- package/src/layouts/pageActionButton.spec.tsx +7 -3
- package/src/layouts/sidebar.tsx +22 -8
- package/types/CheckGlyph/MenuCheckColumn.d.ts +11 -0
- package/types/CheckGlyph/MenuCheckColumn.d.ts.map +1 -0
- package/types/CheckGlyph/index.d.ts +10 -0
- package/types/CheckGlyph/index.d.ts.map +1 -0
- package/types/ContextMenu/index.d.ts.map +1 -1
- package/types/DropdownMenu/index.d.ts.map +1 -1
- package/types/Popover.d.ts +1 -1
- package/types/Popover.d.ts.map +1 -1
- package/types/SchemeToggle/index.d.ts.map +1 -1
- package/types/SheetModal/index.d.ts.map +1 -1
- package/types/SheetModal/index.native.d.ts.map +1 -1
- package/types/TreeSelect/index.d.ts.map +1 -1
- package/types/appShell/AppShell.d.ts.map +1 -1
- package/types/appShell/ScopeMenu.d.ts +0 -18
- package/types/appShell/ScopeMenu.d.ts.map +1 -1
- package/types/appShell/TabBar.d.ts +12 -6
- package/types/appShell/TabBar.d.ts.map +1 -1
- package/types/appShell/TabHost.native.d.ts +23 -5
- package/types/appShell/TabHost.native.d.ts.map +1 -1
- package/types/appShell/bottomChrome.d.ts +11 -1
- package/types/appShell/bottomChrome.d.ts.map +1 -1
- package/types/layouts/sidebar.d.ts +7 -1
- package/types/layouts/sidebar.d.ts.map +1 -1
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
} from "../layouts/page";
|
|
18
18
|
import { ListPageLayout } from "../layouts/PageTemplates";
|
|
19
19
|
import { AppShell, appShellRoute, type AppShellDestination } from "./AppShell";
|
|
20
|
+
import { setBottomChromeInset } from "./bottomChrome";
|
|
20
21
|
|
|
21
22
|
const size = vi.hoisted(() => ({ value: "compact" as string }));
|
|
22
23
|
vi.mock("@multiplatform.one/theme", async (importOriginal) => ({
|
|
@@ -184,6 +185,56 @@ describe("AppShell on a phone", () => {
|
|
|
184
185
|
expect(screen.queryByRole("tablist")).toBeNull();
|
|
185
186
|
expect(screen.getByTestId("page")).toBeTruthy();
|
|
186
187
|
});
|
|
188
|
+
|
|
189
|
+
it("keeps the tab bar around an own-chrome route that is a tab, and on a route below it", () => {
|
|
190
|
+
const withDesk = [...destinations, { key: "/desk", label: "Desk", icon: HouseIcon }];
|
|
191
|
+
for (const path of ["/desk", "/desk/Pokemon"]) {
|
|
192
|
+
const { onNavigate } = shell(path, { destinations: withDesk });
|
|
193
|
+
expect(screen.getByTestId("app-shell").getAttribute("data-chrome")).toBe("own");
|
|
194
|
+
expect(screen.queryByTestId("app-shell-bar")).toBeNull();
|
|
195
|
+
const tabs = screen.getAllByRole("tab");
|
|
196
|
+
expect(tabs.map((tab) => tab.getAttribute("aria-label"))).toEqual([
|
|
197
|
+
"Home",
|
|
198
|
+
"Pokemon",
|
|
199
|
+
"Desk",
|
|
200
|
+
]);
|
|
201
|
+
expect(tabs[2]!.getAttribute("aria-selected")).toBe("true");
|
|
202
|
+
fireEvent.click(tabs[0]!);
|
|
203
|
+
expect(onNavigate).toHaveBeenCalledWith("/");
|
|
204
|
+
expect(screen.getByTestId("page")).toBeTruthy();
|
|
205
|
+
cleanup();
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it("ends an own-chrome tab route above the tab bar it keeps, and clears it once", () => {
|
|
210
|
+
const bar = Symbol("bar");
|
|
211
|
+
act(() => setBottomChromeInset(bar, 77));
|
|
212
|
+
try {
|
|
213
|
+
shell("/desk/Pokemon", {
|
|
214
|
+
destinations: [...destinations, { key: "/desk", label: "Desk", icon: HouseIcon }],
|
|
215
|
+
children: <Screen>row</Screen>,
|
|
216
|
+
});
|
|
217
|
+
const frame = screen.getByTestId("app-shell-own-chrome");
|
|
218
|
+
expect(
|
|
219
|
+
getComputedStyle(frame).paddingBottom === "77px" ||
|
|
220
|
+
/\b_pb-77px\b|padding-bottom: 77px/.test(frame.outerHTML),
|
|
221
|
+
).toBe(true);
|
|
222
|
+
expect(frame.contains(screen.getByText("row"))).toBe(true);
|
|
223
|
+
expect(screen.queryByTestId("screen-chrome-clearance")).toBeNull();
|
|
224
|
+
} finally {
|
|
225
|
+
act(() => setBottomChromeInset(bar, null));
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it("draws no tab bar around an own-chrome route at regular width", () => {
|
|
230
|
+
size.value = "expanded";
|
|
231
|
+
shell("/desk", {
|
|
232
|
+
destinations: [...destinations, { key: "/desk", label: "Desk", icon: HouseIcon }],
|
|
233
|
+
});
|
|
234
|
+
expect(screen.getByTestId("app-shell").getAttribute("data-chrome")).toBe("own");
|
|
235
|
+
expect(screen.queryByRole("tablist")).toBeNull();
|
|
236
|
+
expect(screen.queryByTestId("app-shell-sidebar")).toBeNull();
|
|
237
|
+
});
|
|
187
238
|
});
|
|
188
239
|
|
|
189
240
|
describe("AppShell at regular width", () => {
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
* (LC-101 ONE-SIDEBAR).
|
|
18
18
|
*
|
|
19
19
|
* A route listed in `ownChrome` mounts its own full chrome (a desk), so the
|
|
20
|
-
* shell draws
|
|
20
|
+
* shell draws no bar or sidebar around it. On a phone, one that is also a tab
|
|
21
|
+
* destination keeps the tab bar, the only way to the other tabs (FZ-8105). A page whose `Screen` pins its own top bar
|
|
21
22
|
* (LC-157) owns the nav bar on a phone, so the shell's bar steps aside there.
|
|
22
23
|
*/
|
|
23
24
|
import { zIndex } from "@multiplatform.one/forms";
|
|
@@ -48,7 +49,7 @@ import { Sidebar } from "../layouts/sidebar";
|
|
|
48
49
|
import { useTranslation } from "../shared/i18n";
|
|
49
50
|
import type { TabBarIcon, TabBarItem } from "./TabBar";
|
|
50
51
|
import { TabHost } from "./TabHost";
|
|
51
|
-
import { useBottomChromeInset, useFloatingBarMounted } from "./bottomChrome";
|
|
52
|
+
import { BottomChromeCleared, useBottomChromeInset, useFloatingBarMounted } from "./bottomChrome";
|
|
52
53
|
|
|
53
54
|
export interface AppShellDestination {
|
|
54
55
|
/** The destination's route; a path under it keeps it selected. */
|
|
@@ -305,6 +306,18 @@ export function AppShell({
|
|
|
305
306
|
[destinations],
|
|
306
307
|
);
|
|
307
308
|
|
|
309
|
+
const showTabs = compact && Boolean(destination && tabs.includes(destination));
|
|
310
|
+
const tabItems: TabBarItem[] = tabs.map(({ key, label, icon, nativeIcon }) => ({
|
|
311
|
+
key,
|
|
312
|
+
label,
|
|
313
|
+
icon,
|
|
314
|
+
nativeIcon,
|
|
315
|
+
}));
|
|
316
|
+
const onTabPress = (key: string) => {
|
|
317
|
+
const item = tabs.find((tab) => tab.key === key);
|
|
318
|
+
if (item) go(item);
|
|
319
|
+
};
|
|
320
|
+
|
|
308
321
|
if (ownsChrome) {
|
|
309
322
|
return (
|
|
310
323
|
<YStack
|
|
@@ -315,7 +328,20 @@ export function AppShell({
|
|
|
315
328
|
data-testid={testID}
|
|
316
329
|
data-chrome="own"
|
|
317
330
|
>
|
|
318
|
-
{
|
|
331
|
+
{showTabs ? (
|
|
332
|
+
<TabHost items={tabItems} activeKey={destination?.key} onTabPress={onTabPress}>
|
|
333
|
+
<YStack
|
|
334
|
+
flex={1}
|
|
335
|
+
minHeight={0}
|
|
336
|
+
paddingBottom={chromeInset}
|
|
337
|
+
data-testid="app-shell-own-chrome"
|
|
338
|
+
>
|
|
339
|
+
<BottomChromeCleared>{children}</BottomChromeCleared>
|
|
340
|
+
</YStack>
|
|
341
|
+
</TabHost>
|
|
342
|
+
) : (
|
|
343
|
+
children
|
|
344
|
+
)}
|
|
319
345
|
</YStack>
|
|
320
346
|
);
|
|
321
347
|
}
|
|
@@ -401,13 +427,6 @@ export function AppShell({
|
|
|
401
427
|
</YStack>
|
|
402
428
|
);
|
|
403
429
|
|
|
404
|
-
const showTabs = compact && Boolean(destination && tabs.includes(destination));
|
|
405
|
-
const tabItems: TabBarItem[] = tabs.map(({ key, label, icon, nativeIcon }) => ({
|
|
406
|
-
key,
|
|
407
|
-
label,
|
|
408
|
-
icon,
|
|
409
|
-
nativeIcon,
|
|
410
|
-
}));
|
|
411
430
|
// The floating TabBar takes the accessory into its own capsule. Otherwise
|
|
412
431
|
// it renders in place, and on native it clears the system tab bar, which
|
|
413
432
|
// the content runs under.
|
|
@@ -430,10 +449,7 @@ export function AppShell({
|
|
|
430
449
|
<TabHost
|
|
431
450
|
items={tabItems}
|
|
432
451
|
activeKey={showTabs ? destination?.key : undefined}
|
|
433
|
-
onTabPress={
|
|
434
|
-
const item = tabs.find((tab) => tab.key === key);
|
|
435
|
-
if (item) go(item);
|
|
436
|
-
}}
|
|
452
|
+
onTabPress={onTabPress}
|
|
437
453
|
>
|
|
438
454
|
{content}
|
|
439
455
|
{pageAccessory}
|
|
@@ -135,3 +135,25 @@ describe("ScopeMenu (LC-105 COVER-TRIGGER)", () => {
|
|
|
135
135
|
expect(screen.getByLabelText("Environment: Production")).toBeTruthy();
|
|
136
136
|
});
|
|
137
137
|
});
|
|
138
|
+
|
|
139
|
+
describe("ScopeMenu as a phone sheet (FZ-8557)", () => {
|
|
140
|
+
it("titles the sheet with the picker's label instead of echoing the trigger", async () => {
|
|
141
|
+
const width = window.innerWidth;
|
|
142
|
+
Object.defineProperty(window, "innerWidth", { configurable: true, writable: true, value: 390 });
|
|
143
|
+
try {
|
|
144
|
+
renderWithProviders(<Tenant />);
|
|
145
|
+
fireEvent.click(screen.getByTestId("tenant-trigger"));
|
|
146
|
+
const header = await screen.findByTestId("tenant-sheet-header");
|
|
147
|
+
expect(screen.getByRole("heading", { name: "Tenant" })).toBeTruthy();
|
|
148
|
+
expect(header.closest('[data-testid="floating-panel-sheet"]')).not.toBeNull();
|
|
149
|
+
expect(screen.queryByTestId("tenant-first-row")).toBeNull();
|
|
150
|
+
expect(screen.getAllByRole("menuitemradio")).toHaveLength(2);
|
|
151
|
+
} finally {
|
|
152
|
+
Object.defineProperty(window, "innerWidth", {
|
|
153
|
+
configurable: true,
|
|
154
|
+
writable: true,
|
|
155
|
+
value: width,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
});
|
|
@@ -14,13 +14,16 @@
|
|
|
14
14
|
* side, never one menu with two sections.
|
|
15
15
|
*
|
|
16
16
|
* Narrow viewports and native get FloatingPanel's sheet (phones take
|
|
17
|
-
* sheets)
|
|
17
|
+
* sheets). A sheet isn't over its trigger, so it drops the first row for a
|
|
18
|
+
* sheet title, the picker's label (FZ-8557).
|
|
18
19
|
*/
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
20
|
+
import { CheckGlyph } from "../CheckGlyph";
|
|
21
|
+
import { FloatingPanel, type PanelWidth, useInPanelSheet } from "@multiplatform.one/forms";
|
|
22
|
+
import { menuRowCheckGlyph, menuRowChecked, useResolvedKnobs } from "@multiplatform.one/theme";
|
|
23
|
+
import { CaretDownIcon, CaretUpIcon } from "@phosphor-icons/react";
|
|
22
24
|
import { useState } from "react";
|
|
23
|
-
import { XStack, YStack } from "tamagui";
|
|
25
|
+
import { View, XStack, YStack } from "tamagui";
|
|
26
|
+
import { OverlayHeader } from "../actions/StandardAction";
|
|
24
27
|
import { SizableText } from "../Text";
|
|
25
28
|
|
|
26
29
|
export interface ScopeMenuOption {
|
|
@@ -60,8 +63,8 @@ function ScopeRow({
|
|
|
60
63
|
ariaLabel?: string;
|
|
61
64
|
}) {
|
|
62
65
|
const { knobProps, control } = useResolvedKnobs();
|
|
66
|
+
const inSheet = useInPanelSheet();
|
|
63
67
|
const iconSize = Number(knobProps.controlIcon?.width) || undefined;
|
|
64
|
-
const checkInk = useMenuRowCheckInk();
|
|
65
68
|
const Chevron = chevron === "up" ? CaretUpIcon : CaretDownIcon;
|
|
66
69
|
return (
|
|
67
70
|
<XStack
|
|
@@ -71,8 +74,11 @@ function ScopeRow({
|
|
|
71
74
|
{...(role === "menuitemradio" ? { "aria-checked": !!checked } : {})}
|
|
72
75
|
alignItems="center"
|
|
73
76
|
gap="$2"
|
|
74
|
-
|
|
75
|
-
|
|
77
|
+
// A menu row is the menu row recipe's height, a touch target on a phone
|
|
78
|
+
// (44pt, HIG); the bar trigger and its echo keep the bar's size.
|
|
79
|
+
minHeight={role === "menuitemradio" ? knobProps.menuRow.minHeight : "$3"}
|
|
80
|
+
// A phone sheet's rows keep HIG's 16pt gutter; a bar menu's hug the trigger.
|
|
81
|
+
paddingHorizontal={inSheet ? "$4" : "$2.5"}
|
|
76
82
|
cursor="pointer"
|
|
77
83
|
onPress={onPress}
|
|
78
84
|
// The echo row is the trigger itself, laid on the panel (LC-112): the
|
|
@@ -91,8 +97,8 @@ function ScopeRow({
|
|
|
91
97
|
{...(chevron === "down" ? { borderRadius: knobProps.borderRadius.borderRadius } : undefined)}
|
|
92
98
|
>
|
|
93
99
|
{role === "menuitemradio" ? (
|
|
94
|
-
<YStack width={
|
|
95
|
-
{checked ? <
|
|
100
|
+
<YStack width={menuRowCheckGlyph.size} alignItems="center" aria-hidden>
|
|
101
|
+
{checked ? <CheckGlyph /> : null}
|
|
96
102
|
</YStack>
|
|
97
103
|
) : null}
|
|
98
104
|
<SizableText size="$2" fontWeight={chevron ? "500" : "400"} numberOfLines={1}>
|
|
@@ -103,6 +109,42 @@ function ScopeRow({
|
|
|
103
109
|
);
|
|
104
110
|
}
|
|
105
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Over its trigger, the menu's first row is the pressed item with its chevron
|
|
114
|
+
* flipped (LC-112). A phone sheet isn't over its trigger, so it takes a sheet
|
|
115
|
+
* title, the picker's label, and a close (HIG, FZ-8557 Round 40).
|
|
116
|
+
*/
|
|
117
|
+
function ScopeMenuHead({
|
|
118
|
+
label,
|
|
119
|
+
currentLabel,
|
|
120
|
+
onClose,
|
|
121
|
+
testID,
|
|
122
|
+
}: {
|
|
123
|
+
label: string;
|
|
124
|
+
currentLabel: string;
|
|
125
|
+
onClose: () => void;
|
|
126
|
+
testID: string;
|
|
127
|
+
}) {
|
|
128
|
+
const inSheet = useInPanelSheet();
|
|
129
|
+
if (inSheet) {
|
|
130
|
+
return (
|
|
131
|
+
<View paddingHorizontal="$4" paddingBottom="$2">
|
|
132
|
+
<OverlayHeader title={label} onClose={onClose} testID={`${testID}-sheet-header`} />
|
|
133
|
+
</View>
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
return (
|
|
137
|
+
<ScopeRow
|
|
138
|
+
role="button"
|
|
139
|
+
label={currentLabel}
|
|
140
|
+
chevron="up"
|
|
141
|
+
ariaLabel={`${label}: ${currentLabel}`}
|
|
142
|
+
onPress={onClose}
|
|
143
|
+
testID={`${testID}-first-row`}
|
|
144
|
+
/>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
106
148
|
export function ScopeMenu({
|
|
107
149
|
label,
|
|
108
150
|
options,
|
|
@@ -144,14 +186,11 @@ export function ScopeMenu({
|
|
|
144
186
|
}
|
|
145
187
|
>
|
|
146
188
|
<YStack role="menu" aria-label={label} data-testid={`${testID}-panel`}>
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
ariaLabel={`${label}: ${currentLabel}`}
|
|
153
|
-
onPress={() => setOpen(false)}
|
|
154
|
-
testID={`${testID}-first-row`}
|
|
189
|
+
<ScopeMenuHead
|
|
190
|
+
label={label}
|
|
191
|
+
currentLabel={currentLabel}
|
|
192
|
+
onClose={() => setOpen(false)}
|
|
193
|
+
testID={testID}
|
|
155
194
|
/>
|
|
156
195
|
{options.map((option) => (
|
|
157
196
|
<ScopeRow
|
package/src/appShell/TabBar.tsx
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
import { zIndex } from "@multiplatform.one/forms";
|
|
22
22
|
import { isWeb } from "@multiplatform.one/platform";
|
|
23
23
|
import { type ComponentType, type ReactNode, useEffect, useState } from "react";
|
|
24
|
+
import type { ImageSourcePropType } from "react-native";
|
|
24
25
|
import { XStack, YStack } from "tamagui";
|
|
25
26
|
import { materials, useMaterial } from "../Material";
|
|
26
27
|
import { MaterialBlurFill } from "../Material/blur";
|
|
@@ -41,10 +42,19 @@ export interface TabBarItem {
|
|
|
41
42
|
label: string;
|
|
42
43
|
icon: TabBarIcon;
|
|
43
44
|
/**
|
|
44
|
-
* The
|
|
45
|
-
* on
|
|
45
|
+
* The glyphs the system tab bar draws (TabHost): SF Symbols on iOS, a
|
|
46
|
+
* raster template image on Android (Material's bar draws no SF Symbol or
|
|
47
|
+
* SVG; a bundled PNG, so an OTA can carry it). A platform keeps the MPO
|
|
48
|
+
* TabBar unless every item names its glyph.
|
|
46
49
|
*/
|
|
47
|
-
nativeIcon?:
|
|
50
|
+
nativeIcon?: TabBarNativeIcon;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface TabBarNativeIcon {
|
|
54
|
+
sfSymbol?: string;
|
|
55
|
+
sfSymbolSelected?: string;
|
|
56
|
+
/** A monochrome PNG (24dp, @2x and @3x beside it); the bar tints it. */
|
|
57
|
+
android?: ImageSourcePropType;
|
|
48
58
|
}
|
|
49
59
|
|
|
50
60
|
export interface TabBarProps {
|
|
@@ -16,23 +16,36 @@ import {
|
|
|
16
16
|
NativeTabHost,
|
|
17
17
|
TabHost,
|
|
18
18
|
itemsHaveNativeIcons,
|
|
19
|
+
nativeIconFor,
|
|
19
20
|
nativeTabBarHeight,
|
|
21
|
+
nativeTabsPlatforms,
|
|
20
22
|
resolveNativeTabs,
|
|
21
23
|
} from "./TabHost.native";
|
|
22
24
|
|
|
23
25
|
afterEach(cleanup);
|
|
24
26
|
|
|
25
27
|
const Glyph = () => null;
|
|
28
|
+
const png = (name: string) => ({ uri: `${name}.png`, width: 24, height: 24 });
|
|
26
29
|
|
|
27
30
|
const items: TabBarItem[] = [
|
|
28
31
|
{
|
|
29
32
|
key: "/",
|
|
30
33
|
label: "Home",
|
|
31
34
|
icon: Glyph,
|
|
32
|
-
nativeIcon: { sfSymbol: "house", sfSymbolSelected: "house.fill" },
|
|
35
|
+
nativeIcon: { sfSymbol: "house", sfSymbolSelected: "house.fill", android: png("house") },
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
key: "/pokemon",
|
|
39
|
+
label: "Pokemon",
|
|
40
|
+
icon: Glyph,
|
|
41
|
+
nativeIcon: { sfSymbol: "sparkles", android: png("sparkle") },
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
key: "/moves",
|
|
45
|
+
label: "Moves",
|
|
46
|
+
icon: Glyph,
|
|
47
|
+
nativeIcon: { sfSymbol: "bolt", android: png("lightning") },
|
|
33
48
|
},
|
|
34
|
-
{ key: "/pokemon", label: "Pokemon", icon: Glyph, nativeIcon: { sfSymbol: "sparkles" } },
|
|
35
|
-
{ key: "/moves", label: "Moves", icon: Glyph, nativeIcon: { sfSymbol: "bolt" } },
|
|
36
49
|
];
|
|
37
50
|
|
|
38
51
|
const fakeTabs: NativeTabs = {
|
|
@@ -58,7 +71,8 @@ const fakeTabs: NativeTabs = {
|
|
|
58
71
|
data-testid={`native-screen-${tabKey}`}
|
|
59
72
|
data-focused={String(Boolean(isFocused))}
|
|
60
73
|
data-inset-adjust={String(overrideScrollViewContentInsetAdjustmentBehavior)}
|
|
61
|
-
data-symbol={icon?.ios
|
|
74
|
+
data-symbol={icon?.ios?.name}
|
|
75
|
+
data-android-icon={(icon?.android?.imageSource as { uri?: string } | undefined)?.uri}
|
|
62
76
|
aria-label={title}
|
|
63
77
|
>
|
|
64
78
|
{children}
|
|
@@ -113,19 +127,49 @@ describe("native tabs detection", () => {
|
|
|
113
127
|
expect(resolveNativeTabs(sources(["RNSTabsHost", "RNSTabsScreen"], throws), "ios")).toBeNull();
|
|
114
128
|
});
|
|
115
129
|
|
|
116
|
-
it("keeps the MPO TabBar on Android and the web", () => {
|
|
130
|
+
it("keeps the MPO TabBar on Android and the web by default", () => {
|
|
117
131
|
const screens = vi.fn(() => ({ Tabs: fakeTabs }));
|
|
118
132
|
const all = sources(["RNSTabsHost", "RNSTabsScreen"], screens);
|
|
133
|
+
expect(nativeTabsPlatforms).toEqual({ ios: true, android: false });
|
|
119
134
|
expect(resolveNativeTabs(all, "android")).toBeNull();
|
|
120
135
|
expect(resolveNativeTabs(all, "web")).toBeNull();
|
|
121
136
|
expect(screens).not.toHaveBeenCalled();
|
|
122
137
|
});
|
|
123
138
|
|
|
124
|
-
it("
|
|
139
|
+
it("picks the Material bar on Android once the platform is switched on (FZ-8140)", () => {
|
|
140
|
+
const on = { ios: true, android: true };
|
|
141
|
+
expect(
|
|
142
|
+
resolveNativeTabs(
|
|
143
|
+
sources(["RNSTabsHost", "RNSTabsScreen"], () => ({ Tabs: fakeTabs })),
|
|
144
|
+
"android",
|
|
145
|
+
on,
|
|
146
|
+
),
|
|
147
|
+
).toBe(fakeTabs);
|
|
148
|
+
const screens = vi.fn(() => ({ Tabs: fakeTabs }));
|
|
149
|
+
expect(resolveNativeTabs(sources([], screens), "android", on)).toBeNull();
|
|
150
|
+
expect(screens).not.toHaveBeenCalled();
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it("needs this platform's glyph on every item: an SF Symbol on iOS, a PNG on Android", () => {
|
|
125
154
|
expect(itemsHaveNativeIcons(items)).toBe(true);
|
|
155
|
+
expect(itemsHaveNativeIcons(items, "android")).toBe(true);
|
|
126
156
|
expect(itemsHaveNativeIcons([...items, { key: "/x", label: "X", icon: Glyph }])).toBe(false);
|
|
157
|
+
const symbolsOnly = items.map(({ nativeIcon, ...item }) => ({
|
|
158
|
+
...item,
|
|
159
|
+
nativeIcon: { sfSymbol: nativeIcon?.sfSymbol },
|
|
160
|
+
}));
|
|
161
|
+
expect(itemsHaveNativeIcons(symbolsOnly, "ios")).toBe(true);
|
|
162
|
+
expect(itemsHaveNativeIcons(symbolsOnly, "android")).toBe(false);
|
|
127
163
|
expect(itemsHaveNativeIcons([])).toBe(false);
|
|
128
164
|
});
|
|
165
|
+
|
|
166
|
+
it("hands react-native-screens each platform's glyph from the one item", () => {
|
|
167
|
+
expect(nativeIconFor(items[0]!)).toEqual({
|
|
168
|
+
ios: { type: "sfSymbol", name: "house" },
|
|
169
|
+
android: { type: "imageSource", imageSource: png("house") },
|
|
170
|
+
});
|
|
171
|
+
expect(nativeIconFor({ key: "/x", label: "X", icon: Glyph })).toEqual({});
|
|
172
|
+
});
|
|
129
173
|
});
|
|
130
174
|
|
|
131
175
|
describe("NativeTabHost", () => {
|
|
@@ -136,10 +180,23 @@ describe("NativeTabHost", () => {
|
|
|
136
180
|
expect(pokemon.contains(screen.getByTestId("page"))).toBe(true);
|
|
137
181
|
expect(screen.getByTestId("native-screen-/").getAttribute("data-focused")).toBe("false");
|
|
138
182
|
expect(screen.getByTestId("native-screen-/").getAttribute("data-symbol")).toBe("house");
|
|
183
|
+
expect(screen.getByTestId("native-screen-/").getAttribute("data-android-icon")).toBe(
|
|
184
|
+
"house.png",
|
|
185
|
+
);
|
|
139
186
|
expect(screen.getByTestId("native-host").getAttribute("data-hidden")).toBe("false");
|
|
140
187
|
expect(screen.queryByTestId("tab-bar")).toBeNull();
|
|
141
188
|
});
|
|
142
189
|
|
|
190
|
+
it("paints the theme background under the routed screen, never UIKit's system one", () => {
|
|
191
|
+
renderNative("/pokemon");
|
|
192
|
+
const frame = screen.getByTestId("native-tab-screen");
|
|
193
|
+
expect(screen.getByTestId("native-screen-/pokemon").contains(frame)).toBe(true);
|
|
194
|
+
expect(frame.contains(screen.getByTestId("page"))).toBe(true);
|
|
195
|
+
expect(/_bg-background\b|background-color: var\(--background\)/.test(frame.outerHTML)).toBe(
|
|
196
|
+
true,
|
|
197
|
+
);
|
|
198
|
+
});
|
|
199
|
+
|
|
143
200
|
it("asks the app to navigate on a tab press instead of switching itself", () => {
|
|
144
201
|
const onTabPress = vi.fn();
|
|
145
202
|
renderNative("/pokemon", onTabPress);
|
|
@@ -10,9 +10,10 @@
|
|
|
10
10
|
*
|
|
11
11
|
* The native view ships in react-native-screens' binary half, so it is
|
|
12
12
|
* feature-detected before react-native-screens' Tabs is required: a binary
|
|
13
|
-
* without RNSTabsHost, a platform
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* without RNSTabsHost, a platform switched off in `nativeTabsPlatforms`, or
|
|
14
|
+
* an item without its platform's glyph keeps the MPO TabBar. Android's arm
|
|
15
|
+
* (Material bottom navigation, PNG template icons) is built and switched off
|
|
16
|
+
* until an Android build proves it (FZ-8140).
|
|
16
17
|
*
|
|
17
18
|
* The bar's clearance is the inset this host publishes, as with the MPO
|
|
18
19
|
* TabBar, so a Screen pads by it whether or not it scrolls. Each tab screen
|
|
@@ -20,9 +21,14 @@
|
|
|
20
21
|
* otherwise flip the first scroll view to `automatic`, and UIKit would add
|
|
21
22
|
* the bar's height a second time (FZ-8640).
|
|
22
23
|
*/
|
|
23
|
-
import {
|
|
24
|
+
import {
|
|
25
|
+
useAccentTintedSurface,
|
|
26
|
+
useGlyphColor,
|
|
27
|
+
useIdentityInkOnSurface,
|
|
28
|
+
} from "@multiplatform.one/theme";
|
|
24
29
|
import { type ComponentType, type ReactNode, useEffect, useRef, useState } from "react";
|
|
25
|
-
import { Platform, UIManager } from "react-native";
|
|
30
|
+
import { type ImageSourcePropType, Platform, UIManager } from "react-native";
|
|
31
|
+
import { YStack } from "tamagui";
|
|
26
32
|
import { setBottomChromeInset } from "./bottomChrome";
|
|
27
33
|
import { useBottomInset } from "./bottomInset";
|
|
28
34
|
import { type TabBarItem, tabBarInactiveInk } from "./TabBar";
|
|
@@ -36,7 +42,17 @@ export const nativeTabsComponents = ["RNSTabsHost", "RNSTabsScreen"] as const;
|
|
|
36
42
|
/** Points the system tab bar covers above the home-indicator band. */
|
|
37
43
|
export const nativeTabBarHeight = 49;
|
|
38
44
|
|
|
39
|
-
type
|
|
45
|
+
type ImageIcon = { type: "imageSource"; imageSource: ImageSourcePropType };
|
|
46
|
+
type IconProp = { ios?: { type: "sfSymbol"; name: string }; android?: ImageIcon };
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The platforms whose system tab bar TabHost draws. Android stays off until
|
|
50
|
+
* an emulator build shows the Material bar in light and dark (FZ-8140).
|
|
51
|
+
*/
|
|
52
|
+
export const nativeTabsPlatforms: Readonly<Record<string, boolean>> = {
|
|
53
|
+
ios: true,
|
|
54
|
+
android: false,
|
|
55
|
+
};
|
|
40
56
|
|
|
41
57
|
export interface NativeTabs {
|
|
42
58
|
Host: ComponentType<{
|
|
@@ -47,6 +63,8 @@ export interface NativeTabs {
|
|
|
47
63
|
tabBarItemIconColorActive?: string;
|
|
48
64
|
tabBarItemTitleFontColor?: string;
|
|
49
65
|
tabBarItemTitleFontColorActive?: string;
|
|
66
|
+
tabBarBackgroundColor?: string;
|
|
67
|
+
tabBarItemActiveIndicatorColor?: string;
|
|
50
68
|
experimentalControlNavigationStateInJS?: boolean;
|
|
51
69
|
onNativeFocusChange?: (event: { nativeEvent: { tabKey: string } }) => void;
|
|
52
70
|
}>;
|
|
@@ -56,7 +74,7 @@ export interface NativeTabs {
|
|
|
56
74
|
title?: string;
|
|
57
75
|
isFocused?: boolean;
|
|
58
76
|
icon?: IconProp;
|
|
59
|
-
selectedIcon?:
|
|
77
|
+
selectedIcon?: { type: "sfSymbol"; name: string };
|
|
60
78
|
tabBarItemAccessibilityLabel?: string;
|
|
61
79
|
tabBarItemTestID?: string;
|
|
62
80
|
overrideScrollViewContentInsetAdjustmentBehavior?: boolean;
|
|
@@ -74,8 +92,12 @@ const appSources: NativeTabsSources = {
|
|
|
74
92
|
};
|
|
75
93
|
|
|
76
94
|
/** react-native-screens' Tabs, or null when this platform or binary cannot draw them. */
|
|
77
|
-
export function resolveNativeTabs(
|
|
78
|
-
|
|
95
|
+
export function resolveNativeTabs(
|
|
96
|
+
sources: NativeTabsSources,
|
|
97
|
+
os: string,
|
|
98
|
+
platforms: Readonly<Record<string, boolean>> = nativeTabsPlatforms,
|
|
99
|
+
): NativeTabs | null {
|
|
100
|
+
if (!platforms[os]) return null;
|
|
79
101
|
try {
|
|
80
102
|
if (!nativeTabsComponents.every((name) => sources.hasComponent(name))) return null;
|
|
81
103
|
const tabs = sources.screens().Tabs;
|
|
@@ -92,9 +114,20 @@ function loadNativeTabs(): NativeTabs | null {
|
|
|
92
114
|
return cached;
|
|
93
115
|
}
|
|
94
116
|
|
|
95
|
-
/** True when every item names the
|
|
96
|
-
export function itemsHaveNativeIcons(items: readonly TabBarItem[]): boolean {
|
|
97
|
-
|
|
117
|
+
/** True when every item names the glyph this platform's system bar draws. */
|
|
118
|
+
export function itemsHaveNativeIcons(items: readonly TabBarItem[], os = "ios"): boolean {
|
|
119
|
+
const glyph = (item: TabBarItem) =>
|
|
120
|
+
os === "android" ? item.nativeIcon?.android : item.nativeIcon?.sfSymbol;
|
|
121
|
+
return items.length > 0 && items.every((item) => Boolean(glyph(item)));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** The item's glyphs in react-native-screens' per-platform icon shape. */
|
|
125
|
+
export function nativeIconFor(item: TabBarItem): IconProp {
|
|
126
|
+
const { sfSymbol, android } = item.nativeIcon ?? {};
|
|
127
|
+
return {
|
|
128
|
+
...(sfSymbol ? { ios: { type: "sfSymbol" as const, name: sfSymbol } } : {}),
|
|
129
|
+
...(android ? { android: { type: "imageSource" as const, imageSource: android } } : {}),
|
|
130
|
+
};
|
|
98
131
|
}
|
|
99
132
|
|
|
100
133
|
export function NativeTabHost({
|
|
@@ -107,6 +140,8 @@ export function NativeTabHost({
|
|
|
107
140
|
const { Host, Screen } = tabs;
|
|
108
141
|
const accent = useIdentityInkOnSurface();
|
|
109
142
|
const ink = useGlyphColor(tabBarInactiveInk);
|
|
143
|
+
const surface = useGlyphColor("$color2");
|
|
144
|
+
const indicator = useAccentTintedSurface();
|
|
110
145
|
const deviceInset = useBottomInset();
|
|
111
146
|
const [id] = useState(() => Symbol("native-tab-host"));
|
|
112
147
|
const lastKey = useRef(activeKey ?? items[0]?.key);
|
|
@@ -126,6 +161,8 @@ export function NativeTabHost({
|
|
|
126
161
|
tabBarItemIconColorActive={accent}
|
|
127
162
|
tabBarItemTitleFontColor={ink}
|
|
128
163
|
tabBarItemTitleFontColorActive={accent}
|
|
164
|
+
tabBarBackgroundColor={surface}
|
|
165
|
+
tabBarItemActiveIndicatorColor={indicator}
|
|
129
166
|
experimentalControlNavigationStateInJS
|
|
130
167
|
onNativeFocusChange={(event) => {
|
|
131
168
|
const key = event.nativeEvent.tabKey;
|
|
@@ -138,7 +175,7 @@ export function NativeTabHost({
|
|
|
138
175
|
tabKey={item.key}
|
|
139
176
|
title={item.label}
|
|
140
177
|
isFocused={item.key === focusedKey}
|
|
141
|
-
icon={
|
|
178
|
+
icon={nativeIconFor(item)}
|
|
142
179
|
selectedIcon={
|
|
143
180
|
item.nativeIcon?.sfSymbolSelected
|
|
144
181
|
? { type: "sfSymbol", name: item.nativeIcon.sfSymbolSelected }
|
|
@@ -148,7 +185,11 @@ export function NativeTabHost({
|
|
|
148
185
|
tabBarItemTestID={`tab-bar-item-${item.key.replace(/^\/+/, "") || "root"}`}
|
|
149
186
|
overrideScrollViewContentInsetAdjustmentBehavior={false}
|
|
150
187
|
>
|
|
151
|
-
{item.key === focusedKey ?
|
|
188
|
+
{item.key === focusedKey ? (
|
|
189
|
+
<YStack flex={1} backgroundColor="$background" data-testid="native-tab-screen">
|
|
190
|
+
{children}
|
|
191
|
+
</YStack>
|
|
192
|
+
) : null}
|
|
152
193
|
</Screen>
|
|
153
194
|
))}
|
|
154
195
|
</Host>
|
|
@@ -157,6 +198,6 @@ export function NativeTabHost({
|
|
|
157
198
|
|
|
158
199
|
export function TabHost(props: TabHostProps) {
|
|
159
200
|
const tabs = loadNativeTabs();
|
|
160
|
-
if (!tabs || !itemsHaveNativeIcons(props.items)) return <MpoTabHost {...props} />;
|
|
201
|
+
if (!tabs || !itemsHaveNativeIcons(props.items, Platform.OS)) return <MpoTabHost {...props} />;
|
|
161
202
|
return <NativeTabHost tabs={tabs} {...props} />;
|
|
162
203
|
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react-native-web-vite";
|
|
2
|
+
import { HouseIcon, LightningIcon, SparkleIcon, SquaresFourIcon } from "@phosphor-icons/react";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { Screen } from "../layouts/page";
|
|
5
|
+
import { Text } from "../Text";
|
|
6
|
+
import type { TabBarItem } from "./TabBar";
|
|
7
|
+
import { TabHost } from "./TabHost";
|
|
8
|
+
|
|
9
|
+
const meta: Meta<typeof TabHost> = {
|
|
10
|
+
title: "Components/TabHost",
|
|
11
|
+
component: TabHost,
|
|
12
|
+
parameters: { status: { type: "beta" }, layout: "fullscreen" },
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default meta;
|
|
16
|
+
type Story = StoryObj<typeof TabHost>;
|
|
17
|
+
|
|
18
|
+
const items: TabBarItem[] = [
|
|
19
|
+
{
|
|
20
|
+
key: "/",
|
|
21
|
+
label: "Home",
|
|
22
|
+
icon: HouseIcon,
|
|
23
|
+
nativeIcon: { sfSymbol: "house", sfSymbolSelected: "house.fill" },
|
|
24
|
+
},
|
|
25
|
+
{ key: "/pokemon", label: "Pokemon", icon: SparkleIcon, nativeIcon: { sfSymbol: "sparkles" } },
|
|
26
|
+
{
|
|
27
|
+
key: "/moves",
|
|
28
|
+
label: "Moves",
|
|
29
|
+
icon: LightningIcon,
|
|
30
|
+
nativeIcon: { sfSymbol: "bolt", sfSymbolSelected: "bolt.fill" },
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
key: "/backoffice",
|
|
34
|
+
label: "Backoffice",
|
|
35
|
+
icon: SquaresFourIcon,
|
|
36
|
+
nativeIcon: { sfSymbol: "square.grid.2x2", sfSymbolSelected: "square.grid.2x2.fill" },
|
|
37
|
+
},
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
const rows = Array.from({ length: 30 }, (_, index) => `Row ${index + 1}`);
|
|
41
|
+
|
|
42
|
+
function Sections({ initial, outside }: { initial: string; outside?: boolean }) {
|
|
43
|
+
const [active, setActive] = useState(initial);
|
|
44
|
+
const label = items.find((item) => item.key === active)?.label;
|
|
45
|
+
return (
|
|
46
|
+
<TabHost items={items} activeKey={outside ? undefined : active} onTabPress={setActive}>
|
|
47
|
+
<Screen>
|
|
48
|
+
<Text>{outside ? "A route under no tab" : label}</Text>
|
|
49
|
+
{rows.map((row) => (
|
|
50
|
+
<Text key={row}>{row}</Text>
|
|
51
|
+
))}
|
|
52
|
+
</Screen>
|
|
53
|
+
</TabHost>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* One tab config: the system tab bar on an iPhone whose binary carries
|
|
59
|
+
* native tabs, the MPO floating TabBar on the web, GNOME, Android and an
|
|
60
|
+
* older binary.
|
|
61
|
+
*/
|
|
62
|
+
export const Default: Story = {
|
|
63
|
+
render: () => <Sections initial="/pokemon" />,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* A route under no tab (no `activeKey`): no bar on any platform, and the
|
|
68
|
+
* screen keeps its place. AppShell keeps the bar on routes below a tab.
|
|
69
|
+
*/
|
|
70
|
+
export const OutsideTabs: Story = {
|
|
71
|
+
render: () => <Sections initial="/pokemon" outside />,
|
|
72
|
+
};
|