@multiplatform.one/components 7.29.1 → 7.30.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/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 +2 -2
- package/dist/cjs/Carousel/index.native.js.map +1 -1
- package/dist/cjs/Chip/index.native.js.map +1 -1
- package/dist/cjs/Collapsible.native.js.map +1 -1
- package/dist/cjs/ContextMenu/index.native.js.map +1 -1
- package/dist/cjs/CopyField/index.native.js.map +1 -1
- package/dist/cjs/Dialog.cjs +84 -0
- package/dist/cjs/Dialog.native.js +92 -0
- package/dist/cjs/Dialog.native.js.map +1 -0
- package/dist/cjs/DotIndicator/index.native.js.map +1 -1
- package/dist/cjs/DropdownMenu/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/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/Pagination.native.js +1 -1
- package/dist/cjs/Pagination.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/Separator/index.native.js.map +1 -1
- package/dist/cjs/SheetModal/detents.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/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/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.native.js +1 -1
- 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/DestructiveAction.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/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/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.cjs +288 -0
- package/dist/cjs/code/Highlighter/houseSyntaxTheme.native.js +291 -0
- package/dist/cjs/code/Highlighter/houseSyntaxTheme.native.js.map +1 -0
- package/dist/cjs/code/Highlighter/index.cjs +6 -6
- package/dist/cjs/code/Highlighter/index.native.js +6 -6
- package/dist/cjs/code/Highlighter/index.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/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/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/index.native.js +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 +30 -30
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/knobImmuneExports.cjs +0 -2
- package/dist/cjs/knobImmuneExports.native.js +0 -2
- 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/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/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/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 +1 -1
- package/dist/cjs/layouts/page.native.js.map +1 -1
- package/dist/cjs/layouts/pageHeadingScope.native.js.map +1 -1
- package/dist/cjs/layouts/sidebar.native.js +1 -1
- 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/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.cjs +3 -2
- package/dist/cjs/tamagui.native.js +4 -3
- 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/ImageGrid.native.js +1 -1
- 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/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/TreeView.native.js.map +1 -1
- package/dist/cjs/views/calendarMath.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/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/esm/Dialog.mjs +58 -0
- package/dist/esm/Dialog.mjs.map +1 -0
- package/dist/esm/Dialog.native.js +63 -0
- package/dist/esm/Dialog.native.js.map +1 -0
- package/dist/esm/code/Highlighter/houseSyntaxTheme.mjs +263 -0
- package/dist/esm/code/Highlighter/houseSyntaxTheme.mjs.map +1 -0
- package/dist/esm/code/Highlighter/houseSyntaxTheme.native.js +263 -0
- package/dist/esm/code/Highlighter/houseSyntaxTheme.native.js.map +1 -0
- package/dist/esm/code/Highlighter/index.mjs +5 -6
- package/dist/esm/code/Highlighter/index.mjs.map +1 -1
- package/dist/esm/code/Highlighter/index.native.js +5 -6
- package/dist/esm/code/Highlighter/index.native.js.map +1 -1
- package/dist/esm/knobImmuneExports.mjs +0 -2
- package/dist/esm/knobImmuneExports.mjs.map +1 -1
- package/dist/esm/knobImmuneExports.native.js +0 -2
- package/dist/esm/knobImmuneExports.native.js.map +1 -1
- package/dist/esm/tamagui.mjs +2 -1
- package/dist/esm/tamagui.mjs.map +1 -1
- package/dist/esm/tamagui.native.js +2 -1
- package/dist/esm/tamagui.native.js.map +1 -1
- package/dist/jsx/Accordion/index.native.js +1 -1
- package/dist/jsx/Accordion/index.native.js.map +1 -1
- package/dist/jsx/Alert/index.native.js.map +1 -1
- package/dist/jsx/AnimateHeight/index.native.js.map +1 -1
- package/dist/jsx/Avatar/getInitials.native.js.map +1 -1
- package/dist/jsx/Avatar/index.native.js.map +1 -1
- package/dist/jsx/Badge/index.native.js.map +1 -1
- package/dist/jsx/Button.native.js.map +1 -1
- package/dist/jsx/Card.native.js.map +1 -1
- package/dist/jsx/CardFooter.native.js.map +1 -1
- package/dist/jsx/CardHeader.native.js.map +1 -1
- package/dist/jsx/Carousel/index.native.js +2 -2
- package/dist/jsx/Carousel/index.native.js.map +1 -1
- package/dist/jsx/Chip/index.native.js.map +1 -1
- package/dist/jsx/Collapsible.native.js.map +1 -1
- package/dist/jsx/ContextMenu/index.native.js.map +1 -1
- package/dist/jsx/CopyField/index.native.js.map +1 -1
- package/dist/jsx/Dialog.mjs +58 -0
- package/dist/jsx/Dialog.mjs.map +1 -0
- package/dist/jsx/Dialog.native.js +92 -0
- package/dist/jsx/Dialog.native.js.map +1 -0
- package/dist/jsx/DotIndicator/index.native.js.map +1 -1
- package/dist/jsx/DropdownMenu/index.native.js.map +1 -1
- package/dist/jsx/ErrorBoundary/index.native.js.map +1 -1
- package/dist/jsx/Heading.native.js.map +1 -1
- package/dist/jsx/Meter/index.native.js +1 -1
- package/dist/jsx/Meter/index.native.js.map +1 -1
- package/dist/jsx/Meter/meter.native.js.map +1 -1
- package/dist/jsx/Pagination.native.js +1 -1
- package/dist/jsx/Pagination.native.js.map +1 -1
- package/dist/jsx/ProgressSteps/index.native.js.map +1 -1
- package/dist/jsx/Quote/index.native.js.map +1 -1
- package/dist/jsx/Separator/index.native.js.map +1 -1
- package/dist/jsx/SheetModal/detents.native.js.map +1 -1
- package/dist/jsx/Skeleton/index.native.js.map +1 -1
- package/dist/jsx/SkipLink/index.native.js.map +1 -1
- package/dist/jsx/SortableList/SortableHandle.native.js.map +1 -1
- package/dist/jsx/SortableList/index.native.js.map +1 -1
- package/dist/jsx/SortableList/useSortableRows.native.js.map +1 -1
- package/dist/jsx/Tabs/index.native.js +1 -1
- package/dist/jsx/Tabs/index.native.js.map +1 -1
- package/dist/jsx/Text.native.js.map +1 -1
- package/dist/jsx/Toast/index.native.js.map +1 -1
- package/dist/jsx/Toast/store.native.js.map +1 -1
- package/dist/jsx/Tooltip/nativePress.native.js.map +1 -1
- package/dist/jsx/Tooltip/tooltipShared.native.js.map +1 -1
- package/dist/jsx/TreeSelect/index.native.js +1 -1
- package/dist/jsx/TreeSelect/index.native.js.map +1 -1
- package/dist/jsx/TreeSelect/treeSelectModel.native.js.map +1 -1
- package/dist/jsx/Video/PlayerChrome.native.js.map +1 -1
- package/dist/jsx/Video/VideoFrame.native.js.map +1 -1
- package/dist/jsx/Video/types.native.js.map +1 -1
- package/dist/jsx/Wheel/index.native.js.map +1 -1
- package/dist/jsx/Wizard/index.native.js +2 -2
- package/dist/jsx/Wizard/index.native.js.map +1 -1
- package/dist/jsx/actions/ActionBar.native.js.map +1 -1
- package/dist/jsx/actions/DestructiveAction.native.js.map +1 -1
- package/dist/jsx/actions/devWarn.native.js.map +1 -1
- package/dist/jsx/actions/index.native.js.map +1 -1
- package/dist/jsx/actions/severity.native.js.map +1 -1
- package/dist/jsx/charts/Axis.native.js.map +1 -1
- package/dist/jsx/charts/BarChart.native.js.map +1 -1
- package/dist/jsx/charts/ChartDataView.native.js +1 -1
- package/dist/jsx/charts/ChartDataView.native.js.map +1 -1
- package/dist/jsx/charts/ChartSurface.native.js.map +1 -1
- package/dist/jsx/charts/LineChart.native.js.map +1 -1
- package/dist/jsx/charts/PieChart.native.js.map +1 -1
- package/dist/jsx/charts/Sparkline.native.js.map +1 -1
- package/dist/jsx/charts/accessibility.native.js.map +1 -1
- package/dist/jsx/charts/composeChart.native.js.map +1 -1
- package/dist/jsx/charts/index.native.js.map +1 -1
- package/dist/jsx/charts/math.native.js.map +1 -1
- package/dist/jsx/charts/series.native.js.map +1 -1
- package/dist/jsx/charts/svg.native.js.map +1 -1
- package/dist/jsx/charts/types.native.js.map +1 -1
- package/dist/jsx/charts/useChartTheme.native.js.map +1 -1
- package/dist/jsx/code/Code/index.native.js.map +1 -1
- package/dist/jsx/code/CodeBlock/index.native.js +7 -7
- package/dist/jsx/code/CodeBlock/index.native.js.map +1 -1
- package/dist/jsx/code/HighlightedCode/index.native.js.map +1 -1
- package/dist/jsx/code/Highlighter/houseSyntaxTheme.mjs +263 -0
- package/dist/jsx/code/Highlighter/houseSyntaxTheme.mjs.map +1 -0
- package/dist/jsx/code/Highlighter/houseSyntaxTheme.native.js +291 -0
- package/dist/jsx/code/Highlighter/houseSyntaxTheme.native.js.map +1 -0
- package/dist/jsx/code/Highlighter/index.mjs +5 -6
- package/dist/jsx/code/Highlighter/index.mjs.map +1 -1
- package/dist/jsx/code/Highlighter/index.native.js +6 -6
- package/dist/jsx/code/Highlighter/index.native.js.map +1 -1
- package/dist/jsx/code/Pre/index.native.js.map +1 -1
- package/dist/jsx/code/index.native.js +5 -5
- package/dist/jsx/code/index.native.js.map +1 -1
- package/dist/jsx/componentColors.native.js.map +1 -1
- package/dist/jsx/feedback/ConfirmDialog.native.js.map +1 -1
- package/dist/jsx/feedback/NotifyHost.native.js +2 -2
- package/dist/jsx/feedback/NotifyHost.native.js.map +1 -1
- package/dist/jsx/feedback/copy.native.js.map +1 -1
- package/dist/jsx/feedback/index.native.js.map +1 -1
- package/dist/jsx/feedback/notify.native.js.map +1 -1
- package/dist/jsx/feedback/route.native.js.map +1 -1
- package/dist/jsx/feedback/store.native.js.map +1 -1
- package/dist/jsx/hooks/index.native.js +1 -1
- package/dist/jsx/hooks/index.native.js.map +1 -1
- package/dist/jsx/hooks/useClipboard.native.js.map +1 -1
- package/dist/jsx/hooks/useDocumentTitle.native.js.map +1 -1
- package/dist/jsx/icons/CheckRegular.native.js.map +1 -1
- package/dist/jsx/icons/MinusRegular.native.js.map +1 -1
- package/dist/jsx/icons/index.native.js.map +1 -1
- package/dist/jsx/icons/lucide.native.js.map +1 -1
- package/dist/jsx/icons/themed.native.js.map +1 -1
- package/dist/jsx/images/Image/ImageFrame.native.js +1 -1
- package/dist/jsx/images/Image/ImageFrame.native.js.map +1 -1
- package/dist/jsx/images/Image/index.native.js +1 -1
- package/dist/jsx/images/Image/shared.native.js +1 -1
- package/dist/jsx/images/Image/shared.native.js.map +1 -1
- package/dist/jsx/images/Image/types.native.js.map +1 -1
- package/dist/jsx/images/index.native.js.map +1 -1
- package/dist/jsx/index.native.js +30 -30
- package/dist/jsx/index.native.js.map +1 -1
- package/dist/jsx/knobImmuneExports.mjs +0 -2
- package/dist/jsx/knobImmuneExports.mjs.map +1 -1
- package/dist/jsx/knobImmuneExports.native.js +0 -2
- package/dist/jsx/knobImmuneExports.native.js.map +1 -1
- package/dist/jsx/layouts/AsyncBoundary.native.js +2 -2
- package/dist/jsx/layouts/AsyncBoundary.native.js.map +1 -1
- package/dist/jsx/layouts/Debug/index.native.js.map +1 -1
- package/dist/jsx/layouts/EmptyState.native.js.map +1 -1
- package/dist/jsx/layouts/KeyboardAvoidingWrapper/behavior.native.js.map +1 -1
- package/dist/jsx/layouts/PageTemplates.native.js.map +1 -1
- package/dist/jsx/layouts/PaneScaffold.native.js.map +1 -1
- package/dist/jsx/layouts/SafeAreaWrapper/insets.native.js.map +1 -1
- package/dist/jsx/layouts/ViewSwitcher.native.js.map +1 -1
- package/dist/jsx/layouts/attachments.native.js +1 -1
- package/dist/jsx/layouts/attachments.native.js.map +1 -1
- package/dist/jsx/layouts/breadcrumbs.native.js.map +1 -1
- package/dist/jsx/layouts/index.native.js +3 -3
- package/dist/jsx/layouts/index.native.js.map +1 -1
- package/dist/jsx/layouts/page.native.js +1 -1
- package/dist/jsx/layouts/page.native.js.map +1 -1
- package/dist/jsx/layouts/pageHeadingScope.native.js.map +1 -1
- package/dist/jsx/layouts/sidebar.native.js +1 -1
- package/dist/jsx/layouts/sidebar.native.js.map +1 -1
- package/dist/jsx/layouts/tags.native.js +2 -2
- package/dist/jsx/layouts/tags.native.js.map +1 -1
- package/dist/jsx/layouts/timeline.native.js +2 -2
- package/dist/jsx/layouts/timeline.native.js.map +1 -1
- package/dist/jsx/layouts/toolbar.native.js +1 -1
- package/dist/jsx/layouts/toolbar.native.js.map +1 -1
- package/dist/jsx/shared/actionScan.native.js.map +1 -1
- package/dist/jsx/shared/i18n.native.js.map +1 -1
- package/dist/jsx/shared/t.native.js.map +1 -1
- package/dist/jsx/shared/textRidesText.native.js.map +1 -1
- package/dist/jsx/shared/useReturnFocusOnClose.native.js.map +1 -1
- package/dist/jsx/surfaces.native.js +1 -1
- package/dist/jsx/surfaces.native.js.map +1 -1
- package/dist/jsx/tamagui.mjs +2 -1
- package/dist/jsx/tamagui.mjs.map +1 -1
- package/dist/jsx/tamagui.native.js +4 -3
- package/dist/jsx/tamagui.native.js.map +1 -1
- package/dist/jsx/testSetup.native.js.map +1 -1
- package/dist/jsx/utils/setTinted.native.js.map +1 -1
- package/dist/jsx/utils/unwrapText.native.js.map +1 -1
- package/dist/jsx/views/Calendar.native.js +1 -1
- package/dist/jsx/views/Calendar.native.js.map +1 -1
- package/dist/jsx/views/Dashboard.native.js +2 -2
- package/dist/jsx/views/Dashboard.native.js.map +1 -1
- package/dist/jsx/views/Gantt.native.js +2 -2
- package/dist/jsx/views/Gantt.native.js.map +1 -1
- package/dist/jsx/views/ImageGrid.native.js +1 -1
- package/dist/jsx/views/ImageGrid.native.js.map +1 -1
- package/dist/jsx/views/Kanban.native.js +1 -1
- package/dist/jsx/views/List.native.js.map +1 -1
- package/dist/jsx/views/Matrix.native.js +2 -2
- package/dist/jsx/views/Matrix.native.js.map +1 -1
- package/dist/jsx/views/ReportBuilder.native.js +2 -2
- package/dist/jsx/views/ReportBuilder.native.js.map +1 -1
- package/dist/jsx/views/TreeView.native.js.map +1 -1
- package/dist/jsx/views/calendarMath.native.js.map +1 -1
- package/dist/jsx/views/ganttMath.native.js.map +1 -1
- package/dist/jsx/views/index.native.js +1 -1
- package/dist/jsx/views/index.native.js.map +1 -1
- package/dist/jsx/views/kanbanDnd.native.js.map +1 -1
- package/dist/jsx/views/matrixMath.native.js.map +1 -1
- package/dist/jsx/views/treeViewDnd.native.js.map +1 -1
- package/dist/jsx/views/treeViewLayout.native.js.map +1 -1
- package/dist/jsx/views/treeViewMotion.native.js.map +1 -1
- package/dist/jsx/views/treeViewReveal.native.js.map +1 -1
- package/package.json +9 -9
- package/src/AlertDialogContent.stories.tsx +2 -1
- package/src/Dialog.spec.tsx +165 -0
- package/src/Dialog.tsx +80 -0
- package/src/DialogContent.stories.tsx +2 -1
- package/src/code/HighlightedCode/HighlightedCode.stories.tsx +18 -42
- package/src/code/Highlighter/houseSyntaxTheme.spec.ts +77 -0
- package/src/code/Highlighter/houseSyntaxTheme.ts +151 -0
- package/src/code/Highlighter/index.ts +7 -8
- package/src/code/syntaxInk.spec.tsx +50 -0
- package/src/knobImmuneExports.ts +0 -3
- package/src/tamagui.spec.ts +5 -4
- package/src/tamagui.ts +4 -1
- package/types/Dialog.d.ts +4 -0
- package/types/Dialog.d.ts.map +1 -0
- package/types/code/Highlighter/houseSyntaxTheme.d.ts +23 -0
- package/types/code/Highlighter/houseSyntaxTheme.d.ts.map +1 -0
- package/types/code/Highlighter/index.d.ts +2 -0
- package/types/code/Highlighter/index.d.ts.map +1 -1
- package/types/knobImmuneExports.d.ts.map +1 -1
- package/types/tamagui.d.ts +2 -1
- package/types/tamagui.d.ts.map +1 -1
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
2
|
+
import { X } from "@tamagui/lucide-icons-2";
|
|
3
|
+
import { cleanup, fireEvent, screen, waitFor } from "@testing-library/react";
|
|
4
|
+
import type { ReactNode } from "react";
|
|
5
|
+
import { AlertDialog as TamaguiAlertDialog, Dialog as TamaguiDialog } from "tamagui";
|
|
6
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
7
|
+
import { AlertDialog, Button, Dialog } from "./index";
|
|
8
|
+
|
|
9
|
+
const catalog = vi.hoisted(() => ({ current: {} as Record<string, string> }));
|
|
10
|
+
|
|
11
|
+
vi.mock("./shared/i18n", () => ({
|
|
12
|
+
useTranslation: () => ({ t: (key: string) => catalog.current[key] ?? key }),
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
cleanup();
|
|
17
|
+
catalog.current = {};
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
function OpenDialog({ children }: { children: ReactNode }) {
|
|
21
|
+
return (
|
|
22
|
+
<Dialog open>
|
|
23
|
+
<Dialog.Portal>
|
|
24
|
+
<Dialog.Content>
|
|
25
|
+
<Dialog.Title>Edit profile</Dialog.Title>
|
|
26
|
+
{children}
|
|
27
|
+
</Dialog.Content>
|
|
28
|
+
</Dialog.Portal>
|
|
29
|
+
</Dialog>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function OpenAlertDialog({ children }: { children: ReactNode }) {
|
|
34
|
+
return (
|
|
35
|
+
<AlertDialog open>
|
|
36
|
+
<AlertDialog.Portal>
|
|
37
|
+
<AlertDialog.Content>
|
|
38
|
+
<AlertDialog.Title>Delete account?</AlertDialog.Title>
|
|
39
|
+
{children}
|
|
40
|
+
</AlertDialog.Content>
|
|
41
|
+
</AlertDialog.Portal>
|
|
42
|
+
</AlertDialog>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const noDialogClose = () =>
|
|
47
|
+
expect(screen.queryAllByRole("button", { name: "Dialog Close" })).toHaveLength(0);
|
|
48
|
+
|
|
49
|
+
describe("house Dialog.Close is named by what it shows (MPO-476)", () => {
|
|
50
|
+
it("keeps each asChild button's visible label as its accessible name", () => {
|
|
51
|
+
renderWithProviders(
|
|
52
|
+
<OpenDialog>
|
|
53
|
+
<Dialog.Close asChild>
|
|
54
|
+
<Button>Cancel</Button>
|
|
55
|
+
</Dialog.Close>
|
|
56
|
+
<Dialog.Close asChild>
|
|
57
|
+
<Button theme="accent">Save changes</Button>
|
|
58
|
+
</Dialog.Close>
|
|
59
|
+
</OpenDialog>,
|
|
60
|
+
);
|
|
61
|
+
expect(screen.getByRole("button", { name: "Cancel" })).toBeTruthy();
|
|
62
|
+
expect(screen.getByRole("button", { name: "Save changes" })).toBeTruthy();
|
|
63
|
+
noDialogClose();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("names a bare close with text by that text", () => {
|
|
67
|
+
renderWithProviders(
|
|
68
|
+
<OpenDialog>
|
|
69
|
+
<Dialog.Close>Done</Dialog.Close>
|
|
70
|
+
</OpenDialog>,
|
|
71
|
+
);
|
|
72
|
+
expect(screen.getByRole("button", { name: "Done" })).toBeTruthy();
|
|
73
|
+
noDialogClose();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("gives an icon-only close the localized Close", () => {
|
|
77
|
+
catalog.current = { Close: "మూసివేయి" };
|
|
78
|
+
renderWithProviders(
|
|
79
|
+
<OpenDialog>
|
|
80
|
+
<Dialog.Close asChild>
|
|
81
|
+
<Button circular icon={X} />
|
|
82
|
+
</Dialog.Close>
|
|
83
|
+
<Dialog.Close>
|
|
84
|
+
<X />
|
|
85
|
+
</Dialog.Close>
|
|
86
|
+
</OpenDialog>,
|
|
87
|
+
);
|
|
88
|
+
expect(screen.getAllByRole("button", { name: "మూసివేయి" })).toHaveLength(2);
|
|
89
|
+
noDialogClose();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("keeps an explicit label on the part or its child", () => {
|
|
93
|
+
renderWithProviders(
|
|
94
|
+
<OpenDialog>
|
|
95
|
+
<Dialog.Close asChild>
|
|
96
|
+
<Button circular icon={X} aria-label="Close dialog" />
|
|
97
|
+
</Dialog.Close>
|
|
98
|
+
<Dialog.Close aria-label="Dismiss">
|
|
99
|
+
<X />
|
|
100
|
+
</Dialog.Close>
|
|
101
|
+
</OpenDialog>,
|
|
102
|
+
);
|
|
103
|
+
expect(screen.getByRole("button", { name: "Close dialog" })).toBeTruthy();
|
|
104
|
+
expect(screen.getByRole("button", { name: "Dismiss" })).toBeTruthy();
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("still closes the dialog", async () => {
|
|
108
|
+
renderWithProviders(
|
|
109
|
+
<Dialog defaultOpen>
|
|
110
|
+
<Dialog.Portal>
|
|
111
|
+
<Dialog.Content>
|
|
112
|
+
<Dialog.Title>Edit profile</Dialog.Title>
|
|
113
|
+
<Dialog.Close asChild>
|
|
114
|
+
<Button>Cancel</Button>
|
|
115
|
+
</Dialog.Close>
|
|
116
|
+
</Dialog.Content>
|
|
117
|
+
</Dialog.Portal>
|
|
118
|
+
</Dialog>,
|
|
119
|
+
);
|
|
120
|
+
fireEvent.click(screen.getByRole("button", { name: "Cancel" }));
|
|
121
|
+
await waitFor(() => expect(screen.queryByText("Edit profile")).toBeNull());
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("changes only Close; every other part is tamagui's", () => {
|
|
125
|
+
expect(Dialog.Close).not.toBe(TamaguiDialog.Close);
|
|
126
|
+
for (const part of ["Trigger", "Portal", "Overlay", "Content", "Title", "Description"]) {
|
|
127
|
+
expect(Dialog[part as keyof typeof Dialog]).toBe(
|
|
128
|
+
TamaguiDialog[part as keyof typeof TamaguiDialog],
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
describe("house AlertDialog Cancel and Action are named by what they show (MPO-476)", () => {
|
|
135
|
+
it("keeps each asChild button's visible label as its accessible name", () => {
|
|
136
|
+
renderWithProviders(
|
|
137
|
+
<OpenAlertDialog>
|
|
138
|
+
<AlertDialog.Cancel asChild>
|
|
139
|
+
<Button>Cancel</Button>
|
|
140
|
+
</AlertDialog.Cancel>
|
|
141
|
+
<AlertDialog.Action asChild>
|
|
142
|
+
<Button theme="error">Yes, delete</Button>
|
|
143
|
+
</AlertDialog.Action>
|
|
144
|
+
<AlertDialog.Destructive asChild>
|
|
145
|
+
<Button theme="error">Delete forever</Button>
|
|
146
|
+
</AlertDialog.Destructive>
|
|
147
|
+
</OpenAlertDialog>,
|
|
148
|
+
);
|
|
149
|
+
expect(screen.getByRole("button", { name: "Cancel" })).toBeTruthy();
|
|
150
|
+
expect(screen.getByRole("button", { name: "Yes, delete" })).toBeTruthy();
|
|
151
|
+
expect(screen.getByRole("button", { name: "Delete forever" })).toBeTruthy();
|
|
152
|
+
noDialogClose();
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("changes only the close parts; every other part is tamagui's", () => {
|
|
156
|
+
for (const part of ["Cancel", "Action", "Destructive"] as const) {
|
|
157
|
+
expect(AlertDialog[part]).not.toBe(TamaguiAlertDialog[part]);
|
|
158
|
+
}
|
|
159
|
+
for (const part of ["Trigger", "Portal", "Overlay", "Content", "Title", "Description"]) {
|
|
160
|
+
expect(AlertDialog[part as keyof typeof AlertDialog]).toBe(
|
|
161
|
+
TamaguiAlertDialog[part as keyof typeof TamaguiAlertDialog],
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
});
|
package/src/Dialog.tsx
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* House Dialog and AlertDialog: the tamagui roots with their close parts named
|
|
3
|
+
* by what they show (MPO-476).
|
|
4
|
+
*
|
|
5
|
+
* tamagui 2.7's Dialog.Close sets `aria-label="Dialog Close"` and asChild
|
|
6
|
+
* merges it onto the child, so `<Dialog.Close asChild><Button>Cancel</Button>`
|
|
7
|
+
* was announced "Dialog Close", in English, in every locale. AlertDialog's
|
|
8
|
+
* Cancel, Action and Destructive render the same Close. A visible label that
|
|
9
|
+
* is not in the accessible name fails WCAG 2.5.3.
|
|
10
|
+
*
|
|
11
|
+
* Here a close part with text (its own, or its asChild child's) is named by
|
|
12
|
+
* that text. One with no text and no label of its own, an icon-only X, gets
|
|
13
|
+
* the catalog's localized "Close". An explicit label on the part or on its
|
|
14
|
+
* child still wins. Every other part is the tamagui one.
|
|
15
|
+
*/
|
|
16
|
+
import { isValidElement, type ComponentType, type ReactNode } from "react";
|
|
17
|
+
import {
|
|
18
|
+
AlertDialog as TamaguiAlertDialog,
|
|
19
|
+
Dialog as TamaguiDialog,
|
|
20
|
+
withStaticProperties,
|
|
21
|
+
type GetProps,
|
|
22
|
+
} from "tamagui";
|
|
23
|
+
import { useTranslation } from "./shared/i18n";
|
|
24
|
+
|
|
25
|
+
type Labelled = {
|
|
26
|
+
"aria-label"?: unknown;
|
|
27
|
+
"aria-labelledby"?: unknown;
|
|
28
|
+
accessibilityLabel?: unknown;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
function hasText(node: ReactNode): boolean {
|
|
32
|
+
if (typeof node === "string") return node.trim().length > 0;
|
|
33
|
+
if (typeof node === "number" || typeof node === "bigint") return true;
|
|
34
|
+
if (Array.isArray(node)) return node.some(hasText);
|
|
35
|
+
if (isValidElement<{ children?: ReactNode }>(node)) return hasText(node.props.children);
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function isLabelled(props: Labelled): boolean {
|
|
40
|
+
return (
|
|
41
|
+
props["aria-label"] != null ||
|
|
42
|
+
props["aria-labelledby"] != null ||
|
|
43
|
+
props.accessibilityLabel != null
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function needsCloseName(props: Labelled & { asChild?: unknown; children?: ReactNode }): boolean {
|
|
48
|
+
if (isLabelled(props)) return false;
|
|
49
|
+
const { asChild, children } = props;
|
|
50
|
+
if (asChild && isValidElement<Labelled & { children?: ReactNode }>(children)) {
|
|
51
|
+
return !isLabelled(children.props) && !hasText(children.props.children);
|
|
52
|
+
}
|
|
53
|
+
return !hasText(children);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function namedByContent<C extends ComponentType<any>>(Part: C, displayName: string) {
|
|
57
|
+
const Raw = Part as ComponentType<any>;
|
|
58
|
+
|
|
59
|
+
function LocalizedClose(props: GetProps<C>) {
|
|
60
|
+
const { t } = useTranslation();
|
|
61
|
+
return <Raw aria-label={t("Close")} {...props} />;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function Close(props: GetProps<C>) {
|
|
65
|
+
if (needsCloseName(props)) return <LocalizedClose {...props} />;
|
|
66
|
+
return <Raw aria-label={undefined} {...props} />;
|
|
67
|
+
}
|
|
68
|
+
Close.displayName = displayName;
|
|
69
|
+
return Close;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export const Dialog: typeof TamaguiDialog = withStaticProperties(TamaguiDialog, {
|
|
73
|
+
Close: namedByContent(TamaguiDialog.Close, "DialogClose"),
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
export const AlertDialog: typeof TamaguiAlertDialog = withStaticProperties(TamaguiAlertDialog, {
|
|
77
|
+
Cancel: namedByContent(TamaguiAlertDialog.Cancel, "AlertDialogCancel"),
|
|
78
|
+
Action: namedByContent(TamaguiAlertDialog.Action, "AlertDialogAction"),
|
|
79
|
+
Destructive: namedByContent(TamaguiAlertDialog.Destructive, "AlertDialogDestructive"),
|
|
80
|
+
});
|
|
@@ -4,7 +4,8 @@ import { useState } from "react";
|
|
|
4
4
|
// DialogContent so it inherits the compact nested-scale step (LC-73); the
|
|
5
5
|
// dialog frame itself does not ring (LC-71).
|
|
6
6
|
import { Button } from "@multiplatform.one/forms";
|
|
7
|
-
import {
|
|
7
|
+
import { Paragraph, XStack, YStack } from "tamagui";
|
|
8
|
+
import { Dialog } from "./Dialog";
|
|
8
9
|
import { DialogContent, DialogOverlay } from "./surfaces";
|
|
9
10
|
|
|
10
11
|
function DialogHarness({
|
|
@@ -1,56 +1,32 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from "@storybook/react-native-web-vite";
|
|
2
2
|
import type { ComponentProps } from "react";
|
|
3
|
-
import { YStack
|
|
3
|
+
import { YStack } from "tamagui";
|
|
4
4
|
import { HighlightedCode } from "./index";
|
|
5
5
|
import type { HighlightLine } from "../Highlighter";
|
|
6
6
|
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
const
|
|
7
|
+
// What highlightCode returns under the house syntax theme: theme tokens, so
|
|
8
|
+
// one fixture reads in both schemes (MPO-474).
|
|
9
|
+
const sampleTokens: HighlightLine[] = [
|
|
10
10
|
[
|
|
11
|
-
{ content: "const
|
|
12
|
-
{ content: "
|
|
13
|
-
{ content: "
|
|
14
|
-
{ content: "
|
|
15
|
-
{ content: "
|
|
11
|
+
{ content: "const", color: "$syntaxPurple" },
|
|
12
|
+
{ content: " ", color: "$color12" },
|
|
13
|
+
{ content: "hello", color: "$syntaxBlue" },
|
|
14
|
+
{ content: " ", color: "$color12" },
|
|
15
|
+
{ content: "=", color: "$syntaxPurple" },
|
|
16
|
+
{ content: " ", color: "$color12" },
|
|
17
|
+
{ content: "'world'", color: "$syntaxGreen" },
|
|
18
|
+
{ content: ";", color: "$color12" },
|
|
16
19
|
],
|
|
17
20
|
[
|
|
18
|
-
{ content: "console", color: "
|
|
19
|
-
{ content: "
|
|
20
|
-
{ content: "
|
|
21
|
-
{ content: "(", color: "#abb2bf" },
|
|
22
|
-
{ content: "hello", color: "#e06c75" },
|
|
23
|
-
{ content: ");", color: "#abb2bf" },
|
|
21
|
+
{ content: "console.", color: "$color12" },
|
|
22
|
+
{ content: "log", color: "$syntaxBlue" },
|
|
23
|
+
{ content: "(hello);", color: "$color12" },
|
|
24
24
|
],
|
|
25
25
|
];
|
|
26
26
|
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
{ content: "hello", color: "#8250df" },
|
|
31
|
-
{ content: " = ", color: "#0550ae" },
|
|
32
|
-
{ content: "'world'", color: "#0a3069" },
|
|
33
|
-
{ content: ";", color: "#57606a" },
|
|
34
|
-
],
|
|
35
|
-
[
|
|
36
|
-
{ content: "console", color: "#953800" },
|
|
37
|
-
{ content: ".", color: "#57606a" },
|
|
38
|
-
{ content: "log", color: "#8250df" },
|
|
39
|
-
{ content: "(", color: "#57606a" },
|
|
40
|
-
{ content: "hello", color: "#8250df" },
|
|
41
|
-
{ content: ");", color: "#57606a" },
|
|
42
|
-
],
|
|
43
|
-
];
|
|
44
|
-
|
|
45
|
-
function useSampleTokens(): HighlightLine[] {
|
|
46
|
-
const themeName = useThemeName();
|
|
47
|
-
return themeName?.includes("dark") ? darkSampleTokens : lightSampleTokens;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const SampleHighlightedCode = (props: Omit<ComponentProps<typeof HighlightedCode>, "tokens">) => {
|
|
51
|
-
const tokens = useSampleTokens();
|
|
52
|
-
return <HighlightedCode tokens={tokens} {...props} />;
|
|
53
|
-
};
|
|
27
|
+
const SampleHighlightedCode = (props: Omit<ComponentProps<typeof HighlightedCode>, "tokens">) => (
|
|
28
|
+
<HighlightedCode tokens={sampleTokens} {...props} />
|
|
29
|
+
);
|
|
54
30
|
|
|
55
31
|
const meta: Meta<typeof HighlightedCode> = {
|
|
56
32
|
title: "Components/HighlightedCode",
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MPO-474: the shiki stack paints theme tokens, not GitHub hex. github-light
|
|
3
|
+
* measured 3.13 to 4.35:1 on the house code surfaces and github-dark's comment
|
|
4
|
+
* 3.77:1, and neither palette follows the scheme or the knobs.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { bundledThemes } from "shiki";
|
|
8
|
+
import { describe, expect, it } from "vitest";
|
|
9
|
+
import { highlightCode, houseSyntaxTheme } from "./index";
|
|
10
|
+
|
|
11
|
+
const houseInk = /^\$(color11|color12|syntax(Purple|Green|Blue|Orange|Red))$/;
|
|
12
|
+
|
|
13
|
+
const sample = `// Greets a user
|
|
14
|
+
export function greet(user: User, retries = 3): string {
|
|
15
|
+
const label = \`Hello, \${user.name}\`;
|
|
16
|
+
console.log(label, true, null);
|
|
17
|
+
return label;
|
|
18
|
+
}`;
|
|
19
|
+
|
|
20
|
+
async function inkOf(code: string, language: string, content: string, theme?: string) {
|
|
21
|
+
const lines = await highlightCode(code, language, theme);
|
|
22
|
+
const token = lines.flat().find((candidate) => candidate.content.trim() === content);
|
|
23
|
+
expect(token, `no token ${JSON.stringify(content)}`).toBeTruthy();
|
|
24
|
+
return token!.color;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
describe("MPO-474: the default highlighter theme paints the held syntax tokens", () => {
|
|
28
|
+
it("every token of a TypeScript sample takes a house ink", { timeout: 30000 }, async () => {
|
|
29
|
+
const lines = await highlightCode(sample, "typescript");
|
|
30
|
+
const inks = new Set(lines.flat().map((token) => token.color));
|
|
31
|
+
expect(inks.size).toBeGreaterThan(4);
|
|
32
|
+
for (const color of inks) expect(color).toMatch(houseInk);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it.each([
|
|
36
|
+
["// Greets a user", "$color11"],
|
|
37
|
+
["export", "$syntaxPurple"],
|
|
38
|
+
["function", "$syntaxPurple"],
|
|
39
|
+
["greet", "$syntaxBlue"],
|
|
40
|
+
["User", "$syntaxBlue"],
|
|
41
|
+
["3", "$syntaxBlue"],
|
|
42
|
+
["true", "$syntaxBlue"],
|
|
43
|
+
["string", "$syntaxOrange"],
|
|
44
|
+
["retries", "$syntaxOrange"],
|
|
45
|
+
["`Hello, ${", "$syntaxGreen"],
|
|
46
|
+
])("%s paints %s", { timeout: 30000 }, async (content, ink) => {
|
|
47
|
+
expect(await inkOf(sample, "typescript", content)).toBe(ink);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("diff lines paint the red and green the washes are held for", { timeout: 30000 }, async () => {
|
|
51
|
+
const diff = "- const retries = 1;\n+ const retries = 3;";
|
|
52
|
+
expect(await inkOf(diff, "diff", "- const retries = 1;")).toBe("$syntaxRed");
|
|
53
|
+
expect(await inkOf(diff, "diff", "+ const retries = 3;")).toBe("$syntaxGreen");
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("markup tags paint green like the editor's", { timeout: 30000 }, async () => {
|
|
57
|
+
expect(await inkOf('<a href="/x">hi</a>', "html", "a")).toBe("$syntaxGreen");
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("an explicit theme still ejects to its literal palette", { timeout: 30000 }, async () => {
|
|
61
|
+
expect((await inkOf(sample, "typescript", "export", "github-light"))?.toLowerCase()).toBe(
|
|
62
|
+
"#d73a49",
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("keeps github-light's scope rules one for one, painted only in house ink", async () => {
|
|
67
|
+
const githubLight = (await bundledThemes["github-light"]()).default;
|
|
68
|
+
const scopesOf = (settings: { scope?: string | string[] }[]) =>
|
|
69
|
+
settings.map((setting) => [setting.scope ?? []].flat().join(",")).filter(Boolean);
|
|
70
|
+
expect(scopesOf(houseSyntaxTheme.settings)).toEqual(
|
|
71
|
+
scopesOf(githubLight.tokenColors ?? githubLight.settings ?? []),
|
|
72
|
+
);
|
|
73
|
+
for (const setting of houseSyntaxTheme.settings) {
|
|
74
|
+
if (setting.settings.foreground) expect(setting.settings.foreground).toMatch(houseInk);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
});
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The house shiki theme (MPO-474): github-light's scope rules one for one,
|
|
3
|
+
* each painted with a theme token in the rich-text editor's roles, so code
|
|
4
|
+
* ink follows the scheme and tint and holds `holdSyntaxFloor`'s 4.5:1. Shiki
|
|
5
|
+
* passes a non-hex colour through untouched (a placeholder while tokenizing,
|
|
6
|
+
* restored on every token), which is what lets a theme name Tamagui tokens.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export interface HouseSyntaxThemeSetting {
|
|
10
|
+
scope?: string | string[];
|
|
11
|
+
settings: { foreground?: string; background?: string; fontStyle?: string };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface HouseSyntaxTheme {
|
|
15
|
+
name: string;
|
|
16
|
+
fg: string;
|
|
17
|
+
bg: string;
|
|
18
|
+
settings: HouseSyntaxThemeSetting[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const ink = {
|
|
22
|
+
plain: "$color12",
|
|
23
|
+
muted: "$color11",
|
|
24
|
+
keyword: "$syntaxPurple",
|
|
25
|
+
name: "$syntaxBlue",
|
|
26
|
+
constant: "$syntaxBlue",
|
|
27
|
+
builtin: "$syntaxOrange",
|
|
28
|
+
variable: "$syntaxOrange",
|
|
29
|
+
string: "$syntaxGreen",
|
|
30
|
+
tag: "$syntaxGreen",
|
|
31
|
+
inserted: "$syntaxGreen",
|
|
32
|
+
deleted: "$syntaxRed",
|
|
33
|
+
} as const;
|
|
34
|
+
|
|
35
|
+
export const houseSyntaxTheme: HouseSyntaxTheme = {
|
|
36
|
+
name: "house",
|
|
37
|
+
fg: ink.plain,
|
|
38
|
+
bg: "$color3",
|
|
39
|
+
settings: [
|
|
40
|
+
{ settings: { foreground: ink.plain, background: "$color3" } },
|
|
41
|
+
{
|
|
42
|
+
scope: ["comment", "punctuation.definition.comment", "string.comment"],
|
|
43
|
+
settings: { foreground: ink.muted },
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
scope: [
|
|
47
|
+
"constant",
|
|
48
|
+
"entity.name.constant",
|
|
49
|
+
"variable.other.constant",
|
|
50
|
+
"variable.other.enummember",
|
|
51
|
+
"variable.language",
|
|
52
|
+
],
|
|
53
|
+
settings: { foreground: ink.constant },
|
|
54
|
+
},
|
|
55
|
+
{ scope: ["entity", "entity.name"], settings: { foreground: ink.name } },
|
|
56
|
+
{ scope: "variable.parameter.function", settings: { foreground: ink.plain } },
|
|
57
|
+
{ scope: "entity.name.tag", settings: { foreground: ink.tag } },
|
|
58
|
+
{ scope: "keyword", settings: { foreground: ink.keyword } },
|
|
59
|
+
{ scope: ["storage", "storage.type"], settings: { foreground: ink.keyword } },
|
|
60
|
+
{
|
|
61
|
+
scope: ["storage.modifier.package", "storage.modifier.import", "storage.type.java"],
|
|
62
|
+
settings: { foreground: ink.plain },
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
scope: [
|
|
66
|
+
"string",
|
|
67
|
+
"punctuation.definition.string",
|
|
68
|
+
"string punctuation.section.embedded source",
|
|
69
|
+
],
|
|
70
|
+
settings: { foreground: ink.string },
|
|
71
|
+
},
|
|
72
|
+
{ scope: "support", settings: { foreground: ink.builtin } },
|
|
73
|
+
{ scope: "meta.property-name", settings: { foreground: ink.constant } },
|
|
74
|
+
{ scope: "variable", settings: { foreground: ink.variable } },
|
|
75
|
+
{ scope: "variable.other", settings: { foreground: ink.plain } },
|
|
76
|
+
{ scope: "invalid.broken", settings: { foreground: ink.deleted, fontStyle: "italic" } },
|
|
77
|
+
{ scope: "invalid.deprecated", settings: { foreground: ink.deleted, fontStyle: "italic" } },
|
|
78
|
+
{ scope: "invalid.illegal", settings: { foreground: ink.deleted, fontStyle: "italic" } },
|
|
79
|
+
{ scope: "invalid.unimplemented", settings: { foreground: ink.deleted, fontStyle: "italic" } },
|
|
80
|
+
{
|
|
81
|
+
scope: "carriage-return",
|
|
82
|
+
settings: { foreground: ink.deleted, fontStyle: "italic underline" },
|
|
83
|
+
},
|
|
84
|
+
{ scope: "message.error", settings: { foreground: ink.deleted } },
|
|
85
|
+
{ scope: "string variable", settings: { foreground: ink.variable } },
|
|
86
|
+
{ scope: ["source.regexp", "string.regexp"], settings: { foreground: ink.string } },
|
|
87
|
+
{
|
|
88
|
+
scope: [
|
|
89
|
+
"string.regexp.character-class",
|
|
90
|
+
"string.regexp constant.character.escape",
|
|
91
|
+
"string.regexp source.ruby.embedded",
|
|
92
|
+
"string.regexp string.regexp.arbitrary-repitition",
|
|
93
|
+
],
|
|
94
|
+
settings: { foreground: ink.string },
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
scope: "string.regexp constant.character.escape",
|
|
98
|
+
settings: { foreground: ink.string, fontStyle: "bold" },
|
|
99
|
+
},
|
|
100
|
+
{ scope: "support.constant", settings: { foreground: ink.builtin } },
|
|
101
|
+
{ scope: "support.variable", settings: { foreground: ink.builtin } },
|
|
102
|
+
{ scope: "meta.module-reference", settings: { foreground: ink.constant } },
|
|
103
|
+
{
|
|
104
|
+
scope: "punctuation.definition.list.begin.markdown",
|
|
105
|
+
settings: { foreground: ink.variable },
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
scope: ["markup.heading", "markup.heading entity.name"],
|
|
109
|
+
settings: { foreground: ink.name, fontStyle: "bold" },
|
|
110
|
+
},
|
|
111
|
+
{ scope: "markup.quote", settings: { foreground: ink.muted } },
|
|
112
|
+
{ scope: "markup.italic", settings: { foreground: ink.plain, fontStyle: "italic" } },
|
|
113
|
+
{ scope: "markup.bold", settings: { foreground: ink.plain, fontStyle: "bold" } },
|
|
114
|
+
{ scope: ["markup.underline"], settings: { fontStyle: "underline" } },
|
|
115
|
+
{ scope: ["markup.strikethrough"], settings: { fontStyle: "strikethrough" } },
|
|
116
|
+
{ scope: "markup.inline.raw", settings: { foreground: ink.constant } },
|
|
117
|
+
{
|
|
118
|
+
scope: ["markup.deleted", "meta.diff.header.from-file", "punctuation.definition.deleted"],
|
|
119
|
+
settings: { foreground: ink.deleted },
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
scope: ["markup.inserted", "meta.diff.header.to-file", "punctuation.definition.inserted"],
|
|
123
|
+
settings: { foreground: ink.inserted },
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
scope: ["markup.changed", "punctuation.definition.changed"],
|
|
127
|
+
settings: { foreground: ink.variable },
|
|
128
|
+
},
|
|
129
|
+
{ scope: ["markup.ignored", "markup.untracked"], settings: { foreground: ink.constant } },
|
|
130
|
+
{ scope: "meta.diff.range", settings: { foreground: ink.keyword, fontStyle: "bold" } },
|
|
131
|
+
{ scope: "meta.diff.header", settings: { foreground: ink.constant } },
|
|
132
|
+
{ scope: "meta.separator", settings: { foreground: ink.constant, fontStyle: "bold" } },
|
|
133
|
+
{ scope: "meta.output", settings: { foreground: ink.constant } },
|
|
134
|
+
{
|
|
135
|
+
scope: [
|
|
136
|
+
"brackethighlighter.tag",
|
|
137
|
+
"brackethighlighter.curly",
|
|
138
|
+
"brackethighlighter.round",
|
|
139
|
+
"brackethighlighter.square",
|
|
140
|
+
"brackethighlighter.angle",
|
|
141
|
+
"brackethighlighter.quote",
|
|
142
|
+
],
|
|
143
|
+
settings: { foreground: ink.muted },
|
|
144
|
+
},
|
|
145
|
+
{ scope: "brackethighlighter.unmatched", settings: { foreground: ink.deleted } },
|
|
146
|
+
{
|
|
147
|
+
scope: ["constant.other.reference.link", "string.other.link"],
|
|
148
|
+
settings: { foreground: ink.string, fontStyle: "underline" },
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
};
|
|
@@ -7,11 +7,14 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { createContext, useContext, useEffect, useState } from "react";
|
|
10
|
-
import {
|
|
10
|
+
import { houseSyntaxTheme } from "./houseSyntaxTheme";
|
|
11
|
+
|
|
12
|
+
export * from "./houseSyntaxTheme";
|
|
11
13
|
|
|
12
14
|
/** A single highlighted token with inline color */
|
|
13
15
|
export interface HighlightToken {
|
|
14
16
|
content: string;
|
|
17
|
+
/** A theme token such as `$syntaxBlue` under the house theme, or a named theme's hex */
|
|
15
18
|
color?: string;
|
|
16
19
|
fontStyle?: number; // 0=normal, 1=italic, 2=bold, 3=bold+italic
|
|
17
20
|
}
|
|
@@ -37,11 +40,7 @@ export function useShikiTokens(
|
|
|
37
40
|
theme?: string,
|
|
38
41
|
): HighlightLine[] | null {
|
|
39
42
|
const ctx = useContext(ShikiContext);
|
|
40
|
-
const
|
|
41
|
-
// Default shiki theme follows the app scheme so light mode gets a
|
|
42
|
-
// dark-on-light token palette instead of github-dark's light inks
|
|
43
|
-
const schemeDefault = themeName?.includes("dark") ? "github-dark" : "github-light";
|
|
44
|
-
const resolvedTheme = theme || ctx.theme || schemeDefault;
|
|
43
|
+
const resolvedTheme = theme || ctx.theme || houseSyntaxTheme.name;
|
|
45
44
|
const [tokens, setTokens] = useState<HighlightLine[] | null>(null);
|
|
46
45
|
|
|
47
46
|
useEffect(() => {
|
|
@@ -101,7 +100,7 @@ function getHighlighter(): Promise<any> {
|
|
|
101
100
|
export async function highlightCode(
|
|
102
101
|
code: string,
|
|
103
102
|
language: string,
|
|
104
|
-
theme =
|
|
103
|
+
theme = houseSyntaxTheme.name,
|
|
105
104
|
): Promise<HighlightLine[]> {
|
|
106
105
|
try {
|
|
107
106
|
const highlighter = await Promise.race([
|
|
@@ -111,7 +110,7 @@ export async function highlightCode(
|
|
|
111
110
|
),
|
|
112
111
|
]);
|
|
113
112
|
await Promise.all([
|
|
114
|
-
highlighter.loadTheme(theme as any),
|
|
113
|
+
highlighter.loadTheme((theme === houseSyntaxTheme.name ? houseSyntaxTheme : theme) as any),
|
|
115
114
|
// Unknown languages fall back to plain text below; theme failures
|
|
116
115
|
// reject into the catch (matching the old shorthand behavior).
|
|
117
116
|
highlighter.loadLanguage(language as any).catch(() => {}),
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MPO-474: every shiki surface (CodeBlock, MDXCodeBlock, markdown CodeBlock,
|
|
3
|
+
* CodeEditorField) tokenizes through useShikiTokens and paints through
|
|
4
|
+
* HighlightedCode. By default the ink is a theme token in either scheme, so
|
|
5
|
+
* Tamagui emits the token's class (`_col-syntaxPurpl…`), not a hex class
|
|
6
|
+
* (`_col-D73A4935`) that no scheme or knob can reach.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { createDefaultThemeConfig } from "@multiplatform.one/theme";
|
|
10
|
+
import { cleanup, render, waitFor } from "@testing-library/react";
|
|
11
|
+
import { TamaguiProvider } from "tamagui";
|
|
12
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
13
|
+
import { HighlightedCode } from "./HighlightedCode";
|
|
14
|
+
import { useShikiTokens } from "./Highlighter";
|
|
15
|
+
|
|
16
|
+
afterEach(cleanup);
|
|
17
|
+
|
|
18
|
+
const houseConfig = createDefaultThemeConfig();
|
|
19
|
+
// Tamagui keeps a token's first 11 characters in its atomic class and hashes the rest.
|
|
20
|
+
const inkClass = (token: string) => new RegExp(`_col-${token.slice(0, 11)}`);
|
|
21
|
+
|
|
22
|
+
function Probe({ code, language, theme }: { code: string; language: string; theme?: string }) {
|
|
23
|
+
const tokens = useShikiTokens(code, language, theme);
|
|
24
|
+
return <HighlightedCode tokens={tokens}>{code}</HighlightedCode>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function tokenSpan(container: HTMLElement, text: string) {
|
|
28
|
+
const matches = Array.from(container.querySelectorAll("span")).filter(
|
|
29
|
+
(span) => span.textContent === text,
|
|
30
|
+
);
|
|
31
|
+
return matches.find((span) => !matches.some((other) => other !== span && span.contains(other)));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
describe("MPO-474: shiki ink is a theme token in both schemes", () => {
|
|
35
|
+
for (const scheme of ["light", "dark"] as const) {
|
|
36
|
+
it(`${scheme}: keyword, string and comment take the held tokens`, async () => {
|
|
37
|
+
const { container } = render(
|
|
38
|
+
<TamaguiProvider config={houseConfig.tamagui} defaultTheme={scheme} disableInjectCSS>
|
|
39
|
+
<Probe code={'// note\nconst greeting = "hi";'} language="typescript" />
|
|
40
|
+
</TamaguiProvider>,
|
|
41
|
+
);
|
|
42
|
+
await waitFor(
|
|
43
|
+
() => expect(tokenSpan(container, "const")?.className).toMatch(inkClass("syntaxPurple")),
|
|
44
|
+
{ timeout: 30000 },
|
|
45
|
+
);
|
|
46
|
+
expect(tokenSpan(container, '"hi"')?.className).toMatch(inkClass("syntaxGreen"));
|
|
47
|
+
expect(tokenSpan(container, "// note")?.className).toMatch(inkClass("color11"));
|
|
48
|
+
}, 35000);
|
|
49
|
+
}
|
|
50
|
+
});
|
package/src/knobImmuneExports.ts
CHANGED
|
@@ -63,9 +63,6 @@ export const knobImmuneExports: Readonly<Record<string, string>> = {
|
|
|
63
63
|
// Logic shells with no painted frame of their own; the knob channel lands
|
|
64
64
|
// on the house content surfaces designed to fill them (DialogContent,
|
|
65
65
|
// PopoverContent, SheetFrame, ConfirmDialog).
|
|
66
|
-
Dialog: "composition root (logic/portal shell); knobs land on house DialogContent",
|
|
67
|
-
AlertDialog:
|
|
68
|
-
"composition root; knobs land on house ConfirmDialog / DialogContent surfaces composed inside",
|
|
69
66
|
Popover: "composition root; knobs land on house PopoverContent",
|
|
70
67
|
Sheet: "composition root; knobs land on house SheetFrame",
|
|
71
68
|
Portal: "reparenting utility; renders children elsewhere, paints nothing",
|