@toclocoinc/lattice-grid 1.26.0 → 1.27.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 +1 -1
- package/docs/API.html +211 -15
- package/docs/api-detail.html +163 -5
- package/lattice-grid.d.ts +422 -25
- package/lattice-grid.esm.min.js +2743 -536
- package/lattice-grid.min.cjs +2738 -536
- package/lattice-grid.min.css +1 -1
- package/lattice-grid.min.js +2738 -536
- package/modules/charts.esm.min.js +24 -8
- package/modules/charts.min.cjs +24 -8
- package/modules/charts.min.js +24 -8
- package/modules/devtools.esm.min.js +2 -2
- package/modules/devtools.min.cjs +2 -2
- package/modules/devtools.min.js +2 -2
- package/modules/dhtmlx-compat.esm.min.js +4 -4
- package/modules/dhtmlx-compat.min.cjs +4 -4
- package/modules/dhtmlx-compat.min.js +4 -4
- package/modules/htmx.esm.min.js +3018 -272
- package/modules/htmx.min.cjs +2884 -272
- package/modules/htmx.min.js +2884 -272
- package/modules/react.esm.min.js +13 -2
- package/modules/react.min.cjs +13 -2
- package/modules/react.min.js +13 -2
- package/modules/svelte.esm.min.js +31 -5
- package/modules/svelte.min.cjs +31 -5
- package/modules/svelte.min.js +31 -5
- package/modules/vue.esm.min.js +21 -3
- package/modules/vue.min.cjs +21 -3
- package/modules/vue.min.js +21 -3
- package/modules/webcomponent.esm.min.js +2746 -536
- package/modules/webcomponent.min.cjs +2742 -536
- package/modules/webcomponent.min.js +2742 -536
- package/package.json +1 -1
package/docs/api-detail.html
CHANGED
|
@@ -437,7 +437,7 @@
|
|
|
437
437
|
<div class="shell">
|
|
438
438
|
<aside class="rail">
|
|
439
439
|
<p class="rail__brand">Lattice Grid</p>
|
|
440
|
-
<p class="rail__sub">Developer guide · v1.
|
|
440
|
+
<p class="rail__sub">Developer guide · v1.27.0</p>
|
|
441
441
|
<nav>
|
|
442
442
|
<div class="rail__group">
|
|
443
443
|
<span class="rail__label">Start here</span>
|
|
@@ -835,10 +835,12 @@ createGrid(element, { direction: 'rtl' }); <span class="cmt">// or say so out
|
|
|
835
835
|
|
|
836
836
|
<span class="kw">const</span> lattice = createLatticeAction({ createGrid });
|
|
837
837
|
<span class="kw">let</span> rows = [];
|
|
838
|
+
<span class="kw">let</span> grid;
|
|
838
839
|
</script>
|
|
839
840
|
|
|
840
841
|
<div
|
|
841
|
-
use:lattice={{ columns, rows, rowKey: 'id' }}
|
|
842
|
+
use:lattice={{ columns, rows, rowKey: 'id', onGrid: (g) => (grid = g) }}
|
|
843
|
+
on:ready={(e) => (grid = e.detail.grid)}
|
|
842
844
|
on:cell-changed={(e) => save(e.detail)}
|
|
843
845
|
></div></code></pre>
|
|
844
846
|
</div>
|
|
@@ -851,13 +853,92 @@ createGrid(element, { direction: 'rtl' }); <span class="cmt">// or say so out
|
|
|
851
853
|
framework runtime behind it. Grid events arrive as <code>CustomEvent</code>s on the node,
|
|
852
854
|
with the grid event as <code>detail</code>. If you want a component, four lines around this
|
|
853
855
|
gets you one.</p>
|
|
856
|
+
<p><strong>Reaching the grid.</strong> The action's return value is Svelte's
|
|
857
|
+
<code>{ update, destroy }</code> and cannot carry the instance, so — at parity with React's
|
|
858
|
+
<code>ref.current.grid</code> and Vue's <code>expose({ grid })</code> — there are two documented
|
|
859
|
+
routes to the same object the vanilla examples use, for charts, statistics and imperative
|
|
860
|
+
pivot. Pass an <code>onGrid</code> callback in the action params and it is called once with the
|
|
861
|
+
live grid the moment it is created (synchronously, before the first render); it is consumed by
|
|
862
|
+
the adapter and never reaches the grid config. Or read it off the <code>ready</code> event,
|
|
863
|
+
whose <code>detail</code> carries <code>{ grid }</code> alongside the event's own fields —
|
|
864
|
+
<code>ready</code> fires a turn later, so use <code>onGrid</code> when you need it up front.</p>
|
|
865
|
+
</div>
|
|
866
|
+
|
|
867
|
+
<h3 id="adapters-grid-instance">Accessing the grid instance from your framework</h3>
|
|
868
|
+
<p class="lead-in">
|
|
869
|
+
Anything the adapters do not surface as a prop — <code>grid.export</code>,
|
|
870
|
+
<code>grid.selection</code>, <code>grid.state</code> and the rest — is reached on the live
|
|
871
|
+
grid instance directly. It is the same <code>Grid</code> object <code>createGrid</code>
|
|
872
|
+
returns; the adapter only builds and drives it. There is one documented way to reach it per
|
|
873
|
+
adapter, and it is null until the grid is mounted.
|
|
874
|
+
</p>
|
|
875
|
+
<div class="table-wrap">
|
|
876
|
+
<table>
|
|
877
|
+
<thead><tr><th>Adapter</th><th>How you reach the grid</th></tr></thead>
|
|
878
|
+
<tbody>
|
|
879
|
+
<tr>
|
|
880
|
+
<td class="name">React</td>
|
|
881
|
+
<td>A forwarded ref: <code>ref.current.grid</code>.</td>
|
|
882
|
+
</tr>
|
|
883
|
+
<tr>
|
|
884
|
+
<td class="name">Vue 3</td>
|
|
885
|
+
<td>A template ref calling the exposed method:
|
|
886
|
+
<code>this.$refs.grid.grid()</code> (the component <code>expose</code>s a
|
|
887
|
+
<code>grid()</code> getter).</td>
|
|
888
|
+
</tr>
|
|
889
|
+
<tr>
|
|
890
|
+
<td class="name">Svelte</td>
|
|
891
|
+
<td>Either an <code>onGrid</code> callback in the action params, called with the live grid
|
|
892
|
+
the moment it is created:
|
|
893
|
+
<code>use:lattice={{ ...config, onGrid: (g) => grid = g }}</code>; or, a turn later,
|
|
894
|
+
the grid on any event's <code>detail</code> — the first <code>ready</code> event hands it
|
|
895
|
+
over: <code>on:ready={(e) => grid = e.detail.grid}</code>.</td>
|
|
896
|
+
</tr>
|
|
897
|
+
<tr>
|
|
898
|
+
<td class="name">Web Component</td>
|
|
899
|
+
<td>A property on the element: <code>el.grid</code>.</td>
|
|
900
|
+
</tr>
|
|
901
|
+
</tbody>
|
|
902
|
+
</table>
|
|
903
|
+
</div>
|
|
904
|
+
<div class="example">
|
|
905
|
+
<p class="example__label">React</p>
|
|
906
|
+
<pre><code><span class="kw">const</span> ref = React.useRef(null);
|
|
907
|
+
<span class="cmt">// after mount:</span>
|
|
908
|
+
ref.current.grid.export.toCsv();</code></pre>
|
|
909
|
+
</div>
|
|
910
|
+
<div class="example">
|
|
911
|
+
<p class="example__label">Vue 3</p>
|
|
912
|
+
<pre><code><LatticeGrid ref="grid" :columns="columns" :rows="rows" />
|
|
913
|
+
|
|
914
|
+
<span class="cmt">// in a method, after mount:</span>
|
|
915
|
+
<span class="kw">this</span>.$refs.grid.grid().export.toCsv();</code></pre>
|
|
916
|
+
</div>
|
|
917
|
+
<div class="example">
|
|
918
|
+
<p class="example__label">Svelte</p>
|
|
919
|
+
<pre><code><script>
|
|
920
|
+
<span class="kw">let</span> grid;
|
|
921
|
+
</script>
|
|
922
|
+
|
|
923
|
+
<div
|
|
924
|
+
use:lattice={{ columns, rows, rowKey: 'id' }}
|
|
925
|
+
on:ready={(e) => grid = e.detail.grid}
|
|
926
|
+
></div>
|
|
927
|
+
|
|
928
|
+
<button on:click={() => grid?.export.toCsv()}>Export</button></code></pre>
|
|
929
|
+
</div>
|
|
930
|
+
<div class="example">
|
|
931
|
+
<p class="example__label">Web Component</p>
|
|
932
|
+
<pre><code><span class="kw">const</span> el = document.querySelector('lattice-grid');
|
|
933
|
+
el.grid.export.toCsv();</code></pre>
|
|
854
934
|
</div>
|
|
855
935
|
|
|
856
936
|
<div class="why">
|
|
857
937
|
<p><strong>What the adapters do not do.</strong> They add no features and wrap no API: the
|
|
858
938
|
grid instance is the same object the vanilla examples use, and anything without a prop is
|
|
859
|
-
reached through it directly
|
|
860
|
-
|
|
939
|
+
reached through it directly — via the ref in React, <code>expose</code> in Vue, or
|
|
940
|
+
<code>onGrid</code> / the <code>ready</code> event in Svelte, as the table above shows.
|
|
941
|
+
Nothing is proxied, so nothing can lag behind the grid.</p>
|
|
861
942
|
</div>
|
|
862
943
|
|
|
863
944
|
<h3>The web component is self-contained: use it or the API, not both</h3>
|
|
@@ -1968,6 +2049,47 @@ grid.destroy();
|
|
|
1968
2049
|
<span class="kw">return</span> `grouped by ${groups.join(', ')}`;</code></pre>
|
|
1969
2050
|
</div>
|
|
1970
2051
|
|
|
2052
|
+
<p class="lead-in">
|
|
2053
|
+
<code>kpis</code> is the same idea for the tile every dashboard opens with. A
|
|
2054
|
+
<code>createStat</code> renders a KPI tile — a label, a value, its change against a
|
|
2055
|
+
baseline — reading the grid so it agrees with the grid; what it needs is a container and
|
|
2056
|
+
the wiring to place it. <code>kpis</code> is that placement done by the grid: an array of
|
|
2057
|
+
stat specs becomes a labelled band of tiles above the column header, and the grid creates
|
|
2058
|
+
the container for each and drives <code>createStat</code> itself. Each entry takes the
|
|
2059
|
+
fields <code>createStat</code> takes — <code>of</code>, <code>fn</code>, <code>title</code>,
|
|
2060
|
+
<code>interval</code>, <code>footer</code>, <code>format</code> and the rest — minus
|
|
2061
|
+
<code>grid</code> and <code>container</code>, which the grid supplies. The tiles follow the
|
|
2062
|
+
grid's filters, so the strip cannot disagree with the table beneath it. Off by default and
|
|
2063
|
+
free when absent; no <code>kpis</code>, no band.
|
|
2064
|
+
</p>
|
|
2065
|
+
<div class="example">
|
|
2066
|
+
<p class="example__label">A built-in KPI strip, following the grid</p>
|
|
2067
|
+
<pre data-run="js" data-expect="revenue 4200000" data-covers="config:kpis"><code><span class="kw">const</span> { createHeadlessGrid } = <span class="kw">await</span> import('../packages/core/src/index.js');
|
|
2068
|
+
|
|
2069
|
+
<span class="cmt">// `kpis` is chrome: with createGrid it renders a labelled band of stat tiles</span>
|
|
2070
|
+
<span class="cmt">// above the header, each following the grid's filters. The config is accepted</span>
|
|
2071
|
+
<span class="cmt">// everywhere, and each tile reads the same kernel the totals row uses — which</span>
|
|
2072
|
+
<span class="cmt">// is what a headless grid can show.</span>
|
|
2073
|
+
<span class="kw">const</span> grid = createHeadlessGrid({
|
|
2074
|
+
rowKey: 'region',
|
|
2075
|
+
columns: [{ field: 'region' }, { field: 'mrr', type: 'number' }],
|
|
2076
|
+
rows: [
|
|
2077
|
+
{ region: 'EMEA', mrr: 1200000 },
|
|
2078
|
+
{ region: 'AMER', mrr: 2400000 },
|
|
2079
|
+
{ region: 'APAC', mrr: 600000 },
|
|
2080
|
+
],
|
|
2081
|
+
kpis: [
|
|
2082
|
+
{ title: 'Accounts', fn: 'count' },
|
|
2083
|
+
{ title: 'Revenue', of: 'mrr', fn: 'sum' },
|
|
2084
|
+
],
|
|
2085
|
+
});
|
|
2086
|
+
|
|
2087
|
+
<span class="cmt">// The value the "Revenue" tile would read, from the kernel createStat uses.</span>
|
|
2088
|
+
<span class="kw">const</span> revenue = grid.statistics.reduce('mrr', 'sum');
|
|
2089
|
+
grid.destroy();
|
|
2090
|
+
<span class="kw">return</span> `revenue ${revenue}`;</code></pre>
|
|
2091
|
+
</div>
|
|
2092
|
+
|
|
1971
2093
|
<div class="example">
|
|
1972
2094
|
<p class="example__label">Totals</p>
|
|
1973
2095
|
<pre><code>{ field: 'capacity', type: 'number', total: 'sum' }
|
|
@@ -2403,6 +2525,36 @@ createGrid(right, { columns, rows,
|
|
|
2403
2525
|
</table>
|
|
2404
2526
|
</div>
|
|
2405
2527
|
|
|
2528
|
+
<h2 id="anomaly-summary">Anomaly summary chip</h2>
|
|
2529
|
+
<p class="lead-in">
|
|
2530
|
+
Give a column an <code>anomalyFlag</code> shadow (§9.4) and turn on
|
|
2531
|
+
<code>anomalySummary</code>, and the grid shows a small chip reading how many rows that column
|
|
2532
|
+
flags. Click it to filter the grid to exactly those rows; click again to clear.
|
|
2533
|
+
</p>
|
|
2534
|
+
|
|
2535
|
+
<div class="example">
|
|
2536
|
+
<p class="example__label">One shadow column, counted and filtered on a click</p>
|
|
2537
|
+
<pre><code>createGrid(element, {
|
|
2538
|
+
columns: [
|
|
2539
|
+
{ field: 'reading', title: 'Reading', type: 'number' },
|
|
2540
|
+
{ field: 'outlier', title: 'Anomaly', shadow: { kind: 'anomalyFlag', of: 'reading', threshold: 3.5 } },
|
|
2541
|
+
],
|
|
2542
|
+
rows,
|
|
2543
|
+
anomalySummary: <span class="kw">true</span>, <span class="cmt">// or { column: 'reading', label: '…' }</span>
|
|
2544
|
+
});</code></pre>
|
|
2545
|
+
</div>
|
|
2546
|
+
|
|
2547
|
+
<div class="why">
|
|
2548
|
+
<p><strong>The count and the filter are the same question.</strong> The chip is not a second
|
|
2549
|
+
detector: it reads the <code>anomalyFlag</code> shadow column, so the number it shows is the
|
|
2550
|
+
number of rows that column marks, and the click sets a filter on that same column
|
|
2551
|
+
(<code>{ col, op: 'eq', value: true }</code>). The count comes from
|
|
2552
|
+
<code>grid.statistics.anomalies()</code> over the shadow's base column, so the chip adds no
|
|
2553
|
+
detection of its own — the score is the API's, shown with its method, never an opaque verdict.</p>
|
|
2554
|
+
<p>Off by default, and it draws nothing unless a column carries an <code>anomalyFlag</code>
|
|
2555
|
+
shadow. When more than one does, <code>column</code> names the base to summarise.</p>
|
|
2556
|
+
</div>
|
|
2557
|
+
|
|
2406
2558
|
<h3>Headings without the controls</h3>
|
|
2407
2559
|
<p class="lead-in">
|
|
2408
2560
|
A dense grid often wants the heading and nothing else. <code>showColumnFunctions: false</code>
|
|
@@ -2750,12 +2902,18 @@ createGrid(el, {
|
|
|
2750
2902
|
});</code></pre>
|
|
2751
2903
|
</div>
|
|
2752
2904
|
<p>
|
|
2753
|
-
|
|
2905
|
+
Five adapters ship. <code>odataAdapter</code> writes <code>$filter</code>,
|
|
2754
2906
|
<code>$orderby</code>, <code>$top</code> and <code>$skip</code>, and follows
|
|
2755
2907
|
<code>@odata.nextLink</code> when the server pages on its own terms.
|
|
2756
2908
|
<code>restAdapter</code> covers an ordinary JSON endpoint whose parameter names are yours to
|
|
2757
2909
|
give. <code>dfqlAdapter</code> speaks DemandFlow's query API. <code>duckdbAdapter</code>
|
|
2758
2910
|
takes a live DuckDB connection.
|
|
2911
|
+
<code>graphqlAdapter</code> POSTs a GraphQL operation: because GraphQL has no fixed query
|
|
2912
|
+
semantics, you supply a <code>buildQuery</code> that turns the plan into
|
|
2913
|
+
<code>{ query, variables }</code> and a <code>parseResponse</code> that reads
|
|
2914
|
+
<code>data</code> back into rows and total, with defaults for an offset/limit list and a
|
|
2915
|
+
Relay cursor connection. The default pushes only the window and the total, so anything the
|
|
2916
|
+
schema cannot answer stays with the grid.
|
|
2759
2917
|
</p>
|
|
2760
2918
|
|
|
2761
2919
|
<h3>Declaring what an engine can do</h3>
|