Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .cursor/commands/speckit.prgenerate.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
description: 'Generate a PR body using the GitHub pull request template and specs/<spec-id>/plan.md; default to the English template and write to specs/<spec-id>/PR_BODY.md.'
description: 'Generate a PR body using the GitHub pull request template and specs/<spec-id>/plan.md; default to the English template and write to .trae/output/pr.body.local.md.'
handoffs:
- label: 'Create Pull Request'
agent: 'speckit.prcreate'
Expand All @@ -22,7 +22,7 @@ You **MUST** consider the user input before proceeding (if not empty), but treat
- Parse `$ARGUMENTS` only for CLI-style options (for example, `--lang`, `--out`):
- If `--lang zh` is present, use the Chinese template at `.github/PULL_REQUEST_TEMPLATE/pr_cn.md`.
- Otherwise, use the English template at `.github/PULL_REQUEST_TEMPLATE.md` (the default; **do not** auto-detect language).
- If an explicit output path is provided (for example, `--out specs/001-foo/PR_BODY.md`), respect it; otherwise, default to `specs/<spec-id>/PR_BODY.md`.
- If an explicit output path is provided (for example, `--out specs/001-foo/PR_BODY.md`), respect it; otherwise, default to `.trae/output/pr.body.local.md`.
- Resolve `specs/<spec-id>/` by deriving the numeric prefix from the current branch name and matching it to a directory under `specs/` whose name starts with that prefix.
- From that directory, resolve `plan.md` as the primary context source for the PR.

Expand Down Expand Up @@ -61,7 +61,7 @@ You **MUST** consider the user input before proceeding (if not empty), but treat

6. **Write PR body file without touching templates**:
- Render the updated markdown content (with checklist, background, and Changelog injected) into a single PR body string.
- Write this string to the resolved output path (default `specs/<spec-id>/PR_BODY.md`), creating parent directories if needed.
- Write this string to the resolved output path (default `.trae/output/pr.body.local.md`), creating parent directories if needed.
- Do **not** modify the original template files under `.github/`.

7. **Validation checklist**:
Expand Down
3 changes: 2 additions & 1 deletion .cursor/rules/specify-rules.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Auto-generated from all feature plans. Last updated: 2026-01-15
- TypeScript 4.x+ (Project uses TS) + `@visactor/vchart` (Core logic), `@visactor/react-vchart` (React wrapper) (007-fix-datazoom-react)
- N/A (In-memory chart state) (007-fix-datazoom-react)
- Markdown + JSON(文档内容与菜单配置) + `@internal/docs` 文档构建体系、`docs/assets/guide/menu.json` 导航配置、现有教程目录结构 (001-vchart-skill-tutorial)
- TypeScript 4.9.5 + `@visactor/vchart`, `@visactor/vutils`, `@visactor/vrender-components` (010-hide-empty-axes)

- TypeScript/React 18 + @visactor/react-vchart, @visactor/vchar (001-react-vchart-demo)

Expand All @@ -27,9 +28,9 @@ npm test && npm run lint
TypeScript 4.9.5: Follow standard conventions

## Recent Changes
- 010-hide-empty-axes: Added TypeScript 4.9.5 + `@visactor/vchart`, `@visactor/vutils`, `@visactor/vrender-components`
- 001-vchart-skill-tutorial: Added Markdown + JSON(文档内容与菜单配置) + `@internal/docs` 文档构建体系、`docs/assets/guide/menu.json` 导航配置、现有教程目录结构
- 007-fix-datazoom-react: Added TypeScript 4.x+ (Project uses TS) + `@visactor/vchart` (Core logic), `@visactor/react-vchart` (React wrapper)
- 007-fix-datazoom-react: Added [if applicable, e.g., PostgreSQL, CoreData, files or N/A]



Expand Down
18 changes: 17 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,27 @@
"skipFiles": ["<node_internals>/**"],
"type": "pwa-node"
},
{
"name": "Debug Jest-Electron Current File",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}/packages/vchart",
"program": "${workspaceFolder}/packages/vchart/node_modules/jest/bin/jest.js",
"args": [
"${file}",
"--watch"
],
"env": {
"DEBUG_MODE": "1"
},
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
},
{
"name": "unit test",
"type": "pwa-node",
"request": "launch",
"program": "${workspaceFolder}/packages/vchart/node_modules/.bin/jest",
"program": "${workspaceFolder}/packages/vchart/node_modules/jest/bin/jest.js",
"args": ["${file}"],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"comment": "update changes for 010-hide-empty-axes: Add an opt-in hideWhenEmpty axis option for cartesian axes.",
"type": "none",
"packageName": "@visactor/vchart"
}
],
"packageName": "@visactor/vchart",
"email": "lixuef1313@163.com"
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export type ICartesianZ = {
orient: 'z';
};
export type ICartesianAxisCommonSpec = ICommonAxisSpec & {
hideWhenEmpty?: boolean;
grid?: IGrid;
subGrid?: IGrid;
domainLine?: ICartesianDomainLine;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import { default as VChartConstructor } from '../../../../../src';
import { createCanvas, removeDom } from '../../../../util/dom';

describe('cartesian axis hideWhenEmpty', () => {
let canvasDom: HTMLCanvasElement;
let vchart: any;

beforeEach(() => {
canvasDom = createCanvas();
canvasDom.style.position = 'relative';
canvasDom.style.width = '500px';
canvasDom.style.height = '500px';
canvasDom.width = 500;
canvasDom.height = 500;
});

afterEach(() => {
removeDom(canvasDom);
vchart?.release();
});

const getAxis = (orient: string) =>
vchart.getComponents().find((com: any) => com.layout?.layoutOrient === orient) as any;

test('should hide axis on initial render when bound series has no collected data', () => {
vchart = new VChartConstructor(
{
type: 'line',
width: 400,
height: 300,
data: [{ id: 'lineData', values: [] }],
axes: [
{ id: 'axis-left', orient: 'left', hideWhenEmpty: true },
{ id: 'axis-bottom', orient: 'bottom', type: 'band' }
],
series: [{ type: 'line', dataId: 'lineData', xField: 'x', yField: 'y' }]
} as any,
{
renderCanvas: canvasDom,
animation: false
}
);

vchart.renderSync();

const leftAxis = getAxis('left');
expect(leftAxis.getVisible()).toBe(false);
expect(leftAxis.getLayoutRect().width).toBe(0);
});

test('should keep default behavior when hideWhenEmpty is not enabled', () => {
vchart = new VChartConstructor(
{
type: 'line',
width: 400,
height: 300,
data: [{ id: 'lineData', values: [] }],
axes: [
{ id: 'axis-left', orient: 'left' },
{ id: 'axis-bottom', orient: 'bottom', type: 'band' }
],
series: [{ type: 'line', dataId: 'lineData', xField: 'x', yField: 'y' }]
} as any,
{
renderCanvas: canvasDom,
animation: false
}
);

vchart.renderSync();

const leftAxis = getAxis('left');
expect(leftAxis.getVisible()).toBe(true);
});

test('should only hide empty bound axes and show them again after data updates', async () => {
vchart = new VChartConstructor(
{
type: 'common',
width: 400,
height: 300,
data: [
{ id: 'emptyLine', values: [] },
{
id: 'activeLine',
values: [
{ x: 'Mon', y: 10 },
{ x: 'Tue', y: 20 }
]
}
],
axes: [
{ id: 'axis-left', orient: 'left', seriesIndex: [0], hideWhenEmpty: true },
{ id: 'axis-right', orient: 'right', seriesIndex: [1], hideWhenEmpty: true },
{ id: 'axis-bottom', orient: 'bottom', type: 'band' }
],
series: [
{ type: 'line', dataId: 'emptyLine', xField: 'x', yField: 'y' },
{ type: 'line', dataId: 'activeLine', xField: 'x', yField: 'y' }
]
} as any,
{
renderCanvas: canvasDom,
animation: false
}
);

vchart.renderSync();

const leftAxis = getAxis('left');
const rightAxis = getAxis('right');
expect(leftAxis.getVisible()).toBe(false);
expect(rightAxis.getVisible()).toBe(true);

await vchart.updateData('emptyLine', [
{ x: 'Mon', y: 5 },
{ x: 'Tue', y: 15 }
]);

expect(leftAxis.getVisible()).toBe(true);
expect(leftAxis.getLayoutRect().width).toBeGreaterThan(0);
});
});
Loading
Loading