@altertable/data-app 0.67.0 → 0.68.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/chunks/{index-8qfxv0h5.js → index-gvers8jw.js} +173 -3
- package/dist/chunks/{index-8qfxv0h5.js.map → index-gvers8jw.js.map} +4 -3
- package/dist/react/index.js +24 -12
- package/dist/react/index.js.map +3 -4
- package/dist/react/ui/index.js +1105 -238
- package/dist/react/ui/index.js.map +15 -10
- package/dist/types/react/style-contract.d.ts +12 -0
- package/dist/types/react/ui/ChartLegend.d.ts +1 -1
- package/dist/types/react/ui/ComposedChart.d.ts +1 -1
- package/dist/types/react/ui/FunnelChart.d.ts +20 -0
- package/dist/types/react/ui/JourneyChart.d.ts +10 -0
- package/dist/types/react/ui/RetentionChart.d.ts +27 -0
- package/dist/types/react/ui/chart-data.d.ts +9 -0
- package/dist/types/react/ui/chart-primitives.d.ts +4 -2
- package/dist/types/react/ui/chartColor.d.ts +1 -0
- package/dist/types/react/ui/index.d.ts +7 -0
- package/dist/types/react/ui/journey-flow.d.ts +49 -0
- package/dist/types/react/ui/useSvgId.d.ts +2 -0
- package/dist/worker.js +1 -1
- package/docs/contract.md +2 -1
- package/docs/ui.md +20 -2
- package/docs/widgets.md +15 -12
- package/docs/worker.md +2 -1
- package/package.json +1 -1
|
@@ -59,6 +59,18 @@ export declare const dataAppStyleClasses: {
|
|
|
59
59
|
readonly component: 'ChartLegend.Label';
|
|
60
60
|
readonly kind: 'root';
|
|
61
61
|
};
|
|
62
|
+
readonly 'altertable-funnel-chart': {
|
|
63
|
+
readonly component: 'FunnelChart';
|
|
64
|
+
readonly kind: 'root';
|
|
65
|
+
};
|
|
66
|
+
readonly 'altertable-retention-chart': {
|
|
67
|
+
readonly component: 'RetentionChart';
|
|
68
|
+
readonly kind: 'root';
|
|
69
|
+
};
|
|
70
|
+
readonly 'altertable-journey-chart': {
|
|
71
|
+
readonly component: 'JourneyChart';
|
|
72
|
+
readonly kind: 'root';
|
|
73
|
+
};
|
|
62
74
|
readonly 'altertable-composed-chart': {
|
|
63
75
|
readonly component: 'ComposedChart';
|
|
64
76
|
readonly kind: 'root';
|
|
@@ -14,7 +14,7 @@ export type ChartLegendItemProps = ComponentPropsWithRef<'li'> & {
|
|
|
14
14
|
};
|
|
15
15
|
/** Descriptive by default; compose a button inside the item for an authored series toggle. */
|
|
16
16
|
declare function ChartLegendItem({ inactive, className, ...props }: ChartLegendItemProps): import("react").JSX.Element;
|
|
17
|
-
export type ChartLegendMarkerKind = 'bar' | 'line' | 'area' | 'point' | 'slice';
|
|
17
|
+
export type ChartLegendMarkerKind = 'square' | 'bar' | 'line' | 'area' | 'point' | 'slice';
|
|
18
18
|
export type ChartLegendMarkerProps = Omit<ComponentPropsWithRef<'svg'>, 'children'> & {
|
|
19
19
|
kind: ChartLegendMarkerKind;
|
|
20
20
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ComponentProps } from 'react';
|
|
2
2
|
import { ComposedChartLegend as Legend } from './ComposedChartLegend.js';
|
|
3
3
|
import { ComposedChart as RechartsComposedChart, ZAxis, ReferenceLine, ReferenceArea, ReferenceDot, Brush, Label, LabelList, ErrorBar } from 'recharts';
|
|
4
4
|
import { ChartBar as Bar, ChartDot as Dot, ChartLine as Line, ChartArea as Area, ChartScatter as Scatter, ChartXAxis as XAxis, ChartYAxis as YAxis, ChartGrid as CartesianGrid, ChartTooltip as Tooltip } from './chart-primitives.js';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { CountChartProps } from './chart-data.js';
|
|
2
|
+
/** Ordered step with a unique, nonblank ID. */
|
|
3
|
+
export type FunnelChartStep = {
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
};
|
|
7
|
+
export type FunnelChartSeries = {
|
|
8
|
+
/** Unique, nonblank population ID. */
|
|
9
|
+
id: string;
|
|
10
|
+
label: string;
|
|
11
|
+
/** Finite, nonnegative counts aligned with steps and nonincreasing. */
|
|
12
|
+
values: readonly number[];
|
|
13
|
+
};
|
|
14
|
+
export type FunnelChartProps = CountChartProps & {
|
|
15
|
+
steps: readonly FunnelChartStep[];
|
|
16
|
+
series: readonly FunnelChartSeries[];
|
|
17
|
+
};
|
|
18
|
+
/** Conversion columns with previous-step drop-off, normalized to each series' first step.
|
|
19
|
+
* Owns series highlighting and portion-specific inspection; compose inside VisualizationWidget. */
|
|
20
|
+
export declare function FunnelChart({ steps, series, unit, ariaLabel, className, formatValue, }: FunnelChartProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CountChartProps } from './chart-data.js';
|
|
2
|
+
import { type JourneyChartPath } from './journey-flow.js';
|
|
3
|
+
export type { JourneyChartPath } from './journey-flow.js';
|
|
4
|
+
export type JourneyChartProps = CountChartProps & {
|
|
5
|
+
/** Full paths and their population counts. Branches and outcomes are derived internally. */
|
|
6
|
+
paths: readonly JourneyChartPath[];
|
|
7
|
+
};
|
|
8
|
+
/** Path exploration with two initial steps, expandable prefixes, and three events per depth.
|
|
9
|
+
* Counts and flows use the Step 1 population. Compose inside VisualizationWidget. */
|
|
10
|
+
export declare function JourneyChart({ paths, unit, ariaLabel, className, formatValue, }: JourneyChartProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { CountChartProps } from './chart-data.js';
|
|
2
|
+
export type RetentionChartPoint = {
|
|
3
|
+
/** Nonnegative integer, unique per series; uneven offsets retain their distance. */
|
|
4
|
+
offset: number;
|
|
5
|
+
/** Must agree across series for the same offset. */
|
|
6
|
+
label: string;
|
|
7
|
+
/** Observed retention fraction in [0, 1], or null for an unobserved period. */
|
|
8
|
+
rate: number | null;
|
|
9
|
+
/** Finite count in [0, cohortSize]; null exactly when rate is null. */
|
|
10
|
+
retainedCount: number | null;
|
|
11
|
+
/** Observed but still accumulating; drawn as a dotted tail. */
|
|
12
|
+
incomplete?: boolean;
|
|
13
|
+
};
|
|
14
|
+
export type RetentionChartSeries = {
|
|
15
|
+
/** Unique, nonblank cohort or segment ID. */
|
|
16
|
+
id: string;
|
|
17
|
+
label: string;
|
|
18
|
+
/** Finite, nonnegative starting population. */
|
|
19
|
+
cohortSize: number;
|
|
20
|
+
points: readonly RetentionChartPoint[];
|
|
21
|
+
};
|
|
22
|
+
export type RetentionChartProps = CountChartProps & {
|
|
23
|
+
series: readonly RetentionChartSeries[];
|
|
24
|
+
};
|
|
25
|
+
/** Query-defined retention curves with count inspection and dotted incomplete periods.
|
|
26
|
+
* Rates are not recomputed from counts. Compose inside VisualizationWidget. */
|
|
27
|
+
export declare function RetentionChart({ series, unit, ariaLabel, className, formatValue, }: RetentionChartProps): import("react").JSX.Element;
|
|
@@ -11,6 +11,15 @@ export type ValueChartProps = {
|
|
|
11
11
|
ariaLabel: string;
|
|
12
12
|
formatValue?: (value: number) => string;
|
|
13
13
|
};
|
|
14
|
+
export type CountChartProps = {
|
|
15
|
+
/** Accessible measure and scope description. */
|
|
16
|
+
ariaLabel: string;
|
|
17
|
+
/** Population unit, such as users or sessions. */
|
|
18
|
+
unit: string;
|
|
19
|
+
/** Formats counts; rates use percentage formatting. */
|
|
20
|
+
formatValue?: (value: number) => string;
|
|
21
|
+
className?: string;
|
|
22
|
+
};
|
|
14
23
|
/** Independent observation on two finite numeric axes. */
|
|
15
24
|
export type ScatterChartItem = {
|
|
16
25
|
id: string;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { ComponentProps } from 'react';
|
|
2
|
-
import { type DotProps, Scatter, XAxis, YAxis, CartesianGrid, Tooltip, type BarProps, type LineProps, type AreaProps } from 'recharts';
|
|
3
|
-
export declare const chartBarFill = "var(--atbl-chart-fill, color-mix(in srgb, var(--atbl-accent) 75%, var(--atbl-surface)))";
|
|
2
|
+
import { type DotProps, Scatter, XAxis, YAxis, CartesianGrid, Tooltip, DefaultTooltipContent, type BarProps, type LineProps, type AreaProps } from 'recharts';
|
|
4
3
|
/** Hollow sample marker shared by standalone and composed series. */
|
|
5
4
|
export declare function ChartDot({ active, stroke, fill, r, ...props }: DotProps & {
|
|
6
5
|
active?: boolean;
|
|
@@ -16,5 +15,8 @@ export declare function ChartScatter<Row = unknown, Value = number>(props: Compo
|
|
|
16
15
|
export declare function ChartXAxis<Row = unknown, Value = string | number>(props: ComponentProps<typeof XAxis<Row, Value>>): import("react").JSX.Element;
|
|
17
16
|
export declare function ChartYAxis<Row = unknown, Value = number>(props: ComponentProps<typeof YAxis<Row, Value>>): import("react").JSX.Element;
|
|
18
17
|
export declare function ChartGrid(props: ComponentProps<typeof CartesianGrid>): import("react").JSX.Element;
|
|
18
|
+
export declare function ChartTooltipContent(props: ComponentProps<typeof DefaultTooltipContent> & {
|
|
19
|
+
active?: boolean;
|
|
20
|
+
}): import("react").JSX.Element | null;
|
|
19
21
|
/** Uses the same surface as single-series inspection; Recharts owns interaction. */
|
|
20
22
|
export declare function ChartTooltip(props: ComponentProps<typeof Tooltip>): import("react").JSX.Element;
|
|
@@ -96,3 +96,10 @@ export type { ComposedChartProps } from './ComposedChart.js';
|
|
|
96
96
|
export { ChartLegend } from './ChartLegend.js';
|
|
97
97
|
export type { ChartLegendProps, ChartLegendItemProps, ChartLegendMarkerProps, ChartLegendLabelProps, ChartLegendMarkerKind, } from './ChartLegend.js';
|
|
98
98
|
export type { ComposedChartLegendProps } from './ComposedChartLegend.js';
|
|
99
|
+
export { FunnelChart } from './FunnelChart.js';
|
|
100
|
+
export type { FunnelChartProps, FunnelChartStep, FunnelChartSeries, } from './FunnelChart.js';
|
|
101
|
+
export { RetentionChart } from './RetentionChart.js';
|
|
102
|
+
export type { RetentionChartProps, RetentionChartPoint, RetentionChartSeries, } from './RetentionChart.js';
|
|
103
|
+
export { JourneyChart } from './JourneyChart.js';
|
|
104
|
+
export type { JourneyChartProps, JourneyChartPath, } from './JourneyChart.js';
|
|
105
|
+
export { useSvgId } from './useSvgId.js';
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** Aggregated route; repeated events remain distinct by depth and prefix. */
|
|
2
|
+
export type JourneyChartPath = {
|
|
3
|
+
/** Unique, nonblank path ID. */
|
|
4
|
+
id: string;
|
|
5
|
+
/** At least one nonblank event; null property means no property grouping. */
|
|
6
|
+
steps: readonly {
|
|
7
|
+
event: string;
|
|
8
|
+
property: string | null;
|
|
9
|
+
}[];
|
|
10
|
+
/** Finite, nonnegative population following this route. */
|
|
11
|
+
count: number;
|
|
12
|
+
/** True: converted; false: dropped off; null: no conversion classification. */
|
|
13
|
+
converted: boolean | null;
|
|
14
|
+
/** Stops at the last loaded event, without adding an outcome or expand control. */
|
|
15
|
+
truncated: boolean;
|
|
16
|
+
};
|
|
17
|
+
export type JourneyNode = {
|
|
18
|
+
key: string;
|
|
19
|
+
label: string;
|
|
20
|
+
depth: number;
|
|
21
|
+
outcome: 'event' | 'converted' | 'drop-off' | 'truncated' | 'end' | 'other';
|
|
22
|
+
count: number;
|
|
23
|
+
pathKeys: string[];
|
|
24
|
+
branchKeys?: string[];
|
|
25
|
+
expandable?: boolean;
|
|
26
|
+
expanded?: boolean;
|
|
27
|
+
hiddenBranchCount?: number;
|
|
28
|
+
};
|
|
29
|
+
export declare function journeyNodes(path: JourneyChartPath): Omit<JourneyNode, 'count' | 'pathKeys'>[];
|
|
30
|
+
export declare function buildJourneyFlow(paths: readonly JourneyChartPath[], expandedBranch?: string[]): {
|
|
31
|
+
nodes: JourneyNode[];
|
|
32
|
+
links: {
|
|
33
|
+
key: string;
|
|
34
|
+
source: string;
|
|
35
|
+
target: string;
|
|
36
|
+
count: number;
|
|
37
|
+
pathKeys: string[];
|
|
38
|
+
}[];
|
|
39
|
+
};
|
|
40
|
+
export declare function limitJourneyFlow(graph: ReturnType<typeof buildJourneyFlow>, visibleEventsByDepth?: Record<number, number>): {
|
|
41
|
+
nodes: JourneyNode[];
|
|
42
|
+
links: {
|
|
43
|
+
key: string;
|
|
44
|
+
source: string;
|
|
45
|
+
target: string;
|
|
46
|
+
count: number;
|
|
47
|
+
pathKeys: string[];
|
|
48
|
+
}[];
|
|
49
|
+
};
|
package/dist/worker.js
CHANGED
|
@@ -65,7 +65,7 @@ function trustedParent(config, searchParams) {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
// src/worker/index.ts
|
|
68
|
-
var TOKEN_RE = /^(?=.{1,63}$)[a-z0-9]+(
|
|
68
|
+
var TOKEN_RE = /^(?=.{1,63}$)[a-z0-9]+(?:-+[a-z0-9]+)+$/;
|
|
69
69
|
function isPreviewHost(hostname, domainName) {
|
|
70
70
|
const suffix = `.${domainName}`;
|
|
71
71
|
return hostname.endsWith(suffix) && TOKEN_RE.test(hostname.slice(0, -suffix.length));
|
package/docs/contract.md
CHANGED
|
@@ -11,7 +11,8 @@ import operation types using `import type`.
|
|
|
11
11
|
Declare SQL once with `defineDataApp()` to preserve exact query and parameter
|
|
12
12
|
names. Use stable `lowerCamelCase` IDs describing the result, such as `products`,
|
|
13
13
|
`productsByCategory`, or `dailyRevenue`. Use plural names for row lists; keep parameter
|
|
14
|
-
values in `params`.
|
|
14
|
+
values in `params`. Every query must include `params`; use `{}` when it declares no
|
|
15
|
+
parameters.
|
|
15
16
|
The app owns an immutable registry snapshot. Define operations with
|
|
16
17
|
`dataApp.defineOperation()`.
|
|
17
18
|
|
package/docs/ui.md
CHANGED
|
@@ -100,6 +100,22 @@ the samples. Pie slices represent mutually exclusive parts of one total; shares
|
|
|
100
100
|
use the sum of supplied items, so include Other when showing a subset of the
|
|
101
101
|
whole. Scatter points represent independent X/Y observations.
|
|
102
102
|
|
|
103
|
+
Use `useSvgId()` for stable IDs when composing custom SVG definitions.
|
|
104
|
+
|
|
105
|
+
### Product analytics charts
|
|
106
|
+
|
|
107
|
+
Use `<FunnelChart>`, `<RetentionChart>`, and `<JourneyChart>` from `/react/ui`
|
|
108
|
+
inside `<VisualizationWidget>`. Derive inputs from the displayed rows; the
|
|
109
|
+
binding owns loading, evidence, CSV, and story content. Types and JSDoc describe
|
|
110
|
+
input constraints; the gallery includes complete examples.
|
|
111
|
+
|
|
112
|
+
- `<FunnelChart>` compares ordered step counts across populations. Each series
|
|
113
|
+
uses its first step as the baseline; hatching shows previous-step drop-off.
|
|
114
|
+
- `<RetentionChart>` plots query-defined rates and retained counts by interval
|
|
115
|
+
offset. Use `null` for unobserved periods; `incomplete` produces a dotted tail.
|
|
116
|
+
- `<JourneyChart>` derives expandable branches and outcomes from full paths.
|
|
117
|
+
Truncated paths stop at the last loaded event.
|
|
118
|
+
|
|
103
119
|
### Composed charts
|
|
104
120
|
|
|
105
121
|
Use `<ComposedChart>` from `/react/ui` for multiple series or mixed marks inside
|
|
@@ -134,10 +150,12 @@ its columns aligned with the displayed measures.
|
|
|
134
150
|
|
|
135
151
|
### Legends
|
|
136
152
|
|
|
137
|
-
Include `<ComposedChart.Legend />` to derive labels and markers from the series;
|
|
153
|
+
Include `<ComposedChart.Legend />` to derive labels and colored square markers from the series;
|
|
138
154
|
omit it when no legend is needed. For any chart, compose `<ChartLegend>` with
|
|
139
155
|
`<ChartLegend.Item>`, `<ChartLegend.Marker>`, and `<ChartLegend.Label>` using the
|
|
140
|
-
same names and colors as the plot.
|
|
156
|
+
same names and colors as the plot. Square markers are
|
|
157
|
+
shared with chart tooltips and funnel summaries. Pass `kind="square"` explicitly
|
|
158
|
+
when composing a marker.
|
|
141
159
|
`<PieChart>` includes a legend by default; `showLegend={false}` omits it.
|
|
142
160
|
|
|
143
161
|
Legends align cells in a container-responsive grid, truncate labels, and reserve
|
package/docs/widgets.md
CHANGED
|
@@ -28,18 +28,21 @@ Choose the component by the reader's question. Compose dataset visuals inside
|
|
|
28
28
|
charts come from `/react/ui`; `<Ranking>`, `<Breakdown>`, and `<Comparison>`
|
|
29
29
|
are also available from `/react`.
|
|
30
30
|
|
|
31
|
-
| Question or need | Component
|
|
32
|
-
| --------------------------------------------------------- |
|
|
33
|
-
| How do categories compare? | `<BarChart>`
|
|
34
|
-
| Which items lead? | `<Ranking>`
|
|
35
|
-
| How does a measure change over time? | `<LineChart>`
|
|
36
|
-
| How large is the measure over time? | `<AreaChart>`
|
|
37
|
-
| What makes up the whole? | `<PieChart>`
|
|
38
|
-
| What share of an observed total does each part represent? | `<Breakdown>`
|
|
39
|
-
| How do several measures relate on one plot? | `<ComposedChart>`
|
|
40
|
-
| How are two numeric measures related? | `<ScatterChart>`
|
|
41
|
-
|
|
|
42
|
-
|
|
|
31
|
+
| Question or need | Component | Guidance |
|
|
32
|
+
| --------------------------------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------ |
|
|
33
|
+
| How do categories compare? | `<BarChart>` | Compare nonnegative category values; order by value for rank or by a meaningful category order. |
|
|
34
|
+
| Which items lead? | `<Ranking>` | Use a compact ordered list with values and optional detail. Tracks scale to the largest visible item, not a total. |
|
|
35
|
+
| How does a measure change over time? | `<LineChart>` | Use ordered, equally spaced samples to emphasize the trend. |
|
|
36
|
+
| How large is the measure over time? | `<AreaChart>` | Use the same samples as a line chart when filled magnitude relative to zero helps answer the question. |
|
|
37
|
+
| What makes up the whole? | `<PieChart>` | Use a few mutually exclusive parts of one total; include the remainder as Other. |
|
|
38
|
+
| What share of an observed total does each part represent? | `<Breakdown>` | Use a compact display of values and shares with an explicit total, including when only some parts are shown. |
|
|
39
|
+
| How do several measures relate on one plot? | `<ComposedChart>` | Compose bars, lines, areas, or scatter series; label units clearly and use separate axes for different units. |
|
|
40
|
+
| How are two numeric measures related? | `<ScatterChart>` | Use independent X/Y observations to explore relationships, clusters, and outliers. |
|
|
41
|
+
| Where do users drop out of a sequence? | `<FunnelChart>` | Use ordered counts from the same population reaching each successive step. |
|
|
42
|
+
| Do cohorts return over time? | `<RetentionChart>` | Use query-defined rates and retained counts by numeric offset; mark incomplete periods. |
|
|
43
|
+
| Which paths do users take? | `<JourneyChart>` | Use full paths with population counts and outcomes; explore branches step by step. |
|
|
44
|
+
| How did one metric change between periods? | `<Comparison>` | Use the metric reading and its displayed comparison period. |
|
|
45
|
+
| What are the exact values or row details? | `<TableWidget>` | Use a bound table for lookup, search, and precise comparisons. |
|
|
43
46
|
|
|
44
47
|
Prefer bars or a ranking when readers need to compare similarly sized categories;
|
|
45
48
|
use a pie for a simple composition question. Prefer a line when the trend is
|
package/docs/worker.md
CHANGED
|
@@ -28,7 +28,8 @@ and these string bindings:
|
|
|
28
28
|
| `PARENT_ORIGINS` | Space-separated trusted HTTP(S) origins; first exact origin is the default | `https://app.example.com https://*.preview.example.com` |
|
|
29
29
|
|
|
30
30
|
The Worker serves only `/` on a single preview label under `DOMAIN_NAME` matching
|
|
31
|
-
`/^(?=.{1,63}$)[a-z0-9]+(
|
|
31
|
+
`/^(?=.{1,63}$)[a-z0-9]+(?:-+[a-z0-9]+)+$/`
|
|
32
|
+
(any hyphenated lowercase DNS label; the host keeps each app's label unique). Other hosts and paths
|
|
32
33
|
return 404. GET returns HTML; HEAD returns the same headers with no body. Other
|
|
33
34
|
methods return 405 with `Allow: GET, HEAD`.
|
|
34
35
|
|