xiaodao-spreader 0.1.44 → 0.1.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ZH.md +60 -7
- package/README.md +60 -7
- package/dist/style.css +1 -1
- package/dist/types/components/spreader/components/dropdown.vue.d.ts +3 -0
- package/dist/types/components/spreader/components/find-replace-bar.vue.d.ts +1 -0
- package/dist/types/components/spreader/components/pickers/conditional-format-manager.vue.d.ts +2 -0
- package/dist/types/components/spreader/components/pickers/conditional-format-rule-editor.vue.d.ts +2 -0
- package/dist/types/components/spreader/components/pickers/data-validation-dialog.vue.d.ts +2 -0
- package/dist/types/components/spreader/components/pickers/insert-function-dialog.vue.d.ts +2 -0
- package/dist/types/components/spreader/components/pickers/number-format-dialog.vue.d.ts +2 -0
- package/dist/types/components/spreader/components/pickers/sort-confirm-dialog.vue.d.ts +2 -0
- package/dist/types/components/spreader/components/spreader.vue.d.ts +5 -0
- package/dist/types/components/spreader/components/tabbar.vue.d.ts +2 -0
- package/dist/types/components/spreader/components/toolbar.vue.d.ts +2 -0
- package/dist/types/components/spreader/composables/core-state.d.ts +5 -0
- package/dist/xiaodao-spreader.es.js +7797 -7558
- package/dist/xiaodao-spreader.umd.js +9 -9
- package/package.json +70 -72
package/README.ZH.md
CHANGED
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
- **行列分组与折叠**: 类 Excel 的行/列分组(Outline)。选中整行或整列后,工具栏「分组」下拉(位于排序与筛选之间)提供添加分组 / 取消分组 / 清除分组 / 全部展开 / 全部折叠,直接作用于选中轴;行/列右键菜单提供同构的「分组」子菜单。仅支持一层、互不相交的分组,嵌套或部分重叠会被校验拒绝并提示。分组区间在行号/列号带用交替背景色区分,± 折叠按钮浮动于表头带内,不占用独立 gutter。折叠的行/列不参与内容绘制;插入/删除行列时分组范围自动平移、被清空的分组自动删除。分组状态按工作表持久化(`rowOutlines` / `columnOutlines`),增删与折叠均接入撤销/重做。*见 [行列分组与折叠](#行列分组与折叠)*
|
|
39
39
|
- **单元格批注**: 类 Excel 的单元格批注(Note/Comment)。右键菜单新建 / 编辑 / 删除;单元格右上角红色三角指示器标识含批注;hover 悬停查看、点按编辑;批注独立于单元格值与样式,采用 Note Pool 存储(Sheet 级 notes 池 + cell.noteId 引用),便于排序 / 插入删除时随 cell 一起移动。批注支持多行文本、可选作者、创建 / 修改时间。可通过 `noteAuthor` prop 设置当前作者名。*见 [单元格批注](#单元格批注)*
|
|
40
40
|
- **自动填充(填充柄)**: 类 Excel 的活动选区右下角填充柄,按住向上/下/左/右拖拽即可填充单元格:单值复制、数字/日期/文本数字自动续序列(如 `1,2 → 3,4,5`)、公式引用按相对/绝对/混合规则平移(如 `=A1*2 → =A2*2`)、源 `styleId` 经样式池复用。拖拽期间实时预览、边缘自动滚动、动态扩展工作表、冻结窗格兼容、单次拖拽仅产生一个撤销步骤,*见 [自动填充](#自动填充)*
|
|
41
|
+
- **只读模式**: `editable` prop(默认 `true`)一键切换:`false` 时禁止一切数据/格式修改(编辑、粘贴剪切、删除、填充、行列增删调整、排序筛选、CF/DV/批注、合并边框、冻结、格式刷、替换等),只读下编辑类控件(toolbar、右键菜单、对话框确认/插入按钮、公式栏、查找替换栏)真实禁用,保留选中、滚动、复制、查找定位与查看能力。分层守卫纵深防御(UI disabled → 事件闸门 → handler → 底层 mutation),运行时切换立即生效且不污染 undo 历史,*见 [只读模式](#只读模式read-only)*
|
|
41
42
|
|
|
42
43
|
### 交互体验
|
|
43
44
|
|
|
@@ -145,9 +146,38 @@ const myData = ref<SheetModelData[]>([
|
|
|
145
146
|
| `theme` | `'light' \| 'dark'` | `'light'` | 主题模式 |
|
|
146
147
|
| `locale` | `string` | `'zh-CN'` | 语言: `'zh-CN'` \| `'en-US'` |
|
|
147
148
|
| `noteAuthor` | `string` | `''`(空串,显示时回退为 i18n 占位符「未命名」) | 当前批注作者名;为空时存入批注的 author 字段为空字符串,显示时回退为 i18n 占位符 |
|
|
149
|
+
| `editable` | `boolean` | `true` | 是否允许编辑;`false` 进入只读模式(详见 [只读模式](#只读模式read-only)) |
|
|
148
150
|
|
|
149
151
|
---
|
|
150
152
|
|
|
153
|
+
## 只读模式(Read-only)
|
|
154
|
+
|
|
155
|
+
通过 `editable` prop 可将组件切换为只读展示(默认 `true`,即完全可编辑)。`editable={false}` 时:
|
|
156
|
+
|
|
157
|
+
- **禁止一切修改**:单元格编辑与直接输入、粘贴 / 剪切 / 删除、填充柄、行 / 列增删与宽高调整、排序与筛选、条件格式、数据验证、批注增删改、合并单元格、边框、字体 / 对齐 / 背景 / 文字颜色、数字格式、格式刷、冻结窗格、查找替换、撤销 / 重做均被拦截。
|
|
158
|
+
- **保留查看能力**:选中与多选区、滚动、冻结查看、复制、单元格内容 / 格式 / 批注查看、查找定位(上一条 / 下一条)不受影响。
|
|
159
|
+
- **UI 与逻辑一致**:所有编辑类控件(toolbar 按钮与下拉、右键菜单项、对话框确认 / 插入按钮、公式栏按钮、查找替换栏按钮与「替换为」输入框)在只读下真实禁用或只读;切到只读的瞬间,已打开的编辑浮层与对话框自动关闭,不会出现「按钮看起来能点、点了没反应」。
|
|
160
|
+
- **纵深防御**:守卫分四层——① UI `:disabled` / readonly(体验层)→ ② toolbar emit 闸门与事件拦截 → ③ 处理函数首行守卫 → ④ 底层 mutation 守卫(终极防线)。仅靠 DevTools 删除 HTML 的 `disabled` 属性无法绕过,数据不可能被改写;只读下不产生任何 undo 快照,undo 历史不被污染。
|
|
161
|
+
- **运行时切换即时生效**,无需重挂组件;`v-model` 数据与格式不被改动,切回可编辑后一切如常。
|
|
162
|
+
|
|
163
|
+
```vue
|
|
164
|
+
<template>
|
|
165
|
+
<button @click="editable = !editable">
|
|
166
|
+
{{ editable ? '切换为只读' : '切换为可编辑' }}
|
|
167
|
+
</button>
|
|
168
|
+
<Spreader v-model:data="myData" :editable="editable" />
|
|
169
|
+
</template>
|
|
170
|
+
|
|
171
|
+
<script setup lang="ts">
|
|
172
|
+
import { ref } from 'vue';
|
|
173
|
+
import Spreader from 'xiaodao-spreader';
|
|
174
|
+
import type { SheetModelData } from 'xiaodao-spreader';
|
|
175
|
+
|
|
176
|
+
const myData = ref<SheetModelData[]>([]);
|
|
177
|
+
const editable = ref(true);
|
|
178
|
+
</script>
|
|
179
|
+
```
|
|
180
|
+
|
|
151
181
|
## 数据模型
|
|
152
182
|
|
|
153
183
|
### `SheetModelData`
|
|
@@ -220,6 +250,7 @@ src/
|
|
|
220
250
|
└── components/
|
|
221
251
|
└── spreader/
|
|
222
252
|
├── index.ts # 统一导出口: 组件 + 类型(barrel)
|
|
253
|
+
├── theme.css # 全局主题样式表:--sp-* 变量(.spreadsheet-outer / .sp-spreader-overlay 作用域,light + dark 两套)
|
|
223
254
|
├── components/
|
|
224
255
|
│ ├── spreader.vue # 入口组件:模板 + 样式 + 组合
|
|
225
256
|
│ ├── toolbar.vue # 工具栏(带溢出下拉)
|
|
@@ -251,7 +282,7 @@ src/
|
|
|
251
282
|
│ ├── core-state.ts # Props、cells/merges/selection、字体度量、导航、行列分组状态
|
|
252
283
|
│ ├── find-replace.ts # 查找/替换状态与交互(依赖 Vue)
|
|
253
284
|
│ ├── interactions.ts # 渲染器、公式栏、标签栏、右键菜单、滚动条、事件
|
|
254
|
-
│ ├── sheets-ops.ts # 行列操作、多 Sheet、v-model emit
|
|
285
|
+
│ ├── sheets-ops.ts # 行列操作、多 Sheet、v-model emit、refs
|
|
255
286
|
│ ├── undo-styles.ts # 撤销/重做、格式刷、字体/对齐/颜色
|
|
256
287
|
│ └── float-menu-position.ts # 工具栏下拉菜单共享定位(右锚 + 上下翻向夹紧)
|
|
257
288
|
└── core/
|
|
@@ -274,7 +305,7 @@ src/
|
|
|
274
305
|
├── sort-core.ts # 排序纯算法(零 Vue 依赖,可单测)
|
|
275
306
|
├── sort-icon.ts # 排序图标单一数据源(toolbar + picker)
|
|
276
307
|
├── style-pool.ts # 样式池:去重、注册、解析、迁移、GC
|
|
277
|
-
├── theme.ts #
|
|
308
|
+
├── theme.ts # 主题类型与 light/dark 配色(canvas 用);buildOuterStyle 仅剩尺寸
|
|
278
309
|
├── types.ts # 全部类型定义
|
|
279
310
|
└── utils.ts # 纯工具函数(列标转换、命中测试等)
|
|
280
311
|
```
|
|
@@ -701,30 +732,51 @@ const lightTheme: ThemeColors = { /* 50+ 颜色字段 */ };
|
|
|
701
732
|
const darkTheme: ThemeColors = { /* 50+ 颜色字段 */ };
|
|
702
733
|
```
|
|
703
734
|
|
|
704
|
-
###
|
|
735
|
+
### 主题变量(`--sp-*`)与作用域
|
|
705
736
|
|
|
706
|
-
主题颜色通过 CSS 自定义属性(`--sp
|
|
737
|
+
主题颜色通过 CSS 自定义属性(`--sp-*`)注入,集中声明在组件样式表 `theme.css`:
|
|
707
738
|
|
|
708
739
|
```css
|
|
709
740
|
--sp-bg, --sp-gridBg, --sp-gridLine, --sp-selectionBg,
|
|
710
741
|
--sp-headerBg, --sp-headerBorder, --sp-headerText,
|
|
711
742
|
--sp-formulaBarBg, --sp-formulaBarInputBorder,
|
|
712
743
|
--sp-wrapperBg, --sp-cellEditorBorder,
|
|
713
|
-
/* ...
|
|
744
|
+
/* ... 以及更多(新增变量须同时提供 light 与 dark 两套取值) */
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
变量作用域收敛在组件子树内,不污染宿主页面:
|
|
748
|
+
|
|
749
|
+
- **light**:定义于 `.spreadsheet-outer, .sp-spreader-overlay`
|
|
750
|
+
- **dark**:定义于 `.spreadsheet-outer.dark, .sp-spreader-overlay.dark`,`theme="dark"` 时组件根与各 Teleport 浮层根自动挂 `.dark` 类,绝不读写 `<html>` 的全局类
|
|
751
|
+
|
|
752
|
+
由于下拉 / 对话框 / 右键菜单等浮层经 Teleport 挂到 `<body>` 下(脱离组件 DOM 树,无法从组件祖先继承变量),样式表将同一套变量同时声明在 `.spreadsheet-outer`(组件主体)与 `.sp-spreader-overlay`(浮层根)两个作用域。**消费方必须引入样式表**,否则所有组件样式(含浮层)都取不到主题变量:
|
|
753
|
+
|
|
754
|
+
```ts
|
|
755
|
+
import 'xiaodao-spreader/style.css';
|
|
714
756
|
```
|
|
715
757
|
|
|
758
|
+
另注:Canvas 内部绘制的网格 / 表头 / 选区配色不依赖 CSS 变量,而是由 `ThemeColors`(`lightTheme` / `darkTheme`)按 `theme` prop 直接选取。
|
|
759
|
+
|
|
716
760
|
### 自定义主题
|
|
717
761
|
|
|
718
|
-
传入 `theme="dark"`
|
|
762
|
+
传入 `theme="dark"` 启用暗色模式,或覆盖 `--sp-*` 变量实现完全自定义。变量挂在 `.spreadsheet-outer` 作用域上,覆盖主体时可用包装组件(后代级联),但要连同浮层一起覆盖则需同时写 `.sp-spreader-overlay`(浮层脱离组件树、不从包装组件继承),也可直接用 `theme.css` 同优先级规则覆盖:
|
|
719
763
|
|
|
720
764
|
```vue
|
|
721
765
|
<template>
|
|
722
766
|
<div style="--sp-bg: #1a1a2e; --sp-cellText: #e0e0e0;">
|
|
723
|
-
<Spreader v-model:data="myData"
|
|
767
|
+
<Spreader v-model:data="myData" />
|
|
724
768
|
</div>
|
|
725
769
|
</template>
|
|
726
770
|
```
|
|
727
771
|
|
|
772
|
+
```css
|
|
773
|
+
/* 覆盖 Teleport 浮层(下拉/对话框/右键菜单)时须用该选择器,仅覆盖组件根不够 */
|
|
774
|
+
.sp-spreader-overlay {
|
|
775
|
+
--sp-bg: #1a1a2e;
|
|
776
|
+
--sp-cellText: #e0e0e0;
|
|
777
|
+
}
|
|
778
|
+
```
|
|
779
|
+
|
|
728
780
|
### 国际化
|
|
729
781
|
|
|
730
782
|
内置语言:`'zh-CN'`、`'en-US'`。通过 `locale` 属性传入。右键菜单和工具栏标签自动本地化。
|
|
@@ -809,6 +861,7 @@ x-spreader 以触屏为第一交互:每个鼠标操作都有对称的触屏路
|
|
|
809
861
|
- [x] 自动筛选(AutoFilter):工具栏「筛选」/`Ctrl+Shift+L` 启用,表头下箭头、智能向下探测数据区、值/文本/数值/日期多类型筛选、清除单列与整体移除分离;见 [自动筛选(AutoFilter)](#自动筛选autofilter)
|
|
810
862
|
- [x] 触屏与移动端交互:选择 / 右键菜单 / 筛选 / 列宽行高 / 框选 / 格式刷 / tab 菜单均补齐对称触屏路径,浮层支持点外部关闭;见 [触屏与移动端交互](#触屏与移动端交互)
|
|
811
863
|
- [x] 单元格批注:Note Pool 存储、右键菜单 CRUD、hover 查看、编辑浮层、持久化与撤销;见 [单元格批注](#单元格批注)
|
|
864
|
+
- [x] 只读模式:`editable` prop 分层守卫,UI 与逻辑双重收口;见 [只读模式](#只读模式read-only)
|
|
812
865
|
- [ ] 打印布局
|
|
813
866
|
|
|
814
867
|
### 远期
|
package/README.md
CHANGED
|
@@ -37,6 +37,7 @@ A high-performance, canvas-based spreadsheet component for Vue 3: bringing an Ex
|
|
|
37
37
|
- **Cell Notes**: Excel-style cell notes (comments). Right-click menu to create / edit / delete; red triangle indicator at cell corner marks cells with notes; hover to preview, click to edit. Notes are independent from cell values and styles, stored via a Note Pool (Sheet-level notes pool + cell.noteId reference), so sort / insert-delete moves cells together with their notes. Notes support multi-line text, optional author, and create/update timestamps. Author name can be set via the noteAuthor prop. *see [Cell Notes](#cell-notes)*
|
|
38
38
|
- **Auto Fill (Fill Handle)**: Excel-style fill handle at the bottom-right corner of the active selection. Drag it up/down/left/right to fill cells: single values copy, number/date/text-number sequences auto-continue (e.g. `1,2 → 3,4,5`), formula references adjust per relative/absolute/mixed rules (e.g. `=A1*2` → `=A2*2`), and source `styleId` is reused via the style pool. Live preview during drag, edge auto-scroll, dynamic sheet expansion, freeze-pane compatibility, and a single undo step per operation: *see [Auto Fill](#auto-fill)*
|
|
39
39
|
- **Row / Column Grouping & Collapsing**: Excel-style row/column outlines. Select whole rows or columns, then the toolbar "Group" dropdown (between Sort and Filter) offers Add Group / Ungroup / Clear Outline / Expand All / Collapse All, applied directly to the selected axis; row/column context menus expose a matching "Group" submenu. Only one level of non-overlapping groups is supported - nesting and partial overlap are rejected with a message. Group ranges get alternating background colors in the row/column header band; ± collapse buttons float inside the header band without reserving a separate gutter. Collapsed rows/columns are skipped during content rendering; inserting/deleting rows or columns shifts group ranges and auto-removes emptied groups. Groups persist per-sheet (`rowOutlines` / `columnOutlines`) through v-model, and every mutation integrates with undo/redo. *see [Row / Column Grouping & Collapsing](#row--column-grouping--collapsing)*
|
|
40
|
+
- **Read-only Mode**: the `editable` prop (default `true`) toggles between full editing and a read-only view. With `editable={false}` every data / format mutation is blocked (editing, paste/cut/delete, fill, row/column insert & resize, sort/filter, CF/DV/notes, merge/borders, freeze panes, format painter, find & replace), all editing controls (toolbar, context menus, dialog confirm/insert buttons, formula bar, find & replace bar) are truly disabled, while selection, scrolling, copying, find-locate and viewing stay available. Guarding is layered (UI disabled → event gate → handler guard → underlying mutation guard) as defense in depth, runtime toggling takes effect immediately and never pollutes the undo history: *see [Read-only Mode](#read-only-mode)*
|
|
40
41
|
|
|
41
42
|
### Interaction
|
|
42
43
|
- **Smart Selection**: Click, drag, Shift+Click, row/column header select, corner-cell select-all
|
|
@@ -142,9 +143,38 @@ const myData = ref<SheetModelData[]>([
|
|
|
142
143
|
| `theme` | `'light' \| 'dark'` | `'light'` | Theme mode |
|
|
143
144
|
| `locale` | `string` | `'zh-CN'` | Language: `'zh-CN'` \| `'en-US'` |
|
|
144
145
|
| `noteAuthor` | `string` | `''` | Current note author name; when empty, saved notes have empty author field that renders as i18n placeholder |
|
|
146
|
+
| `editable` | `boolean` | `true` | Whether editing is allowed; `false` enters read-only mode (see [Read-only Mode](#read-only-mode)) |
|
|
145
147
|
|
|
146
148
|
---
|
|
147
149
|
|
|
150
|
+
## Read-only Mode
|
|
151
|
+
|
|
152
|
+
Pass the `editable` prop to switch the component into a read-only view (default `true`, i.e. fully editable). With `editable={false}`:
|
|
153
|
+
|
|
154
|
+
- **Every mutation is blocked**: cell editing and direct typing, paste / cut / delete, the fill handle, row / column insert & resize, sorting & filtering, conditional formatting, data validation, note add/edit/delete, merge cells, borders, font / alignment / fill / text color, number format, format painter, freeze panes, find & replace, and undo / redo.
|
|
155
|
+
- **Viewing stays available**: selection & multi-range selection, scrolling, frozen-pane viewing, copying, inspecting cell content / format / notes, and find navigation (previous / next) are unaffected.
|
|
156
|
+
- **UI stays consistent with logic**: every editing control (toolbar buttons & dropdowns, context-menu items, dialog confirm / insert buttons, formula-bar buttons, find & replace buttons and the "replace with" input) is truly disabled or read-only; the moment read-only is switched on, any open editing overlay or dialog closes automatically - no more "buttons look clickable but do nothing".
|
|
157
|
+
- **Defense in depth**: four guard layers - ① UI `:disabled` / readonly (UX) → ② toolbar emit gate & event interception → ③ guard at the top of each handler → ④ underlying mutation guards (last line of defense). Removing the HTML `disabled` attribute via DevTools cannot bypass the guards, so the data can never be rewritten; read-only never pushes undo snapshots, so the undo history stays unpolluted.
|
|
158
|
+
- **Runtime toggling takes effect immediately** without remounting; the `v-model` data and formatting are untouched and editing works as usual after switching back.
|
|
159
|
+
|
|
160
|
+
```vue
|
|
161
|
+
<template>
|
|
162
|
+
<button @click="editable = !editable">
|
|
163
|
+
{{ editable ? 'Switch to read-only' : 'Switch to editable' }}
|
|
164
|
+
</button>
|
|
165
|
+
<Spreader v-model:data="myData" :editable="editable" />
|
|
166
|
+
</template>
|
|
167
|
+
|
|
168
|
+
<script setup lang="ts">
|
|
169
|
+
import { ref } from 'vue';
|
|
170
|
+
import Spreader from 'xiaodao-spreader';
|
|
171
|
+
import type { SheetModelData } from 'xiaodao-spreader';
|
|
172
|
+
|
|
173
|
+
const myData = ref<SheetModelData[]>([]);
|
|
174
|
+
const editable = ref(true);
|
|
175
|
+
</script>
|
|
176
|
+
```
|
|
177
|
+
|
|
148
178
|
## Data Model
|
|
149
179
|
|
|
150
180
|
### `SheetModelData`
|
|
@@ -218,6 +248,7 @@ src/
|
|
|
218
248
|
└── components/
|
|
219
249
|
└── spreader/
|
|
220
250
|
├── index.ts # Unified export: component + types (barrel)
|
|
251
|
+
├── theme.css # Global theme stylesheet: --sp-* variables (.spreadsheet-outer / .sp-spreader-overlay scope, light + dark pairs)
|
|
221
252
|
├── components/
|
|
222
253
|
│ ├── spreader.vue # Entry component: template + style + composition
|
|
223
254
|
│ ├── toolbar.vue # Toolbar with overflow dropdown
|
|
@@ -249,7 +280,7 @@ src/
|
|
|
249
280
|
│ ├── core-state.ts # Props, cells/merges/selection, font metrics, navigation, outline state
|
|
250
281
|
│ ├── find-replace.ts # Find/replace state & interaction (Vue-dependent)
|
|
251
282
|
│ ├── interactions.ts # Renderer, formula bar, tab bar, context menu, scrollbar, events
|
|
252
|
-
│ ├── sheets-ops.ts # Row/col ops, multi-sheet, v-model emit,
|
|
283
|
+
│ ├── sheets-ops.ts # Row/col ops, multi-sheet, v-model emit, refs
|
|
253
284
|
│ ├── undo-styles.ts # Undo/redo, format painter, font/alignment/color
|
|
254
285
|
│ └── float-menu-position.ts # Shared toolbar dropdown positioning (right-anchor + flip/clamp)
|
|
255
286
|
└── core/
|
|
@@ -272,7 +303,7 @@ src/
|
|
|
272
303
|
├── sort-core.ts # Sort pure algorithms (zero Vue deps, unit-testable)
|
|
273
304
|
├── sort-icon.ts # Sort icon single source (toolbar + picker)
|
|
274
305
|
├── style-pool.ts # Style pool: dedup, registration, resolve, migration, GC
|
|
275
|
-
├── theme.ts # Theme
|
|
306
|
+
├── theme.ts # Theme types + light/dark palettes (for Canvas); buildOuterStyle now returns size only
|
|
276
307
|
├── types.ts # All type definitions
|
|
277
308
|
└── utils.ts # Pure utilities (column label, hit test, resolve size)
|
|
278
309
|
```
|
|
@@ -697,30 +728,51 @@ const lightTheme: ThemeColors = { /* 50+ color fields */ };
|
|
|
697
728
|
const darkTheme: ThemeColors = { /* 50+ color fields */ };
|
|
698
729
|
```
|
|
699
730
|
|
|
700
|
-
###
|
|
731
|
+
### Theme Variables (`--sp-*`) and Scope
|
|
701
732
|
|
|
702
|
-
Theme colors are injected via CSS custom properties (`--sp-*`)
|
|
733
|
+
Theme colors are injected via CSS custom properties (`--sp-*`), declared centrally in the component stylesheet `theme.css`:
|
|
703
734
|
|
|
704
735
|
```css
|
|
705
736
|
--sp-bg, --sp-gridBg, --sp-gridLine, --sp-selectionBg,
|
|
706
737
|
--sp-headerBg, --sp-headerBorder, --sp-headerText,
|
|
707
738
|
--sp-formulaBarBg, --sp-formulaBarInputBorder,
|
|
708
739
|
--sp-wrapperBg, --sp-cellEditorBorder,
|
|
709
|
-
/* ... and many more */
|
|
740
|
+
/* ... and many more (new variables must ship both light and dark values) */
|
|
741
|
+
```
|
|
742
|
+
|
|
743
|
+
Variable scope is confined to the component subtree so the host page is never polluted:
|
|
744
|
+
|
|
745
|
+
- **light**: declared on `.spreadsheet-outer, .sp-spreader-overlay`
|
|
746
|
+
- **dark**: declared on `.spreadsheet-outer.dark, .sp-spreader-overlay.dark`; when `theme="dark"` the component root and every teleported overlay root get a `.dark` class automatically - `<html>` globals are never touched
|
|
747
|
+
|
|
748
|
+
Because dropdowns / dialogs / context menus are teleported to `<body>` (outside the component DOM tree, so they cannot inherit variables from component ancestors), the stylesheet declares the same variable set on both `.spreadsheet-outer` (component body) and `.sp-spreader-overlay` (overlay roots). **Consumers must import the stylesheet**, otherwise every component style (including overlays) loses its theme variables:
|
|
749
|
+
|
|
750
|
+
```ts
|
|
751
|
+
import 'xiaodao-spreader/style.css';
|
|
710
752
|
```
|
|
711
753
|
|
|
754
|
+
Note: colors painted on the Canvas (grid, headers, selection) do not depend on CSS variables; they come from `ThemeColors` (`lightTheme` / `darkTheme`) picked by the `theme` prop.
|
|
755
|
+
|
|
712
756
|
### Custom Theme
|
|
713
757
|
|
|
714
|
-
Pass `theme="dark"` for dark mode, or
|
|
758
|
+
Pass `theme="dark"` for dark mode, or override `--sp-*` variables for full customization. The variables live on the `.spreadsheet-outer` scope, so a wrapper component can override the component body via descendant inheritance, but to cover teleported overlays as well you must also target `.sp-spreader-overlay` (overlays leave the component tree and do not inherit from the wrapper):
|
|
715
759
|
|
|
716
760
|
```vue
|
|
717
761
|
<template>
|
|
718
762
|
<div style="--sp-bg: #1a1a2e; --sp-cellText: #e0e0e0;">
|
|
719
|
-
<Spreader v-model:data="myData"
|
|
763
|
+
<Spreader v-model:data="myData" />
|
|
720
764
|
</div>
|
|
721
765
|
</template>
|
|
722
766
|
```
|
|
723
767
|
|
|
768
|
+
```css
|
|
769
|
+
/* Needed to restyle teleported overlays (dropdowns/dialogs/context menus); overriding only the component root is not enough */
|
|
770
|
+
.sp-spreader-overlay {
|
|
771
|
+
--sp-bg: #1a1a2e;
|
|
772
|
+
--sp-cellText: #e0e0e0;
|
|
773
|
+
}
|
|
774
|
+
```
|
|
775
|
+
|
|
724
776
|
### Internationalization
|
|
725
777
|
|
|
726
778
|
Built-in languages: `'zh-CN'`, `'en-US'`. Pass via `locale` prop. Right-click menus and toolbar labels are automatically localized.
|
|
@@ -805,6 +857,7 @@ x-spreader is touch-first: every mouse interaction has a symmetric touch path, v
|
|
|
805
857
|
- [x] Auto Filter (AutoFilter): toolbar "Filter" / `Ctrl+Shift+L` to enable, header drop-down arrows, intelligent downward data probing, value/text/number/date multi-type filters, separate clear-column vs remove-all; see [Auto Filter (AutoFilter)](#auto-filter-autofilter)
|
|
806
858
|
- [x] Touch & mobile interaction: symmetric touch paths for select / context menu / filter / resize / range select / format brush / tab menu; popups close on outside tap; see [Touch & Mobile Interaction](#touch--mobile-interaction)
|
|
807
859
|
- [x] Cell comments / notes: Note Pool storage, context-menu CRUD, hover preview, edit overlay, persistence & undo; see [Cell Notes](#cell-notes)
|
|
860
|
+
- [x] Read-only Mode: `editable` prop with layered guards, UI and logic both covered; see [Read-only Mode](#read-only-mode)
|
|
808
861
|
- [ ] Print layout
|
|
809
862
|
|
|
810
863
|
### Long-term
|