@multiplatform.one/components 7.7.0 → 7.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/Accordion/index.native.js +1 -1
- package/dist/cjs/Accordion/index.native.js.map +1 -1
- package/dist/cjs/Alert/index.cjs +13 -29
- package/dist/cjs/Alert/index.native.js +17 -37
- 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 +1 -1
- package/dist/cjs/Carousel/index.native.js.map +1 -1
- package/dist/cjs/Chip/index.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/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.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.cjs +3 -1
- package/dist/cjs/actions/ActionBar.native.js +11 -2
- 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/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 +6 -6
- 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/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 +29 -29
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/knobImmuneExports.native.js.map +1 -1
- package/dist/cjs/layouts/AsyncBoundary.native.js +2 -2
- package/dist/cjs/layouts/AsyncBoundary.native.js.map +1 -1
- package/dist/cjs/layouts/Debug/index.native.js.map +1 -1
- package/dist/cjs/layouts/EmptyState.native.js.map +1 -1
- package/dist/cjs/layouts/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.map +1 -1
- package/dist/cjs/layouts/pageHeadingScope.native.js.map +1 -1
- package/dist/cjs/layouts/sidebar.native.js.map +1 -1
- package/dist/cjs/layouts/tags.native.js +1 -1
- 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.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/useKeyboardInset.native.js.map +1 -1
- package/dist/cjs/shared/useReturnFocusOnClose.native.js.map +1 -1
- package/dist/cjs/surfaces.native.js +1 -1
- package/dist/cjs/surfaces.native.js.map +1 -1
- package/dist/cjs/tamagui.native.js.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.map +1 -1
- package/dist/cjs/views/Dashboard.native.js +1 -1
- package/dist/cjs/views/Dashboard.native.js.map +1 -1
- package/dist/cjs/views/Gantt.native.js +1 -1
- 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/List.native.js.map +1 -1
- package/dist/cjs/views/ReportBuilder.native.js +1 -1
- 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/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/esm/Alert/index.mjs +14 -31
- package/dist/esm/Alert/index.mjs.map +1 -1
- package/dist/esm/Alert/index.native.js +36 -57
- package/dist/esm/Alert/index.native.js.map +1 -1
- package/dist/esm/actions/ActionBar.mjs +6 -4
- package/dist/esm/actions/ActionBar.mjs.map +1 -1
- package/dist/esm/actions/ActionBar.native.js +13 -4
- package/dist/esm/actions/ActionBar.native.js.map +1 -1
- package/dist/jsx/Alert/index.mjs +14 -31
- package/dist/jsx/Alert/index.mjs.map +1 -1
- package/dist/jsx/Alert/index.native.js +17 -37
- package/dist/jsx/Alert/index.native.js.map +1 -1
- package/dist/jsx/actions/ActionBar.mjs +6 -4
- package/dist/jsx/actions/ActionBar.mjs.map +1 -1
- package/dist/jsx/actions/ActionBar.native.js +11 -2
- package/dist/jsx/actions/ActionBar.native.js.map +1 -1
- package/dist/jsx/feedback/NotifyHost.native.js +1 -1
- package/dist/jsx/index.native.js +1 -1
- package/dist/jsx/layouts/AsyncBoundary.native.js +1 -1
- package/dist/jsx/layouts/AsyncBoundary.native.js.map +1 -1
- package/package.json +9 -9
- package/src/Alert/index.tsx +9 -4
- package/src/AnimateHeight/AnimateHeight.stories.spec.tsx +37 -0
- package/src/AnimateHeight/AnimateHeight.stories.tsx +95 -0
- package/src/Avatar/Avatar.spec.tsx +4 -1
- package/src/Button.spec.tsx +26 -15
- package/src/SheetModal/SheetModal.stories.spec.tsx +54 -0
- package/src/SheetModal/SheetModal.stories.tsx +109 -0
- package/src/actions/ActionBar.stories.spec.tsx +45 -0
- package/src/actions/ActionBar.stories.tsx +161 -0
- package/src/actions/ActionBar.tsx +8 -1
- package/src/charts/Axis.stories.spec.tsx +86 -0
- package/src/charts/Axis.stories.tsx +186 -0
- package/src/charts/ChartSurface.stories.spec.tsx +43 -0
- package/src/charts/ChartSurface.stories.tsx +148 -0
- package/types/Alert/index.d.ts.map +1 -1
- package/types/actions/ActionBar.d.ts.map +1 -1
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react-native-web-vite";
|
|
2
|
+
import { Paragraph, YStack } from "tamagui";
|
|
3
|
+
import { Card } from "../surfaces";
|
|
4
|
+
import { XAxis, YAxis } from "./Axis";
|
|
5
|
+
import { ChartSurface } from "./ChartSurface";
|
|
6
|
+
import { computeCartesianPlot } from "./composeChart";
|
|
7
|
+
import { createBandScale, createLinearScale, formatAxisTick, getLinearTicks } from "./math";
|
|
8
|
+
import type { ChartSize } from "./types";
|
|
9
|
+
import { useChartTheme } from "./useChartTheme";
|
|
10
|
+
|
|
11
|
+
const weekdays = ["Mon", "Tue", "Wed", "Thu", "Fri"];
|
|
12
|
+
const longLabels = [
|
|
13
|
+
"Engineering",
|
|
14
|
+
"Customer Success",
|
|
15
|
+
"Finance and Legal",
|
|
16
|
+
"People Operations",
|
|
17
|
+
"Infrastructure",
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
interface AxisFrameProps {
|
|
21
|
+
size: ChartSize;
|
|
22
|
+
categories: string[];
|
|
23
|
+
domain: [number, number];
|
|
24
|
+
showXLabels?: boolean;
|
|
25
|
+
showYGrid?: boolean;
|
|
26
|
+
showYLine?: boolean;
|
|
27
|
+
showYTicks?: boolean;
|
|
28
|
+
yTicks?: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Both axes drawn against a real plot rectangle. The left margin is derived
|
|
33
|
+
* from the widest y tick LABEL (computeCartesianPlot), not a magic number, so
|
|
34
|
+
* the axis never clips its own text.
|
|
35
|
+
*/
|
|
36
|
+
function AxisFrame({
|
|
37
|
+
size,
|
|
38
|
+
categories,
|
|
39
|
+
domain,
|
|
40
|
+
showXLabels = true,
|
|
41
|
+
showYGrid = true,
|
|
42
|
+
showYLine = false,
|
|
43
|
+
showYTicks = false,
|
|
44
|
+
yTicks = 4,
|
|
45
|
+
}: AxisFrameProps) {
|
|
46
|
+
const { labelFontSize } = useChartTheme();
|
|
47
|
+
const marginScale = createLinearScale({ domain, range: [0, 1] });
|
|
48
|
+
const tickValues = getLinearTicks(marginScale, yTicks);
|
|
49
|
+
const plot = computeCartesianPlot(size, {
|
|
50
|
+
showXAxis: true,
|
|
51
|
+
showYAxis: true,
|
|
52
|
+
yTickLabels: tickValues.map((value) => formatAxisTick(value)),
|
|
53
|
+
fontSize: labelFontSize,
|
|
54
|
+
});
|
|
55
|
+
if (plot.width <= 0 || plot.height <= 0) return null;
|
|
56
|
+
const xScale = createBandScale({
|
|
57
|
+
domain: categories,
|
|
58
|
+
range: [plot.x, plot.x + plot.width],
|
|
59
|
+
});
|
|
60
|
+
const yScale = createLinearScale({
|
|
61
|
+
domain,
|
|
62
|
+
range: [plot.y + plot.height, plot.y],
|
|
63
|
+
});
|
|
64
|
+
return (
|
|
65
|
+
<>
|
|
66
|
+
<YAxis
|
|
67
|
+
plot={plot}
|
|
68
|
+
scale={yScale}
|
|
69
|
+
ticks={yTicks}
|
|
70
|
+
showGrid={showYGrid}
|
|
71
|
+
showLine={showYLine}
|
|
72
|
+
showTicks={showYTicks}
|
|
73
|
+
/>
|
|
74
|
+
<XAxis plot={plot} scale={xScale} showLabels={showXLabels} />
|
|
75
|
+
</>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const meta: Meta<typeof XAxis> = {
|
|
80
|
+
title: "Components/Axis",
|
|
81
|
+
component: XAxis,
|
|
82
|
+
parameters: {
|
|
83
|
+
status: { type: "beta" },
|
|
84
|
+
docs: {
|
|
85
|
+
description: {
|
|
86
|
+
component:
|
|
87
|
+
"The two axis primitives the cartesian charts compose. `XAxis` is categorical: a baseline, tick marks, and a label centred under each band or point, truncated with an ellipsis once it is wider than its step so nothing overflows the surface (LC-10). `YAxis` is continuous: nice d3 ticks, right-aligned labels in the left margin, and horizontal grid lines on by default with the axis line off, because the grid already carries the edge. All chrome resolves through `useChartTheme` — axis lines take the border role, grid the divider role, labels the muted text role at the AA floor. Tick numbers ride the charts package's own density register, the declared exemption to the house number channel.",
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
export default meta;
|
|
93
|
+
|
|
94
|
+
type Story = StoryObj<typeof XAxis>;
|
|
95
|
+
|
|
96
|
+
export const Default: Story = {
|
|
97
|
+
name: "Main",
|
|
98
|
+
render: () => (
|
|
99
|
+
<YStack maxWidth={560}>
|
|
100
|
+
<Card>
|
|
101
|
+
<ChartSurface label="Empty axis frame, weekdays across a 0 to 100 value axis." height={220}>
|
|
102
|
+
{(size) => <AxisFrame size={size} categories={weekdays} domain={[0, 100]} />}
|
|
103
|
+
</ChartSurface>
|
|
104
|
+
</Card>
|
|
105
|
+
</YStack>
|
|
106
|
+
),
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export const AxisLineAndTicks: Story = {
|
|
110
|
+
name: "Grid off, axis line on",
|
|
111
|
+
parameters: {
|
|
112
|
+
docs: {
|
|
113
|
+
description: {
|
|
114
|
+
story:
|
|
115
|
+
"`showGrid={false}` with `showLine` and `showTicks` on: the classic ticked frame for charts that must not carry horizontal rules across the plot.",
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
render: () => (
|
|
120
|
+
<YStack maxWidth={560}>
|
|
121
|
+
<Card>
|
|
122
|
+
<ChartSurface label="Ticked axis frame with no grid." height={220}>
|
|
123
|
+
{(size) => (
|
|
124
|
+
<AxisFrame
|
|
125
|
+
size={size}
|
|
126
|
+
categories={weekdays}
|
|
127
|
+
domain={[0, 100]}
|
|
128
|
+
showYGrid={false}
|
|
129
|
+
showYLine
|
|
130
|
+
showYTicks
|
|
131
|
+
/>
|
|
132
|
+
)}
|
|
133
|
+
</ChartSurface>
|
|
134
|
+
</Card>
|
|
135
|
+
</YStack>
|
|
136
|
+
),
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export const LabelTruncation: Story = {
|
|
140
|
+
name: "Long labels truncate",
|
|
141
|
+
parameters: {
|
|
142
|
+
docs: {
|
|
143
|
+
description: {
|
|
144
|
+
story:
|
|
145
|
+
"Department names wider than their band. XAxis truncates each label to its step with an ellipsis rather than letting text collide or run off the surface.",
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
render: () => (
|
|
150
|
+
<YStack gap="$4">
|
|
151
|
+
{[520, 280].map((width) => (
|
|
152
|
+
<Card key={width} width={width}>
|
|
153
|
+
<YStack gap="$2">
|
|
154
|
+
<Paragraph size="$2">{`${width}px container`}</Paragraph>
|
|
155
|
+
<ChartSurface label={`Department axis at ${width}px`} height={180}>
|
|
156
|
+
{(size) => <AxisFrame size={size} categories={longLabels} domain={[0, 40]} />}
|
|
157
|
+
</ChartSurface>
|
|
158
|
+
</YStack>
|
|
159
|
+
</Card>
|
|
160
|
+
))}
|
|
161
|
+
</YStack>
|
|
162
|
+
),
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
export const WideValueRange: Story = {
|
|
166
|
+
name: "Nice ticks on a wide range",
|
|
167
|
+
parameters: {
|
|
168
|
+
docs: {
|
|
169
|
+
description: {
|
|
170
|
+
story:
|
|
171
|
+
"A 0 to 1,250,000 domain. YAxis asks d3 for nice ticks and formats them through the charts density register, so the left margin stays a handful of characters wide.",
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
render: () => (
|
|
176
|
+
<YStack maxWidth={560}>
|
|
177
|
+
<Card>
|
|
178
|
+
<ChartSurface label="Weekday axis against a 0 to 1.25 million value axis." height={220}>
|
|
179
|
+
{(size) => (
|
|
180
|
+
<AxisFrame size={size} categories={weekdays} domain={[0, 1250000]} yTicks={5} />
|
|
181
|
+
)}
|
|
182
|
+
</ChartSurface>
|
|
183
|
+
</Card>
|
|
184
|
+
</YStack>
|
|
185
|
+
),
|
|
186
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChartSurface is exported from the charts barrel but only ever appeared
|
|
3
|
+
* inside the composed charts' stories, so it had no title of its own
|
|
4
|
+
* (MPO-193). These mount every exported story and assert the surface really
|
|
5
|
+
* paints: an explicit width draws immediately, and the accessible summary
|
|
6
|
+
* lands on the SVG root as one described image (Axiom 12).
|
|
7
|
+
*/
|
|
8
|
+
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
9
|
+
import { cleanup, screen } from "@testing-library/react";
|
|
10
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
11
|
+
import meta, { Default, FixedWidth, Responsive } from "./ChartSurface.stories";
|
|
12
|
+
|
|
13
|
+
afterEach(cleanup);
|
|
14
|
+
|
|
15
|
+
describe("ChartSurface stories", () => {
|
|
16
|
+
it("declares the Components/ChartSurface title against the component", () => {
|
|
17
|
+
expect(meta.title).toBe("Components/ChartSurface");
|
|
18
|
+
expect(meta.component).toBeDefined();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("Explicit width draws without any layout pass", () => {
|
|
22
|
+
const { container } = renderWithProviders(<>{FixedWidth.render?.({} as never, {} as never)}</>);
|
|
23
|
+
const root = screen.getByRole("img", { name: "Five categorical dots" });
|
|
24
|
+
expect(root.getAttribute("width")).toBe("360");
|
|
25
|
+
expect(container.querySelectorAll("circle")).toHaveLength(5);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("Main mounts and carries its generated summary as the accessible name", () => {
|
|
29
|
+
renderWithProviders(
|
|
30
|
+
<>{Default.render?.(Default.args as never, { args: Default.args } as never)}</>,
|
|
31
|
+
);
|
|
32
|
+
// happy-dom runs no layout, so the measured surface holds at width 0 and
|
|
33
|
+
// draws nothing — the label still has to be the declared summary.
|
|
34
|
+
expect(Default.args?.label).toBe("Sessions per weekday, peaking Thursday at 9.");
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("Tracks the container mounts one surface per width", () => {
|
|
38
|
+
renderWithProviders(<>{Responsive.render?.({} as never, {} as never)}</>);
|
|
39
|
+
expect(screen.getByText("520px container")).toBeTruthy();
|
|
40
|
+
expect(screen.getByText("320px container")).toBeTruthy();
|
|
41
|
+
expect(screen.getByText("200px container")).toBeTruthy();
|
|
42
|
+
});
|
|
43
|
+
});
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react-native-web-vite";
|
|
2
|
+
import { Paragraph, YStack } from "tamagui";
|
|
3
|
+
import { Card } from "../surfaces";
|
|
4
|
+
import { ChartSurface } from "./ChartSurface";
|
|
5
|
+
import { createBandScale, createLinearScale } from "./math";
|
|
6
|
+
import { Circle, Line, Rect } from "./svg";
|
|
7
|
+
import type { ChartSize } from "./types";
|
|
8
|
+
import { useChartTheme } from "./useChartTheme";
|
|
9
|
+
|
|
10
|
+
const bars = [
|
|
11
|
+
{ label: "Mon", value: 3 },
|
|
12
|
+
{ label: "Tue", value: 7 },
|
|
13
|
+
{ label: "Wed", value: 5 },
|
|
14
|
+
{ label: "Thu", value: 9 },
|
|
15
|
+
{ label: "Fri", value: 6 },
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The point of the surface is that children get PIXELS, not a 0-100 viewBox:
|
|
20
|
+
* scales resolve against the measured viewport, so strokes stay 1px and hit
|
|
21
|
+
* targets stay honest at any container width.
|
|
22
|
+
*/
|
|
23
|
+
function Marks({ size }: { size: ChartSize }) {
|
|
24
|
+
const { palette, gridColor } = useChartTheme();
|
|
25
|
+
const x = createBandScale({
|
|
26
|
+
domain: bars.map((bar) => bar.label),
|
|
27
|
+
range: [8, size.width - 8],
|
|
28
|
+
});
|
|
29
|
+
const y = createLinearScale({ domain: [0, 10], range: [size.height - 8, 8] });
|
|
30
|
+
return (
|
|
31
|
+
<>
|
|
32
|
+
<Line
|
|
33
|
+
x1={8}
|
|
34
|
+
y1={size.height - 8}
|
|
35
|
+
x2={size.width - 8}
|
|
36
|
+
y2={size.height - 8}
|
|
37
|
+
stroke={gridColor}
|
|
38
|
+
strokeWidth={1}
|
|
39
|
+
/>
|
|
40
|
+
{bars.map((bar) => (
|
|
41
|
+
<Rect
|
|
42
|
+
key={bar.label}
|
|
43
|
+
x={x(bar.label) ?? 0}
|
|
44
|
+
y={y(bar.value)}
|
|
45
|
+
width={x.bandwidth()}
|
|
46
|
+
height={size.height - 8 - y(bar.value)}
|
|
47
|
+
fill={palette.single}
|
|
48
|
+
/>
|
|
49
|
+
))}
|
|
50
|
+
</>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function Dots({ size }: { size: ChartSize }) {
|
|
55
|
+
const { palette } = useChartTheme();
|
|
56
|
+
return (
|
|
57
|
+
<>
|
|
58
|
+
{bars.map((bar, index) => (
|
|
59
|
+
<Circle
|
|
60
|
+
key={bar.label}
|
|
61
|
+
cx={((index + 1) / (bars.length + 1)) * size.width}
|
|
62
|
+
cy={size.height / 2}
|
|
63
|
+
r={6 + index * 2}
|
|
64
|
+
fill={palette.categorical[index % palette.categorical.length]}
|
|
65
|
+
/>
|
|
66
|
+
))}
|
|
67
|
+
</>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const meta: Meta<typeof ChartSurface> = {
|
|
72
|
+
title: "Components/ChartSurface",
|
|
73
|
+
component: ChartSurface,
|
|
74
|
+
parameters: {
|
|
75
|
+
status: { type: "beta" },
|
|
76
|
+
docs: {
|
|
77
|
+
description: {
|
|
78
|
+
component:
|
|
79
|
+
'The responsive SVG viewport every chart in this package draws into. It measures its own width through `onLayout` (ResizeObserver-backed on web) and hands children a pixel-space `{ width, height }`, so scales land on real device pixels: strokes stay crisp, nothing is stretched by `preserveAspectRatio`, and a 44px touch target really is 44px. `label` is the generated accessible summary and renders as `role="img"`, so the chart is one described image rather than a pile of unlabelled shapes. Pass an explicit `width` to bypass measurement for SSR, tests, and fixed layouts. The draw-in fade drops entirely at `animation="none"` or OS reduced motion.',
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
argTypes: {
|
|
84
|
+
label: { control: "text" },
|
|
85
|
+
height: { control: { type: "range", min: 80, max: 320, step: 10 } },
|
|
86
|
+
width: { control: "number" },
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
export default meta;
|
|
90
|
+
|
|
91
|
+
type Story = StoryObj<typeof ChartSurface>;
|
|
92
|
+
|
|
93
|
+
export const Default: Story = {
|
|
94
|
+
name: "Main",
|
|
95
|
+
args: { label: "Sessions per weekday, peaking Thursday at 9.", height: 200 },
|
|
96
|
+
render: (args) => (
|
|
97
|
+
<YStack maxWidth={560}>
|
|
98
|
+
<Card>
|
|
99
|
+
<ChartSurface {...args}>{(size) => <Marks size={size} />}</ChartSurface>
|
|
100
|
+
</Card>
|
|
101
|
+
</YStack>
|
|
102
|
+
),
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export const Responsive: Story = {
|
|
106
|
+
name: "Tracks the container",
|
|
107
|
+
parameters: {
|
|
108
|
+
docs: {
|
|
109
|
+
description: {
|
|
110
|
+
story:
|
|
111
|
+
"Same surface, three container widths. No `width` prop: each instance measures its own parent, so the band scale re-solves instead of scaling a fixed viewBox.",
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
render: () => (
|
|
116
|
+
<YStack gap="$4">
|
|
117
|
+
{[520, 320, 200].map((width) => (
|
|
118
|
+
<Card key={width} width={width}>
|
|
119
|
+
<YStack gap="$2">
|
|
120
|
+
<Paragraph size="$2">{`${width}px container`}</Paragraph>
|
|
121
|
+
<ChartSurface label={`Sessions per weekday at ${width}px`} height={140}>
|
|
122
|
+
{(size) => <Marks size={size} />}
|
|
123
|
+
</ChartSurface>
|
|
124
|
+
</YStack>
|
|
125
|
+
</Card>
|
|
126
|
+
))}
|
|
127
|
+
</YStack>
|
|
128
|
+
),
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export const FixedWidth: Story = {
|
|
132
|
+
name: "Explicit width",
|
|
133
|
+
parameters: {
|
|
134
|
+
docs: {
|
|
135
|
+
description: {
|
|
136
|
+
story:
|
|
137
|
+
"An explicit `width` bypasses measurement entirely — the path SSR and tests take, where no layout pass ever runs.",
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
render: () => (
|
|
142
|
+
<Card alignSelf="flex-start">
|
|
143
|
+
<ChartSurface label="Five categorical dots" width={360} height={120}>
|
|
144
|
+
{(size) => <Dots size={size} />}
|
|
145
|
+
</ChartSurface>
|
|
146
|
+
</Card>
|
|
147
|
+
),
|
|
148
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Alert/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAaxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAKxC,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAEnE,MAAM,WAAW,UAAW,SAAQ,IAAI,CAAC,QAAQ,CAAC,OAAO,UAAU,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IACxF,kFAAkF;IAClF,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,uBAAuB;IACvB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,sDAAsD;IACtD,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,2FAA2F;IAC3F,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,sFAAsF;IACtF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,0EAA0E;IAC1E,eAAe,CAAC,EAAE,SAAS,CAAC;IAC5B,0CAA0C;IAC1C,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,0DAA0D;IAC1D,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC/B,iCAAiC;IACjC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,6BAA6B;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,sDAAsD;IACtD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAsBD,QAAA,MAAM,UAAU;;;6CAQd,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Alert/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAaxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAKxC,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAEnE,MAAM,WAAW,UAAW,SAAQ,IAAI,CAAC,QAAQ,CAAC,OAAO,UAAU,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IACxF,kFAAkF;IAClF,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,uBAAuB;IACvB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,sDAAsD;IACtD,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,2FAA2F;IAC3F,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,sFAAsF;IACtF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,0EAA0E;IAC1E,eAAe,CAAC,EAAE,SAAS,CAAC;IAC5B,0CAA0C;IAC1C,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,0DAA0D;IAC1D,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC/B,iCAAiC;IACjC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,6BAA6B;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,sDAAsD;IACtD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAsBD,QAAA,MAAM,UAAU;;;6CAQd,CAAC;AA4YH;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,2CAOtC;AAED,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC,OAAO,UAAU,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionBar.d.ts","sourceRoot":"","sources":["../../src/actions/ActionBar.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"ActionBar.d.ts","sourceRoot":"","sources":["../../src/actions/ActionBar.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EASL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,MAAM,EAAE,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAC;AAKhD,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,KAAK,GAAG,SAAS,CAAC;AAEzD,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,MAAM,CAAC,EAAE,UAAU,CAAC,GAAG;IACvE,iDAAiD;IACjD,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,iDAAiD;IACjD,SAAS,CAAC,EAAE,SAAS,GAAG,SAAS,EAAE,CAAC;IACpC,kEAAkE;IAClE,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,yEAAyE;IACzE,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,qCAAqC;IACrC,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC;AA0CF,wBAAgB,SAAS,CAAC,EACxB,OAAO,EACP,SAAS,EACT,MAAM,EACN,QAAQ,EACR,KAAa,EACb,gBAAwB,EACxB,EAAE,EAAE,MAAM,EACV,GAAU,EACV,GAAG,UAAU,EACd,EAAE,cAAc,2CAkHhB"}
|