tsgrid-ui 2.7.0 → 2.9.0
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 +229 -0
- package/dist/base.d.ts +148 -0
- package/dist/base.es6.js +11 -0
- package/dist/base.es6.js.map +1 -0
- package/dist/chunks/chunk-26XP2XU3.js +1795 -0
- package/dist/chunks/chunk-26XP2XU3.js.map +1 -0
- package/dist/chunks/chunk-3NYH6545.js +2423 -0
- package/dist/chunks/chunk-3NYH6545.js.map +1 -0
- package/dist/chunks/chunk-BIB3X2TW.js +1638 -0
- package/dist/chunks/chunk-BIB3X2TW.js.map +1 -0
- package/dist/chunks/chunk-DXZJHS4M.js +1283 -0
- package/dist/chunks/chunk-DXZJHS4M.js.map +1 -0
- package/dist/chunks/chunk-EVZMMVXO.js +1212 -0
- package/dist/chunks/chunk-EVZMMVXO.js.map +1 -0
- package/dist/chunks/chunk-GJD5NFWQ.js +2305 -0
- package/dist/chunks/chunk-GJD5NFWQ.js.map +1 -0
- package/dist/chunks/chunk-IYF3Q7GX.js +127 -0
- package/dist/chunks/chunk-IYF3Q7GX.js.map +1 -0
- package/dist/chunks/chunk-OFASTA2A.js +2980 -0
- package/dist/chunks/chunk-OFASTA2A.js.map +1 -0
- package/dist/chunks/chunk-OMLGN735.js +677 -0
- package/dist/chunks/chunk-OMLGN735.js.map +1 -0
- package/dist/chunks/chunk-WKSLGUB3.js +1127 -0
- package/dist/chunks/chunk-WKSLGUB3.js.map +1 -0
- package/dist/chunks/chunk-YBY52G2U.js +849 -0
- package/dist/chunks/chunk-YBY52G2U.js.map +1 -0
- package/dist/field.d.ts +329 -0
- package/dist/field.es6.js +11 -0
- package/dist/field.es6.js.map +1 -0
- package/dist/form.d.ts +162 -0
- package/dist/form.es6.js +14 -0
- package/dist/form.es6.js.map +1 -0
- package/dist/layout.d.ts +108 -0
- package/dist/layout.es6.js +13 -0
- package/dist/layout.es6.js.map +1 -0
- package/dist/locale.d.ts +30 -0
- package/dist/locale.es6.js +7 -0
- package/dist/locale.es6.js.map +1 -0
- package/dist/metafile-esm.json +1 -0
- package/dist/popup.d.ts +92 -0
- package/dist/popup.es6.js +18 -0
- package/dist/popup.es6.js.map +1 -0
- package/dist/query-CKGg5Ugv.d.ts +81 -0
- package/dist/sidebar.d.ts +138 -0
- package/dist/sidebar.es6.js +11 -0
- package/dist/sidebar.es6.js.map +1 -0
- package/dist/tabs.d.ts +63 -0
- package/dist/tabs.es6.js +11 -0
- package/dist/tabs.es6.js.map +1 -0
- package/dist/toolbar.d.ts +97 -0
- package/dist/toolbar.es6.js +11 -0
- package/dist/toolbar.es6.js.map +1 -0
- package/dist/tooltip.d.ts +322 -0
- package/dist/tooltip.es6.js +18 -0
- package/dist/tooltip.es6.js.map +1 -0
- package/dist/tsgrid-ui.css +2 -2
- package/dist/tsgrid-ui.d.ts +16 -2004
- package/dist/tsgrid-ui.es6.js +7750 -23831
- package/dist/tsgrid-ui.es6.js.map +1 -1
- package/dist/tsgrid-ui.es6.min.js +28 -28
- package/dist/tsgrid-ui.js +103 -25
- package/dist/tsgrid-ui.min.css +2 -2
- package/dist/tsgrid-ui.min.js +24 -24
- package/dist/tsutils-message-CogFtVtO.d.ts +82 -0
- package/dist/utils.d.ts +418 -0
- package/dist/utils.es6.js +14 -0
- package/dist/utils.es6.js.map +1 -0
- package/package.json +26 -5
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,235 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to **TsGrid UI** will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## v2.8.0 — 2026-05-14
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **Subpath exports** — 11 new `package.json` export entries enable tree-shakable imports
|
|
10
|
+
(amendment #983: `./grid` deferred to Phase 3 pending `splitting:true` code-split):
|
|
11
|
+
- `tsgrid-ui/locale` → `TsLocale` (~3,843 B, 99.6% smaller than barrel)
|
|
12
|
+
- `tsgrid-ui/base` → `TsBase`, `TsEvent`, `toSafeEvent` (~32,135 B, 96.6% smaller)
|
|
13
|
+
- `tsgrid-ui/utils` → `TsUi`, `TsUtils`, `query` (~127,812 B, 86.5% smaller)
|
|
14
|
+
- `tsgrid-ui/popup` → `TsPopup`, `TsAlert`, `TsConfirm`, `TsPrompt`, `TsDialog` (~159,775 B, 83.1% smaller)
|
|
15
|
+
- `tsgrid-ui/tooltip` → `TsTooltip`, `TsMenu`, `TsColor`, `TsDate`, `Tooltip` (~244,488 B, 74.1% smaller)
|
|
16
|
+
- `tsgrid-ui/tabs` → `TsTabs` (~268,343 B, 71.6% smaller)
|
|
17
|
+
- `tsgrid-ui/toolbar` → `TsToolbar` (~288,428 B, 69.5% smaller)
|
|
18
|
+
- `tsgrid-ui/sidebar` → `TsSidebar` (~306,229 B, 67.6% smaller)
|
|
19
|
+
- `tsgrid-ui/field` → `TsField` (~312,704 B, 66.9% smaller)
|
|
20
|
+
- `tsgrid-ui/layout` → `TsLayout` (~354,172 B, 62.5% smaller)
|
|
21
|
+
- `tsgrid-ui/form` → `TsForm` (~468,108 B, 50.5% smaller)
|
|
22
|
+
- **`./package.json` export** — enables tooling that reads package metadata at runtime.
|
|
23
|
+
- **`reports/bundle/v2.8.0-baseline.json`** — schemaVersion 2; per-subpath empirical byte
|
|
24
|
+
measurements. Phase 2 gate for the v3.0 tree-shakable roadmap.
|
|
25
|
+
- Grid users continue using the barrel import (`tsgrid-ui`); `./grid` subpath export deferred
|
|
26
|
+
to Phase 3 once `splitting:true` reduces transitive duplication.
|
|
27
|
+
|
|
28
|
+
### Bundle
|
|
29
|
+
|
|
30
|
+
- Monolith `tsgrid-ui` entry unchanged at 945,470 bytes (byte-identical to v2.7.1).
|
|
31
|
+
- Subpath bundles emitted with `splitting: false`; shared modules re-emitted per subpath.
|
|
32
|
+
Most modern bundlers deduplicate transparently (esbuild, Rollup, Vite, webpack 5+, Parcel 2+).
|
|
33
|
+
- `splitting: true` shared-chunk optimization planned for v2.9 / Phase 3.
|
|
34
|
+
- Dist artifact count: 7 → 29 files (+11 ESM subpath bundles + 11 `.d.ts` files).
|
|
35
|
+
|
|
36
|
+
### BC
|
|
37
|
+
|
|
38
|
+
- Public API surface: **purely additive**. The `"."` barrel entry is byte-identical to v2.7.1.
|
|
39
|
+
- `dist/tsgrid-ui.es6.js` SHA: byte-identical to v2.7.1 (INV-SX-6 PASS).
|
|
40
|
+
- `src/index.ts` barrel: byte-identical to v2.7.1 (INV-7 PASS).
|
|
41
|
+
- No `require:` condition on subpaths — CJS consumers continue using `'tsgrid-ui'` barrel.
|
|
42
|
+
CJS subpaths planned for Phase 4 (requires `wrap-legacy.mjs` per-symbol refactoring).
|
|
43
|
+
- No barrel deprecation: `'tsgrid-ui'` barrel is fully supported with zero deprecation markers.
|
|
44
|
+
- SEMVER MINOR per SemVer §7. No breaking changes.
|
|
45
|
+
|
|
46
|
+
### Tests
|
|
47
|
+
|
|
48
|
+
- `test/unit/subpath-exports.test.ts` (NEW) — 3 groups: exports shape, dist existence,
|
|
49
|
+
bundle floor. All 3 groups GREEN from Phase 6 onward.
|
|
50
|
+
- `test/consumer-smoke.ts` — extended with 11 named-import probes + 11 type-only probes.
|
|
51
|
+
- Total Vitest tests: **352/352 GREEN** (v2.7.1 baseline: 301/301 — +13 new assertions
|
|
52
|
+
plus expanded parametric tests via `it.each`).
|
|
53
|
+
- `tsup.config.analyze.ts`: UNCHANGED (INV-ANALYZE-ISOLATION PASS).
|
|
54
|
+
|
|
55
|
+
## v2.9.0 — 2026-05-15
|
|
56
|
+
|
|
57
|
+
### Added
|
|
58
|
+
|
|
59
|
+
- **`TsToolbar.toggle(...args): any[]` — new public API** (`src/tstoolbar.ts:481`): flips the `checked` state of one or more items without firing events or opening overlays. Complements `check()` / `uncheck()` / `click()`:
|
|
60
|
+
- `button` / `check` / `html` / `spacer` / `break`: flip `it.checked`.
|
|
61
|
+
- `drop` / `menu` / `menu-radio` / `menu-check` / `color` / `text-color`: if currently checked, closes the toolbar's `-drop` overlay via `TsTooltip.hide` before flipping (mirrors `uncheck()` overlay-close path). Never opens overlays.
|
|
62
|
+
- `radio`: `console.warn` + skip. Use `check()` / `uncheck()` for radios.
|
|
63
|
+
- `group`: recurses into `it.items`; the container itself is never in the effected list.
|
|
64
|
+
- `sub-id` with `:` notation and missing ids: silently skipped.
|
|
65
|
+
- Returns the array of ids whose state actually flipped (never `undefined`).
|
|
66
|
+
- State-only — does NOT fire `onClick` or `onChange`.
|
|
67
|
+
|
|
68
|
+
### Fixed (toolbar polish-lifecycle)
|
|
69
|
+
|
|
70
|
+
- `setCount` no longer recurses into non-count item types — guarded at function entry (`7d721185`).
|
|
71
|
+
- `destroy()` now closes pending overlays before unmount, preventing detached tooltip refs (`01752f36`).
|
|
72
|
+
- `menu-check` items now seed `selected` from `it.items` function-form returns at insert time (`712a1bac`).
|
|
73
|
+
|
|
74
|
+
### Fixed (toolbar polish-api)
|
|
75
|
+
|
|
76
|
+
- `get(id, true)` and `remove()` now compute the correct sub-item index inside group containers (`8a522974`, Smell 6).
|
|
77
|
+
|
|
78
|
+
### Refactor (toolbar polish-api)
|
|
79
|
+
|
|
80
|
+
- Removed unreachable `item.type==null` guard in toolbar render path (`50c8f2ea`, Smell 2).
|
|
81
|
+
|
|
82
|
+
### Style (toolbar polish-api)
|
|
83
|
+
|
|
84
|
+
- Single display value emitted for hidden-group sub-items (`2418f929`, Smell 4).
|
|
85
|
+
- Intentional switch fall-through explicitly annotated (`577bd566`, Smell 3).
|
|
86
|
+
|
|
87
|
+
### Build / Dist
|
|
88
|
+
|
|
89
|
+
- Removed orphan chunks from analyze build (`459b8202`, closes WARNING-V1).
|
|
90
|
+
- Rebuilt CJS dist with v2.8.1 banner (`48960492`, closes WARNING-V2).
|
|
91
|
+
- Rebuilt `dist/` after polish-api merge — restored coherence (`35fd76ba`, closes WARNING-V4).
|
|
92
|
+
|
|
93
|
+
### BC
|
|
94
|
+
|
|
95
|
+
- Public API surface: **purely additive**. `TsToolbar.toggle()` is new; all existing methods unchanged.
|
|
96
|
+
- SEMVER MINOR (new public API on `TsToolbar`).
|
|
97
|
+
|
|
98
|
+
### Internal
|
|
99
|
+
|
|
100
|
+
- Verify-pass for v2.8.1 (`2bcb55a3`) was completed on the `feature/v2.8.1-chunk-splitting-side-effects` branch before polish-lifecycle (3 fixes), polish-api Smells (2/3/4/6), and `toggle()` API landed on master. v2.9.0 packages those post-verify additions as a minor release.
|
|
101
|
+
|
|
102
|
+
## v2.8.1 — 2026-05-15
|
|
103
|
+
|
|
104
|
+
### Added
|
|
105
|
+
|
|
106
|
+
#### Bundle
|
|
107
|
+
|
|
108
|
+
- **`sideEffects` per-file map** — `package.json` now declares an explicit 9-entry
|
|
109
|
+
`sideEffects` array, enabling webpack and rollup to tree-shake unused subpaths:
|
|
110
|
+
- Side-effectful (must load): `tsgrid-ui.css`, `tsgrid-ui.min.css`,
|
|
111
|
+
`utils.es6.js`, `popup.es6.js`, `tooltip.es6.js`, `tsgrid-ui.es6.js`,
|
|
112
|
+
`tsgrid-ui.es6.min.js`, `tsgrid-ui.js`, `tsgrid-ui.min.js`.
|
|
113
|
+
- Implicitly pure (may tree-shake): `locale.es6.js`, `base.es6.js`,
|
|
114
|
+
`tabs.es6.js`, `toolbar.es6.js`, `sidebar.es6.js`, `field.es6.js`,
|
|
115
|
+
`layout.es6.js`, `form.es6.js`, and all `dist/chunks/*.js`.
|
|
116
|
+
- **IMPORTANT**: esbuild (and therefore vite, tsup) does **NOT** honor
|
|
117
|
+
`package.json sideEffects`. Only webpack and rollup benefit from this field.
|
|
118
|
+
esbuild's own tree-shaking is based solely on static analysis of ESM imports.
|
|
119
|
+
|
|
120
|
+
- **ESM shared chunks under `dist/chunks/`** — `splitting: true` is now active in the
|
|
121
|
+
ESM non-min block (`tsup.config.ts` block 1). esbuild extracts shared code into
|
|
122
|
+
`dist/chunks/chunk-<8CHAR>.js` files automatically. With 12 entry points, 10 chunks
|
|
123
|
+
are produced. Consumers importing multiple subpaths load shared code once.
|
|
124
|
+
|
|
125
|
+
- **Multi-subpath byte savings** (webpack/rollup consumers):
|
|
126
|
+
- SC-A (`./popup` + `./form`): **19.8% reduction** (627,883 B → 503,563 B effective)
|
|
127
|
+
- SC-B (`./popup` + `./tooltip` + `./tabs`): **54.9% reduction** (672,606 B → 303,119 B)
|
|
128
|
+
- SC-C (`./locale` only): +123 B overhead (+3.2%, well within ≤1 KB canary threshold)
|
|
129
|
+
- SC-D (monolith `.`): +2,348 B overhead (+0.25%, within ±2% AC10 allowance)
|
|
130
|
+
- Full scenario table: `reports/bundle/v2.8.1-splitting-savings.md`
|
|
131
|
+
|
|
132
|
+
- **Cycle 5 forward reference** — `dist/utils.es6.js`, `dist/popup.es6.js`, and
|
|
133
|
+
`dist/tooltip.es6.js` remain in the `sideEffects` array because their constructors
|
|
134
|
+
run module-level side effects at import time (global singleton registration).
|
|
135
|
+
Cycle 5 (singleton lazy-init refactor) will remove these from the array, unlocking
|
|
136
|
+
additional savings for esbuild/vite consumers that currently cannot benefit.
|
|
137
|
+
|
|
138
|
+
- **`dist/chunks/` must ship with the package** — consumers installing tsgrid-ui from
|
|
139
|
+
npm must ensure `dist/chunks/*.js` files are present. The `package.json files` array
|
|
140
|
+
already covers `dist/` recursively; no additional configuration needed.
|
|
141
|
+
|
|
142
|
+
### BC
|
|
143
|
+
|
|
144
|
+
- Public API surface: **purely additive**. All existing `import` paths are unchanged.
|
|
145
|
+
`dist/chunks/` is a new subdirectory but is an implementation detail — not a public API.
|
|
146
|
+
- SEMVER PATCH. No breaking changes.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
### Fixed (build)
|
|
151
|
+
- `scripts/wrap-legacy.mjs`: `buildHeader()` is now deterministic — per-build
|
|
152
|
+
`new Date().toLocaleString('en-us')` timestamp removed. Version string is now
|
|
153
|
+
read dynamically from `package.json` via `readFile + JSON.parse` (was stale
|
|
154
|
+
hardcoded `1.0.x (nightly)`). CJS dist artifacts (`dist/tsgrid-ui.js`,
|
|
155
|
+
`dist/tsgrid-ui.min.js`) are now bit-identical across consecutive rebuilds
|
|
156
|
+
on unchanged source.
|
|
157
|
+
- Anti-regression: new Vitest unit test at `test/unit/wrap-legacy.test.ts`
|
|
158
|
+
guards against reintroduction of `new Date(`, `Date.now(`, `Math.random(`
|
|
159
|
+
in the post-build script.
|
|
160
|
+
|
|
161
|
+
### Notes (build)
|
|
162
|
+
- SEMVER: chore — no version bump.
|
|
163
|
+
- Supersedes the CJS-SHA Option-B caveat from the bundle-baseline-instrumentation
|
|
164
|
+
cycle (spec #960 INV-BBI-1). Future cycles MAY assume strict CJS-SHA equality
|
|
165
|
+
across all 5 dist artifacts.
|
|
166
|
+
|
|
167
|
+
### Added (tooling)
|
|
168
|
+
- `pnpm bundle:analyze` — generate esbuild metafile + per-module advisory summary (`reports/bundle/latest.md`, gitignored).
|
|
169
|
+
- `pnpm bundle:snapshot -- --version=vX.Y.Z` — write committed baseline JSON to `reports/bundle/<version>-baseline.json`.
|
|
170
|
+
- `tsup.config.analyze.ts` — analyze-only tsup config (single ESM-non-min block + `metafile: true`); structurally isolated from `tsup.config.ts` (INV-ANALYZE-ISOLATION).
|
|
171
|
+
- `reports/bundle/v2.7.1-baseline.json` — v2.7.1 ESM-non-min per-module byte composition. This artifact unlocks Phase 2 (subpath exports) acceptance testing (INV-CYCLE-1-HARD-GATE).
|
|
172
|
+
- `reports/bundle/README.md` — schema + scope documentation.
|
|
173
|
+
|
|
174
|
+
### Internal
|
|
175
|
+
- Zero new devDependencies. Zero changes to `src/`. Zero changes to `dist/*.js` on production builds (byte-identical, verified via `shasum` gate).
|
|
176
|
+
- SEMVER: chore / no version bump. Next version bump (v2.8.0) reserved for Phase 2 (subpath exports).
|
|
177
|
+
|
|
178
|
+
## v2.7.1 — 2026-05-14
|
|
179
|
+
|
|
180
|
+
### Fixed
|
|
181
|
+
|
|
182
|
+
- **R-LOC-V26-PRESERVED — `keepPhrases=false` now actually clears phrases** (`src/tsutils-locale.ts:133`, string branch): The v2.6.0 / v2.7.0 implementation `deps.extend({}, settings, TsLocale, { phrases: {} }, data)` was a deep-merge no-op on the phrases sub-tree — `extend` is deep and `extend(existingPhrases, {})` iterates `Object.keys({})` → zero keys, leaving pre-existing phrase keys intact. v2.7.1 replaces this with the spread-override-before-extend idiom: `const phrasesCleared = { ...settings, phrases: {} }; deps.extend({}, phrasesCleared, TsLocale, data)`. Pre-existing `settings.phrases` keys are NOW cleared before the `TsLocale` + `data` phrase-merge, aligning with the original code comment "clear phrases from language before merging" (in place since v2.6.0). Covered by `T-LOC-5` (flipped) + `INV-L7-PHRASES-CLEAR` (string clause). See engram #925 (discovery).
|
|
183
|
+
- **R-LOC-2 — `_locale()` no longer mutates the caller's input array** (`src/tsutils-locale.ts:80,86`, array branch): Calling `await Utils.locale(['en-us', 'ru-ru'])` previously rewrote the caller's array in-place to `['locale/en-us.json', 'locale/ru-ru.json']` (alias mutation via `const localeArr = locale as string[]` + `localeArr[ind] = file`). v2.7.1 uses `.map()` upfront for path expansion, producing a fresh internal array; the caller's original array reference and contents are byte-identical post-call. Covered by new `T-LOC-11` + `INV-L7-IMMUTABLE-INPUT`.
|
|
184
|
+
- **R-V271-4 — Array-branch `mergedSettings` init now actually pre-resets phrases** (`src/tsutils-locale.ts:79`, array branch): `let mergedSettings = deps.extend({}, settings, { phrases: {} })` had the same deep-merge no-op as R-LOC-V26-PRESERVED — pre-existing `settings.phrases` keys leaked into the initial fanout accumulator. v2.7.1 replaces it with `let mergedSettings = deps.extend({}, { ...settings, phrases: {} })`, aligning with the comment "Pre-reset phrases before fanout" (in place since v2.7.0). Covered by new `T-LOC-12` + `INV-L7-PHRASES-CLEAR` (array clause).
|
|
185
|
+
|
|
186
|
+
### Tests
|
|
187
|
+
|
|
188
|
+
- `T-LOC-5` flipped + header rewritten: was `expect(phrases).toHaveProperty('stale', 'remove-me')`; now `expect(phrases).not.toHaveProperty('stale')`. Positive assertion `expect(phrases).toHaveProperty('Add new record')` retained (proves the `keepPhrases=false` branch still merges TsLocale defaults). Comment block removes the `R-LOC-V26-PRESERVED` preservation note and adds the `INV-L7-PHRASES-CLEAR` reference + "v2.7.1 PATCH: phrases-clear now works as documented" one-liner.
|
|
189
|
+
- `T-LOC-11` NEW: array-input immutability gate (`INV-L7-IMMUTABLE-INPUT`). Snapshots the caller's input array, awaits `_locale(input, ...)`, asserts `expect(input).toEqual(snapshot)` AND `expect(input).toBe(inputRef)`. Sub-assertion: `deps.fetch` was still called with expanded paths (`'locale/en-us.json'`, `'locale/ru-ru.json'`).
|
|
190
|
+
- `T-LOC-12` NEW: array-branch `mergedSettings` phrases-clear gate (`INV-L7-PHRASES-CLEAR`, array clause). Sets `TsUtils.settings.phrases = { stale: 'remove-me' }` pre-call; asserts post-call `result.settings.phrases` does NOT contain `stale`.
|
|
191
|
+
- Total Vitest tests: **299/299 GREEN** (v2.7.0 baseline: 297/297).
|
|
192
|
+
|
|
193
|
+
### Bundle
|
|
194
|
+
|
|
195
|
+
Delta vs v2.7.0 baseline (`e8d9a74e`):
|
|
196
|
+
|
|
197
|
+
| Artifact | v2.7.0 | v2.7.1 | Δ bytes | Δ % |
|
|
198
|
+
|----------|--------|--------|---------|-----|
|
|
199
|
+
| `dist/tsgrid-ui.js` (CJS) | 947,274 B | 947,277 B | +3 B | +0.0003% |
|
|
200
|
+
| `dist/tsgrid-ui.es6.js` (ESM) | 945,466 B | 945,470 B | +4 B | +0.0004% |
|
|
201
|
+
| `dist/tsgrid-ui.min.js` (CJS min) | 509,260 B | 509,263 B | +3 B | +0.0003% |
|
|
202
|
+
| `dist/tsgrid-ui.es6.min.js` (ESM min) | 508,125 B | 508,129 B | +4 B | +0.0004% |
|
|
203
|
+
| `dist/tsgrid-ui.d.ts` | 94,446 B | 94,446 B | 0 B | 0.0000% |
|
|
204
|
+
| `dist/tsgrid-ui.css` | 246,980 B | 246,979 B | -1 B | -0.0004% |
|
|
205
|
+
| `dist/tsgrid-ui.min.css` | 229,707 B | 229,706 B | -1 B | -0.0004% |
|
|
206
|
+
|
|
207
|
+
All within ±2% gate. PASSED. JS bundles grew by +3–4 B (3 small fixes + new INV-L7-* inline comments — Terser strips comments in min bundles so min delta is tiny). The `d.ts` is **byte-identical** to v2.7.0 (INV-L7-API PASS — `locale(` signature unchanged). CSS delta is icon-noise (non-deterministic gulp regen, ±1 B).
|
|
208
|
+
|
|
209
|
+
### BC
|
|
210
|
+
|
|
211
|
+
- `TsUtils.locale(locale, keepPhrases?, noMerge?): Promise<{ file: string; data: unknown } | void>` — signature **BYTE-IDENTICAL** to v2.7.0. Public API surface unchanged. `dist/tsgrid-ui.d.ts` `locale(` line unchanged (INV-L7-API PASS).
|
|
212
|
+
- **Behavior corrections** (PATCH-classifiable per SemVer §6 — implementation now matches documented intent in all three cases):
|
|
213
|
+
- `await Utils.locale(lang, false /* keepPhrases */)` no longer preserves pre-existing `settings.phrases` keys (now matches the in-code comment "clear phrases from language before merging").
|
|
214
|
+
- `await Utils.locale([...])` no longer mutates the input array (caller's array reference + contents are byte-identical post-call).
|
|
215
|
+
- The internal array-branch `mergedSettings` accumulator no longer leaks pre-existing phrase keys into the fanout.
|
|
216
|
+
- `src/index.ts` barrel — **byte-identical** to v2.7.0 (INV-7 PASS).
|
|
217
|
+
- SEMVER PATCH. BC verdict: NONE for consumers using the documented behavior; latent-bug-correction for consumers depending on the never-documented broken behavior (none identified in repo audit).
|
|
218
|
+
|
|
219
|
+
### Known issues
|
|
220
|
+
|
|
221
|
+
- **R-LOC-3** (carry-forward from v2.6 / v2.7): Locale extraction does NOT directly unblock formatter extraction. The `format()` family still has its own deps-injection requirement; will be tackled separately in v2.8 via a `FormatterDeps` cluster.
|
|
222
|
+
- `R-LOC-V26-PRESERVED`, `R-LOC-2`, `R-V271-4` — **REMOVED** (now fixed; see §Fixed above).
|
|
223
|
+
|
|
224
|
+
### Internal
|
|
225
|
+
|
|
226
|
+
- `INV-L7-PHRASES-CLEAR` (NEW invariant): When `keepPhrases=false` (string branch) OR array-branch init, the resulting `settings.phrases` MUST NOT contain keys from the pre-call `settings.phrases` that are absent from `TsLocale.phrases` (and `data.phrases` for the string branch). Gated by `T-LOC-5` (flipped) + `T-LOC-12` (new).
|
|
227
|
+
- `INV-L7-IMMUTABLE-INPUT` (NEW invariant): `_locale()` MUST NOT mutate the `locale` argument when it is an array. Caller's array reference + contents are byte-identical post-call. Gated by `T-LOC-11` (new).
|
|
228
|
+
- `INV-L7-LEAF` (carry, PASS): `tsutils-locale.ts` runtime imports limited to `./tslocale.js`; type-only from `./tsutils.js`. No tsbase/tsutils runtime imports.
|
|
229
|
+
- `INV-9` (carry, PASS): zero `this.X` references in `_locale()` body.
|
|
230
|
+
- `INV-LINT-INV8` canary (carry, PASS): `src/tsutils-*.ts` ESLint glob covers `tsutils-locale.ts`.
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
5
234
|
## v2.7.0 — 2026-05-14
|
|
6
235
|
|
|
7
236
|
### Refactor
|
package/dist/base.d.ts
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Part of TsUi 2.0 library
|
|
3
|
+
* - Dependencies: TsUtils
|
|
4
|
+
* - on/off/trigger methods id not showing in help
|
|
5
|
+
* - refactored with event object
|
|
6
|
+
*
|
|
7
|
+
* Chanes in 2.0.+
|
|
8
|
+
* - added unmount that cleans up the box
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Payload object passed to handlers registered via `.on(eventName, handler)`.
|
|
13
|
+
*
|
|
14
|
+
* IMPORTANT — circular references:
|
|
15
|
+
* `event.owner` points back to the widget that triggered the event, and that
|
|
16
|
+
* widget keeps `activeEvents: TsEvent[]` referencing this same payload.
|
|
17
|
+
* Calling `JSON.stringify(event)` will throw "Converting circular structure
|
|
18
|
+
* to JSON". Use `toSafeEvent(event)` from `tsgrid-ui` to extract a
|
|
19
|
+
* serializable subset before storing in reactive state (Angular signals,
|
|
20
|
+
* React state, Pinia/Redux stores, etc.).
|
|
21
|
+
*
|
|
22
|
+
* Note: the per-class declarations like `onSelect: (event: CustomEvent) => void`
|
|
23
|
+
* in TsGrid/TsForm/etc. are historical noise — the runtime always passes a
|
|
24
|
+
* `TsEventPayload`, never a DOM `CustomEvent`. This will be corrected in v2.0.
|
|
25
|
+
*/
|
|
26
|
+
interface TsEventPayload<TDetail = unknown> {
|
|
27
|
+
type: string | null;
|
|
28
|
+
phase: 'before' | 'after' | string;
|
|
29
|
+
detail: TDetail & TsEventData;
|
|
30
|
+
target: unknown;
|
|
31
|
+
object: unknown;
|
|
32
|
+
isStopped: boolean;
|
|
33
|
+
isCancelled: boolean;
|
|
34
|
+
/** Reference to the widget that triggered this event. CIRCULAR — do not serialize. */
|
|
35
|
+
owner: unknown;
|
|
36
|
+
}
|
|
37
|
+
interface TsEventData {
|
|
38
|
+
type?: string | null;
|
|
39
|
+
target?: unknown;
|
|
40
|
+
phase?: string;
|
|
41
|
+
object?: unknown;
|
|
42
|
+
[key: string]: unknown;
|
|
43
|
+
}
|
|
44
|
+
interface TsEventListener {
|
|
45
|
+
name: string;
|
|
46
|
+
edata: {
|
|
47
|
+
type: string | null;
|
|
48
|
+
execute: string;
|
|
49
|
+
onComplete: null;
|
|
50
|
+
scope?: string;
|
|
51
|
+
handler?: unknown;
|
|
52
|
+
[key: string]: unknown;
|
|
53
|
+
};
|
|
54
|
+
handler: Function;
|
|
55
|
+
}
|
|
56
|
+
declare class TsEvent {
|
|
57
|
+
type: string | null;
|
|
58
|
+
detail: TsEventData;
|
|
59
|
+
owner: TsBase;
|
|
60
|
+
target: unknown;
|
|
61
|
+
phase: string;
|
|
62
|
+
object: unknown;
|
|
63
|
+
execute: null;
|
|
64
|
+
isStopped: boolean;
|
|
65
|
+
isCancelled: boolean;
|
|
66
|
+
onComplete: ((edata: TsEvent) => void) | null;
|
|
67
|
+
listeners: Array<(edata: TsEvent) => void>;
|
|
68
|
+
complete: Promise<TsEvent>;
|
|
69
|
+
_resolve: (value: TsEvent) => void;
|
|
70
|
+
_reject: (reason?: unknown) => void;
|
|
71
|
+
constructor(owner: TsBase, edata: TsEventData);
|
|
72
|
+
finish(detail?: Partial<TsEventData>): void;
|
|
73
|
+
done(func: (edata: TsEvent) => void): void;
|
|
74
|
+
preventDefault(): void;
|
|
75
|
+
stopPropagation(): void;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Extract a JSON-serializable subset of a TsEvent payload, dropping the
|
|
79
|
+
* circular `owner` and `complete` references. Use before storing in
|
|
80
|
+
* Angular signals, React state, Pinia/Redux stores, or any DevTools that
|
|
81
|
+
* snapshots state via JSON.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* grid.on('select', (event) => {
|
|
85
|
+
* this.lastSelection.set(toSafeEvent(event))
|
|
86
|
+
* })
|
|
87
|
+
*/
|
|
88
|
+
declare function toSafeEvent<TDetail = unknown>(event: unknown): {
|
|
89
|
+
type: string | null;
|
|
90
|
+
phase: string;
|
|
91
|
+
detail: TDetail & TsEventData;
|
|
92
|
+
isStopped: boolean;
|
|
93
|
+
isCancelled: boolean;
|
|
94
|
+
};
|
|
95
|
+
declare class TsBase {
|
|
96
|
+
activeEvents: TsEvent[];
|
|
97
|
+
listeners: TsEventListener[];
|
|
98
|
+
debug: boolean;
|
|
99
|
+
name?: string;
|
|
100
|
+
box?: HTMLElement | null;
|
|
101
|
+
[key: string]: unknown;
|
|
102
|
+
/**
|
|
103
|
+
* Initializes base object for TsUi, registers it with TsUi object
|
|
104
|
+
*
|
|
105
|
+
* @param {string} name - name of the object
|
|
106
|
+
* @returns
|
|
107
|
+
*/
|
|
108
|
+
constructor(name?: string);
|
|
109
|
+
/**
|
|
110
|
+
* Adds event listener, supports event phase and event scoping
|
|
111
|
+
*
|
|
112
|
+
* @param {*} edata - an object or string, if string "eventName:phase.scope"
|
|
113
|
+
* @param {*} handler
|
|
114
|
+
* @returns itself
|
|
115
|
+
*/
|
|
116
|
+
on(events: string | TsEventData | Array<string | TsEventData>, handler: Function): this;
|
|
117
|
+
/**
|
|
118
|
+
* Removes event listener, supports event phase and event scoping
|
|
119
|
+
*
|
|
120
|
+
* @param {*} edata - an object or string, if string "eventName:phase.scope"
|
|
121
|
+
* @param {*} handler
|
|
122
|
+
* @returns itself
|
|
123
|
+
*/
|
|
124
|
+
off(events: string | TsEventData | Array<string | TsEventData>, handler?: Function): this;
|
|
125
|
+
/**
|
|
126
|
+
* Triggers even listeners for a specific event, loops through this.listeners
|
|
127
|
+
*
|
|
128
|
+
* @param {Object} edata - Object
|
|
129
|
+
* @returns modified edata
|
|
130
|
+
*
|
|
131
|
+
* NOTE: `edata` is typed as `any` here intentionally. The method mutates the argument
|
|
132
|
+
* from TsEventData into a TsEvent mid-execution. Runtime type mutation is inherent
|
|
133
|
+
* to the event dispatch pattern. Phase 6 strict tighten will revisit this.
|
|
134
|
+
*/
|
|
135
|
+
trigger(eventName: string | TsEventData | TsEvent, edataIn?: TsEventData): TsEvent;
|
|
136
|
+
/**
|
|
137
|
+
* This method renders component into the box. It is overwritten in descendents and in this base
|
|
138
|
+
* component it is empty.
|
|
139
|
+
*/
|
|
140
|
+
render(_box?: HTMLElement | string | null): void;
|
|
141
|
+
/**
|
|
142
|
+
* Removes all classes that start with tsg-* and sets box to null. It is needed so that control will
|
|
143
|
+
* release the box to be used for other widgets
|
|
144
|
+
*/
|
|
145
|
+
unmount(): void;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export { TsBase, TsEvent, type TsEventData, type TsEventListener, type TsEventPayload, toSafeEvent };
|
package/dist/base.es6.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|