diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md
index 14a0fcaa81..916dadda53 100644
--- a/.github/ISSUE_TEMPLATE/bug-report.md
+++ b/.github/ISSUE_TEMPLATE/bug-report.md
@@ -49,7 +49,7 @@ eg.
-
+
### 🔗 Reproduce Link
diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md
index bc72b546fd..518d3e947a 100644
--- a/.github/ISSUE_TEMPLATE/feature-request.md
+++ b/.github/ISSUE_TEMPLATE/feature-request.md
@@ -8,6 +8,39 @@ labels: 🙏feature request
+### 🏷 Version
+
+
+
+
+
+
+| Package | Version |
+| -------------- | ------- |
+| @antv/s2 | |
+| @antv/s2-react | |
+| @antv/s2-vue | |
+
+### Sheet Type
+
+
+
+
+- [ ] PivotSheet
+- [ ] TableSheet
+- [ ] GridAnalysisSheet
+- [ ] StrategySheet
+- [ ] EditableSheet
+
### 🖋 Description
diff --git a/.github/workflows/issue-labeled.yml b/.github/workflows/issue-labeled.yml
index 4eb12f78cc..b345097204 100644
--- a/.github/workflows/issue-labeled.yml
+++ b/.github/workflows/issue-labeled.yml
@@ -105,7 +105,7 @@ jobs:
body: |
你好 @${{ github.event.issue.user.login }},经过我们的反复讨论, 你的需求现已被采纳, 我们会排期开发, 但人力资源有限, 短期内无法支持, 请关注后续发布日志。当然, 如果能贡献 PR 帮助我们改进, 不胜感激!
- Hello, @${{ github.vent.issue.user.login }}, your feature request has been accepted after our repeated discussion. We will schedule the development. However, it could not be supported in the short term since limited time, please pay attention to the follow-up release logs. Of course, looking forward for your PR!
+ Hello, @${{ github.event.issue.user.login }}, your feature request has been accepted after our repeated discussion. We will schedule the development. However, it could not be supported in the short term since limited time, please pay attention to the follow-up release logs. Of course, looking forward for your PR!
- name: Rejected
if: github.event.label.name == '❌ won''t support'
diff --git a/.github/workflows/issue-opend.yml b/.github/workflows/issue-opend.yml
index 1cfb08c64c..ec973f8af4 100644
--- a/.github/workflows/issue-opend.yml
+++ b/.github/workflows/issue-opend.yml
@@ -20,9 +20,9 @@ jobs:
Hello, @${{ github.event.issue.user.login }}, please edit your issue title. a concise issue title will save everyone time. please do not leave the title as the body or empty.
- # 如果是 bug 的 issue, 但是基本的版本号,表格类型, 描述都没有, 直接关闭, 不多BB.
- - name: check bug report issue body
- if: contains(github.event.issue.title, '🐛') == true && contains(github.event.issue.body, 'Version') == false && contains(github.event.issue.body, 'Sheet Type') == false && contains(github.event.issue.body, 'Description') == false
+ # 如果 issue 的提交者无视模版, 连基本的版本号,表格类型, 描述都没有, 直接自动关闭, 不多BB.
+ - name: check issue body
+ if: contains(github.event.issue.body, 'Version') == false && contains(github.event.issue.body, 'Sheet Type') == false && contains(github.event.issue.body, 'Description') == false
uses: actions-cool/issues-helper@main
with:
actions: 'create-comment,add-labels,close-issue'
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index bd6657e86c..730543c82d 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -38,7 +38,7 @@
2. 安装依赖:`yarn bootstrap` 或者 `yarn`
3. 提交你的改动,commit 请遵守 [AngularJS Git Commit Message Conventions](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#heading=h.uyo6cb12dt6w)
4. 如果你的改动是修复 bug, 还可以在提交信息后面加上 `close #issue 号`, 这样可以在 pr 合并后,可以自动关闭对应的 issue, 比如 `fix: render bug close #123`
-5. 确保加上了对应的单元测试和文档 (如有必要)
+5. 确保加上了对应的单元测试和文档 (如果有 `Snapshot` UI 快照 (.snap 文件)更新, 可以运行 `yarn core:test -- -u` 和 `yarn react:test -- -u` 自动更新, 并一起提交上来, 请勿手动编辑)
6. 所有 Lint 和 Test 检查通过后,并且 review 通过,我们会合并你的 pr.
![preview](https://gw.alipayobjects.com/zos/antfincdn/ssOxFrycD/86339514-5f9a-4101-8690-e47c97cd8af5.png)
diff --git a/README.en-US.md b/README.en-US.md
index 166fd4efca..9f4e2fdd37 100644
--- a/README.en-US.md
+++ b/README.en-US.md
@@ -68,8 +68,9 @@ demo components and expansion capabilities, it allows developers to use it quick
## 📦 Installation
```bash
-$ npm install @antv/s2
-# yarn add @antv/s2
+$ npm install @antv/s2 --save
+# yarn add @antv/s2 --save
+# pnpm install @antv/s2 --save
```
## 🔨 Getting Started
@@ -227,9 +228,6 @@ yarn site:start
-
-
-
## 👬 Contributors
diff --git a/README.md b/README.md
index d636c4b73d..341116452c 100644
--- a/README.md
+++ b/README.md
@@ -64,8 +64,9 @@ S2 是 AntV 在多维交叉分析表格领域的解决方案,完全基于数
## 📦 安装
```bash
-$ npm install @antv/s2
-# yarn add @antv/s2
+$ npm install @antv/s2 --save
+# yarn add @antv/s2 --save
+# pnpm install @antv/s2 --save
```
## 🔨 使用
@@ -73,7 +74,7 @@ $ npm install @antv/s2
### 1. 数据准备
- s2DataConfig
+ s2DataConfig
```ts
const s2DataConfig = {
@@ -221,9 +222,6 @@ yarn site:start
-
-
-
## 👬 Contributors
diff --git a/packages/s2-core/CHANGELOG.md b/packages/s2-core/CHANGELOG.md
index 8e9027b7d8..a2a3ec4035 100644
--- a/packages/s2-core/CHANGELOG.md
+++ b/packages/s2-core/CHANGELOG.md
@@ -1,3 +1,13 @@
+# [@antv/s2-v1.51.2](https://github.com/antvis/S2/compare/@antv/s2-v1.51.1...@antv/s2-v1.51.2) (2023-10-27)
+
+
+### Bug Fixes
+
+* **interaction:** 修复拖动水平滚动条后单元格选中状态被重置 close [#2376](https://github.com/antvis/S2/issues/2376) ([#2380](https://github.com/antvis/S2/issues/2380)) ([b2e9700](https://github.com/antvis/S2/commit/b2e97008122f5320342fd069a08f6e821a5c9ad6))
+* **layout:** 修复在紧凑模式列头宽度未按文本自适应 close [#2385](https://github.com/antvis/S2/issues/2385) ([#2392](https://github.com/antvis/S2/issues/2392)) ([2edd99c](https://github.com/antvis/S2/commit/2edd99c367116bad661a02893a303311787eb647))
+* 修复分组汇总时,按汇总排序获取排序数据为空 ([#2370](https://github.com/antvis/S2/issues/2370)) ([2443762](https://github.com/antvis/S2/commit/24437622e1b259288bf7f8f3505837088a6e1b9d))
+* 修复树状角头,当有存在icon时,内容与box宽度恰好相等,出现换行 close [#2389](https://github.com/antvis/S2/issues/2389) ([#2390](https://github.com/antvis/S2/issues/2390)) ([19497b3](https://github.com/antvis/S2/commit/19497b34aaa9bd19ca5f410926f3035f1aa76d09))
+
# [@antv/s2-v1.51.1](https://github.com/antvis/S2/compare/@antv/s2-v1.51.0...@antv/s2-v1.51.1) (2023-10-13)
diff --git a/packages/s2-core/__tests__/bugs/issue-2385-spec.ts b/packages/s2-core/__tests__/bugs/issue-2385-spec.ts
new file mode 100644
index 0000000000..4e3e56430a
--- /dev/null
+++ b/packages/s2-core/__tests__/bugs/issue-2385-spec.ts
@@ -0,0 +1,57 @@
+/**
+ * @description spec for issue #2385
+ * https://github.com/antvis/S2/issues/2385
+ */
+import { createPivotSheet, getContainer } from '../util/helpers';
+import * as mockDataConfig from '../data/data-issue-2385.json';
+import type { S2Options } from '../../src';
+import { PivotSheet, TableSheet } from '@/sheet-type';
+
+const s2Options: S2Options = {
+ width: 800,
+ height: 600,
+ style: {
+ cellCfg: {
+ width: 200,
+ },
+ layoutWidthType: 'compact',
+ },
+};
+
+describe('Compare Layout Tests', () => {
+ test('should get max col width for pivot sheet', () => {
+ const s2 = new PivotSheet(getContainer(), mockDataConfig, s2Options);
+ s2.setTheme({
+ dataCell: {
+ text: {
+ fontSize: 20,
+ },
+ },
+ });
+ s2.render();
+
+ const colLeafNodes = s2.facet.layoutResult.colLeafNodes;
+ expect(Math.floor(colLeafNodes[0].width)).toBeCloseTo(179);
+ expect(Math.floor(colLeafNodes[1].width)).toEqual(98);
+ });
+
+ test('should get max col width for table sheet', () => {
+ const s2 = new TableSheet(getContainer(), mockDataConfig, s2Options);
+ s2.setDataCfg({
+ fields: {
+ columns: ['price'],
+ },
+ });
+ s2.setTheme({
+ dataCell: {
+ text: {
+ fontSize: 20,
+ },
+ },
+ });
+ s2.render();
+
+ const colLeafNodes = s2.facet.layoutResult.colLeafNodes;
+ expect(Math.floor(colLeafNodes[0].width)).toBeCloseTo(165);
+ });
+});
diff --git a/packages/s2-core/__tests__/data/data-issue-2385.json b/packages/s2-core/__tests__/data/data-issue-2385.json
new file mode 100644
index 0000000000..c8ad719d5c
--- /dev/null
+++ b/packages/s2-core/__tests__/data/data-issue-2385.json
@@ -0,0 +1,272 @@
+{
+ "data": [
+ {
+ "province": "浙江",
+ "city": "杭州",
+ "type": "笔",
+ "price": "11111111"
+ },
+ {
+ "province": "浙江",
+ "city": "杭州",
+ "type": "纸张",
+ "price": "2"
+ },
+ {
+ "province": "浙江",
+ "city": "舟山",
+ "type": "笔",
+ "price": "2"
+ },
+ {
+ "province": "浙江",
+ "city": "舟山",
+ "type": "纸张",
+ "price": "133.333"
+ },
+ {
+ "province": "吉林",
+ "city": "长春",
+ "type": "笔",
+ "price": "3"
+ },
+ {
+ "province": "吉林",
+ "city": "长春",
+ "type": "纸张",
+ "price": "2"
+ },
+ {
+ "province": "吉林",
+ "city": "白山",
+ "type": "笔",
+ "price": "4"
+ },
+ {
+ "province": "吉林",
+ "city": "白山",
+ "type": "纸张",
+ "price": "1"
+ },
+ {
+ "province": "浙江",
+ "city": "杭州",
+ "type": "笔",
+ "price": "11111111111111111"
+ },
+ {
+ "province": "浙江",
+ "city": "杭州",
+ "type": "纸张",
+ "price": "2"
+ },
+ {
+ "province": "浙江",
+ "city": "舟山",
+ "type": "笔",
+ "price": "2"
+ },
+ {
+ "province": "浙江",
+ "city": "舟山",
+ "type": "纸张",
+ "price": "666.333"
+ },
+ {
+ "province": "吉林",
+ "city": "长春",
+ "type": "笔",
+ "price": "3"
+ },
+ {
+ "province": "吉林",
+ "city": "长春",
+ "type": "纸张",
+ "price": "2"
+ },
+ {
+ "province": "吉林",
+ "city": "白山",
+ "type": "笔",
+ "price": "4"
+ },
+ {
+ "province": "吉林",
+ "city": "白山",
+ "type": "纸张",
+ "price": "1"
+ },
+ {
+ "province": "浙江",
+ "city": "杭州",
+ "type": "笔",
+ "cost": "33.333"
+ },
+ {
+ "province": "浙江",
+ "city": "杭州",
+ "type": "纸张",
+ "cost": "1.5"
+ },
+ {
+ "province": "浙江",
+ "city": "舟山",
+ "type": "笔",
+ "cost": "1.5"
+ },
+ {
+ "province": "浙江",
+ "city": "舟山",
+ "type": "纸张",
+ "cost": "0.2"
+ },
+ {
+ "province": "吉林",
+ "city": "长春",
+ "type": "笔",
+ "cost": "2"
+ },
+ {
+ "province": "吉林",
+ "city": "长春",
+ "type": "纸张",
+ "cost": "1"
+ },
+ {
+ "province": "吉林",
+ "city": "白山",
+ "type": "笔",
+ "cost": "3"
+ },
+ {
+ "province": "吉林",
+ "city": "白山",
+ "type": "纸张",
+ "cost": "33.333"
+ },
+ {
+ "price": "15.5"
+ },
+ {
+ "province": "浙江",
+ "price": "5.5"
+ },
+ {
+ "province": "浙江",
+ "city": "杭州",
+ "price": "3"
+ },
+ {
+ "province": "浙江",
+ "city": "舟山",
+ "price": "2.5"
+ },
+ {
+ "province": "吉林",
+ "price": "10"
+ },
+ {
+ "province": "吉林",
+ "city": "长春",
+ "price": "5"
+ },
+ {
+ "province": "吉林",
+ "city": "白山",
+ "price": "5"
+ },
+ {
+ "type": "笔",
+ "price": "10"
+ },
+ {
+ "type": "笔",
+ "province": "浙江",
+ "price": "3"
+ },
+ {
+ "type": "笔",
+ "province": "吉林",
+ "price": "7"
+ },
+ {
+ "type": "纸张",
+ "price": "5.5"
+ },
+ {
+ "type": "纸张",
+ "province": "浙江",
+ "price": "2.5"
+ },
+ {
+ "type": "纸张",
+ "province": "吉林",
+ "price": "3"
+ },
+ {
+ "cost": "10.2"
+ },
+ {
+ "province": "浙江",
+ "cost": "3.7"
+ },
+ {
+ "province": "浙江",
+ "city": "杭州",
+ "cost": "2"
+ },
+ {
+ "province": "浙江",
+ "city": "舟山",
+ "cost": "1.7"
+ },
+ {
+ "province": "吉林",
+ "cost": "6.5"
+ },
+ {
+ "province": "吉林",
+ "city": "长春",
+ "cost": "3"
+ },
+ {
+ "province": "吉林",
+ "city": "白山",
+ "cost": "3.5"
+ },
+ {
+ "type": "笔",
+ "cost": "7"
+ },
+ {
+ "type": "笔",
+ "province": "浙江",
+ "cost": "2"
+ },
+ {
+ "type": "笔",
+ "province": "吉林",
+ "cost": "5"
+ },
+ {
+ "type": "纸张",
+ "cost": "3.2"
+ },
+ {
+ "type": "纸张",
+ "province": "浙江",
+ "cost": "1.7"
+ },
+ {
+ "type": "纸张",
+ "province": "吉林",
+ "cost": "1.5"
+ }
+ ],
+ "fields": {
+ "rows": ["province", "city"],
+ "columns": ["type"],
+ "values": ["price"],
+ "valueInCols": true
+ }
+}
diff --git a/packages/s2-core/__tests__/spreadsheet/__snapshots__/corner-spec.ts.snap b/packages/s2-core/__tests__/spreadsheet/__snapshots__/corner-spec.ts.snap
index b3dc716fbd..f3430d0399 100644
--- a/packages/s2-core/__tests__/spreadsheet/__snapshots__/corner-spec.ts.snap
+++ b/packages/s2-core/__tests__/spreadsheet/__snapshots__/corner-spec.ts.snap
@@ -188,7 +188,7 @@ Array [
"rowIndex": undefined,
"seriesNumberWidth": 0,
"value": "province/city/数值",
- "width": 150,
+ "width": 151,
"x": 0,
"y": 0,
},
@@ -253,7 +253,7 @@ Array [
"rowIndex": undefined,
"seriesNumberWidth": 80,
"value": "province/city/数值",
- "width": 150,
+ "width": 151,
"x": 80,
"y": 0,
},
@@ -448,7 +448,7 @@ Array [
"rowIndex": undefined,
"seriesNumberWidth": 0,
"value": "province/city",
- "width": 122,
+ "width": 123,
"x": 0,
"y": 0,
},
@@ -513,7 +513,7 @@ Array [
"rowIndex": undefined,
"seriesNumberWidth": 80,
"value": "province/city",
- "width": 122,
+ "width": 123,
"x": 80,
"y": 0,
},
@@ -708,7 +708,7 @@ Array [
"rowIndex": undefined,
"seriesNumberWidth": 0,
"value": "province/city",
- "width": 122,
+ "width": 123,
"x": 0,
"y": 0,
},
@@ -773,7 +773,7 @@ Array [
"rowIndex": undefined,
"seriesNumberWidth": 80,
"value": "province/city",
- "width": 122,
+ "width": 123,
"x": 80,
"y": 0,
},
diff --git a/packages/s2-core/__tests__/spreadsheet/__snapshots__/theme-spec.ts.snap b/packages/s2-core/__tests__/spreadsheet/__snapshots__/theme-spec.ts.snap
index f9b83c35d8..50d2c40be0 100644
--- a/packages/s2-core/__tests__/spreadsheet/__snapshots__/theme-spec.ts.snap
+++ b/packages/s2-core/__tests__/spreadsheet/__snapshots__/theme-spec.ts.snap
@@ -19,6 +19,7 @@ Object {
"cell": Object {
"backgroundColor": "#E0E9FD",
"backgroundColorOpacity": 1,
+ "borderDash": Array [],
"horizontalBorderColor": "#CCDBFC",
"horizontalBorderColorOpacity": 1,
"horizontalBorderWidth": 1,
@@ -102,6 +103,7 @@ Object {
"cell": Object {
"backgroundColor": "#E0E9FD",
"backgroundColorOpacity": 1,
+ "borderDash": Array [],
"horizontalBorderColor": "#CCDBFC",
"horizontalBorderColorOpacity": 1,
"horizontalBorderWidth": 1,
@@ -147,6 +149,7 @@ Object {
"cell": Object {
"backgroundColor": "#FFFFFF",
"backgroundColorOpacity": 1,
+ "borderDash": Array [],
"crossBackgroundColor": "#F5F8FE",
"horizontalBorderColor": "#E0E9FD",
"horizontalBorderColorOpacity": 1,
@@ -273,6 +276,7 @@ Object {
"cell": Object {
"backgroundColor": "#FFFFFF",
"backgroundColorOpacity": 1,
+ "borderDash": Array [],
"crossBackgroundColor": "#F5F8FE",
"horizontalBorderColor": "#E0E9FD",
"horizontalBorderColorOpacity": 1,
@@ -420,6 +424,7 @@ Object {
"cell": Object {
"backgroundColor": "#F5F8FE",
"backgroundColorOpacity": 1,
+ "borderDash": Array [],
"horizontalBorderColor": "#E0E9FD",
"horizontalBorderColorOpacity": 1,
"horizontalBorderWidth": 1,
@@ -512,6 +517,7 @@ Object {
"trackColor": "rgba(0,0,0,0.01)",
},
"splitLine": Object {
+ "borderDash": Array [],
"horizontalBorderColor": "#326EF4",
"horizontalBorderColorOpacity": 0.2,
"horizontalBorderWidth": 2,
diff --git a/packages/s2-core/__tests__/spreadsheet/scroll-spec.ts b/packages/s2-core/__tests__/spreadsheet/scroll-spec.ts
index bf4fad922e..b634849f5a 100644
--- a/packages/s2-core/__tests__/spreadsheet/scroll-spec.ts
+++ b/packages/s2-core/__tests__/spreadsheet/scroll-spec.ts
@@ -1,7 +1,7 @@
/* eslint-disable jest/no-conditional-expect */
import * as mockDataConfig from 'tests/data/simple-data.json';
import { createMockCellInfo, getContainer, sleep } from 'tests/util/helpers';
-import { ScrollType } from '../../src/ui/scrollbar';
+import { ScrollBar, ScrollType } from '../../src/ui/scrollbar';
import type { CellScrollPosition } from './../../src/common/interface/scroll';
import { PivotSheet, SpreadSheet } from '@/sheet-type';
import type {
@@ -880,4 +880,52 @@ describe('Scroll Tests', () => {
expect(errorSpy).toBeCalledTimes(1);
});
+
+ // https://github.com/antvis/S2/issues/2376
+ test.each(['hScrollBar', 'hRowScrollBar'])(
+ 'should not reset interaction state after %s scrollbar thumb or track clicked',
+ (scrollbarName) => {
+ const containsMock = jest
+ .spyOn(HTMLElement.prototype, 'contains')
+ .mockImplementation(() => true);
+
+ const reset = jest.fn();
+
+ const scrollbar = s2.facet[scrollbarName] as ScrollBar;
+ const colCell = s2.getColumnLeafNodes()[0].belongsCell;
+
+ s2.on(S2Event.GLOBAL_RESET, reset);
+ s2.interaction.selectHeaderCell({
+ cell: colCell,
+ });
+
+ expect(s2.interaction.isSelectedState()).toBeTruthy();
+
+ const { maxX, maxY } = s2.facet?.panelBBox || {};
+ const { x, y } = canvas.getBoundingClientRect() || {};
+
+ // 滚动条
+ window.dispatchEvent(
+ new MouseEvent('click', {
+ clientX: x + scrollbar.position.x,
+ // 在滚动条内点击
+ clientY: y + scrollbar.position.y + scrollbar.theme.size - 2,
+ } as MouseEventInit),
+ );
+
+ // 滑动轨道
+ window.dispatchEvent(
+ new MouseEvent('click', {
+ // 右下角滑道点击
+ clientX: x + maxX - 2,
+ clientY: y + maxY + 2,
+ } as MouseEventInit),
+ );
+
+ expect(s2.interaction.isSelectedState()).toBeTruthy();
+ expect(reset).not.toHaveBeenCalled();
+
+ containsMock.mockReset();
+ },
+ );
});
diff --git a/packages/s2-core/__tests__/spreadsheet/spread-sheet-tree-mode-spec.ts b/packages/s2-core/__tests__/spreadsheet/spread-sheet-tree-mode-spec.ts
index 510c28565a..d7761e11b5 100644
--- a/packages/s2-core/__tests__/spreadsheet/spread-sheet-tree-mode-spec.ts
+++ b/packages/s2-core/__tests__/spreadsheet/spread-sheet-tree-mode-spec.ts
@@ -26,7 +26,7 @@ describe('SpreadSheet Tree Mode Tests', () => {
s2.render();
const rowsHierarchyWidth = s2.facet.layoutResult.rowsHierarchy.width;
- expect(Math.round(rowsHierarchyWidth)).toEqual(123);
+ expect(Math.round(rowsHierarchyWidth)).toEqual(124);
// 行头维度均更改为较长的 name
const newDataCfg: S2DataConfig = {
@@ -49,5 +49,39 @@ describe('SpreadSheet Tree Mode Tests', () => {
rowsHierarchyWidth,
);
});
+
+ // https://github.com/antvis/S2/issues/2389
+ test('the corner should only have one line with action icon', () => {
+ // 行头维度更改为较长的 name
+ const newDataCfg: S2DataConfig = {
+ ...mockDataConfig,
+ meta: [
+ {
+ field: 'province',
+ name: '省1234567890份',
+ },
+ {
+ field: 'city',
+ name: '城1234567890市',
+ },
+ ],
+ };
+ // 添加icon
+ const newS2Options: S2Options = {
+ ...s2Options,
+ headerActionIcons: [
+ {
+ iconNames: ['SortDownSelected'],
+ belongsCell: 'cornerCell',
+ },
+ ],
+ };
+ const s2 = new PivotSheet(container, newDataCfg, newS2Options);
+ s2.render();
+
+ // 检查文本是否只有一行
+ const textLen = s2.facet.cornerHeader.cfg.children[0].textShapes.length;
+ expect(textLen).toEqual(1);
+ });
});
});
diff --git a/packages/s2-core/__tests__/unit/facet/layout/col-node-width-spec.ts b/packages/s2-core/__tests__/unit/facet/layout/col-node-width-spec.ts
index 49217dcd9f..f31e370a9b 100644
--- a/packages/s2-core/__tests__/unit/facet/layout/col-node-width-spec.ts
+++ b/packages/s2-core/__tests__/unit/facet/layout/col-node-width-spec.ts
@@ -53,7 +53,7 @@ describe('Col width Test', () => {
});
s2.render();
const { colLeafNodes } = s2.facet.layoutResult;
- expect(Math.round(colLeafNodes[0].width)).toBe(339);
+ expect(Math.round(colLeafNodes[0].width)).toBe(338);
});
test('get correct width in layoutWidthType adaptive tree mode when enable seriesnumber', () => {
@@ -63,7 +63,7 @@ describe('Col width Test', () => {
});
s2.render();
const { colLeafNodes } = s2.facet.layoutResult;
- expect(Math.round(colLeafNodes[0].width)).toBe(299);
+ expect(Math.round(colLeafNodes[0].width)).toBe(298);
});
test('get correct width in layoutWidthType compact mode', () => {
diff --git a/packages/s2-core/package.json b/packages/s2-core/package.json
index cbc465052a..3e28ed259f 100644
--- a/packages/s2-core/package.json
+++ b/packages/s2-core/package.json
@@ -1,7 +1,7 @@
{
"private": false,
"name": "@antv/s2",
- "version": "1.51.1",
+ "version": "1.51.2",
"main": "lib/index.js",
"unpkg": "dist/index.min.js",
"module": "esm/index.js",
diff --git a/packages/s2-core/src/cell/col-cell.ts b/packages/s2-core/src/cell/col-cell.ts
index bf73bd4095..fcab2334e3 100644
--- a/packages/s2-core/src/cell/col-cell.ts
+++ b/packages/s2-core/src/cell/col-cell.ts
@@ -460,6 +460,7 @@ export class ColCell extends HeaderCell {
horizontalBorderColor,
horizontalBorderWidth,
horizontalBorderColorOpacity,
+ borderDash,
} = this.theme.splitLine;
const lineX = this.isLastColumn() ? x + width - horizontalBorderWidth : x;
@@ -475,6 +476,7 @@ export class ColCell extends HeaderCell {
stroke: horizontalBorderColor,
lineWidth: horizontalBorderWidth,
strokeOpacity: horizontalBorderColorOpacity,
+ lineDash: borderDash,
},
);
}
diff --git a/packages/s2-core/src/common/interface/theme.ts b/packages/s2-core/src/common/interface/theme.ts
index acf8a63a0a..1eb86691f3 100644
--- a/packages/s2-core/src/common/interface/theme.ts
+++ b/packages/s2-core/src/common/interface/theme.ts
@@ -97,7 +97,9 @@ export interface TextAlignCfg {
textBaseline?: TextBaseline;
}
-export interface TextTheme extends TextAlignCfg {
+export interface TextTheme
+ extends TextAlignCfg,
+ Pick {
/* 字体 */
fontFamily?: string;
/* 字体大小 */
@@ -139,6 +141,8 @@ export interface CellTheme {
miniBarChartHeight?: number;
/* @deprecated 已废弃, 请用 miniChartTheme.interval.fill 代替 */
miniBarChartFillColor?: string;
+ /** 单元格边线虚线 */
+ borderDash?: number[];
}
export interface IconTheme {
@@ -214,6 +218,8 @@ export interface SplitLine {
/* 线性变化右侧颜色 */
right: string;
};
+ /** 分割线虚线 */
+ borderDash?: number[];
}
export interface DefaultCellTheme extends GridAnalysisCellTheme {
/* 粗体文本样式 */
diff --git a/packages/s2-core/src/facet/header/frame.ts b/packages/s2-core/src/facet/header/frame.ts
index 364cc9d88a..0c18d38b47 100644
--- a/packages/s2-core/src/facet/header/frame.ts
+++ b/packages/s2-core/src/facet/header/frame.ts
@@ -65,6 +65,7 @@ export class Frame extends Group {
stroke: splitLine.verticalBorderColor,
lineWidth: splitLine.verticalBorderWidth,
opacity: splitLine.verticalBorderColorOpacity,
+ lineDash: splitLine.borderDash,
},
});
}
@@ -94,6 +95,7 @@ export class Frame extends Group {
stroke: splitLine.horizontalBorderColor,
lineWidth: splitLine.horizontalBorderWidth,
opacity: splitLine.horizontalBorderColorOpacity,
+ lineDash: splitLine.borderDash,
},
});
}
diff --git a/packages/s2-core/src/facet/pivot-facet.ts b/packages/s2-core/src/facet/pivot-facet.ts
index 7b2e93b112..1acf386d12 100644
--- a/packages/s2-core/src/facet/pivot-facet.ts
+++ b/packages/s2-core/src/facet/pivot-facet.ts
@@ -285,6 +285,7 @@ export class PivotFacet extends BaseFacet {
cell: colCellStyle,
icon: colIconStyle,
} = this.spreadsheet.theme.colCell;
+ const { text: dataCellTextStyle } = this.spreadsheet.theme.dataCell;
// leaf node rough width
const cellFormatter = this.spreadsheet.dataSet.getFieldFormatter(
@@ -298,7 +299,10 @@ export class PivotFacet extends BaseFacet {
colIconStyle,
);
const leafNodeRoughWidth =
- this.spreadsheet.measureTextWidthRoughly(leafNodeLabel) + iconWidth;
+ this.spreadsheet.measureTextWidthRoughly(
+ leafNodeLabel,
+ colCellTextStyle,
+ ) + iconWidth;
// 采样 50 个 label,逐个计算找出最长的 label
let maxDataLabel: string;
@@ -325,8 +329,10 @@ export class PivotFacet extends BaseFacet {
cellData[EXTRA_FIELD],
)?.(valueData) ?? valueData;
const cellLabel = `${formattedValue}`;
- const cellLabelWidth =
- this.spreadsheet.measureTextWidthRoughly(cellLabel);
+ const cellLabelWidth = this.spreadsheet.measureTextWidthRoughly(
+ cellLabel,
+ dataCellTextStyle,
+ );
if (cellLabelWidth > maxDataLabelWidth) {
maxDataLabel = cellLabel;
@@ -336,7 +342,6 @@ export class PivotFacet extends BaseFacet {
}
}
- // compare result
const isLeafNodeWidthLonger = leafNodeRoughWidth > maxDataLabelWidth;
const maxLabel = isLeafNodeWidthLonger ? leafNodeLabel : maxDataLabel;
const appendedWidth = isLeafNodeWidthLonger ? iconWidth : 0;
@@ -345,10 +350,20 @@ export class PivotFacet extends BaseFacet {
'Max Label In Col:',
col.field,
maxLabel,
+ maxDataLabelWidth,
);
+ // 取列头/数值字体最大的文本宽度 https://github.com/antvis/S2/issues/2385
+ const maxTextWidth = this.spreadsheet.measureTextWidth(maxLabel, {
+ ...colCellTextStyle,
+ fontSize: Math.max(
+ dataCellTextStyle.fontSize,
+ colCellTextStyle.fontSize,
+ ),
+ });
+
return (
- this.spreadsheet.measureTextWidth(maxLabel, colCellTextStyle) +
+ maxTextWidth +
colCellStyle.padding?.left +
colCellStyle.padding?.right +
appendedWidth
@@ -736,8 +751,11 @@ export class PivotFacet extends BaseFacet {
.join('/');
const { bolderText: cornerCellTextStyle, icon: cornerIconStyle } =
this.spreadsheet.theme.cornerCell;
- // 初始化角头时,保证其在树形模式下不换行,给与两个icon的宽度空余(tree icon 和 action icon),减少复杂的 action icon 判断
+ // 初始化角头时,保证其在树形模式下不换行
+ // 给与两个icon的宽度空余(tree icon 和 action icon),减少复杂的 action icon 判断
+ // 额外增加 1,当内容和容器宽度恰好相等时会出现换行
const maxLabelWidth =
+ 1 +
this.spreadsheet.measureTextWidth(treeHeaderLabel, cornerCellTextStyle) +
cornerIconStyle.size * 2 +
cornerIconStyle.margin?.left +
diff --git a/packages/s2-core/src/facet/table-facet.ts b/packages/s2-core/src/facet/table-facet.ts
index e1608eb241..23ab9e67e2 100644
--- a/packages/s2-core/src/facet/table-facet.ts
+++ b/packages/s2-core/src/facet/table-facet.ts
@@ -667,12 +667,14 @@ export class TableFacet extends BaseFacet {
lineWidth: style?.verticalBorderWidth,
stroke: style?.verticalBorderColor,
opacity: style?.verticalBorderColorOpacity,
+ lineDash: style?.borderDash,
};
const horizontalBorderStyle = {
lineWidth: style?.horizontalBorderWidth,
stroke: style?.horizontalBorderColor,
opacity: style?.horizontalBorderColorOpacity,
+ lineDash: style?.borderDash,
};
if (frozenColCount > 0) {
diff --git a/packages/s2-core/src/group/grid-group.ts b/packages/s2-core/src/group/grid-group.ts
index 4f92f9b085..f0a6b28c41 100644
--- a/packages/s2-core/src/group/grid-group.ts
+++ b/packages/s2-core/src/group/grid-group.ts
@@ -70,6 +70,7 @@ export class GridGroup extends Group {
strokeOpacity: style.verticalBorderColorOpacity,
lineWidth: verticalBorderWidth,
lineCap: SQUARE_LINE_CAP,
+ lineDash: style.borderDash,
},
);
});
@@ -90,6 +91,7 @@ export class GridGroup extends Group {
strokeOpacity: style.horizontalBorderColorOpacity,
lineWidth: horizontalBorderWidth,
lineCap: SQUARE_LINE_CAP,
+ lineDash: style.borderDash,
},
);
});
diff --git a/packages/s2-core/src/interaction/event-controller.ts b/packages/s2-core/src/interaction/event-controller.ts
index f9d54c4851..a1258710b1 100644
--- a/packages/s2-core/src/interaction/event-controller.ts
+++ b/packages/s2-core/src/interaction/event-controller.ts
@@ -207,21 +207,32 @@ export class EventController {
// 比如实际 400 * 300 => hd (800 * 600)
// 从视觉来看, 虽然点击了空白处, 但其实还是处于 放大后的 canvas 区域, 所以还需要额外判断一下坐标
const { width, height } = this.getContainerRect();
+
return (
canvas.contains(event.target as HTMLElement) &&
event.clientX <= x + width &&
event.clientY <= y + height
);
}
+
return false;
}
private getContainerRect() {
- const { maxX, maxY } = this.spreadsheet.facet?.panelBBox || {};
- const { width, height } = this.spreadsheet.options;
+ const { facet, options } = this.spreadsheet;
+ const scrollBar = facet.hRowScrollBar || facet.hScrollBar;
+ const { maxX, maxY } = facet?.panelBBox || {};
+ const { width, height } = options;
+
+ /**
+ * https://github.com/antvis/S2/issues/2376
+ * 横向的滚动条在表格外 (Canvas 内), 点击滚动条(含滑道区域) 不应该重置交互
+ */
+ const trackHeight = scrollBar?.theme?.size || 0;
+
return {
width: Math.min(width, maxX),
- height: Math.min(height, maxY),
+ height: Math.min(height, maxY + trackHeight),
};
}
diff --git a/packages/s2-core/src/theme/index.ts b/packages/s2-core/src/theme/index.ts
index 9bc4c7074b..21ac42bc90 100644
--- a/packages/s2-core/src/theme/index.ts
+++ b/packages/s2-core/src/theme/index.ts
@@ -55,6 +55,8 @@ export const getTheme = (
// ----------- border width --------------
horizontalBorderWidth: 1,
verticalBorderWidth: 1,
+ // -------------- border dash -----------------
+ borderDash: [],
// -------------- layout -----------------
padding: {
top: 8,
@@ -198,6 +200,8 @@ export const getTheme = (
// ----------- border width --------------
horizontalBorderWidth: 1,
verticalBorderWidth: 1,
+ // -------------- border dash -----------------
+ borderDash: [],
// -------------- layout -----------------
padding: {
top: 0,
@@ -268,6 +272,8 @@ export const getTheme = (
// ----------- bottom border width --------------
horizontalBorderWidth: 1,
verticalBorderWidth: 1,
+ // -------------- border dash -----------------
+ borderDash: [],
// -------------- layout -----------------
padding: {
top: 0,
@@ -362,6 +368,8 @@ export const getTheme = (
// ----------- border width --------------
horizontalBorderWidth: 1,
verticalBorderWidth: 1,
+ // -------------- border dash -----------------
+ borderDash: [],
// -------------- layout -----------------
padding: {
top: 0,
@@ -461,6 +469,7 @@ export const getTheme = (
left: 'rgba(0,0,0,0.1)',
right: 'rgba(0,0,0,0)',
},
+ borderDash: [],
},
// ------------- prepareSelectMask -----------------
prepareSelectMask: {
diff --git a/packages/s2-core/src/utils/cell/cell.ts b/packages/s2-core/src/utils/cell/cell.ts
index f49b25d3eb..42db386cca 100644
--- a/packages/s2-core/src/utils/cell/cell.ts
+++ b/packages/s2-core/src/utils/cell/cell.ts
@@ -266,6 +266,7 @@ export const getBorderPositionAndStyle = (
verticalBorderWidth,
verticalBorderColor,
verticalBorderColorOpacity,
+ borderDash,
} = style;
let x1;
let y1;
@@ -293,6 +294,7 @@ export const getBorderPositionAndStyle = (
lineWidth: horizontalBorderWidth,
stroke: horizontalBorderColor,
strokeOpacity: horizontalBorderColorOpacity,
+ lineDash: borderDash,
};
}
@@ -315,6 +317,7 @@ export const getBorderPositionAndStyle = (
lineWidth: verticalBorderWidth,
stroke: verticalBorderColor,
strokeOpacity: verticalBorderColorOpacity,
+ lineDash: borderDash,
};
}
diff --git a/packages/s2-react/CHANGELOG.md b/packages/s2-react/CHANGELOG.md
index b739337a0d..f860c52446 100644
--- a/packages/s2-react/CHANGELOG.md
+++ b/packages/s2-react/CHANGELOG.md
@@ -1,3 +1,11 @@
+# [@antv/s2-react-v1.44.1](https://github.com/antvis/S2/compare/@antv/s2-react-v1.44.0...@antv/s2-react-v1.44.1) (2023-10-27)
+
+
+### Bug Fixes
+
+* **interaction:** 修复拖动水平滚动条后单元格选中状态被重置 close [#2376](https://github.com/antvis/S2/issues/2376) ([#2380](https://github.com/antvis/S2/issues/2380)) ([b2e9700](https://github.com/antvis/S2/commit/b2e97008122f5320342fd069a08f6e821a5c9ad6))
+* **layout:** 修复在紧凑模式列头宽度未按文本自适应 close [#2385](https://github.com/antvis/S2/issues/2385) ([#2392](https://github.com/antvis/S2/issues/2392)) ([2edd99c](https://github.com/antvis/S2/commit/2edd99c367116bad661a02893a303311787eb647))
+
# [@antv/s2-react-v1.44.0](https://github.com/antvis/S2/compare/@antv/s2-react-v1.43.0...@antv/s2-react-v1.44.0) (2023-09-22)
diff --git a/packages/s2-react/__tests__/data/mock-dataset.json b/packages/s2-react/__tests__/data/mock-dataset.json
index d42360ebc8..c807f0b973 100644
--- a/packages/s2-react/__tests__/data/mock-dataset.json
+++ b/packages/s2-react/__tests__/data/mock-dataset.json
@@ -80,7 +80,7 @@
"sub_type": "沙发"
},
{
- "number": 632,
+ "number": 632632632,
"province": "浙江省",
"city": "绍兴市",
"type": "家具",
diff --git a/packages/s2-react/__tests__/unit/components/sheets/strategy-sheet/index-spec.tsx b/packages/s2-react/__tests__/unit/components/sheets/strategy-sheet/index-spec.tsx
index 46facbf366..66cbf1a2ef 100644
--- a/packages/s2-react/__tests__/unit/components/sheets/strategy-sheet/index-spec.tsx
+++ b/packages/s2-react/__tests__/unit/components/sheets/strategy-sheet/index-spec.tsx
@@ -18,7 +18,7 @@ import {
SheetComponent,
SheetComponentOptions,
} from '../../../../../src/components';
-import { getContainer } from '../../../../util/helpers';
+import { getContainer, sleep } from '../../../../util/helpers';
import {
StrategyOptions,
StrategySheetDataConfig,
@@ -36,6 +36,7 @@ describe(' Tests', () => {
ReactDOM.unmountComponentAtNode(container);
container.remove();
});
+
const renderStrategySheet = (
options: SheetComponentOptions | null,
dataCfg?: S2DataConfig,
@@ -74,7 +75,7 @@ describe(' Tests', () => {
renderStrategySheet(s2Options);
- expect(s2.options.tooltip.data.content).toEqual(content);
+ expect(s2.options.tooltip!.data!.content).toEqual(content);
});
test('should replace hierarchyType with "customTree" when rows is empty and contains custom tree items', () => {
@@ -114,16 +115,21 @@ describe(' Tests', () => {
renderStrategySheet(s2Options, s2DataConfig);
- expect(s2.options.style.colCfg.hideMeasureColumn).toBeTruthy();
+ expect(s2.options.style!.colCfg!.hideMeasureColumn).toBeTruthy();
});
test('should enable hidden columns operation', () => {
renderStrategySheet(null);
- expect(s2.options.tooltip.operation.hiddenColumns).toBeTruthy();
+ expect(s2.options.tooltip!.operation!.hiddenColumns).toBeTruthy();
});
- test.each([CellTypes.ROW_CELL, CellTypes.COL_CELL, CellTypes.DATA_CELL])(
+ test.each([
+ CellTypes.ROW_CELL,
+ CellTypes.COL_CELL,
+ CellTypes.DATA_CELL,
+ CellTypes.CORNER_CELL,
+ ])(
'should overwrite strategy sheet default custom tooltip and render custom %s tooltip',
(cellType) => {
const content = `${cellType} test content`;
@@ -131,6 +137,7 @@ describe(' Tests', () => {
[CellTypes.ROW_CELL]: 'row',
[CellTypes.COL_CELL]: 'col',
[CellTypes.DATA_CELL]: 'data',
+ [CellTypes.CORNER_CELL]: 'corner',
}[cellType];
renderStrategySheet({
@@ -150,6 +157,28 @@ describe(' Tests', () => {
},
);
+ test('should get current cell custom tooltip content', () => {
+ renderStrategySheet({
+ tooltip: {
+ showTooltip: true,
+ row: {
+ content: () => {CellTypes.ROW_CELL}
,
+ },
+ data: {
+ content: () => {CellTypes.DATA_CELL}
,
+ },
+ },
+ });
+
+ jest.spyOn(s2, 'getCellType').mockReturnValueOnce(CellTypes.COL_CELL);
+
+ s2.showTooltipWithInfo({} as GEvent, []);
+
+ [CellTypes.ROW_CELL, CellTypes.DATA_CELL].forEach((content) => {
+ expect(s2.tooltip.container.innerText).not.toEqual(content);
+ });
+ });
+
test('should render correctly KPI bullet column measure text', () => {
renderStrategySheet(
{
@@ -209,7 +238,7 @@ describe(' Tests', () => {
expect(textList).toEqual([cornerExtraFieldText, '日期']);
- expect(cornerNode.label).toEqual(cornerExtraFieldText);
+ expect(cornerNode!.label).toEqual(cornerExtraFieldText);
});
test('should format corner date field', () => {
diff --git a/packages/s2-react/package.json b/packages/s2-react/package.json
index 202ab32399..4f5173f81a 100644
--- a/packages/s2-react/package.json
+++ b/packages/s2-react/package.json
@@ -1,7 +1,7 @@
{
"private": false,
"name": "@antv/s2-react",
- "version": "1.44.0",
+ "version": "1.44.1",
"main": "lib/index.js",
"unpkg": "dist/index.min.js",
"module": "esm/index.js",
diff --git a/packages/s2-react/playground/config.ts b/packages/s2-react/playground/config.ts
index 52719ad7ee..ccb83ab7ac 100644
--- a/packages/s2-react/playground/config.ts
+++ b/packages/s2-react/playground/config.ts
@@ -1,5 +1,5 @@
-import { isUpDataValue, type Columns } from '@antv/s2';
-import type { S2DataConfig } from '@antv/s2';
+import { isUpDataValue, type Columns, customMerge } from '@antv/s2';
+import type { S2DataConfig, ThemeCfg } from '@antv/s2';
import { getBaseSheetComponentOptions } from '@antv/s2-shared';
import type { SliderSingleProps } from 'antd';
import {
@@ -46,6 +46,36 @@ export const pivotSheetDataCfg: S2DataConfig = {
fields,
};
+export const pivotSheetDataCfgForCompactMode = customMerge(pivotSheetDataCfg, {
+ data: [
+ ...pivotSheetDataCfg.data,
+ {
+ province: '浙江',
+ city: '杭州',
+ type: '笔',
+ price: '11111111',
+ },
+ {
+ province: '浙江',
+ city: '杭州',
+ type: '纸张',
+ price: '2',
+ },
+ {
+ province: '浙江',
+ city: '舟山',
+ type: '笔',
+ price: '2',
+ },
+ {
+ province: '浙江',
+ city: '舟山',
+ type: '纸张',
+ price: '133.333',
+ },
+ ],
+});
+
export const s2Options: SheetComponentOptions = {
debug: true,
width: 600,
@@ -110,10 +140,16 @@ export const s2Options: SheetComponentOptions = {
},
cellCfg: {
height: 50,
+ width: 200,
},
},
};
+export const s2ThemeConfig: ThemeCfg = {
+ name: 'default',
+ theme: {},
+};
+
export const sliderOptions: SliderSingleProps = {
min: 0,
max: 10,
diff --git a/packages/s2-react/playground/index.tsx b/packages/s2-react/playground/index.tsx
index 1d7ebd62ab..67b6cdc630 100644
--- a/packages/s2-react/playground/index.tsx
+++ b/packages/s2-react/playground/index.tsx
@@ -67,6 +67,8 @@ import {
tableSheetDataCfg,
tableSheetMultipleColumns,
tableSheetSingleColumns,
+ s2ThemeConfig,
+ pivotSheetDataCfgForCompactMode,
} from './config';
import './index.less';
import { ResizeConfig } from './resize';
@@ -167,9 +169,7 @@ function MainLayout() {
const [showPagination, setShowPagination] =
React.useState(false);
const [showTotals, setShowTotals] = React.useState(false);
- const [themeCfg, setThemeCfg] = React.useState({
- name: 'default',
- });
+ const [themeCfg, setThemeCfg] = React.useState(s2ThemeConfig);
const [themeColor, setThemeColor] = React.useState('#FFF');
const [showCustomTooltip, setShowCustomTooltip] = React.useState(false);
const [adaptive, setAdaptive] = React.useState(false);
@@ -320,6 +320,27 @@ function MainLayout() {
);
}, [tableSheetColumnType]);
+ useUpdateEffect(() => {
+ switch (options.style.layoutWidthType) {
+ case 'compact':
+ updateOptions({
+ style: {
+ cellCfg: {
+ width: 200,
+ },
+ },
+ });
+ setDataCfg(pivotSheetDataCfgForCompactMode);
+ break;
+
+ default:
+ updateOptions({
+ style: DEFAULT_STYLE,
+ });
+ setDataCfg(pivotSheetDataCfg);
+ }
+ }, [options.style.layoutWidthType]);
+
// ================== Config ========================
const mergedOptions: SheetComponentOptions = customMerge(
@@ -437,7 +458,7 @@ function MainLayout() {
行列等宽
列等宽
@@ -445,7 +466,10 @@ function MainLayout() {
-
+
默认
简约灰
多彩蓝
diff --git a/packages/s2-react/src/components/sheets/strategy-sheet/index.tsx b/packages/s2-react/src/components/sheets/strategy-sheet/index.tsx
index fcced7995d..f7252e29e0 100644
--- a/packages/s2-react/src/components/sheets/strategy-sheet/index.tsx
+++ b/packages/s2-react/src/components/sheets/strategy-sheet/index.tsx
@@ -1,14 +1,13 @@
-import type { S2CellType } from '@antv/s2';
+import type { S2CellType, S2DataConfig } from '@antv/s2';
import {
- type ColHeaderConfig,
- customMerge,
Node,
- type S2DataConfig,
- type S2Options,
SpreadSheet,
- type ViewMeta,
+ customMerge,
+ type ColHeaderConfig,
type MultiData,
+ type S2Options,
type TooltipShowOptions,
+ type ViewMeta,
} from '@antv/s2';
import { isArray, isEmpty, isFunction, isNil, size } from 'lodash';
import React from 'react';
@@ -114,7 +113,7 @@ export const StrategySheet: React.FC = React.memo(
},
col: {
content: (cell, tooltipOptions) =>
- getContent('row')(cell, tooltipOptions) ?? (
+ getContent('col')(cell, tooltipOptions) ?? (
),
},
diff --git a/s2-site/docs/api/basic-class/spreadsheet.zh.md b/s2-site/docs/api/basic-class/spreadsheet.zh.md
index c52e37f00b..37d949e8c1 100644
--- a/s2-site/docs/api/basic-class/spreadsheet.zh.md
+++ b/s2-site/docs/api/basic-class/spreadsheet.zh.md
@@ -58,7 +58,7 @@ s2.isPivotMode()
| updatePagination | 更新分页 | (pagination: [Pagination](/docs/api/general/S2Options#pagination)) => void | |
| getContentHeight | 获取当前表格实际内容高度 | `() => number` | |
| changeSheetSize (别名:changeSize) | 修改表格画布大小,不用重新加载数据 | `(width?: number, height?: number) => void` | |
-| getLayoutWidthType | 获取单元格宽度布局类型(LayoutWidthType: `adaptive(自适应)` \| `colAdaptive(列自适应)` \| `compact(紧凑)`) | () => `LayoutWidthType`| |
+| getLayoutWidthType | 获取单元格宽度布局类型。[详情](/api/general/s2-options#style) | () => `adaptive \| colAdaptive \| compact` | |
| getRowNodes | 获取行头节点 | (level: number) => [Node[]](/docs/api/basic-class/node/) | |
| getRowLeafNodes | 获取行头叶子节点 | () => [Node[]](/docs/api/basic-class/node/) | |
| getColumnNodes | 获取列头节点 | (level: number) => [Node[]](/docs/api/basic-class/node/) | |
diff --git a/s2-site/docs/api/general/S2DataConfig.zh.md b/s2-site/docs/api/general/S2DataConfig.zh.md
index f06b8effbe..55d5bee498 100644
--- a/s2-site/docs/api/general/S2DataConfig.zh.md
+++ b/s2-site/docs/api/general/S2DataConfig.zh.md
@@ -68,7 +68,7 @@ object **必选**,_default:null_
| columns | 列维度列表 | [Columns[]](#columns) | `[]` | |
| values | 指标维度列表 | `string[]` | `[]` | |
| valueInCols | 指标维度是否在列头 | `boolean` | `true` | |
-| customValueOrder | 自定义指标维度在行列头中的层级顺序 (即 `values` 的 顺序,从 `0` 开始) [查看示例](/zh/examples/custom/custom-layout/#custom-value-order) | `number` | - | |
+| customValueOrder | 自定义指标维度在行列头中的层级顺序 (即 `values` 的 顺序,从 `0` 开始,**仅支持单指标**) [查看示例](/zh/examples/custom/custom-layout/#custom-value-order) | `number` | - | |
### Meta
diff --git a/s2-site/docs/api/general/S2Theme.en.md b/s2-site/docs/api/general/S2Theme.en.md
index 34f7079343..2190018346 100644
--- a/s2-site/docs/api/general/S2Theme.en.md
+++ b/s2-site/docs/api/general/S2Theme.en.md
@@ -132,6 +132,7 @@ Function description: Split line style
| showShadow | Whether to display the outer shadow of the dividing line (in the case of frozen rows and columns) | `boolean` | `true` | |
| shadowWidth | shadow width | `number` | 10 | |
| shadowColors | `left` : change the left color linearly `right` : change the color of the right side linearly | `{left: string,` `right: string}` | `{left: 'rgba(0,0,0,0.1)',` `right: 'rgba(0,0,0,0)'}` | |
+| borderDash | Split line dash | `number[]` | `[]` | |
#### TextTheme
@@ -171,6 +172,7 @@ Function description: Cell general theme
| interactionState | cell interaction state | [InteractionStateTheme](#interactionstatetheme) | - | |
| miniBarChartHeight | In-Cell Conditional Formatting - Sparkline Bar Height | `number` | 12 | |
| miniBarChartFillColor | In-cell conditional formatting - default fill color for mini bar charts | `string` | - | |
+| borderDash | cell border dash | `number[]` | `[]` | |
#### IconTheme
diff --git a/s2-site/docs/api/general/S2Theme.zh.md b/s2-site/docs/api/general/S2Theme.zh.md
index 892ef33676..ae1df30d2b 100644
--- a/s2-site/docs/api/general/S2Theme.zh.md
+++ b/s2-site/docs/api/general/S2Theme.zh.md
@@ -134,6 +134,7 @@ s2.setTheme({
| showShadow | 分割线是否显示外阴影(行列冻结情况下) | `boolean` | `true` | |
| shadowWidth | 阴影宽度 | `number` | 10 | |
| shadowColors | `left` : 线性变化左侧颜色
`right` : 线性变化右侧颜色 | `{left: string,`
`right: string}` | `{left: 'rgba(0,0,0,0.1)',`
`right: 'rgba(0,0,0,0)'}` | |
+| borderDash | 分割线虚线 | `number[]` | `[]` | |
#### TextTheme
@@ -148,6 +149,8 @@ s2.setTheme({
| fontFamily | 字体 | `string` | `Roboto, PingFangSC,`
`BlinkMacSystemFont,`
`Microsoft YaHei,`
`Arial, sans-serif` | |
| fontSize | 字体大小 | `number` | - | |
| fontWeight | number
string: `normal`
`bold`
`bolder`
`lighter` 字体粗细 | `number` \| `string` | 粗体文本:Mobile:`520` PC: `bold`
普通文本:`normal` | |
+| fontStyle | 字体样式 | `normal \| italic \| oblique` | `normal` |
+| fontVariant | 字体变体 | `normal \| small-caps \| string` | `normal` |
| fill | 字体颜色 | `string` | - | |
| linkTextFill | 链接文本颜色 | `string` | - | |
| opacity | 字体透明度 | `number` | 1 | |
@@ -173,6 +176,7 @@ s2.setTheme({
| interactionState | 单元格交互态 ([查看默认配置](https://github.com/antvis/S2/blob/master/packages/s2-core/src/theme/index.ts#L66-L107)) ([示例](/zh/examples/interaction/basic#state-theme)) | Record<[InteractionStateName](#interactionstatename), [InteractionStateTheme](#interactionstatetheme)> | - | |
| miniBarChartHeight | 单元格内条件格式-迷你条形图高度 | `number` | 12 | |
| miniBarChartFillColor | 单元格内条件格式-迷你条形图默认填充颜色 | `string` | - | |
+| borderDash | 单元格边线虚线 | `number[]` | `[]` | |
#### IconTheme
diff --git a/s2-site/docs/api/graphic.zh.md b/s2-site/docs/api/graphic.zh.md
index 7c92aff545..8fb20a7e90 100644
--- a/s2-site/docs/api/graphic.zh.md
+++ b/s2-site/docs/api/graphic.zh.md
@@ -47,6 +47,8 @@ S2 使用 [AntV/G](https://g.antv.vision/zh/docs/guide/introduce) 作为绘图
| fontSize | `number` | 文字大小 |
| fontFamily | `string` | 文字字体 |
| fontWeight | `number` | 字体粗细 |
+| fontStyle | `normal \| italic \| oblique` | 字体样式 |
+| fontVariant | `normal \| small-caps \| string` | 字体变体 |
| lineHeight | `number` | 文字的行高 |
| textAlign | `center` \| `left` \| `right` \| `start` \| `end` | 设置文本内容的对齐方式 |
| textBaseline | `top` \| `middle` \| `bottom` \| `alphabetic` \| `hanging` | 设置在绘制文本时使用的当前文本基线|
diff --git a/s2-site/docs/common/contact-us.en.md b/s2-site/docs/common/contact-us.en.md
index 192fd5b82e..397c40a4ad 100644
--- a/s2-site/docs/common/contact-us.en.md
+++ b/s2-site/docs/common/contact-us.en.md
@@ -7,7 +7,4 @@ order: 5
-
-
-
diff --git a/s2-site/docs/common/contact-us.zh.md b/s2-site/docs/common/contact-us.zh.md
index 59ae6f1dba..6281d0dc71 100644
--- a/s2-site/docs/common/contact-us.zh.md
+++ b/s2-site/docs/common/contact-us.zh.md
@@ -7,7 +7,4 @@ order: 5
-
-
-
diff --git a/s2-site/docs/common/development.zh.md b/s2-site/docs/common/development.zh.md
index 7e5bee0bc2..88b9a3135d 100644
--- a/s2-site/docs/common/development.zh.md
+++ b/s2-site/docs/common/development.zh.md
@@ -1,4 +1,12 @@
-跃跃欲试想贡献?[查看贡献指南](https://s2.antv.antgroup.com/manual/contribution)
+跃跃欲试想贡献?[查看贡献指南](https://s2.antv.antgroup.com/manual/contribution) , 欢迎 [Pull Request](https://github.com/antvis/S2/pulls),或给我们 [报告 Bug](https://github.com/antvis/S2/issues/new?assignees=&labels=&projects=&template=bug-report.md&title=%F0%9F%90%9B).
+
+> 强烈建议花一点你的宝贵时间阅读:
+
+- [《提 Issue 前必读》](https://github.com/antvis/S2/issues/1904)
+- [《如何向开源项目提交无法解答的问题》](https://zhuanlan.zhihu.com/p/25795393)
+- [《如何有效地报告 Bug》](https://www.chiark.greenend.org.uk/~sgtatham/bugs-cn.html)
+- [《提问的智慧》](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way)
+- [《如何向开源社区提问题》](https://github.com/seajs/seajs/issues/545)
```bash
git clone git@github.com:antvis/S2.git
diff --git a/s2-site/docs/common/packages.zh.md b/s2-site/docs/common/packages.zh.md
index 3b0767f32b..01f71f584a 100644
--- a/s2-site/docs/common/packages.zh.md
+++ b/s2-site/docs/common/packages.zh.md
@@ -3,8 +3,23 @@ title: Packages
order: 5
---
+- `@antv/s2`: 基于 `Canvas` 和 [AntV/G](https://g.antv.vision/zh/docs/guide/introduce) 开发,提供基本的表格展示/交互等能力。
+- `@antv/s2-react`: 基于 `React` 和 `@antv/s2` 封装,提供配套的分析组件,配置项和 `@antv/s2` 通用。
+- `@antv/s2-vue`: 基于 `Vue3` 和 `@antv/s2` 封装,配置项和 `@antv/s2` 通用,如果你想在 `Vue2` 中使用,请使用 `@antv/s2`。
+
+也就是说 `@antv/s2` 和**框架无关**,你也可以在 `Vue`, `Angular` 等框架中直接使用。
+
| 版本号 | 稳定版 | 测试版 | 预览版 | 先行版 | 包大小 | 下载量 |
| -------- | ------ | --------- | ---------- | ---------- | ---------- | ------ |
| [@antv/s2](https://github.com/antvis/S2/tree/master/packages/s2-core) | ![latest](https://img.shields.io/npm/v/@antv/s2/latest.svg) | ![beta](https://img.shields.io/npm/v/@antv/s2/beta.svg) | ![alpha](https://img.shields.io/npm/v/@antv/s2/alpha.svg) | ![next](https://img.shields.io/npm/v/@antv/s2/next.svg) | ![size](https://img.badgesize.io/https:/unpkg.com/@antv/s2@latest/dist/index.min.js?label=gzip%20size&compression=gzip) | ![download](https://img.shields.io/npm/dm/@antv/s2.svg) |
| [@antv/s2-react](https://github.com/antvis/S2/tree/master/packages/s2-react) | ![latest](https://img.shields.io/npm/v/@antv/s2-react/latest.svg) | ![beta](https://img.shields.io/npm/v/@antv/s2-react/beta.svg) | ![alpha](https://img.shields.io/npm/v/@antv/s2-react/alpha.svg) | ![next](https://img.shields.io/npm/v/@antv/s2-react/next.svg)| ![size](https://img.badgesize.io/https:/unpkg.com/@antv/s2-react@latest/dist/index.min.js?label=gzip%20size&compression=gzip) | ![download](https://img.shields.io/npm/dm/@antv/s2-react.svg) |
| [@antv/s2-vue](https://github.com/antvis/S2/tree/master/packages/s2-vue) | ![latest](https://img.shields.io/npm/v/@antv/s2-vue/latest.svg) | ![beta](https://img.shields.io/npm/v/@antv/s2-vue/beta.svg) | ![alpha](https://img.shields.io/npm/v/@antv/s2-vue/alpha.svg) | ![next](https://img.shields.io/npm/v/@antv/s2-vue/next.svg) | ![size](https://img.badgesize.io/https:/unpkg.com/@antv/s2-vue@latest/dist/index.min.js?label=gzip%20size&compression=gzip) | ![download](https://img.shields.io/npm/dm/@antv/s2-vue.svg) |
+
+:::info{title='如何获取新版本发布通知?'}
+
+- 订阅:[https://github.com/antvis/S2/releases.atom](https://github.com/antvis/S2/releases.atom) 来获得新版本发布的通知。
+- 加入钉钉交流群,新版本发布后,会通过🤖 群机器人推送。
+- `Watch` [S2 代码仓库](https://github.com/antvis/S2), 选择 `Custom - Releases` 来获取消息推送。
+
+![preview](https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*NKYFSKFV_scAAAAAAAAAAAAADmJ7AQ/original)
+:::
diff --git a/s2-site/docs/common/style.zh.md b/s2-site/docs/common/style.zh.md
index c0709c5bbf..26b81349fd 100644
--- a/s2-site/docs/common/style.zh.md
+++ b/s2-site/docs/common/style.zh.md
@@ -9,7 +9,7 @@ object **必选**,_default:null_ 功能描述:样式设置
| 参数 | 类型 | 必选 | 默认值 | 功能描述 |
| --- | --- | --- | --- | --- |
-| layoutWidthType | `adaptive` \| `colAdaptive` \| `compact` | | | 单元格宽度布局类型
`adaptive` : 行列等宽,均分整个 `Canvas` 画布宽度
`colAdaptive`:列等宽,行头紧凑布局,列等分画布宽度减去行头宽度的剩余宽度
`compact`:行列紧凑布局,指标维度少的时候无法布满整个画布 |
+| layoutWidthType | `adaptive \| colAdaptive \| compact` | | | 单元格宽度布局类型
`adaptive` : 行列等宽,均分整个表格 (`Canvas`) 画布宽度
`colAdaptive`:列等宽,行头紧凑布局,列等分画布宽度减去行头宽度的剩余宽度
`compact`:行列紧凑布局,列头宽度为内容实际宽度 (采样列前 50 个数值), 指标维度少的时候无法布满整个画布 |
| showTreeLeafNodeAlignDot | `boolean` | | false | 树状模式下叶子节点是否显示层级占位点 |
| treeRowsWidth | `number` | | 120 | 树状模式行单元格宽度 (优先级大于 `rowCfg.width` 和 `rowCfg.treeRowsWidth (已废弃)`) |
| hierarchyCollapse | `boolean` | | `false` | 在树状结构模式下行头是否默认展开。 |
@@ -18,7 +18,7 @@ object **必选**,_default:null_ 功能描述:样式设置
| cellCfg | [CellCfg](#cellcfg) | | | 单元格配置 |
| colCfg | [ColCfg](#colcfg) | | | 列样式配置 |
| rowCfg | [RowCfg](#rowcfg) | | | 行样式配置 |
-| device | `pc` \| `mobile` | | `pc` | 设备类型 |
+| device | `pc \| mobile` | | `pc` | 设备类型 |
## CellCfg
diff --git a/s2-site/docs/manual/advanced/custom/hook.zh.md b/s2-site/docs/manual/advanced/custom/hook.zh.md
index a395b2e60c..b527c4ce92 100644
--- a/s2-site/docs/manual/advanced/custom/hook.zh.md
+++ b/s2-site/docs/manual/advanced/custom/hook.zh.md
@@ -31,23 +31,23 @@ order: 1
## dataCell
-改变数据单元格的默认实现,需要继承自 [dataCell](https://github.com/antvis/S2/blob/master/packages/s2-core/src/cell/data-cell.ts),覆盖某些方法,比如字体样式、背景样式等。[例子](/examples/custom/custom-cell#data-cell)
+修改数据单元格的默认实现,需要继承自 [DataCell](https://github.com/antvis/S2/blob/master/packages/s2-core/src/cell/data-cell.ts) (明细表对应 [TableDataCell](https://github.com/antvis/S2/blob/master/packages/s2-core/src/cell/table-data-cell.ts)),复写某些方法,比如字体样式、背景样式等。[例子](/examples/custom/custom-cell#data-cell)
## rowCell
-改变行头单元格的默认实现,需要继承自 [rowCell](https://github.com/antvis/S2/blob/master/packages/s2-core/src/cell/row-cell.ts),覆盖某些方法,比如字体样式、背景样式等。[例子](/examples/custom/custom-cell#row-cell)
+修改行头单元格的默认实现,需要继承自 [RowCell](https://github.com/antvis/S2/blob/master/packages/s2-core/src/cell/row-cell.ts),复写某些方法,比如字体样式、背景样式等。[例子](/examples/custom/custom-cell#row-cell)
## colCell
-改变列头单元格的默认实现,需要继承自 [colCell](https://github.com/antvis/S2/blob/master/packages/s2-core/src/cell/col-cell.ts),覆盖某些方法,比如字体样式、背景样式等。[例子](/examples/custom/custom-cell#col-cell)
+修改列头单元格的默认实现,需要继承自 [ColCell](https://github.com/antvis/S2/blob/master/packages/s2-core/src/cell/col-cell.ts)(明细表对应 [TableColCell](https://github.com/antvis/S2/blob/master/packages/s2-core/src/cell/table-col-cell.ts)),复写某些方法,比如字体样式、背景样式等。[例子](/examples/custom/custom-cell#col-cell)
## cornerCell
-改变角头单元格的默认实现,需要继承自 [cornerCell](https://github.com/antvis/S2/blob/master/packages/s2-core/src/cell/corner-cell.ts),覆盖某些方法,比如字体样式、背景样式等。[例子](/examples/custom/custom-cell#corner-cell)
+修改角头单元格的默认实现,需要继承自 [TableCornerCell](https://github.com/antvis/S2/blob/master/packages/s2-core/src/cell/corner-cell.ts)(明细表对应 [TableCornerCell](https://github.com/antvis/S2/blob/master/packages/s2-core/src/cell/table-corner-cell.ts)),复写某些方法,比如字体样式、背景样式等。[例子](/examples/custom/custom-cell#corner-cell)
## cornerHeader
-改变角头的默认实现,需要继承自 [Group](https://g.antv.vision/zh/docs/api/group),覆盖某些方法,比如渲染内容更换等。[例子](/examples/custom/custom-cell#corner-cell)
+修改角头的默认实现,需要继承自 [Group](https://g.antv.vision/zh/docs/api/group),复写某些方法,比如渲染内容更换等。[例子](/examples/custom/custom-cell#corner-header)
## frame
diff --git a/s2-site/docs/manual/basic/analysis/strategy.zh.md b/s2-site/docs/manual/basic/analysis/strategy.zh.md
index 39d1c72a64..0ca2bdf96f 100644
--- a/s2-site/docs/manual/basic/analysis/strategy.zh.md
+++ b/s2-site/docs/manual/basic/analysis/strategy.zh.md
@@ -176,7 +176,13 @@ const s2Options = {
-配置如下:
+### 在普通透视表中使用
+
+如果不依赖 `React`, 想在 `@antv/s2` 普通的透视表中使用 mini 图,可以参考这个 [示例](/zh/examples/custom/custom-cell/#mini-chart)
+
+
+
+### API
diff --git a/s2-site/docs/manual/faq.zh.md b/s2-site/docs/manual/faq.zh.md
index 99d67ee8c9..706556faeb 100644
--- a/s2-site/docs/manual/faq.zh.md
+++ b/s2-site/docs/manual/faq.zh.md
@@ -4,7 +4,7 @@ order: 8
---
:::warning{title="一些建议"}
-**在提出问题前,请确保你已经仔细阅读了一遍文档,查看了相关图表示例,并且已经查看了常见问题。**
+**在提出问题前,请确保你已经仔细阅读了一遍文档,查看了相关图表示例,并且已经查看了常见问题和 Issues。**
:::
## 1. 使用问题
@@ -254,17 +254,7 @@ s2.setTheme({
目前只有 React 版本 `@antv/s2-react` 支持编辑表格,其他版本暂不支持,需参考 [源码](https://github.com/antvis/S2/blob/2d85d5739f5a3a52e92df699a935df93aa2a6a73/packages/s2-react/src/components/sheets/editable-sheet/index.tsx#L10) 自行实现
-### S2 有对应的 `Vue` 或者 `Angular` 版本吗?
-
-目前,S2 由三个包构成
-
-- `@antv/s2`: 基于 `canvas` 和 [AntV/G](https://g.antv.vision/zh/docs/guide/introduce) 开发,提供基本的表格展示/交互等能力
-- `@antv/s2-react`: 基于 `@antv/s2` 封装,提供配套的分析组件
-- `@antv/s2-vue`: 基于 `Vue3` 和 `@antv/s2` 封装,提供配套的分析组件
-
-也就是说 `@antv/s2` 和**框架无关**,你可以在 `Vue`, `Angular` 等框架中使用。
-
-以下是版本概览:
+### S2 有对应的 `Vue` 或者 `Angular` 版本吗?如何获取新版本发布通知?
@@ -323,6 +313,8 @@ s2.setTheme({
### 有讨论群吗?
+交流群不提供任何答疑,有任何问题请直接提交 [Issue](https://github.com/antvis/S2/issues/new/choose) 或者 [Discussion](https://github.com/antvis/S2/discussions/new?category=q-a), 当然,也期待你的 [Pull request](https://github.com/antvis/S2/pulls).
+
## 2. 错误和警告
diff --git a/s2-site/docs/manual/getting-started.zh.md b/s2-site/docs/manual/getting-started.zh.md
index 64705d1340..4f23674fd9 100644
--- a/s2-site/docs/manual/getting-started.zh.md
+++ b/s2-site/docs/manual/getting-started.zh.md
@@ -2,26 +2,30 @@
title: 快速上手
order: 1
---
+
## 📦 安装
-### npm | yarn 安装
+### 使用 npm 或 yarn 或 pnpm 安装
```bash
# npm
-$ npm install @antv/s2
+$ npm install @antv/s2 --save
# yarn
-$ yarn add @antv/s2
+$ yarn add @antv/s2 --save
+
+# pnpm
+$ pnpm install @antv/s2 --save
```
### 使用 React 或 Vue3 版本
```bash
# React
-$ yarn add @antv/s2 @antv/s2-react
+$ yarn add @antv/s2 @antv/s2-react --save
# Vue3
-$ yarn add @antv/s2 @antv/s2-vue
+$ yarn add @antv/s2 @antv/s2-vue --save
```
### 浏览器引入(不推荐)
@@ -34,6 +38,8 @@ $ yarn add @antv/s2 @antv/s2-vue
创建 `S2` 表格有三种方式,基础类版本 `(s2-core)` 和 基于 `core` 层 封装的 `React` 和 `Vue3` 版本
+### 版本
+
### 基础类
@@ -184,7 +190,8 @@ s2.render();
### `React` 版本
-`S2` 提供了开箱即用的 `React` 版本 [表格组件](/examples/gallery#category-表格组件), 还有丰富的配套 [分析组件](/examples/gallery#category-Tooltip), 帮助开发者快速满足业务看数分析需求。
+`S2` 提供了开箱即用的 `React` 版本 [表格组件](examples/gallery#category-表格组件)
+, 还有丰富的配套 [分析组件](/examples/gallery#category-Tooltip), 帮助开发者快速满足业务看数分析需求。
#### 表格组件使用
@@ -194,8 +201,6 @@ import ReactDOM from 'react-dom';
import { SheetComponent } from '@antv/s2-react';
import '@antv/s2-react/dist/style.min.css';
-const container = document.getElementById('container');
-
ReactDOM.render(
diff --git a/s2-site/docs/manual/introduction.zh.md b/s2-site/docs/manual/introduction.zh.md
index c577f4e01a..7e0c4361e5 100644
--- a/s2-site/docs/manual/introduction.zh.md
+++ b/s2-site/docs/manual/introduction.zh.md
@@ -27,7 +27,7 @@ redirect_from:
## ❓ 什么是 S2
-[S2](https://github.com/antvis/s2) 是一个面向可视分析领域的数据驱动的表可视化引擎。"S" 取自于 "SpreadSheet" 的两个 "S","2" 代表了透视表中的行列两个维度。旨在提供美观、易用、高性能、易扩展的多维表格。
+[S2](https://github.com/antvis/s2) 是一个面向可视分析领域的数据驱动的表可视化引擎。`S` 取自于 `SpreadSheet` 的两个 `S`,`2` 代表了透视表中的行列两个维度。旨在提供美观、易用、高性能、易扩展的多维表格。
![demos](https://gw.alipayobjects.com/zos/antfincdn/6R5Koawk9L/huaban%2525202.png)
@@ -42,8 +42,9 @@ redirect_from:
## 📦 安装
```bash
-npm install @antv/s2
-# yarn add @antv/s2
+npm install @antv/s2 --save
+# yarn add @antv/s2 --save
+# pnpm install @antv/s2 --save
```
## 🔨 使用
diff --git a/s2-site/examples/case/art/demo/lost-text.tsx b/s2-site/examples/case/art/demo/lost-text.tsx
new file mode 100644
index 0000000000..898564f3e2
--- /dev/null
+++ b/s2-site/examples/case/art/demo/lost-text.tsx
@@ -0,0 +1,292 @@
+/* eslint-disable max-classes-per-file */
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { SheetComponent } from '@antv/s2-react';
+import { Tag } from 'antd';
+import {
+ BaseEvent,
+ CellTypes,
+ getTheme,
+ InterceptType,
+ S2Event,
+ CornerCell,
+} from '@antv/s2';
+
+import '@antv/s2-react/dist/style.min.css';
+
+const Theme = {
+ rowCell: {
+ text: {
+ opacity: 0,
+ },
+ bolderText: {
+ opacity: 0,
+ },
+ measureText: {
+ opacity: 0,
+ },
+ },
+ colCell: {
+ text: {
+ opacity: 0,
+ },
+ bolderText: {
+ opacity: 0,
+ },
+ measureText: {
+ opacity: 0,
+ },
+ },
+ dataCell: {
+ text: {
+ opacity: 0,
+ },
+ },
+};
+
+class CustomCornerCell extends CornerCell {
+ drawBackgroundShape() {
+ this.addShape('rect', {
+ attrs: {
+ ...this.getCellArea(),
+ fill: '#E0E9FD',
+ },
+ });
+ }
+
+ getCornerText() {
+ return '👍🏻';
+ }
+}
+
+class CustomInteraction extends BaseEvent {
+ timer = null;
+
+ count = 0;
+
+ changeCell(cellType: CellTypes) {
+ this.count++;
+
+ const defaultTheme = getTheme(null)?.[cellType];
+ this.spreadsheet.setTheme({
+ [cellType]: defaultTheme,
+ });
+ this.spreadsheet.render(false);
+
+ if (this.count >= 3) {
+ clearInterval(this.timer);
+ this.showSuccessTips();
+ }
+ }
+
+ resetCell() {
+ this.count = 0;
+ this.spreadsheet.setTheme(Theme);
+ this.spreadsheet.render(false);
+ }
+
+ showSuccessTips() {
+ const rect = this.spreadsheet.getCanvasElement().getBoundingClientRect();
+
+ this.spreadsheet.showTooltip({
+ position: {
+ x: rect.width / 2 + rect.left,
+ y: rect.height / 2 + rect.top,
+ },
+ content: (
+
+ ),
+ });
+ this.spreadsheet.interaction.addIntercepts([InterceptType.HOVER]);
+ }
+
+ bindEvents() {
+ // 角头: 一键三连
+ this.addCornerCellInteraction();
+ // 行头: 多选全部偶数行
+ this.addRowCellInteraction();
+ // 列头: 调整列宽/刷选全部
+ this.addColCellInteraction();
+ // 数值: 键盘方向键移动端选中单元格到右下角
+ this.addDataCellInteraction();
+ }
+
+ addCornerCellInteraction() {
+ const countMap: Record = {
+ 0: CellTypes.ROW_CELL,
+ 1: CellTypes.COL_CELL,
+ 2: CellTypes.DATA_CELL,
+ };
+
+ this.spreadsheet.on(S2Event.CORNER_CELL_MOUSE_DOWN, () => {
+ clearInterval(this.timer);
+ this.resetCell();
+
+ this.timer = setInterval(() => {
+ this.changeCell(countMap[this.count]);
+ }, 1000);
+ });
+
+ this.spreadsheet.on(S2Event.CORNER_CELL_MOUSE_UP, () => {
+ clearInterval(this.timer);
+
+ if (this.count < 3) {
+ this.resetCell();
+ }
+ });
+ }
+
+ addDataCellInteraction() {
+ this.spreadsheet.on(S2Event.DATA_CELL_SELECT_MOVE, (cells) => {
+ const { colIndex, rowIndex } = cells[0];
+
+ const isLastCell = colIndex === 3 && rowIndex === 7;
+ if (isLastCell) {
+ this.changeCell(CellTypes.DATA_CELL);
+ }
+ });
+ }
+
+ addColCellInteraction() {
+ this.spreadsheet.on(S2Event.LAYOUT_RESIZE_COL_WIDTH, ({ info }) => {
+ const rules = [6, 66, 666];
+ if (rules.includes(info.resizedWidth)) {
+ this.changeCell(CellTypes.COL_CELL);
+ }
+ });
+
+ this.spreadsheet.on(S2Event.COL_CELL_BRUSH_SELECTION, (colCells) => {
+ const isAllSelected =
+ colCells.length === this.spreadsheet.getColumnNodes().length;
+ if (isAllSelected) {
+ this.changeCell(CellTypes.COL_CELL);
+ }
+ });
+ }
+
+ addRowCellInteraction() {
+ this.spreadsheet.on(S2Event.GLOBAL_SELECTED, (cells) => {
+ const selectedOddRowCells = cells.filter((cell) => {
+ const meta = cell.getMeta();
+ return cell.cellType === CellTypes.ROW_CELL && meta.rowIndex % 2 !== 0;
+ });
+
+ const isAllOddRowCellsSelected = selectedOddRowCells.length === 4;
+ if (isAllOddRowCellsSelected) {
+ this.changeCell(CellTypes.ROW_CELL);
+ }
+ });
+ }
+}
+
+export const s2Options = {
+ debug: true,
+ width: 600,
+ height: 400,
+ showSeriesNumber: false,
+ showDefaultHeaderActionIcon: false,
+ interaction: {
+ enableCopy: true,
+ // 防止 mac 触摸板横向滚动触发浏览器返回, 和移动端下拉刷新
+ overscrollBehavior: 'none',
+ brushSelection: {
+ data: true,
+ col: true,
+ row: true,
+ },
+ hoverFocus: false,
+ hoverHighlight: false,
+ customInteractions: [
+ {
+ key: 'CustomInteraction',
+ interaction: CustomInteraction,
+ },
+ ],
+ },
+ tooltip: {
+ showTooltip: false,
+ },
+ hierarchyType: 'grid',
+ style: {
+ rowCfg: {
+ width: 100,
+ },
+ cellCfg: {
+ width: 50,
+ height: 30,
+ },
+ },
+ cornerCell: (...args) => new CustomCornerCell(...args),
+};
+
+fetch(
+ 'https://gw.alipayobjects.com/os/bmw-prod/2a5dbbc8-d0a7-4d02-b7c9-34f6ca63cff6.json',
+)
+ .then((res) => res.json())
+ .then((dataCfg) => {
+ ReactDOM.render(
+
+
+ 单元格的文字都消失了, 想办法让文字全部显示出来.
+
+ 查看代码
+
+
+
+ -
+
+ 列头可以 "调整" 成三个尺码: s (6px) M (66px) L (666px)
+
+
+ -
+ 列头10个单元格可以 "圈" 在一起
+
+ -
+ 行头多选, 让它显示斑马纹
+
+ -
+ 有一个数值单元格喜欢待在角落 ↑ ↓ ← →
+
+ -
+ 搞不定, 试试看看
+
+ 基础交互
+
+ 章节或试试 长按一键三连
+
+
+ >
+ ),
+ }}
+ />,
+ document.getElementById('container'),
+ );
+ });
diff --git a/s2-site/examples/case/art/demo/meta.json b/s2-site/examples/case/art/demo/meta.json
index 4472e98d6c..77f7574aa4 100644
--- a/s2-site/examples/case/art/demo/meta.json
+++ b/s2-site/examples/case/art/demo/meta.json
@@ -15,10 +15,18 @@
{
"filename": "time-spend-abstract.tsx",
"title": {
- "zh": "想如何度过一天(抽象版)",
+ "zh": "想如何度过一天 (抽象版)",
"en": "How to spend the day"
},
"screenshot": "https://gw.alipayobjects.com/zos/antfincdn/lN8USZvMEV/f6b5e06f-5def-4db8-a9c8-826e347d0fa1.png"
+ },
+ {
+ "filename": "lost-text.tsx",
+ "title": {
+ "zh": "消失的文字 (交互小游戏)",
+ "en": "Lost text"
+ },
+ "screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*3WDCR7PZY6MAAAAAAAAAAAAADmJ7AQ/original"
}
]
}
diff --git a/s2-site/examples/custom/custom-cell/demo/corner-header.ts b/s2-site/examples/custom/custom-cell/demo/corner-header.ts
index 1b40471866..4d65f8ea4f 100644
--- a/s2-site/examples/custom/custom-cell/demo/corner-header.ts
+++ b/s2-site/examples/custom/custom-cell/demo/corner-header.ts
@@ -8,13 +8,17 @@ import { get } from 'lodash';
*/
class CustomCornerHeader extends Group {
node;
+
backgroundShape;
+
textShape;
+
constructor(node) {
super({});
this.node = node;
this.initCornerHeader();
}
+
initCornerHeader() {
this.initBg();
this.initText();
@@ -77,6 +81,5 @@ fetch(
};
const s2 = new PivotSheet(container, s2DataConfig, s2Options);
- // 使用
s2.render();
});
diff --git a/s2-site/examples/custom/custom-cell/demo/custom-specified-cell.ts b/s2-site/examples/custom/custom-cell/demo/custom-specified-cell.ts
index 086cf0dec2..31f93077a4 100644
--- a/s2-site/examples/custom/custom-cell/demo/custom-specified-cell.ts
+++ b/s2-site/examples/custom/custom-cell/demo/custom-specified-cell.ts
@@ -1,8 +1,8 @@
/* eslint-disable max-classes-per-file */
-import { PivotSheet, DataCell, ColCell } from '@antv/s2';
+import { PivotSheet, DataCell, ColCell, CornerCell, RowCell } from '@antv/s2';
/**
- * 自定义 DataCell,给特定单元格设置背景色, 文字大小, 颜色
+ * 自定义 DataCell,通过复写基类方法, 给特定单元格设置背景色, 文字大小, 颜色等...
* 查看更多方法 https://github.com/antvis/S2/blob/master/packages/s2-core/src/cell/data-cell.ts
*/
class CustomDataCell extends DataCell {
@@ -62,7 +62,7 @@ class CustomDataCell extends DataCell {
}
/**
- * 自定义 ColCell, 给特定单元格设置文字大小, 颜色
+ * 自定义 ColCell, 通过复写基类方法, 给特定单元格设置文字大小, 颜色等...
* 查看更多方法 https://github.com/antvis/S2/blob/master/packages/s2-core/src/cell/col-cell.ts
*/
class CustomColCell extends ColCell {
@@ -70,7 +70,7 @@ class CustomColCell extends ColCell {
const defaultTextStyle = super.getTextStyle();
// 指定列
- if (this.meta.rowIndex % 2 === 0) {
+ if (this.meta.colIndex % 2 === 0) {
return {
...defaultTextStyle,
fontSize: 16,
@@ -102,6 +102,81 @@ class CustomColCell extends ColCell {
}
}
+/**
+ * 自定义 CornerCell, 通过复写基类方法, 给特定单元格设置文字大小, 颜色等...
+ * 查看更多方法 https://github.com/antvis/S2/blob/master/packages/s2-core/src/cell/corner-cell.ts
+ */
+class CustomCornerCell extends CornerCell {
+ getBackgroundColor() {
+ // 特定数据
+ if (this.meta.field === 'province') {
+ return {
+ backgroundColor: 'red',
+ backgroundColorOpacity: 0.2,
+ };
+ }
+
+ return super.getBackgroundColor();
+ }
+
+ getTextStyle() {
+ const defaultTextStyle = super.getTextStyle();
+
+ if (this.meta.field === 'type') {
+ return {
+ ...defaultTextStyle,
+ fill: '#06a',
+ fontSize: 20,
+ fontWeight: 200,
+ };
+ }
+
+ return super.getTextStyle();
+ }
+}
+
+/**
+ * 自定义 RowCell, 通过复写基类方法, 给特定单元格设置文字大小, 颜色等...
+ * 查看更多方法 https://github.com/antvis/S2/blob/master/packages/s2-core/src/cell/row-cell.ts
+ */
+class CustomRowCell extends RowCell {
+ getBackgroundColor() {
+ // 特定数据
+ if (this.meta.field === 'province') {
+ return {
+ backgroundColor: 'red',
+ backgroundColorOpacity: 0.2,
+ };
+ }
+
+ return super.getBackgroundColor();
+ }
+
+ getTextStyle() {
+ const defaultTextStyle = super.getTextStyle();
+
+ if (this.meta.field === 'type') {
+ return {
+ ...defaultTextStyle,
+ fill: '#06a',
+ fontSize: 20,
+ fontWeight: 200,
+ };
+ }
+
+ if (this.meta.rowIndex >= 1) {
+ return {
+ ...defaultTextStyle,
+ fill: '#dcdcdc',
+ fontSize: 20,
+ fontWeight: 700,
+ };
+ }
+
+ return super.getTextStyle();
+ }
+}
+
fetch(
'https://gw.alipayobjects.com/os/bmw-prod/cd9814d0-6dfa-42a6-8455-5a6bd0ff93ca.json',
)
@@ -120,16 +195,20 @@ fetch(
const s2Options = {
width: 600,
height: 480,
- dataCell: (viewMeta) => {
- return new CustomDataCell(viewMeta, viewMeta?.spreadsheet);
+ cornerCell: (node, spreadsheet, headerConfig) => {
+ return new CustomCornerCell(node, spreadsheet, headerConfig);
},
- // rowCell 同理, 请参考示例
colCell: (node, spreadsheet, headerConfig) => {
return new CustomColCell(node, spreadsheet, headerConfig);
},
+ rowCell: (node, spreadsheet, headerConfig) => {
+ return new CustomRowCell(node, spreadsheet, headerConfig);
+ },
+ dataCell: (viewMeta) => {
+ return new CustomDataCell(viewMeta, viewMeta?.spreadsheet);
+ },
};
const s2 = new PivotSheet(container, s2DataConfig, s2Options);
- // 使用
s2.render();
});
diff --git a/s2-site/examples/custom/custom-cell/demo/custom-table-cell.ts b/s2-site/examples/custom/custom-cell/demo/custom-table-cell.ts
new file mode 100644
index 0000000000..7a3e822182
--- /dev/null
+++ b/s2-site/examples/custom/custom-cell/demo/custom-table-cell.ts
@@ -0,0 +1,139 @@
+/* eslint-disable max-classes-per-file */
+import { TableColCell, TableDataCell, TableSheet } from '@antv/s2';
+
+/**
+ * 自定义 DataCell,通过复写基类方法, 给特定单元格设置背景色, 文字大小, 颜色等...
+ * 查看更多方法 https://github.com/antvis/S2/blob/master/packages/s2-core/src/cell/table-data-cell.ts
+ */
+class CustomDataCell extends TableDataCell {
+ getBackgroundColor() {
+ // 特定数据
+ if (this.meta.fieldValue >= 6000) {
+ return {
+ backgroundColor: 'red',
+ backgroundColorOpacity: 0.2,
+ };
+ }
+
+ return super.getBackgroundColor();
+ }
+
+ getTextStyle() {
+ const defaultTextStyle = super.getTextStyle();
+ // 序号
+
+ if (this.meta.colIndex === 0) {
+ return {
+ ...defaultTextStyle,
+ fontWeight: 600,
+ textAlign: 'center',
+ };
+ }
+
+ // 指定列
+ if (this.meta.rowIndex % 2 === 0 && this.meta.colIndex > 0) {
+ return {
+ ...defaultTextStyle,
+ fontSize: 16,
+ fill: '#396',
+ textAlign: 'left',
+ };
+ }
+
+ // 指定数据
+ if (this.meta.fieldValue >= 600 || this.meta.fieldValue === '沙发') {
+ return {
+ ...defaultTextStyle,
+ fontSize: 14,
+ fontWeight: 700,
+ fill: '#f63',
+ textAlign: 'center',
+ };
+ }
+
+ // 指定单元格
+ if (this.meta.id === '7-root[&]省份') {
+ return {
+ ...defaultTextStyle,
+ fontSize: 12,
+ fontWeight: 200,
+ fill: '#dcdcdc',
+ opacity: 0.9,
+ textAlign: 'right',
+ };
+ }
+
+ // 使用默认处理
+ return super.getTextStyle();
+ }
+}
+
+/**
+ * 自定义 ColCell, 通过复写基类方法, 给特定单元格设置文字大小, 颜色等...
+ * 查看更多方法 https://github.com/antvis/S2/blob/master/packages/s2-core/src/cell/table-col-cell.ts
+ */
+class CustomColCell extends TableColCell {
+ getTextStyle() {
+ const defaultTextStyle = super.getTextStyle();
+
+ // 指定列
+ if (this.meta.colIndex % 2 === 0) {
+ return {
+ ...defaultTextStyle,
+ fontSize: 16,
+ fill: '#396',
+ textAlign: 'left',
+ };
+ }
+
+ // 指定层级
+ if (this.meta.level >= 0) {
+ return {
+ ...defaultTextStyle,
+ fill: 'pink',
+ textAlign: 'center',
+ };
+ }
+
+ // 指定文本
+ if (this.meta.label === '子类别') {
+ return {
+ ...defaultTextStyle,
+ fontSize: 22,
+ textAlign: 'right',
+ };
+ }
+
+ // 使用默认处理
+ return super.getTextStyle();
+ }
+}
+
+fetch(
+ 'https://gw.alipayobjects.com/os/bmw-prod/cd9814d0-6dfa-42a6-8455-5a6bd0ff93ca.json',
+)
+ .then((res) => res.json())
+ .then((res) => {
+ const container = document.getElementById('container');
+ const s2DataConfig = {
+ fields: {
+ columns: ['province', 'city', 'type', 'sub_type', 'number'],
+ },
+ meta: res.meta,
+ data: res.data,
+ };
+ const s2Options = {
+ width: 600,
+ height: 480,
+ showSeriesNumber: true,
+ colCell: (node, spreadsheet, headerConfig) => {
+ return new CustomColCell(node, spreadsheet, headerConfig);
+ },
+ dataCell: (viewMeta) => {
+ return new CustomDataCell(viewMeta, viewMeta?.spreadsheet);
+ },
+ };
+ const s2 = new TableSheet(container, s2DataConfig, s2Options);
+
+ s2.render();
+ });
diff --git a/s2-site/examples/custom/custom-cell/demo/data-cell-placeholder.ts b/s2-site/examples/custom/custom-cell/demo/data-cell-placeholder.ts
new file mode 100644
index 0000000000..b61659a5d8
--- /dev/null
+++ b/s2-site/examples/custom/custom-cell/demo/data-cell-placeholder.ts
@@ -0,0 +1,42 @@
+import { PivotSheet, CornerCell } from '@antv/s2';
+
+fetch(
+ 'https://gw.alipayobjects.com/os/bmw-prod/cd9814d0-6dfa-42a6-8455-5a6bd0ff93ca.json',
+)
+ .then((res) => res.json())
+ .then((res) => {
+ const container = document.getElementById('container');
+ const s2DataConfig = {
+ fields: {
+ rows: ['province', 'city'],
+ columns: ['type', 'sub_type'],
+ values: ['number'],
+ },
+ meta: res.meta,
+ data: res.data.map((item, i) => {
+ return {
+ ...item,
+ number: i < 5 ? item.number : null,
+ };
+ }),
+ };
+ const s2Options = {
+ width: 600,
+ height: 480,
+ // 默认 "-"
+ // placeholder: '',
+ placeholder: (cell) => {
+ // 或者根据当前单元格动态设置
+ console.log('cell: ', cell);
+ if (cell.cellType === 'dataCell') {
+ return '*****';
+ }
+
+ // 返回 null, 使用默认值 ("-")
+ return null;
+ },
+ };
+ const s2 = new PivotSheet(container, s2DataConfig, s2Options);
+
+ s2.render();
+ });
diff --git a/s2-site/examples/custom/custom-cell/demo/data-cell.ts b/s2-site/examples/custom/custom-cell/demo/data-cell.ts
index 8a93ca9805..dc936cfeb0 100644
--- a/s2-site/examples/custom/custom-cell/demo/data-cell.ts
+++ b/s2-site/examples/custom/custom-cell/demo/data-cell.ts
@@ -1,5 +1,4 @@
-import { PivotSheet, DataCell, drawObjectText } from '@antv/s2';
-import { isObject } from 'lodash';
+import { DataCell, PivotSheet } from '@antv/s2';
/**
* 自定义 DataCell,给数值单元格添加背景图
@@ -15,15 +14,6 @@ class CustomDataCell extends DataCell {
},
});
}
-
- // 当配置对象时,完全接管绘制(实现趋势表的mini图功能)
- protected drawTextShape() {
- if (isObject(this.getMeta().fieldValue)) {
- drawObjectText(this);
- } else {
- super.drawTextShape();
- }
- }
}
fetch(
@@ -39,28 +29,7 @@ fetch(
values: ['number'],
},
meta: res.meta,
- data: [
- ...res.data,
- // 用于绘制 mini 图的数据
- {
- province: '海南省',
- city: '三亚市',
- type: '家具',
- sub_type: '桌子',
- number: {
- values: {
- type: 'line',
- data: [
- { date: '周一', value: 110 },
- { date: '周二', value: 150 },
- { date: '周三', value: 90 },
- { date: '周三', value: 190 },
- ],
- encode: { x: 'date', y: 'value' },
- },
- },
- },
- ],
+ data: res.data,
};
const s2Options = {
@@ -75,6 +44,5 @@ fetch(
};
const s2 = new PivotSheet(container, s2DataConfig, s2Options);
- // 使用
s2.render();
});
diff --git a/s2-site/examples/custom/custom-cell/demo/meta.json b/s2-site/examples/custom/custom-cell/demo/meta.json
index cc500816a2..0da90cfb49 100644
--- a/s2-site/examples/custom/custom-cell/demo/meta.json
+++ b/s2-site/examples/custom/custom-cell/demo/meta.json
@@ -58,7 +58,7 @@
"zh": "自定义特定单元格",
"en": "custom specified cell"
},
- "screenshot": "https://gw.alipayobjects.com/mdn/rms_56cbb2/afts/img/A*KJqYQKjxIwIAAAAAAAAAAAAAARQnAQ"
+ "screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*GSh4R6qdC5IAAAAAAAAAAAAADmJ7AQ/original"
},
{
"filename": "custom-merged-cell.ts",
@@ -67,6 +67,30 @@
"en": "custom merged cell"
},
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*B7mTTZYFjv8AAAAAAAAAAAAADmJ7AQ/original"
+ },
+ {
+ "filename": "custom-table-cell.ts",
+ "title": {
+ "zh": "自定义明细表单元格",
+ "en": "custom table cell"
+ },
+ "screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*-uLETb4gK9AAAAAAAAAAAAAADmJ7AQ/original"
+ },
+ {
+ "filename": "mini-chart.ts",
+ "title": {
+ "zh": "自定义 mini 图",
+ "en": "custom mini chart"
+ },
+ "screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*apnIT4KXP3YAAAAAAAAAAAAADmJ7AQ/original"
+ },
+ {
+ "filename": "data-cell-placeholder.ts",
+ "title": {
+ "zh": "自定义空数据单元格占位符",
+ "en": "custom cell placeholder"
+ },
+ "screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*B-VMT7kCWL0AAAAAAAAAAAAADmJ7AQ/original"
}
]
}
diff --git a/s2-site/examples/custom/custom-cell/demo/mini-chart.ts b/s2-site/examples/custom/custom-cell/demo/mini-chart.ts
new file mode 100644
index 0000000000..ee007fa585
--- /dev/null
+++ b/s2-site/examples/custom/custom-cell/demo/mini-chart.ts
@@ -0,0 +1,178 @@
+import { PivotSheet, DataCell, drawObjectText } from '@antv/s2';
+import { isArray, isObject } from 'lodash';
+
+/**
+ * 自定义 DataCell,使用 drawObjectText 绘制简易的 mini 图
+ * 查看更多方法 https://github.com/antvis/S2/blob/master/packages/s2-core/src/cell/data-cell.ts
+ */
+class CustomDataCell extends DataCell {
+ // 当数值为对象时,完全接管绘制, 使用内置的 `drawObjectText` 根据不同的数据结构 (见下方) 绘制不同的图形
+ drawTextShape() {
+ const { fieldValue } = this.getMeta();
+
+ if (isObject(fieldValue) || isArray(fieldValue)) {
+ drawObjectText(this);
+ return;
+ }
+
+ super.drawTextShape();
+ }
+}
+
+fetch(
+ 'https://gw.alipayobjects.com/os/bmw-prod/cd9814d0-6dfa-42a6-8455-5a6bd0ff93ca.json',
+)
+ .then((res) => res.json())
+ .then((res) => {
+ const container = document.getElementById('container')!;
+ const s2DataConfig = {
+ fields: {
+ rows: ['province', 'city'],
+ columns: ['type', 'sub_type'],
+ values: ['number'],
+ },
+ meta: res.meta,
+ data: [
+ // 用于绘制 mini 图的数据, 数据结构请查阅: https://s2.antv.antgroup.com/manual/basic/analysis/strategy#%E9%85%8D%E7%BD%AE-mini-%E5%9B%BE
+ {
+ province: '海南省',
+ city: '三亚市',
+ type: '家具',
+ sub_type: '桌子',
+ number: {
+ // 折线图
+ values: {
+ type: 'line',
+ data: [
+ {
+ year: '2017',
+ value: -368,
+ },
+ {
+ year: '2018',
+ value: 368,
+ },
+ {
+ year: '2019',
+ value: 368,
+ },
+ {
+ year: '2020',
+ value: 368,
+ },
+ {
+ year: '2021',
+ value: 268,
+ },
+ {
+ year: '2022',
+ value: 168,
+ },
+ ],
+ encode: { x: 'year', y: 'value' },
+ },
+ },
+ },
+ {
+ province: '海南省',
+ city: '三亚市',
+ type: '家具',
+ sub_type: '沙发',
+ number: {
+ // 柱状图
+ values: {
+ type: 'bar',
+ data: [
+ {
+ year: '2017',
+ value: -368,
+ },
+ {
+ year: '2018',
+ value: 328,
+ },
+ {
+ year: '2019',
+ value: 38,
+ },
+ {
+ year: '2020',
+ value: 168,
+ },
+ {
+ year: '2021',
+ value: 268,
+ },
+ {
+ year: '2022',
+ value: 368,
+ },
+ ],
+ encode: { x: 'year', y: 'value' },
+ },
+ },
+ },
+ {
+ province: '海南省',
+ city: '三亚市',
+ type: '办公用品',
+ sub_type: '笔',
+ number: {
+ // 多列文本
+ values: [
+ [3877, -4324, '42%'],
+ [3877, 4324, '-42%'],
+ ],
+ },
+ },
+ {
+ province: '海南省',
+ city: '三亚市',
+ type: '办公用品',
+ sub_type: '纸张',
+ number: {
+ // 子弹图
+ values: {
+ measure: 0.3,
+ target: 0.76,
+ },
+ },
+ },
+ ...res.data,
+ ],
+ };
+
+ const s2Options = {
+ width: 1000,
+ height: 680,
+ style: {
+ cellCfg: {
+ height: 40,
+ },
+ },
+ conditions: {
+ text: [
+ {
+ field: 'number',
+ mapping: (value, cellInfo) => {
+ const { meta, colIndex } = cellInfo || {};
+ if (colIndex === 0 || !value || !meta?.fieldValue) {
+ return {
+ fill: '#000',
+ };
+ }
+ return {
+ fill: value > 0 ? '#FF4D4F' : '#29A294',
+ };
+ },
+ },
+ ],
+ },
+ dataCell: (viewMeta) => {
+ return new CustomDataCell(viewMeta, viewMeta?.spreadsheet);
+ },
+ };
+ const s2 = new PivotSheet(container, s2DataConfig, s2Options);
+
+ s2.render();
+ });
diff --git a/s2-site/examples/custom/custom-cell/demo/totals-cell.ts b/s2-site/examples/custom/custom-cell/demo/totals-cell.ts
index e716f275d2..5c140c1f7c 100644
--- a/s2-site/examples/custom/custom-cell/demo/totals-cell.ts
+++ b/s2-site/examples/custom/custom-cell/demo/totals-cell.ts
@@ -1,7 +1,7 @@
import { PivotSheet, RowCell, renderRect } from '@antv/s2';
/**
- * 继承 RowCell, 单独修改小计/总计的背景色和文字颜色
+ * 继承 RowCell, 单独修改行小计/行总计的背景色和文字颜色 (继承 ColCell, 列小计/列总计 同理)
* 查看更多方法 https://github.com/antvis/S2/blob/master/packages/s2-core/src/cell/row-cell.ts
*/
class CustomTotalsRowCell extends RowCell {
diff --git a/s2-site/examples/custom/custom-layout/demo/custom-coordinate.ts b/s2-site/examples/custom/custom-layout/demo/custom-coordinate.ts
index a4e721a4f1..0df1e0189b 100644
--- a/s2-site/examples/custom/custom-layout/demo/custom-coordinate.ts
+++ b/s2-site/examples/custom/custom-layout/demo/custom-coordinate.ts
@@ -13,6 +13,28 @@ fetch(
values: ['number'],
},
data: res.data,
+ meta: [
+ {
+ field: 'number',
+ name: '数量',
+ },
+ {
+ field: 'province',
+ name: '省份',
+ },
+ {
+ field: 'city',
+ name: '城市',
+ },
+ {
+ field: 'type',
+ name: '类别',
+ },
+ {
+ field: 'sub_type',
+ name: '子类别',
+ },
+ ],
};
const s2Options = {
diff --git a/s2-site/examples/custom/custom-layout/demo/custom-data-position.ts b/s2-site/examples/custom/custom-layout/demo/custom-data-position.ts
index 2ca7fa1f57..fa7c5460c0 100644
--- a/s2-site/examples/custom/custom-layout/demo/custom-data-position.ts
+++ b/s2-site/examples/custom/custom-layout/demo/custom-data-position.ts
@@ -13,6 +13,28 @@ fetch(
values: ['number'],
},
data: res.data,
+ meta: [
+ {
+ field: 'number',
+ name: '数量',
+ },
+ {
+ field: 'province',
+ name: '省份',
+ },
+ {
+ field: 'city',
+ name: '城市',
+ },
+ {
+ field: 'type',
+ name: '类别',
+ },
+ {
+ field: 'sub_type',
+ name: '子类别',
+ },
+ ],
};
const s2Options = {
diff --git a/s2-site/examples/custom/custom-layout/demo/custom-layout-arrange.ts b/s2-site/examples/custom/custom-layout/demo/custom-layout-arrange.ts
index 26f8249c57..b233076ca5 100644
--- a/s2-site/examples/custom/custom-layout/demo/custom-layout-arrange.ts
+++ b/s2-site/examples/custom/custom-layout/demo/custom-layout-arrange.ts
@@ -13,6 +13,28 @@ fetch(
values: ['number'],
},
data: res.data,
+ meta: [
+ {
+ field: 'number',
+ name: '数量',
+ },
+ {
+ field: 'province',
+ name: '省份',
+ },
+ {
+ field: 'city',
+ name: '城市',
+ },
+ {
+ field: 'type',
+ name: '类别',
+ },
+ {
+ field: 'sub_type',
+ name: '子类别',
+ },
+ ],
};
const s2Options = {
diff --git a/s2-site/examples/custom/custom-layout/demo/custom-layout-hierarchy.ts b/s2-site/examples/custom/custom-layout/demo/custom-layout-hierarchy.ts
index bd0fc3e70c..746ec39187 100644
--- a/s2-site/examples/custom/custom-layout/demo/custom-layout-hierarchy.ts
+++ b/s2-site/examples/custom/custom-layout/demo/custom-layout-hierarchy.ts
@@ -45,6 +45,28 @@ fetch(
},
],
],
+ meta: [
+ {
+ field: 'number',
+ name: '数量',
+ },
+ {
+ field: 'province',
+ name: '省份',
+ },
+ {
+ field: 'city',
+ name: '城市',
+ },
+ {
+ field: 'type',
+ name: '类别',
+ },
+ {
+ field: 'sub_type',
+ name: '子类别',
+ },
+ ],
};
const s2Options = {
diff --git a/s2-site/examples/custom/custom-layout/demo/custom-value-order.ts b/s2-site/examples/custom/custom-layout/demo/custom-value-order.ts
index ba02eedb84..1bd014dc1c 100644
--- a/s2-site/examples/custom/custom-layout/demo/custom-value-order.ts
+++ b/s2-site/examples/custom/custom-layout/demo/custom-value-order.ts
@@ -16,6 +16,28 @@ fetch(
customValueOrder: 1,
},
data: res.data,
+ meta: [
+ {
+ field: 'number',
+ name: '数量',
+ },
+ {
+ field: 'province',
+ name: '省份',
+ },
+ {
+ field: 'city',
+ name: '城市',
+ },
+ {
+ field: 'type',
+ name: '类别',
+ },
+ {
+ field: 'sub_type',
+ name: '子类别',
+ },
+ ],
};
const s2Options = {
diff --git a/s2-site/examples/layout/adaptive/demo/react-adaptive.tsx b/s2-site/examples/layout/adaptive/demo/react-adaptive.tsx
index f89d279ec9..8133f86da9 100644
--- a/s2-site/examples/layout/adaptive/demo/react-adaptive.tsx
+++ b/s2-site/examples/layout/adaptive/demo/react-adaptive.tsx
@@ -1,7 +1,6 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { SheetComponent } from '@antv/s2-react';
-import { concat, debounce, forEach, map } from 'lodash';
fetch(
'https://gw.alipayobjects.com/os/bmw-prod/2a5dbbc8-d0a7-4d02-b7c9-34f6ca63cff6.json',
@@ -13,13 +12,16 @@ fetch(
height: 480,
};
-
ReactDOM.render(
- document.getElementById('container')
- }} />,
+ getContainer: () => document.getElementById('container'),
+ }}
+ />,
document.getElementById('container'),
);
});
diff --git a/s2-site/examples/layout/basic/demo/adaptive.ts b/s2-site/examples/layout/basic/demo/adaptive.ts
new file mode 100644
index 0000000000..e63fdb9be5
--- /dev/null
+++ b/s2-site/examples/layout/basic/demo/adaptive.ts
@@ -0,0 +1,21 @@
+import { PivotSheet } from '@antv/s2';
+
+fetch(
+ 'https://gw.alipayobjects.com/os/bmw-prod/2a5dbbc8-d0a7-4d02-b7c9-34f6ca63cff6.json',
+)
+ .then((res) => res.json())
+ .then((dataCfg) => {
+ const container = document.getElementById('container');
+
+ const s2Options = {
+ width: 600,
+ height: 480,
+ style: {
+ // 了解更多: https://s2.antv.antgroup.com/api/general/s2-options#style
+ layoutWidthType: 'adaptive',
+ },
+ };
+ const s2 = new PivotSheet(container, dataCfg, s2Options);
+
+ s2.render();
+ });
diff --git a/s2-site/examples/layout/basic/demo/colAdaptive.ts b/s2-site/examples/layout/basic/demo/colAdaptive.ts
index a8c54becc5..6c37ca45da 100644
--- a/s2-site/examples/layout/basic/demo/colAdaptive.ts
+++ b/s2-site/examples/layout/basic/demo/colAdaptive.ts
@@ -11,6 +11,7 @@ fetch(
width: 600,
height: 480,
style: {
+ // 了解更多: https://s2.antv.antgroup.com/api/general/s2-options#style
layoutWidthType: 'colAdaptive',
},
};
diff --git a/s2-site/examples/layout/basic/demo/compact.ts b/s2-site/examples/layout/basic/demo/compact.ts
index bf1b9ce198..408058793c 100644
--- a/s2-site/examples/layout/basic/demo/compact.ts
+++ b/s2-site/examples/layout/basic/demo/compact.ts
@@ -5,16 +5,32 @@ fetch(
)
.then((res) => res.json())
.then((dataCfg) => {
+ // 增加几条长度不一致的 mock 数据
+ dataCfg.data.at(0).number = 11111111;
+ dataCfg.data.at(6).number = 7777;
+ dataCfg.data.at(-1).number = 666666;
+
const container = document.getElementById('container');
const s2Options = {
- width: 400,
+ width: 600,
height: 480,
style: {
+ // 了解更多: https://s2.antv.antgroup.com/api/general/s2-options#style
layoutWidthType: 'compact',
},
};
+
const s2 = new PivotSheet(container, dataCfg, s2Options);
+ // 紧凑模式下, 列头宽度为实际内容宽度 (取当前列最大值, 采样每一列前 50 条数据)
+ s2.setTheme({
+ dataCell: {
+ text: {
+ fontSize: 16,
+ },
+ },
+ });
+
s2.render();
});
diff --git a/s2-site/examples/layout/basic/demo/meta.json b/s2-site/examples/layout/basic/demo/meta.json
index be75879383..7ac8996af1 100644
--- a/s2-site/examples/layout/basic/demo/meta.json
+++ b/s2-site/examples/layout/basic/demo/meta.json
@@ -4,13 +4,21 @@
"en": "Pivot"
},
"demos": [
+ {
+ "filename": "adaptive.ts",
+ "title": {
+ "zh": "行列等宽布局 (默认)",
+ "en": "Adaptive (Default)"
+ },
+ "screenshot": "https://gw.alipayobjects.com/zos/antfincdn/cEkDC%26g%24xj/df31b66d-4a76-4e69-be5a-f467af2d337d.png"
+ },
{
"filename": "compact.ts",
"title": {
"zh": "紧凑布局",
"en": "Compact"
},
- "screenshot": "https://gw.alipayobjects.com/zos/antfincdn/yzBFZaMMLH/55a2d580-1121-468e-9d0b-25f3e9ae25df.png"
+ "screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*NN_lTpAqhQkAAAAAAAAAAAAADmJ7AQ/original"
},
{
"filename": "colAdaptive.ts",
diff --git a/s2-site/examples/react-component/sheet/demo/strategy-mini-chart.tsx b/s2-site/examples/react-component/sheet/demo/strategy-mini-chart.tsx
index 5de2358db1..f4b2632e37 100644
--- a/s2-site/examples/react-component/sheet/demo/strategy-mini-chart.tsx
+++ b/s2-site/examples/react-component/sheet/demo/strategy-mini-chart.tsx
@@ -3,6 +3,11 @@ import ReactDOM from 'react-dom';
import { SheetComponent, SheetComponentOptions } from '@antv/s2-react';
import '@antv/s2-react/dist/style.min.css';
+/**
+ * 该示例为 React 版本的趋势分析表
+ * 如何在普通图表中使用, 请查看: https://s2.antv.antgroup.com/zh/examples/custom/custom-cell#mini-chart
+ */
+
fetch(
'https://gw.alipayobjects.com/os/bmw-prod/b942d973-7364-4fad-a10a-369426a61376.json',
)
diff --git a/s2-site/package.json b/s2-site/package.json
index 0bde635b0f..0d5394b618 100644
--- a/s2-site/package.json
+++ b/s2-site/package.json
@@ -28,14 +28,14 @@
"sync:s2-lock": "yarn upgrade @antv/s2 @antv/s2-react --latest"
},
"dependencies": {
- "@ant-design/icons": "^4.7.0",
- "@antv/dumi-theme-antv": "^0.3.5",
+ "@ant-design/icons": "^4.8.1",
+ "@antv/dumi-theme-antv": "^0.3.20",
"@antv/g-canvas": "^0.5.12",
- "@antv/s2": "^1.42.0",
- "@antv/s2-react": "^1.37.0",
- "antd": "^4.24.1",
- "copy-to-clipboard": "^3.3.1",
- "dumi": "^2.0.3",
+ "@antv/s2": "^1.51.2",
+ "@antv/s2-react": "^1.44.1",
+ "antd": "^4.24.14",
+ "copy-to-clipboard": "^3.3.3",
+ "dumi": "^2.2.14",
"gh-pages": "^3.1.0",
"lodash": "^4.17.21",
"react-color": "^2.19.3"
diff --git a/s2-site/public/site.css b/s2-site/public/site.css
index 9c282610b2..bbe2cc2b58 100644
--- a/s2-site/public/site.css
+++ b/s2-site/public/site.css
@@ -18,6 +18,10 @@
margin: 20px 0;
}
+.dumi-default-table {
+ margin: 0;
+}
+
img[alt='preview'] {
margin: 10px 0;
}