| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
fix(core): provide dataVars defaults in prebuilt CSS (#7694) * fix(core): provide dataVars defaults in prebuilt CSS Amend AST-066 with a draft prebuilt-distribution exception while retaining source tree-shaking and sparse theme overrides. Extract the canonical StyleX group through the existing dependency-aware build and prove defaults, provider deduplication, and both CSS load orders. * docs: clarify prebuilt data token ownership Keep approval narration in the PR rather than the AST-066 system record, use the normal pending-decider field, and correct stale JS-only chart comments without changing mark defaults or runtime output. * docs: align AST-080 data group placement note Core prebuilt CSS owns the canonical dataVars group; Lab relies on that stylesheet without another copy. Update only the current-state note, leaving AST-066 approval metadata unchanged. * docs: name AST-066 heading by its behavior Retitle the prebuilt data-defaults section without changing its content or draft approval metadata. * docs: record AST-066 spec-owner approval Restore current/accepted authority and date DEC-9 from cixzhang’s recorded 2026-10-20 approval of b69e0546. The metadata-recording head still needs exact-head re-approval. | 3 天前 | |
fix(charts): harden Chart contract (#6247) | 1 个月前 | |
fix(charts): harden Chart contract (#6247) | 1 个月前 | |
fix(charts): harden Chart contract (#6247) | 1 个月前 | |
fix(charts): harden Chart contract (#6247) | 1 个月前 | |
[Component Audit] ChartAxis: preserve complete truncated labels (#6346) * fix(charts): preserve complete ChartAxis labels * fix(charts): count axis density by grapheme | 1 个月前 | |
[Component Audit] ChartAxis: preserve complete truncated labels (#6346) * fix(charts): preserve complete ChartAxis labels * fix(charts): count axis density by grapheme | 1 个月前 | |
[Component Audit] ChartAxis: preserve complete truncated labels (#6346) * fix(charts): preserve complete ChartAxis labels * fix(charts): count axis density by grapheme | 1 个月前 | |
[Component Audit] ChartAxis: preserve complete truncated labels (#6346) * fix(charts): preserve complete ChartAxis labels * fix(charts): count axis density by grapheme | 1 个月前 | |
harden(charts): production-hardening pass (follow-up to #3672) (#3694) * harden(charts): collapse non-finite xPixel input to NaN sentinel Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): stacked y-domain covers all layer boundaries, not just net totals Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): clamp Chart to finite size; 'use client' on ChartContext barrel path Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): dodge excludes non-finite y; guard color-accessor throws and whitespace paints Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): converge annotation marks on xPixel/isBandScale; guard errorBar cap width Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): free/flag shaders in createProgram to close a GL resource leak Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): fix GPU-pick readPixels Y-flip off-by-one in dotGLInteractive Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): clamp tickCount before d3 .ticks() to prevent RangeError crash Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): tooltip guards for NaN coords, custom-render-null card, and stale hovered index Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): reject non-finite palette count; validate date-only strings in formatters Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): size heatmap cells to the band step for a contiguous grid WebGL heatmap cells were sized to the shared x-scale's bar-padded bandwidth, leaving large gaps between columns while the local y-scale stayed tight — a sparse, asymmetric grid. Size cells to the band step (centered on the band) so they fill their slot: a proper contiguous heatmap, still axis-aligned. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): heatmap cells fill full band step, not bandwidth Cells were sized to xScale.bandwidth(), but the shared x band scale carries ~0.2 padding, so step > bandwidth left permanent gaps between columns that cellGap could not close (a sparse, striped grid instead of a contiguous heatmap). Size cells to the full band step and center them on the band so cellGap alone controls spacing. Applied to both the charts heatmapGL mark and the lab ChartHeatmapGL component. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(charts): categorical y-axis for heatmap rows A heatmap's rows are categories (e.g. days), but the chart's y-axis was a linear value scale — so a left <ChartAxis> showed meaningless 0-N value ticks and the rows didn't correspond to the axis. Add an opt-in categorical y-axis: a series can declare `layout.yBandKey`, and the layout pass builds a shared `yBandScale` over that key's unique values, exposed on the series/chart context. ChartAxis prefers `yBandScale` for vertical axes, so the left axis renders the row labels aligned to each cell. heatmapGL now declares `dataKeys: []` + `layout.yBandKey` and draws rows from the shared band scale, keeping cells aligned with the axis and out of the linear y-domain / value tooltip. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): frame heatmap with edge-anchored x/y axis lines A heatmap's categorical y-axis leaves the linear y-domain degenerate and spanning zero, so ChartAxis' "draw the bottom edge line at zero" rule placed the x-axis line mid-plot, cutting across the cells. Anchor the bottom edge line to the plot edge whenever the y-axis is categorical (yBandScale present), and fill heatmap rows edge-to-edge (band padding 0) so the grid meets both axis lines. The WebGL heatmap story now enables the x and y axis lines, which frame the grid at its edges. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): heatmap columns tile edge-to-edge (drop bar x-padding) For a categorical grid (heatmap), the x band scale still carried the bar-style outer padding (0.2), so columns were inset ~4-5px from the left/right axis lines while the rows (padding 0) sat flush top/bottom — an asymmetric, gappy look. When the y-axis is categorical, drop the x padding too so the grid fills the plot edge-to-edge and meets both axis lines flush on every side. Also hoists the yBandKey detection so x and y share it. Co-authored-by: Cursor <cursoragent@cursor.com> * docs(charts): add heatmap screenshot Co-authored-by: Cursor <cursoragent@cursor.com> * chore(charts): drop committed heatmap screenshot The screenshot belongs in the PR description, not the source tree. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com> | 3 个月前 | |
docs(charts): document ChartGrid audit surface (#6347) | 1 个月前 | |
docs(charts): document ChartGrid audit surface (#6347) | 1 个月前 | |
docs(charts): document ChartGrid audit surface (#6347) | 1 个月前 | |
docs(charts): document ChartGrid audit surface (#6347) | 1 个月前 | |
docs(charts): document ChartLegend audit surface (#6379) | 1 个月前 | |
docs(charts): document ChartLegend audit surface (#6379) | 1 个月前 | |
fix(charts): harden Chart contract (#6247) | 1 个月前 | |
fix(charts): harden Chart contract (#6247) | 1 个月前 | |
docs(charts): document ChartSwatch audit surface (#6388) | 1 个月前 | |
docs(charts): document ChartSwatch audit surface (#6388) | 1 个月前 | |
test: route charts/vega into the ui vitest project and cover the untested viz packages and hooks (#4295) (#4377) * test: cover the viz packages and five core hooks packages/charts and packages/vega had no functional tests at all, and packages/lab's chart primitives (Chart*, Radial*, ThreeD*, Sankey*, SVGIcon) rendered nothing under test. Add colocated tests for each, plus renderHook tests for the three useCalendar* hooks, useCollapsible and useTableFilterState. Harness: charts and vega were falling through to the `node` vitest project, which has no jsdom, no StyleX transform and no jest-dom, so their tests could never have run there. Move both into the `ui` project and give vega the test scripts the other packages already have. 53 test files, 307 tests. Verified: full suite 7943 pass / 430 files, still green with packages/core/dist absent (the cold-CI path, which charts needs because it imports core by bare name for values); 8 sampled mutations across all four packages, each killed by exactly the new test. Refs #4295 * test: cover remaining core hooks and components Finishes the functional-coverage sweep started in 64d9ea3. Adds renderHook tests for useScrollLock, useLightbox, useChatPasteAsToken, useImperativeAlertDialog, useTranslator and useTooltip, plus colocated tests for the components that had none: CommandPaletteEmpty, InputClearButton, TypeaheadItem, ChatSendButton, PowerSearchToken, PowerSearchFilterEditor and TableHeaderCell. Two of the issue's nine "zero-test" components already had tests (ChatComposerDrawer, MobileNavToggle, from #3996 and #3721), so the inventory is smaller than the issue states. Extracts the StyleX declaration read-back helper that three of these files each needed into __tests__/stylexDeclarations.ts rather than landing a third copy. Two branches are deliberately left uncovered, with the reason recorded next to them: the ignored-onOpenChange(true) guards in useLightbox and useImperativeAlertDialog are unreachable through the public surface, and reaching into element props to force them both breaks the repo's no-react-introspection lint rule and asserts a value that is already settled. useTooltip's focus paths are also omitted -- jsdom resolves :focus-visible as :focus, so those tests would pass with the gate deleted. Verified: 8101 tests / 443 files green, eslint and prettier clean, core typecheck clean; three sampled mutations (the send-button variant ternary, CommandPaletteEmpty's xstyle merge, useTooltip's touch suppression) each killed by exactly one new test. Refs #4295 * test: port the branch's remaining assertions onto main's test files The eight add/add conflicts resolved to main's files in the merge; this ports back only the assertions main does not cover and that still hold today (render gates and sizing, layer groups and masks, style restore, registry glyph, xstyle forwarding, context guards). Duplicates of main's coverage are dropped rather than kept twice. Four files went stale over the 815-commit gap and follow today's behavior: the hidden data-table fallback (#4382) means chart label and tooltip queries scope to the svg; useTooltip's touch guard is per pointer type (#5248) and a controlled tooltip reports Escape through onHide (#4881); TableHeaderCell dividers are logical inline-end properties (#4434). * test(calendar): assert month labels as English literals CI's lint job fails on the one raw Intl call left in these tests: main's no-raw-intl-locale rule keeps its test-oracle allowlist inside the rule, and this file is not on it. The oracle was also the wrong side: with no InternationalizationProvider mounted, useLocale() resolves to 'en', so the hook's labels never followed the machine locale that Intl.DateTimeFormat(undefined) reads. Literal 'April 2026' style assertions match Calendar.test.tsx and drop the Intl dependency. | 1 个月前 | |
docs(charts): document ChartSwatch audit surface (#6388) | 1 个月前 | |
[Component Audit] ChartTooltip: keep hover details above modal surfaces (#6394) * test(charts): cover ChartTooltip layer hosting * fix(charts): keep ChartTooltip in the top layer * test(charts): harden modal tooltip evidence * fix(charts): preserve tooltip layer fallback * docs(charts): register ChartTooltip route * fix(charts): preserve tooltip layer context * fix(charts): keep tooltip open across data points | 1 个月前 | |
[Component Audit] ChartTooltip: keep hover details above modal surfaces (#6394) * test(charts): cover ChartTooltip layer hosting * fix(charts): keep ChartTooltip in the top layer * test(charts): harden modal tooltip evidence * fix(charts): preserve tooltip layer fallback * docs(charts): register ChartTooltip route * fix(charts): preserve tooltip layer context * fix(charts): keep tooltip open across data points | 1 个月前 | |
[Component Audit] ChartTooltip: keep hover details above modal surfaces (#6394) * test(charts): cover ChartTooltip layer hosting * fix(charts): keep ChartTooltip in the top layer * test(charts): harden modal tooltip evidence * fix(charts): preserve tooltip layer fallback * docs(charts): register ChartTooltip route * fix(charts): preserve tooltip layer context * fix(charts): keep tooltip open across data points | 1 个月前 | |
[Component Audit] ChartTooltip: keep hover details above modal surfaces (#6394) * test(charts): cover ChartTooltip layer hosting * fix(charts): keep ChartTooltip in the top layer * test(charts): harden modal tooltip evidence * fix(charts): preserve tooltip layer fallback * docs(charts): register ChartTooltip route * fix(charts): preserve tooltip layer context * fix(charts): keep tooltip open across data points | 1 个月前 | |
fix(i18n): harden date locale handling (#5303) * fix(core): don't format PlainDate with the runtime's locale plainDateFormat passed undefined to Intl.DateTimeFormat, so the locale resolved to whatever the runtime had. Across an SSR boundary that can differ and produce a hydration mismatch. Default to 'en', matching what useLocale() returns outside a provider, while keeping the optional locale parameter for provider-aware callers. * chore: add plain date locale changeset * fix(core): harden date locale behavior * fix: keep date formatting Gregorian --------- Co-authored-by: Joey Farina <17398284+josephfarina@users.noreply.github.com> | 1 个月前 | |
fix(charts): harden Chart contract (#6247) | 1 个月前 | |
refactor: migrate charts/lab color parsers onto shared @astryxdesign/core/utils/color (#3749) | 3 个月前 | |
refactor: migrate charts/lab color parsers onto shared @astryxdesign/core/utils/color (#3749) | 3 个月前 | |
feat(charts): first pass — extract config-model chart into private @astryxdesign/charts (#3672) * feat(charts): move ChartV2 into @astryxdesign/charts + Stage 1 fixes Fills the bootstrap @astryxdesign/charts scaffold (#3570) with the config-model chart formerly known as ChartV2 in @astryxdesign/lab, and removes it from lab. Adopts the scaffold's canary-only publish model; adds d3 deps, the build:css step, and the ./charts.css export (as the scaffold README anticipated). Includes the Stage 1 fixes done pre-reconciliation: collision-free _uid series identity; yBaseline/yDomain/xDomain + plot clip + continuous headroom + working streaming; theme-palette auto-colors with fixed default tokens and accessor series in the legend; width-aware axis label density; implemented dot.dodge; reference-line label clamping. Wires charts into Storybook + CLI templates and adds the charts target to build-css. README updated to describe the real (d3-based) implementation, superseding the "peer engine" scaffold wording. Co-authored-by: Cursor <cursoragent@cursor.com> * docs(charts): add launch readiness audit Co-authored-by: Cursor <cursoragent@cursor.com> * chore(charts): reorganize Storybook into a clean Charts/* section Replaces the scattered Lab/ChartV2* stories with a coherent Charts/ hierarchy covering every mark and chrome component: Bar, Line, Area, Dot, Band, Candlestick, Error Bar, Reference Line, WebGL (scatter/interactive/heatmap/ streaming), Color (auto-palette + accessor), Composite (mixed/kitchen-sink), and Chrome (Axes & Grids, Legend, Swatch, Tooltip). Shared datasets live in _data.ts. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): wire charts into sandbox + restore clean lockfile Two CI failures on #3672: - build (Build Sandbox): the CLI page templates now import @astryxdesign/charts, but the sandbox app didn't depend on it → "Module not found". Add @astryxdesign/charts to apps/sandbox dependencies (it's a 'use client' page, so no 'use client' is required on the chart components for this build). - dependency-check: an earlier local install via the public npm registry had bumped unrelated transitive deps (@typescript-eslint 8.63.0, browserslist, caniuse-lite) to versions not mirrored in the internal registry. Restore the lockfile to origin/main and re-add only the charts importer (d3 deps) + the sandbox/storybook workspace links. Lockfile diff vs main is now +25/-0. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): add charts dep to docsite (Vercel build) The docsite's templateComponents.ts lazy-imports every CLI page template, including table-page-chart and table-page-shoe-store-heatmap which now import @astryxdesign/charts. Without charts as a docsite dependency, the Vercel/Next build fails with "Module not found: Can't resolve '@astryxdesign/charts'" (same root cause as the sandbox build). Add the dep + the workspace link in the lockfile importer. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): declare charts as a CLI peer/dev dependency The docsite lazy-imports CLI page templates in place from packages/cli/templates/**, so webpack resolves their `import '@astryxdesign/charts'` from packages/cli/node_modules — not from the docsite's own node_modules. Adding charts to the docsite alone (prev commit) therefore didn't fix the "Can't resolve '@astryxdesign/charts'" build error. Mirror how `@astryxdesign/lab` is wired (peerDependencies + peerDependenciesMeta + devDependencies) so the chart templates resolve. Verified locally: docsite webpack compile + TypeScript now pass. The only remaining local failure is a pre-existing `/community` prerender error that reproduces solely on Node 25 (CI/Vercel use Node 24; origin/main's Vercel deploy is green with the identical route + cacheComponents:true). Co-authored-by: Cursor <cursoragent@cursor.com> * feat(charts): sharpen WebGL interactive-scatter hover - Widen the color-pick hit target (HIT_PADDING) so hover is "magnetic" instead of pixel-perfect; remove a double-add in the pick shader. - Replace the same-color hover ring with a high-contrast marker (solid fill + light outline + soft halo) that reads on any background. - Rename the two WebGL scatter stories so the static (dotGL) and interactive (dotGLInteractive) variants are unmistakable. Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(charts): production-hardening quality pass across the package Parallel quality pass over all of packages/charts/src. No public API or shared type contracts changed. charts typecheck + lint + build are clean, and storybook (consumer) typechecks clean. Engine (Chart/layout/ChartContext/types/utils): - NaN/Infinity-safe scales; degenerate single-point/zero-range domains expand instead of collapsing to one pixel; explicit x/yDomain ignored when non-finite. Stack-group map built once (was twice). - 'use client' on the Chart root; palette auto-assignment moved out of a side-effect useMemo into a render-phase loop (colors could be dropped). Data marks (bar/line/area/dot + markColor): - Missing/NaN values now render as real gaps (line/area .defined()) or are skipped (bar/dot) instead of collapsing to the baseline. - Grouped-bar width clamped (no divide-by-zero / negative width); NaN-safe rounded-rect paths; color resolver rejects empty/invalid paints. - line/area/dot share xPixel() (removed 3 copies of band-scale logic). Annotation marks (band/candlestick/errorBar/referenceLine): - Missing bounds -> gaps, not false spikes to the axis. - Candlestick renders on linear/time x (slot width from adjacent gap) and skips incomplete OHLC rows. - Reference-line labels clamped inside the plot in both orientations. WebGL (dotGL/dotGLInteractive/heatmapGL/streamGL/webgl): - Eliminate GL context + buffer/texture leaks (create once and reuse; full teardown on unmount; webglcontextlost/restored handling). - streamGL coalesces pushes into one draw per rAF and redraws on resize. - hexToGL robust to shorthand/invalid input (no NaN uniforms). Chrome (ChartAxis/Grid/Legend/Tooltip/Swatch + legend/tooltip): - Axis uses d3 native tick formatting (no float dust; real date labels), value-based keys, label-density thinning on both axes. - Tooltip viewport-clamped; hides when a custom render returns null. - Swatch uses dynamic StyleX instead of an inline style. Color + formatters (getChartColors/useChartColors/formatters): - Fix palettes returning empty strings for un-overridden data tokens (resolve via the canonical token resolver; light/dark + tuple aware). - useChartColors returns a stable reference; categorical wrap-around; sequential/diverging interpolation for any series count. - Formatters rebuilt on cached Intl: correct negatives, boundaries, large numbers, NaN/Infinity, ISO/epoch dates (timezone off-by-one fixed). Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com> | 3 个月前 | |
harden(charts): production-hardening pass (follow-up to #3672) (#3694) * harden(charts): collapse non-finite xPixel input to NaN sentinel Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): stacked y-domain covers all layer boundaries, not just net totals Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): clamp Chart to finite size; 'use client' on ChartContext barrel path Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): dodge excludes non-finite y; guard color-accessor throws and whitespace paints Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): converge annotation marks on xPixel/isBandScale; guard errorBar cap width Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): free/flag shaders in createProgram to close a GL resource leak Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): fix GPU-pick readPixels Y-flip off-by-one in dotGLInteractive Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): clamp tickCount before d3 .ticks() to prevent RangeError crash Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): tooltip guards for NaN coords, custom-render-null card, and stale hovered index Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): reject non-finite palette count; validate date-only strings in formatters Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): size heatmap cells to the band step for a contiguous grid WebGL heatmap cells were sized to the shared x-scale's bar-padded bandwidth, leaving large gaps between columns while the local y-scale stayed tight — a sparse, asymmetric grid. Size cells to the band step (centered on the band) so they fill their slot: a proper contiguous heatmap, still axis-aligned. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): heatmap cells fill full band step, not bandwidth Cells were sized to xScale.bandwidth(), but the shared x band scale carries ~0.2 padding, so step > bandwidth left permanent gaps between columns that cellGap could not close (a sparse, striped grid instead of a contiguous heatmap). Size cells to the full band step and center them on the band so cellGap alone controls spacing. Applied to both the charts heatmapGL mark and the lab ChartHeatmapGL component. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(charts): categorical y-axis for heatmap rows A heatmap's rows are categories (e.g. days), but the chart's y-axis was a linear value scale — so a left <ChartAxis> showed meaningless 0-N value ticks and the rows didn't correspond to the axis. Add an opt-in categorical y-axis: a series can declare `layout.yBandKey`, and the layout pass builds a shared `yBandScale` over that key's unique values, exposed on the series/chart context. ChartAxis prefers `yBandScale` for vertical axes, so the left axis renders the row labels aligned to each cell. heatmapGL now declares `dataKeys: []` + `layout.yBandKey` and draws rows from the shared band scale, keeping cells aligned with the axis and out of the linear y-domain / value tooltip. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): frame heatmap with edge-anchored x/y axis lines A heatmap's categorical y-axis leaves the linear y-domain degenerate and spanning zero, so ChartAxis' "draw the bottom edge line at zero" rule placed the x-axis line mid-plot, cutting across the cells. Anchor the bottom edge line to the plot edge whenever the y-axis is categorical (yBandScale present), and fill heatmap rows edge-to-edge (band padding 0) so the grid meets both axis lines. The WebGL heatmap story now enables the x and y axis lines, which frame the grid at its edges. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): heatmap columns tile edge-to-edge (drop bar x-padding) For a categorical grid (heatmap), the x band scale still carried the bar-style outer padding (0.2), so columns were inset ~4-5px from the left/right axis lines while the rows (padding 0) sat flush top/bottom — an asymmetric, gappy look. When the y-axis is categorical, drop the x padding too so the grid fills the plot edge-to-edge and meets both axis lines flush on every side. Also hoists the yBandKey detection so x and y share it. Co-authored-by: Cursor <cursoragent@cursor.com> * docs(charts): add heatmap screenshot Co-authored-by: Cursor <cursoragent@cursor.com> * chore(charts): drop committed heatmap screenshot The screenshot belongs in the PR description, not the source tree. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com> | 3 个月前 | |
feat(charts): first pass — extract config-model chart into private @astryxdesign/charts (#3672) * feat(charts): move ChartV2 into @astryxdesign/charts + Stage 1 fixes Fills the bootstrap @astryxdesign/charts scaffold (#3570) with the config-model chart formerly known as ChartV2 in @astryxdesign/lab, and removes it from lab. Adopts the scaffold's canary-only publish model; adds d3 deps, the build:css step, and the ./charts.css export (as the scaffold README anticipated). Includes the Stage 1 fixes done pre-reconciliation: collision-free _uid series identity; yBaseline/yDomain/xDomain + plot clip + continuous headroom + working streaming; theme-palette auto-colors with fixed default tokens and accessor series in the legend; width-aware axis label density; implemented dot.dodge; reference-line label clamping. Wires charts into Storybook + CLI templates and adds the charts target to build-css. README updated to describe the real (d3-based) implementation, superseding the "peer engine" scaffold wording. Co-authored-by: Cursor <cursoragent@cursor.com> * docs(charts): add launch readiness audit Co-authored-by: Cursor <cursoragent@cursor.com> * chore(charts): reorganize Storybook into a clean Charts/* section Replaces the scattered Lab/ChartV2* stories with a coherent Charts/ hierarchy covering every mark and chrome component: Bar, Line, Area, Dot, Band, Candlestick, Error Bar, Reference Line, WebGL (scatter/interactive/heatmap/ streaming), Color (auto-palette + accessor), Composite (mixed/kitchen-sink), and Chrome (Axes & Grids, Legend, Swatch, Tooltip). Shared datasets live in _data.ts. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): wire charts into sandbox + restore clean lockfile Two CI failures on #3672: - build (Build Sandbox): the CLI page templates now import @astryxdesign/charts, but the sandbox app didn't depend on it → "Module not found". Add @astryxdesign/charts to apps/sandbox dependencies (it's a 'use client' page, so no 'use client' is required on the chart components for this build). - dependency-check: an earlier local install via the public npm registry had bumped unrelated transitive deps (@typescript-eslint 8.63.0, browserslist, caniuse-lite) to versions not mirrored in the internal registry. Restore the lockfile to origin/main and re-add only the charts importer (d3 deps) + the sandbox/storybook workspace links. Lockfile diff vs main is now +25/-0. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): add charts dep to docsite (Vercel build) The docsite's templateComponents.ts lazy-imports every CLI page template, including table-page-chart and table-page-shoe-store-heatmap which now import @astryxdesign/charts. Without charts as a docsite dependency, the Vercel/Next build fails with "Module not found: Can't resolve '@astryxdesign/charts'" (same root cause as the sandbox build). Add the dep + the workspace link in the lockfile importer. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): declare charts as a CLI peer/dev dependency The docsite lazy-imports CLI page templates in place from packages/cli/templates/**, so webpack resolves their `import '@astryxdesign/charts'` from packages/cli/node_modules — not from the docsite's own node_modules. Adding charts to the docsite alone (prev commit) therefore didn't fix the "Can't resolve '@astryxdesign/charts'" build error. Mirror how `@astryxdesign/lab` is wired (peerDependencies + peerDependenciesMeta + devDependencies) so the chart templates resolve. Verified locally: docsite webpack compile + TypeScript now pass. The only remaining local failure is a pre-existing `/community` prerender error that reproduces solely on Node 25 (CI/Vercel use Node 24; origin/main's Vercel deploy is green with the identical route + cacheComponents:true). Co-authored-by: Cursor <cursoragent@cursor.com> * feat(charts): sharpen WebGL interactive-scatter hover - Widen the color-pick hit target (HIT_PADDING) so hover is "magnetic" instead of pixel-perfect; remove a double-add in the pick shader. - Replace the same-color hover ring with a high-contrast marker (solid fill + light outline + soft halo) that reads on any background. - Rename the two WebGL scatter stories so the static (dotGL) and interactive (dotGLInteractive) variants are unmistakable. Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(charts): production-hardening quality pass across the package Parallel quality pass over all of packages/charts/src. No public API or shared type contracts changed. charts typecheck + lint + build are clean, and storybook (consumer) typechecks clean. Engine (Chart/layout/ChartContext/types/utils): - NaN/Infinity-safe scales; degenerate single-point/zero-range domains expand instead of collapsing to one pixel; explicit x/yDomain ignored when non-finite. Stack-group map built once (was twice). - 'use client' on the Chart root; palette auto-assignment moved out of a side-effect useMemo into a render-phase loop (colors could be dropped). Data marks (bar/line/area/dot + markColor): - Missing/NaN values now render as real gaps (line/area .defined()) or are skipped (bar/dot) instead of collapsing to the baseline. - Grouped-bar width clamped (no divide-by-zero / negative width); NaN-safe rounded-rect paths; color resolver rejects empty/invalid paints. - line/area/dot share xPixel() (removed 3 copies of band-scale logic). Annotation marks (band/candlestick/errorBar/referenceLine): - Missing bounds -> gaps, not false spikes to the axis. - Candlestick renders on linear/time x (slot width from adjacent gap) and skips incomplete OHLC rows. - Reference-line labels clamped inside the plot in both orientations. WebGL (dotGL/dotGLInteractive/heatmapGL/streamGL/webgl): - Eliminate GL context + buffer/texture leaks (create once and reuse; full teardown on unmount; webglcontextlost/restored handling). - streamGL coalesces pushes into one draw per rAF and redraws on resize. - hexToGL robust to shorthand/invalid input (no NaN uniforms). Chrome (ChartAxis/Grid/Legend/Tooltip/Swatch + legend/tooltip): - Axis uses d3 native tick formatting (no float dust; real date labels), value-based keys, label-density thinning on both axes. - Tooltip viewport-clamped; hides when a custom render returns null. - Swatch uses dynamic StyleX instead of an inline style. Color + formatters (getChartColors/useChartColors/formatters): - Fix palettes returning empty strings for un-overridden data tokens (resolve via the canonical token resolver; light/dark + tuple aware). - useChartColors returns a stable reference; categorical wrap-around; sequential/diverging interpolation for any series count. - Formatters rebuilt on cached Intl: correct negatives, boundaries, large numbers, NaN/Infinity, ISO/epoch dates (timezone off-by-one fixed). Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com> | 3 个月前 | |
harden(charts): production-hardening pass (follow-up to #3672) (#3694) * harden(charts): collapse non-finite xPixel input to NaN sentinel Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): stacked y-domain covers all layer boundaries, not just net totals Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): clamp Chart to finite size; 'use client' on ChartContext barrel path Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): dodge excludes non-finite y; guard color-accessor throws and whitespace paints Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): converge annotation marks on xPixel/isBandScale; guard errorBar cap width Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): free/flag shaders in createProgram to close a GL resource leak Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): fix GPU-pick readPixels Y-flip off-by-one in dotGLInteractive Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): clamp tickCount before d3 .ticks() to prevent RangeError crash Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): tooltip guards for NaN coords, custom-render-null card, and stale hovered index Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): reject non-finite palette count; validate date-only strings in formatters Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): size heatmap cells to the band step for a contiguous grid WebGL heatmap cells were sized to the shared x-scale's bar-padded bandwidth, leaving large gaps between columns while the local y-scale stayed tight — a sparse, asymmetric grid. Size cells to the band step (centered on the band) so they fill their slot: a proper contiguous heatmap, still axis-aligned. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): heatmap cells fill full band step, not bandwidth Cells were sized to xScale.bandwidth(), but the shared x band scale carries ~0.2 padding, so step > bandwidth left permanent gaps between columns that cellGap could not close (a sparse, striped grid instead of a contiguous heatmap). Size cells to the full band step and center them on the band so cellGap alone controls spacing. Applied to both the charts heatmapGL mark and the lab ChartHeatmapGL component. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(charts): categorical y-axis for heatmap rows A heatmap's rows are categories (e.g. days), but the chart's y-axis was a linear value scale — so a left <ChartAxis> showed meaningless 0-N value ticks and the rows didn't correspond to the axis. Add an opt-in categorical y-axis: a series can declare `layout.yBandKey`, and the layout pass builds a shared `yBandScale` over that key's unique values, exposed on the series/chart context. ChartAxis prefers `yBandScale` for vertical axes, so the left axis renders the row labels aligned to each cell. heatmapGL now declares `dataKeys: []` + `layout.yBandKey` and draws rows from the shared band scale, keeping cells aligned with the axis and out of the linear y-domain / value tooltip. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): frame heatmap with edge-anchored x/y axis lines A heatmap's categorical y-axis leaves the linear y-domain degenerate and spanning zero, so ChartAxis' "draw the bottom edge line at zero" rule placed the x-axis line mid-plot, cutting across the cells. Anchor the bottom edge line to the plot edge whenever the y-axis is categorical (yBandScale present), and fill heatmap rows edge-to-edge (band padding 0) so the grid meets both axis lines. The WebGL heatmap story now enables the x and y axis lines, which frame the grid at its edges. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): heatmap columns tile edge-to-edge (drop bar x-padding) For a categorical grid (heatmap), the x band scale still carried the bar-style outer padding (0.2), so columns were inset ~4-5px from the left/right axis lines while the rows (padding 0) sat flush top/bottom — an asymmetric, gappy look. When the y-axis is categorical, drop the x padding too so the grid fills the plot edge-to-edge and meets both axis lines flush on every side. Also hoists the yBandKey detection so x and y share it. Co-authored-by: Cursor <cursoragent@cursor.com> * docs(charts): add heatmap screenshot Co-authored-by: Cursor <cursoragent@cursor.com> * chore(charts): drop committed heatmap screenshot The screenshot belongs in the PR description, not the source tree. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com> | 3 个月前 | |
feat(charts): first pass — extract config-model chart into private @astryxdesign/charts (#3672) * feat(charts): move ChartV2 into @astryxdesign/charts + Stage 1 fixes Fills the bootstrap @astryxdesign/charts scaffold (#3570) with the config-model chart formerly known as ChartV2 in @astryxdesign/lab, and removes it from lab. Adopts the scaffold's canary-only publish model; adds d3 deps, the build:css step, and the ./charts.css export (as the scaffold README anticipated). Includes the Stage 1 fixes done pre-reconciliation: collision-free _uid series identity; yBaseline/yDomain/xDomain + plot clip + continuous headroom + working streaming; theme-palette auto-colors with fixed default tokens and accessor series in the legend; width-aware axis label density; implemented dot.dodge; reference-line label clamping. Wires charts into Storybook + CLI templates and adds the charts target to build-css. README updated to describe the real (d3-based) implementation, superseding the "peer engine" scaffold wording. Co-authored-by: Cursor <cursoragent@cursor.com> * docs(charts): add launch readiness audit Co-authored-by: Cursor <cursoragent@cursor.com> * chore(charts): reorganize Storybook into a clean Charts/* section Replaces the scattered Lab/ChartV2* stories with a coherent Charts/ hierarchy covering every mark and chrome component: Bar, Line, Area, Dot, Band, Candlestick, Error Bar, Reference Line, WebGL (scatter/interactive/heatmap/ streaming), Color (auto-palette + accessor), Composite (mixed/kitchen-sink), and Chrome (Axes & Grids, Legend, Swatch, Tooltip). Shared datasets live in _data.ts. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): wire charts into sandbox + restore clean lockfile Two CI failures on #3672: - build (Build Sandbox): the CLI page templates now import @astryxdesign/charts, but the sandbox app didn't depend on it → "Module not found". Add @astryxdesign/charts to apps/sandbox dependencies (it's a 'use client' page, so no 'use client' is required on the chart components for this build). - dependency-check: an earlier local install via the public npm registry had bumped unrelated transitive deps (@typescript-eslint 8.63.0, browserslist, caniuse-lite) to versions not mirrored in the internal registry. Restore the lockfile to origin/main and re-add only the charts importer (d3 deps) + the sandbox/storybook workspace links. Lockfile diff vs main is now +25/-0. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): add charts dep to docsite (Vercel build) The docsite's templateComponents.ts lazy-imports every CLI page template, including table-page-chart and table-page-shoe-store-heatmap which now import @astryxdesign/charts. Without charts as a docsite dependency, the Vercel/Next build fails with "Module not found: Can't resolve '@astryxdesign/charts'" (same root cause as the sandbox build). Add the dep + the workspace link in the lockfile importer. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): declare charts as a CLI peer/dev dependency The docsite lazy-imports CLI page templates in place from packages/cli/templates/**, so webpack resolves their `import '@astryxdesign/charts'` from packages/cli/node_modules — not from the docsite's own node_modules. Adding charts to the docsite alone (prev commit) therefore didn't fix the "Can't resolve '@astryxdesign/charts'" build error. Mirror how `@astryxdesign/lab` is wired (peerDependencies + peerDependenciesMeta + devDependencies) so the chart templates resolve. Verified locally: docsite webpack compile + TypeScript now pass. The only remaining local failure is a pre-existing `/community` prerender error that reproduces solely on Node 25 (CI/Vercel use Node 24; origin/main's Vercel deploy is green with the identical route + cacheComponents:true). Co-authored-by: Cursor <cursoragent@cursor.com> * feat(charts): sharpen WebGL interactive-scatter hover - Widen the color-pick hit target (HIT_PADDING) so hover is "magnetic" instead of pixel-perfect; remove a double-add in the pick shader. - Replace the same-color hover ring with a high-contrast marker (solid fill + light outline + soft halo) that reads on any background. - Rename the two WebGL scatter stories so the static (dotGL) and interactive (dotGLInteractive) variants are unmistakable. Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(charts): production-hardening quality pass across the package Parallel quality pass over all of packages/charts/src. No public API or shared type contracts changed. charts typecheck + lint + build are clean, and storybook (consumer) typechecks clean. Engine (Chart/layout/ChartContext/types/utils): - NaN/Infinity-safe scales; degenerate single-point/zero-range domains expand instead of collapsing to one pixel; explicit x/yDomain ignored when non-finite. Stack-group map built once (was twice). - 'use client' on the Chart root; palette auto-assignment moved out of a side-effect useMemo into a render-phase loop (colors could be dropped). Data marks (bar/line/area/dot + markColor): - Missing/NaN values now render as real gaps (line/area .defined()) or are skipped (bar/dot) instead of collapsing to the baseline. - Grouped-bar width clamped (no divide-by-zero / negative width); NaN-safe rounded-rect paths; color resolver rejects empty/invalid paints. - line/area/dot share xPixel() (removed 3 copies of band-scale logic). Annotation marks (band/candlestick/errorBar/referenceLine): - Missing bounds -> gaps, not false spikes to the axis. - Candlestick renders on linear/time x (slot width from adjacent gap) and skips incomplete OHLC rows. - Reference-line labels clamped inside the plot in both orientations. WebGL (dotGL/dotGLInteractive/heatmapGL/streamGL/webgl): - Eliminate GL context + buffer/texture leaks (create once and reuse; full teardown on unmount; webglcontextlost/restored handling). - streamGL coalesces pushes into one draw per rAF and redraws on resize. - hexToGL robust to shorthand/invalid input (no NaN uniforms). Chrome (ChartAxis/Grid/Legend/Tooltip/Swatch + legend/tooltip): - Axis uses d3 native tick formatting (no float dust; real date labels), value-based keys, label-density thinning on both axes. - Tooltip viewport-clamped; hides when a custom render returns null. - Swatch uses dynamic StyleX instead of an inline style. Color + formatters (getChartColors/useChartColors/formatters): - Fix palettes returning empty strings for un-overridden data tokens (resolve via the canonical token resolver; light/dark + tuple aware). - useChartColors returns a stable reference; categorical wrap-around; sequential/diverging interpolation for any series count. - Formatters rebuilt on cached Intl: correct negatives, boundaries, large numbers, NaN/Infinity, ISO/epoch dates (timezone off-by-one fixed). Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com> | 3 个月前 | |
fix(core): provide dataVars defaults in prebuilt CSS (#7694) * fix(core): provide dataVars defaults in prebuilt CSS Amend AST-066 with a draft prebuilt-distribution exception while retaining source tree-shaking and sparse theme overrides. Extract the canonical StyleX group through the existing dependency-aware build and prove defaults, provider deduplication, and both CSS load orders. * docs: clarify prebuilt data token ownership Keep approval narration in the PR rather than the AST-066 system record, use the normal pending-decider field, and correct stale JS-only chart comments without changing mark defaults or runtime output. * docs: align AST-080 data group placement note Core prebuilt CSS owns the canonical dataVars group; Lab relies on that stylesheet without another copy. Update only the current-state note, leaving AST-066 approval metadata unchanged. * docs: name AST-066 heading by its behavior Retitle the prebuilt data-defaults section without changing its content or draft approval metadata. * docs: record AST-066 spec-owner approval Restore current/accepted authority and date DEC-9 from cixzhang’s recorded 2026-10-20 approval of b69e0546. The metadata-recording head still needs exact-head re-approval. | 3 天前 | |
test: route charts/vega into the ui vitest project and cover the untested viz packages and hooks (#4295) (#4377) * test: cover the viz packages and five core hooks packages/charts and packages/vega had no functional tests at all, and packages/lab's chart primitives (Chart*, Radial*, ThreeD*, Sankey*, SVGIcon) rendered nothing under test. Add colocated tests for each, plus renderHook tests for the three useCalendar* hooks, useCollapsible and useTableFilterState. Harness: charts and vega were falling through to the `node` vitest project, which has no jsdom, no StyleX transform and no jest-dom, so their tests could never have run there. Move both into the `ui` project and give vega the test scripts the other packages already have. 53 test files, 307 tests. Verified: full suite 7943 pass / 430 files, still green with packages/core/dist absent (the cold-CI path, which charts needs because it imports core by bare name for values); 8 sampled mutations across all four packages, each killed by exactly the new test. Refs #4295 * test: cover remaining core hooks and components Finishes the functional-coverage sweep started in 64d9ea3. Adds renderHook tests for useScrollLock, useLightbox, useChatPasteAsToken, useImperativeAlertDialog, useTranslator and useTooltip, plus colocated tests for the components that had none: CommandPaletteEmpty, InputClearButton, TypeaheadItem, ChatSendButton, PowerSearchToken, PowerSearchFilterEditor and TableHeaderCell. Two of the issue's nine "zero-test" components already had tests (ChatComposerDrawer, MobileNavToggle, from #3996 and #3721), so the inventory is smaller than the issue states. Extracts the StyleX declaration read-back helper that three of these files each needed into __tests__/stylexDeclarations.ts rather than landing a third copy. Two branches are deliberately left uncovered, with the reason recorded next to them: the ignored-onOpenChange(true) guards in useLightbox and useImperativeAlertDialog are unreachable through the public surface, and reaching into element props to force them both breaks the repo's no-react-introspection lint rule and asserts a value that is already settled. useTooltip's focus paths are also omitted -- jsdom resolves :focus-visible as :focus, so those tests would pass with the gate deleted. Verified: 8101 tests / 443 files green, eslint and prettier clean, core typecheck clean; three sampled mutations (the send-button variant ternary, CommandPaletteEmpty's xstyle merge, useTooltip's touch suppression) each killed by exactly one new test. Refs #4295 * test: port the branch's remaining assertions onto main's test files The eight add/add conflicts resolved to main's files in the merge; this ports back only the assertions main does not cover and that still hold today (render gates and sizing, layer groups and masks, style restore, registry glyph, xstyle forwarding, context guards). Duplicates of main's coverage are dropped rather than kept twice. Four files went stale over the 815-commit gap and follow today's behavior: the hidden data-table fallback (#4382) means chart label and tooltip queries scope to the svg; useTooltip's touch guard is per pointer type (#5248) and a controlled tooltip reports Escape through onHide (#4881); TableHeaderCell dividers are logical inline-end properties (#4434). * test(calendar): assert month labels as English literals CI's lint job fails on the one raw Intl call left in these tests: main's no-raw-intl-locale rule keeps its test-oracle allowlist inside the rule, and this file is not on it. The oracle was also the wrong side: with no InternationalizationProvider mounted, useLocale() resolves to 'en', so the hook's labels never followed the machine locale that Intl.DateTimeFormat(undefined) reads. Literal 'April 2026' style assertions match Calendar.test.tsx and drop the Intl dependency. | 1 个月前 | |
feat(charts): first pass — extract config-model chart into private @astryxdesign/charts (#3672) * feat(charts): move ChartV2 into @astryxdesign/charts + Stage 1 fixes Fills the bootstrap @astryxdesign/charts scaffold (#3570) with the config-model chart formerly known as ChartV2 in @astryxdesign/lab, and removes it from lab. Adopts the scaffold's canary-only publish model; adds d3 deps, the build:css step, and the ./charts.css export (as the scaffold README anticipated). Includes the Stage 1 fixes done pre-reconciliation: collision-free _uid series identity; yBaseline/yDomain/xDomain + plot clip + continuous headroom + working streaming; theme-palette auto-colors with fixed default tokens and accessor series in the legend; width-aware axis label density; implemented dot.dodge; reference-line label clamping. Wires charts into Storybook + CLI templates and adds the charts target to build-css. README updated to describe the real (d3-based) implementation, superseding the "peer engine" scaffold wording. Co-authored-by: Cursor <cursoragent@cursor.com> * docs(charts): add launch readiness audit Co-authored-by: Cursor <cursoragent@cursor.com> * chore(charts): reorganize Storybook into a clean Charts/* section Replaces the scattered Lab/ChartV2* stories with a coherent Charts/ hierarchy covering every mark and chrome component: Bar, Line, Area, Dot, Band, Candlestick, Error Bar, Reference Line, WebGL (scatter/interactive/heatmap/ streaming), Color (auto-palette + accessor), Composite (mixed/kitchen-sink), and Chrome (Axes & Grids, Legend, Swatch, Tooltip). Shared datasets live in _data.ts. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): wire charts into sandbox + restore clean lockfile Two CI failures on #3672: - build (Build Sandbox): the CLI page templates now import @astryxdesign/charts, but the sandbox app didn't depend on it → "Module not found". Add @astryxdesign/charts to apps/sandbox dependencies (it's a 'use client' page, so no 'use client' is required on the chart components for this build). - dependency-check: an earlier local install via the public npm registry had bumped unrelated transitive deps (@typescript-eslint 8.63.0, browserslist, caniuse-lite) to versions not mirrored in the internal registry. Restore the lockfile to origin/main and re-add only the charts importer (d3 deps) + the sandbox/storybook workspace links. Lockfile diff vs main is now +25/-0. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): add charts dep to docsite (Vercel build) The docsite's templateComponents.ts lazy-imports every CLI page template, including table-page-chart and table-page-shoe-store-heatmap which now import @astryxdesign/charts. Without charts as a docsite dependency, the Vercel/Next build fails with "Module not found: Can't resolve '@astryxdesign/charts'" (same root cause as the sandbox build). Add the dep + the workspace link in the lockfile importer. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): declare charts as a CLI peer/dev dependency The docsite lazy-imports CLI page templates in place from packages/cli/templates/**, so webpack resolves their `import '@astryxdesign/charts'` from packages/cli/node_modules — not from the docsite's own node_modules. Adding charts to the docsite alone (prev commit) therefore didn't fix the "Can't resolve '@astryxdesign/charts'" build error. Mirror how `@astryxdesign/lab` is wired (peerDependencies + peerDependenciesMeta + devDependencies) so the chart templates resolve. Verified locally: docsite webpack compile + TypeScript now pass. The only remaining local failure is a pre-existing `/community` prerender error that reproduces solely on Node 25 (CI/Vercel use Node 24; origin/main's Vercel deploy is green with the identical route + cacheComponents:true). Co-authored-by: Cursor <cursoragent@cursor.com> * feat(charts): sharpen WebGL interactive-scatter hover - Widen the color-pick hit target (HIT_PADDING) so hover is "magnetic" instead of pixel-perfect; remove a double-add in the pick shader. - Replace the same-color hover ring with a high-contrast marker (solid fill + light outline + soft halo) that reads on any background. - Rename the two WebGL scatter stories so the static (dotGL) and interactive (dotGLInteractive) variants are unmistakable. Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(charts): production-hardening quality pass across the package Parallel quality pass over all of packages/charts/src. No public API or shared type contracts changed. charts typecheck + lint + build are clean, and storybook (consumer) typechecks clean. Engine (Chart/layout/ChartContext/types/utils): - NaN/Infinity-safe scales; degenerate single-point/zero-range domains expand instead of collapsing to one pixel; explicit x/yDomain ignored when non-finite. Stack-group map built once (was twice). - 'use client' on the Chart root; palette auto-assignment moved out of a side-effect useMemo into a render-phase loop (colors could be dropped). Data marks (bar/line/area/dot + markColor): - Missing/NaN values now render as real gaps (line/area .defined()) or are skipped (bar/dot) instead of collapsing to the baseline. - Grouped-bar width clamped (no divide-by-zero / negative width); NaN-safe rounded-rect paths; color resolver rejects empty/invalid paints. - line/area/dot share xPixel() (removed 3 copies of band-scale logic). Annotation marks (band/candlestick/errorBar/referenceLine): - Missing bounds -> gaps, not false spikes to the axis. - Candlestick renders on linear/time x (slot width from adjacent gap) and skips incomplete OHLC rows. - Reference-line labels clamped inside the plot in both orientations. WebGL (dotGL/dotGLInteractive/heatmapGL/streamGL/webgl): - Eliminate GL context + buffer/texture leaks (create once and reuse; full teardown on unmount; webglcontextlost/restored handling). - streamGL coalesces pushes into one draw per rAF and redraws on resize. - hexToGL robust to shorthand/invalid input (no NaN uniforms). Chrome (ChartAxis/Grid/Legend/Tooltip/Swatch + legend/tooltip): - Axis uses d3 native tick formatting (no float dust; real date labels), value-based keys, label-density thinning on both axes. - Tooltip viewport-clamped; hides when a custom render returns null. - Swatch uses dynamic StyleX instead of an inline style. Color + formatters (getChartColors/useChartColors/formatters): - Fix palettes returning empty strings for un-overridden data tokens (resolve via the canonical token resolver; light/dark + tuple aware). - useChartColors returns a stable reference; categorical wrap-around; sequential/diverging interpolation for any series count. - Formatters rebuilt on cached Intl: correct negatives, boundaries, large numbers, NaN/Infinity, ISO/epoch dates (timezone off-by-one fixed). Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com> | 3 个月前 | |
harden(charts): production-hardening pass (follow-up to #3672) (#3694) * harden(charts): collapse non-finite xPixel input to NaN sentinel Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): stacked y-domain covers all layer boundaries, not just net totals Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): clamp Chart to finite size; 'use client' on ChartContext barrel path Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): dodge excludes non-finite y; guard color-accessor throws and whitespace paints Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): converge annotation marks on xPixel/isBandScale; guard errorBar cap width Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): free/flag shaders in createProgram to close a GL resource leak Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): fix GPU-pick readPixels Y-flip off-by-one in dotGLInteractive Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): clamp tickCount before d3 .ticks() to prevent RangeError crash Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): tooltip guards for NaN coords, custom-render-null card, and stale hovered index Co-authored-by: Cursor <cursoragent@cursor.com> * harden(charts): reject non-finite palette count; validate date-only strings in formatters Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): size heatmap cells to the band step for a contiguous grid WebGL heatmap cells were sized to the shared x-scale's bar-padded bandwidth, leaving large gaps between columns while the local y-scale stayed tight — a sparse, asymmetric grid. Size cells to the band step (centered on the band) so they fill their slot: a proper contiguous heatmap, still axis-aligned. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): heatmap cells fill full band step, not bandwidth Cells were sized to xScale.bandwidth(), but the shared x band scale carries ~0.2 padding, so step > bandwidth left permanent gaps between columns that cellGap could not close (a sparse, striped grid instead of a contiguous heatmap). Size cells to the full band step and center them on the band so cellGap alone controls spacing. Applied to both the charts heatmapGL mark and the lab ChartHeatmapGL component. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(charts): categorical y-axis for heatmap rows A heatmap's rows are categories (e.g. days), but the chart's y-axis was a linear value scale — so a left <ChartAxis> showed meaningless 0-N value ticks and the rows didn't correspond to the axis. Add an opt-in categorical y-axis: a series can declare `layout.yBandKey`, and the layout pass builds a shared `yBandScale` over that key's unique values, exposed on the series/chart context. ChartAxis prefers `yBandScale` for vertical axes, so the left axis renders the row labels aligned to each cell. heatmapGL now declares `dataKeys: []` + `layout.yBandKey` and draws rows from the shared band scale, keeping cells aligned with the axis and out of the linear y-domain / value tooltip. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): frame heatmap with edge-anchored x/y axis lines A heatmap's categorical y-axis leaves the linear y-domain degenerate and spanning zero, so ChartAxis' "draw the bottom edge line at zero" rule placed the x-axis line mid-plot, cutting across the cells. Anchor the bottom edge line to the plot edge whenever the y-axis is categorical (yBandScale present), and fill heatmap rows edge-to-edge (band padding 0) so the grid meets both axis lines. The WebGL heatmap story now enables the x and y axis lines, which frame the grid at its edges. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(charts): heatmap columns tile edge-to-edge (drop bar x-padding) For a categorical grid (heatmap), the x band scale still carried the bar-style outer padding (0.2), so columns were inset ~4-5px from the left/right axis lines while the rows (padding 0) sat flush top/bottom — an asymmetric, gappy look. When the y-axis is categorical, drop the x padding too so the grid fills the plot edge-to-edge and meets both axis lines flush on every side. Also hoists the yBandKey detection so x and y share it. Co-authored-by: Cursor <cursoragent@cursor.com> * docs(charts): add heatmap screenshot Co-authored-by: Cursor <cursoragent@cursor.com> * chore(charts): drop committed heatmap screenshot The screenshot belongs in the PR description, not the source tree. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com> | 3 个月前 | |
refactor: migrate charts/lab color parsers onto shared @astryxdesign/core/utils/color (#3749) | 3 个月前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 3 天前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 3 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 3 个月前 | ||
| 3 个月前 | ||
| 3 个月前 | ||
| 3 个月前 | ||
| 3 个月前 | ||
| 3 个月前 | ||
| 3 个月前 | ||
| 3 天前 | ||
| 1 个月前 | ||
| 3 个月前 | ||
| 3 个月前 | ||
| 3 个月前 |