@threestarsoftware/tssgrid 0.1.36 → 0.1.37

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/CHANGELOG.md CHANGED
@@ -3,6 +3,15 @@
3
3
  TssGrid の各リリースの変更点。日付は JST。形式は [Keep a Changelog](https://keepachangelog.com/ja/1.1.0/) 準拠(ゆるめ)。
4
4
  数値は特記なき限り**自社調べ**(headless Chrome / Windows 11・環境差あり)。
5
5
 
6
+ ## [0.1.37] - 2026-11-06
7
+
8
+ ### 追加(公式フレームワークアダプタ)
9
+ - **React / Vue 3 の薄い公式アダプタを追加**(`@threestarsoftware/tssgrid/react`・`@threestarsoftware/tssgrid/vue`)。競合(`ag-grid-react` / `@handsontable/react`)と同じ「コアはフレームワーク非依存のまま・薄いコンポーネントがライフサイクルと props を橋渡し」の形。**コアは無依存を維持**=`react` / `vue` は **peerDependency(任意・`peerDependenciesMeta.optional`)**、アダプタは `React.createElement` / `Vue.h` で手書き=**ビルド不要(UMD)**。
10
+ - グリッドは**アンコントロールド**:マウントで生成・アンマウントで `destroy()`、**cell を React/Vue で描かない**(高速)。値は **ref で公開した grid 本体(命令API)** + `onAfterChange` 等のコールバック。`data` プロップは参照が変わった時だけ `setData`(毎レンダー新配列を渡すとリセット=頻繁な更新は命令APIで)。
11
+ - React: `<TssGridReact columns={..} data={..} onAfterChange={..} ref={ref} />`、`ref.current` が grid 本体。StrictMode 二重マウント安全(`destroy` 冪等)、SSR/Next 安全(構築は `useEffect`=クライアント専用)。
12
+ - Vue: `<TssGridVue :columns :data :options="{ onAfterChange }" ref="g" />`、`g.grid()` が grid 本体。
13
+ - `columns/data/plugins/options` と全 `on*` コールバックをそのまま透過。型(`.d.ts`)付き。例 `examples/react.html` / `examples/vue.html`(CDN UMD のノービルドデモ)。
14
+
6
15
  ## [0.1.36] - 2026-11-06
7
16
 
8
17
  inline ピッカー3兄弟(**tss-time / tss-calendar / tss-datetime**)に共通して潜んでいた「ポップアップの `<select>` が使えない/確定がピッカー内部の値を書き戻す/編集中の表示が食い違う」を一掃。土台としてコアに2つの affordance を追加。
package/README.md CHANGED
@@ -78,9 +78,39 @@ const { TssGrid, HistoryManager } = require('@threestarsoftware/tssgrid');
78
78
 
79
79
  ## フレームワークで使う(React / Vue / Angular)
80
80
 
81
- 専用ラッパーは**作りません**。vanilla on DOM なので CRA/Vite/Next/Webpack/Angular/Nuxt でそのまま動きます。コツは **マウント時に生成し、アンマウント時に `grid.destroy()`** するだけ(リスナ・ResizeObserver・DOM を後始末。idempotent)。
81
+ **React / Vue には薄い公式アダプタ**(`@threestarsoftware/tssgrid/react`・`/vue`)があります。コアは無依存のまま=`react`・`vue` は **peerDependency(任意)**、アダプタは `React.createElement` / `Vue.h` で手書き=**ノービルド**。グリッドは「アンコントロールド」(マウントで生成・アンマウントで `destroy()`・**cell は React/Vue で描かない**=高速)、値は **ref で公開した grid 本体(命令API)** + `onAfterChange` 等のコールバック、`data` プロップは「差し替え」用(参照が変わった時だけ `setData`)。動く例: [`examples/react.html`](https://tssgrid.threestarsoftware.co.jp/examples/react.html) / [`examples/vue.html`](https://tssgrid.threestarsoftware.co.jp/examples/vue.html)。
82
82
 
83
- **React**:
83
+ **React(公式アダプタ)**:
84
+ ```jsx
85
+ import { useRef } from 'react';
86
+ import { TssGridReact } from '@threestarsoftware/tssgrid/react';
87
+ import '@threestarsoftware/tssgrid/tssgrid.css';
88
+
89
+ function Grid({ columns, data }) {
90
+ const ref = useRef(null); // ref.current = grid 本体(命令API)
91
+ return <TssGridReact columns={columns} data={data}
92
+ onAfterChange={(ch, src) => console.log(ch, src)} ref={ref} />;
93
+ // 例: ref.current.sortBy('age','desc') / ref.current.getRows()
94
+ }
95
+ ```
96
+
97
+ **Vue 3(公式アダプタ)**:
98
+ ```vue
99
+ <script setup>
100
+ import { ref } from 'vue';
101
+ import { TssGridVue } from '@threestarsoftware/tssgrid/vue';
102
+ import '@threestarsoftware/tssgrid/tssgrid.css';
103
+ const g = ref(null); // g.value.grid() = grid 本体
104
+ </script>
105
+ <template>
106
+ <TssGridVue :columns="columns" :data="data"
107
+ :options="{ onAfterChange: (ch, src) => console.log(ch, src) }" ref="g" />
108
+ </template>
109
+ ```
110
+
111
+ アダプタを使わず**依存ゼロで直接**使うこともできます(vanilla on DOM。CRA/Vite/Next/Webpack/Angular/Nuxt でそのまま。コツは **マウント時に生成し、アンマウント時に `grid.destroy()`**)。
112
+
113
+ **React(直接)**:
84
114
  ```jsx
85
115
  import { useEffect, useRef } from 'react';
86
116
  import { TssGrid } from '@threestarsoftware/tssgrid';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threestarsoftware/tssgrid",
3
- "version": "0.1.36",
3
+ "version": "0.1.37",
4
4
  "description": "軽量・ノービルド・日本語IME堅牢な編集グリッド(vanilla JS / 依存なし / MIT)。Excel ライクな入力画面を <script> タグ1本で。",
5
5
  "license": "MIT",
6
6
  "author": "ThreeStarSoftware (https://www.threestarsoftware.co.jp/)",
@@ -67,9 +67,29 @@
67
67
  "types": "./plugins/tss-comment.d.ts",
68
68
  "default": "./plugins/tss-comment.js"
69
69
  },
70
+ "./react": {
71
+ "types": "./react/index.d.ts",
72
+ "default": "./react/index.js"
73
+ },
74
+ "./vue": {
75
+ "types": "./vue/index.d.ts",
76
+ "default": "./vue/index.js"
77
+ },
70
78
  "./plugins/*": "./plugins/*",
71
79
  "./package.json": "./package.json"
72
80
  },
81
+ "peerDependencies": {
82
+ "react": ">=16.8.0",
83
+ "vue": ">=3.0.0"
84
+ },
85
+ "peerDependenciesMeta": {
86
+ "react": {
87
+ "optional": true
88
+ },
89
+ "vue": {
90
+ "optional": true
91
+ }
92
+ },
73
93
  "unpkg": "src/tssgrid.js",
74
94
  "jsdelivr": "src/tssgrid.js",
75
95
  "sideEffects": [
@@ -83,6 +103,8 @@
83
103
  "src/tssgrid.css",
84
104
  "src/tssgrid.d.ts",
85
105
  "plugins/",
106
+ "react/",
107
+ "vue/",
86
108
  "README.md",
87
109
  "CHANGELOG.md",
88
110
  "LICENSE"
@@ -0,0 +1,19 @@
1
+ // TssGridReact — TssGrid の薄い React アダプタの型。
2
+ import * as React from 'react';
3
+ import { TssGrid, TssGridOptions } from '../src/tssgrid';
4
+
5
+ // トップレベルに書ける定番オプション+全 on* コールバックは Partial<TssGridOptions> として受ける。
6
+ // それ以外は options={{…}} でまとめて渡す。className / style は host の <div> に付く。
7
+ export interface TssGridReactProps extends Partial<TssGridOptions> {
8
+ className?: string;
9
+ style?: React.CSSProperties;
10
+ options?: TssGridOptions;
11
+ }
12
+
13
+ // ref には grid 本体(命令API)が入る。
14
+ declare const TssGridReact: React.ForwardRefExoticComponent<
15
+ TssGridReactProps & React.RefAttributes<TssGrid>
16
+ >;
17
+
18
+ export default TssGridReact;
19
+ export { TssGridReact };
package/react/index.js ADDED
@@ -0,0 +1,74 @@
1
+ /*! TssGridReact — TssGrid の薄い React アダプタ(UMD・ノービルド・react は peerDependency)
2
+ *
3
+ * 方針(競合 ag-grid-react / @handsontable/react と同じ):
4
+ * - グリッドは「アンコントロールド」= マウント時に1回生成し、アンマウントで destroy()。cell を React で描かない(高速)。
5
+ * - 値の読み書きは ref 経由の命令API(grid 本体)+ onAfterChange 等のコールバック。data プロップは「差し替え」用。
6
+ * - 全ての on* コールバック(onAfterChange / onEditEnd …)と columns/data/plugins/options をそのまま TssGrid へ渡す。
7
+ *
8
+ * 使い方:
9
+ * import { TssGridReact } from '@threestarsoftware/tssgrid/react';
10
+ * import '@threestarsoftware/tssgrid/tssgrid.css';
11
+ * const ref = useRef(null);
12
+ * <TssGridReact columns={cols} data={rows} plugins={[...]}
13
+ * onAfterChange={(ch, src) => ...} ref={ref} />
14
+ * // 命令API: ref.current.sortBy('col','desc') / ref.current.getRows() など(grid 本体)
15
+ *
16
+ * 注意:
17
+ * - data は「参照が変わった時だけ」setData されます(毎レンダー新配列を渡すと毎回リセット=カーソルも飛ぶ)。
18
+ * 頻繁な更新は ref の命令API(setValue/ appendRows 等)を使うのが定石。
19
+ * - 構築は useEffect(クライアント専用)なので SSR/Next でもそのまま(サーバでは空 div)。columns を変えたい時は key で remount。
20
+ */
21
+ (function (root, factory) {
22
+ if (typeof module !== 'undefined' && module.exports) {
23
+ module.exports = factory(require('react'), require('../src/tssgrid.js'));
24
+ } else {
25
+ root.TssGridReact = factory(root.React, { TssGrid: root.TssGrid });
26
+ }
27
+ })(typeof self !== 'undefined' ? self : this, function (React, core) {
28
+ 'use strict';
29
+ var TssGrid = core && (core.TssGrid || core);
30
+ var h = React.createElement;
31
+ // トップレベルに書ける定番オプション(それ以外は options={{…}} で)。
32
+ var PASS = { columns: 1, headers: 1, data: 1, plugins: 1, name: 1, width: 1, height: 1, rowHeight: 1, rowHeaders: 1, colHeaders: 1, minSpareRows: 1, maxRows: 1, history: 1, virtual: 1, hiddenColumns: 1 };
33
+
34
+ function buildOptions(props) {
35
+ var o = {};
36
+ if (props.options) for (var k in props.options) o[k] = props.options[k];
37
+ for (var key in props) {
38
+ if (PASS[key]) o[key] = props[key];
39
+ else if (/^on[A-Z]/.test(key) && typeof props[key] === 'function') o[key] = props[key]; // on* コールバック総通し
40
+ }
41
+ return o;
42
+ }
43
+
44
+ var TssGridReact = React.forwardRef(function (props, ref) {
45
+ var hostRef = React.useRef(null);
46
+ var gridRef = React.useRef(null);
47
+ var propsRef = React.useRef(props);
48
+ propsRef.current = props;
49
+ var firstData = React.useRef(true);
50
+ var readyState = React.useState(0); // grid 生成後に ref(命令API)を更新させるためのバンプ
51
+
52
+ React.useEffect(function () { // 生成は1回(アンコントロールド)。StrictMode 二重でも destroy が冪等。
53
+ var grid = new TssGrid(hostRef.current, buildOptions(propsRef.current));
54
+ gridRef.current = grid;
55
+ firstData.current = true;
56
+ readyState[1](function (n) { return n + 1; }); // ref.current = grid 本体 に更新(useImperativeHandle を再評価)
57
+ return function () { try { grid.destroy(); } catch (e) {} if (gridRef.current === grid) gridRef.current = null; };
58
+ }, []);
59
+
60
+ React.useEffect(function () { // data の参照が変わったら差し替え(初回=生成時の data を使うのでスキップ)
61
+ if (firstData.current) { firstData.current = false; return; }
62
+ var g = gridRef.current;
63
+ if (g && propsRef.current.data != null) g.setData(propsRef.current.data);
64
+ }, [props.data]);
65
+
66
+ React.useImperativeHandle(ref, function () { return gridRef.current; }, [readyState[0]]); // grid 本体を命令API として公開(生成後に更新)
67
+
68
+ return h('div', { ref: hostRef, className: props.className, style: props.style });
69
+ });
70
+ TssGridReact.displayName = 'TssGridReact';
71
+ TssGridReact.TssGridReact = TssGridReact; // import { TssGridReact } / import TssGridReact どちらも通す
72
+ TssGridReact.default = TssGridReact;
73
+ return TssGridReact;
74
+ });
package/vue/index.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ // TssGridVue — TssGrid の薄い Vue 3 アダプタの型。
2
+ import { DefineComponent } from 'vue';
3
+ import { TssGrid, TssGridOptions } from '../src/tssgrid';
4
+
5
+ export type TssGridVueProps = Partial<TssGridOptions> & { options?: TssGridOptions };
6
+
7
+ // expose: grid() で grid 本体(命令API)を返す。
8
+ export interface TssGridVueExposed {
9
+ grid(): TssGrid | null;
10
+ }
11
+
12
+ declare const TssGridVue: DefineComponent<TssGridVueProps>;
13
+
14
+ export default TssGridVue;
15
+ export { TssGridVue };
package/vue/index.js ADDED
@@ -0,0 +1,56 @@
1
+ /*! TssGridVue — TssGrid の薄い Vue 3 アダプタ(UMD・ノービルド・vue は peerDependency)
2
+ *
3
+ * 方針(React アダプタと同じ): グリッドはアンコントロールド。マウントで生成・アンマウントで destroy()。
4
+ * 値の読み書きは expose した grid 本体(命令API)+ on* コールバック。data プロップは「差し替え」用。
5
+ *
6
+ * 使い方:
7
+ * import { TssGridVue } from '@threestarsoftware/tssgrid/vue';
8
+ * import '@threestarsoftware/tssgrid/tssgrid.css';
9
+ * <TssGridVue :columns="cols" :data="rows" :plugins="[...]" :options="{ onAfterChange }" ref="g" />
10
+ * // 命令API: this.$refs.g.grid().sortBy('col','desc') など(grid 本体を返す)
11
+ *
12
+ * 注意: on* コールバックは :options(例 :options="{ onAfterChange: fn }")か、@after-change などの属性で渡せます。
13
+ * data は参照が変わった時だけ setData(毎回新配列はリセット=カーソルが飛ぶ)。頻繁な更新は grid の命令APIで。
14
+ */
15
+ (function (root, factory) {
16
+ if (typeof module !== 'undefined' && module.exports) {
17
+ module.exports = factory(require('vue'), require('../src/tssgrid.js'));
18
+ } else {
19
+ root.TssGridVue = factory(root.Vue, { TssGrid: root.TssGrid });
20
+ }
21
+ })(typeof self !== 'undefined' ? self : this, function (Vue, core) {
22
+ 'use strict';
23
+ var TssGrid = core && (core.TssGrid || core);
24
+ var PASS = ['columns', 'data', 'plugins', 'headers', 'name', 'width', 'height', 'rowHeight', 'rowHeaders', 'colHeaders', 'minSpareRows', 'maxRows', 'history', 'virtual', 'hiddenColumns'];
25
+
26
+ var TssGridVue = Vue.defineComponent({
27
+ name: 'TssGridVue',
28
+ inheritAttrs: false, // on* 属性を div に二重付けしない
29
+ props: {
30
+ columns: Array, data: Array, plugins: Array, options: Object, headers: Array,
31
+ name: String, width: [Number, String], height: [Number, String],
32
+ rowHeight: Number, rowHeaders: { type: Boolean, default: undefined }, minSpareRows: Number,
33
+ },
34
+ setup: function (props, ctx) {
35
+ var el = Vue.ref(null);
36
+ var grid = null;
37
+ function buildOptions() {
38
+ var o = {};
39
+ if (props.options) for (var k in props.options) o[k] = props.options[k];
40
+ PASS.forEach(function (key) { if (props[key] !== undefined) o[key] = props[key]; });
41
+ var attrs = ctx.attrs || {};
42
+ for (var a in attrs) { if (/^on[A-Z]/.test(a) && typeof attrs[a] === 'function') o[a] = attrs[a]; } // @after-change 等=attrs の onAfterChange
43
+ return o;
44
+ }
45
+ Vue.onMounted(function () { grid = new TssGrid(el.value, buildOptions()); });
46
+ Vue.onBeforeUnmount(function () { if (grid) { try { grid.destroy(); } catch (e) {} grid = null; } });
47
+ Vue.watch(function () { return props.data; }, function (d) { if (grid && d != null) grid.setData(d); }); // 参照が変わったら差し替え
48
+ ctx.expose({ grid: function () { return grid; } }); // grid 本体を命令API として公開
49
+ return function () { return Vue.h('div', { ref: el }); };
50
+ },
51
+ });
52
+
53
+ TssGridVue.TssGridVue = TssGridVue;
54
+ TssGridVue.default = TssGridVue;
55
+ return TssGridVue;
56
+ });