hazo_dataviz 0.6.2 → 0.7.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/CHANGE_LOG.md +12 -0
- package/dist/charts/chart_controls.d.ts.map +1 -1
- package/dist/charts/chart_controls.js +8 -7
- package/dist/charts/line_chart.d.ts.map +1 -1
- package/dist/charts/line_chart.js +2 -1
- package/dist/charts/multi_line_chart.d.ts.map +1 -1
- package/dist/charts/multi_line_chart.js +2 -1
- package/dist/charts/time_series_chart.d.ts +6 -0
- package/dist/charts/time_series_chart.d.ts.map +1 -1
- package/dist/charts/time_series_chart.js +11 -8
- package/dist/index.client.d.ts +1 -0
- package/dist/index.client.d.ts.map +1 -1
- package/dist/index.client.js +1 -0
- package/dist/lib/format.js +1 -1
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +18 -0
- package/dist/locales/en.json +22 -0
- package/dist/visualizers/area.d.ts.map +1 -1
- package/dist/visualizers/area.js +2 -1
- package/dist/visualizers/bar.d.ts.map +1 -1
- package/dist/visualizers/bar.js +2 -1
- package/dist/visualizers/chart_frame.d.ts.map +1 -1
- package/dist/visualizers/chart_frame.js +2 -1
- package/dist/visualizers/line.d.ts.map +1 -1
- package/dist/visualizers/line.js +2 -1
- package/dist/visualizers/single_stat.d.ts.map +1 -1
- package/dist/visualizers/single_stat.js +2 -1
- package/dist/visualizers/stacked_bar.d.ts.map +1 -1
- package/dist/visualizers/stacked_bar.js +2 -1
- package/dist/visualizers/table.d.ts.map +1 -1
- package/dist/visualizers/table.js +3 -2
- package/package.json +9 -5
package/CHANGE_LOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# hazo_dataviz — Change Log
|
|
2
2
|
|
|
3
|
+
## 0.7.0 — 2026-09-21
|
|
4
|
+
|
|
5
|
+
i18n adoption — closes the workspace-wide `audit:i18n` gap for this package (it was missing from the original migration list; every other `hazo_*` package now has this bridge).
|
|
6
|
+
|
|
7
|
+
- **New `src/locales/en.json`** — a flat, literal-dotted-key catalog with 20 strings extracted from chart/visualizer components: empty states (`chart_frame.no_data`, `table.no_data`, `line_chart.no_data`, `multi_line_chart.no_data`, `time_series_chart.no_data`), the `TimeSeriesChart` multi-series fallback label (`time_series_chart.series_label`, `{{n}}` interpolated) and its "today" reference-line marker (`time_series_chart.reference_today`), `ChartControls`' grain/chart-type segmented-control labels (Daily/Weekly/Monthly/Quarterly/Yearly, Line/Bar), and every builtin visualizer's display `label` (Table, Single Stat, Area/Bar/Line/Stacked Bar Chart).
|
|
8
|
+
- **New `t` export** from `src/lib/index.ts` (re-exported from `./client` and the default server entry), wired via `createPackageT('hazo_dataviz', en)` from `hazo_core/i18n`. Uses a plain `import en from '../locales/en.json'` (not `createRequire`) — this catalog module is bundled into client/browser code via `index.client.ts`, and `createRequire` is Node-only; a plain JSON import works under this package's `"module": "Node16"` tsconfig with `resolveJsonModule: true` and is browser-safe. `tsc` copies `src/locales/en.json` into `dist/locales/en.json` automatically, no manual build-step copy needed.
|
|
9
|
+
- **Call sites updated**: `chart_frame.tsx` (`EmptyState`), `table.tsx`, `line_chart.tsx`, `multi_line_chart.tsx`, `time_series_chart.tsx`, `chart_controls.tsx`, and the `label` field of every builtin visualizer (`line.tsx`, `bar.tsx`, `stacked_bar.tsx`, `area.tsx`, `table.tsx`, `single_stat.tsx`) now call `t()` instead of embedding English literals. Several of these files already used a local variable named `t` for the resolved `ChartTheme` — the i18n import is aliased to `translate` in `chart_controls.tsx`, `line_chart.tsx`, and `time_series_chart.tsx` to avoid the collision.
|
|
10
|
+
- **`hazo_i18n` added as an optional peer** (`^0.5.0`, `peerDependenciesMeta.optional: true`) — mirrors the guarded, fire-and-forget registration `hazo_core/i18n` already performs; this package never imports `hazo_i18n` directly. `hazo_core` peer floor raised `^2.3.0` → `^2.4.0` (the version that ships `hazo_core/i18n`).
|
|
11
|
+
- **New `/autotest` scenario group** (`hazo_dataviz_i18n` in `test-app/app/autotest/hazo_dataviz_scenarios.ts`): catalog loads, all 20 known keys resolve via `t.has()`/`t.raw()`, `{{n}}` interpolation on the series-label fallback, missing-key bare-key fallback, and a check that every builtin visualizer's `.label` matches `t()`'s rendering of its own key (i.e. actually wired, not still hardcoded).
|
|
12
|
+
- **Fix (unrelated, pre-existing build break)**: `lib/format.ts`'s `currency` case called `formatCurrency(Number(value), format.ccy)` — a string second argument — which no longer type-checks against `hazo_core`'s `formatCurrency(amount, options: FormatCurrencyOptions)` signature (a breaking change landed in `hazo_core` outside this package). Fixed to `formatCurrency(Number(value), { currency: format.ccy })` so `npm run build` passes again; unrelated to the i18n work but was blocking verification.
|
|
13
|
+
- Bumped `test-app`'s `hazo_dataviz` dep range `^0.6.0` → `^0.7.0`.
|
|
14
|
+
|
|
3
15
|
## 0.6.2 — 2026-09-07
|
|
4
16
|
|
|
5
17
|
- **Fix (`TimeSeriesChart` Y-axis label clipping)**: `CHART_MARGIN.left` was `-4` and the Y axis was hardcoded to `width={40}`, both tuned for short labels — a 3-digit price label like `"360$"` overflowed 40px and got clipped on the left edge. `CHART_MARGIN.left` is now `4`, and the axis width defaults to `50` via a new `yAxisWidth?: number` prop (`TimeSeriesChartProps`), so consumers with longer tick labels (bigger numbers, longer units) can widen it further without patching the chart.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart_controls.d.ts","sourceRoot":"","sources":["../../src/charts/chart_controls.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"chart_controls.d.ts","sourceRoot":"","sources":["../../src/charts/chart_controls.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAIzD,YAAY,EAAE,SAAS,EAAE,CAAC;AAI1B,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,KAAK,CAAC;AAEvC,MAAM,WAAW,UAAU;IACzB,yCAAyC;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,uBAAuB;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,gCAAgC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,SAAS,CAAC;IACjB,SAAS,EAAE,SAAS,CAAC;IACrB,aAAa,EAAE,CAAC,CAAC,EAAE,SAAS,KAAK,IAAI,CAAC;IACtC,iBAAiB,EAAE,CAAC,CAAC,EAAE,SAAS,KAAK,IAAI,CAAC;IAC1C,sEAAsE;IACtE,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;IACrB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB,mEAAmE;IACnE,KAAK,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA+ID,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,SAAS,EACT,aAAa,EACb,iBAAiB,EACjB,MAAuB,EACvB,UAAgC,EAChC,KAAK,EACL,SAAS,GACV,EAAE,kBAAkB,GAAG,KAAK,CAAC,YAAY,CA+BzC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { t as translate } from '../lib/index.js';
|
|
3
4
|
// ── Constants ─────────────────────────────────────────────────────────────────
|
|
4
5
|
const DEFAULT_THEME = {
|
|
5
6
|
ink: '#2f2a25',
|
|
@@ -11,15 +12,15 @@ const DEFAULT_THEME = {
|
|
|
11
12
|
const DEFAULT_GRAINS = ['day', 'week', 'month', 'year'];
|
|
12
13
|
const DEFAULT_CHART_TYPES = ['line', 'bar'];
|
|
13
14
|
const GRAIN_LABELS = {
|
|
14
|
-
day: '
|
|
15
|
-
week: '
|
|
16
|
-
month: '
|
|
17
|
-
quarter: '
|
|
18
|
-
year: '
|
|
15
|
+
day: translate('chart_controls.grain_day'),
|
|
16
|
+
week: translate('chart_controls.grain_week'),
|
|
17
|
+
month: translate('chart_controls.grain_month'),
|
|
18
|
+
quarter: translate('chart_controls.grain_quarter'),
|
|
19
|
+
year: translate('chart_controls.grain_year'),
|
|
19
20
|
};
|
|
20
21
|
const CHART_TYPE_LABELS = {
|
|
21
|
-
line: '
|
|
22
|
-
bar: '
|
|
22
|
+
line: translate('chart_controls.type_line'),
|
|
23
|
+
bar: translate('chart_controls.type_bar'),
|
|
23
24
|
};
|
|
24
25
|
// ── Tiny SVG icons (optional visual hint beside each label) ───────────────────
|
|
25
26
|
function LineIcon() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"line_chart.d.ts","sourceRoot":"","sources":["../../src/charts/line_chart.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAU/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAOtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"line_chart.d.ts","sourceRoot":"","sources":["../../src/charts/line_chart.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAU/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAOtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGzD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,eAAe,CAAC;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAKD,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,KAAK,EACL,KAAK,EACL,KAAK,EACL,MAAM,EACN,IAAS,EACT,WAAkB,EAClB,KAAK,EACL,UAAU,EACV,KAAK,EACL,SAAS,GACV,EAAE,cAAc,GAAG,KAAK,CAAC,YAAY,CA6GrC"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { LineChart as RechartsLineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, } from 'recharts';
|
|
4
4
|
import { ChartLegend, ChartTooltip, resolveChartTheme, } from './chart_common.js';
|
|
5
|
+
import { t as translate } from '../lib/index.js';
|
|
5
6
|
/** See `TimeSeriesChart`'s copy — same reasoning, same numbers. */
|
|
6
7
|
const CHART_MARGIN = { top: 8, right: 8, bottom: 0, left: -4 };
|
|
7
8
|
export function LineChart({ data, dates, color, width, height, unit = '', showTooltip = true, label, showLegend, theme, className, }) {
|
|
@@ -16,7 +17,7 @@ export function LineChart({ data, dates, color, width, height, unit = '', showTo
|
|
|
16
17
|
height: chartHeight,
|
|
17
18
|
color: t.muted,
|
|
18
19
|
fontSize: 14,
|
|
19
|
-
}, children:
|
|
20
|
+
}, children: translate('line_chart.no_data') }));
|
|
20
21
|
}
|
|
21
22
|
const chartData = dates.map((d, i) => ({ x: d, value: data[i] ?? null }));
|
|
22
23
|
const legendVisible = showLegend ?? label != null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multi_line_chart.d.ts","sourceRoot":"","sources":["../../src/charts/multi_line_chart.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAW/B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"multi_line_chart.d.ts","sourceRoot":"","sources":["../../src/charts/multi_line_chart.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAW/B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,KAAK,EACL,KAAK,EACL,MAAM,EACN,WAAkB,EAClB,UAAiB,EACjB,SAAS,GACV,EAAE,mBAAmB,GAAG,KAAK,CAAC,YAAY,CAuE1C"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { LineChart as RechartsLineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, } from 'recharts';
|
|
4
|
+
import { t } from '../lib/index.js';
|
|
4
5
|
export function MultiLineChart({ series, dates, width, height, showTooltip = true, showLegend = true, className, }) {
|
|
5
6
|
const chartHeight = height ?? 130;
|
|
6
7
|
// Empty series or all-empty guard — render a placeholder, never throw
|
|
@@ -14,7 +15,7 @@ export function MultiLineChart({ series, dates, width, height, showTooltip = tru
|
|
|
14
15
|
height: chartHeight,
|
|
15
16
|
color: '#9ca3af',
|
|
16
17
|
fontSize: 14,
|
|
17
|
-
}, children:
|
|
18
|
+
}, children: t('multi_line_chart.no_data') }));
|
|
18
19
|
}
|
|
19
20
|
// Build wide rows: { x: date, [seriesLabel]: value | null, ... }
|
|
20
21
|
const chartData = dates.map((d, i) => {
|
|
@@ -42,6 +42,12 @@ export interface TimeSeriesChartProps {
|
|
|
42
42
|
* into the `height` you asked for.
|
|
43
43
|
*/
|
|
44
44
|
showLegend?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Width (px) reserved for the Y axis tick labels. Default 50 — enough for
|
|
47
|
+
* a 3-digit price plus a currency symbol (e.g. "360$") without clipping.
|
|
48
|
+
* Widen it further for longer labels (large numbers, longer units).
|
|
49
|
+
*/
|
|
50
|
+
yAxisWidth?: number;
|
|
45
51
|
className?: string;
|
|
46
52
|
}
|
|
47
53
|
export declare function TimeSeriesChart(props: TimeSeriesChartProps): React.ReactElement;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time_series_chart.d.ts","sourceRoot":"","sources":["../../src/charts/time_series_chart.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAQ/B,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAQjE,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"time_series_chart.d.ts","sourceRoot":"","sources":["../../src/charts/time_series_chart.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAQ/B,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAQjE,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAKzD,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,eAAe,CAAC;IACtB,kEAAkE;IAClE,GAAG,CAAC,EAAE,GAAG,CAAC;CACX;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,wBAAwB;IACxB,MAAM,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC5B,qEAAqE;IACrE,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5B,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,SAAS,KAAK,IAAI,CAAC;IACvC,iBAAiB,CAAC,EAAE,CAAC,CAAC,EAAE,SAAS,KAAK,IAAI,CAAC;IAC3C,uGAAuG;IACvG,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,mFAAmF;IACnF,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;IACrB;;;;;;;;;OASG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAeD,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,KAAK,CAAC,YAAY,CAkQ/E"}
|
|
@@ -5,16 +5,19 @@ import { LineChart as RLineChart, Line, BarChart as RBarChart, Bar, XAxis, YAxis
|
|
|
5
5
|
import { aggregateSeries } from '../lib/time_bucket.js';
|
|
6
6
|
import { ChartControls } from './chart_controls.js';
|
|
7
7
|
import { ChartLegend, ChartTooltip, resolveChartTheme, } from './chart_common.js';
|
|
8
|
+
import { t as translate } from '../lib/index.js';
|
|
8
9
|
// ── TimeSeriesChart ────────────────────────────────────────────────────────────
|
|
10
|
+
/** Default width (px) reserved for the Y axis; see `yAxisWidth` prop. */
|
|
11
|
+
const DEFAULT_Y_AXIS_WIDTH = 50;
|
|
9
12
|
/**
|
|
10
13
|
* Breathing room round the plot. `top: 8` stops a peak's stroke being clipped
|
|
11
14
|
* by the container edge; `right: 8` does the same for the last point's active
|
|
12
|
-
* dot; `left:
|
|
13
|
-
*
|
|
15
|
+
* dot; `left: 4` gives the Y axis tick labels room so they aren't clipped by
|
|
16
|
+
* the container edge.
|
|
14
17
|
*/
|
|
15
|
-
const CHART_MARGIN = { top: 8, right: 8, bottom: 0, left:
|
|
18
|
+
const CHART_MARGIN = { top: 8, right: 8, bottom: 0, left: 4 };
|
|
16
19
|
export function TimeSeriesChart(props) {
|
|
17
|
-
const { dates, series, data, color, label, agg, height = 220, unit, theme, referenceDate, grain: grainProp, chartType: chartTypeProp, onGrainChange, onChartTypeChange, grains, showLegend, className, } = props;
|
|
20
|
+
const { dates, series, data, color, label, agg, height = 220, unit, theme, referenceDate, grain: grainProp, chartType: chartTypeProp, onGrainChange, onChartTypeChange, grains, showLegend, yAxisWidth, className, } = props;
|
|
18
21
|
// ── Controlled vs uncontrolled ────────────────────────────────────────────
|
|
19
22
|
const isControlled = grainProp !== undefined && chartTypeProp !== undefined;
|
|
20
23
|
const [grainState, setGrainState] = React.useState(grainProp ?? 'day');
|
|
@@ -57,7 +60,7 @@ export function TimeSeriesChart(props) {
|
|
|
57
60
|
height,
|
|
58
61
|
color: t.muted,
|
|
59
62
|
fontSize: 14,
|
|
60
|
-
}, children:
|
|
63
|
+
}, children: translate('time_series_chart.no_data') }));
|
|
61
64
|
}
|
|
62
65
|
// ── Roll-up ───────────────────────────────────────────────────────────────
|
|
63
66
|
const rolled = resolvedSeries.map((s) => aggregateSeries(dates, s.data, activeGrain, s.agg ?? 'sum'));
|
|
@@ -66,7 +69,7 @@ export function TimeSeriesChart(props) {
|
|
|
66
69
|
const seriesMeta = resolvedSeries.map((s, i) => ({
|
|
67
70
|
key: `s${i}`,
|
|
68
71
|
color: s.color,
|
|
69
|
-
label: s.label ?? (resolvedSeries.length > 1 ?
|
|
72
|
+
label: s.label ?? (resolvedSeries.length > 1 ? translate('time_series_chart.series_label', { n: i + 1 }) : ''),
|
|
70
73
|
}));
|
|
71
74
|
const chartRows = bucketDates.map((d, i) => {
|
|
72
75
|
const row = { x: d };
|
|
@@ -99,7 +102,7 @@ export function TimeSeriesChart(props) {
|
|
|
99
102
|
axisLine: false,
|
|
100
103
|
tickLine: false,
|
|
101
104
|
tickMargin: 8,
|
|
102
|
-
width:
|
|
105
|
+
width: yAxisWidth ?? DEFAULT_Y_AXIS_WIDTH,
|
|
103
106
|
tickFormatter: yTickFmt,
|
|
104
107
|
};
|
|
105
108
|
// Vertical gridlines carry no information a time axis doesn't already
|
|
@@ -118,7 +121,7 @@ export function TimeSeriesChart(props) {
|
|
|
118
121
|
.filter((s) => s.label !== '')
|
|
119
122
|
.map((s) => ({ label: s.label, color: s.color }));
|
|
120
123
|
const legendVisible = showLegend ?? (legendEntries.length > 1 && legendEntries.length === seriesMeta.length);
|
|
121
|
-
const referenceEl = showReference ? (_jsx(ReferenceLine, { x: referenceDate, stroke: "#fbbf24", strokeDasharray: "4 3", label: { value: '
|
|
124
|
+
const referenceEl = showReference ? (_jsx(ReferenceLine, { x: referenceDate, stroke: "#fbbf24", strokeDasharray: "4 3", label: { value: translate('time_series_chart.reference_today'), position: 'insideTopRight', fontSize: 10, fill: '#fbbf24' } })) : null;
|
|
122
125
|
// ── Render ────────────────────────────────────────────────────────────────
|
|
123
126
|
return (_jsxs("div", { className: className, children: [showControls && (_jsx("div", { style: { marginBottom: 8 }, children: _jsx(ChartControls, { grain: activeGrain, chartType: activeType, onGrainChange: handleGrain, onChartTypeChange: handleType, grains: grains, theme: theme }) })), _jsx("div", { style: { height, width: '100%' }, children: mounted && activeType === 'bar' ? (_jsx(ResponsiveContainer, { width: "100%", height: height, children: _jsxs(RBarChart, { data: chartRows, margin: CHART_MARGIN, barGap: 2, children: [gridEl, _jsx(XAxis, { ...xAxisProps }), _jsx(YAxis, { ...yAxisProps }), tooltipEl, referenceEl, seriesMeta.map((s) => (_jsx(Bar, { dataKey: s.key, name: s.label, fill: s.color, radius: [3, 3, 0, 0], maxBarSize: 28, isAnimationActive: false }, s.key)))] }) })) : mounted ? (_jsx(ResponsiveContainer, { width: "100%", height: height, children: _jsxs(RLineChart, { data: chartRows, margin: CHART_MARGIN, children: [gridEl, _jsx(XAxis, { ...xAxisProps }), _jsx(YAxis, { ...yAxisProps }), tooltipEl, referenceEl, seriesMeta.map((s) => (_jsx(Line, { type: "monotone", dataKey: s.key, name: s.label, stroke: s.color, strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", dot: false,
|
|
124
127
|
// A hover dot ringed in the chart surface reads as a marker
|
package/dist/index.client.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.client.d.ts","sourceRoot":"","sources":["../src/index.client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,YAAY,EACV,iBAAiB,EACjB,KAAK,EACL,GAAG,EACH,SAAS,EACT,MAAM,EACN,QAAQ,GACT,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACnF,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC7F,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAGjF,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAK3D,OAAO,EACL,WAAW,EACX,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACnE,YAAY,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,YAAY,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACxE,YAAY,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAC5F,YAAY,EAAE,kBAAkB,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC5F,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGrF,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,YAAY,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.client.d.ts","sourceRoot":"","sources":["../src/index.client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,CAAC,EAAE,MAAM,gBAAgB,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,YAAY,EACV,iBAAiB,EACjB,KAAK,EACL,GAAG,EACH,SAAS,EACT,MAAM,EACN,QAAQ,GACT,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACnF,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC7F,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAGjF,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAK3D,OAAO,EACL,WAAW,EACX,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACnE,YAAY,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,YAAY,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACxE,YAAY,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAC5F,YAAY,EAAE,kBAAkB,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC5F,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGrF,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,YAAY,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC"}
|
package/dist/index.client.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Client-safe entry — no Node.js builtins.
|
|
2
2
|
export { CONTRACT_VERSION } from './lib/contract-version.js';
|
|
3
|
+
export { t } from './lib/index.js';
|
|
3
4
|
export { parseDescriptor } from './schema/descriptor.js';
|
|
4
5
|
export { parseQuery } from './schema/query.js';
|
|
5
6
|
export { derivePickerOptions } from './lib/picker.js';
|
package/dist/lib/format.js
CHANGED
|
@@ -25,7 +25,7 @@ export function formatValue(value, format) {
|
|
|
25
25
|
return '';
|
|
26
26
|
switch (format.kind) {
|
|
27
27
|
case 'currency':
|
|
28
|
-
return formatCurrency(Number(value), format.ccy);
|
|
28
|
+
return formatCurrency(Number(value), { currency: format.ccy });
|
|
29
29
|
case 'number':
|
|
30
30
|
return formatNumber(Number(value), format.decimals);
|
|
31
31
|
case 'percent':
|
package/dist/lib/index.d.ts
CHANGED
package/dist/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAoBlD,eAAO,MAAM,CAAC,gCAAqC,CAAC"}
|
package/dist/lib/index.js
CHANGED
|
@@ -1,2 +1,20 @@
|
|
|
1
1
|
export { CONTRACT_VERSION } from './contract-version.js';
|
|
2
2
|
export { derivePickerOptions } from './picker.js';
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// i18n
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
//
|
|
7
|
+
// Uses a plain `import ... from '../locales/en.json'` (resolveJsonModule),
|
|
8
|
+
// NOT `createRequire` — this package's client entry (index.client.ts)
|
|
9
|
+
// re-exports the chart/visualizer components that call `t()`, so this
|
|
10
|
+
// catalog module ends up bundled into browser code. `createRequire` is
|
|
11
|
+
// Node-only and would break there; a plain JSON import works under this
|
|
12
|
+
// package's "module": "Node16" tsconfig (no import-attribute syntax needed)
|
|
13
|
+
// and is bundler/browser-safe.
|
|
14
|
+
import en from '../locales/en.json';
|
|
15
|
+
import { createPackageT } from 'hazo_core/i18n';
|
|
16
|
+
// Namespaced translator for this package's own baked-in strings (chart
|
|
17
|
+
// empty states, axis/legend labels, visualizer display names). `en.json` is
|
|
18
|
+
// a flat { "key": "English text" } catalog — add keys there as they come
|
|
19
|
+
// up, then call t('key', { var: value }) for {{var}} interpolation.
|
|
20
|
+
export const t = createPackageT('hazo_dataviz', en);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"chart_frame.no_data": "No data to display",
|
|
3
|
+
"table.no_data": "No data to display",
|
|
4
|
+
"line_chart.no_data": "No data",
|
|
5
|
+
"multi_line_chart.no_data": "No data",
|
|
6
|
+
"time_series_chart.no_data": "No data",
|
|
7
|
+
"time_series_chart.series_label": "Series {{n}}",
|
|
8
|
+
"time_series_chart.reference_today": "today",
|
|
9
|
+
"chart_controls.grain_day": "Daily",
|
|
10
|
+
"chart_controls.grain_week": "Weekly",
|
|
11
|
+
"chart_controls.grain_month": "Monthly",
|
|
12
|
+
"chart_controls.grain_quarter": "Quarterly",
|
|
13
|
+
"chart_controls.grain_year": "Yearly",
|
|
14
|
+
"chart_controls.type_line": "Line",
|
|
15
|
+
"chart_controls.type_bar": "Bar",
|
|
16
|
+
"visualizer.table_label": "Table",
|
|
17
|
+
"visualizer.single_stat_label": "Single Stat",
|
|
18
|
+
"visualizer.area_label": "Area Chart",
|
|
19
|
+
"visualizer.bar_label": "Bar Chart",
|
|
20
|
+
"visualizer.line_label": "Line Chart",
|
|
21
|
+
"visualizer.stacked_bar_label": "Stacked Bar Chart"
|
|
22
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"area.d.ts","sourceRoot":"","sources":["../../src/visualizers/area.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,UAAU,EAAoC,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"area.d.ts","sourceRoot":"","sources":["../../src/visualizers/area.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,UAAU,EAAoC,MAAM,mBAAmB,CAAC;AAgDtF,eAAO,MAAM,IAAI,EAAE,UAgFlB,CAAC"}
|
package/dist/visualizers/area.js
CHANGED
|
@@ -3,6 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, } from 'recharts';
|
|
4
4
|
import { classifyShape } from '../lib/shape.js';
|
|
5
5
|
import { pickColor } from './palette.js';
|
|
6
|
+
import { t } from '../lib/index.js';
|
|
6
7
|
import { makeFormatter, makeTooltip, EmptyState, axisProps, gridProps, legendProps, CHART_MARGIN, CHART_THEME, } from './chart_frame.js';
|
|
7
8
|
function pivotData(result, encoding) {
|
|
8
9
|
if (!encoding.series) {
|
|
@@ -29,7 +30,7 @@ function pivotData(result, encoding) {
|
|
|
29
30
|
}
|
|
30
31
|
export const area = {
|
|
31
32
|
id: 'area',
|
|
32
|
-
label: '
|
|
33
|
+
label: t('visualizer.area_label'),
|
|
33
34
|
accepts(descriptor, query) {
|
|
34
35
|
const shape = classifyShape(descriptor, query);
|
|
35
36
|
if (shape.temporalDims.length >= 1 && shape.measureCount >= 1)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bar.d.ts","sourceRoot":"","sources":["../../src/visualizers/bar.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,UAAU,EAAoC,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"bar.d.ts","sourceRoot":"","sources":["../../src/visualizers/bar.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,UAAU,EAAoC,MAAM,mBAAmB,CAAC;AAgBtF,eAAO,MAAM,GAAG,EAAE,UA+DjB,CAAC"}
|
package/dist/visualizers/bar.js
CHANGED
|
@@ -3,10 +3,11 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, } from 'recharts';
|
|
4
4
|
import { classifyShape } from '../lib/shape.js';
|
|
5
5
|
import { pickColor } from './palette.js';
|
|
6
|
+
import { t } from '../lib/index.js';
|
|
6
7
|
import { makeFormatter, makeTooltip, EmptyState, axisProps, gridProps, legendProps, CHART_MARGIN, } from './chart_frame.js';
|
|
7
8
|
export const bar = {
|
|
8
9
|
id: 'bar',
|
|
9
|
-
label: '
|
|
10
|
+
label: t('visualizer.bar_label'),
|
|
10
11
|
accepts(descriptor, query) {
|
|
11
12
|
const shape = classifyShape(descriptor, query);
|
|
12
13
|
if (shape.dimCount === 1 && shape.categoricalDims.length === 1 && shape.measureCount >= 1) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart_frame.d.ts","sourceRoot":"","sources":["../../src/visualizers/chart_frame.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"chart_frame.d.ts","sourceRoot":"","sources":["../../src/visualizers/chart_frame.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEhE;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW;IACtB,sCAAsC;;IAEtC,iDAAiD;;IAEjD,8CAA8C;;IAE9C,oCAAoC;;IAEpC,6BAA6B;;IAE7B,2BAA2B;;IAE3B,mCAAmC;;CAE3B,CAAC;AAEX,yEAAyE;AACzE,eAAO,MAAM,YAAY;;;;;CAAsD,CAAC;AAEhF,uFAAuF;AACvF,eAAO,MAAM,SAAS;;;;;;;;;;CAKZ,CAAC;AAEX,sFAAsF;AACtF,eAAO,MAAM,SAAS;;;CAGZ,CAAC;AAEX;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,CAAC,CAAC,EAAE,OAAO,KAAK,MAAM,CAYhF;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,cAAc,GAAG,SAAS,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAK3G;AAED,UAAU,mBAAmB;IAC3B,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC3B;AAED,UAAU,kBAAkB;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAChC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;GAMG;AAMH,wBAAgB,WAAW,CACzB,cAAc,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,MAAM,EACtC,cAAc,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,MAAM,GACrC,CAAC,KAAK,EAAE,kBAAkB,KAAK,GAAG,CAqEpC;AAED,wDAAwD;AACxD,eAAO,MAAM,WAAW;;;;;;;CAOvB,CAAC;AAEF;;GAEG;AACH,wBAAgB,UAAU,IAAI,KAAK,CAAC,YAAY,CAqB/C"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { formatValue } from '../lib/format.js';
|
|
4
|
+
import { t } from '../lib/index.js';
|
|
4
5
|
/**
|
|
5
6
|
* "Studio" chart theme — a warm, editorial token set shared by every recharts
|
|
6
7
|
* visualizer so the package renders one coherent look out of the box.
|
|
@@ -142,5 +143,5 @@ export function EmptyState() {
|
|
|
142
143
|
height: 120,
|
|
143
144
|
color: CHART_THEME.muted,
|
|
144
145
|
fontSize: 13,
|
|
145
|
-
}, children: [_jsxs("svg", { width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", stroke: CHART_THEME.hairline, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("path", { d: "M3 3v18h18" }), _jsx("path", { d: "M7 15l3-3 3 2 5-6" })] }), _jsx("span", { children:
|
|
146
|
+
}, children: [_jsxs("svg", { width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", stroke: CHART_THEME.hairline, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("path", { d: "M3 3v18h18" }), _jsx("path", { d: "M7 15l3-3 3 2 5-6" })] }), _jsx("span", { children: t('chart_frame.no_data') })] }));
|
|
146
147
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"line.d.ts","sourceRoot":"","sources":["../../src/visualizers/line.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,UAAU,EAAoC,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"line.d.ts","sourceRoot":"","sources":["../../src/visualizers/line.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,UAAU,EAAoC,MAAM,mBAAmB,CAAC;AAkDtF,eAAO,MAAM,IAAI,EAAE,UAsElB,CAAC"}
|
package/dist/visualizers/line.js
CHANGED
|
@@ -3,6 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, } from 'recharts';
|
|
4
4
|
import { classifyShape } from '../lib/shape.js';
|
|
5
5
|
import { pickColor } from './palette.js';
|
|
6
|
+
import { t } from '../lib/index.js';
|
|
6
7
|
import { makeFormatter, makeTooltip, EmptyState, axisProps, gridProps, legendProps, CHART_MARGIN, CHART_THEME, } from './chart_frame.js';
|
|
7
8
|
function pivotData(result, encoding) {
|
|
8
9
|
if (!encoding.series) {
|
|
@@ -31,7 +32,7 @@ function pivotData(result, encoding) {
|
|
|
31
32
|
}
|
|
32
33
|
export const line = {
|
|
33
34
|
id: 'line',
|
|
34
|
-
label: '
|
|
35
|
+
label: t('visualizer.line_label'),
|
|
35
36
|
accepts(descriptor, query) {
|
|
36
37
|
const shape = classifyShape(descriptor, query);
|
|
37
38
|
if (shape.temporalDims.length >= 1 && shape.measureCount >= 1)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"single_stat.d.ts","sourceRoot":"","sources":["../../src/visualizers/single_stat.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAoC,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"single_stat.d.ts","sourceRoot":"","sources":["../../src/visualizers/single_stat.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAoC,MAAM,mBAAmB,CAAC;AAQtF,eAAO,MAAM,UAAU,EAAE,UAmFxB,CAAC"}
|
|
@@ -3,9 +3,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { classifyShape } from '../lib/shape.js';
|
|
4
4
|
import { makeFormatter, CHART_THEME } from './chart_frame.js';
|
|
5
5
|
import { pickColor } from './palette.js';
|
|
6
|
+
import { t } from '../lib/index.js';
|
|
6
7
|
export const singleStat = {
|
|
7
8
|
id: 'single_stat',
|
|
8
|
-
label: '
|
|
9
|
+
label: t('visualizer.single_stat_label'),
|
|
9
10
|
accepts(descriptor, query) {
|
|
10
11
|
const shape = classifyShape(descriptor, query);
|
|
11
12
|
if (shape.measureCount === 1 && shape.dimCount === 0)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stacked_bar.d.ts","sourceRoot":"","sources":["../../src/visualizers/stacked_bar.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,UAAU,EAAoC,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"stacked_bar.d.ts","sourceRoot":"","sources":["../../src/visualizers/stacked_bar.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,UAAU,EAAoC,MAAM,mBAAmB,CAAC;AA+CtF,eAAO,MAAM,UAAU,EAAE,UAmFxB,CAAC"}
|
|
@@ -3,6 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, } from 'recharts';
|
|
4
4
|
import { classifyShape } from '../lib/shape.js';
|
|
5
5
|
import { pickColor } from './palette.js';
|
|
6
|
+
import { t } from '../lib/index.js';
|
|
6
7
|
import { makeFormatter, makeTooltip, EmptyState, axisProps, gridProps, legendProps, CHART_MARGIN, } from './chart_frame.js';
|
|
7
8
|
function pivotData(result, encoding) {
|
|
8
9
|
if (!encoding.series) {
|
|
@@ -29,7 +30,7 @@ function pivotData(result, encoding) {
|
|
|
29
30
|
}
|
|
30
31
|
export const stackedBar = {
|
|
31
32
|
id: 'stacked_bar',
|
|
32
|
-
label: '
|
|
33
|
+
label: t('visualizer.stacked_bar_label'),
|
|
33
34
|
accepts(descriptor, query) {
|
|
34
35
|
const shape = classifyShape(descriptor, query);
|
|
35
36
|
// A stacked bar needs two dimensions and at least one categorical dimension to
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../src/visualizers/table.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAoC,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../src/visualizers/table.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAoC,MAAM,mBAAmB,CAAC;AAMtF,eAAO,MAAM,KAAK,EAAE,UAiGnB,CAAC"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { makeFormatter, CHART_THEME } from './chart_frame.js';
|
|
4
|
+
import { t } from '../lib/index.js';
|
|
4
5
|
export const table = {
|
|
5
6
|
id: 'table',
|
|
6
|
-
label: '
|
|
7
|
+
label: t('visualizer.table_label'),
|
|
7
8
|
accepts(_descriptor, _query) {
|
|
8
9
|
return 0.1;
|
|
9
10
|
},
|
|
@@ -16,7 +17,7 @@ export const table = {
|
|
|
16
17
|
height: 80,
|
|
17
18
|
color: CHART_THEME.muted,
|
|
18
19
|
fontSize: 13,
|
|
19
|
-
}, children:
|
|
20
|
+
}, children: t('table.no_data') }));
|
|
20
21
|
}
|
|
21
22
|
const formatters = result.columns.map((col) => makeFormatter(col));
|
|
22
23
|
return (_jsx("div", { style: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hazo_dataviz",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Headless data visualization primitives for hazo apps",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -45,10 +45,11 @@
|
|
|
45
45
|
"zod": "^4.1.12"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
|
-
"hazo_api": "^2.
|
|
49
|
-
"hazo_connect": "^4.
|
|
50
|
-
"hazo_core": "^2.
|
|
51
|
-
"
|
|
48
|
+
"hazo_api": "^2.8.0",
|
|
49
|
+
"hazo_connect": "^4.3.0",
|
|
50
|
+
"hazo_core": "^2.4.0",
|
|
51
|
+
"hazo_i18n": "^0.5.0",
|
|
52
|
+
"hazo_ui": "^6.12.0",
|
|
52
53
|
"react": "^18.0.0 || ^19.0.0",
|
|
53
54
|
"react-dom": "^18.0.0 || ^19.0.0",
|
|
54
55
|
"recharts": "^2.15.4 || ^3.0.0"
|
|
@@ -57,6 +58,9 @@
|
|
|
57
58
|
"hazo_connect": {
|
|
58
59
|
"optional": true
|
|
59
60
|
},
|
|
61
|
+
"hazo_i18n": {
|
|
62
|
+
"optional": true
|
|
63
|
+
},
|
|
60
64
|
"hazo_ui": {
|
|
61
65
|
"optional": true
|
|
62
66
|
},
|