@multiplatform.one/components 7.8.0 → 7.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +98 -0
- package/dist/cjs/Accordion/index.cjs +3 -3
- package/dist/cjs/Accordion/index.native.js +4 -4
- package/dist/cjs/Accordion/index.native.js.map +1 -1
- package/dist/cjs/Chip/index.cjs +1 -1
- package/dist/cjs/Chip/index.native.js +1 -1
- package/dist/cjs/Chip/index.native.js.map +1 -1
- package/dist/cjs/ContextMenu/index.cjs +3 -3
- package/dist/cjs/ContextMenu/index.native.js +3 -3
- package/dist/cjs/ContextMenu/index.native.js.map +1 -1
- package/dist/cjs/DropdownMenu/index.cjs +3 -3
- package/dist/cjs/DropdownMenu/index.native.js +3 -3
- package/dist/cjs/DropdownMenu/index.native.js.map +1 -1
- package/dist/cjs/Meter/index.cjs +3 -2
- package/dist/cjs/Meter/index.native.js +3 -2
- package/dist/cjs/Meter/index.native.js.map +1 -1
- package/dist/cjs/Meter/meter.cjs +1 -2
- package/dist/cjs/Meter/meter.native.js +1 -2
- package/dist/cjs/Meter/meter.native.js.map +1 -1
- package/dist/cjs/Pagination.cjs +2 -2
- package/dist/cjs/Pagination.native.js +2 -2
- package/dist/cjs/Pagination.native.js.map +1 -1
- package/dist/cjs/ProgressSteps/index.cjs +3 -3
- package/dist/cjs/ProgressSteps/index.native.js +3 -3
- package/dist/cjs/ProgressSteps/index.native.js.map +1 -1
- package/dist/cjs/Quote/index.cjs +1 -2
- package/dist/cjs/Quote/index.native.js +1 -2
- package/dist/cjs/Quote/index.native.js.map +1 -1
- package/dist/cjs/SheetModal/index.cjs +22 -3
- package/dist/cjs/SheetModal/index.native.js +50 -10
- package/dist/cjs/SheetModal/index.native.js.map +1 -1
- package/dist/cjs/Tabs/index.cjs +34 -13
- package/dist/cjs/Tabs/index.native.js +38 -13
- package/dist/cjs/Tabs/index.native.js.map +1 -1
- package/dist/cjs/Toast/index.cjs +4 -5
- package/dist/cjs/Toast/index.native.js +4 -5
- package/dist/cjs/Toast/index.native.js.map +1 -1
- package/dist/cjs/TreeSelect/index.cjs +46 -7
- package/dist/cjs/TreeSelect/index.native.js +58 -7
- package/dist/cjs/TreeSelect/index.native.js.map +1 -1
- package/dist/cjs/charts/PieChart.cjs +1 -2
- package/dist/cjs/charts/PieChart.native.js +1 -2
- package/dist/cjs/charts/PieChart.native.js.map +1 -1
- package/dist/cjs/code/HighlightedCode/index.cjs +1 -1
- package/dist/cjs/code/HighlightedCode/index.native.js +1 -1
- package/dist/cjs/code/HighlightedCode/index.native.js.map +1 -1
- package/dist/cjs/componentColors.cjs +6 -4
- package/dist/cjs/componentColors.native.js +6 -4
- package/dist/cjs/componentColors.native.js.map +1 -1
- package/dist/cjs/images/Image/ImageFrame.cjs +4 -2
- package/dist/cjs/images/Image/ImageFrame.native.js +4 -2
- package/dist/cjs/images/Image/ImageFrame.native.js.map +1 -1
- package/dist/cjs/layouts/AsyncBoundary.cjs +1 -2
- package/dist/cjs/layouts/AsyncBoundary.native.js +1 -2
- package/dist/cjs/layouts/AsyncBoundary.native.js.map +1 -1
- package/dist/cjs/layouts/EmptyState.cjs +6 -2
- package/dist/cjs/layouts/EmptyState.native.js +10 -6
- package/dist/cjs/layouts/EmptyState.native.js.map +1 -1
- package/dist/cjs/layouts/attachments.cjs +4 -4
- package/dist/cjs/layouts/attachments.native.js +4 -4
- package/dist/cjs/layouts/attachments.native.js.map +1 -1
- package/dist/cjs/layouts/breadcrumbs.cjs +1 -2
- package/dist/cjs/layouts/breadcrumbs.native.js +1 -2
- package/dist/cjs/layouts/breadcrumbs.native.js.map +1 -1
- package/dist/cjs/layouts/page.cjs +2 -2
- package/dist/cjs/layouts/page.native.js +2 -2
- package/dist/cjs/layouts/page.native.js.map +1 -1
- package/dist/cjs/layouts/sidebar.cjs +2 -2
- package/dist/cjs/layouts/sidebar.native.js +2 -2
- package/dist/cjs/layouts/sidebar.native.js.map +1 -1
- package/dist/cjs/layouts/tags.cjs +6 -7
- package/dist/cjs/layouts/tags.native.js +6 -9
- package/dist/cjs/layouts/tags.native.js.map +1 -1
- package/dist/cjs/layouts/timeline.cjs +5 -5
- package/dist/cjs/layouts/timeline.native.js +5 -5
- package/dist/cjs/layouts/timeline.native.js.map +1 -1
- package/dist/cjs/surfaces.cjs +1 -0
- package/dist/cjs/surfaces.native.js +1 -0
- package/dist/cjs/surfaces.native.js.map +1 -1
- package/dist/cjs/views/Calendar.cjs +11 -8
- package/dist/cjs/views/Calendar.native.js +11 -8
- package/dist/cjs/views/Calendar.native.js.map +1 -1
- package/dist/cjs/views/Dashboard.cjs +6 -6
- package/dist/cjs/views/Dashboard.native.js +7 -7
- package/dist/cjs/views/Dashboard.native.js.map +1 -1
- package/dist/cjs/views/Gantt.cjs +3 -3
- package/dist/cjs/views/Gantt.native.js +3 -3
- package/dist/cjs/views/Gantt.native.js.map +1 -1
- package/dist/cjs/views/Kanban.cjs +2 -2
- package/dist/cjs/views/Kanban.native.js +2 -2
- package/dist/cjs/views/Kanban.native.js.map +1 -1
- package/dist/cjs/views/ReportBuilder.cjs +4 -4
- package/dist/cjs/views/ReportBuilder.native.js +4 -4
- package/dist/cjs/views/ReportBuilder.native.js.map +1 -1
- package/dist/cjs/views/TreeView.cjs +248 -19
- package/dist/cjs/views/TreeView.native.js +264 -20
- package/dist/cjs/views/TreeView.native.js.map +1 -1
- package/dist/cjs/views/treeViewReveal.cjs +55 -0
- package/dist/cjs/views/treeViewReveal.native.js +80 -0
- package/dist/cjs/views/treeViewReveal.native.js.map +1 -0
- package/dist/esm/Accordion/index.mjs +3 -3
- package/dist/esm/Accordion/index.mjs.map +1 -1
- package/dist/esm/Accordion/index.native.js +4 -4
- package/dist/esm/Accordion/index.native.js.map +1 -1
- package/dist/esm/Chip/index.mjs +1 -1
- package/dist/esm/Chip/index.mjs.map +1 -1
- package/dist/esm/Chip/index.native.js +1 -1
- package/dist/esm/Chip/index.native.js.map +1 -1
- package/dist/esm/ContextMenu/index.mjs +3 -3
- package/dist/esm/ContextMenu/index.mjs.map +1 -1
- package/dist/esm/ContextMenu/index.native.js +3 -3
- package/dist/esm/ContextMenu/index.native.js.map +1 -1
- package/dist/esm/DropdownMenu/index.mjs +3 -3
- package/dist/esm/DropdownMenu/index.mjs.map +1 -1
- package/dist/esm/DropdownMenu/index.native.js +3 -3
- package/dist/esm/DropdownMenu/index.native.js.map +1 -1
- package/dist/esm/Meter/index.mjs +3 -2
- package/dist/esm/Meter/index.mjs.map +1 -1
- package/dist/esm/Meter/index.native.js +3 -2
- package/dist/esm/Meter/index.native.js.map +1 -1
- package/dist/esm/Meter/meter.mjs +1 -2
- package/dist/esm/Meter/meter.mjs.map +1 -1
- package/dist/esm/Meter/meter.native.js +1 -2
- package/dist/esm/Meter/meter.native.js.map +1 -1
- package/dist/esm/Pagination.mjs +2 -2
- package/dist/esm/Pagination.mjs.map +1 -1
- package/dist/esm/Pagination.native.js +2 -2
- package/dist/esm/Pagination.native.js.map +1 -1
- package/dist/esm/ProgressSteps/index.mjs +3 -3
- package/dist/esm/ProgressSteps/index.mjs.map +1 -1
- package/dist/esm/ProgressSteps/index.native.js +3 -3
- package/dist/esm/ProgressSteps/index.native.js.map +1 -1
- package/dist/esm/Quote/index.mjs +1 -2
- package/dist/esm/Quote/index.mjs.map +1 -1
- package/dist/esm/Quote/index.native.js +1 -2
- package/dist/esm/Quote/index.native.js.map +1 -1
- package/dist/esm/SheetModal/index.mjs +22 -3
- package/dist/esm/SheetModal/index.mjs.map +1 -1
- package/dist/esm/SheetModal/index.native.js +51 -11
- package/dist/esm/SheetModal/index.native.js.map +1 -1
- package/dist/esm/Tabs/index.mjs +34 -13
- package/dist/esm/Tabs/index.mjs.map +1 -1
- package/dist/esm/Tabs/index.native.js +38 -13
- package/dist/esm/Tabs/index.native.js.map +1 -1
- package/dist/esm/Toast/index.mjs +4 -5
- package/dist/esm/Toast/index.mjs.map +1 -1
- package/dist/esm/Toast/index.native.js +4 -5
- package/dist/esm/Toast/index.native.js.map +1 -1
- package/dist/esm/TreeSelect/index.mjs +46 -7
- package/dist/esm/TreeSelect/index.mjs.map +1 -1
- package/dist/esm/TreeSelect/index.native.js +58 -7
- package/dist/esm/TreeSelect/index.native.js.map +1 -1
- package/dist/esm/charts/PieChart.mjs +1 -2
- package/dist/esm/charts/PieChart.mjs.map +1 -1
- package/dist/esm/charts/PieChart.native.js +1 -2
- package/dist/esm/charts/PieChart.native.js.map +1 -1
- package/dist/esm/code/HighlightedCode/index.mjs +1 -1
- package/dist/esm/code/HighlightedCode/index.mjs.map +1 -1
- package/dist/esm/code/HighlightedCode/index.native.js +1 -1
- package/dist/esm/code/HighlightedCode/index.native.js.map +1 -1
- package/dist/esm/componentColors.mjs +6 -4
- package/dist/esm/componentColors.mjs.map +1 -1
- package/dist/esm/componentColors.native.js +6 -4
- package/dist/esm/componentColors.native.js.map +1 -1
- package/dist/esm/images/Image/ImageFrame.mjs +4 -2
- package/dist/esm/images/Image/ImageFrame.mjs.map +1 -1
- package/dist/esm/images/Image/ImageFrame.native.js +4 -2
- package/dist/esm/images/Image/ImageFrame.native.js.map +1 -1
- package/dist/esm/layouts/AsyncBoundary.mjs +1 -2
- package/dist/esm/layouts/AsyncBoundary.mjs.map +1 -1
- package/dist/esm/layouts/AsyncBoundary.native.js +1 -2
- package/dist/esm/layouts/AsyncBoundary.native.js.map +1 -1
- package/dist/esm/layouts/EmptyState.mjs +7 -3
- package/dist/esm/layouts/EmptyState.mjs.map +1 -1
- package/dist/esm/layouts/EmptyState.native.js +11 -7
- package/dist/esm/layouts/EmptyState.native.js.map +1 -1
- package/dist/esm/layouts/attachments.mjs +4 -4
- package/dist/esm/layouts/attachments.mjs.map +1 -1
- package/dist/esm/layouts/attachments.native.js +4 -4
- package/dist/esm/layouts/attachments.native.js.map +1 -1
- package/dist/esm/layouts/breadcrumbs.mjs +1 -2
- package/dist/esm/layouts/breadcrumbs.mjs.map +1 -1
- package/dist/esm/layouts/breadcrumbs.native.js +1 -2
- package/dist/esm/layouts/breadcrumbs.native.js.map +1 -1
- package/dist/esm/layouts/page.mjs +2 -2
- package/dist/esm/layouts/page.mjs.map +1 -1
- package/dist/esm/layouts/page.native.js +2 -2
- package/dist/esm/layouts/page.native.js.map +1 -1
- package/dist/esm/layouts/sidebar.mjs +2 -2
- package/dist/esm/layouts/sidebar.mjs.map +1 -1
- package/dist/esm/layouts/sidebar.native.js +2 -2
- package/dist/esm/layouts/sidebar.native.js.map +1 -1
- package/dist/esm/layouts/tags.mjs +6 -7
- package/dist/esm/layouts/tags.mjs.map +1 -1
- package/dist/esm/layouts/tags.native.js +6 -9
- package/dist/esm/layouts/tags.native.js.map +1 -1
- package/dist/esm/layouts/timeline.mjs +5 -5
- package/dist/esm/layouts/timeline.mjs.map +1 -1
- package/dist/esm/layouts/timeline.native.js +5 -5
- package/dist/esm/layouts/timeline.native.js.map +1 -1
- package/dist/esm/surfaces.mjs +1 -0
- package/dist/esm/surfaces.mjs.map +1 -1
- package/dist/esm/surfaces.native.js +1 -0
- package/dist/esm/surfaces.native.js.map +1 -1
- package/dist/esm/views/Calendar.mjs +11 -8
- package/dist/esm/views/Calendar.mjs.map +1 -1
- package/dist/esm/views/Calendar.native.js +11 -8
- package/dist/esm/views/Calendar.native.js.map +1 -1
- package/dist/esm/views/Dashboard.mjs +6 -6
- package/dist/esm/views/Dashboard.mjs.map +1 -1
- package/dist/esm/views/Dashboard.native.js +7 -7
- package/dist/esm/views/Dashboard.native.js.map +1 -1
- package/dist/esm/views/Gantt.mjs +3 -3
- package/dist/esm/views/Gantt.mjs.map +1 -1
- package/dist/esm/views/Gantt.native.js +3 -3
- package/dist/esm/views/Gantt.native.js.map +1 -1
- package/dist/esm/views/Kanban.mjs +2 -2
- package/dist/esm/views/Kanban.mjs.map +1 -1
- package/dist/esm/views/Kanban.native.js +2 -2
- package/dist/esm/views/Kanban.native.js.map +1 -1
- package/dist/esm/views/ReportBuilder.mjs +4 -4
- package/dist/esm/views/ReportBuilder.mjs.map +1 -1
- package/dist/esm/views/ReportBuilder.native.js +4 -4
- package/dist/esm/views/ReportBuilder.native.js.map +1 -1
- package/dist/esm/views/TreeView.mjs +249 -20
- package/dist/esm/views/TreeView.mjs.map +1 -1
- package/dist/esm/views/TreeView.native.js +265 -21
- package/dist/esm/views/TreeView.native.js.map +1 -1
- package/dist/esm/views/treeViewReveal.mjs +29 -0
- package/dist/esm/views/treeViewReveal.mjs.map +1 -0
- package/dist/esm/views/treeViewReveal.native.js +51 -0
- package/dist/esm/views/treeViewReveal.native.js.map +1 -0
- package/dist/jsx/Accordion/index.mjs +3 -3
- package/dist/jsx/Accordion/index.mjs.map +1 -1
- package/dist/jsx/Accordion/index.native.js +4 -4
- package/dist/jsx/Accordion/index.native.js.map +1 -1
- package/dist/jsx/Chip/index.mjs +1 -1
- package/dist/jsx/Chip/index.mjs.map +1 -1
- package/dist/jsx/Chip/index.native.js +1 -1
- package/dist/jsx/Chip/index.native.js.map +1 -1
- package/dist/jsx/ContextMenu/index.mjs +3 -3
- package/dist/jsx/ContextMenu/index.mjs.map +1 -1
- package/dist/jsx/ContextMenu/index.native.js +3 -3
- package/dist/jsx/ContextMenu/index.native.js.map +1 -1
- package/dist/jsx/DropdownMenu/index.mjs +3 -3
- package/dist/jsx/DropdownMenu/index.mjs.map +1 -1
- package/dist/jsx/DropdownMenu/index.native.js +3 -3
- package/dist/jsx/DropdownMenu/index.native.js.map +1 -1
- package/dist/jsx/Meter/index.mjs +3 -2
- package/dist/jsx/Meter/index.mjs.map +1 -1
- package/dist/jsx/Meter/index.native.js +3 -2
- package/dist/jsx/Meter/index.native.js.map +1 -1
- package/dist/jsx/Meter/meter.mjs +1 -2
- package/dist/jsx/Meter/meter.mjs.map +1 -1
- package/dist/jsx/Meter/meter.native.js +1 -2
- package/dist/jsx/Meter/meter.native.js.map +1 -1
- package/dist/jsx/Pagination.mjs +2 -2
- package/dist/jsx/Pagination.mjs.map +1 -1
- package/dist/jsx/Pagination.native.js +2 -2
- package/dist/jsx/Pagination.native.js.map +1 -1
- package/dist/jsx/ProgressSteps/index.mjs +3 -3
- package/dist/jsx/ProgressSteps/index.mjs.map +1 -1
- package/dist/jsx/ProgressSteps/index.native.js +3 -3
- package/dist/jsx/ProgressSteps/index.native.js.map +1 -1
- package/dist/jsx/Quote/index.mjs +1 -2
- package/dist/jsx/Quote/index.mjs.map +1 -1
- package/dist/jsx/Quote/index.native.js +1 -2
- package/dist/jsx/Quote/index.native.js.map +1 -1
- package/dist/jsx/SheetModal/index.mjs +22 -3
- package/dist/jsx/SheetModal/index.mjs.map +1 -1
- package/dist/jsx/SheetModal/index.native.js +50 -10
- package/dist/jsx/SheetModal/index.native.js.map +1 -1
- package/dist/jsx/Tabs/index.mjs +34 -13
- package/dist/jsx/Tabs/index.mjs.map +1 -1
- package/dist/jsx/Tabs/index.native.js +38 -13
- package/dist/jsx/Tabs/index.native.js.map +1 -1
- package/dist/jsx/Toast/index.mjs +4 -5
- package/dist/jsx/Toast/index.mjs.map +1 -1
- package/dist/jsx/Toast/index.native.js +4 -5
- package/dist/jsx/Toast/index.native.js.map +1 -1
- package/dist/jsx/TreeSelect/index.mjs +46 -7
- package/dist/jsx/TreeSelect/index.mjs.map +1 -1
- package/dist/jsx/TreeSelect/index.native.js +58 -7
- package/dist/jsx/TreeSelect/index.native.js.map +1 -1
- package/dist/jsx/charts/PieChart.mjs +1 -2
- package/dist/jsx/charts/PieChart.mjs.map +1 -1
- package/dist/jsx/charts/PieChart.native.js +1 -2
- package/dist/jsx/charts/PieChart.native.js.map +1 -1
- package/dist/jsx/code/HighlightedCode/index.mjs +1 -1
- package/dist/jsx/code/HighlightedCode/index.mjs.map +1 -1
- package/dist/jsx/code/HighlightedCode/index.native.js +1 -1
- package/dist/jsx/code/HighlightedCode/index.native.js.map +1 -1
- package/dist/jsx/componentColors.mjs +6 -4
- package/dist/jsx/componentColors.mjs.map +1 -1
- package/dist/jsx/componentColors.native.js +6 -4
- package/dist/jsx/componentColors.native.js.map +1 -1
- package/dist/jsx/images/Image/ImageFrame.mjs +4 -2
- package/dist/jsx/images/Image/ImageFrame.mjs.map +1 -1
- package/dist/jsx/images/Image/ImageFrame.native.js +4 -2
- package/dist/jsx/images/Image/ImageFrame.native.js.map +1 -1
- package/dist/jsx/layouts/AsyncBoundary.mjs +1 -2
- package/dist/jsx/layouts/AsyncBoundary.mjs.map +1 -1
- package/dist/jsx/layouts/AsyncBoundary.native.js +1 -2
- package/dist/jsx/layouts/AsyncBoundary.native.js.map +1 -1
- package/dist/jsx/layouts/EmptyState.mjs +7 -3
- package/dist/jsx/layouts/EmptyState.mjs.map +1 -1
- package/dist/jsx/layouts/EmptyState.native.js +10 -6
- package/dist/jsx/layouts/EmptyState.native.js.map +1 -1
- package/dist/jsx/layouts/attachments.mjs +4 -4
- package/dist/jsx/layouts/attachments.mjs.map +1 -1
- package/dist/jsx/layouts/attachments.native.js +4 -4
- package/dist/jsx/layouts/attachments.native.js.map +1 -1
- package/dist/jsx/layouts/breadcrumbs.mjs +1 -2
- package/dist/jsx/layouts/breadcrumbs.mjs.map +1 -1
- package/dist/jsx/layouts/breadcrumbs.native.js +1 -2
- package/dist/jsx/layouts/breadcrumbs.native.js.map +1 -1
- package/dist/jsx/layouts/page.mjs +2 -2
- package/dist/jsx/layouts/page.mjs.map +1 -1
- package/dist/jsx/layouts/page.native.js +2 -2
- package/dist/jsx/layouts/page.native.js.map +1 -1
- package/dist/jsx/layouts/sidebar.mjs +2 -2
- package/dist/jsx/layouts/sidebar.mjs.map +1 -1
- package/dist/jsx/layouts/sidebar.native.js +2 -2
- package/dist/jsx/layouts/sidebar.native.js.map +1 -1
- package/dist/jsx/layouts/tags.mjs +6 -7
- package/dist/jsx/layouts/tags.mjs.map +1 -1
- package/dist/jsx/layouts/tags.native.js +6 -9
- package/dist/jsx/layouts/tags.native.js.map +1 -1
- package/dist/jsx/layouts/timeline.mjs +5 -5
- package/dist/jsx/layouts/timeline.mjs.map +1 -1
- package/dist/jsx/layouts/timeline.native.js +5 -5
- package/dist/jsx/layouts/timeline.native.js.map +1 -1
- package/dist/jsx/surfaces.mjs +1 -0
- package/dist/jsx/surfaces.mjs.map +1 -1
- package/dist/jsx/surfaces.native.js +1 -0
- package/dist/jsx/surfaces.native.js.map +1 -1
- package/dist/jsx/views/Calendar.mjs +11 -8
- package/dist/jsx/views/Calendar.mjs.map +1 -1
- package/dist/jsx/views/Calendar.native.js +11 -8
- package/dist/jsx/views/Calendar.native.js.map +1 -1
- package/dist/jsx/views/Dashboard.mjs +6 -6
- package/dist/jsx/views/Dashboard.mjs.map +1 -1
- package/dist/jsx/views/Dashboard.native.js +7 -7
- package/dist/jsx/views/Dashboard.native.js.map +1 -1
- package/dist/jsx/views/Gantt.mjs +3 -3
- package/dist/jsx/views/Gantt.mjs.map +1 -1
- package/dist/jsx/views/Gantt.native.js +3 -3
- package/dist/jsx/views/Gantt.native.js.map +1 -1
- package/dist/jsx/views/Kanban.mjs +2 -2
- package/dist/jsx/views/Kanban.mjs.map +1 -1
- package/dist/jsx/views/Kanban.native.js +2 -2
- package/dist/jsx/views/Kanban.native.js.map +1 -1
- package/dist/jsx/views/ReportBuilder.mjs +4 -4
- package/dist/jsx/views/ReportBuilder.mjs.map +1 -1
- package/dist/jsx/views/ReportBuilder.native.js +4 -4
- package/dist/jsx/views/ReportBuilder.native.js.map +1 -1
- package/dist/jsx/views/TreeView.mjs +249 -20
- package/dist/jsx/views/TreeView.mjs.map +1 -1
- package/dist/jsx/views/TreeView.native.js +264 -20
- package/dist/jsx/views/TreeView.native.js.map +1 -1
- package/dist/jsx/views/treeViewReveal.mjs +29 -0
- package/dist/jsx/views/treeViewReveal.mjs.map +1 -0
- package/dist/jsx/views/treeViewReveal.native.js +80 -0
- package/dist/jsx/views/treeViewReveal.native.js.map +1 -0
- package/package.json +11 -11
- package/src/Accordion/index.tsx +4 -6
- package/src/Chip/index.tsx +1 -1
- package/src/ContextMenu/index.tsx +3 -3
- package/src/DropdownMenu/index.tsx +3 -3
- package/src/Meter/Meter.spec.tsx +12 -4
- package/src/Meter/index.tsx +3 -2
- package/src/Meter/meter.ts +6 -1
- package/src/Pagination.tsx +2 -2
- package/src/ProgressSteps/index.tsx +3 -3
- package/src/Quote/index.tsx +1 -3
- package/src/SheetModal/SheetModal.fill.spec.tsx +147 -0
- package/src/SheetModal/SheetModal.ownedBody.spec.tsx +200 -0
- package/src/SheetModal/SheetModal.stories.spec.tsx +23 -2
- package/src/SheetModal/SheetModal.stories.tsx +275 -2
- package/src/SheetModal/index.native.tsx +50 -6
- package/src/SheetModal/index.tsx +40 -3
- package/src/Tabs/Tabs.lifecycle.spec.tsx +123 -0
- package/src/Tabs/Tabs.measurement.spec.tsx +186 -0
- package/src/Tabs/Tabs.stories.tsx +43 -0
- package/src/Tabs/index.tsx +44 -15
- package/src/Toast/Toast.spec.tsx +120 -48
- package/src/Toast/index.tsx +5 -3
- package/src/TreeSelect/index.tsx +61 -1
- package/src/charts/PieChart.tsx +1 -2
- package/src/code/HighlightedCode/index.tsx +1 -1
- package/src/componentColors.ts +6 -4
- package/src/images/Image/ImageFrame.tsx +2 -2
- package/src/layouts/AsyncBoundary.tsx +1 -2
- package/src/layouts/EmptyState.spec.tsx +58 -1
- package/src/layouts/EmptyState.tsx +11 -7
- package/src/layouts/KeyboardAvoidingWrapper/KeyboardAvoidingWrapper.stories.tsx +3 -3
- package/src/layouts/PaneScaffold.stories.tsx +3 -8
- package/src/layouts/SafeAreaWrapper/SafeAreaWrapper.stories.tsx +3 -3
- package/src/layouts/attachments.tsx +4 -4
- package/src/layouts/breadcrumbs.tsx +1 -2
- package/src/layouts/page.tsx +2 -2
- package/src/layouts/sidebar.tsx +2 -2
- package/src/layouts/tags-trigger.spec.tsx +32 -0
- package/src/layouts/tags.tsx +7 -9
- package/src/layouts/timeline.tsx +5 -5
- package/src/surfaces.spec.tsx +97 -3
- package/src/surfaces.tsx +4 -2
- package/src/textAccentSecondary.spec.tsx +187 -0
- package/src/views/Calendar.tsx +9 -8
- package/src/views/Dashboard.tsx +13 -8
- package/src/views/Gantt.tsx +3 -3
- package/src/views/Kanban.native.tsx +2 -2
- package/src/views/Kanban.tsx +2 -2
- package/src/views/ReportBuilder.tsx +4 -4
- package/src/views/TreeView.reveal.spec.tsx +174 -0
- package/src/views/TreeView.reveal.stories.tsx +249 -0
- package/src/views/TreeView.scroll-index.spec.tsx +246 -0
- package/src/views/TreeView.scroll.spec.tsx +857 -0
- package/src/views/TreeView.spec.tsx +1 -1
- package/src/views/TreeView.tsx +353 -29
- package/src/views/treeViewReveal.spec.ts +83 -0
- package/src/views/treeViewReveal.ts +45 -0
- package/src/views/views.spec.tsx +13 -12
- package/types/Accordion/index.d.ts.map +1 -1
- package/types/Meter/index.d.ts.map +1 -1
- package/types/Meter/meter.d.ts +5 -1
- package/types/Meter/meter.d.ts.map +1 -1
- package/types/Quote/index.d.ts.map +1 -1
- package/types/SheetModal/index.d.ts +8 -1
- package/types/SheetModal/index.d.ts.map +1 -1
- package/types/SheetModal/index.native.d.ts +1 -1
- package/types/SheetModal/index.native.d.ts.map +1 -1
- package/types/Tabs/index.d.ts.map +1 -1
- package/types/Toast/index.d.ts.map +1 -1
- package/types/TreeSelect/index.d.ts +9 -1
- package/types/TreeSelect/index.d.ts.map +1 -1
- package/types/charts/PieChart.d.ts.map +1 -1
- package/types/componentColors.d.ts +1 -4
- package/types/componentColors.d.ts.map +1 -1
- package/types/images/Image/ImageFrame.d.ts.map +1 -1
- package/types/layouts/AsyncBoundary.d.ts.map +1 -1
- package/types/layouts/EmptyState.d.ts.map +1 -1
- package/types/layouts/breadcrumbs.d.ts.map +1 -1
- package/types/layouts/tags.d.ts.map +1 -1
- package/types/surfaces.d.ts.map +1 -1
- package/types/views/Calendar.d.ts.map +1 -1
- package/types/views/Dashboard.d.ts +7 -3
- package/types/views/Dashboard.d.ts.map +1 -1
- package/types/views/TreeView.d.ts +19 -1
- package/types/views/TreeView.d.ts.map +1 -1
- package/types/views/treeViewReveal.d.ts +11 -0
- package/types/views/treeViewReveal.d.ts.map +1 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { act, cleanup, screen } from "@testing-library/react";
|
|
3
|
+
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
4
|
+
import { Tabs, tabsScrollIntoViewX } from "./index";
|
|
5
|
+
|
|
6
|
+
const observed = vi.hoisted(() => ({ scroll: null as any, interactions: new Map<string, any>() }));
|
|
7
|
+
|
|
8
|
+
// The actual component and primitives render. Only public measurement events
|
|
9
|
+
// and the imperative scroll boundary are controlled; this is not browser proof.
|
|
10
|
+
vi.mock("tamagui", async (importOriginal) => {
|
|
11
|
+
const actual = await importOriginal<any>();
|
|
12
|
+
const React = await import("react");
|
|
13
|
+
return {
|
|
14
|
+
...actual,
|
|
15
|
+
ScrollView: React.forwardRef((props: any, ref) => {
|
|
16
|
+
observed.scroll = props;
|
|
17
|
+
return React.createElement(actual.ScrollView, { ...props, ref });
|
|
18
|
+
}),
|
|
19
|
+
styled: (...args: any[]) => {
|
|
20
|
+
const Component = actual.styled(...args);
|
|
21
|
+
if (args[0] !== actual.Tabs.Tab) return Component;
|
|
22
|
+
return React.forwardRef((props: any, ref) => {
|
|
23
|
+
observed.interactions.set(props.value, props.onInteraction);
|
|
24
|
+
return React.createElement(Component, { ...props, ref });
|
|
25
|
+
});
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const items = Array.from({ length: 6 }, (_, index) => ({
|
|
31
|
+
value: `tab-${index}`,
|
|
32
|
+
label: `Tab ${index + 1}`,
|
|
33
|
+
}));
|
|
34
|
+
const last = { x: 500, y: 0, width: 100, height: 40 };
|
|
35
|
+
|
|
36
|
+
afterEach(() => {
|
|
37
|
+
cleanup();
|
|
38
|
+
vi.restoreAllMocks();
|
|
39
|
+
observed.scroll = null;
|
|
40
|
+
observed.interactions.clear();
|
|
41
|
+
document.documentElement.removeAttribute("dir");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
function fixture(mode: "value" | "defaultValue" = "value") {
|
|
45
|
+
const rendered = renderWithProviders(<Tabs items={items} {...{ [mode]: "tab-5" }} />);
|
|
46
|
+
expect(screen.getByRole("tab", { name: "Tab 6" })).toHaveAttribute("aria-selected", "true");
|
|
47
|
+
const host = rendered.container.querySelector('[data-tabs-scroll="true"]') as any;
|
|
48
|
+
expect(typeof host.scrollTo).toBe("function");
|
|
49
|
+
const scroll = vi.spyOn(host, "scrollTo").mockImplementation(() => {});
|
|
50
|
+
const viewport = (width: number) =>
|
|
51
|
+
act(() => observed.scroll.onLayout({ nativeEvent: { layout: { width } } }));
|
|
52
|
+
const content = (width: number) => act(() => observed.scroll.onContentSizeChange(width, 40));
|
|
53
|
+
const active = (layout = last) => act(() => observed.interactions.get("tab-5")("select", layout));
|
|
54
|
+
const manualScroll = (x: number) =>
|
|
55
|
+
act(() => observed.scroll.onScroll({ nativeEvent: { contentOffset: { x } } }));
|
|
56
|
+
return { ...rendered, scroll, viewport, content, active, manualScroll };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
describe.each(["value", "defaultValue"] as const)(
|
|
60
|
+
"Tabs public measurement ordering (%s)",
|
|
61
|
+
(mode) => {
|
|
62
|
+
it("reveals initial last tab when metrics arrive before its layout (control)", () => {
|
|
63
|
+
const tree = fixture(mode);
|
|
64
|
+
tree.viewport(390);
|
|
65
|
+
tree.content(600);
|
|
66
|
+
tree.active();
|
|
67
|
+
expect(tree.scroll).toHaveBeenCalledWith({ x: 210, animated: true });
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("reveals initial last tab when content arrives after its layout", () => {
|
|
71
|
+
const tree = fixture(mode);
|
|
72
|
+
tree.viewport(390);
|
|
73
|
+
tree.active();
|
|
74
|
+
expect(tree.scroll).not.toHaveBeenCalled();
|
|
75
|
+
tree.content(600);
|
|
76
|
+
expect(tree.scroll).toHaveBeenCalled();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("corrects after a viewport shrink with unchanged active-tab bounds", () => {
|
|
80
|
+
const tree = fixture(mode);
|
|
81
|
+
tree.viewport(800);
|
|
82
|
+
tree.content(600);
|
|
83
|
+
tree.active();
|
|
84
|
+
expect(tree.scroll).not.toHaveBeenCalled();
|
|
85
|
+
tree.viewport(390);
|
|
86
|
+
expect(tree.scroll).toHaveBeenCalled();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("does not force a manual scroll back after the active tab was revealed", () => {
|
|
90
|
+
const tree = fixture(mode);
|
|
91
|
+
tree.viewport(390);
|
|
92
|
+
tree.content(600);
|
|
93
|
+
tree.active();
|
|
94
|
+
expect(tree.scroll).toHaveBeenCalledWith({ x: 210, animated: true });
|
|
95
|
+
tree.scroll.mockClear();
|
|
96
|
+
tree.manualScroll(0);
|
|
97
|
+
expect(tree.scroll).not.toHaveBeenCalled();
|
|
98
|
+
});
|
|
99
|
+
},
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
it.each(["value", "defaultValue"] as const)(
|
|
103
|
+
"reveals after late viewport measurement (%s)",
|
|
104
|
+
(mode) => {
|
|
105
|
+
const tree = fixture(mode);
|
|
106
|
+
tree.content(600);
|
|
107
|
+
tree.active();
|
|
108
|
+
expect(tree.scroll).not.toHaveBeenCalled();
|
|
109
|
+
tree.viewport(390);
|
|
110
|
+
expect(tree.scroll).toHaveBeenCalledExactlyOnceWith({ x: 210, animated: true });
|
|
111
|
+
},
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
it("retries after a hidden viewport becomes usable and ignores identical measurements", () => {
|
|
115
|
+
const tree = fixture();
|
|
116
|
+
tree.viewport(0);
|
|
117
|
+
tree.content(600);
|
|
118
|
+
tree.active();
|
|
119
|
+
expect(tree.scroll).not.toHaveBeenCalled();
|
|
120
|
+
tree.viewport(390);
|
|
121
|
+
expect(tree.scroll).toHaveBeenCalledExactlyOnceWith({ x: 210, animated: true });
|
|
122
|
+
tree.manualScroll(210);
|
|
123
|
+
tree.scroll.mockClear();
|
|
124
|
+
tree.viewport(390);
|
|
125
|
+
tree.content(600);
|
|
126
|
+
tree.active();
|
|
127
|
+
expect(tree.scroll).not.toHaveBeenCalled();
|
|
128
|
+
tree.viewport(800);
|
|
129
|
+
expect(tree.scroll).not.toHaveBeenCalled();
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("rechecks changed content width without fighting subsequent manual scroll", () => {
|
|
133
|
+
const tree = fixture();
|
|
134
|
+
tree.viewport(390);
|
|
135
|
+
tree.content(390);
|
|
136
|
+
tree.active();
|
|
137
|
+
expect(tree.scroll).not.toHaveBeenCalled();
|
|
138
|
+
tree.content(600);
|
|
139
|
+
expect(tree.scroll).toHaveBeenCalledExactlyOnceWith({ x: 210, animated: true });
|
|
140
|
+
tree.manualScroll(210);
|
|
141
|
+
tree.scroll.mockClear();
|
|
142
|
+
tree.content(620);
|
|
143
|
+
expect(tree.scroll).toHaveBeenCalledExactlyOnceWith({ x: 230, animated: true });
|
|
144
|
+
tree.manualScroll(230);
|
|
145
|
+
tree.scroll.mockClear();
|
|
146
|
+
tree.manualScroll(0);
|
|
147
|
+
tree.active();
|
|
148
|
+
tree.viewport(390);
|
|
149
|
+
tree.content(620);
|
|
150
|
+
expect(tree.scroll).not.toHaveBeenCalled();
|
|
151
|
+
tree.content(650);
|
|
152
|
+
expect(tree.scroll).toHaveBeenCalledExactlyOnceWith({ x: 242, animated: true });
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("waits for the latest selected tab's layout when dimensions were pending", () => {
|
|
156
|
+
const tree = fixture();
|
|
157
|
+
tree.viewport(390);
|
|
158
|
+
tree.active();
|
|
159
|
+
tree.rerender(<Tabs items={items} value="tab-0" />);
|
|
160
|
+
tree.content(600);
|
|
161
|
+
expect(tree.scroll).not.toHaveBeenCalled();
|
|
162
|
+
act(() => observed.interactions.get("tab-0")("select", { ...last, x: 0 }));
|
|
163
|
+
expect(tree.scroll).not.toHaveBeenCalled();
|
|
164
|
+
expect(screen.getByRole("tab", { name: "Tab 1" })).toHaveAttribute("aria-selected", "true");
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it("uses the negative RTL offset range after delayed dimensions", () => {
|
|
168
|
+
document.documentElement.setAttribute("dir", "rtl");
|
|
169
|
+
const tree = fixture();
|
|
170
|
+
tree.viewport(390);
|
|
171
|
+
tree.active({ ...last, x: 0 });
|
|
172
|
+
tree.content(600);
|
|
173
|
+
expect(tree.scroll).toHaveBeenCalledExactlyOnceWith({ x: -210, animated: true });
|
|
174
|
+
tree.manualScroll(-210);
|
|
175
|
+
tree.scroll.mockClear();
|
|
176
|
+
tree.manualScroll(0);
|
|
177
|
+
expect(tree.scroll).not.toHaveBeenCalled();
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it.each([0, -1, Number.NaN, Number.POSITIVE_INFINITY])(
|
|
181
|
+
"does not scroll with unusable width %s",
|
|
182
|
+
(width) => {
|
|
183
|
+
expect(tabsScrollIntoViewX(last, 0, width, 600, "ltr")).toBeUndefined();
|
|
184
|
+
expect(tabsScrollIntoViewX({ ...last, width }, 0, 390, 600, "ltr")).toBeUndefined();
|
|
185
|
+
},
|
|
186
|
+
);
|
|
@@ -362,3 +362,46 @@ export const EqualSmall: Story = {
|
|
|
362
362
|
</YStack>
|
|
363
363
|
),
|
|
364
364
|
};
|
|
365
|
+
|
|
366
|
+
export const InitialSixthActive: Story = {
|
|
367
|
+
args: { defaultValue: "section-6", ariaLabel: "Example sections" },
|
|
368
|
+
render: (args) => {
|
|
369
|
+
const [wide, setWide] = React.useState(false);
|
|
370
|
+
const [fullLabels, setFullLabels] = React.useState(true);
|
|
371
|
+
const [hidden, setHidden] = React.useState(false);
|
|
372
|
+
const [mount, setMount] = React.useState(0);
|
|
373
|
+
const items: TabsItem[] = Array.from({ length: 6 }, (_, index) => ({
|
|
374
|
+
value: `section-${index + 1}`,
|
|
375
|
+
label: fullLabels ? `Section ${index + 1} overview` : `${index + 1}`,
|
|
376
|
+
content: (
|
|
377
|
+
<Panel
|
|
378
|
+
title={`Section ${index + 1}`}
|
|
379
|
+
body="The selected section stays visible when the strip is measured or resized."
|
|
380
|
+
/>
|
|
381
|
+
),
|
|
382
|
+
}));
|
|
383
|
+
return (
|
|
384
|
+
<YStack gap="$3">
|
|
385
|
+
<XStack gap="$2" flexWrap="wrap">
|
|
386
|
+
<Button onPress={() => setWide((value) => !value)}>
|
|
387
|
+
{wide ? "Set width to 390px" : "Set width to 800px"}
|
|
388
|
+
</Button>
|
|
389
|
+
<Button onPress={() => setFullLabels((value) => !value)}>
|
|
390
|
+
{fullLabels ? "Use short labels" : "Load full labels"}
|
|
391
|
+
</Button>
|
|
392
|
+
<Button onPress={() => setHidden((value) => !value)}>
|
|
393
|
+
{hidden ? "Show strip" : "Hide strip"}
|
|
394
|
+
</Button>
|
|
395
|
+
<Button onPress={() => setMount((value) => value + 1)}>Reset to sixth tab</Button>
|
|
396
|
+
</XStack>
|
|
397
|
+
<Text color="$color11">
|
|
398
|
+
Use short labels, then load full labels to change content width. Hide and show the strip
|
|
399
|
+
to defer usable measurements. Scroll manually after reveal to check that it stays put.
|
|
400
|
+
</Text>
|
|
401
|
+
<YStack width={wide ? 800 : 390} maxWidth="100%" display={hidden ? "none" : "flex"}>
|
|
402
|
+
<Tabs key={mount} {...args} items={items} />
|
|
403
|
+
</YStack>
|
|
404
|
+
</YStack>
|
|
405
|
+
);
|
|
406
|
+
},
|
|
407
|
+
};
|
package/src/Tabs/index.tsx
CHANGED
|
@@ -174,6 +174,14 @@ export function tabsScrollIntoViewX(
|
|
|
174
174
|
direction: TabsDirection,
|
|
175
175
|
pad = 32,
|
|
176
176
|
): number | undefined {
|
|
177
|
+
if (
|
|
178
|
+
![layout.x, layout.width, layout.height, offset, viewport, content].every(Number.isFinite) ||
|
|
179
|
+
layout.width <= 0 ||
|
|
180
|
+
layout.height <= 0 ||
|
|
181
|
+
viewport <= 0 ||
|
|
182
|
+
content <= 0
|
|
183
|
+
)
|
|
184
|
+
return undefined;
|
|
177
185
|
const range = Math.max(content - viewport, 0);
|
|
178
186
|
if (range <= 0) return undefined;
|
|
179
187
|
const minScrollLeft = direction === "rtl" ? -range : 0;
|
|
@@ -366,23 +374,28 @@ function TabsRoot({
|
|
|
366
374
|
};
|
|
367
375
|
|
|
368
376
|
// Active tab layout (relative to the list) for the sliding indicator
|
|
369
|
-
const [activeLayout, setActiveLayout] = React.useState<TabLayout | null>(
|
|
370
|
-
|
|
371
|
-
|
|
377
|
+
const [activeLayout, setActiveLayout] = React.useState<(TabLayout & { value: string }) | null>(
|
|
378
|
+
null,
|
|
379
|
+
);
|
|
380
|
+
const handleInteraction = (tabValue: string, type: string, layout: TabLayout | null) => {
|
|
381
|
+
if (type !== "select" || !layout || tabValue !== currentValue) return;
|
|
372
382
|
setActiveLayout((prev) =>
|
|
373
383
|
prev &&
|
|
384
|
+
prev.value === tabValue &&
|
|
374
385
|
prev.x === layout.x &&
|
|
375
386
|
prev.y === layout.y &&
|
|
376
387
|
prev.width === layout.width &&
|
|
377
388
|
prev.height === layout.height
|
|
378
389
|
? prev
|
|
379
|
-
: layout,
|
|
390
|
+
: { ...layout, value: tabValue },
|
|
380
391
|
);
|
|
381
392
|
};
|
|
382
393
|
|
|
383
394
|
// Overflow tracking for edge fades + keep-active-visible scrolling
|
|
384
395
|
const scrollRef = React.useRef<ScrollView>(null);
|
|
396
|
+
const tabRefs = React.useRef(new Map<string, HTMLElement>());
|
|
385
397
|
const scrollMetrics = React.useRef({ offset: 0, viewport: 0, content: 0 });
|
|
398
|
+
const [sizeRevision, setSizeRevision] = React.useState(0);
|
|
386
399
|
const [fades, setFades] = React.useState({ left: false, right: false });
|
|
387
400
|
const updateFades = () => {
|
|
388
401
|
const { offset, viewport, content } = scrollMetrics.current;
|
|
@@ -390,20 +403,38 @@ function TabsRoot({
|
|
|
390
403
|
setFades((prev) => (prev.left === next.left && prev.right === next.right ? prev : next));
|
|
391
404
|
};
|
|
392
405
|
|
|
406
|
+
const updateScrollSize = (dimension: "viewport" | "content", size: number) => {
|
|
407
|
+
if (!Object.is(scrollMetrics.current[dimension], size)) {
|
|
408
|
+
scrollMetrics.current[dimension] = size;
|
|
409
|
+
if (isWeb) {
|
|
410
|
+
const selected = tabRefs.current.get(currentValue);
|
|
411
|
+
if (selected && selected.offsetWidth > 0 && selected.offsetHeight > 0) {
|
|
412
|
+
handleInteraction(currentValue, "select", {
|
|
413
|
+
x: selected.offsetLeft,
|
|
414
|
+
y: selected.offsetTop,
|
|
415
|
+
width: selected.offsetWidth,
|
|
416
|
+
height: selected.offsetHeight,
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
setSizeRevision((current) => current + 1);
|
|
421
|
+
}
|
|
422
|
+
updateFades();
|
|
423
|
+
};
|
|
424
|
+
|
|
393
425
|
// Scroll the newly active tab into view when it is clipped
|
|
394
426
|
React.useEffect(() => {
|
|
395
|
-
if (!activeLayout) return;
|
|
427
|
+
if (!activeLayout || activeLayout.value !== currentValue) return;
|
|
396
428
|
const { offset, viewport, content } = scrollMetrics.current;
|
|
397
429
|
const target = tabsScrollIntoViewX(activeLayout, offset, viewport, content, direction);
|
|
398
|
-
if (target !== undefined) {
|
|
430
|
+
if (target !== undefined && Math.abs(target - offset) >= 1) {
|
|
399
431
|
scrollRef.current?.scrollTo({ x: target, animated: true });
|
|
400
432
|
}
|
|
401
|
-
}, [activeLayout, direction]);
|
|
433
|
+
}, [activeLayout, currentValue, direction, sizeRevision]);
|
|
402
434
|
|
|
403
435
|
const isUnderline = variant === "underline";
|
|
404
436
|
const isBand = variant === "band";
|
|
405
437
|
const equalDistribution = isBand || distribution === "equal";
|
|
406
|
-
const tabRefs = React.useRef(new Map<string, HTMLElement>());
|
|
407
438
|
const onTabKeyDown = (event: React.KeyboardEvent, value: string) => {
|
|
408
439
|
if (!["Home", "End", "ArrowLeft", "ArrowRight"].includes(event.key)) return;
|
|
409
440
|
const enabled = items.filter((item) => !disabled && !item.disabled);
|
|
@@ -576,7 +607,7 @@ function TabsRoot({
|
|
|
576
607
|
accessibilityState: { selected: isActive, disabled: Boolean(isDisabled) },
|
|
577
608
|
})}
|
|
578
609
|
hitSlop={tabHitSlop}
|
|
579
|
-
onInteraction={handleInteraction}
|
|
610
|
+
onInteraction={(type, layout) => handleInteraction(item.value, type, layout)}
|
|
580
611
|
cursor={isDisabled ? "not-allowed" : "pointer"}
|
|
581
612
|
backgroundColor={
|
|
582
613
|
isBand
|
|
@@ -645,12 +676,12 @@ function TabsRoot({
|
|
|
645
676
|
fontWeight={!isBand && isActive ? "700" : knobProps.label.fontWeight}
|
|
646
677
|
color={
|
|
647
678
|
isDisabled
|
|
648
|
-
?
|
|
679
|
+
? disabledState.textKnobProps.color
|
|
649
680
|
: isActive
|
|
650
681
|
? variant === "contained" && onSelectedTint
|
|
651
682
|
? onSelectedTint
|
|
652
683
|
: componentColors.text.primary
|
|
653
|
-
:
|
|
684
|
+
: knobProps.textAccentColor
|
|
654
685
|
}
|
|
655
686
|
>
|
|
656
687
|
{wrapBareTextChildren(item.label, (label) => label)}
|
|
@@ -716,12 +747,10 @@ function TabsRoot({
|
|
|
716
747
|
updateFades();
|
|
717
748
|
}}
|
|
718
749
|
onLayout={(e) => {
|
|
719
|
-
|
|
720
|
-
updateFades();
|
|
750
|
+
updateScrollSize("viewport", e.nativeEvent.layout.width);
|
|
721
751
|
}}
|
|
722
752
|
onContentSizeChange={(w) => {
|
|
723
|
-
|
|
724
|
-
updateFades();
|
|
753
|
+
updateScrollSize("content", w);
|
|
725
754
|
}}
|
|
726
755
|
>
|
|
727
756
|
{tabList}
|
package/src/Toast/Toast.spec.tsx
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import { fireEvent, screen, act, cleanup } from "@testing-library/react";
|
|
2
|
-
import type { ReactElement } from "react";
|
|
2
|
+
import type { ReactElement, ReactNode } from "react";
|
|
3
3
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
4
4
|
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
5
|
-
import { Button, SizableText,
|
|
5
|
+
import { Button, SizableText, TamaguiProvider, useTheme, YStack } from "tamagui";
|
|
6
6
|
import {
|
|
7
7
|
__resetDevWarnSeen,
|
|
8
8
|
aaTextContrastRatio,
|
|
9
|
-
|
|
9
|
+
createDefaultThemeConfig,
|
|
10
|
+
createThemesBuilder,
|
|
11
|
+
defaultAccentTheme,
|
|
12
|
+
defaultBaseTheme,
|
|
13
|
+
defaultBuilderOptions,
|
|
14
|
+
measureContrast,
|
|
10
15
|
normalizeToHex,
|
|
11
16
|
Preset,
|
|
12
|
-
relativeLuminance,
|
|
13
17
|
useAccentOnSurface,
|
|
14
18
|
} from "@multiplatform.one/theme";
|
|
15
19
|
import { Toast, ToastViewport, useToast, nativeToastA11y, nativeToastControlA11y } from "./index";
|
|
@@ -514,35 +518,91 @@ function tokenVal(theme: ReturnType<typeof useTheme>, key: string): string {
|
|
|
514
518
|
return typeof raw === "string" ? raw : "";
|
|
515
519
|
}
|
|
516
520
|
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
521
|
+
const TOAST_INTENTS = ["accent", "success", "warning", "error"] as const;
|
|
522
|
+
const CONTRAST_SCHEMES = ["light", "dark"] as const;
|
|
523
|
+
|
|
524
|
+
const houseConfig = createDefaultThemeConfig();
|
|
525
|
+
const houseThemes = createThemesBuilder(
|
|
526
|
+
defaultBaseTheme,
|
|
527
|
+
defaultAccentTheme,
|
|
528
|
+
defaultBuilderOptions,
|
|
529
|
+
).themes() as Record<string, Record<string, string>>;
|
|
530
|
+
|
|
531
|
+
/**
|
|
532
|
+
* The HOUSE config, not the stock one `renderWithProviders` mounts. The
|
|
533
|
+
* intent sub-themes the Toast wraps in (`light_warning`, ...) exist only
|
|
534
|
+
* there; under stock the wrap falls back to the base ramp and the arm
|
|
535
|
+
* certifies a pair the product never paints.
|
|
536
|
+
*/
|
|
537
|
+
function ContrastScheme({
|
|
538
|
+
scheme,
|
|
539
|
+
children,
|
|
540
|
+
}: {
|
|
541
|
+
scheme: (typeof CONTRAST_SCHEMES)[number];
|
|
542
|
+
children: ReactNode;
|
|
543
|
+
}) {
|
|
528
544
|
return (
|
|
529
|
-
|
|
530
|
-
<
|
|
531
|
-
|
|
532
|
-
title="Archived"
|
|
533
|
-
intent={intent}
|
|
534
|
-
action={{ label: ACTION, onPress: () => {} }}
|
|
535
|
-
onDismiss={() => {}}
|
|
536
|
-
/>
|
|
537
|
-
</>
|
|
545
|
+
<TamaguiProvider config={houseConfig.tamagui} defaultTheme={scheme} disableInjectCSS>
|
|
546
|
+
<YStack backgroundColor="$background">{children}</YStack>
|
|
547
|
+
</TamaguiProvider>
|
|
538
548
|
);
|
|
539
549
|
}
|
|
540
550
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
551
|
+
/**
|
|
552
|
+
* Accent toasts stay on the BASE theme and take their ink from
|
|
553
|
+
* `useAccentOnSurface()` -- a picked value, not a token the label can name in
|
|
554
|
+
* a class. Stamp it from inside the theme the Toast mounts in.
|
|
555
|
+
*/
|
|
556
|
+
function AccentInkProbe() {
|
|
557
|
+
const onSurface = useAccentOnSurface();
|
|
558
|
+
const theme = useTheme();
|
|
559
|
+
const ink = onSurface.startsWith("$")
|
|
560
|
+
? tokenVal(theme, onSurface.slice(1)) || onSurface
|
|
561
|
+
: onSurface;
|
|
562
|
+
return <span data-testid="accent-ink" data-fg={ink} />;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* The RESTING atom for a prefix. Tamagui spells state atoms `_o-0hover-1` /
|
|
567
|
+
* `_bg-0active-color5`, so a bare prefix read picks up hover paint and
|
|
568
|
+
* certifies a surface nobody rests on.
|
|
569
|
+
*/
|
|
570
|
+
function restAtom(node: Element, prefix: string): string | undefined {
|
|
571
|
+
for (const cls of Array.from(node.classList)) {
|
|
572
|
+
if (!cls.startsWith(prefix)) continue;
|
|
573
|
+
const value = cls.slice(prefix.length);
|
|
574
|
+
if (/^\d*(hover|active|focus|press|disabled)/.test(value)) continue;
|
|
575
|
+
return value;
|
|
576
|
+
}
|
|
577
|
+
return undefined;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/** `_o-0--9` is Tamagui's atom for 0.9; no resting atom means no rest dim. */
|
|
581
|
+
function restOpacity(node: Element): number {
|
|
582
|
+
const atom = restAtom(node, "_o-");
|
|
583
|
+
if (atom === undefined) return 1;
|
|
584
|
+
const value = Number(atom.replaceAll("--", "."));
|
|
585
|
+
return Number.isFinite(value) ? value : 1;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* The ink as PAINTED. An opacity on the press target multiplies the label
|
|
590
|
+
* toward the fill under it, so the token pair is not what a reader sees:
|
|
591
|
+
* MPO-128's warning action measures 4.66:1 as tokens and 3.88:1 as pixels.
|
|
592
|
+
*/
|
|
593
|
+
function paintedInk(ink: string, ground: string, alpha: number): string {
|
|
594
|
+
const f = normalizeToHex(ink);
|
|
595
|
+
const b = normalizeToHex(ground);
|
|
596
|
+
if (!f || !b) return ink;
|
|
597
|
+
if (alpha >= 1) return f;
|
|
598
|
+
const channel = (offset: number) =>
|
|
599
|
+
Math.round(
|
|
600
|
+
Number.parseInt(f.slice(offset, offset + 2), 16) * alpha +
|
|
601
|
+
Number.parseInt(b.slice(offset, offset + 2), 16) * (1 - alpha),
|
|
602
|
+
)
|
|
603
|
+
.toString(16)
|
|
604
|
+
.padStart(2, "0");
|
|
605
|
+
return `#${channel(1)}${channel(3)}${channel(5)}`;
|
|
546
606
|
}
|
|
547
607
|
|
|
548
608
|
describe("Toast overlay shadow (standalone === viewport)", () => {
|
|
@@ -694,28 +754,40 @@ describe("Toast action label weight and contrast (TEXT NODE)", () => {
|
|
|
694
754
|
expect(screen.getByTestId("toast").contains(textNode)).toBe(true);
|
|
695
755
|
});
|
|
696
756
|
|
|
697
|
-
it.each(
|
|
698
|
-
"%s action label clears
|
|
757
|
+
it.each(TOAST_INTENTS)(
|
|
758
|
+
"%s action label clears the AA floor AS PAINTED, in light and dark",
|
|
699
759
|
(intent) => {
|
|
700
|
-
for (const scheme of
|
|
760
|
+
for (const scheme of CONTRAST_SCHEMES) {
|
|
701
761
|
renderWithProviders(
|
|
702
|
-
<
|
|
703
|
-
<
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
const labelColor = (label as HTMLElement).style.color;
|
|
712
|
-
const pillBg = (pill as HTMLElement).style.backgroundColor;
|
|
713
|
-
const fromProbe = measuredRatio(fg, bg);
|
|
714
|
-
const fromNodes = measuredRatio(labelColor || fg, pillBg || bg);
|
|
715
|
-
const ratio = Number.isFinite(fromNodes) ? fromNodes : fromProbe;
|
|
716
|
-
expect(ratio, `${scheme} ${intent} ${fg} on ${bg}`).toBeGreaterThanOrEqual(
|
|
717
|
-
aaTextContrastRatio,
|
|
762
|
+
<ContrastScheme scheme={scheme}>
|
|
763
|
+
<AccentInkProbe />
|
|
764
|
+
<Toast
|
|
765
|
+
title="Archived"
|
|
766
|
+
intent={intent}
|
|
767
|
+
action={{ label: ACTION, onPress: () => {} }}
|
|
768
|
+
onDismiss={() => {}}
|
|
769
|
+
/>
|
|
770
|
+
</ContrastScheme>,
|
|
718
771
|
);
|
|
772
|
+
// Non-accent intents ride their hue sub-theme; accent stays on base.
|
|
773
|
+
const theme = houseThemes[intent === "accent" ? scheme : `${scheme}_${intent}`];
|
|
774
|
+
const groundToken = restAtom(screen.getByTestId("toast"), "_bg-");
|
|
775
|
+
const inkToken = restAtom(screen.getByText(ACTION), "_col-");
|
|
776
|
+
const ground = theme?.[groundToken ?? ""] ?? "";
|
|
777
|
+
const ink =
|
|
778
|
+
intent === "accent"
|
|
779
|
+
? (screen.getByTestId("accent-ink").getAttribute("data-fg") ?? "")
|
|
780
|
+
: (theme?.[inkToken ?? ""] ?? "");
|
|
781
|
+
const where = `${scheme} ${intent}: ${inkToken ?? "?"} on ${groundToken ?? "?"}`;
|
|
782
|
+
expect(ground, `${where} -- the toast frame paints no resting fill`).toBeTruthy();
|
|
783
|
+
expect(ink, `${where} -- the action label emits no resting ink`).toBeTruthy();
|
|
784
|
+
const alpha = restOpacity(screen.getByLabelText(ACTION));
|
|
785
|
+
const report = measureContrast({
|
|
786
|
+
foreground: paintedInk(ink, ground, alpha),
|
|
787
|
+
background: ground,
|
|
788
|
+
label: `${where} at rest opacity ${alpha}`,
|
|
789
|
+
});
|
|
790
|
+
expect(report.ratio, report.label).toBeGreaterThanOrEqual(aaTextContrastRatio);
|
|
719
791
|
cleanup();
|
|
720
792
|
}
|
|
721
793
|
},
|
package/src/Toast/index.tsx
CHANGED
|
@@ -283,12 +283,14 @@ const ToastActionTarget = styled(View, {
|
|
|
283
283
|
alignItems: "center",
|
|
284
284
|
justifyContent: "center",
|
|
285
285
|
flexShrink: 0,
|
|
286
|
-
|
|
286
|
+
// No REST dim. The label is $color11 — the lowest AA-safe step of the hue —
|
|
287
|
+
// sitting straight on the toast fill, so it carries no headroom for a
|
|
288
|
+
// multiplier: 0.9 composited every light intent under 4.5 (MPO-128). Hover
|
|
289
|
+
// and press read off the pill's own fill instead.
|
|
287
290
|
outlineWidth: 0,
|
|
288
|
-
hoverStyle: { opacity: 1 },
|
|
289
291
|
pressStyle: { opacity: 0.95 },
|
|
290
292
|
focusStyle: { outlineWidth: 0 },
|
|
291
|
-
focusVisibleStyle: {
|
|
293
|
+
focusVisibleStyle: { outlineWidth: 0 },
|
|
292
294
|
});
|
|
293
295
|
|
|
294
296
|
const ToastActionPill = styled(View, {
|