@toclocoinc/lattice-grid 1.64.0 → 1.66.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 +6 -3
- package/angular/LICENSE +111 -0
- package/angular/README.md +78 -0
- package/angular/fesm2022/toclocoinc-lattice-grid-angular.mjs +2843 -0
- package/angular/package.json +16 -0
- package/angular/types/toclocoinc-lattice-grid-angular.d.ts +1366 -0
- package/docs/API.html +791 -8
- package/docs/api-detail.html +172 -4
- package/lattice-grid.d.ts +241 -205
- package/lattice-grid.esm.min.js +19 -7
- package/lattice-grid.min.cjs +19 -7
- package/lattice-grid.min.css +1 -1
- package/lattice-grid.min.js +19 -7
- package/modules/ai.d.ts +10 -13
- package/modules/ai.esm.min.js +3 -3
- package/modules/ai.min.cjs +3 -3
- package/modules/ai.min.js +3 -3
- package/modules/angular.d.ts +2 -2
- package/modules/angular.esm.min.js +433 -7
- package/modules/angular.min.cjs +433 -7
- package/modules/angular.min.js +433 -7
- package/modules/chart-alluvial.d.ts +2 -2
- package/modules/chart-alluvial.esm.min.js +1 -1
- package/modules/chart-alluvial.min.cjs +1 -1
- package/modules/chart-alluvial.min.js +1 -1
- package/modules/chart-arc.d.ts +2 -2
- package/modules/chart-arc.esm.min.js +1 -1
- package/modules/chart-arc.min.cjs +1 -1
- package/modules/chart-arc.min.js +1 -1
- package/modules/chart-bubblemap.d.ts +2 -2
- package/modules/chart-bubblemap.esm.min.js +1 -1
- package/modules/chart-bubblemap.min.cjs +1 -1
- package/modules/chart-bubblemap.min.js +1 -1
- package/modules/chart-bump.d.ts +2 -2
- package/modules/chart-bump.esm.min.js +1 -1
- package/modules/chart-bump.min.cjs +1 -1
- package/modules/chart-bump.min.js +1 -1
- package/modules/chart-calendar.d.ts +2 -2
- package/modules/chart-calendar.esm.min.js +1 -1
- package/modules/chart-calendar.min.cjs +1 -1
- package/modules/chart-calendar.min.js +1 -1
- package/modules/chart-decomposition.d.ts +2 -2
- package/modules/chart-decomposition.esm.min.js +1 -1
- package/modules/chart-decomposition.min.cjs +1 -1
- package/modules/chart-decomposition.min.js +1 -1
- package/modules/chart-diverging.d.ts +2 -2
- package/modules/chart-diverging.esm.min.js +1 -1
- package/modules/chart-diverging.min.cjs +1 -1
- package/modules/chart-diverging.min.js +1 -1
- package/modules/chart-dumbbell.d.ts +2 -2
- package/modules/chart-dumbbell.esm.min.js +1 -1
- package/modules/chart-dumbbell.min.cjs +1 -1
- package/modules/chart-dumbbell.min.js +1 -1
- package/modules/chart-fan.d.ts +2 -2
- package/modules/chart-fan.esm.min.js +1 -1
- package/modules/chart-fan.min.cjs +1 -1
- package/modules/chart-fan.min.js +1 -1
- package/modules/chart-hexbin.d.ts +2 -2
- package/modules/chart-hexbin.esm.min.js +1 -1
- package/modules/chart-hexbin.min.cjs +1 -1
- package/modules/chart-hexbin.min.js +1 -1
- package/modules/chart-hexmap.d.ts +2 -2
- package/modules/chart-hexmap.esm.min.js +1 -1
- package/modules/chart-hexmap.min.cjs +1 -1
- package/modules/chart-hexmap.min.js +1 -1
- package/modules/chart-icicle.d.ts +2 -2
- package/modules/chart-icicle.esm.min.js +1 -1
- package/modules/chart-icicle.min.cjs +1 -1
- package/modules/chart-icicle.min.js +1 -1
- package/modules/chart-markermap.d.ts +1 -1
- package/modules/chart-markermap.esm.min.js +1 -1
- package/modules/chart-markermap.min.cjs +1 -1
- package/modules/chart-markermap.min.js +1 -1
- package/modules/chart-parallel.d.ts +2 -2
- package/modules/chart-parallel.esm.min.js +1 -1
- package/modules/chart-parallel.min.cjs +1 -1
- package/modules/chart-parallel.min.js +1 -1
- package/modules/chart-ridgeline.d.ts +2 -2
- package/modules/chart-ridgeline.esm.min.js +1 -1
- package/modules/chart-ridgeline.min.cjs +1 -1
- package/modules/chart-ridgeline.min.js +1 -1
- package/modules/chart-roc.d.ts +2 -2
- package/modules/chart-roc.esm.min.js +1 -1
- package/modules/chart-roc.min.cjs +1 -1
- package/modules/chart-roc.min.js +1 -1
- package/modules/chart-slope.d.ts +2 -2
- package/modules/chart-slope.esm.min.js +1 -1
- package/modules/chart-slope.min.cjs +1 -1
- package/modules/chart-slope.min.js +1 -1
- package/modules/chart-splom.d.ts +2 -2
- package/modules/chart-splom.esm.min.js +1 -1
- package/modules/chart-splom.min.cjs +1 -1
- package/modules/chart-splom.min.js +1 -1
- package/modules/chart-waffle.d.ts +2 -2
- package/modules/chart-waffle.esm.min.js +1 -1
- package/modules/chart-waffle.min.cjs +1 -1
- package/modules/chart-waffle.min.js +1 -1
- package/modules/charts.d.ts +4 -5
- package/modules/charts.esm.min.js +261 -48
- package/modules/charts.min.cjs +261 -48
- package/modules/charts.min.js +261 -48
- package/modules/data-router.d.ts +5 -6
- package/modules/data-router.esm.min.js +3 -3
- package/modules/data-router.min.cjs +3 -3
- package/modules/data-router.min.js +3 -3
- package/modules/devtools.d.ts +1 -1
- package/modules/devtools.esm.min.js +1 -1
- package/modules/devtools.min.cjs +1 -1
- package/modules/devtools.min.js +1 -1
- package/modules/dhtmlx-compat.d.ts +1 -1
- package/modules/dhtmlx-compat.esm.min.js +3 -3
- package/modules/dhtmlx-compat.min.cjs +3 -3
- package/modules/dhtmlx-compat.min.js +3 -3
- package/modules/gantt.d.ts +37 -43
- package/modules/gantt.esm.min.js +3 -3
- package/modules/gantt.min.cjs +3 -3
- package/modules/gantt.min.js +3 -3
- package/modules/geo-europe-nuts.d.ts +2 -2
- package/modules/geo-europe-nuts.esm.min.js +1 -1
- package/modules/geo-uk.d.ts +2 -2
- package/modules/geo-uk.esm.min.js +1 -1
- package/modules/geo-us-states.d.ts +2 -2
- package/modules/geo-us-states.esm.min.js +1 -1
- package/modules/geo-world-110m.d.ts +2 -2
- package/modules/geo-world-110m.esm.min.js +1 -1
- package/modules/geo-world-50m.d.ts +2 -2
- package/modules/geo-world-50m.esm.min.js +1 -1
- package/modules/htmx.d.ts +2 -2
- package/modules/htmx.esm.min.js +19 -7
- package/modules/htmx.min.cjs +19 -7
- package/modules/htmx.min.js +19 -7
- package/modules/kanban.d.ts +14 -14
- package/modules/kanban.esm.min.js +3 -3
- package/modules/kanban.min.cjs +3 -3
- package/modules/kanban.min.js +3 -3
- package/modules/kpi.d.ts +5 -5
- package/modules/kpi.esm.min.js +3 -3
- package/modules/kpi.min.cjs +3 -3
- package/modules/kpi.min.js +3 -3
- package/modules/layout.d.ts +2 -2
- package/modules/layout.esm.min.js +3 -3
- package/modules/layout.min.cjs +3 -3
- package/modules/layout.min.js +3 -3
- package/modules/mock-socket.d.ts +1 -1
- package/modules/mock-socket.esm.min.js +1 -1
- package/modules/mock-socket.min.cjs +1 -1
- package/modules/mock-socket.min.js +1 -1
- package/modules/react.d.ts +4 -5
- package/modules/react.esm.min.js +3 -3
- package/modules/react.min.cjs +3 -3
- package/modules/react.min.js +3 -3
- package/modules/svelte.d.ts +252 -4
- package/modules/svelte.esm.min.js +960 -6
- package/modules/svelte.min.cjs +942 -5
- package/modules/svelte.min.js +942 -5
- package/modules/tabs.d.ts +2 -3
- package/modules/tabs.esm.min.js +3 -3
- package/modules/tabs.min.cjs +3 -3
- package/modules/tabs.min.js +3 -3
- package/modules/vue.d.ts +398 -9
- package/modules/vue.esm.min.js +1163 -31
- package/modules/vue.min.cjs +1147 -30
- package/modules/vue.min.js +1147 -30
- package/modules/webcomponent.d.ts +234 -2
- package/modules/webcomponent.esm.min.js +1267 -38
- package/modules/webcomponent.min.cjs +1249 -38
- package/modules/webcomponent.min.js +1249 -38
- package/package.json +27 -2
- package/svelte/Chart.svelte +34 -0
- package/svelte/Gantt.svelte +34 -0
- package/svelte/Grid.svelte +30 -0
- package/svelte/GridProvider.svelte +13 -0
- package/svelte/KPI.svelte +34 -0
- package/svelte/Kanban.svelte +34 -0
- package/svelte/Layout.svelte +34 -0
- package/svelte/Router.svelte +16 -0
- package/svelte/Tabs.svelte +53 -0
package/docs/API.html
CHANGED
|
@@ -360,7 +360,7 @@
|
|
|
360
360
|
<div class="shell">
|
|
361
361
|
<aside class="rail">
|
|
362
362
|
<p class="rail__brand">Lattice Grid</p>
|
|
363
|
-
<p class="rail__sub">API reference · v1.
|
|
363
|
+
<p class="rail__sub">API reference · v1.66.0</p>
|
|
364
364
|
<nav>
|
|
365
365
|
<div class="rail__group">
|
|
366
366
|
<span class="rail__label">Start</span>
|
|
@@ -413,6 +413,15 @@
|
|
|
413
413
|
<a href="#sources">Sources</a>
|
|
414
414
|
<a href="#events">Event reference</a>
|
|
415
415
|
</div>
|
|
416
|
+
<div class="rail__group">
|
|
417
|
+
<span class="rail__label">Frameworks</span>
|
|
418
|
+
<a href="#adapters">Framework adapters</a>
|
|
419
|
+
<a href="#react-v2">React</a>
|
|
420
|
+
<a href="#vue-v2">Vue</a>
|
|
421
|
+
<a href="#svelte-v2">Svelte</a>
|
|
422
|
+
<a href="#angular-v2">Angular</a>
|
|
423
|
+
<a href="#webcomponent-v2">Web Components</a>
|
|
424
|
+
</div>
|
|
416
425
|
<div class="rail__group">
|
|
417
426
|
<span class="rail__label">Registries</span>
|
|
418
427
|
<a href="#names">Built-in names</a>
|
|
@@ -444,7 +453,7 @@
|
|
|
444
453
|
</header>
|
|
445
454
|
|
|
446
455
|
<p class="chips">
|
|
447
|
-
<span class="chip">Version 1.
|
|
456
|
+
<span class="chip">Version 1.66.0</span>
|
|
448
457
|
<span class="chip">Zero dependencies</span>
|
|
449
458
|
<span class="chip"><a href="api-detail.html">Developer guide →</a></span>
|
|
450
459
|
</p>
|
|
@@ -520,8 +529,9 @@
|
|
|
520
529
|
<thead><tr><th>Entry point</th><th>Factory</th><th>Needs</th></tr></thead>
|
|
521
530
|
<tbody>
|
|
522
531
|
<tr><td class="name">modules/react</td><td class="sig">createLatticeGrid({ React, createGrid })</td><td class="desc">Returns a component. Forwards a ref exposing <code>.grid</code>. Since 1.63 the same entry point also builds a component for <a href="#react-v2">every other viewer</a> and the data router.</td></tr>
|
|
523
|
-
<tr><td class="name">
|
|
524
|
-
<tr><td class="name">modules/
|
|
532
|
+
<tr><td class="name">@toclocoinc/<wbr>lattice-grid/angular</td><td class="sig"><lattice-grid [config]="…"></td><td class="desc">A compiled entry point of this package, not a bundle: standalone components compiled ahead of time, one per viewer, plus the data router as a service. No second install. See <a href="#angular-v2">Angular</a>. <code>modules/angular</code>, which needs the JIT compiler, is deprecated.</td></tr>
|
|
533
|
+
<tr><td class="name">modules/vue</td><td class="sig">createLatticeGrid({ vue, createGrid })</td><td class="desc">Returns a Vue 3 component definition. Since 1.66 the same entry point also builds a component for <a href="#vue-v2">every other viewer</a> and the data router.</td></tr>
|
|
534
|
+
<tr><td class="name">modules/svelte</td><td class="sig">createLatticeAction({ createGrid })</td><td class="desc">Returns a <code>use:</code> action. Since 1.66 the package also ships <a href="#svelte-v2">a Svelte 5 component per viewer</a> as <code>.svelte</code> source at <code>@toclocoinc/lattice-grid/svelte/*.svelte</code>, and this entry point carries the helpers they are built from.</td></tr>
|
|
525
535
|
</tbody>
|
|
526
536
|
</table>
|
|
527
537
|
</div>
|
|
@@ -706,6 +716,473 @@ controller.destroy();
|
|
|
706
716
|
a line that could never run. The build now deletes that branch from every emitted artefact.
|
|
707
717
|
</p>
|
|
708
718
|
|
|
719
|
+
<h3 id="vue-v2">Vue 3: every viewer, not only the grid</h3>
|
|
720
|
+
<p>
|
|
721
|
+
Until 1.66 the Vue adapter wrapped <code>createGrid</code> and nothing else. Every other
|
|
722
|
+
shipped viewer — the KPI panel, a chart, the board, the Gantt, the layout, the tab
|
|
723
|
+
strip — and the data router had no Vue surface, so a Vue application wrote its own
|
|
724
|
+
<code>onMounted</code>/<code>onBeforeUnmount</code> pair per viewer. It does not have to any
|
|
725
|
+
more: there is one component per viewer, and each keeps the contract the grid component
|
|
726
|
+
already kept.
|
|
727
|
+
</p>
|
|
728
|
+
<p>
|
|
729
|
+
Every component is built with <code>defineComponent</code> and a render function, so the
|
|
730
|
+
adapter needs <strong>no template compiler</strong> in your build and runs on
|
|
731
|
+
<code>vue.runtime.*</code> — the compiler-free build a Vite application ships. The
|
|
732
|
+
floor is <strong>Vue 3.3</strong>.
|
|
733
|
+
</p>
|
|
734
|
+
<pre><code><span class="cmt">// lattice.js — built once, at module scope.</span>
|
|
735
|
+
<span class="kw">import</span> * <span class="kw">as</span> vue <span class="kw">from</span> 'vue';
|
|
736
|
+
<span class="kw">import</span> { createGrid } <span class="kw">from</span> '@toclocoinc/lattice-grid';
|
|
737
|
+
<span class="kw">import</span> { createKPI } <span class="kw">from</span> '@toclocoinc/lattice-grid/modules/kpi';
|
|
738
|
+
<span class="kw">import</span> { createChart } <span class="kw">from</span> '@toclocoinc/lattice-grid/modules/charts';
|
|
739
|
+
<span class="kw">import</span> { createDataRouter } <span class="kw">from</span> '@toclocoinc/lattice-grid/modules/data-router';
|
|
740
|
+
<span class="kw">import</span> { createLatticeVue } <span class="kw">from</span> '@toclocoinc/lattice-grid/modules/vue';
|
|
741
|
+
|
|
742
|
+
<span class="kw">export const</span> L = createLatticeVue({ vue, createGrid, createKPI, createChart, createDataRouter });</code></pre>
|
|
743
|
+
<pre><code><span class="cmt">// Dashboard.vue</span>
|
|
744
|
+
<script setup>
|
|
745
|
+
<span class="kw">import</span> { L } <span class="kw">from</span> './lattice.js';
|
|
746
|
+
|
|
747
|
+
L.provideLatticeGrids();
|
|
748
|
+
L.provideLatticeRouter(ROUTER_CONFIG);
|
|
749
|
+
|
|
750
|
+
<span class="kw">const</span> rows = shallowRef([]);
|
|
751
|
+
</script>
|
|
752
|
+
|
|
753
|
+
<template>
|
|
754
|
+
<component :is="L.LatticeGrid" name="quakes" route="all" v-bind="GRID_CONFIG" :rows="rows" />
|
|
755
|
+
<component :is="L.LatticeKPI" grid-name="quakes" :tiles="TILES" :columns="5" />
|
|
756
|
+
<component :is="L.LatticeChart" grid-name="quakes" type="bar" x="region" y="count" />
|
|
757
|
+
</template></code></pre>
|
|
758
|
+
<div class="table-wrap">
|
|
759
|
+
<table>
|
|
760
|
+
<thead><tr><th>Export</th><th>Signature</th><th>What it is</th></tr></thead>
|
|
761
|
+
<tbody>
|
|
762
|
+
<tr><td class="name">createLatticeGrid</td><td class="sig">({ vue, createGrid })</td><td class="desc">The grid component. Extended in 1.66 with <code>rowUpdates</code>, <code>predicates</code>, <code>name</code>, <code>route</code> and the <code>grid-ready</code> / <code>grid-destroyed</code> emits. Unchanged for anyone already on it.</td></tr>
|
|
763
|
+
<tr><td class="name">createLatticeKPI</td><td class="sig">({ vue, createKPI })</td><td class="desc">The KPI panel. Grid-bound through the provided registry by default; bind <code>:rows</code> instead for a panel with no grid.</td></tr>
|
|
764
|
+
<tr><td class="name">createLatticeChart</td><td class="sig">({ vue, createChart })</td><td class="desc">A chart. Requires a grid, so nothing is mounted until one exists; a changed spec key goes to <code>chart.update()</code> and the chart redraws rather than being rebuilt.</td></tr>
|
|
765
|
+
<tr><td class="name">createLatticeKanban</td><td class="sig">({ vue, createKanban })</td><td class="desc">The board. <code>rows</code>, <code>quickFilter</code>, <code>sprint</code>, <code>epic</code>, <code>loading</code> and <code>error</code> are live props.</td></tr>
|
|
766
|
+
<tr><td class="name">createLatticeGantt</td><td class="sig">({ vue, createGantt })</td><td class="desc">The Gantt. <code>tasks</code> and <code>dependencies</code> are live props.</td></tr>
|
|
767
|
+
<tr><td class="name">createLatticeLayout</td><td class="sig">({ vue, createLayout })</td><td class="desc">The layout. Windows are driven through the exposed instance; its events arrive as <code>@layout-changed</code>, <code>@window-moved</code> and the rest.</td></tr>
|
|
768
|
+
<tr><td class="name">createLatticeTabs</td><td class="sig">({ vue, createTabs, createGrid? })</td><td class="desc">The tab strip, with <strong>Vue-rendered tab content</strong>: a tab's content is a <strong>named slot</strong> — <code><template #overview></code> for a tab with <code>id: 'overview'</code>, or <code><template #tab-overview></code> — rendered into the strip's own panel through a <code><Teleport></code>, so a tab's grid is a real <code>LatticeGrid</code> with props, a ref and the surrounding <code>provide</code>s. A tab with no slot is left to the module, so the two kinds mix on one strip.</td></tr>
|
|
769
|
+
<tr><td class="name">createLatticeGridContext</td><td class="sig">({ vue })</td><td class="desc">Returns <code>{ LatticeGridProvider, provideLatticeGrids, useLatticeGrid }</code>. A grid-bound viewer needs the grid <em>instance</em>, which appears after the first render; a template ref cannot help, because assigning to one re-renders nobody. Call <code>provideLatticeGrids()</code> in a parent's <code>setup</code>, or wrap the subtree in <code><LatticeGridProvider></code>. Several grids may publish under one registry — <code>name</code> on the grid, <code>grid-name</code> on the viewer.</td></tr>
|
|
770
|
+
<tr><td class="name">createLatticeRouter</td><td class="sig">({ vue, createDataRouter })</td><td class="desc">Returns <code>{ provideLatticeRouter, useLatticeRouter, LatticeRouterProvider }</code>. <code>provideLatticeRouter(config)</code> is called in a component's <code>setup</code>: the router is built by the first grid under it that names a <code>route</code>, and destroyed when that component's scope is. The config is read once, because rebuilding would drop every attached grid and every row held.</td></tr>
|
|
771
|
+
<tr><td class="name">createLatticeViewer</td><td class="sig">({ vue, viewer, mount, … })</td><td class="desc">The generic behind all of the above, and the escape hatch for a viewer with no named factory yet.</td></tr>
|
|
772
|
+
<tr><td class="name">createLatticeVue</td><td class="sig">({ vue, …factories })</td><td class="desc">Every binding from one call: pass the factories the application uses and it builds those components, leaving the rest undefined. Nothing is imported, so an application that never uses the board never loads the board.</td></tr>
|
|
773
|
+
<tr><td class="name">createViewerController</td><td class="sig">({ viewer, mount, element, props })</td><td class="desc">The framework-free viewer lifecycle — mount once, push changed props into the live instance, destroy — shared by every adapter.</td></tr>
|
|
774
|
+
<tr><td class="name">VIEWER_EVENTS</td><td class="type">Record<string, readonly string[]></td><td class="desc">Every event each non-grid viewer emits, keyed by viewer name.</td></tr>
|
|
775
|
+
<tr><td class="name">VIEWER_APPLY</td><td class="type">Record<string, Record<string, Function>></td><td class="desc">Which props each viewer can take <em>live</em>, and the instance call each becomes. Anything not listed is mount-time configuration.</td></tr>
|
|
776
|
+
<tr><td class="name">viewerHandlerName</td><td class="type">(event) => string</td><td class="desc">A viewer event as the handler key the shared controller dispatches on: <code>card:move</code> becomes <code>onCardMove</code>. A Vue template binds the dashed form instead — <code>@card-move</code>.</td></tr>
|
|
777
|
+
<tr><td class="name">DEFAULT_GRID_NAME</td><td class="type">string</td><td class="desc">The name a grid publishes itself under when you do not choose one: <code>default</code>.</td></tr>
|
|
778
|
+
</tbody>
|
|
779
|
+
</table>
|
|
780
|
+
</div>
|
|
781
|
+
|
|
782
|
+
<pre data-run="js" data-expect="7 components, cell-changed, card-move, default, rows 2" data-covers="export:createLatticeVue export:createLatticeGrid export:createLatticeKPI export:createLatticeChart export:createLatticeKanban export:createLatticeGantt export:createLatticeLayout export:createLatticeTabs export:createLatticeViewer export:createLatticeGridContext export:createLatticeRouter export:createViewerController export:viewerHandlerName export:dashedName export:VIEWER_EVENTS export:VIEWER_APPLY export:DEFAULT_GRID_NAME export:EVENT_NAMES"><code><span class="kw">const</span> A = <span class="kw">await</span> import('../packages/modules/vue/index.js');
|
|
783
|
+
|
|
784
|
+
<span class="cmt">// A stand-in for Vue. The adapter never imports it, so a factory only needs</span>
|
|
785
|
+
<span class="cmt">// the handful of names it destructures — which is exactly why this example</span>
|
|
786
|
+
<span class="cmt">// runs in Node with no framework installed.</span>
|
|
787
|
+
<span class="kw">const</span> vue = {
|
|
788
|
+
defineComponent: (d) => d, h: () => ({}), ref: (v) => ({ value: v }),
|
|
789
|
+
shallowRef: (v) => ({ value: v }), computed: (f) => ({ get value() { <span class="kw">return</span> f(); } }),
|
|
790
|
+
watch: () => () => {}, onMounted: () => {}, onBeforeUnmount: () => {},
|
|
791
|
+
onScopeDispose: () => {}, provide: () => {}, inject: () => <span class="kw">null</span>,
|
|
792
|
+
Teleport: Symbol('Teleport'), Fragment: Symbol('Fragment'),
|
|
793
|
+
};
|
|
794
|
+
<span class="kw">const</span> stub = () => ({ on: () => () => {}, setRows: () => {}, destroy() {} });
|
|
795
|
+
|
|
796
|
+
<span class="cmt">// One call builds whichever components the factories you pass support.</span>
|
|
797
|
+
<span class="kw">const</span> L = A.createLatticeVue({
|
|
798
|
+
vue, createGrid: stub, createKPI: stub, createChart: stub, createDataRouter: stub,
|
|
799
|
+
});
|
|
800
|
+
|
|
801
|
+
<span class="cmt">// …or one factory at a time. Each returns a Vue component definition.</span>
|
|
802
|
+
<span class="kw">const</span> components = [
|
|
803
|
+
A.createLatticeGrid({ vue, createGrid: stub }),
|
|
804
|
+
A.createLatticeKPI({ vue, createKPI: stub }),
|
|
805
|
+
A.createLatticeChart({ vue, createChart: stub }),
|
|
806
|
+
A.createLatticeKanban({ vue, createKanban: stub }),
|
|
807
|
+
A.createLatticeGantt({ vue, createGantt: stub }),
|
|
808
|
+
A.createLatticeLayout({ vue, createLayout: stub }),
|
|
809
|
+
A.createLatticeTabs({ vue, createTabs: stub }),
|
|
810
|
+
].filter((c) => <span class="kw">typeof</span> c.setup === 'function');
|
|
811
|
+
|
|
812
|
+
<span class="cmt">// The generic behind them, the registry pair and the router composables.</span>
|
|
813
|
+
A.createLatticeViewer({ vue, viewer: 'kpi', mount: stub });
|
|
814
|
+
<span class="kw">const</span> { LatticeGridProvider, useLatticeGrid } = A.createLatticeGridContext({ vue });
|
|
815
|
+
<span class="kw">const</span> { provideLatticeRouter } = A.createLatticeRouter({ vue, createDataRouter: stub });
|
|
816
|
+
|
|
817
|
+
<span class="cmt">// Events are bound under dashed names, because a colon is directive syntax.</span>
|
|
818
|
+
<span class="kw">const</span> gridEvent = A.dashedName(A.EVENT_NAMES.find((n) => n === 'cell:changed'));
|
|
819
|
+
<span class="kw">const</span> viewerEvent = A.dashedName(A.VIEWER_EVENTS.kanban.find((n) => n === 'card:move'));
|
|
820
|
+
A.viewerHandlerName('card:move');
|
|
821
|
+
|
|
822
|
+
<span class="cmt">// And the lifecycle underneath, driven with no framework at all: mount once,</span>
|
|
823
|
+
<span class="cmt">// push a changed live prop into the instance that already exists, destroy.</span>
|
|
824
|
+
<span class="kw">const</span> seen = [];
|
|
825
|
+
<span class="kw">const</span> controller = A.createViewerController({
|
|
826
|
+
viewer: 'kpi',
|
|
827
|
+
element: {},
|
|
828
|
+
props: { rows: [{ id: 1 }] },
|
|
829
|
+
mount: () => ({ setRows: (r) => seen.push(r.length), on: () => () => {}, destroy() {} }),
|
|
830
|
+
});
|
|
831
|
+
controller.update({ rows: [{ id: 1 }, { id: 2 }] });
|
|
832
|
+
controller.destroy();
|
|
833
|
+
<span class="kw">void</span> [L.LatticeGrid, LatticeGridProvider, useLatticeGrid, provideLatticeRouter, A.VIEWER_APPLY];
|
|
834
|
+
|
|
835
|
+
<span class="kw">return</span> `${components.length} components, ${gridEvent}, ${viewerEvent}, `
|
|
836
|
+
+ `${A.DEFAULT_GRID_NAME}, rows ${seen.join('/')}`;</code></pre>
|
|
837
|
+
|
|
838
|
+
<p class="section-note">
|
|
839
|
+
<strong>The grid paints outside Vue's reactivity, and that is deliberate.</strong> The
|
|
840
|
+
adapter creates the grid in <code>onMounted</code> and pushes changed props into it; the grid
|
|
841
|
+
then renders on its own schedule, not Vue's. So <code>nextTick()</code> tells you Vue has
|
|
842
|
+
patched the DOM, <em>not</em> that the grid has painted. Measure, screenshot or scroll in a
|
|
843
|
+
grid event — <code>@render-done</code>, <code>@rows-changed</code>,
|
|
844
|
+
<code>@size-changed</code> — rather than after <code>nextTick</code> or in
|
|
845
|
+
<code>onMounted</code>.
|
|
846
|
+
</p>
|
|
847
|
+
<p class="section-note">
|
|
848
|
+
<strong>Hold big row arrays in a <code>shallowRef</code>, never a <code>ref</code>.</strong>
|
|
849
|
+
<code>ref([...100k rows])</code> makes every row object a reactive proxy: Vue walks the array
|
|
850
|
+
on assignment and every property read on every row goes through a proxy trap from then on.
|
|
851
|
+
The grid neither needs nor wants that — it re-reads the array itself when the reference
|
|
852
|
+
changes. Use <code>shallowRef(rows)</code> and assign a <em>new</em> array when the data
|
|
853
|
+
changes (<code>rows.value = next</code>), or <code>markRaw</code> the objects. The same goes
|
|
854
|
+
for the grid instance you keep off a template ref: a <code>ref</code> would proxy the whole
|
|
855
|
+
<code>Grid</code>, and the proxy is not <code>===</code> the object
|
|
856
|
+
<code>createGrid</code> returned.
|
|
857
|
+
</p>
|
|
858
|
+
<p class="section-note">
|
|
859
|
+
<strong>Props are diffed with <code>Object.is</code>, and that is a promise about identity.</strong>
|
|
860
|
+
An inline <code>:columns="[{ field: 'a' }]"</code> is a new array on every render, so it
|
|
861
|
+
counts as changed every render and reconfigures the grid every render. Hoist it to module
|
|
862
|
+
scope or put it behind a <code>computed</code>. This is not a defect to work around: a deep
|
|
863
|
+
compare of a million-row array on every render would cost more than the reload it prevents.
|
|
864
|
+
For the same reason nothing here uses a <code>{ deep: true }</code> watcher — one over a
|
|
865
|
+
config carrying <code>rows</code> would walk every row object on every tick.
|
|
866
|
+
</p>
|
|
867
|
+
<p class="section-note">
|
|
868
|
+
<strong>Live props versus mount-time props.</strong> The grid takes any changed configuration
|
|
869
|
+
key through one call (<code>grid.setAll</code>); no other viewer does. So each viewer declares
|
|
870
|
+
which props it can take while it is running (<code>VIEWER_APPLY</code>), and everything else
|
|
871
|
+
is mount-time configuration. A mount-time prop that changes is <em>not</em> silently ignored
|
|
872
|
+
and <em>not</em> silently remounted (that would throw away scroll position, selection and
|
|
873
|
+
expansion): it is named once in a warning that tells you to give the component a
|
|
874
|
+
<code>:key</code> that changes when the rebuild is wanted, or to drive the instance through
|
|
875
|
+
the ref. The tab strip's whole <code>tabs</code> array is mount-time for the same reason
|
|
876
|
+
— the module has no way to repaint an existing tab's label or badge.
|
|
877
|
+
</p>
|
|
878
|
+
<p class="section-note">
|
|
879
|
+
<strong>Events are dashed; the lifecycle pair is <code>grid-ready</code> and
|
|
880
|
+
<code>grid-destroyed</code>.</strong> <code>cell:changed</code> is emitted as
|
|
881
|
+
<code>@cell-changed</code>, because a colon in a Vue binding is directive syntax. Every grid
|
|
882
|
+
event is declared in <code>emits</code>, so none of them falls through onto the host element.
|
|
883
|
+
The two lifecycle emits are named <code>grid-*</code> because <code>ready</code> and
|
|
884
|
+
<code>destroy</code> are grid event names already re-emitted here, and the React and Angular
|
|
885
|
+
adapters name their pair the same.
|
|
886
|
+
</p>
|
|
887
|
+
<p class="section-note">
|
|
888
|
+
<strong>Reaching the instance, and <code>class</code>/<code>style</code>/<code>id</code>.</strong>
|
|
889
|
+
A template ref on the grid exposes <code>grid()</code>
|
|
890
|
+
(<code>gridRef.value.grid()</code>); every other component exposes
|
|
891
|
+
<code>instance()</code>. Both are <code>null</code> before mount. <code>class</code>,
|
|
892
|
+
<code>style</code> and <code>id</code> are applied to the component's own host element rather
|
|
893
|
+
than passed on as configuration; every other binding is the viewer's configuration, with a
|
|
894
|
+
known kebab-cased key mapped to its camelCase form (<code>:row-key</code> reaches
|
|
895
|
+
<code>rowKey</code>), as the web component does.
|
|
896
|
+
</p>
|
|
897
|
+
<p class="section-note">
|
|
898
|
+
<strong>Cleanup, and no SSR.</strong> Every component destroys its instance, stops its
|
|
899
|
+
watchers and unsubscribes its listeners in <code>onBeforeUnmount</code>, so a
|
|
900
|
+
<code>v-if</code> toggled twice leaves exactly one instance alive and an unmounted page
|
|
901
|
+
leaves nothing on a timer or an event bus. The router is destroyed with the component whose
|
|
902
|
+
<code>setup</code> provided it. Every component owns a real DOM element and builds nothing
|
|
903
|
+
until <code>onMounted</code>, so a server render emits the empty host and nothing else: there
|
|
904
|
+
is no SSR or Nuxt server-side support, and Vue 2 is not supported.
|
|
905
|
+
</p>
|
|
906
|
+
|
|
907
|
+
<h3 id="svelte-v2">Svelte 5: components you compile, not a bundle you load</h3>
|
|
908
|
+
<p>
|
|
909
|
+
Until 1.66 the Svelte adapter was a single action, <code>use:lattice</code>, over a grid.
|
|
910
|
+
An action cannot do what the other adapters do — it takes a node and a value, so it has
|
|
911
|
+
no children, no snippets and no context of its own, and a tab strip whose panels hold
|
|
912
|
+
Svelte-rendered content is simply out of its reach. So 1.66 adds <strong>components</strong>,
|
|
913
|
+
one per viewer, and they ship the way the Svelte ecosystem ships components: as
|
|
914
|
+
<code>.svelte</code> <strong>source</strong>, compiled by your own toolchain.
|
|
915
|
+
<code>svelte</code> is an <em>optional</em> peer dependency; the package still installs
|
|
916
|
+
nothing. <strong>Svelte 5 only</strong> — the components are written in runes and
|
|
917
|
+
snippets, neither of which exists in Svelte 4. The action is unchanged and still supported.
|
|
918
|
+
</p>
|
|
919
|
+
<pre><code><span class="cmt"><!-- Dashboard.svelte --></span>
|
|
920
|
+
<script>
|
|
921
|
+
<span class="kw">import</span> Provider <span class="kw">from</span> '@toclocoinc/lattice-grid/svelte/GridProvider.svelte';
|
|
922
|
+
<span class="kw">import</span> Grid <span class="kw">from</span> '@toclocoinc/lattice-grid/svelte/Grid.svelte';
|
|
923
|
+
<span class="kw">import</span> KPI <span class="kw">from</span> '@toclocoinc/lattice-grid/svelte/KPI.svelte';
|
|
924
|
+
<span class="kw">import</span> Chart <span class="kw">from</span> '@toclocoinc/lattice-grid/svelte/Chart.svelte';
|
|
925
|
+
<span class="kw">import</span> Tabs <span class="kw">from</span> '@toclocoinc/lattice-grid/svelte/Tabs.svelte';
|
|
926
|
+
|
|
927
|
+
<span class="kw">let</span> rows = $state.raw([]);
|
|
928
|
+
<span class="kw">let</span> board;
|
|
929
|
+
</script>
|
|
930
|
+
|
|
931
|
+
<Provider>
|
|
932
|
+
<Grid bind:this={board} name="quakes" class="grid" {...GRID_CONFIG} {rows}
|
|
933
|
+
onCellChanged={(e) => save(e)} />
|
|
934
|
+
<KPI gridName="quakes" tiles={TILES} columns={5} />
|
|
935
|
+
<Chart gridName="quakes" type="bar" x="region" y="count" />
|
|
936
|
+
|
|
937
|
+
<Tabs tabs={TABS} active={open} onTabChanged={(e) => (open = e.id)}>
|
|
938
|
+
{#snippet all()}<Grid name="all" {...GRID_CONFIG} {rows} />{/snippet}
|
|
939
|
+
</Tabs>
|
|
940
|
+
</Provider></code></pre>
|
|
941
|
+
<div class="table-wrap">
|
|
942
|
+
<table>
|
|
943
|
+
<thead><tr><th>Component</th><th>Import</th><th>What it is</th></tr></thead>
|
|
944
|
+
<tbody>
|
|
945
|
+
<tr><td class="name">Grid.svelte</td><td class="sig">@toclocoinc/<wbr>lattice-grid/<wbr>svelte/<wbr>Grid.svelte</td><td class="desc">One grid for the component's lifetime. Every configuration key is a prop, diffed with <code>Object.is</code> and pushed through <code>setAll</code>; <code>rowUpdates</code> is a keyed diff straight to <code>rows.apply()</code>; <code>predicates</code> are named filters registered through <code>filters.where</code>, so they compose with the reader's own. <code>bind:this</code> plus <code>grid()</code> hands you the live <code>Grid</code>.</td></tr>
|
|
946
|
+
<tr><td class="name">GridProvider.svelte</td><td class="sig">…/<wbr>svelte/<wbr>GridProvider.svelte</td><td class="desc">Puts a grid registry in context. A grid publishes itself under its <code>name</code>; a viewer finds it by <code>gridName</code>. Also available as <code>createGridRegistry()</code> for a host that would rather call <code>setContext</code> itself.</td></tr>
|
|
947
|
+
<tr><td class="name">KPI, Chart, Kanban, Gantt, Layout</td><td class="sig">…/<wbr>svelte/<wbr>KPI.svelte, …</td><td class="desc">One viewer each, built once and updated in place. A grid-bound viewer waits for its grid rather than mounting empty, and a <em>different</em> grid rebuilds it. <code>bind:this</code> plus <code>instance()</code> hands you the live viewer.</td></tr>
|
|
948
|
+
<tr><td class="name">Tabs.svelte</td><td class="sig">…/<wbr>svelte/<wbr>Tabs.svelte</td><td class="desc">The tab strip, with Svelte-rendered panels: a tab's content is a <code>{#snippet}</code> named after the tab's id, so a tab's grid is a real component with props, context and a reference. A tab with no snippet is left to the module, so configuration-driven tabs still work and the two kinds mix.</td></tr>
|
|
949
|
+
<tr><td class="name">Router.svelte</td><td class="sig">…/<wbr>svelte/<wbr>Router.svelte</td><td class="desc">A Data Router in context, built by the first grid that names a <code>route</code> and destroyed with the component.</td></tr>
|
|
950
|
+
</tbody>
|
|
951
|
+
</table>
|
|
952
|
+
</div>
|
|
953
|
+
<p>
|
|
954
|
+
The components are deliberately <strong>thin</strong> — a template, the <code>$props()</code>
|
|
955
|
+
plumbing, a <code>bind:this</code> getter and the context wiring — because they ship as source
|
|
956
|
+
you read. Every rule they follow lives in <code>modules/svelte</code>, which ships minified,
|
|
957
|
+
and each is exported so you can build a component of your own on exactly the same footing:
|
|
958
|
+
</p>
|
|
959
|
+
<div class="table-wrap">
|
|
960
|
+
<table>
|
|
961
|
+
<thead><tr><th>Export</th><th>Signature</th><th>What it does</th></tr></thead>
|
|
962
|
+
<tbody>
|
|
963
|
+
<tr><td class="name">bindGrid</td><td class="sig">({ createGrid, element, props, registry, router })</td><td class="desc">Owns one grid: builds it once, diffs props into it through <code>setAll</code>, registers <code>predicates</code> before it publishes, applies each new <code>rowUpdates</code> object through <code>rows.apply()</code>, attaches it to the router, and on <code>destroy</code> detaches and withdraws before destroying.</td></tr>
|
|
964
|
+
<tr><td class="name">bindViewer</td><td class="sig">({ viewer, factory, element, registry })</td><td class="desc">Owns one KPI panel, chart, board, plan or layout. <code>sync(props)</code> builds it once everything it needs has arrived, pushes changed props into the live instance, and rebuilds it only when it is bound to a <em>different</em> grid.</td></tr>
|
|
965
|
+
<tr><td class="name">bindTabs</td><td class="sig">({ createTabs, element, createGrid, onPanels })</td><td class="desc">Owns one tab strip and claims a panel for each tab the host rendered content for. <code>place(id, holder)</code> moves that tab's <code>display: contents</code> holder into the panel — Svelte has no portal, and moving one container is what keeps the subtree a genuine child of the component that declared it.</td></tr>
|
|
966
|
+
<tr><td class="name">createGridRegistry</td><td class="sig">()</td><td class="desc">The registry <code>GridProvider.svelte</code> puts in context: <code>publish</code>, <code>get</code>, <code>names</code> and a <code>subscribe</code> a component turns into its own reactivity.</td></tr>
|
|
967
|
+
<tr><td class="name">createRouterHandle</td><td class="sig">({ createDataRouter, config })</td><td class="desc">A Data Router built on the first grid that asks to be routed and destroyed with the component that provided it. <code>config</code> may be a function, read at build time.</td></tr>
|
|
968
|
+
<tr><td class="name">adaptProps</td><td class="sig">(kind, props)</td><td class="desc">Splits a component's props into the instance's configuration and the adapter's own, dropping <code>class</code>/<code>style</code>/<code>id</code>, resolving <code>row-key</code>-style aliases, and normalising a callback prop written either way.</td></tr>
|
|
969
|
+
<tr><td class="name">pickCallback</td><td class="sig">(props, name)</td><td class="desc">A callback prop under either spelling: <code>onGridReady</code> or <code>ongridready</code>.</td></tr>
|
|
970
|
+
<tr><td class="name">viewerMount</td><td class="sig">(viewer, factory)</td><td class="desc">The call each module's factory actually takes — three want <code>(element, config)</code>, the chart wants a <code>container</code> in its options and the Gantt an <code>element</code>.</td></tr>
|
|
971
|
+
<tr><td class="name">snippetTabIds</td><td class="sig">(tabs, props)</td><td class="desc">Which tabs the host declared a snippet for, in declaration order.</td></tr>
|
|
972
|
+
<tr><td class="name">VIEWER_BINDING</td><td class="sig">Record<string, {…}></td><td class="desc">How each viewer is wired: its label, the config keys without which nothing is built, and the key its bound grid is passed under.</td></tr>
|
|
973
|
+
<tr><td class="name">GRID_REGISTRY_KEY<br>ROUTER_KEY</td><td class="sig">symbol</td><td class="desc">The context keys the registry and the router handle are published under. Registered symbols (<code>Symbol.for</code>), so two components imported from different files meet the same registry.</td></tr>
|
|
974
|
+
</tbody>
|
|
975
|
+
</table>
|
|
976
|
+
</div>
|
|
977
|
+
<pre data-run="js" data-expect="config rowKey,onCellChanged; own main; registry main; grid dark; tabs one; viewers kpi,chart,kanban,gantt,layout; router 1" data-covers="export:bindGrid export:bindViewer export:bindTabs export:createGridRegistry export:createRouterHandle export:adaptProps export:pickCallback export:viewerMount export:snippetTabIds export:VIEWER_BINDING export:GRID_REGISTRY_KEY export:ROUTER_KEY"><code><span class="kw">const</span> S = <span class="kw">await</span> import('../packages/modules/svelte/index.js');
|
|
978
|
+
|
|
979
|
+
<span class="cmt">// A component hands its props straight to the helpers. They keep the</span>
|
|
980
|
+
<span class="cmt">// adapter's own props out of the instance and accept a callback under</span>
|
|
981
|
+
<span class="cmt">// either Svelte 5 spelling.</span>
|
|
982
|
+
<span class="kw">const</span> split = S.adaptProps('grid', {
|
|
983
|
+
rowKey: 'id', 'class': 'grid', name: 'main', oncellchanged: () => {},
|
|
984
|
+
});
|
|
985
|
+
<span class="kw">const</span> ready = S.pickCallback({ ongridready: () => 'called' }, 'onGridReady');
|
|
986
|
+
|
|
987
|
+
<span class="cmt">// The registry a <GridProvider> puts in context, and the grid binding a</span>
|
|
988
|
+
<span class="cmt">// <Grid> drives. Both are plain functions: no Svelte here at all.</span>
|
|
989
|
+
<span class="kw">const</span> registry = S.createGridRegistry();
|
|
990
|
+
<span class="kw">const</span> applied = [];
|
|
991
|
+
<span class="kw">const</span> fakeGrid = () => ({
|
|
992
|
+
setAll: (c) => applied.push(c.theme), destroy() {},
|
|
993
|
+
on: () => () => {}, rows: { apply: () => {} },
|
|
994
|
+
filters: { where: () => {} },
|
|
995
|
+
});
|
|
996
|
+
<span class="kw">const</span> bound = S.bindGrid({
|
|
997
|
+
createGrid: fakeGrid, element: {}, registry, props: { name: 'main', theme: 'light' },
|
|
998
|
+
});
|
|
999
|
+
bound.update({ name: 'main', theme: 'dark' });
|
|
1000
|
+
|
|
1001
|
+
<span class="cmt">// A viewer waits for its grid, then is built once. VIEWER_BINDING says</span>
|
|
1002
|
+
<span class="cmt">// which key its grid arrives under and what it cannot be built without.</span>
|
|
1003
|
+
<span class="kw">const</span> built = [];
|
|
1004
|
+
<span class="kw">const</span> stub = () => ({ on: () => () => {}, setRows: () => {}, update: () => {}, destroy() {} });
|
|
1005
|
+
<span class="kw">for</span> (<span class="kw">const</span> viewer <span class="kw">of</span> Object.keys(S.VIEWER_BINDING)) {
|
|
1006
|
+
<span class="kw">const</span> panel = S.bindViewer({
|
|
1007
|
+
viewer, element: {}, registry,
|
|
1008
|
+
factory: (...args) => { built.push(viewer); <span class="kw">return</span> stub(...args); },
|
|
1009
|
+
});
|
|
1010
|
+
panel.sync({ gridName: 'main' });
|
|
1011
|
+
panel.destroy();
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
<span class="cmt">// A tab strip claims a panel for each tab the host wrote a snippet for.</span>
|
|
1015
|
+
<span class="kw">const</span> tabs = [{ id: 'one' }, { id: 'two' }];
|
|
1016
|
+
<span class="kw">const</span> props = { one: () => {} };
|
|
1017
|
+
<span class="kw">const</span> strip = S.bindTabs({
|
|
1018
|
+
element: {},
|
|
1019
|
+
createTabs: (el, config) => ({ config, on: () => () => {}, destroy() {} }),
|
|
1020
|
+
});
|
|
1021
|
+
strip.sync({ tabs, contentIds: S.snippetTabIds(tabs, props) });
|
|
1022
|
+
<span class="kw">const</span> claimed = strip.instance.config.tabs.filter((t) => t.view).map((t) => t.id);
|
|
1023
|
+
|
|
1024
|
+
<span class="cmt">// One router, built by the first grid that asks and destroyed with the</span>
|
|
1025
|
+
<span class="cmt">// component that provided it.</span>
|
|
1026
|
+
<span class="kw">let</span> routers = 0;
|
|
1027
|
+
<span class="kw">const</span> handle = S.createRouterHandle({
|
|
1028
|
+
createDataRouter: () => { routers += 1; <span class="kw">return</span> { attach: () => {}, detach: () => {}, destroy: () => {} }; },
|
|
1029
|
+
});
|
|
1030
|
+
handle.attach({}, 'all'); handle.attach({}, 'all'); handle.destroy();
|
|
1031
|
+
|
|
1032
|
+
<span class="cmt">// And the call each module's factory actually takes.</span>
|
|
1033
|
+
S.viewerMount('chart', (opts) => opts)({}, { type: 'bar' });
|
|
1034
|
+
<span class="kw">void</span> [S.GRID_REGISTRY_KEY, S.ROUTER_KEY, ready()];
|
|
1035
|
+
|
|
1036
|
+
<span class="kw">return</span> `config ${Object.keys(split.config).join(',')}; own ${split.own.name}; `
|
|
1037
|
+
+ `registry ${registry.names().join(',')}; grid ${applied.join(',')}; `
|
|
1038
|
+
+ `tabs ${claimed.join(',')}; viewers ${built.join(',')}; router ${routers}`;</code></pre>
|
|
1039
|
+
|
|
1040
|
+
<p class="section-note">
|
|
1041
|
+
<strong>Events are callback props.</strong> Svelte 5 removed component events, so
|
|
1042
|
+
<code>cell:changed</code> arrives as <code>onCellChanged</code> — the same name React
|
|
1043
|
+
uses. The all-lowercase <code>oncellchanged</code> is accepted too, for anyone who prefers
|
|
1044
|
+
Svelte's DOM attribute style. The grid's own dashed names (<code>cell-changed</code>) still
|
|
1045
|
+
apply to the <code>use:lattice</code> action, which dispatches <code>CustomEvent</code>s on
|
|
1046
|
+
the node.
|
|
1047
|
+
</p>
|
|
1048
|
+
<p class="section-note">
|
|
1049
|
+
<strong>Reactivity, and rows.</strong> The grid paints outside Svelte's scheduler: it owns
|
|
1050
|
+
its element and its own render loop, and nothing inside it is reactive state. Hold large row
|
|
1051
|
+
arrays in <code>$state.raw</code> (or in an ordinary <code>let</code>), never in deep
|
|
1052
|
+
<code>$state</code> — a proxy over a million rows costs far more than the reload it
|
|
1053
|
+
would save, and the components diff by identity, so a new array is what signals a change.
|
|
1054
|
+
An inline literal prop (<code>columns={[…]}</code>) is a new array on every render and
|
|
1055
|
+
reconfigures the viewer every time; hoist it.
|
|
1056
|
+
</p>
|
|
1057
|
+
<p class="section-note">
|
|
1058
|
+
<strong>Cleanup, and no SSR.</strong> Every component builds its instance in
|
|
1059
|
+
<code>onMount</code> and destroys it in <code>onDestroy</code>, unsubscribing its listeners,
|
|
1060
|
+
withdrawing its grid from the registry and detaching from the router before the grid goes.
|
|
1061
|
+
Nothing is built during server rendering — SvelteKit SSR emits the empty host element
|
|
1062
|
+
and nothing else — so these components are browser-only by construction.
|
|
1063
|
+
</p>
|
|
1064
|
+
|
|
1065
|
+
<h3 id="angular-v2">Angular: a compiled entry point, <code>@toclocoinc/lattice-grid/angular</code></h3>
|
|
1066
|
+
<p>
|
|
1067
|
+
Angular's components are not objects a library can assemble at run time in a production
|
|
1068
|
+
build. <code>modules/angular</code> did assemble them that way, which needs Angular's JIT
|
|
1069
|
+
compiler in the page — present on a development server, absent from every AOT build.
|
|
1070
|
+
So Angular gets an entry point of its own: TypeScript components compiled by
|
|
1071
|
+
<code>@angular/compiler-cli</code> into a partial-Ivy library, which your build's Angular
|
|
1072
|
+
Linker turns into definitions exactly as it does for any other Angular library you install.
|
|
1073
|
+
<strong>No compiler in your bundle, and one standalone component per viewer.</strong>
|
|
1074
|
+
</p>
|
|
1075
|
+
<p>
|
|
1076
|
+
It ships <em>inside</em> the grid package, at the subpath
|
|
1077
|
+
<code>@toclocoinc/lattice-grid/angular</code>: one install, one version number, one
|
|
1078
|
+
licence. <code>@angular/core</code> and <code>@angular/common</code> are optional peer
|
|
1079
|
+
dependencies of the package, so a project that is not an Angular one installs nothing extra
|
|
1080
|
+
and sees no warning.
|
|
1081
|
+
</p>
|
|
1082
|
+
<pre><code>npm install @toclocoinc/lattice-grid</code></pre>
|
|
1083
|
+
<pre><code><span class="kw">import</span> { bootstrapApplication } <span class="kw">from</span> '@angular/platform-browser';
|
|
1084
|
+
<span class="kw">import</span> { createGrid } <span class="kw">from</span> '@toclocoinc/lattice-grid';
|
|
1085
|
+
<span class="kw">import</span> { createKPI } <span class="kw">from</span> '@toclocoinc/lattice-grid/modules/kpi';
|
|
1086
|
+
<span class="kw">import</span> { createChart } <span class="kw">from</span> '@toclocoinc/lattice-grid/modules/charts';
|
|
1087
|
+
<span class="kw">import</span> {
|
|
1088
|
+
LatticeGridComponent, LatticeKpiComponent, LatticeChartComponent, provideLattice,
|
|
1089
|
+
} <span class="kw">from</span> '@toclocoinc/lattice-grid/angular';
|
|
1090
|
+
|
|
1091
|
+
@Component({
|
|
1092
|
+
selector: 'app-dashboard',
|
|
1093
|
+
imports: [LatticeGridComponent, LatticeKpiComponent, LatticeChartComponent],
|
|
1094
|
+
template: `
|
|
1095
|
+
<lattice-grid #grid name="quakes" [config]="config" [quickFilter]="search()"
|
|
1096
|
+
(cell-changed)="save($event)" />
|
|
1097
|
+
<lattice-kpi gridName="quakes" [config]="{ tiles }" />
|
|
1098
|
+
<lattice-chart gridName="quakes" [config]="{ type: 'bar', x: 'region', y: 'count' }" />
|
|
1099
|
+
`,
|
|
1100
|
+
})
|
|
1101
|
+
<span class="kw">export class</span> Dashboard {
|
|
1102
|
+
<span class="cmt">// The live grid, the same object createGrid returns.</span>
|
|
1103
|
+
grid = viewChild<LatticeGridComponent>('grid');
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
<span class="cmt">// Each factory is injected, not imported by the library: an application that</span>
|
|
1107
|
+
<span class="cmt">// shows a grid downloads the grid, and never the board or the eighteen charts.</span>
|
|
1108
|
+
bootstrapApplication(Dashboard, {
|
|
1109
|
+
providers: [provideLattice({ createGrid, createKPI, createChart })],
|
|
1110
|
+
});</code></pre>
|
|
1111
|
+
|
|
1112
|
+
<div class="table-wrap">
|
|
1113
|
+
<table>
|
|
1114
|
+
<thead><tr><th>Export</th><th>Element</th><th>What it is</th></tr></thead>
|
|
1115
|
+
<tbody>
|
|
1116
|
+
<tr><td class="name">LatticeGridComponent</td><td class="sig"><lattice-grid></td><td class="desc">The grid. <code>[config]</code> is every configuration key; <code>[sort]</code>, <code>[filters]</code>, <code>[quickFilter]</code> and <code>[selectedKeys]</code> are applied through the matching API; <code>[rowUpdates]</code> and <code>[predicates]</code> drive a live feed. Every grid event is an output under its kebab-case name, and <code>(grid-ready)</code> hands you the instance. Give the element a height.</td></tr>
|
|
1117
|
+
<tr><td class="name">LatticeGridDirective</td><td class="sig">[latticeGrid]</td><td class="desc">The same component on an element your template already owns: <code><div [latticeGrid]="config" class="tall"></div></code>. Same inputs, outputs and <code>grid</code> reference.</td></tr>
|
|
1118
|
+
<tr><td class="name">LatticeKpiComponent</td><td class="sig"><lattice-kpi></td><td class="desc">The KPI panel. Grid-bound by default — <code>[gridName]</code> picks which published grid — or give it <code>[rows]</code> for a panel with no grid.</td></tr>
|
|
1119
|
+
<tr><td class="name">LatticeChartComponent</td><td class="sig"><lattice-chart></td><td class="desc">A chart. Requires a grid, so nothing is built until one exists; a changed spec key goes to <code>chart.update()</code> and the chart redraws rather than being rebuilt. <code>(click)</code>, <code>(hover)</code> and <code>(leave)</code> on this element are the chart's events, carrying the datum under the pointer.</td></tr>
|
|
1120
|
+
<tr><td class="name">LatticeKanbanComponent</td><td class="sig"><lattice-kanban></td><td class="desc">The board. <code>[rows]</code>, <code>[quickFilter]</code>, <code>[sprint]</code>, <code>[epic]</code>, <code>[loading]</code> and <code>[error]</code> are live inputs.</td></tr>
|
|
1121
|
+
<tr><td class="name">LatticeGanttComponent</td><td class="sig"><lattice-gantt></td><td class="desc">The plan. <code>[tasks]</code> and <code>[dependencies]</code> are live inputs. It takes an explicit <code>[grid]</code> but never adopts a published one.</td></tr>
|
|
1122
|
+
<tr><td class="name">LatticeLayoutComponent</td><td class="sig"><lattice-layout></td><td class="desc">The dashboard layout. Windows are driven through the instance; its events arrive as <code>(layout-changed)</code>, <code>(window-moved)</code> and the rest.</td></tr>
|
|
1123
|
+
<tr><td class="name">LatticeTabsComponent<br>LatticeTabDirective</td><td class="sig"><lattice-tabs><br>ng-template[latticeTab]</td><td class="desc">The tab strip, with <strong>Angular-rendered tab content</strong>: a tab's content is an <code><ng-template latticeTab="id"></code> in your own template, rendered into the strip's panel through this component's <code>ViewContainerRef</code> — so a tab's grid is a real <code><lattice-grid></code> with inputs, a reference and your injectors above it. A tab with no template is left to the module, so configuration-driven grid tabs still work and the two kinds mix on one strip.</td></tr>
|
|
1124
|
+
<tr><td class="name">LatticeGridRegistry</td><td class="sig">inject(LatticeGridRegistry)</td><td class="desc">Where <code><lattice-grid name="…"></code> publishes itself and grid-bound viewers find it, as a signal per name — a panel declared before its grid exists mounts itself the moment the grid arrives. <code>providedIn: 'root'</code>; put it in a component's own <code>providers</code> to scope a registry to that subtree.</td></tr>
|
|
1125
|
+
<tr><td class="name">provideLattice</td><td class="sig">provideLattice({ …factories })</td><td class="desc">The factories the components build through. Give it the ones your application uses; a component whose factory is missing names the import and the provider call that fixes it.</td></tr>
|
|
1126
|
+
<tr><td class="name">provideLatticeRouter<br>LatticeRouter</td><td class="sig">providers: [provideLatticeRouter(cfg)]</td><td class="desc">The data router as a service. Put it in a component's <code>providers</code> and it is created when the first <code><lattice-grid route="…"></code> under it attaches, and destroyed with that component — its configuration read once, because rebuilding would drop every attached grid and every row it holds. Each grid detaches before it is destroyed, so the router never holds a dead grid.</td></tr>
|
|
1127
|
+
</tbody>
|
|
1128
|
+
</table>
|
|
1129
|
+
</div>
|
|
1130
|
+
|
|
1131
|
+
<p class="section-note">
|
|
1132
|
+
<strong>Change detection: zone or zoneless, unconfigured.</strong> The grid is created inside
|
|
1133
|
+
<code>NgZone.runOutsideAngular</code>, because it installs its own scroll, wheel and pointer
|
|
1134
|
+
listeners and running change detection on every scroll frame of a million-row grid is the
|
|
1135
|
+
difference between smooth and unusable. An event that reaches an output you have
|
|
1136
|
+
<em>bound</em> re-enters the zone, so <code>(cell-changed)="count = count + 1"</code> repaints
|
|
1137
|
+
exactly as you expect; an output nobody bound costs nothing. Under zoneless change detection
|
|
1138
|
+
that machinery is Angular's own no-op and a signal you set in a handler repaints the view.
|
|
1139
|
+
The one thing to know when reading the grid's DOM from Angular: <strong>the grid paints on its
|
|
1140
|
+
own schedule, not Angular's</strong>, so measure a cell in a grid event, not in
|
|
1141
|
+
<code>ngAfterViewInit</code>.
|
|
1142
|
+
</p>
|
|
1143
|
+
<p class="section-note">
|
|
1144
|
+
<strong><code>OnPush</code> is safe everywhere.</strong> None of these components asks its
|
|
1145
|
+
parent to re-render: each owns one element, builds one instance in
|
|
1146
|
+
<code>afterNextRender</code> and pushes changed inputs into it from <code>ngOnChanges</code>.
|
|
1147
|
+
A host on <code>OnPush</code> that never re-renders still gets a fully live grid, because the
|
|
1148
|
+
grid is not rendered by Angular.
|
|
1149
|
+
</p>
|
|
1150
|
+
<p class="section-note">
|
|
1151
|
+
<strong>Inputs are diffed by identity, and never rebuild the instance.</strong> A changed
|
|
1152
|
+
input reaches the viewer that is already on screen — scroll position, selection,
|
|
1153
|
+
expansion and any open editor intact. Two things rebuild rather than update: the grid a
|
|
1154
|
+
viewer is bound to, and an input it cannot exist without. An input a viewer has no live
|
|
1155
|
+
setter for is named once in a warning rather than silently dropped. And because the
|
|
1156
|
+
comparison is <code>Object.is</code>, an inline <code>[config]="{ rows: rows }"</code> is a
|
|
1157
|
+
new object on every pass: hold it in a field or a signal.
|
|
1158
|
+
</p>
|
|
1159
|
+
<p class="section-note">
|
|
1160
|
+
<strong>Cleanup is the component's.</strong> <code>ngOnDestroy</code> detaches from the
|
|
1161
|
+
router, withdraws the grid from the registry and destroys the instance — in that order.
|
|
1162
|
+
An <code>@if</code> that closes and opens again leaves exactly one instance alive, and
|
|
1163
|
+
destroying the application leaves no instance, interval or listener behind. That is asserted
|
|
1164
|
+
with counters in a real browser, against the linked package, in
|
|
1165
|
+
<code>test/angular-package-browser.test.js</code>.
|
|
1166
|
+
</p>
|
|
1167
|
+
<p class="section-note">
|
|
1168
|
+
<strong>Angular 17 and up, browser only.</strong> The library is compiled partially, so your
|
|
1169
|
+
own Angular version compiles it: its declarations need a linker no newer than 14, and its peer
|
|
1170
|
+
range is <code>>=17</code>. Nothing is created on the server —
|
|
1171
|
+
<code>isPlatformBrowser</code> guards every build and <code>afterNextRender</code> does not
|
|
1172
|
+
run there — so a server-rendered page emits the empty host element and the grid is built
|
|
1173
|
+
on hydration. Angular Universal is not otherwise supported.
|
|
1174
|
+
</p>
|
|
1175
|
+
<p class="section-note">
|
|
1176
|
+
<strong><code>modules/angular</code> is deprecated.</strong> The old bundle still works where
|
|
1177
|
+
it always worked — a page with <code>@angular/compiler</code> loaded — and it now
|
|
1178
|
+
says so once, and fails with a <code>[lattice]</code> message naming this package when it
|
|
1179
|
+
finds a real Angular with no JIT compiler, instead of leaving you with Angular's own. In
|
|
1180
|
+
1.65 it also gained the fix that <code><div [latticeGrid]="config"></code> binds the
|
|
1181
|
+
configuration through the directive's selector, as its documentation always said it did. It
|
|
1182
|
+
will be removed in a later release; move to <code>@toclocoinc/lattice-grid/angular</code>,
|
|
1183
|
+
which covers every viewer rather than the grid alone and needs no second install.
|
|
1184
|
+
</p>
|
|
1185
|
+
|
|
709
1186
|
<div class="note">
|
|
710
1187
|
<p><strong>Published as <code>@toclocoinc/lattice-grid</code></strong>: <code>npm install
|
|
711
1188
|
@toclocoinc/lattice-grid</code>, then <code>import { createLatticeGrid } from
|
|
@@ -880,6 +1357,93 @@ defaults(<span class="kw">null</span>); <span class="cmt">// clea
|
|
|
880
1357
|
|
|
881
1358
|
<p class="section-note">Events are re-dispatched as <code>CustomEvent</code>s named <code>lattice-</code> plus the grid name with colons hyphenated: <code>cell:changed</code> becomes <code>lattice-cell-changed</code>. The payload is on <code>event.detail</code>. The prefix avoids colliding with platform events, the grid emits one called <code>scroll</code>.</p>
|
|
882
1359
|
|
|
1360
|
+
<h3 id="webcomponent-v2">Web Components: every viewer, not only the grid</h3>
|
|
1361
|
+
<p class="section-note">Since 1.66 the same bundle registers one element per viewer, so a page
|
|
1362
|
+
without a bundler gets the KPI panel, a chart, the board, the Gantt, the dashboard layout, the
|
|
1363
|
+
tab strip and the Data Router as tags. The grid is already registered on import;
|
|
1364
|
+
<code>defineLatticeElements</code> registers the rest from the module factories the page has
|
|
1365
|
+
imported, because nothing is imported by this module — a page that draws no charts never loads
|
|
1366
|
+
the charts bundle.</p>
|
|
1367
|
+
|
|
1368
|
+
<pre data-run="js" data-expect="8" data-covers="export:ELEMENT_TAGS"><code><span class="cmt">// Every tag this package can register, under the default prefix.</span>
|
|
1369
|
+
<span class="kw">const</span> { ELEMENT_TAGS } = <span class="kw">await</span> import('../packages/modules/webcomponent/elements.js');
|
|
1370
|
+
<span class="kw">return</span> Object.keys(ELEMENT_TAGS).length;</code></pre>
|
|
1371
|
+
|
|
1372
|
+
<pre><code><script type="module">
|
|
1373
|
+
import { createKPI } from './dist/modules/kpi.esm.js';
|
|
1374
|
+
import { createChart } from './dist/modules/charts.esm.js';
|
|
1375
|
+
import { defineLatticeElements } from './dist/modules/webcomponent.esm.js';
|
|
1376
|
+
defineLatticeElements({ createKPI, createChart });
|
|
1377
|
+
</script>
|
|
1378
|
+
|
|
1379
|
+
<lattice-grid name="quakes" row-key="id"></lattice-grid>
|
|
1380
|
+
<lattice-kpi grid-name="quakes"></lattice-kpi>
|
|
1381
|
+
<lattice-chart grid-name="quakes" type="bar" x="place" y="mag"></lattice-chart></code></pre>
|
|
1382
|
+
|
|
1383
|
+
<div class="table-wrap">
|
|
1384
|
+
<table>
|
|
1385
|
+
<thead><tr><th>Tag</th><th>Viewer</th><th>Notes</th></tr></thead>
|
|
1386
|
+
<tbody>
|
|
1387
|
+
<tr><td class="sig"><lattice-grid></td><td class="type">createGrid</td><td class="desc">Registered on import. Gains <code>name</code>, <code>route</code>, <code>route-options</code>, the <code>predicates</code> and <code>rowUpdates</code> properties, and <code>grid-ready</code> / <code>grid-destroyed</code>.</td></tr>
|
|
1388
|
+
<tr><td class="sig"><lattice-kpi></td><td class="type">createKPI</td><td class="desc">Grid-bound by default; set <code>rows</code> for a standalone panel. <code>tiles</code> is a property. Like every grid-bound viewer it <strong>waits</strong> for its grid rather than mounting empty, so a panel written above its grid is built once, when the grid arrives.</td></tr>
|
|
1389
|
+
<tr><td class="sig"><lattice-chart></td><td class="type">createChart</td><td class="desc">Always drawn from a grid, so it waits for one. Every other attribute is the chart spec and a change goes into <code>chart.update()</code>.</td></tr>
|
|
1390
|
+
<tr><td class="sig"><lattice-kanban></td><td class="type">createKanban</td><td class="desc">Board. <code>rows</code>, <code>columns</code>, <code>card</code>, <code>facets</code> are properties.</td></tr>
|
|
1391
|
+
<tr><td class="sig"><lattice-gantt></td><td class="type">createGantt</td><td class="desc"><code>tasks</code> and <code>dependencies</code> are properties and both are live.</td></tr>
|
|
1392
|
+
<tr><td class="sig"><lattice-layout></td><td class="type">createLayout</td><td class="desc"><code>windows</code> is a property.</td></tr>
|
|
1393
|
+
<tr><td class="sig"><lattice-tabs></td><td class="type">createTabs</td><td class="desc">A tab's content is a <code><template data-tab="‹id›"></code> child, cloned into the panel the module creates. With no <code>tabs</code> property the descriptors are read from the templates. A tab with no template is left to the module; the two kinds mix.</td></tr>
|
|
1394
|
+
<tr><td class="sig"><lattice-router></td><td class="type">createDataRouter</td><td class="desc">A grouping element. Owns one Data Router, built by the first <code><lattice-grid route="…"></code> beneath it and destroyed on disconnect, and the name registry its descendants resolve <code>grid-name</code> through.</td></tr>
|
|
1395
|
+
</tbody>
|
|
1396
|
+
</table>
|
|
1397
|
+
</div>
|
|
1398
|
+
|
|
1399
|
+
<p class="section-note"><strong>Attributes for scalars, properties for structures.</strong> An
|
|
1400
|
+
attribute is a string, so <code>columns</code>, <code>rows</code>, <code>tiles</code>,
|
|
1401
|
+
<code>tasks</code>, <code>windows</code> and a geometry pack are properties. Scalars work as
|
|
1402
|
+
either: an empty attribute is <code>true</code>, <code>true</code>/<code>false</code> are
|
|
1403
|
+
booleans, a finite number is a number, a value starting <code>[</code> or <code>{</code> is
|
|
1404
|
+
JSON, and anything else is the string — so use the property when the type matters. On the viewer
|
|
1405
|
+
elements a hyphenated attribute reaches the camelCase key (<code>column-property</code> →
|
|
1406
|
+
<code>columnProperty</code>). Every configuration key has a real property, including one no
|
|
1407
|
+
table here names: assign it and the element adopts it. <code><lattice-grid></code> keeps
|
|
1408
|
+
its own attribute table above — each of those is a property too
|
|
1409
|
+
(<code>el.theme</code>, <code>el.rowKey</code>) — and takes everything outside it through
|
|
1410
|
+
<code>config</code>.</p>
|
|
1411
|
+
|
|
1412
|
+
<p class="section-note"><strong>Upgrade order.</strong> A property assigned before the element
|
|
1413
|
+
upgrades is honoured. <strong>Set your configuration before the element connects</strong> —
|
|
1414
|
+
<code>document.createElement</code>, assign, then append — so the viewer is built once with
|
|
1415
|
+
everything it needs rather than built empty and reconfigured; in markup, use the JSON attribute
|
|
1416
|
+
forms. <strong>Cleanup</strong> is on disconnect, deferred by a microtask so moving an element in
|
|
1417
|
+
the DOM keeps its instance rather than rebuilding it. <strong>SSR</strong>: every element owns a
|
|
1418
|
+
real DOM node, so nothing is built until it is connected in a browser; a server render emits the
|
|
1419
|
+
empty tag and no more.</p>
|
|
1420
|
+
|
|
1421
|
+
<p class="section-note"><strong>Events.</strong> Instance events are <code>CustomEvent</code>s
|
|
1422
|
+
named <code>lattice-</code> plus the event name with colons hyphenated
|
|
1423
|
+
(<code>card:move</code> → <code>lattice-card-move</code>); the prefix is load-bearing,
|
|
1424
|
+
because the grid emits <code>scroll</code> and a chart emits <code>click</code>. The lifecycle
|
|
1425
|
+
events are this adapter's own and are unprefixed: <code>grid-ready</code> /
|
|
1426
|
+
<code>grid-destroyed</code> on the grid and <code>ready</code> / <code>destroyed</code> on every
|
|
1427
|
+
viewer, each carrying the instance in <code>detail</code>. The instance is also on
|
|
1428
|
+
<code>el.grid</code> / <code>el.instance</code>.</p>
|
|
1429
|
+
|
|
1430
|
+
<h4>Inside a shadow root</h4>
|
|
1431
|
+
<p class="section-note">The elements are light DOM, deliberately. A <em>host</em> that puts them
|
|
1432
|
+
inside a shadow root of its own is a different matter: the theme, each module's injected
|
|
1433
|
+
stylesheet and the grid's generated one all live in <code>document.head</code> and none of them
|
|
1434
|
+
crosses a shadow boundary, so a grid in there used to render structurally perfect and completely
|
|
1435
|
+
unstyled. Every element now calls <code>adoptLatticeStyles</code> on its own root when that root
|
|
1436
|
+
is a shadow root, mirroring each sheet as a constructable <code>CSSStyleSheet</code> and keeping
|
|
1437
|
+
it level as the grid compiles new classes and as a module injects its own. A host that manages
|
|
1438
|
+
its own <code>adoptedStyleSheets</code> can take the sheets directly with
|
|
1439
|
+
<code>latticeStyleSheets()</code>; <code>lattice-styles="off"</code> on an element opts out. A
|
|
1440
|
+
stylesheet that cannot be read as text — a cross-origin <code><link></code>, or one
|
|
1441
|
+
carrying <code>@import</code> — is cloned into the root as a <code><link></code> instead.</p>
|
|
1442
|
+
|
|
1443
|
+
<pre><code><span class="kw">const</span> root = host.attachShadow({ mode: 'open' });
|
|
1444
|
+
adoptLatticeStyles(root);
|
|
1445
|
+
root.append(document.createElement('lattice-grid'));</code></pre>
|
|
1446
|
+
|
|
883
1447
|
<h2 id="dhtmlx-compat">dhtmlx Grid compatibility wrapper</h2>
|
|
884
1448
|
<p class="section-note">A <code>Grid</code> class shaped like dhtmlx's own <code>dhx.Grid</code> (Suite 5+), backed by a real Lattice grid. Covers column definitions, <code>.data</code>, <code>.selection</code>, <code>.history</code>, <code>.export.csv</code>/<code>.xlsx</code>, and a name-mapped subset of <code>.events</code>: see <a href="api-detail.html#dhtmlx-guide">the guide</a> for exactly what is and is not covered. Not the classic pre-Suite-5 <code>dhtmlXGridObject</code>.</p>
|
|
885
1449
|
|
|
@@ -1393,7 +1957,7 @@ grid.destroy();
|
|
|
1393
1957
|
<table>
|
|
1394
1958
|
<thead><tr><th>Member</th><th>Returns</th><th>Description</th></tr></thead>
|
|
1395
1959
|
<tbody>
|
|
1396
|
-
<tr><td class="sig">getVersion()</td><td class="type">string</td><td class="desc">The version this grid came from, e.g. <code>'1.
|
|
1960
|
+
<tr><td class="sig">getVersion()</td><td class="type">string</td><td class="desc">The version this grid came from, e.g. <code>'1.66.0'</code>. Also on the module as <code>getVersion()</code>, for when you have no grid to hand.</td></tr>
|
|
1397
1961
|
<tr><td class="sig">get(key)</td><td class="type">unknown</td><td class="desc">Read any configuration key.</td></tr>
|
|
1398
1962
|
<tr><td class="sig">set(key, value)</td><td class="type">void</td><td class="desc">Write one key. Every key is live; nothing needs a rebuild.</td></tr>
|
|
1399
1963
|
<tr><td class="sig">setAll(values)</td><td class="type">void</td><td class="desc">Write several in one pass. Emits one <code>config:changed</code> for the batch, not one per key.</td></tr>
|
|
@@ -8074,7 +8638,7 @@ spans.addSpan('R0', 'name', 3, 2); <span class="cmt">// rowspan 3, colspan 2</sp
|
|
|
8074
8638
|
|
|
8075
8639
|
<h3 id="module-exports-example">Every module export, executed</h3>
|
|
8076
8640
|
<p class="section-note">Every shipped module’s exports, resolved against its own barrel on every build.</p>
|
|
8077
|
-
<pre data-run="js" data-expect="
|
|
8641
|
+
<pre data-run="js" data-expect="80" data-covers="export:ContextMenu export:Messages export:Registry export:autoInit export:createGrid export:createLocalViewStorage export:createMessages export:createStat export:deltaOf export:gridElementsWithin export:hydrateTable export:mountPanel export:readTable export:toneOf export:Chart export:PALETTE export:SCHEMES export:TYPES export:createChart export:chartRange export:canChartRange export:deriveRangeSpec export:regressionPlots export:registerScheme export:resolveScheme export:schemeNames export:setDefaultScheme export:HTML_ROW_WARNING_THRESHOLD export:QUERY_CHANGED_EVENT export:SCROLL_NEAR_END_EVENT export:attach export:destroyWithin export:driveInfiniteScroll export:driveOobUpdates export:driveServerMode export:ingestResponse export:initWithin export:queryParams export:restoreStateWithin export:rowsFromFragment export:rowsFromJson export:saveStateWithin export:ATTRIBUTE_CONFIG export:EVENT_PREFIX export:GridElementController export:LatticeGrid export:TAG_NAME export:createLatticeGridElement export:defineLatticeGrid export:domEventName export:observedAttributeNames export:createLatticeElements export:defineLatticeElements export:ELEMENT_TAGS export:createLatticeKPIElement export:createLatticeChartElement export:createLatticeKanbanElement export:createLatticeGanttElement export:createLatticeLayoutElement export:createLatticeTabsElement export:createLatticeRouterElement export:adoptLatticeStyles export:latticeStyleSheets export:CONSOLE_ACTIVATION export:createDevtools export:expose export:EVENT_NAMES export:handlerName export:createLatticeGrid export:dashedName export:createLatticeAction export:Grid export:warnIfLargeHtmlPayload export:createDataRouter export:MockWebSocket export:rng export:opsFeed export:priceFeed export:createKanban export:pack"><code><span class="cmt">// Every declared export of every shipped module, resolved against its own</span>
|
|
8078
8642
|
<span class="cmt">// barrel. A module that stopped exporting something fails here.</span>
|
|
8079
8643
|
<span class="kw">const</span> modules = [
|
|
8080
8644
|
[<span class="kw">await</span> import('../packages/dom/src/index.js'), [
|
|
@@ -8099,6 +8663,10 @@ spans.addSpan('R0', 'name', 3, 2); <span class="cmt">// rowspan 3, colspan 2</sp
|
|
|
8099
8663
|
'ATTRIBUTE_CONFIG', 'EVENT_PREFIX', 'GridElementController',
|
|
8100
8664
|
'TAG_NAME', 'createLatticeGridElement', 'defineLatticeGrid', 'domEventName',
|
|
8101
8665
|
'observedAttributeNames',
|
|
8666
|
+
'createLatticeElements', 'defineLatticeElements', 'ELEMENT_TAGS',
|
|
8667
|
+
'createLatticeKPIElement', 'createLatticeChartElement', 'createLatticeKanbanElement',
|
|
8668
|
+
'createLatticeGanttElement', 'createLatticeLayoutElement', 'createLatticeTabsElement',
|
|
8669
|
+
'createLatticeRouterElement', 'adoptLatticeStyles', 'latticeStyleSheets',
|
|
8102
8670
|
]],
|
|
8103
8671
|
[<span class="kw">await</span> import('../packages/modules/devtools/index.js'), [
|
|
8104
8672
|
'CONSOLE_ACTIVATION', 'createDevtools', 'expose',
|
|
@@ -8415,6 +8983,18 @@ grid.destroy();
|
|
|
8415
8983
|
<tr><td class="name">ATTRIBUTE_CONFIG</td><td class="type">Readonly<Record<string, unknown>></td><td class="desc">Which attributes map to which configuration keys.</td></tr>
|
|
8416
8984
|
<tr><td class="name">observedAttributeNames</td><td class="type">() => string[]</td><td class="desc">The attributes the element reacts to.</td></tr>
|
|
8417
8985
|
<tr><td class="name">domEventName</td><td class="type">(event) => string</td><td class="desc">The DOM event name a grid event is dispatched under.</td></tr>
|
|
8986
|
+
<tr><td class="name">defineLatticeElements</td><td class="type">(opts?) => Record<string, class></td><td class="desc">Register one element per viewer from the factories you pass, under <code>prefix</code> (<code>lattice-</code> by default). Safe to call twice. See <a href="#webcomponent-v2">Web Components</a>.</td></tr>
|
|
8987
|
+
<tr><td class="name">createLatticeElements</td><td class="type">(deps?) => Record<string, class></td><td class="desc">The classes, without registering them.</td></tr>
|
|
8988
|
+
<tr><td class="name">ELEMENT_TAGS</td><td class="type">Readonly<Record<string, string>></td><td class="desc">The tag each viewer takes, before the prefix.</td></tr>
|
|
8989
|
+
<tr><td class="name">createLatticeKPIElement</td><td class="type">({ createKPI }) => class</td><td class="desc">The <code><lattice-kpi></code> class on its own.</td></tr>
|
|
8990
|
+
<tr><td class="name">createLatticeChartElement</td><td class="type">({ createChart }) => class</td><td class="desc">The <code><lattice-chart></code> class on its own.</td></tr>
|
|
8991
|
+
<tr><td class="name">createLatticeKanbanElement</td><td class="type">({ createKanban }) => class</td><td class="desc">The <code><lattice-kanban></code> class on its own.</td></tr>
|
|
8992
|
+
<tr><td class="name">createLatticeGanttElement</td><td class="type">({ createGantt }) => class</td><td class="desc">The <code><lattice-gantt></code> class on its own.</td></tr>
|
|
8993
|
+
<tr><td class="name">createLatticeLayoutElement</td><td class="type">({ createLayout }) => class</td><td class="desc">The <code><lattice-layout></code> class on its own.</td></tr>
|
|
8994
|
+
<tr><td class="name">createLatticeTabsElement</td><td class="type">({ createTabs, createGrid? }) => class</td><td class="desc">The <code><lattice-tabs></code> class on its own.</td></tr>
|
|
8995
|
+
<tr><td class="name">createLatticeRouterElement</td><td class="type">({ createDataRouter }) => class</td><td class="desc">The <code><lattice-router></code> class on its own.</td></tr>
|
|
8996
|
+
<tr><td class="name">adoptLatticeStyles</td><td class="type">(root, opts?) => () => void</td><td class="desc">Make a shadow root see Lattice's styles, and keep it seeing them as more are generated. Returns the undo.</td></tr>
|
|
8997
|
+
<tr><td class="name">latticeStyleSheets</td><td class="type">(opts?) => CSSStyleSheet[]</td><td class="desc">Those stylesheets as constructable sheets, for a host managing its own <code>adoptedStyleSheets</code>. Shared and live; do not mutate them.</td></tr>
|
|
8418
8998
|
</tbody>
|
|
8419
8999
|
</table>
|
|
8420
9000
|
</div>
|
|
@@ -11083,6 +11663,7 @@ return `next ${p.mean.toFixed(1)}; r2 ${f.r2.toFixed(1)}; band ${p.upper - p.low
|
|
|
11083
11663
|
<tr><td class="name">pipes</td><td class="type">Record<string, (value: unknown, ...args: string[]) => string></td><td class="desc">Named text transforms usable from a format mask or a template. <small>(optional)</small></td></tr>
|
|
11084
11664
|
<tr><td class="name">totalFns</td><td class="type">Record<string, TotalFn></td><td class="desc">Your own reductions, alongside the built-in ones. <small>(optional)</small></td></tr>
|
|
11085
11665
|
<tr><td class="name">variants</td><td class="type">Record<string, VariantDefinition></td><td class="desc">Named appearance variants a row or cell can be switched into by a rule. <small>(optional)</small></td></tr>
|
|
11666
|
+
<tr><td class="name">icons</td><td class="type">Record<string, IconDefinition></td><td class="desc">Your own SVG glyphs, registered by name before the first paint. The same registry `registerIcon` writes to and every cell, header control, rail button and chart glyph is painted from, so a name given here is usable anywhere a glyph name is: a column's `icon` decoration, a rail action's `icon`, a network node's `icon`. Registering a built-in name overrides it. Read the result back through {@link Grid.icons}. <small>(optional)</small></td></tr>
|
|
11086
11667
|
<tr><td class="name">tree</td><td class="type">TreeConfig</td><td class="desc">Hierarchical rows: where the parent link or the path lives. <small>(optional)</small></td></tr>
|
|
11087
11668
|
<tr><td class="name">detail</td><td class="type">DetailConfig</td><td class="desc">The expandable panel beneath a row. <small>(optional)</small></td></tr>
|
|
11088
11669
|
<tr><td class="name">selection</td><td class="type">SelectionConfig | 'single' | 'multiple' | 'none'</td><td class="desc">What the user may select, and how selection behaves across groups. The `'none'` shorthand is `{ mode: 'none' }` and behaves identically: no row selection, and no cell ranges or fill handle either. <small>(optional)</small></td></tr>
|
|
@@ -11162,7 +11743,7 @@ return `next ${p.mean.toFixed(1)}; r2 ${f.r2.toFixed(1)}; band ${p.upper - p.low
|
|
|
11162
11743
|
<tr><td class="name">rowClass</td><td class="type">string | string[] | ((p: RowStyleParams) => string | string[])</td><td class="desc">A class, or classes, for every row. Re-evaluated on each repaint. <small>(optional)</small></td></tr>
|
|
11163
11744
|
<tr><td class="name">rowStyle</td><td class="type">CellStyle | ((p: RowStyleParams) => CellStyle)</td><td class="desc">Inline styles for every row. Camel-case or hyphenated property names. <small>(optional)</small></td></tr>
|
|
11164
11745
|
<tr><td class="name">toolPanel</td><td class="type">boolean | {</td><td class="desc"><small>(optional)</small></td></tr>
|
|
11165
|
-
<tr><td class="name">groupPanel</td><td class="type">boolean | {</td><td class="desc">A drag-and-drop group-by strip above the column header — the pattern AG Grid calls the row-group panel. Drag a column heading into it to group by that column; the active groups show as removable, reorderable chips, and reordering the chips changes the nesting order. It is keyboard-operable (arrows navigate, Shift+arrow reorders, Delete ungroups, and an add control groups any column), and every change is announced through the live region, which is why it also addresses the drag-only complaint
|
|
11746
|
+
<tr><td class="name">groupPanel</td><td class="type">boolean | {</td><td class="desc">A drag-and-drop group-by strip above the column header — the pattern AG Grid calls the row-group panel. Drag a column heading into it to group by that column; the active groups show as removable, reorderable chips, and reordering the chips changes the nesting order. It is keyboard-operable (arrows navigate, Shift+arrow reorders, Delete ungroups, and an add control groups any column), and every change is announced through the live region, which is why it also addresses the drag-only complaint (BACKLOG-0000429). Off by default and non-breaking, matching `toolPanel`. It drives the same grouping model as `grid.columns.group()`; it reimplements nothing. <small>(optional)</small></td></tr>
|
|
11166
11747
|
<tr><td class="name">kpis</td><td class="type">Array<Omit<StatConfig, 'grid' | 'container'>></td><td class="desc">A built-in KPI/stat strip: a labelled band of {@link createStat} tiles the grid places for you, above the column header. Each entry is a stat spec — the same fields {@link StatConfig} takes, minus `grid` and `container`, which the grid supplies — so a strip tile and a hand-placed one are the same object. The tiles follow the grid's filters, recomputing on every change exactly as a stand-alone stat does. Off by default and non-breaking, matching `groupPanel`: no `kpis` means no band and no cost. It reuses `createStat` and reimplements no compute. <small>(optional)</small></td></tr>
|
|
11167
11748
|
<tr><td class="name">quickFilterText</td><td class="type">string</td><td class="desc">The quick filter's initial text. <small>(optional)</small></td></tr>
|
|
11168
11749
|
<tr><td class="name">permissions</td><td class="type">PermissionPolicy</td><td class="desc">Per-column read/write/hidden policy. A usability control, not a security boundary: hidden data is still resident in the store. Enforce the same policy server-side with `permittedColumns` / `permittedExport`. <small>(optional)</small></td></tr>
|
|
@@ -12048,6 +12629,71 @@ return `next ${p.mean.toFixed(1)}; r2 ${f.r2.toFixed(1)}; band ${p.upper - p.low
|
|
|
12048
12629
|
</tbody>
|
|
12049
12630
|
</table>
|
|
12050
12631
|
</div>
|
|
12632
|
+
<h3 id="type-LatticeChartElement">LatticeChartElement</h3>
|
|
12633
|
+
<p class="section-note">`<lattice-chart>`. Always drawn from a grid, so it waits for one.</p>
|
|
12634
|
+
<div class="table-wrap">
|
|
12635
|
+
<table>
|
|
12636
|
+
<thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
|
|
12637
|
+
<tbody>
|
|
12638
|
+
<tr><td class="name">shapes</td><td class="type">unknown</td><td class="desc"></td></tr>
|
|
12639
|
+
<tr><td class="name">series</td><td class="type">unknown</td><td class="desc"></td></tr>
|
|
12640
|
+
<tr><td class="name">data</td><td class="type">unknown</td><td class="desc"></td></tr>
|
|
12641
|
+
<tr><td class="name">formatting</td><td class="type">unknown</td><td class="desc"></td></tr>
|
|
12642
|
+
<tr><td class="name">type</td><td class="type">string | undefined</td><td class="desc"></td></tr>
|
|
12643
|
+
<tr><td class="name">x</td><td class="type">string | undefined</td><td class="desc"></td></tr>
|
|
12644
|
+
<tr><td class="name">y</td><td class="type">string | string[] | undefined</td><td class="desc"></td></tr>
|
|
12645
|
+
<tr><td class="name">value</td><td class="type">string | undefined</td><td class="desc"></td></tr>
|
|
12646
|
+
<tr><td class="name">label</td><td class="type">string | undefined</td><td class="desc"></td></tr>
|
|
12647
|
+
<tr><td class="name">lon</td><td class="type">string | undefined</td><td class="desc"></td></tr>
|
|
12648
|
+
<tr><td class="name">lat</td><td class="type">string | undefined</td><td class="desc"></td></tr>
|
|
12649
|
+
<tr><td class="name">labels</td><td class="type">boolean | undefined</td><td class="desc"></td></tr>
|
|
12650
|
+
<tr><td class="name">stacked</td><td class="type">boolean | undefined</td><td class="desc"></td></tr>
|
|
12651
|
+
<tr><td class="name">horizontal</td><td class="type">boolean | undefined</td><td class="desc"></td></tr>
|
|
12652
|
+
<tr><td class="name">scheme</td><td class="type">string | undefined</td><td class="desc"></td></tr>
|
|
12653
|
+
</tbody>
|
|
12654
|
+
</table>
|
|
12655
|
+
</div>
|
|
12656
|
+
<h3 id="type-LatticeGanttElement">LatticeGanttElement</h3>
|
|
12657
|
+
<p class="section-note">`<lattice-gantt>`.</p>
|
|
12658
|
+
<div class="table-wrap">
|
|
12659
|
+
<table>
|
|
12660
|
+
<thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
|
|
12661
|
+
<tbody>
|
|
12662
|
+
<tr><td class="name">tasks</td><td class="type">unknown[]</td><td class="desc"></td></tr>
|
|
12663
|
+
<tr><td class="name">dependencies</td><td class="type">unknown[]</td><td class="desc"></td></tr>
|
|
12664
|
+
<tr><td class="name">resources</td><td class="type">unknown</td><td class="desc"></td></tr>
|
|
12665
|
+
<tr><td class="name">calendar</td><td class="type">unknown</td><td class="desc"></td></tr>
|
|
12666
|
+
<tr><td class="name">columns</td><td class="type">unknown</td><td class="desc"></td></tr>
|
|
12667
|
+
<tr><td class="name">rowKey</td><td class="type">string | undefined</td><td class="desc"></td></tr>
|
|
12668
|
+
<tr><td class="name">scale</td><td class="type">string | undefined</td><td class="desc"></td></tr>
|
|
12669
|
+
<tr><td class="name">autoSchedule</td><td class="type">boolean | undefined</td><td class="desc"></td></tr>
|
|
12670
|
+
</tbody>
|
|
12671
|
+
</table>
|
|
12672
|
+
</div>
|
|
12673
|
+
<h3 id="type-LatticeGridElement">LatticeGridElement</h3>
|
|
12674
|
+
<p class="section-note">`<lattice-grid>`. Structures are properties, scalars are the attributes in the table above, and `config` merges anything without an attribute of its own. Instance events arrive as `CustomEvent`s named `lattice-` plus the event name with colons hyphenated; `grid-ready` and `grid-destroyed` are this adapter's own and carry {@link LatticeGridEventDetail}.</p>
|
|
12675
|
+
<div class="table-wrap">
|
|
12676
|
+
<table>
|
|
12677
|
+
<thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
|
|
12678
|
+
<tbody>
|
|
12679
|
+
<tr><td class="name">theme</td><td class="type">string | undefined</td><td class="desc">Every attribute in the table above is also a property of the same name.</td></tr>
|
|
12680
|
+
<tr><td class="name">density</td><td class="type">string | undefined</td><td class="desc"></td></tr>
|
|
12681
|
+
<tr><td class="name">locale</td><td class="type">string | undefined</td><td class="desc"></td></tr>
|
|
12682
|
+
<tr><td class="name">rowKey</td><td class="type">string | undefined</td><td class="desc"></td></tr>
|
|
12683
|
+
<tr><td class="name">rowHeight</td><td class="type">number | undefined</td><td class="desc"></td></tr>
|
|
12684
|
+
<tr><td class="name">headerHeight</td><td class="type">number | undefined</td><td class="desc"></td></tr>
|
|
12685
|
+
<tr><td class="name">autoHeight</td><td class="type">boolean | undefined</td><td class="desc"></td></tr>
|
|
12686
|
+
<tr><td class="name">selection</td><td class="type">string | undefined</td><td class="desc"></td></tr>
|
|
12687
|
+
<tr><td class="name">grid</td><td class="type">Grid | null</td><td class="desc">The live grid, or null while the element is disconnected. <small>(read-only)</small></td></tr>
|
|
12688
|
+
<tr><td class="name">instance</td><td class="type">Grid | null</td><td class="desc">The live grid, under the name every viewer element uses. <small>(read-only)</small></td></tr>
|
|
12689
|
+
<tr><td class="name">rows</td><td class="type">Row[]</td><td class="desc">The row data.</td></tr>
|
|
12690
|
+
<tr><td class="name">columns</td><td class="type">Column[]</td><td class="desc">The column definitions.</td></tr>
|
|
12691
|
+
<tr><td class="name">config</td><td class="type">GridConfig</td><td class="desc">Any configuration without an attribute of its own; merged, not replaced.</td></tr>
|
|
12692
|
+
<tr><td class="name">predicates</td><td class="type">Record<string, ((row: Row) => boolean) | null> | undefined</td><td class="desc">Named row predicates, registered through `grid.filters.where` — they compose with whatever filter the reader has set, unlike `filters`.</td></tr>
|
|
12693
|
+
<tr><td class="name">rowUpdates</td><td class="type">{ add?: Row[]; update?: Row[]; remove?: unknown[] } | undefined</td><td class="desc">A keyed diff applied straight to `grid.rows.apply()`.</td></tr>
|
|
12694
|
+
</tbody>
|
|
12695
|
+
</table>
|
|
12696
|
+
</div>
|
|
12051
12697
|
<h3 id="type-LatticeGridHandle">LatticeGridHandle</h3>
|
|
12052
12698
|
<p class="section-note">The live instance a `<LatticeGrid>` ref exposes; `null` before mount.</p>
|
|
12053
12699
|
<div class="table-wrap">
|
|
@@ -12058,6 +12704,75 @@ return `next ${p.mean.toFixed(1)}; r2 ${f.r2.toFixed(1)}; band ${p.upper - p.low
|
|
|
12058
12704
|
</tbody>
|
|
12059
12705
|
</table>
|
|
12060
12706
|
</div>
|
|
12707
|
+
<h3 id="type-LatticeKanbanElement">LatticeKanbanElement</h3>
|
|
12708
|
+
<p class="section-note">`<lattice-kanban>`. Grid-bound like the KPI panel; give it `rows` to stand alone.</p>
|
|
12709
|
+
<div class="table-wrap">
|
|
12710
|
+
<table>
|
|
12711
|
+
<thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
|
|
12712
|
+
<tbody>
|
|
12713
|
+
<tr><td class="name">rows</td><td class="type">Row[]</td><td class="desc"></td></tr>
|
|
12714
|
+
<tr><td class="name">columns</td><td class="type">unknown[]</td><td class="desc"></td></tr>
|
|
12715
|
+
<tr><td class="name">card</td><td class="type">unknown</td><td class="desc"></td></tr>
|
|
12716
|
+
<tr><td class="name">facets</td><td class="type">unknown</td><td class="desc"></td></tr>
|
|
12717
|
+
<tr><td class="name">rowKey</td><td class="type">string | undefined</td><td class="desc"></td></tr>
|
|
12718
|
+
<tr><td class="name">columnProperty</td><td class="type">string | undefined</td><td class="desc"></td></tr>
|
|
12719
|
+
<tr><td class="name">titleProperty</td><td class="type">string | undefined</td><td class="desc"></td></tr>
|
|
12720
|
+
<tr><td class="name">swimlanes</td><td class="type">boolean | undefined</td><td class="desc"></td></tr>
|
|
12721
|
+
</tbody>
|
|
12722
|
+
</table>
|
|
12723
|
+
</div>
|
|
12724
|
+
<h3 id="type-LatticeKPIElement">LatticeKPIElement</h3>
|
|
12725
|
+
<p class="section-note">`<lattice-kpi>`. Grid-bound by default, and it **waits** for its grid rather than mounting empty; give it `rows` for a standalone panel.</p>
|
|
12726
|
+
<div class="table-wrap">
|
|
12727
|
+
<table>
|
|
12728
|
+
<thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
|
|
12729
|
+
<tbody>
|
|
12730
|
+
<tr><td class="name">tiles</td><td class="type">unknown[]</td><td class="desc"></td></tr>
|
|
12731
|
+
<tr><td class="name">rows</td><td class="type">Row[]</td><td class="desc"></td></tr>
|
|
12732
|
+
<tr><td class="name">columns</td><td class="type">number | undefined</td><td class="desc"></td></tr>
|
|
12733
|
+
<tr><td class="name">rowKey</td><td class="type">string | undefined</td><td class="desc"></td></tr>
|
|
12734
|
+
<tr><td class="name">locale</td><td class="type">string | undefined</td><td class="desc"></td></tr>
|
|
12735
|
+
<tr><td class="name">theme</td><td class="type">string | undefined</td><td class="desc"></td></tr>
|
|
12736
|
+
<tr><td class="name">density</td><td class="type">string | undefined</td><td class="desc"></td></tr>
|
|
12737
|
+
<tr><td class="name">format</td><td class="type">unknown</td><td class="desc"></td></tr>
|
|
12738
|
+
</tbody>
|
|
12739
|
+
</table>
|
|
12740
|
+
</div>
|
|
12741
|
+
<h3 id="type-LatticeLayoutElement">LatticeLayoutElement</h3>
|
|
12742
|
+
<p class="section-note">`<lattice-layout>`.</p>
|
|
12743
|
+
<div class="table-wrap">
|
|
12744
|
+
<table>
|
|
12745
|
+
<thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
|
|
12746
|
+
<tbody>
|
|
12747
|
+
<tr><td class="name">windows</td><td class="type">unknown[]</td><td class="desc"></td></tr>
|
|
12748
|
+
<tr><td class="name">columns</td><td class="type">number | undefined</td><td class="desc"></td></tr>
|
|
12749
|
+
<tr><td class="name">rows</td><td class="type">number | undefined</td><td class="desc"></td></tr>
|
|
12750
|
+
<tr><td class="name">compact</td><td class="type">string | undefined</td><td class="desc"></td></tr>
|
|
12751
|
+
</tbody>
|
|
12752
|
+
</table>
|
|
12753
|
+
</div>
|
|
12754
|
+
<h3 id="type-LatticeRouterElement">LatticeRouterElement</h3>
|
|
12755
|
+
<p class="section-note">`<lattice-router>`. Owns a Data Router for the life of the element, built by the first `<lattice-grid route="…">` beneath it.</p>
|
|
12756
|
+
<div class="table-wrap">
|
|
12757
|
+
<table>
|
|
12758
|
+
<thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
|
|
12759
|
+
<tbody>
|
|
12760
|
+
<tr><td class="name">router</td><td class="type">unknown</td><td class="desc">The live router, or null until something routes. <small>(read-only)</small></td></tr>
|
|
12761
|
+
<tr><td class="name">instance</td><td class="type">unknown</td><td class="desc">The live router, under the name every viewer element uses. <small>(read-only)</small></td></tr>
|
|
12762
|
+
<tr><td class="name">config</td><td class="type">Record<string, unknown></td><td class="desc">The router configuration; read once, when the router is built.</td></tr>
|
|
12763
|
+
</tbody>
|
|
12764
|
+
</table>
|
|
12765
|
+
</div>
|
|
12766
|
+
<h3 id="type-LatticeTabsElement">LatticeTabsElement</h3>
|
|
12767
|
+
<p class="section-note">`<lattice-tabs>`. A tab's content is a `<template data-tab="‹id›">` child, cloned into the panel the module creates for it; a tab with no template is left to the module.</p>
|
|
12768
|
+
<div class="table-wrap">
|
|
12769
|
+
<table>
|
|
12770
|
+
<thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
|
|
12771
|
+
<tbody>
|
|
12772
|
+
<tr><td class="name">tabs</td><td class="type">unknown[]</td><td class="desc"></td></tr>
|
|
12773
|
+
</tbody>
|
|
12774
|
+
</table>
|
|
12775
|
+
</div>
|
|
12061
12776
|
<h3 id="type-LatticeTabSpec">LatticeTabSpec</h3>
|
|
12062
12777
|
<p class="section-note">One tab of a `<LatticeTabs>`; `content` makes it React's rather than the module's.</p>
|
|
12063
12778
|
<div class="table-wrap">
|
|
@@ -12086,6 +12801,19 @@ return `next ${p.mean.toFixed(1)}; r2 ${f.r2.toFixed(1)}; band ${p.upper - p.low
|
|
|
12086
12801
|
</tbody>
|
|
12087
12802
|
</table>
|
|
12088
12803
|
</div>
|
|
12804
|
+
<h3 id="type-LatticeViewerElement">LatticeViewerElement</h3>
|
|
12805
|
+
<p class="section-note">What every viewer element carries.</p>
|
|
12806
|
+
<div class="table-wrap">
|
|
12807
|
+
<table>
|
|
12808
|
+
<thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
|
|
12809
|
+
<tbody>
|
|
12810
|
+
<tr><td class="name">instance</td><td class="type">Instance | null</td><td class="desc">The live viewer, or null before it is built. Every configuration key below is also a property, and an attribute of the same name is the same key. A key none of these interfaces declares works as a property too — the element adopts it — but is written through `config` where the declarations are the contract. <small>(read-only)</small></td></tr>
|
|
12811
|
+
<tr><td class="name">grid</td><td class="type">unknown</td><td class="desc">The grid this viewer is built against, when it is given one directly.</td></tr>
|
|
12812
|
+
<tr><td class="name">gridName</td><td class="type">string | undefined</td><td class="desc">Which published grid to bind to; the `grid-name` attribute in markup.</td></tr>
|
|
12813
|
+
<tr><td class="name">config</td><td class="type">Record<string, unknown></td><td class="desc">Any configuration without a property of its own; merged, not replaced.</td></tr>
|
|
12814
|
+
</tbody>
|
|
12815
|
+
</table>
|
|
12816
|
+
</div>
|
|
12089
12817
|
<h3 id="type-LatticeViewerHandle">LatticeViewerHandle</h3>
|
|
12090
12818
|
<p class="section-note">The live instance a viewer component's ref exposes; `null` before mount.</p>
|
|
12091
12819
|
<div class="table-wrap">
|
|
@@ -12096,6 +12824,61 @@ return `next ${p.mean.toFixed(1)}; r2 ${f.r2.toFixed(1)}; band ${p.upper - p.low
|
|
|
12096
12824
|
</tbody>
|
|
12097
12825
|
</table>
|
|
12098
12826
|
</div>
|
|
12827
|
+
<h3 id="type-LatticeVueGridExposed">LatticeVueGridExposed</h3>
|
|
12828
|
+
<p class="section-note">What a `<LatticeGrid>` template ref exposes; `grid()` is null before mount.</p>
|
|
12829
|
+
<div class="table-wrap">
|
|
12830
|
+
<table>
|
|
12831
|
+
<thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
|
|
12832
|
+
<tbody>
|
|
12833
|
+
<tr><td class="name">grid</td><td class="type">(): Grid | null</td><td class="desc"></td></tr>
|
|
12834
|
+
</tbody>
|
|
12835
|
+
</table>
|
|
12836
|
+
</div>
|
|
12837
|
+
<h3 id="type-LatticeVueGridRegistry">LatticeVueGridRegistry</h3>
|
|
12838
|
+
<p class="section-note">Where grids publish themselves so the viewers around them can find one.</p>
|
|
12839
|
+
<div class="table-wrap">
|
|
12840
|
+
<table>
|
|
12841
|
+
<thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
|
|
12842
|
+
<tbody>
|
|
12843
|
+
<tr><td class="name">grids</td><td class="type">{ value: Readonly<Record<string, Grid>> }</td><td class="desc">A shallow ref of name → grid; replaced, never mutated, on each change.</td></tr>
|
|
12844
|
+
<tr><td class="name">publish</td><td class="type">(name: string, grid: Grid | null): void</td><td class="desc">Publish a grid under a name, or withdraw it with `null`.</td></tr>
|
|
12845
|
+
</tbody>
|
|
12846
|
+
</table>
|
|
12847
|
+
</div>
|
|
12848
|
+
<h3 id="type-LatticeVueRouterHandle">LatticeVueRouterHandle</h3>
|
|
12849
|
+
<p class="section-note">The Data Router handle a `provideLatticeRouter` puts in scope.</p>
|
|
12850
|
+
<div class="table-wrap">
|
|
12851
|
+
<table>
|
|
12852
|
+
<thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
|
|
12853
|
+
<tbody>
|
|
12854
|
+
<tr><td class="name">router</td><td class="type">unknown</td><td class="desc">The live router, built the first time anything asks for it. <small>(read-only)</small></td></tr>
|
|
12855
|
+
<tr><td class="name">attach</td><td class="type">(grid: Grid, route: unknown, opts?: Record<string, unknown>): void</td><td class="desc">Attach a grid to a route.</td></tr>
|
|
12856
|
+
<tr><td class="name">detach</td><td class="type">(grid: Grid): void</td><td class="desc">Detach a grid, before it is destroyed.</td></tr>
|
|
12857
|
+
<tr><td class="name">destroy</td><td class="type">(): void</td><td class="desc">Destroy the router; called for you when the providing scope is disposed.</td></tr>
|
|
12858
|
+
</tbody>
|
|
12859
|
+
</table>
|
|
12860
|
+
</div>
|
|
12861
|
+
<h3 id="type-LatticeVueTabSpec">LatticeVueTabSpec</h3>
|
|
12862
|
+
<p class="section-note">One tab of a `<LatticeTabs>`; a slot named for its `id` makes it Vue's.</p>
|
|
12863
|
+
<div class="table-wrap">
|
|
12864
|
+
<table>
|
|
12865
|
+
<thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
|
|
12866
|
+
<tbody>
|
|
12867
|
+
<tr><td class="name">id</td><td class="type">string</td><td class="desc"></td></tr>
|
|
12868
|
+
<tr><td class="name">label</td><td class="type">string</td><td class="desc"><small>(optional)</small></td></tr>
|
|
12869
|
+
</tbody>
|
|
12870
|
+
</table>
|
|
12871
|
+
</div>
|
|
12872
|
+
<h3 id="type-LatticeVueViewerExposed">LatticeVueViewerExposed</h3>
|
|
12873
|
+
<p class="section-note">What a viewer's template ref exposes; `instance()` is null before mount.</p>
|
|
12874
|
+
<div class="table-wrap">
|
|
12875
|
+
<table>
|
|
12876
|
+
<thead><tr><th>Member</th><th>Type</th><th>Description</th></tr></thead>
|
|
12877
|
+
<tbody>
|
|
12878
|
+
<tr><td class="name">instance</td><td class="type">(): Instance | null</td><td class="desc"></td></tr>
|
|
12879
|
+
</tbody>
|
|
12880
|
+
</table>
|
|
12881
|
+
</div>
|
|
12099
12882
|
<h3 id="type-Layout">Layout</h3>
|
|
12100
12883
|
<p class="section-note">A reconfigurable dashboard: a cell grid inside an element, and a set of windows on it that a user can move, resize and close by pointer or by keyboard (BACKLOG-0001108). The module is **payload-agnostic**: a window body is a container with an id, which this module creates and sizes and never reads. It tells a payload it was resized by emitting `window:resized`; it never calls into one, because it cannot know what one is.</p>
|
|
12101
12884
|
<div class="table-wrap">
|
|
@@ -14065,7 +14848,7 @@ return `next ${p.mean.toFixed(1)}; r2 ${f.r2.toFixed(1)}; band ${p.upper - p.low
|
|
|
14065
14848
|
<!-- END GENERATED TYPE REFERENCE -->
|
|
14066
14849
|
|
|
14067
14850
|
<footer>
|
|
14068
|
-
Lattice Grid 1.
|
|
14851
|
+
Lattice Grid 1.66.0 · Copyright © 2026 TOCLOCO Inc. All rights reserved.
|
|
14069
14852
|
This document describes the behaviour of the shipped library. Where this guide and the code
|
|
14070
14853
|
disagree, the code wins: please <a href="https://www.latticegrid.dev">tell us</a>.
|
|
14071
14854
|
</footer>
|