@toclocoinc/lattice-grid 1.65.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 -4
- 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 +675 -14
- package/docs/api-detail.html +137 -4
- package/lattice-grid.d.ts +1 -1
- package/lattice-grid.esm.min.js +18 -6
- package/lattice-grid.min.cjs +18 -6
- package/lattice-grid.min.css +1 -1
- package/lattice-grid.min.js +18 -6
- package/modules/ai.d.ts +1 -1
- 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 +1 -1
- package/modules/angular.esm.min.js +7 -7
- package/modules/angular.min.cjs +7 -7
- package/modules/angular.min.js +7 -7
- package/modules/chart-alluvial.d.ts +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- package/modules/geo-europe-nuts.esm.min.js +1 -1
- package/modules/geo-uk.d.ts +1 -1
- package/modules/geo-uk.esm.min.js +1 -1
- package/modules/geo-us-states.d.ts +1 -1
- package/modules/geo-us-states.esm.min.js +1 -1
- package/modules/geo-world-110m.d.ts +1 -1
- package/modules/geo-world-110m.esm.min.js +1 -1
- package/modules/geo-world-50m.d.ts +1 -1
- package/modules/geo-world-50m.esm.min.js +1 -1
- package/modules/htmx.d.ts +1 -1
- package/modules/htmx.esm.min.js +18 -6
- package/modules/htmx.min.cjs +18 -6
- package/modules/htmx.min.js +18 -6
- package/modules/kanban.d.ts +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- 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 +251 -2
- 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 +1 -1
- 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 +233 -1
- package/modules/webcomponent.esm.min.js +1266 -37
- package/modules/webcomponent.min.cjs +1248 -37
- package/modules/webcomponent.min.js +1248 -37
- 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>
|
|
@@ -417,7 +417,10 @@
|
|
|
417
417
|
<span class="rail__label">Frameworks</span>
|
|
418
418
|
<a href="#adapters">Framework adapters</a>
|
|
419
419
|
<a href="#react-v2">React</a>
|
|
420
|
+
<a href="#vue-v2">Vue</a>
|
|
421
|
+
<a href="#svelte-v2">Svelte</a>
|
|
420
422
|
<a href="#angular-v2">Angular</a>
|
|
423
|
+
<a href="#webcomponent-v2">Web Components</a>
|
|
421
424
|
</div>
|
|
422
425
|
<div class="rail__group">
|
|
423
426
|
<span class="rail__label">Registries</span>
|
|
@@ -450,7 +453,7 @@
|
|
|
450
453
|
</header>
|
|
451
454
|
|
|
452
455
|
<p class="chips">
|
|
453
|
-
<span class="chip">Version 1.
|
|
456
|
+
<span class="chip">Version 1.66.0</span>
|
|
454
457
|
<span class="chip">Zero dependencies</span>
|
|
455
458
|
<span class="chip"><a href="api-detail.html">Developer guide →</a></span>
|
|
456
459
|
</p>
|
|
@@ -526,9 +529,9 @@
|
|
|
526
529
|
<thead><tr><th>Entry point</th><th>Factory</th><th>Needs</th></tr></thead>
|
|
527
530
|
<tbody>
|
|
528
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>
|
|
529
|
-
<tr><td class="name">@toclocoinc/<wbr>lattice-grid
|
|
530
|
-
<tr><td class="name">modules/vue</td><td class="sig">createLatticeGrid({ vue, createGrid })</td><td class="desc">Returns a Vue 3 component definition.</td></tr>
|
|
531
|
-
<tr><td class="name">modules/svelte</td><td class="sig">createLatticeAction({ createGrid })</td><td class="desc">Returns a <code>use:</code> action.</td></tr>
|
|
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>
|
|
532
535
|
</tbody>
|
|
533
536
|
</table>
|
|
534
537
|
</div>
|
|
@@ -713,24 +716,377 @@ controller.destroy();
|
|
|
713
716
|
a line that could never run. The build now deletes that branch from every emitted artefact.
|
|
714
717
|
</p>
|
|
715
718
|
|
|
716
|
-
<h3 id="
|
|
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>
|
|
717
1066
|
<p>
|
|
718
1067
|
Angular's components are not objects a library can assemble at run time in a production
|
|
719
1068
|
build. <code>modules/angular</code> did assemble them that way, which needs Angular's JIT
|
|
720
1069
|
compiler in the page — present on a development server, absent from every AOT build.
|
|
721
|
-
So Angular gets
|
|
1070
|
+
So Angular gets an entry point of its own: TypeScript components compiled by
|
|
722
1071
|
<code>@angular/compiler-cli</code> into a partial-Ivy library, which your build's Angular
|
|
723
1072
|
Linker turns into definitions exactly as it does for any other Angular library you install.
|
|
724
1073
|
<strong>No compiler in your bundle, and one standalone component per viewer.</strong>
|
|
725
1074
|
</p>
|
|
726
|
-
<
|
|
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>
|
|
727
1083
|
<pre><code><span class="kw">import</span> { bootstrapApplication } <span class="kw">from</span> '@angular/platform-browser';
|
|
728
1084
|
<span class="kw">import</span> { createGrid } <span class="kw">from</span> '@toclocoinc/lattice-grid';
|
|
729
1085
|
<span class="kw">import</span> { createKPI } <span class="kw">from</span> '@toclocoinc/lattice-grid/modules/kpi';
|
|
730
1086
|
<span class="kw">import</span> { createChart } <span class="kw">from</span> '@toclocoinc/lattice-grid/modules/charts';
|
|
731
1087
|
<span class="kw">import</span> {
|
|
732
1088
|
LatticeGridComponent, LatticeKpiComponent, LatticeChartComponent, provideLattice,
|
|
733
|
-
} <span class="kw">from</span> '@toclocoinc/lattice-grid
|
|
1089
|
+
} <span class="kw">from</span> '@toclocoinc/lattice-grid/angular';
|
|
734
1090
|
|
|
735
1091
|
@Component({
|
|
736
1092
|
selector: 'app-dashboard',
|
|
@@ -823,8 +1179,8 @@ bootstrapApplication(Dashboard, {
|
|
|
823
1179
|
finds a real Angular with no JIT compiler, instead of leaving you with Angular's own. In
|
|
824
1180
|
1.65 it also gained the fix that <code><div [latticeGrid]="config"></code> binds the
|
|
825
1181
|
configuration through the directive's selector, as its documentation always said it did. It
|
|
826
|
-
will be removed in a later release; move to <code>@toclocoinc/lattice-grid
|
|
827
|
-
which covers every viewer rather than the grid alone.
|
|
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.
|
|
828
1184
|
</p>
|
|
829
1185
|
|
|
830
1186
|
<div class="note">
|
|
@@ -1001,6 +1357,93 @@ defaults(<span class="kw">null</span>); <span class="cmt">// clea
|
|
|
1001
1357
|
|
|
1002
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>
|
|
1003
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
|
+
|
|
1004
1447
|
<h2 id="dhtmlx-compat">dhtmlx Grid compatibility wrapper</h2>
|
|
1005
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>
|
|
1006
1449
|
|
|
@@ -1514,7 +1957,7 @@ grid.destroy();
|
|
|
1514
1957
|
<table>
|
|
1515
1958
|
<thead><tr><th>Member</th><th>Returns</th><th>Description</th></tr></thead>
|
|
1516
1959
|
<tbody>
|
|
1517
|
-
<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>
|
|
1518
1961
|
<tr><td class="sig">get(key)</td><td class="type">unknown</td><td class="desc">Read any configuration key.</td></tr>
|
|
1519
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>
|
|
1520
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>
|
|
@@ -8195,7 +8638,7 @@ spans.addSpan('R0', 'name', 3, 2); <span class="cmt">// rowspan 3, colspan 2</sp
|
|
|
8195
8638
|
|
|
8196
8639
|
<h3 id="module-exports-example">Every module export, executed</h3>
|
|
8197
8640
|
<p class="section-note">Every shipped module’s exports, resolved against its own barrel on every build.</p>
|
|
8198
|
-
<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>
|
|
8199
8642
|
<span class="cmt">// barrel. A module that stopped exporting something fails here.</span>
|
|
8200
8643
|
<span class="kw">const</span> modules = [
|
|
8201
8644
|
[<span class="kw">await</span> import('../packages/dom/src/index.js'), [
|
|
@@ -8220,6 +8663,10 @@ spans.addSpan('R0', 'name', 3, 2); <span class="cmt">// rowspan 3, colspan 2</sp
|
|
|
8220
8663
|
'ATTRIBUTE_CONFIG', 'EVENT_PREFIX', 'GridElementController',
|
|
8221
8664
|
'TAG_NAME', 'createLatticeGridElement', 'defineLatticeGrid', 'domEventName',
|
|
8222
8665
|
'observedAttributeNames',
|
|
8666
|
+
'createLatticeElements', 'defineLatticeElements', 'ELEMENT_TAGS',
|
|
8667
|
+
'createLatticeKPIElement', 'createLatticeChartElement', 'createLatticeKanbanElement',
|
|
8668
|
+
'createLatticeGanttElement', 'createLatticeLayoutElement', 'createLatticeTabsElement',
|
|
8669
|
+
'createLatticeRouterElement', 'adoptLatticeStyles', 'latticeStyleSheets',
|
|
8223
8670
|
]],
|
|
8224
8671
|
[<span class="kw">await</span> import('../packages/modules/devtools/index.js'), [
|
|
8225
8672
|
'CONSOLE_ACTIVATION', 'createDevtools', 'expose',
|
|
@@ -8536,6 +8983,18 @@ grid.destroy();
|
|
|
8536
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>
|
|
8537
8984
|
<tr><td class="name">observedAttributeNames</td><td class="type">() => string[]</td><td class="desc">The attributes the element reacts to.</td></tr>
|
|
8538
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>
|
|
8539
8998
|
</tbody>
|
|
8540
8999
|
</table>
|
|
8541
9000
|
</div>
|
|
@@ -12170,6 +12629,71 @@ return `next ${p.mean.toFixed(1)}; r2 ${f.r2.toFixed(1)}; band ${p.upper - p.low
|
|
|
12170
12629
|
</tbody>
|
|
12171
12630
|
</table>
|
|
12172
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>
|
|
12173
12697
|
<h3 id="type-LatticeGridHandle">LatticeGridHandle</h3>
|
|
12174
12698
|
<p class="section-note">The live instance a `<LatticeGrid>` ref exposes; `null` before mount.</p>
|
|
12175
12699
|
<div class="table-wrap">
|
|
@@ -12180,6 +12704,75 @@ return `next ${p.mean.toFixed(1)}; r2 ${f.r2.toFixed(1)}; band ${p.upper - p.low
|
|
|
12180
12704
|
</tbody>
|
|
12181
12705
|
</table>
|
|
12182
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>
|
|
12183
12776
|
<h3 id="type-LatticeTabSpec">LatticeTabSpec</h3>
|
|
12184
12777
|
<p class="section-note">One tab of a `<LatticeTabs>`; `content` makes it React's rather than the module's.</p>
|
|
12185
12778
|
<div class="table-wrap">
|
|
@@ -12208,6 +12801,19 @@ return `next ${p.mean.toFixed(1)}; r2 ${f.r2.toFixed(1)}; band ${p.upper - p.low
|
|
|
12208
12801
|
</tbody>
|
|
12209
12802
|
</table>
|
|
12210
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>
|
|
12211
12817
|
<h3 id="type-LatticeViewerHandle">LatticeViewerHandle</h3>
|
|
12212
12818
|
<p class="section-note">The live instance a viewer component's ref exposes; `null` before mount.</p>
|
|
12213
12819
|
<div class="table-wrap">
|
|
@@ -12218,6 +12824,61 @@ return `next ${p.mean.toFixed(1)}; r2 ${f.r2.toFixed(1)}; band ${p.upper - p.low
|
|
|
12218
12824
|
</tbody>
|
|
12219
12825
|
</table>
|
|
12220
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>
|
|
12221
12882
|
<h3 id="type-Layout">Layout</h3>
|
|
12222
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>
|
|
12223
12884
|
<div class="table-wrap">
|
|
@@ -14187,7 +14848,7 @@ return `next ${p.mean.toFixed(1)}; r2 ${f.r2.toFixed(1)}; band ${p.upper - p.low
|
|
|
14187
14848
|
<!-- END GENERATED TYPE REFERENCE -->
|
|
14188
14849
|
|
|
14189
14850
|
<footer>
|
|
14190
|
-
Lattice Grid 1.
|
|
14851
|
+
Lattice Grid 1.66.0 · Copyright © 2026 TOCLOCO Inc. All rights reserved.
|
|
14191
14852
|
This document describes the behaviour of the shipped library. Where this guide and the code
|
|
14192
14853
|
disagree, the code wins: please <a href="https://www.latticegrid.dev">tell us</a>.
|
|
14193
14854
|
</footer>
|