rj-grid 0.2.7 → 0.2.8

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_EN.md ADDED
@@ -0,0 +1,328 @@
1
+ <p align="center">
2
+ <img src="docs/images/01-overview.png" alt="rj-grid full feature overview" width="100%" />
3
+ </p>
4
+
5
+ <h1 align="center">rj-grid</h1>
6
+
7
+ <p align="center">
8
+ <b>An enterprise-grade Vue 3 data grid with zero third-party dependencies — every AG Grid feature, MIT licensed, ~110 KB gzip.</b><br/>
9
+ Virtual scrolling · pinned columns · grouping & pivoting · tree · undoable editing · formula engine · SSRM server-side row model · theming & i18n · print/CSV/Excel/PDF · offline natural-language query (NLQ)
10
+ </p>
11
+
12
+ <p align="center">
13
+ <a href="https://www.npmjs.com/package/rj-grid"><img src="https://img.shields.io/npm/v/rj-grid.svg?logo=npm&color=cb3837" alt="npm version"/></a>
14
+ <a href="https://github.com/rjding/rjGrid"><img src="https://img.shields.io/github/stars/rjding/rjGrid?logo=github&color=181717" alt="GitHub stars"/></a>
15
+ <a href="https://gitee.com/rjding/rj-grid"><img src="https://img.shields.io/badge/Gitee-rj--grid-orange?logo=gitee&logoColor=white" alt="Gitee mirror"/></a>
16
+ <a href="https://github.com/rjding/rjGrid/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License MIT"/></a>
17
+ <a href="https://gitee.com/rjding/rj-grid"><img src="https://img.shields.io/badge/third--party%20deps-0-blue.svg" alt="Zero dependencies"/></a>
18
+ <img src="https://img.shields.io/badge/gzip-~110KB-lightgrey.svg" alt="Bundle size"/>
19
+ <a href="https://vuejs.org/"><img src="https://img.shields.io/badge/vue-3.x-brightgreen.svg?logo=vuedotjs" alt="Vue 3"/></a>
20
+ <img src="https://img.shields.io/badge/tests-407%20passed-yellowgreen.svg" alt="Tests"/>
21
+ <img src="https://img.shields.io/badge/types-TypeScript-blue.svg?logo=typescript" alt="TypeScript"/>
22
+ </p>
23
+
24
+ <p align="center">
25
+ <a href="#-quick-start">Quick Start</a> ·
26
+ <a href="#-feature-showcase">Showcase</a> ·
27
+ <a href="#-vs-ag-grid">vs AG Grid</a> ·
28
+ <a href="docs/RjGrid_Manual_EN.md">Full Manual</a> ·
29
+ <a href="https://github.com/rjding/rjGrid">GitHub</a> ·
30
+ <a href="https://gitee.com/rjding/rj-grid">Gitee</a> ·
31
+ <a href="README.md">中文</a>
32
+ </p>
33
+
34
+ ---
35
+
36
+ ## 💡 Why rj-grid
37
+
38
+ Picture this: a single `<rj-grid>` tag that replaces those tables in your project that freeze past a few tens of thousands of rows, and that force you to swap libraries the moment you need grouping — all **without pulling in any third-party dependency** and without paying a license fee to a commercial grid vendor.
39
+
40
+ - **Truly zero-dependency**: the only runtime requirement is `vue`; even the optional charting is lazily `import('echarts')`. Nothing is bundled, nothing pollutes your lockfile.
41
+ - **Absurdly small**: ~110 KB gzip, yet it packs the combined feature set of several other libraries.
42
+ - **Silky at 100k rows**: two-way row/column virtual scrolling; 100,000 rows × 12 columns open instantly in practice (generation takes only ~12 ms).
43
+ - **AG Grid-parity features**: tree / grouping / pivoting / SSRM / formulas / theming / i18n / export / NLQ — all included.
44
+ - **Native TypeScript**: full type inference and `.d.ts`; editor autocompletion throughout — not a rough "make it work first" job.
45
+ - **Free for commercial use**: MIT license, safe for individuals and companies alike.
46
+
47
+ ---
48
+
49
+ ## ✨ Feature overview
50
+
51
+ | Category | What you get |
52
+ |---|---|
53
+ | Rendering | Row/column virtual scrolling (smooth at 100k rows), pinned columns, multi-level headers, three density levels, pinned rows, full-width rows; **single-click a cell to select its row** (`selectOnCellClick`, no checkbox needed) |
54
+ | Data | Four modes: client-side / pagination / infinite scroll / **SSRM server-side row model** (block cache on demand) |
55
+ | Grouping | Tree of arbitrary depth, drag-to-group, multi-level grouping + group footers, column pivoting (with a high-cardinality guardrail) |
56
+ | Editing | 8 editor types, validation, undo/redo, batched transaction back-fill, built-in add/edit row dialog |
57
+ | Formulas | Zero-dependency Excel-style formulas: `=B2*C2`, `SUM/COUNTIF/SUMIF`, range references, circular-reference detection |
58
+ | Filtering | Header funnel / floating filter row / quick search / advanced filter (cross-column AND/OR expression tree) — four layers stackable |
59
+ | Appearance | Theme engine (4 presets × light/dark × accent color × custom CSS variables), i18n (zh/en + text override), icon replacement |
60
+ | Output | Print / CSV / Excel / PDF, with three scopes: selected rows / current view / backend export; the four buttons can each be shown/hidden (`showPrint`/`showCsv`/`showPdf`/`showExcel`) |
61
+ | AI | Purely offline deterministic **NLQ**, bilingual and following i18n: Chinese like `数量大于50 按单价降序`, English like `qty > 50 sort by price desc`, with the readback matching the language |
62
+ | State | `stateKey` auto-persistence + programmatic `getState/setState`; your view survives a refresh |
63
+
64
+ ---
65
+
66
+ ## 🚀 Quick Start
67
+
68
+ > Three steps, two minutes, running.
69
+
70
+ **① Install**
71
+
72
+ ```bash
73
+ npm install rj-grid
74
+ # or pnpm add rj-grid / yarn add rj-grid
75
+ ```
76
+
77
+ **② Import the component and styles**
78
+
79
+ ```ts
80
+ // main.ts —— importing the stylesheet once globally is enough
81
+ import 'rj-grid/style.css'
82
+ ```
83
+
84
+ **③ Use it directly**
85
+
86
+ ```vue
87
+ <template>
88
+ <rj-grid :columns="cols" :rows="rows" row-key="id" :height="480" show-toolbar />
89
+ </template>
90
+
91
+ <script setup lang="ts">
92
+ import { RjGrid } from 'rj-grid' // ⚠️ must be a VALUE import, not `type` only
93
+ import type { RjColumn, RjRowData } from 'rj-grid'
94
+
95
+ const cols: RjColumn[] = [
96
+ { field: 'name', title: 'Name', width: 160, filter: 'text' },
97
+ { field: 'qty', title: 'Qty', type: 'num', aggFunc: 'sum' },
98
+ { field: 'price', title: 'Price', type: 'money', aggFunc: 'avg' }
99
+ ]
100
+ const rows: RjRowData[] = [
101
+ { id: 1, name: 'Bearing', qty: 100, price: 12.5 },
102
+ { id: 2, name: 'Motor', qty: 30, price: 480 }
103
+ ]
104
+ </script>
105
+ ```
106
+
107
+ Turn on `show-toolbar` and you instantly get pinned columns, grouping, filtering, export and column visibility — without writing another line of code. Want more? Just add a prop — full parameters for every feature are in the [📖 Manual](docs/RjGrid_Manual_EN.md).
108
+
109
+ ---
110
+
111
+ ## 🎬 Feature showcase
112
+
113
+ Real product screenshots/GIFs, all captured from the `playground` demo page:
114
+
115
+ <table>
116
+ <tr>
117
+ <td width="50%">
118
+ <b>🎨 Theme engine · 4 presets × light/dark × multi-language</b><br/>
119
+ <img src="docs/images/theme-cycle.gif" alt="Theme switching animation" width="100%"/>
120
+ </td>
121
+ <td width="50%">
122
+ <b>🤖 Offline natural-language query (NLQ)</b><br/>
123
+ Type a sentence; it applies filter + sort + grouping automatically.<br/>
124
+ <img src="docs/images/nlq-query.gif" alt="NLQ query animation" width="100%"/>
125
+ </td>
126
+ </tr>
127
+ <tr>
128
+ <td>
129
+ <b>🌲 Tree hierarchy · expand / collapse in one click</b><br/>
130
+ <img src="docs/images/tree-expand.gif" alt="Tree expand/collapse animation" width="100%"/>
131
+ </td>
132
+ <td>
133
+ <b>🔍 Quick filter · instant cross-column match highlighting</b><br/>
134
+ <img src="docs/images/quick-filter.gif" alt="Quick filter animation" width="100%"/>
135
+ </td>
136
+ </tr>
137
+ <tr>
138
+ <td>
139
+ <b>🧮 Formula engine · Excel-style, zero dependency</b><br/>
140
+ <img src="docs/images/15-formula.png" alt="Formula column" width="100%"/>
141
+ </td>
142
+ <td>
143
+ <b>📦 Built-in row edit / add dialog · form generated from column defs</b><br/>
144
+ <img src="docs/images/08-row-form.png" alt="Row dialog" width="100%"/>
145
+ </td>
146
+ </tr>
147
+ <tr>
148
+ <td>
149
+ <b>📊 Group aggregation + footers</b><br/>
150
+ <img src="docs/images/12-group.png" alt="Group aggregation" width="100%"/>
151
+ </td>
152
+ <td>
153
+ <b>⚡ 100k-row virtual scrolling · generation takes only ~12 ms</b><br/>
154
+ <img src="docs/images/10-perf-100k.png" alt="Big-data performance" width="100%"/>
155
+ </td>
156
+ </tr>
157
+ <tr>
158
+ <td>
159
+ <b>↕️ Row drag · drag the handle to reorder rows</b><br/>
160
+ <img src="docs/images/row-drag.gif" alt="Row drag animation" width="100%"/>
161
+ </td>
162
+ <td>
163
+ <b>⇄ Column drag · drag in the column menu's "Columns" tab to reorder (order changes live)</b><br/>
164
+ <img src="docs/images/col-drag.gif" alt="Column drag animation" width="100%"/>
165
+ </td>
166
+ </tr>
167
+ <tr>
168
+ <td colspan="2">
169
+ <b>➕ Dynamic query fields · get a configurable query bar with a single `queryable` prop</b><br/>
170
+ <img src="docs/images/query-field.gif" alt="Dynamic query field animation" width="100%"/>
171
+ </td>
172
+ </tr>
173
+ <tr>
174
+ <td width="50%">
175
+ <b>🔎 Server-side query + pagination · condition bar and pager on one row</b><br/>
176
+ <img src="docs/images/13-server-pagination.png" alt="Server-side query pagination" width="100%"/>
177
+ </td>
178
+ <td width="50%">
179
+ <b>☰ Three density levels · fit more on screen or go roomy and readable, switch freely</b><br/>
180
+ <img src="docs/images/21-density.png" alt="Display density switching" width="100%"/>
181
+ </td>
182
+ </tr>
183
+ <tr>
184
+ <td width="50%">
185
+ <b>💾 Save view · snapshot the current query/column layout/sorting in one click</b><br/>
186
+ <img src="docs/images/save-view.gif" alt="Save view animation" width="100%"/>
187
+ </td>
188
+ <td width="50%">
189
+ <b>▦ Tool panel · manage column visibility / grouping / pivoting by drag</b><br/>
190
+ <img src="docs/images/panel.gif" alt="Tool panel animation" width="100%"/>
191
+ </td>
192
+ </tr>
193
+ <tr>
194
+ <td colspan="2">
195
+ <b>🖨 Print / export · front-end (selected rows / current view) + backend export, three scopes</b><br/>
196
+ <img src="docs/images/print-export.gif" alt="Print/export scope animation" width="100%"/>
197
+ </td>
198
+ </tr>
199
+ </table>
200
+
201
+ ---
202
+
203
+ ## 🔍 vs AG Grid
204
+
205
+ | Aspect | rj-grid | AG Grid |
206
+ |---|---|---|
207
+ | License / cost | ✅ MIT, completely free | ⚠️ enterprise features need a commercial license |
208
+ | Third-party runtime deps | ✅ `vue` only | ⚠️ ships its own framework and module system |
209
+ | gzip size | ✅ ~110 KB | considerably larger |
210
+ | Native Vue 3 | ✅ value-import and use, not a wrapper | provides a Vue wrapper layer |
211
+ | Offline natural-language query | ✅ built-in deterministic NLQ | ❌ none |
212
+ | Virtual scroll / grouping / pivot / SSRM / formulas / theming / export | ✅ all built in | ✅ some behind the paid tier |
213
+
214
+ > rj-grid is not positioned as an "AG Grid clone" — it's a **free, lightweight, batteries-included**, high-quality option for Vue projects.
215
+
216
+ ---
217
+
218
+ ## 🧩 Data modes (pick as needed)
219
+
220
+ ```vue
221
+ <!-- Client-side: load everything into rows; sorting/filtering/grouping all run in the browser, virtual scrolling handles 100k rows -->
222
+ <rj-grid :columns="cols" :rows="rows" row-key="id" />
223
+
224
+ <!-- Pagination: backend-paged, loadData automatically carries sorting/filters/page number; pager position is set by pager-position -->
225
+ <rj-grid :columns="cols" data-mode="pagination" :load-data="loadData" :page-size="20" />
226
+
227
+ <!-- Infinite scroll: fetch the next block when scrolling to the bottom, no page numbers -->
228
+ <rj-grid :columns="cols" data-mode="infinite" :load-data="loadData" />
229
+
230
+ <!-- SSRM server-side row model: grouping / big-data block cache, load blocks on demand -->
231
+ <rj-grid :columns="cols" data-mode="serverSide" :load-data="loadData" server-side-grouping />
232
+ ```
233
+
234
+ ```ts
235
+ import type { RjLoadServerParams } from 'rj-grid'
236
+ // params automatically include start/end/page/pageSize/sort/filters/quickFilterText/rowGroup… — pass them straight to the backend
237
+ async function loadData(p: RjLoadServerParams) {
238
+ const res = await api.queryPage(p)
239
+ return { rows: res.list, total: res.total, success: true }
240
+ }
241
+ ```
242
+
243
+ Full configuration and callback signatures for each mode are in [Manual §6 Data modes](docs/RjGrid_Manual_EN.md).
244
+
245
+ ---
246
+
247
+ ## 🛠 Compatibility & tech stack
248
+
249
+ - **Framework**: Vue `^3.4.0` (the only required peer dependency)
250
+ - **Optional**: `echarts >= 5.0.0` (used only by the "integrated chart" dialog; degrades gracefully when not installed, without crashing the page)
251
+ - **Language**: fully typed TypeScript, `.d.ts` shipped with the package
252
+ - **Styles**: a single `rj-grid/style.css`; theming via CSS variables, overridable as needed
253
+ - **Build**: Vite library mode, single ESM file, `sideEffects` limited to CSS, tree-shaking friendly
254
+
255
+ ---
256
+
257
+ ## 🖥 Run the demo page locally
258
+
259
+ The demo page (`playground/`) starts its own server and doesn't depend on a host project; the 8 tabs are your feature map:
260
+
261
+ ```bash
262
+ git clone https://github.com/rjding/rjGrid.git # in mainland China you can use the mirror: git clone https://gitee.com/rjding/rj-grid.git
263
+ cd rjGrid
264
+ pnpm install
265
+ pnpm dev # defaults to http://localhost:5173
266
+ ```
267
+
268
+ > ① Full features ② Big-data performance ③ Tree/grouping/pivot ④ Server-side modes ⑤ SSRM block cache ⑥ Formula engine ⑦ Theming & i18n ⑧ AI natural-language query
269
+
270
+ ---
271
+
272
+ <details>
273
+ <summary><b>📚 Maintainer info (repo layout / dev commands / release discipline)</b></summary>
274
+
275
+ ### Repository structure
276
+
277
+ | Path | Purpose |
278
+ |---|---|
279
+ | `index.ts` | Package entry (value-exports `RjGrid` + the NLQ / query-condition kernel + all public types) |
280
+ | `src/` | Component and engine source (`src/types.ts` is the type authority) |
281
+ | `__tests__/` | 407 unit-test cases, entry `__tests__/run.ts` |
282
+ | `build/rjDistCheck.mjs` | Five dist health-check guards (run automatically at the end of a build) |
283
+ | `vite.lib.config.ts` | Library build: single ESM file + single `style.css`, external `vue`/`echarts`, no sourcemap |
284
+ | `playground/` | 8-tab demo page |
285
+ | `docs/RjGrid_Manual_EN.md` | Full manual (features, API, pitfalls and boundaries) |
286
+ | `dist/` | Release artifacts, committed alongside the library |
287
+
288
+ ### Development commands
289
+
290
+ ```bash
291
+ pnpm test # unit tests, 407 passed
292
+ pnpm ts # vue-tsc --noEmit
293
+ pnpm lint # eslint + stylelint
294
+ pnpm build # vite lib → vue-tsc d.ts → five dist health-check guards
295
+ pnpm size # bundle size report
296
+ pnpm dev # playground demo page
297
+ ```
298
+
299
+ ### Releasing a new version
300
+
301
+ Edit the source → `npm version patch|minor|major` (auto bump + commit + tag) → `git push --follow-tags` → `npm publish` (`prepublishOnly` automatically runs `pnpm build && pnpm test`, so a stale dist can never be published).
302
+
303
+ ### Host-integration notes
304
+
305
+ - When installed from npm the directory name is standardized (`node_modules/rj-grid`), so styles can be imported directly with `import 'rj-grid/style.css'`.
306
+ - On the component side you must **value-import** `import { RjGrid } from 'rj-grid'`; a type-only import throws `Failed to resolve component: rj-grid` at runtime.
307
+ - When installing via a git URL, pnpm places the dependency in a directory whose name contains `#<commit>`; vite resource URLs with a bare `#` are treated as a fragment and dropped → 404 under dev, so use a CSS `@import` shim in that case (see Manual §15.4).
308
+ - Committing `dist` only exists to support the git-URL install path; `sourcemap: false` is source protection, not an option, and the five dist guards keep it in check at the same time.
309
+
310
+ </details>
311
+
312
+ ---
313
+
314
+ ## 🤝 Contributing
315
+
316
+ Issues and PRs are welcome: report bugs, request features, improve docs. Please include relevant unit tests with your change and keep `pnpm test && pnpm ts && pnpm lint && pnpm build` all green.
317
+
318
+ ## 📄 License
319
+
320
+ [MIT](LICENSE) — free for individuals and companies to use, modify and redistribute.
321
+
322
+ ## ☕ Support the author
323
+
324
+ If rj-grid has helped you, consider dropping a ⭐ Star, or buying the author a coffee:
325
+
326
+ <p align="center">
327
+ <img src="docs/88888.png" alt="A little support, a lot of love" width="240"/>
328
+ </p>
package/dist/rj-grid.js CHANGED
@@ -4019,11 +4019,13 @@ function buildThemeVars(params = {}) {
4019
4019
  }
4020
4020
  return vars;
4021
4021
  }
4022
- function resolveMode(mode, prefersDark) {
4022
+ function resolveMode(mode, prefersDark, hostDark = null) {
4023
4023
  if (mode === "dark")
4024
4024
  return "dark";
4025
4025
  if (mode === "light")
4026
4026
  return "light";
4027
+ if (hostDark !== null)
4028
+ return hostDark ? "dark" : "light";
4027
4029
  return prefersDark ? "dark" : "light";
4028
4030
  }
4029
4031
  const zhCN = {
@@ -10146,6 +10148,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
10146
10148
  height: { default: "100%" },
10147
10149
  loading: { type: Boolean },
10148
10150
  theme: {},
10151
+ detectHostTheme: { type: Boolean, default: true },
10149
10152
  density: { default: "medium" },
10150
10153
  lang: {},
10151
10154
  localeText: {},
@@ -10320,6 +10323,32 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
10320
10323
  prefersDark.value = mq.matches;
10321
10324
  (_a = mq.addEventListener) == null ? void 0 : _a.call(mq, "change", (e) => prefersDark.value = e.matches);
10322
10325
  }
10326
+ const hostDark = ref(null);
10327
+ function readHostClass() {
10328
+ if (typeof document === "undefined")
10329
+ return;
10330
+ const cl = document.documentElement.classList;
10331
+ if (cl.contains("dark"))
10332
+ hostDark.value = true;
10333
+ else if (cl.contains("light"))
10334
+ hostDark.value = false;
10335
+ else
10336
+ hostDark.value = null;
10337
+ }
10338
+ if (props.detectHostTheme)
10339
+ readHostClass();
10340
+ let hostThemeMo = null;
10341
+ onMounted(() => {
10342
+ if (!props.detectHostTheme || typeof MutationObserver === "undefined")
10343
+ return;
10344
+ readHostClass();
10345
+ hostThemeMo = new MutationObserver(readHostClass);
10346
+ hostThemeMo.observe(document.documentElement, { attributes: true, attributeFilter: ["class"] });
10347
+ });
10348
+ onBeforeUnmount(() => {
10349
+ hostThemeMo == null ? void 0 : hostThemeMo.disconnect();
10350
+ hostThemeMo = null;
10351
+ });
10323
10352
  function themeFromProp(t2) {
10324
10353
  if (!t2)
10325
10354
  return {};
@@ -10334,7 +10363,11 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
10334
10363
  { deep: true }
10335
10364
  );
10336
10365
  const themeMode = computed(
10337
- () => resolveMode(themeState.value.mode, prefersDark.value)
10366
+ () => resolveMode(
10367
+ themeState.value.mode,
10368
+ prefersDark.value,
10369
+ props.detectHostTheme ? hostDark.value : null
10370
+ )
10338
10371
  );
10339
10372
  const themeVars = computed(() => buildThemeVars({ ...themeState.value, mode: themeMode.value }));
10340
10373
  const dark = computed(() => themeMode.value === "dark");
@@ -11970,21 +12003,42 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
11970
12003
  return {};
11971
12004
  return { left: r.left + "px", top: r.top + "px", width: r.width + "px", height: r.height + "px" };
11972
12005
  }
12006
+ function rightFit() {
12007
+ return layout.value.totalWidth <= viewportW.value;
12008
+ }
11973
12009
  function headerClipStyle(side) {
11974
- return side === "left" ? { left: "0px", width: layout.value.leftWidth + "px" } : { right: "0px", width: layout.value.rightWidth + "px" };
12010
+ if (side === "left")
12011
+ return { left: "0px", width: layout.value.leftWidth + "px" };
12012
+ return rightFit() ? {
12013
+ left: layout.value.totalWidth - layout.value.rightWidth + "px",
12014
+ right: "auto",
12015
+ width: layout.value.rightWidth + "px"
12016
+ } : { right: "0px", width: layout.value.rightWidth + "px" };
11975
12017
  }
11976
12018
  function fixedLayerStyle(side) {
11977
12019
  const clip = { height: viewportH.value + "px", overflow: "hidden" };
11978
- return side === "left" ? {
11979
- position: "absolute",
11980
- left: "0px",
11981
- top: "0px",
11982
- width: layout.value.leftWidth + "px",
11983
- ...clip
11984
- } : {
12020
+ if (side === "left") {
12021
+ return {
12022
+ position: "absolute",
12023
+ left: "0px",
12024
+ top: "0px",
12025
+ width: layout.value.leftWidth + "px",
12026
+ ...clip
12027
+ };
12028
+ }
12029
+ if (rightFit()) {
12030
+ return {
12031
+ position: "absolute",
12032
+ left: layout.value.totalWidth - layout.value.rightWidth + "px",
12033
+ right: "auto",
12034
+ top: "0px",
12035
+ width: layout.value.rightWidth + "px",
12036
+ ...clip
12037
+ };
12038
+ }
12039
+ return {
11985
12040
  position: "absolute",
11986
12041
  right: "0px",
11987
- // 基类 .rj-fixed-layer 带 left:0,绝对定位下 left 会压过 right → 必须显式 auto,否则右冻结层贴到左边缘
11988
12042
  left: "auto",
11989
12043
  top: "0px",
11990
12044
  width: layout.value.rightWidth + "px",
@@ -24,6 +24,8 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<im
24
24
  height?: string | number | undefined;
25
25
  loading?: boolean | undefined;
26
26
  theme?: RjThemeParams | "light" | "dark" | undefined;
27
+ /** 未显式指定主题时,是否自动跟随宿主 <html> 的 dark/light class(element-plus/vben/tailwind 约定);默认 true */
28
+ detectHostTheme?: boolean | undefined;
27
29
  density?: "small" | "medium" | "large" | undefined;
28
30
  /** 语言:'zh' | 'en' | 区域标识(内部归一),默认中文 */
29
31
  lang?: string | undefined;
@@ -151,6 +153,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<im
151
153
  }>, {
152
154
  rows: () => never[];
153
155
  height: string;
156
+ detectHostTheme: boolean;
154
157
  density: string;
155
158
  showToolbar: boolean;
156
159
  quickFilterEnabled: boolean;
@@ -250,6 +253,8 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<im
250
253
  height?: string | number | undefined;
251
254
  loading?: boolean | undefined;
252
255
  theme?: RjThemeParams | "light" | "dark" | undefined;
256
+ /** 未显式指定主题时,是否自动跟随宿主 <html> 的 dark/light class(element-plus/vben/tailwind 约定);默认 true */
257
+ detectHostTheme?: boolean | undefined;
253
258
  density?: "small" | "medium" | "large" | undefined;
254
259
  /** 语言:'zh' | 'en' | 区域标识(内部归一),默认中文 */
255
260
  lang?: string | undefined;
@@ -377,6 +382,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<im
377
382
  }>, {
378
383
  rows: () => never[];
379
384
  height: string;
385
+ detectHostTheme: boolean;
380
386
  density: string;
381
387
  showToolbar: boolean;
382
388
  quickFilterEnabled: boolean;
@@ -477,6 +483,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<im
477
483
  rows: RjRowData[];
478
484
  pageSize: number;
479
485
  queryFields: RjQueryFieldDef[];
486
+ detectHostTheme: boolean;
480
487
  showToolbar: boolean;
481
488
  quickFilterEnabled: boolean;
482
489
  floatingFilters: boolean;
@@ -29,5 +29,9 @@ export interface RjThemeParams {
29
29
  * 纯函数:无 DOM / 无时间戳 / 无随机,确定性可单测/快照。
30
30
  */
31
31
  export declare function buildThemeVars(params?: RjThemeParams): Record<string, string>;
32
- /** 解析 auto → light/dark(组件侧调用,注入 matchMedia 判定结果) */
33
- export declare function resolveMode(mode: RjThemeParams['mode'], prefersDark: boolean): 'light' | 'dark';
32
+ /**
33
+ * 解析 auto → light/dark(组件侧调用)。
34
+ * 三级优先级:显式 mode(dark/light)> 宿主 <html>.dark/.light class(hostDark,null 表示宿主未表态)> OS prefers-color-scheme。
35
+ * hostDark 作为可选第三参并默认 null,保持既有两参调用与测试不受影响。
36
+ */
37
+ export declare function resolveMode(mode: RjThemeParams['mode'], prefersDark: boolean, hostDark?: boolean | null): 'light' | 'dark';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rj-grid",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "description": "零第三方依赖的自研 Vue3 虚拟表格:虚拟滚动 / 冻结列 / 行拖拽 / 分组透视 / 公式 / SSRM / 主题 i18n / 自然语言查询",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -45,21 +45,6 @@
45
45
  "optional": true
46
46
  }
47
47
  },
48
- "scripts": {
49
- "start": "vite --config vite.playground.config.ts",
50
- "dev": "vite --config vite.playground.config.ts",
51
- "build:play": "vite build --config vite.playground.config.ts",
52
- "preview:play": "vite preview --config vite.playground.config.ts",
53
- "build": "node ./node_modules/vite/bin/vite.js build --config vite.lib.config.ts && node --max_old_space_size=8192 ./node_modules/vue-tsc/bin/vue-tsc.js -p tsconfig.types.json && node build/rjDistCheck.mjs",
54
- "check:dist": "node build/rjDistCheck.mjs",
55
- "test": "esbuild __tests__/run.ts --bundle --platform=node --format=cjs --external:vue --outfile=node_modules/.cache/rjtest.cjs --log-level=error && node node_modules/.cache/rjtest.cjs",
56
- "lint": "eslint --fix --ext .ts,.vue index.ts src __tests__ playground && stylelint \"src/styles/*.scss\"",
57
- "ts": "node --max_old_space_size=8192 ./node_modules/vue-tsc/bin/vue-tsc.js --noEmit -p tsconfig.json",
58
- "size": "node ./node_modules/vite/bin/vite.js build --config vite.size.config.ts && node build/rjSizeReport.mjs",
59
- "publish:github": "node scripts/publish-github.mjs",
60
- "publish:github:push": "node scripts/publish-github.mjs --push",
61
- "prepublishOnly": "pnpm build && pnpm test"
62
- },
63
48
  "keywords": [
64
49
  "vue3",
65
50
  "virtual-table",
@@ -89,5 +74,19 @@
89
74
  "vue": "3.5.12",
90
75
  "vue-eslint-parser": "^9.3.2",
91
76
  "vue-tsc": "^1.8.27"
77
+ },
78
+ "scripts": {
79
+ "start": "vite --config vite.playground.config.ts",
80
+ "dev": "vite --config vite.playground.config.ts",
81
+ "build:play": "vite build --config vite.playground.config.ts",
82
+ "preview:play": "vite preview --config vite.playground.config.ts",
83
+ "build": "node ./node_modules/vite/bin/vite.js build --config vite.lib.config.ts && node --max_old_space_size=8192 ./node_modules/vue-tsc/bin/vue-tsc.js -p tsconfig.types.json && node build/rjDistCheck.mjs",
84
+ "check:dist": "node build/rjDistCheck.mjs",
85
+ "test": "esbuild __tests__/run.ts --bundle --platform=node --format=cjs --external:vue --outfile=node_modules/.cache/rjtest.cjs --log-level=error && node node_modules/.cache/rjtest.cjs",
86
+ "lint": "eslint --fix --ext .ts,.vue index.ts src __tests__ playground && stylelint \"src/styles/*.scss\"",
87
+ "ts": "node --max_old_space_size=8192 ./node_modules/vue-tsc/bin/vue-tsc.js --noEmit -p tsconfig.json",
88
+ "size": "node ./node_modules/vite/bin/vite.js build --config vite.size.config.ts && node build/rjSizeReport.mjs",
89
+ "publish:github": "node scripts/publish-github.mjs",
90
+ "publish:github:push": "node scripts/publish-github.mjs --push"
92
91
  }
93
- }
92
+ }