@livenetworks/ashlar 2.1.12 → 2.2.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 +25 -2
- package/components/COMPONENTS.md +29 -25
- package/components/ln-api-connector/ln-api-connector.schema.json +105 -105
- package/components/ln-chart/ln-chart-dev.scss +0 -4
- package/components/ln-core/README.md +16 -60
- package/components/ln-core/index.js +1 -1
- package/components/ln-core/ln-core.schema.json +120 -120
- package/components/ln-core/query.js +113 -113
- package/components/ln-core/reactive.js +0 -59
- package/components/ln-data-coordinator/README.md +2 -0
- package/components/ln-data-coordinator/ln-data-coordinator.js +1 -1
- package/components/ln-data-coordinator/ln-data-coordinator.schema.json +196 -196
- package/components/ln-data-coordinator/src/ln-data-coordinator.js +457 -432
- package/components/ln-data-store/ln-data-store.schema.json +92 -92
- package/components/ln-date/ln-date.js +1 -1
- package/components/ln-date/src/ln-date.js +1 -1
- package/components/ln-debug/ln-debug.js +1 -1
- package/components/ln-debug/ln-debug.schema.json +28 -28
- package/components/ln-debug/src/generated-attributes.js +304 -302
- package/components/ln-dropdown/ln-dropdown.schema.json +90 -90
- package/components/ln-external-links/README.md +19 -19
- package/components/ln-external-links/ln-external-links.js +1 -1
- package/components/ln-external-links/ln-external-links.schema.json +9 -0
- package/components/ln-external-links/ln-external-links.scss +12 -0
- package/components/ln-external-links/src/ln-external-links.js +3 -2
- package/components/ln-filter/README.md +2 -1
- package/components/ln-filter/ln-filter.js +1 -1
- package/components/ln-filter/ln-filter.schema.json +157 -169
- package/components/ln-filter/src/ln-filter.js +4 -4
- package/components/ln-form/ln-form.schema.json +57 -57
- package/components/ln-key/ln-key.js +1 -1
- package/components/ln-key/ln-key.schema.json +8 -0
- package/components/ln-key/src/ln-key.js +8 -5
- package/components/ln-obfuscator/ln-obfuscator.js +1 -1
- package/components/ln-obfuscator/ln-obfuscator.schema.json +6 -0
- package/components/ln-obfuscator/src/ln-obfuscator.js +2 -2
- package/components/ln-options/ln-options.schema.json +47 -47
- package/components/ln-popover/ln-popover.schema.json +82 -82
- package/components/ln-progress/ln-progress.schema.json +0 -13
- package/components/ln-search/ln-search.schema.json +111 -111
- package/components/ln-sort/README.md +1 -0
- package/components/ln-sort/ln-sort.js +1 -1
- package/components/ln-sort/ln-sort.schema.json +100 -112
- package/components/ln-sort/src/sort-model.js +1 -6
- package/components/ln-sortable/ln-sortable.schema.json +38 -38
- package/components/ln-sortable/ln-sortable.scss +25 -25
- package/components/ln-table/README.md +8 -1
- package/components/ln-table/ln-table.js +1 -1
- package/components/ln-table/ln-table.schema.json +195 -195
- package/components/ln-table/src/ln-table.js +43 -7
- package/components/ln-table-coordinator/ln-table-coordinator.js +1 -1
- package/components/ln-table-coordinator/ln-table-coordinator.schema.json +18 -0
- package/components/ln-table-coordinator/src/ln-table-coordinator.js +104 -2
- package/components/ln-toast/README.md +1 -1
- package/components/ln-toast/ln-toast.js +1 -1
- package/components/ln-toast/ln-toast.schema.json +6 -0
- package/components/ln-toast/src/ln-toast.js +1 -1
- package/components/ln-validate/README.md +6 -6
- package/components/ln-validate/ln-validate-dev.scss +0 -5
- package/components/ln-validate/ln-validate.js +1 -1
- package/components/ln-validate/ln-validate.schema.json +0 -6
- package/components/ln-validate/src/ln-validate.js +48 -29
- package/ln-ashlar.html-data.json +1824 -1814
- package/package.json +15 -5
- package/theme/README.md +74 -0
- package/theme/base/_global.scss +2 -2
- package/theme/base/_reset.scss +11 -0
- package/theme/components/_app-shell.scss +0 -8
- package/theme/components/_form.scss +6 -6
- package/theme/components/_ln-table.scss +6 -3
- package/theme/components/_scrollbar.scss +5 -4
- package/theme/components/_sortable.scss +19 -19
- package/theme/components/_stat-card.scss +1 -0
- package/theme/components/_table.scss +11 -35
- package/theme/config/_density.scss +110 -65
- package/theme/config/_palette.scss +71 -49
- package/theme/config/_theme.scss +27 -31
- package/theme/config/_tokens.scss +28 -26
- package/theme/config/mixins/_app-shell.scss +17 -21
- package/theme/config/mixins/_avatar.scss +2 -2
- package/theme/config/mixins/_btn.scss +4 -2
- package/theme/config/mixins/_card.scss +88 -71
- package/theme/config/mixins/_colors.scss +2 -1
- package/theme/config/mixins/_display.scss +12 -0
- package/theme/config/mixins/_footer.scss +3 -1
- package/theme/config/mixins/_form.scss +74 -55
- package/theme/config/mixins/_layout.scss +9 -0
- package/theme/config/mixins/_ln-table.scss +22 -15
- package/theme/config/mixins/_modal.scss +3 -0
- package/theme/config/mixins/_nav.scss +31 -8
- package/theme/config/mixins/_sidebar.scss +2 -1
- package/theme/config/mixins/_spacing.scss +4 -4
- package/theme/config/mixins/_stat-card.scss +33 -2
- package/theme/config/mixins/_status-badge.scss +1 -0
- package/theme/config/mixins/_table.scss +87 -69
- package/theme/config/mixins/_tabs.scss +31 -0
- package/theme/config/mixins/_toast.scss +0 -1
- package/theme/designs/relaxed/_card.scss +12 -0
- package/theme/designs/relaxed/_layout.scss +24 -0
- package/theme/ln-ashlar-core.scss +1 -0
- package/theme/ln-ashlar-dev.scss +0 -1
- package/theme/ln-ashlar-relaxed.scss +67 -0
- package/theme/tailwind/components.css +2198 -0
- package/theme/tailwind/entry.css +3 -0
- package/theme/tailwind/theme.css +23 -0
- package/theme/utilities/_utilities.scss +1 -11
- package/web-types.json +2351 -2337
- package/components/ln-progress/ln-progress-dev.scss +0 -8
|
@@ -1,112 +1,100 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$comment": "This file is partly generated. The $comment, component, generator, and each attribute's direction, sources, type, values, fallback, and description keys are owned by the generator and synchronized from JS source code. All other keys are preserved and safe to hand-author. Regenerate with `npm run sync:ln-schemas`.",
|
|
3
|
-
"component": "ln-sort",
|
|
4
|
-
"generator": "scripts/sync-ln-schemas.mjs",
|
|
5
|
-
"attributes": {
|
|
6
|
-
"data-ln-debug": {
|
|
7
|
-
"direction": null,
|
|
8
|
-
"sources": [
|
|
9
|
-
"ln-sort-dev.scss"
|
|
10
|
-
]
|
|
11
|
-
},
|
|
12
|
-
"data-ln-
|
|
13
|
-
"direction": "author",
|
|
14
|
-
"sources": [
|
|
15
|
-
"src/sort
|
|
16
|
-
]
|
|
17
|
-
},
|
|
18
|
-
"data-ln-
|
|
19
|
-
"direction":
|
|
20
|
-
"sources": [
|
|
21
|
-
"src/sort
|
|
22
|
-
]
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
"
|
|
49
|
-
|
|
50
|
-
"
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
"
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
"
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
"
|
|
85
|
-
|
|
86
|
-
"
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
],
|
|
102
|
-
"fallback": "none",
|
|
103
|
-
"description": "Active sort state applied to column or control"
|
|
104
|
-
},
|
|
105
|
-
"data-ln-table-empty": {
|
|
106
|
-
"direction": "author",
|
|
107
|
-
"sources": [
|
|
108
|
-
"src/sort-model.js"
|
|
109
|
-
]
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"$comment": "This file is partly generated. The $comment, component, generator, and each attribute's direction, sources, type, values, fallback, and description keys are owned by the generator and synchronized from JS source code. All other keys are preserved and safe to hand-author. Regenerate with `npm run sync:ln-schemas`.",
|
|
3
|
+
"component": "ln-sort",
|
|
4
|
+
"generator": "scripts/sync-ln-schemas.mjs",
|
|
5
|
+
"attributes": {
|
|
6
|
+
"data-ln-debug": {
|
|
7
|
+
"direction": null,
|
|
8
|
+
"sources": [
|
|
9
|
+
"ln-sort-dev.scss"
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
"data-ln-field": {
|
|
13
|
+
"direction": "author",
|
|
14
|
+
"sources": [
|
|
15
|
+
"src/ln-sort.js"
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
"data-ln-hash": {
|
|
19
|
+
"direction": null,
|
|
20
|
+
"sources": [
|
|
21
|
+
"src/ln-sort.js"
|
|
22
|
+
],
|
|
23
|
+
"type": "string",
|
|
24
|
+
"description": "URL hash routing key for sort state persistence"
|
|
25
|
+
},
|
|
26
|
+
"data-ln-query": {
|
|
27
|
+
"direction": null,
|
|
28
|
+
"sources": [
|
|
29
|
+
"src/ln-sort.js"
|
|
30
|
+
],
|
|
31
|
+
"type": "string",
|
|
32
|
+
"description": "URL query parameter name for sort state persistence"
|
|
33
|
+
},
|
|
34
|
+
"data-ln-sort": {
|
|
35
|
+
"direction": null,
|
|
36
|
+
"sources": [
|
|
37
|
+
"ln-sort-dev.scss",
|
|
38
|
+
"src/ln-sort.js"
|
|
39
|
+
],
|
|
40
|
+
"type": "string",
|
|
41
|
+
"description": "Target table or list element ID to sort"
|
|
42
|
+
},
|
|
43
|
+
"data-ln-sort-dir": {
|
|
44
|
+
"direction": "author",
|
|
45
|
+
"sources": [
|
|
46
|
+
"src/ln-sort.js"
|
|
47
|
+
],
|
|
48
|
+
"type": "enum",
|
|
49
|
+
"values": [
|
|
50
|
+
"asc",
|
|
51
|
+
"desc"
|
|
52
|
+
],
|
|
53
|
+
"fallback": "asc",
|
|
54
|
+
"description": "Default or requested sort direction"
|
|
55
|
+
},
|
|
56
|
+
"data-ln-sort-exclude": {
|
|
57
|
+
"direction": "author",
|
|
58
|
+
"sources": [
|
|
59
|
+
"src/sort-model.js"
|
|
60
|
+
]
|
|
61
|
+
},
|
|
62
|
+
"data-ln-sort-field": {
|
|
63
|
+
"direction": null,
|
|
64
|
+
"sources": [
|
|
65
|
+
"src/ln-sort.js"
|
|
66
|
+
],
|
|
67
|
+
"type": "string",
|
|
68
|
+
"description": "Field name or column key to sort by"
|
|
69
|
+
},
|
|
70
|
+
"data-ln-sort-items": {
|
|
71
|
+
"direction": "author",
|
|
72
|
+
"sources": [
|
|
73
|
+
"src/ln-sort.js",
|
|
74
|
+
"src/sort-model.js"
|
|
75
|
+
],
|
|
76
|
+
"type": "string",
|
|
77
|
+
"description": "CSS selector matching sortable child items"
|
|
78
|
+
},
|
|
79
|
+
"data-ln-sort-state": {
|
|
80
|
+
"direction": "both",
|
|
81
|
+
"sources": [
|
|
82
|
+
"src/ln-sort.js"
|
|
83
|
+
],
|
|
84
|
+
"type": "enum",
|
|
85
|
+
"values": [
|
|
86
|
+
"asc",
|
|
87
|
+
"desc",
|
|
88
|
+
"none"
|
|
89
|
+
],
|
|
90
|
+
"fallback": "none",
|
|
91
|
+
"description": "Active sort state applied to column or control"
|
|
92
|
+
},
|
|
93
|
+
"data-ln-table-empty": {
|
|
94
|
+
"direction": "author",
|
|
95
|
+
"sources": [
|
|
96
|
+
"src/sort-model.js"
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -74,15 +74,10 @@ export function isExcludedSortItem(el) {
|
|
|
74
74
|
if (!el || typeof el !== 'object' || el.nodeType !== 1) return true;
|
|
75
75
|
if (el.tagName === 'TEMPLATE') return true;
|
|
76
76
|
if (typeof el.hasAttribute === 'function') {
|
|
77
|
-
if (el.hasAttribute('data-ln-sort-exclude') || el.hasAttribute('hidden')) return true;
|
|
77
|
+
if (el.hasAttribute('data-ln-sort-exclude') || el.hasAttribute('data-ln-table-empty') || el.hasAttribute('hidden')) return true;
|
|
78
78
|
}
|
|
79
79
|
if (el.classList && el.classList.contains('hidden')) return true;
|
|
80
80
|
if (el.style && el.style.display === 'none') return true;
|
|
81
|
-
if (typeof el.matches === 'function') {
|
|
82
|
-
if (el.matches('.empty-state, .ln-table__empty, .ln-table__empty-state, [data-ln-empty], [data-ln-empty-state], [data-ln-table-empty]')) {
|
|
83
|
-
return true;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
81
|
return false;
|
|
87
82
|
}
|
|
88
83
|
|
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$comment": "This file is partly generated. The $comment, component, generator, and each attribute's direction, sources, type, values, fallback, and description keys are owned by the generator and synchronized from JS source code. All other keys are preserved and safe to hand-author. Regenerate with `npm run sync:ln-schemas`.",
|
|
3
|
-
"component": "ln-sortable",
|
|
4
|
-
"generator": "scripts/sync-ln-schemas.mjs",
|
|
5
|
-
"attributes": {
|
|
6
|
-
"data-ln-debug": {
|
|
7
|
-
"direction": null,
|
|
8
|
-
"sources": [
|
|
9
|
-
"ln-sortable-dev.scss"
|
|
10
|
-
]
|
|
11
|
-
},
|
|
12
|
-
"data-ln-sortable": {
|
|
13
|
-
"direction": "author",
|
|
14
|
-
"sources": [
|
|
15
|
-
"ln-sortable-dev.scss",
|
|
16
|
-
"ln-sortable.scss",
|
|
17
|
-
"src/ln-sortable.js"
|
|
18
|
-
],
|
|
19
|
-
"type": "enum",
|
|
20
|
-
"values": [
|
|
21
|
-
"enabled",
|
|
22
|
-
"disabled"
|
|
23
|
-
],
|
|
24
|
-
"fallback": "enabled",
|
|
25
|
-
"description": "Enables drag-and-drop item reordering or disables when set to disabled"
|
|
26
|
-
},
|
|
27
|
-
"data-ln-sortable-handle": {
|
|
28
|
-
"direction": "author",
|
|
29
|
-
"sources": [
|
|
30
|
-
"ln-sortable-dev.scss",
|
|
31
|
-
"ln-sortable.scss",
|
|
32
|
-
"src/ln-sortable.js"
|
|
33
|
-
],
|
|
34
|
-
"type": "marker",
|
|
35
|
-
"description": "Designates an element as the drag handle for its parent sortable item"
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"$comment": "This file is partly generated. The $comment, component, generator, and each attribute's direction, sources, type, values, fallback, and description keys are owned by the generator and synchronized from JS source code. All other keys are preserved and safe to hand-author. Regenerate with `npm run sync:ln-schemas`.",
|
|
3
|
+
"component": "ln-sortable",
|
|
4
|
+
"generator": "scripts/sync-ln-schemas.mjs",
|
|
5
|
+
"attributes": {
|
|
6
|
+
"data-ln-debug": {
|
|
7
|
+
"direction": null,
|
|
8
|
+
"sources": [
|
|
9
|
+
"ln-sortable-dev.scss"
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
"data-ln-sortable": {
|
|
13
|
+
"direction": "author",
|
|
14
|
+
"sources": [
|
|
15
|
+
"ln-sortable-dev.scss",
|
|
16
|
+
"ln-sortable.scss",
|
|
17
|
+
"src/ln-sortable.js"
|
|
18
|
+
],
|
|
19
|
+
"type": "enum",
|
|
20
|
+
"values": [
|
|
21
|
+
"enabled",
|
|
22
|
+
"disabled"
|
|
23
|
+
],
|
|
24
|
+
"fallback": "enabled",
|
|
25
|
+
"description": "Enables drag-and-drop item reordering or disables when set to disabled"
|
|
26
|
+
},
|
|
27
|
+
"data-ln-sortable-handle": {
|
|
28
|
+
"direction": "author",
|
|
29
|
+
"sources": [
|
|
30
|
+
"ln-sortable-dev.scss",
|
|
31
|
+
"ln-sortable.scss",
|
|
32
|
+
"src/ln-sortable.js"
|
|
33
|
+
],
|
|
34
|
+
"type": "marker",
|
|
35
|
+
"description": "Designates an element as the drag handle for its parent sortable item"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
// ==========================================================================
|
|
2
|
-
// ln-sortable — Functional State & Drag Rules
|
|
3
|
-
// ==========================================================================
|
|
4
|
-
|
|
5
|
-
[data-ln-sortable] {
|
|
6
|
-
&.ln-sortable--active {
|
|
7
|
-
user-select: none;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
> * {
|
|
11
|
-
&.ln-sortable--dragging {
|
|
12
|
-
will-change: transform, opacity;
|
|
13
|
-
opacity: 0.4;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
[data-ln-sortable-handle] {
|
|
19
|
-
touch-action: none;
|
|
20
|
-
cursor: grab;
|
|
21
|
-
|
|
22
|
-
&:active {
|
|
23
|
-
cursor: grabbing;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
1
|
+
// ==========================================================================
|
|
2
|
+
// ln-sortable — Functional State & Drag Rules
|
|
3
|
+
// ==========================================================================
|
|
4
|
+
|
|
5
|
+
[data-ln-sortable] {
|
|
6
|
+
&.ln-sortable--active {
|
|
7
|
+
user-select: none;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
> * {
|
|
11
|
+
&.ln-sortable--dragging {
|
|
12
|
+
will-change: transform, opacity;
|
|
13
|
+
opacity: 0.4;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
[data-ln-sortable-handle] {
|
|
19
|
+
touch-action: none;
|
|
20
|
+
cursor: grab;
|
|
21
|
+
|
|
22
|
+
&:active {
|
|
23
|
+
cursor: grabbing;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -181,6 +181,7 @@ External UI controls (`ln-search`, `ln-filter`, filter header buttons, clear but
|
|
|
181
181
|
| `data-ln-table-row-select` | `<input>` | Selection checkbox in row templates. |
|
|
182
182
|
| `data-ln-table-row-action="name"`| `<button>` | Action button trigger in row templates. |
|
|
183
183
|
| `data-ln-table-loading` | Indicator / Template | Loading indicator element in footer (revealed during background re-fetch) or loading state template. |
|
|
184
|
+
| `data-ln-table-empty` | `<tr>` / Template | Written by ln-table on the rendered empty and loading placeholder row. ln-sort and ln-filter skip rows that carry it. Author it on a hand-written placeholder row in a plain table. On a `<template>` it holds the empty-state content. |
|
|
184
185
|
|
|
185
186
|
---
|
|
186
187
|
|
|
@@ -234,7 +235,7 @@ Column filters use static authored markup — a `[data-ln-popover]` block contai
|
|
|
234
235
|
<!-- th attribute maps filter key → column -->
|
|
235
236
|
<th data-ln-table-filter-col="department">
|
|
236
237
|
Department
|
|
237
|
-
<button
|
|
238
|
+
<button type="button"
|
|
238
239
|
data-ln-table-col-filter
|
|
239
240
|
data-ln-popover-for="filter-dept"
|
|
240
241
|
aria-label="Filter department">
|
|
@@ -330,6 +331,12 @@ the same target: `ln-table` calls `preventDefault()` unconditionally on
|
|
|
330
331
|
|
|
331
332
|
A single observer on `document.body`: new `data-ln-table` root injected → `new lnTable(node)`; elements injected inside a live root → local rescan (no full re-init); `data-ln-table-source`/`-window` attribute set on an existing element → re-evaluated live (see Windowed Mode below).
|
|
332
333
|
|
|
334
|
+
### Virtual scroll row height
|
|
335
|
+
|
|
336
|
+
`_rowHeight` is measured once, from the first rows that exist (`_parseRows`, else `_enableVirtualScroll`). While virtual scrolling is active, a window `resize` sets a flag and goes through the same rAF as scroll. The next `_renderVirtual` re-measures the pitch of the rendered block (first to last pool row) before it writes anything. If the pitch changed, for example because a media query turned rows into stacked cards, the window is recomputed and the scroll position moves so the record at the top of the viewport stays there. `calculateVirtualWindow` still assumes uniform rows, so the pitch is an average. Changes in container width that do not resize the window are not observed.
|
|
337
|
+
|
|
338
|
+
Column widths are locked once (`<colgroup>` + inline `table-layout: fixed`), from the column-header row, and only while that row has a box. A header that is hidden at bootstrap (stacked-card mode, or a hidden ancestor) defers the lock. A virtual table retries it on each window `resize` until it succeeds. A non-virtual table stays on automatic layout.
|
|
339
|
+
|
|
333
340
|
### Windowed cache mechanics
|
|
334
341
|
|
|
335
342
|
Backed by `ln-core.createWindowCache` — the table owns the cache instance, not the full dataset:
|