@toclocoinc/lattice-grid 1.11.0 → 1.12.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/README.md CHANGED
@@ -4,24 +4,24 @@
4
4
  dependencies, no build step required. Optional adapters for React, Vue, Svelte
5
5
  and Web Components ship alongside it.
6
6
 
7
- Version 1.11.0 · [latticegrid.dev](https://www.latticegrid.dev) · TOCLOCO Inc
7
+ Version 1.12.0 · [latticegrid.dev](https://www.latticegrid.dev) · TOCLOCO Inc
8
8
 
9
9
  ---
10
10
 
11
11
  ## What's here
12
12
 
13
13
  This repository is the distribution: the built library, its type declarations
14
- and the documentation. Everything is self-contained nothing is fetched at
14
+ and the documentation. Everything is self-contained: nothing is fetched at
15
15
  runtime, not a CDN, not a font, not an icon sprite.
16
16
 
17
17
  | File | What it is |
18
18
  |---|---|
19
- | `lattice-grid.min.js` | The library. UMD works with a `<script>` tag. |
19
+ | `lattice-grid.min.js` | The library. UMD: works with a `<script>` tag. |
20
20
  | `lattice-grid.esm.min.js` | The same, as an ES module. |
21
21
  | `lattice-grid.min.css` | The theme. Required. |
22
22
  | `lattice-grid.d.ts` | TypeScript declarations. |
23
23
  | `docs/API.html` | The complete API reference. |
24
- | `docs/api-detail.html` | The developer guide what each part does, and why. |
24
+ | `docs/api-detail.html` | The developer guide: what each part does, and why. |
25
25
 
26
26
  Every module is optional and none of them is loaded unless you import it.
27
27
 
@@ -32,7 +32,7 @@ Every module is optional and none of them is loaded unless you import it.
32
32
  | `modules/vue.esm.min.js` | Vue adapter. |
33
33
  | `modules/svelte.esm.min.js` | Svelte adapter. |
34
34
  | `modules/webcomponent.esm.min.js` | `<lattice-grid>` as a custom element. |
35
- | `modules/htmx.esm.min.js` | htmx integration survives htmx's DOM swaps, hydrates from a server-rendered `<table>`, and drives sort, filter and infinite scroll over plain htmx requests. UMD and CJS builds sit beside it. |
35
+ | `modules/htmx.esm.min.js` | htmx integration: survives htmx's DOM swaps, hydrates from a server-rendered `<table>`, and drives sort, filter and infinite scroll over plain htmx requests. UMD and CJS builds sit beside it. |
36
36
  | `modules/dhtmlx-compat.esm.min.js` | A compatibility wrapper for dhtmlx Grid, for moving an existing integration across without rewriting it. |
37
37
  | `modules/devtools.esm.min.js` | The devtools panel, including the accessibility checks. |
38
38
 
@@ -55,20 +55,20 @@ enough to know whether the grid covers what you need.
55
55
  - **Live data.** `rows.apply({add, update, remove})` patches in place: the grid
56
56
  re-queries the stages a change actually touched and repaints the cells that
57
57
  moved. A feed can be paused and resumed with the queue held.
58
- - **Any source.** Rows in memory, or a source you write server-side paging,
58
+ - **Any source.** Rows in memory, or a source you write: server-side paging,
59
59
  infinite scroll, streaming, or an async provider. Sorting and filtering can be
60
60
  handed to the server or left to the grid.
61
61
 
62
62
  ### Working with the data
63
63
 
64
- - **Editing.** Cell, row and form editing, with twenty-three editors text,
64
+ - **Editing.** Cell, row and form editing, with twenty-three editors: text,
65
65
  number, date, time, select, multi-select, colour, rating, slider, segmented,
66
66
  code, password, icon picker and more. Validation, async commits, optimistic
67
67
  updates with rollback, and a full undo history.
68
68
  - **Selection and ranges.** Cell, row, column and rectangular range selection,
69
69
  with clipboard behaviour that round-trips through Excel.
70
70
  - **Fill, copy and paste** across a range, including formulas.
71
- - **Formulas.** A closed, safe expression language no `eval`, no host access
71
+ - **Formulas.** A closed, safe expression language, no `eval`, no host access ,
72
72
  with maths, text, logic, date and statistical functions, evaluated against
73
73
  other columns.
74
74
  - **Export.** CSV with fields sanitised against formula injection, real `.xlsx`
@@ -79,18 +79,18 @@ enough to know whether the grid covers what you need.
79
79
  ### Seeing the data
80
80
 
81
81
  - **Charts.** `modules/charts` draws thirty-five chart types from the grid's own
82
- data line, bar, area, scatter, pie, donut, sunburst, treemap, radar, gauge,
82
+ data: line, bar, area, scatter, pie, donut, sunburst, treemap, radar, gauge,
83
83
  funnel, heatmap, histogram, box plot, candlestick, combo, geomap, sankey,
84
84
  chord, network, stream, violin, gantt and more. They follow the grid's
85
85
  filters, and clicking a mark can filter it in turn.
86
- - **Statistics.** `grid.statistics` profiles a column in one pass count,
86
+ - **Statistics.** `grid.statistics` profiles a column in one pass: count,
87
87
  missing, distinct, five-number summary, standard deviation, outliers and a
88
- histogram and answers correlations and weighted averages. Thirty-eight
88
+ histogram, and answers correlations and weighted averages. Thirty-eight
89
89
  reduction kernels are available to the totals row, and you can register your
90
90
  own.
91
91
  - **Shadow columns.** Values the grid maintains about itself: how many times a
92
92
  row has changed, what a value was when the page loaded, how fast it is moving,
93
- its rank, percentile or share of the total. Real columns sortable,
93
+ its rank, percentile or share of the total. Real columns: sortable,
94
94
  filterable, exportable, saved into a view.
95
95
  - **Conditional formatting** as runtime state a user can change, with rules that
96
96
  either name a threshold or describe the data: the top decile, the outliers,
@@ -102,14 +102,14 @@ enough to know whether the grid covers what you need.
102
102
 
103
103
  - **Tool panels** for columns, filters, views, quick filter, formatting and
104
104
  statistics, docked or as an icon rail.
105
- - **Saved views** the whole grid state as a named, shareable object, stored
105
+ - **Saved views**, the whole grid state as a named, shareable object, stored
106
106
  on your server or in the browser.
107
107
  - **Column menu, context menu and status bar**, each extensible with your own
108
108
  items.
109
109
  - **Pinned columns and rows**, column groups, resize, reorder, autosize, and a
110
110
  density control.
111
111
  - **Master–detail rows**, tree data, and full-width rows.
112
- - **Presence** live cursors, selections and edit locks for collaborative use,
112
+ - **Presence**: live cursors, selections and edit locks for collaborative use,
113
113
  carrying intent and never values.
114
114
  - **Comments** threaded on cells, and an annotation layer for presenting.
115
115
  - **Full-screen mode**, print, and image capture.
@@ -126,7 +126,7 @@ enough to know whether the grid covers what you need.
126
126
  a reset that keeps a host page's stylesheet out.
127
127
  - **Typed.** Complete TypeScript declarations, checked against the runtime on
128
128
  every build.
129
- - **Zero runtime dependencies.** Nothing is fetched at runtime not a CDN, not
129
+ - **Zero runtime dependencies.** Nothing is fetched at runtime, not a CDN, not
130
130
  a font, not an icon sprite.
131
131
 
132
132
  ---
@@ -189,7 +189,7 @@ const LatticeGrid = createLatticeGrid({ React, createGrid });
189
189
  ```
190
190
 
191
191
  The web component is the exception: it carries the grid inside it, so use it *or*
192
- `createGrid` in a page, not both two copies keep separate registries, and a
192
+ `createGrid` in a page, not both, two copies keep separate registries, and a
193
193
  renderer registered through one will not appear in the other.
194
194
 
195
195
  The full setup for each framework is in the developer guide.
@@ -200,9 +200,9 @@ Two integrations that are not framework adapters.
200
200
 
201
201
  **htmx.** `modules/htmx` lets a grid survive htmx's own DOM swaps, hydrate from
202
202
  a server-rendered `<table>`, and drive sort, filter and infinite scroll over
203
- plain htmx requests. It is a complete package rather than an add-on
203
+ plain htmx requests. It is a complete package rather than an add-on ,
204
204
  `createGrid`, `autoInit`, `hydrateTable`, `readTable`, `serialiseState` and
205
- `restoreState` are re-exported alongside its own functions so a page using it
205
+ `restoreState` are re-exported alongside its own functions, so a page using it
206
206
  imports this and never the base package as well.
207
207
 
208
208
  **dhtmlx.** `modules/dhtmlx-compat` exposes a dhtmlx Grid-shaped API over
@@ -212,7 +212,7 @@ than rewriting it in one go.
212
212
  ### TypeScript
213
213
 
214
214
  Declarations ship in the box and are wired up in `package.json`, so editors find
215
- them without configuration autocomplete, inline documentation and type
215
+ them without configuration: autocomplete, inline documentation and type
216
216
  checking against the real API.
217
217
 
218
218
  ```ts
@@ -228,7 +228,7 @@ your editor tells you and what the grid does cannot drift apart.
228
228
 
229
229
  A grid usually lives in whatever box the page layout gave it, and that box is
230
230
  usually too small for the job. The left rail's last button fills the browser
231
- window with the grid; clicking it again or pressing <kbd>Esc</kbd> puts it
231
+ window with the grid; clicking it again, or pressing <kbd>Esc</kbd>: puts it
232
232
  back exactly where it was.
233
233
 
234
234
  ```js
@@ -248,8 +248,8 @@ it was found.
248
248
 
249
249
  ## Data types
250
250
 
251
- Seven built-in types `text`, `number`, `boolean`, `date`, `dateString`,
252
- `object` and `lookup` cover ordinary business data and are inferred from your
251
+ Seven built-in types: `text`, `number`, `boolean`, `date`, `dateString`,
252
+ `object` and `lookup`: cover ordinary business data and are inferred from your
253
253
  rows automatically.
254
254
 
255
255
  Beyond those, Lattice Grid ships **88 technical field types** for the data that
@@ -259,16 +259,16 @@ editor, filter, alignment, clipboard behaviour and Excel mapping.
259
259
 
260
260
  | Group | Types |
261
261
  |---|---|
262
- | **Network** | `ipv4`, `ipv6`, `cidr` sort in address order, not lexically, so `10.0.0.9` comes before `10.0.0.10`. |
263
- | **Time** | `time`, `datetime`, `duration` three things a single `date` type keeps being asked to be. |
264
- | **Radix** | `hex`, `hex8`, `hex16`, `hex32`, `binary`, `binary8`, `octal` the stored value stays a plain number; the base is presentation and input only. |
265
- | **Data** | `bytes`, `megabytes`, `gigabytes`, `bitrate`, `gigabits` shows `10 GB`, accepts `10,000M` typed in, stores `10`. Decimal and binary ladders are both first class, because `MB` and `MiB` are different quantities. |
262
+ | **Network** | `ipv4`, `ipv6`, `cidr`: sort in address order, not lexically, so `10.0.0.9` comes before `10.0.0.10`. |
263
+ | **Time** | `time`, `datetime`, `duration`: three things a single `date` type keeps being asked to be. |
264
+ | **Radix** | `hex`, `hex8`, `hex16`, `hex32`, `binary`, `binary8`, `octal`, the stored value stays a plain number; the base is presentation and input only. |
265
+ | **Data** | `bytes`, `megabytes`, `gigabytes`, `bitrate`, `gigabits`: shows `10 GB`, accepts `10,000M` typed in, stores `10`. Decimal and binary ladders are both first class, because `MB` and `MiB` are different quantities. |
266
266
  | **Mechanical** | length, mass, duration, speed, acceleration, area, volume, force, pressure, torque, density, energy, power, angle, `rpm` and angular velocity. |
267
267
  | **Fluid and thermal** | volumetric flow, mass flow, dynamic and kinematic viscosity, thermal conductivity, specific heat, and temperature in `celsius`, `fahrenheit` and `kelvin`. |
268
- | **Electrical and SI** | voltage, current, resistance, capacitance, inductance, charge, conductance, frequency, flux density, luminous flux, luminous intensity, illuminance and substance all auto-prefixed across the SI range. |
268
+ | **Electrical and SI** | voltage, current, resistance, capacitance, inductance, charge, conductance, frequency, flux density, luminous flux, luminous intensity, illuminance and substance: all auto-prefixed across the SI range. |
269
269
  | **Chemistry and radiation** | `molarity`, `ppm`, `ppb`, absorbed dose, equivalent dose, radioactivity and dose rate. |
270
- | **Finance and ratios** | `basisPoints`, `ratio`, `percentRate`, and decibels which are reduced logarithmically, not averaged. |
271
- | **Structured** | `json`, `secret` `secret` is write-only: editable, never displayed, never exported. |
270
+ | **Finance and ratios** | `basisPoints`, `ratio`, `percentRate`, and decibels, which are reduced logarithmically, not averaged. |
271
+ | **Structured** | `json`, `secret`: `secret` is write-only: editable, never displayed, never exported. |
272
272
 
273
273
  ### Units of your own
274
274
 
@@ -297,7 +297,7 @@ createGrid(el, {
297
297
 
298
298
  `display: 'auto'` walks the ladder and picks the most readable rung, so 1,500
299
299
  tex renders as `1.5 ktex`. A unit given `{ auto: false }` stays off that ladder
300
- while remaining accepted on input and available as an explicit `display` which
300
+ while remaining accepted on input and available as an explicit `display`: which
301
301
  is how imperial units sit beside metric ones without an auto readout jumping
302
302
  between the two.
303
303
 
@@ -313,15 +313,15 @@ createUnitType({ system: 'money', unit: '$', placement: 'prefix', decimals: 2 })
313
313
  ```
314
314
 
315
315
  Whatever the display, **the stored value is always a plain number in the
316
- column's base unit** so sorting, filtering, grouping, totals and the pivot all
316
+ column's base unit**, so sorting, filtering, grouping, totals and the pivot all
317
317
  work on the number and never on the text.
318
318
 
319
319
  ---
320
320
 
321
321
  ## Documentation
322
322
 
323
- - **[API reference](docs/API.html)** every namespace, method, config key and event.
324
- - **[Developer guide](docs/api-detail.html)** what each part does and why, with worked examples.
323
+ - **[API reference](docs/API.html)**: every namespace, method, config key and event.
324
+ - **[Developer guide](docs/api-detail.html)**: what each part does and why, with worked examples.
325
325
 
326
326
  ---
327
327
 
@@ -335,7 +335,7 @@ edition, no pro tier, no feature held back behind a key.
335
335
  - **Licensed to deploy.** On any other host, an unlicensed grid renders
336
336
  everything and carries a small trial watermark.
337
337
 
338
- Nothing is ever disabled, degraded or withheld the failure to avoid is a
338
+ Nothing is ever disabled, degraded or withheld, the failure to avoid is a
339
339
  production screen breaking because a licence lapsed over a weekend. A key
340
340
  removes the watermark; that is the whole of what it does.
341
341
 
package/docs/AI-SKILL.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # The AI skill layer
2
2
 
3
3
  A prompt input above the grid that turns "EMEA deals over 50k, biggest first"
4
- into a filter and a sort via whichever language model you choose.
4
+ into a filter and a sort: via whichever language model you choose.
5
5
 
6
6
  This document has two halves. The first is for the developer wiring it up. The
7
7
  second is written to be handed to a model, and describes the grid as a skill it
@@ -14,18 +14,18 @@ can drive.
14
14
  **The grid never calls a language model. It makes no network request of any
15
15
  kind.** It calls one async callback you supply, and whatever that callback
16
16
  returns is validated and previewed. You own the model, the API key, the
17
- request, and the part that matters the privacy decision.
17
+ request, and (the part that matters) the privacy decision.
18
18
 
19
19
  By default the callback receives:
20
20
 
21
- - `schema` the generated description of your columns: ids, titles, types,
21
+ - `schema`, the generated description of your columns: ids, titles, types,
22
22
  which are filterable/sortable/groupable, and the declared option lists of
23
23
  lookup columns.
24
- - `context` **empty**, unless you put something in it.
24
+ - `context`: **empty**, unless you put something in it.
25
25
 
26
26
  **No row values leave the grid.** Not a sample, not a summary, not the first
27
- page. If you want the model to see data and for some questions it genuinely
28
- helps you put it in `context` yourself, deliberately, having decided that
27
+ page. If you want the model to see data, and for some questions it genuinely
28
+ helps: you put it in `context` yourself, deliberately, having decided that
29
29
  sending it to a third party is acceptable for that data, that tenant and that
30
30
  jurisdiction. There is no flag that turns it on by accident.
31
31
 
@@ -43,7 +43,7 @@ Two things worth knowing before you do:
43
43
 
44
44
  ---
45
45
 
46
- # Part one wiring it up
46
+ # Part one: wiring it up
47
47
 
48
48
  ## Setup
49
49
 
@@ -68,7 +68,7 @@ gets a preview:
68
68
  > **Filter Region is EMEA, sort Margin descending**
69
69
  > [ Apply ] [ Discard ]
70
70
 
71
- Nothing changes until Apply. That is not a configurable nicety it is the
71
+ Nothing changes until Apply. That is not a configurable nicety, it is the
72
72
  reason the feature is shippable to a customer with an audit function.
73
73
 
74
74
  ## The callback contract
@@ -186,13 +186,13 @@ if (plan.ok && await userConfirms(plan.describe())) {
186
186
 
187
187
  `plan` is `{ ok, actions, rejected, explain, describe() }`:
188
188
 
189
- - `ok` true when at least one action survived validation.
190
- - `actions` the validated, normalised actions.
191
- - `rejected` `{ at, what, reason }` for every part refused, whether or not
189
+ - `ok`: true when at least one action survived validation.
190
+ - `actions`, the validated, normalised actions.
191
+ - `rejected`: `{ at, what, reason }` for every part refused, whether or not
192
192
  anything survived. Show these: a user approving three of five conditions
193
193
  needs to see the other two.
194
- - `explain` the model's own one-liner. Informational only.
195
- - `describe()` the plan in English, **built from the validated actions**, not
194
+ - `explain`, the model's own one-liner. Informational only.
195
+ - `describe()`, the plan in English, **built from the validated actions**, not
196
196
  from `explain`. A model is not a reliable narrator of its own output.
197
197
 
198
198
  ## Keeping the schema small
@@ -200,7 +200,7 @@ if (plan.ok && await userConfirms(plan.describe())) {
200
200
  A 200-column grid with a 5,000-option lookup on every column would produce a
201
201
  schema nobody can afford to send, and a schema truncated by the transport is a
202
202
  schema the model silently misreads. Everything is budgeted, and every cut is
203
- reported in `schema.truncated` and stated in the prompt text a model told
203
+ reported in `schema.truncated` and stated in the prompt text, a model told
204
204
  "20 of 812 options shown" asks for the rest or falls back to `contains`,
205
205
  whereas one shown a silently short list concludes those 20 are all there is.
206
206
 
@@ -222,7 +222,7 @@ ai: {
222
222
  ## Events
223
223
 
224
224
  Applying goes through `filters.set`, `sort.set`, `columns.group`,
225
- `columns.show` and `columns.hide` the public API, nothing private. So a
225
+ `columns.show` and `columns.hide`, the public API, nothing private. So a
226
226
  model-driven change emits the same `filter:changed`, `sort:changed` and
227
227
  `model:changed` events, lands in the same `state.get()` snapshot, and sits on
228
228
  the same undo path as the user having done it by hand. If you want to record
@@ -262,12 +262,12 @@ And the boundary this feature does *not* claim:
262
262
  > boundary against a hostile model. **Never give a model more authority than
263
263
  > the user already has.** Run the callback with the user's own credentials,
264
264
  > filter server-side by the user's own permissions, and treat what comes back
265
- > as a suggestion from an untrusted source because that is exactly what it
265
+ > as a suggestion from an untrusted source, because that is exactly what it
266
266
  > is.
267
267
 
268
268
  ---
269
269
 
270
- # Part two the skill, for the model
270
+ # Part two, the skill, for the model
271
271
 
272
272
  *Everything below is written to be given to a model, whether pasted into a
273
273
  system prompt or emitted by `promptText(schema)`.*
@@ -276,7 +276,7 @@ system prompt or emitted by `promptText(schema)`.*
276
276
 
277
277
  You can reshape a Lattice data grid: filter rows, sort them, group them, and
278
278
  show or hide columns. You cannot read, edit, delete or export data, and you
279
- cannot run code. Your output is a proposal a human sees a plain-English
279
+ cannot run code. Your output is a proposal, a human sees a plain-English
280
280
  summary of it and decides whether to apply it.
281
281
 
282
282
  You will be given a schema listing every column: its id, its title, its family,
@@ -307,7 +307,7 @@ Reply with one JSON object and no other text:
307
307
  | `setQuick` | `text` | Sets the quick filter, which matches across every column |
308
308
  | `clear` | `what` | One of `filters`, `sort`, `group`, `quick`, `all` |
309
309
 
310
- Nothing outside this table exists. To remove something, use `clear` an empty
310
+ Nothing outside this table exists. To remove something, use `clear`, an empty
311
311
  `setSort` or `groupBy` is rejected, not treated as a clear.
312
312
 
313
313
  ### Filters
@@ -356,7 +356,7 @@ Which operators apply depends on the column's **family**, given in the schema:
356
356
  | `object` | `eq` `ne` `blank` `notBlank` |
357
357
 
358
358
  `contains` on a number column is rejected. So is `eq` on a `lookupMulti`
359
- column, whose cells hold arrays use `containsAny`.
359
+ column, whose cells hold arrays: use `containsAny`.
360
360
 
361
361
  Dates are ISO 8601 strings: `"2026-01-01"` or `"2026-01-01T00:00:00Z"`.
362
362
 
@@ -396,7 +396,7 @@ notes | Notes | text |
396
396
  ```json
397
397
  {
398
398
  "actions": [ { "type": "groupBy", "columns": ["region"] } ],
399
- "explain": "Grouped by region. I cannot add total rows that is a grid setting."
399
+ "explain": "Grouped by region. I cannot add total rows: that is a grid setting."
400
400
  }
401
401
  ```
402
402
 
@@ -436,7 +436,7 @@ column is the commonest way to answer this question wrongly.
436
436
  { "actions": [ { "type": "clear", "what": "all" } ], "explain": "Cleared the view." }
437
437
  ```
438
438
 
439
- **"sort by notes"** `notes` has no capabilities listed, so it cannot be
439
+ **"sort by notes"**: `notes` has no capabilities listed, so it cannot be
440
440
  sorted:
441
441
 
442
442
  ```json