@livenetworks/ashlar 2.0.7 → 2.0.9

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.
Files changed (213) hide show
  1. package/LICENSE +641 -641
  2. package/components/COMPONENTS.md +1116 -1116
  3. package/components/index.js +81 -81
  4. package/components/ln-accordion/ln-accordion-dev.scss +8 -8
  5. package/components/ln-accordion/ln-accordion.js +1 -1
  6. package/components/ln-accordion/ln-accordion.schema.json +30 -30
  7. package/components/ln-ajax/ln-ajax-dev.scss +8 -8
  8. package/components/ln-ajax/ln-ajax.js +1 -1
  9. package/components/ln-ajax/ln-ajax.schema.json +30 -30
  10. package/components/ln-api-connector/ln-api-connector.js +1 -1
  11. package/components/ln-api-connector/ln-api-connector.schema.json +9 -0
  12. package/components/ln-api-connector/src/ln-api-connector.js +2 -0
  13. package/components/ln-api-queue/ln-api-queue.js +1 -1
  14. package/components/ln-api-queue/ln-api-queue.schema.json +34 -34
  15. package/components/ln-api-queue/src/ln-api-queue.js +3 -13
  16. package/components/ln-autoresize/ln-autoresize-dev.scss +8 -8
  17. package/components/ln-autoresize/ln-autoresize.js +1 -1
  18. package/components/ln-autoresize/ln-autoresize.schema.json +22 -22
  19. package/components/ln-autosave/ln-autosave-dev.scss +13 -13
  20. package/components/ln-autosave/ln-autosave.js +1 -1
  21. package/components/ln-autosave/ln-autosave.schema.json +48 -48
  22. package/components/ln-autosave/src/autosave-model.js +34 -34
  23. package/components/ln-chart/ln-chart.js +1 -1
  24. package/components/ln-chart/ln-chart.schema.json +146 -146
  25. package/components/ln-chart/src/chart-model.js +154 -154
  26. package/components/ln-circular-progress/ln-circular-progress.js +1 -1
  27. package/components/ln-circular-progress/ln-circular-progress.schema.json +42 -42
  28. package/components/ln-confirm/ln-confirm-dev.scss +24 -24
  29. package/components/ln-confirm/ln-confirm.js +1 -1
  30. package/components/ln-confirm/ln-confirm.schema.json +66 -66
  31. package/components/ln-confirm/src/ln-confirm.js +178 -178
  32. package/components/ln-core/attrs.js +13 -0
  33. package/components/ln-core/crypto.js +286 -265
  34. package/components/ln-core/dom.js +115 -115
  35. package/components/ln-core/form.js +146 -136
  36. package/components/ln-core/helpers.js +33 -33
  37. package/components/ln-core/http.js +48 -48
  38. package/components/ln-core/index.js +1 -1
  39. package/components/ln-core/lifecycle.js +5 -0
  40. package/components/ln-core/ln-core.schema.json +3 -2
  41. package/components/ln-core/locale.js +55 -55
  42. package/components/ln-core/matching.js +78 -78
  43. package/components/ln-core/number.js +125 -125
  44. package/components/ln-core/template.js +206 -206
  45. package/components/ln-couchdb-connector/ln-couchdb-connector.js +1 -1
  46. package/components/ln-couchdb-connector/ln-couchdb-connector.schema.json +50 -50
  47. package/components/ln-couchdb-connector/src/ln-couchdb-connector.js +1 -0
  48. package/components/ln-data-coordinator/README.md +9 -38
  49. package/components/ln-data-coordinator/ln-data-coordinator-dev.scss +8 -8
  50. package/components/ln-data-coordinator/ln-data-coordinator.js +1 -1
  51. package/components/ln-data-coordinator/ln-data-coordinator.schema.json +16 -16
  52. package/components/ln-data-coordinator/src/data-read-policy.js +0 -7
  53. package/components/ln-data-coordinator/src/ln-data-coordinator.js +432 -1308
  54. package/components/ln-data-store/ln-data-store-dev.scss +13 -13
  55. package/components/ln-data-store/ln-data-store.js +1 -1
  56. package/components/ln-data-store/ln-data-store.schema.json +84 -84
  57. package/components/ln-data-store/src/data-store-model.js +184 -184
  58. package/components/ln-data-store/src/ln-data-store.js +1 -1
  59. package/components/ln-date/ln-date.js +1 -1
  60. package/components/ln-date/ln-date.schema.json +92 -92
  61. package/components/ln-date/src/date-model.js +186 -186
  62. package/components/ln-debug/ln-debug.js +1 -1
  63. package/components/ln-debug/ln-debug.schema.json +28 -28
  64. package/components/ln-debug/src/console-sink.js +19 -19
  65. package/components/ln-debug/src/gate.js +95 -95
  66. package/components/ln-debug/src/generated-attributes.js +4 -2
  67. package/components/ln-dropdown/ln-dropdown-dev.scss +13 -13
  68. package/components/ln-dropdown/ln-dropdown.js +1 -1
  69. package/components/ln-dropdown/ln-dropdown.schema.json +90 -90
  70. package/components/ln-editor/ln-editor.js +1 -1
  71. package/components/ln-editor/ln-editor.schema.json +58 -58
  72. package/components/ln-external-links/ln-external-links.js +1 -1
  73. package/components/ln-external-links/ln-external-links.schema.json +18 -18
  74. package/components/ln-fill/ln-fill.js +1 -1
  75. package/components/ln-fill/ln-fill.schema.json +23 -23
  76. package/components/ln-filter/ln-filter.js +1 -1
  77. package/components/ln-filter/ln-filter.schema.json +153 -153
  78. package/components/ln-filter/src/filter-model.js +185 -185
  79. package/components/ln-form/ln-form-dev.scss +8 -8
  80. package/components/ln-form/ln-form.js +1 -1
  81. package/components/ln-form/ln-form.schema.json +6 -0
  82. package/components/ln-form/src/ln-form.js +21 -0
  83. package/components/ln-http/ln-http.js +1 -1
  84. package/components/ln-http/ln-http.schema.json +6 -6
  85. package/components/ln-icon/ln-icon.schema.json +6 -6
  86. package/components/ln-include/ln-include.js +1 -1
  87. package/components/ln-include/ln-include.schema.json +23 -23
  88. package/components/ln-key/ln-key-dev.scss +18 -18
  89. package/components/ln-key/ln-key.js +1 -1
  90. package/components/ln-key/ln-key.schema.json +56 -56
  91. package/components/ln-key/src/ln-key.js +10 -10
  92. package/components/ln-link/ln-link-dev.scss +8 -8
  93. package/components/ln-link/ln-link.js +1 -1
  94. package/components/ln-link/ln-link.schema.json +22 -22
  95. package/components/ln-list/README.md +152 -152
  96. package/components/ln-list/ln-list-dev.scss +8 -8
  97. package/components/ln-list/ln-list.js +1 -1
  98. package/components/ln-list/ln-list.schema.json +166 -166
  99. package/components/ln-modal/ln-modal.js +1 -1
  100. package/components/ln-modal/ln-modal.schema.json +65 -65
  101. package/components/ln-nav/ln-nav.js +1 -1
  102. package/components/ln-nav/ln-nav.schema.json +25 -25
  103. package/components/ln-number/ln-number.js +1 -1
  104. package/components/ln-number/ln-number.schema.json +63 -63
  105. package/components/ln-number/src/ln-number.js +26 -0
  106. package/components/ln-number/src/number-model.js +31 -31
  107. package/components/ln-obfuscator/README.md +60 -60
  108. package/components/ln-obfuscator/ln-obfuscator.js +1 -1
  109. package/components/ln-obfuscator/ln-obfuscator.schema.json +49 -49
  110. package/components/ln-obfuscator/src/ln-obfuscator.js +159 -159
  111. package/components/ln-obfuscator/src/obfuscator-model.js +250 -250
  112. package/components/ln-options/ln-options.js +1 -1
  113. package/components/ln-options/ln-options.schema.json +6 -0
  114. package/components/ln-options/src/ln-options.js +4 -4
  115. package/components/ln-persist/README.md +151 -151
  116. package/components/ln-persist/ln-persist.js +1 -1
  117. package/components/ln-persist/ln-persist.schema.json +28 -28
  118. package/components/ln-persist/src/ln-persist.js +83 -83
  119. package/components/ln-picklist/README.md +230 -230
  120. package/components/ln-picklist/ln-picklist-dev.scss +22 -22
  121. package/components/ln-picklist/ln-picklist.js +1 -1
  122. package/components/ln-picklist/ln-picklist.schema.json +49 -49
  123. package/components/ln-picklist/src/ln-picklist.js +228 -228
  124. package/components/ln-popover/ln-popover-dev.scss +13 -13
  125. package/components/ln-popover/ln-popover.js +1 -1
  126. package/components/ln-popover/ln-popover.schema.json +82 -82
  127. package/components/ln-progress/ln-progress-dev.scss +8 -8
  128. package/components/ln-progress/ln-progress.js +1 -1
  129. package/components/ln-progress/ln-progress.schema.json +40 -40
  130. package/components/ln-router/ln-router.js +1 -1
  131. package/components/ln-router/ln-router.schema.json +76 -76
  132. package/components/ln-scroll/README.md +45 -45
  133. package/components/ln-scroll/ln-scroll.js +1 -1
  134. package/components/ln-scroll/ln-scroll.schema.json +85 -85
  135. package/components/ln-scroll/src/ln-scroll.js +150 -150
  136. package/components/ln-search/README.md +188 -188
  137. package/components/ln-search/ln-search.js +1 -1
  138. package/components/ln-search/ln-search.schema.json +103 -103
  139. package/components/ln-slug/ln-slug.js +1 -1
  140. package/components/ln-slug/ln-slug.schema.json +23 -23
  141. package/components/ln-slug/src/ln-slug.js +25 -1
  142. package/components/ln-sort/ln-sort.js +1 -1
  143. package/components/ln-sort/ln-sort.schema.json +104 -104
  144. package/components/ln-sort/src/ln-sort.js +321 -321
  145. package/components/ln-sort/src/sort-model.js +117 -117
  146. package/components/ln-sortable/ln-sortable-dev.scss +13 -13
  147. package/components/ln-sortable/ln-sortable.js +1 -1
  148. package/components/ln-sortable/ln-sortable.schema.json +36 -36
  149. package/components/ln-stat/ln-stat-dev.scss +8 -8
  150. package/components/ln-stat/ln-stat.js +1 -1
  151. package/components/ln-stat/ln-stat.schema.json +32 -32
  152. package/components/ln-stat/src/stat-model.js +28 -28
  153. package/components/ln-table/ln-table.js +1 -1
  154. package/components/ln-table/ln-table.schema.json +211 -211
  155. package/components/ln-table/src/table-model.js +98 -98
  156. package/components/ln-table-coordinator/ln-table-coordinator.js +1 -1
  157. package/components/ln-table-coordinator/ln-table-coordinator.schema.json +93 -93
  158. package/components/ln-tabs/ln-tabs.js +1 -1
  159. package/components/ln-tabs/ln-tabs.schema.json +75 -75
  160. package/components/ln-tabs/src/ln-tabs.js +208 -208
  161. package/components/ln-tabs/src/tabs-model.js +82 -82
  162. package/components/ln-time/ln-time-dev.scss +13 -13
  163. package/components/ln-time/ln-time.js +1 -1
  164. package/components/ln-time/ln-time.schema.json +38 -38
  165. package/components/ln-toast/ln-toast.js +1 -1
  166. package/components/ln-toast/ln-toast.schema.json +65 -65
  167. package/components/ln-toggle/ln-toggle.js +1 -1
  168. package/components/ln-toggle/ln-toggle.schema.json +52 -52
  169. package/components/ln-tooltip/ln-tooltip.js +1 -1
  170. package/components/ln-tooltip/ln-tooltip.schema.json +86 -86
  171. package/components/ln-translations/ln-translations.js +1 -1
  172. package/components/ln-translations/ln-translations.schema.json +120 -120
  173. package/components/ln-ui-coordinator/README.md +62 -62
  174. package/components/ln-ui-coordinator/ln-ui-coordinator.js +1 -1
  175. package/components/ln-ui-coordinator/ln-ui-coordinator.schema.json +28 -28
  176. package/components/ln-ui-coordinator/src/ln-ui-coordinator.js +140 -140
  177. package/components/ln-upload/ln-upload.js +1 -1
  178. package/components/ln-upload/ln-upload.schema.json +193 -193
  179. package/components/ln-upload/src/upload-model.js +78 -78
  180. package/components/ln-validate/ln-validate.js +1 -1
  181. package/components/ln-validate/ln-validate.schema.json +50 -50
  182. package/components/ln-validate/src/validate-model.js +64 -64
  183. package/components/ln-websocket-connector/README.md +166 -166
  184. package/components/ln-websocket-connector/ln-websocket-connector.js +1 -1
  185. package/components/ln-websocket-connector/ln-websocket-connector.schema.json +29 -29
  186. package/components/ln-websocket-connector/src/ln-websocket-connector.js +283 -279
  187. package/ln-ashlar.html-data.json +15 -8
  188. package/package.json +85 -84
  189. package/theme/brand.css +73 -73
  190. package/theme/components/_confirm.scss +6 -6
  191. package/theme/components/_picklist.scss +3 -3
  192. package/theme/config/_palette.scss +274 -274
  193. package/theme/config/_theme.scss +292 -292
  194. package/theme/config/_tokens.scss +285 -285
  195. package/theme/config/mixins/_index.scss +62 -62
  196. package/theme/config/mixins/_picklist.scss +66 -66
  197. package/theme/ln-ashlar-dev.scss +66 -66
  198. package/theme/ln-ashlar-landing.scss +56 -56
  199. package/theme/ln-ashlar-theme.scss +63 -63
  200. package/theme/presentation/_bento.scss +151 -151
  201. package/theme/presentation/_cta.scss +111 -111
  202. package/theme/presentation/_effects.scss +216 -216
  203. package/theme/presentation/_features.scss +108 -108
  204. package/theme/presentation/_footer.scss +129 -129
  205. package/theme/presentation/_hero.scss +158 -158
  206. package/theme/presentation/_layout.scss +170 -170
  207. package/theme/presentation/_navbar.scss +140 -140
  208. package/theme/presentation/_pricing.scss +262 -262
  209. package/theme/presentation/_stats.scss +87 -87
  210. package/theme/presentation/_testimonials.scss +124 -124
  211. package/theme/presentation/_tokens.scss +39 -39
  212. package/theme/presentation/_typography.scss +163 -163
  213. package/web-types.json +26 -12
@@ -1,22 +1,22 @@
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-link",
4
- "generator": "scripts/sync-ln-schemas.mjs",
5
- "attributes": {
6
- "data-ln-debug": {
7
- "direction": null,
8
- "sources": [
9
- "ln-link-dev.scss"
10
- ]
11
- },
12
- "data-ln-link": {
13
- "direction": "author",
14
- "sources": [
15
- "ln-link-dev.scss",
16
- "src/ln-link.js"
17
- ],
18
- "type": "marker",
19
- "description": "Makes entire table row or container clickable based on child anchor link"
20
- }
21
- }
22
- }
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-link",
4
+ "generator": "scripts/sync-ln-schemas.mjs",
5
+ "attributes": {
6
+ "data-ln-debug": {
7
+ "direction": null,
8
+ "sources": [
9
+ "ln-link-dev.scss"
10
+ ]
11
+ },
12
+ "data-ln-link": {
13
+ "direction": "author",
14
+ "sources": [
15
+ "ln-link-dev.scss",
16
+ "src/ln-link.js"
17
+ ],
18
+ "type": "marker",
19
+ "description": "Makes entire table row or container clickable based on child anchor link"
20
+ }
21
+ }
22
+ }
@@ -1,152 +1,152 @@
1
- # ln-list
2
-
3
- > Applied to a list or grid container via `data-ln-list="name"`. In SSR mode, it coordinates direct DOM search,
4
- > filter, and sort interactions on its child items. In data-driven mode (`data-ln-list-source="store"`), it listens for
5
- > `ln-data-store:data` CustomEvents, clones `<template data-ln-template="name-row">`, populates fields via `fill()`,
6
- > and mounts rendered items into `[data-ln-list-body]` with optional virtual scroll windowing.
7
-
8
- ---
9
-
10
- ## 📦 Declarative Setup in HTML
11
-
12
- ### 1. Simple SSR List
13
- For a server-rendered list where the backend outputs `<li>` elements directly:
14
-
15
- ```html
16
- <search aria-label="Search documents">
17
- <svg class="ln-icon" aria-hidden="true"><use href="#ln-icon-search"></use></svg>
18
- <input type="search" placeholder="Search..." data-ln-search-for="documents-list">
19
- <button type="button" data-ln-search-clear aria-label="Clear search">
20
- <svg class="ln-icon" aria-hidden="true"><use href="#ln-icon-x"></use></svg>
21
- </button>
22
- </search>
23
-
24
- <ul id="documents-list" data-ln-list="documents" data-ln-search="">
25
- <li data-ln-item-id="1">Document A</li>
26
- <li data-ln-item-id="2">Document B</li>
27
- </ul>
28
- ```
29
-
30
- ### 2. Data-Driven Grid List (with Virtual Scroll)
31
- Opted-in by adding the `data-ln-list-source` attribute pointing to a `data-ln-data-store`. The search input targets the store:
32
-
33
- ```html
34
- <!-- Store is the State Host for queries in Data-Driven mode -->
35
- <div data-ln-data-store="documents" data-ln-search=""></div>
36
-
37
- <search aria-label="Search documents">
38
- <svg class="ln-icon" aria-hidden="true"><use href="#ln-icon-search"></use></svg>
39
- <input type="search" placeholder="Search..." data-ln-search-for="documents">
40
- <button type="button" data-ln-search-clear aria-label="Clear search">
41
- <svg class="ln-icon" aria-hidden="true"><use href="#ln-icon-x"></use></svg>
42
- </button>
43
- </search>
44
-
45
- <section id="documents-grid"
46
- data-ln-list="documents"
47
- data-ln-list-source="documents"
48
- data-ln-list-window="1000"
49
- data-ln-list-selectable>
50
-
51
- <!-- Items container -->
52
- <ul class="grid-layout" data-ln-list-body></ul>
53
-
54
- <!-- Row Template (Must contain an element with data-ln-item attribute) -->
55
- <template data-ln-template="documents-row">
56
- <li data-ln-item class="card-item">
57
- <header>
58
- <input type="checkbox" data-ln-item-select>
59
- <h3 data-ln-field="title"></h3>
60
- </header>
61
- <p>{{ description }}</p>
62
- <button type="button" data-ln-item-action="delete">Delete</button>
63
- </li>
64
- </template>
65
-
66
- <!-- Empty States -->
67
- <template data-ln-template="documents-empty">
68
- <div class="empty-state">No documents found.</div>
69
- </template>
70
-
71
- <template data-ln-template="documents-empty-filtered">
72
- <div class="empty-state">No matching documents found.</div>
73
- </template>
74
- </section>
75
- ```
76
-
77
- ---
78
-
79
- ## 🛠️ Attributes Reference
80
-
81
- | Attribute | Elements | Description |
82
- | :--- | :--- | :--- |
83
- | `data-ln-list` | Root wrapper | Component identifier. Target must carry a unique `id`. |
84
- | `data-ln-list-source` | Root wrapper | Opt-in indicator for Data-Driven Mode (points to Store ID). |
85
- | `data-ln-list-selectable` | Root wrapper | Enables checkbox-based item selections. |
86
- | `data-ln-list-window="N"` | Root wrapper | Opt-in server-side sliding-window virtualization. `N` sets the resident-row cap (default 1000). Requires Data-Driven Mode. |
87
- | `data-ln-list-window-page="N"` | Root wrapper | Chunk/page fetch size for windowed requests (default 200). |
88
- | `data-ln-list-window-threshold="N"` | Root wrapper | Prefetch margin threshold in rows before reaching edge (default 25). |
89
- | `data-ln-list-count="N"` | Root wrapper | Declares unfiltered grand total for windowed lists. |
90
- | `data-ln-list-body` | Sub-element | Target container where items are rendered (falls back to root). |
91
- | `data-ln-item` | Template element | Identifies an item root inside a template or hydrated markup. |
92
- | `data-ln-item-id` | `[data-ln-item]` | Unique ID of the row item. |
93
- | `data-ln-item-select` | `<input>` | Checkbox inside item template for row selection. |
94
- | `data-ln-item-action="name"` | `<button>` | Item action button (dispatches `ln-list:item-action`). |
95
- | `data-ln-list-select-all` | `<input>` | Global select-all checkbox for list items. |
96
- | `data-ln-list-field="key"` | Sub-element | Maps element value (via `readValue()`) to record property for sorting/filtering. |
97
- | `data-ln-list-total` | `<span>` | Target element to display total record count. |
98
- | `data-ln-list-filtered` | `<span>` | Target element to display filtered count. |
99
- | `data-ln-list-selected` | `<span>` | Target element to display active selection count. |
100
- | `data-ln-list-empty` | `<template>` | Empty state template in SSR mode. |
101
- | `data-ln-empty` | `<template>` | Generic empty state template in Data-Driven mode. |
102
- | `data-ln-empty-when="initial\|search"` | Sub-element | Conditional empty state view inside `template[data-ln-empty]`. |
103
-
104
- ---
105
-
106
- ## ⚡ DOM Events
107
-
108
- ### Listened Events
109
-
110
- * `ln-list:set-search` `{ query }`: Layer 1 command to set list search term.
111
- * `ln-list:set-data` `{ data, total, filtered }`: Hydrates/renders the items in Data-Driven mode.
112
- * `ln-list:set-loading` `{ loading: true|false }`: Toggles the loading dimming overlay class (`.ln-list--loading`).
113
- * `ln-list:page-failed` `{ offset }`: Windowed mode — the coordinator reports the page fetch at `offset` failed.
114
- * `ln-list:request-revalidate`: Windowed mode — asks the cache to revalidate the currently visible page after a local mutation.
115
- * `ln-list:request-invalidate`: Windowed mode — invalidates window cache and resets to page 0.
116
- * `ln-list:request-clear-filters`: Layer 1 command to clear search and active filters.
117
- * `ln-search:change` `{ term }`: Top-level search change. In Data-Driven mode, triggers query refetch via `_requestData()`. In SSR mode, filters in-memory records and updates DOM.
118
- * `ln-filter:change` `{ key, values }`: SSR mode — filters in-memory records by field / data attributes.
119
- * `ln-sort:change` `{ field, direction }`: In Data-Driven mode, sets `currentSort` and triggers query refetch via `_requestData()`. In SSR mode, sorts in-memory records and updates virtual scroll.
120
-
121
- ### Emitted Events
122
-
123
- * `ln-list:request-data` `{ list, sort, filters, search }`: Requests data query from the Coordinator. When windowed, includes `{ offset, limit, queryGen }`.
124
- * `ln-list:search` `{ list, query }`: Fired in Data-Driven mode when search term updates.
125
- * `ln-list:ready` `{ total }`: Fired when initial markup parsing completes.
126
- * `ln-list:rendered` `{ list, total, visible }`: Fired after items have been drawn to DOM.
127
- * `ln-list:filter` `{ term, matched, total }`: Fired in SSR mode when search/filter narrows visible items.
128
- * `ln-list:sorted` `{ field, direction, matched, total }`: Fired in SSR mode when items are sorted.
129
- * `ln-list:item-click` `{ list, id, record }`: Fired when clicking item body (excluding buttons, anchors, inputs).
130
- * `ln-list:item-action` `{ list, id, action, record }`: Fired when clicking `[data-ln-item-action]`.
131
- * `ln-list:select` `{ list, selectedIds, count }`: Fired when selection updates.
132
- * `ln-list:select-all` `{ list, selected: true|false }`: Fired when select-all triggers.
133
- * `ln-list:empty` `{ term, total }`: Fired when the list becomes empty.
134
- * `ln-list:clear-filters` `{ list }`: Fired in Data-Driven mode when filters are cleared.
135
-
136
- ---
137
-
138
- ## 🔧 Internals
139
-
140
- Source: `components/ln-list/src/ln-list.js`.
141
-
142
- ### Spacer element matches container semantics
143
-
144
- Virtual scroll needs top/bottom spacer elements to preserve scroll height without rendering off-screen rows. If `[data-ln-list-body]` is a `<ul>`/`<ol>`, spacers are `<li class="ln-list__spacer" aria-hidden="true">` to stay HTML5-valid and accessible; any other container gets `<div class="ln-list__spacer" aria-hidden="true">`.
145
-
146
- ### Slice / Windowed virtualization
147
-
148
- When windowed virtualization is enabled (`data-ln-list-window`), `ln-list` operates with slice rendering via `createWindowCache`. Only a sliding window of records is kept resident in the view. When the user scrolls, `ln-list` renders placeholder items for records that are not yet loaded and dispatches `ln-list:request-data` with `{ offset, limit }` to fetch the missing slice from the coordinator.
149
-
150
- ### `_parseChildren()`
151
-
152
- Parses static children inside `[data-ln-list-body]` into `this._data` at mount (excluding existing spacers), extracting `searchText` and structured values via `readValue()` (`data-ln-value`), and measures the first child's height for `this._itemHeight`.
1
+ # ln-list
2
+
3
+ > Applied to a list or grid container via `data-ln-list="name"`. In SSR mode, it coordinates direct DOM search,
4
+ > filter, and sort interactions on its child items. In data-driven mode (`data-ln-list-source="store"`), it listens for
5
+ > `ln-data-store:data` CustomEvents, clones `<template data-ln-template="name-row">`, populates fields via `fill()`,
6
+ > and mounts rendered items into `[data-ln-list-body]` with optional virtual scroll windowing.
7
+
8
+ ---
9
+
10
+ ## 📦 Declarative Setup in HTML
11
+
12
+ ### 1. Simple SSR List
13
+ For a server-rendered list where the backend outputs `<li>` elements directly:
14
+
15
+ ```html
16
+ <search aria-label="Search documents">
17
+ <svg class="ln-icon" aria-hidden="true"><use href="#ln-icon-search"></use></svg>
18
+ <input type="search" placeholder="Search..." data-ln-search-for="documents-list">
19
+ <button type="button" data-ln-search-clear aria-label="Clear search">
20
+ <svg class="ln-icon" aria-hidden="true"><use href="#ln-icon-x"></use></svg>
21
+ </button>
22
+ </search>
23
+
24
+ <ul id="documents-list" data-ln-list="documents" data-ln-search="">
25
+ <li data-ln-item-id="1">Document A</li>
26
+ <li data-ln-item-id="2">Document B</li>
27
+ </ul>
28
+ ```
29
+
30
+ ### 2. Data-Driven Grid List (with Virtual Scroll)
31
+ Opted-in by adding the `data-ln-list-source` attribute pointing to a `data-ln-data-store`. The search input targets the store:
32
+
33
+ ```html
34
+ <!-- Store is the State Host for queries in Data-Driven mode -->
35
+ <div data-ln-data-store="documents" data-ln-search=""></div>
36
+
37
+ <search aria-label="Search documents">
38
+ <svg class="ln-icon" aria-hidden="true"><use href="#ln-icon-search"></use></svg>
39
+ <input type="search" placeholder="Search..." data-ln-search-for="documents">
40
+ <button type="button" data-ln-search-clear aria-label="Clear search">
41
+ <svg class="ln-icon" aria-hidden="true"><use href="#ln-icon-x"></use></svg>
42
+ </button>
43
+ </search>
44
+
45
+ <section id="documents-grid"
46
+ data-ln-list="documents"
47
+ data-ln-list-source="documents"
48
+ data-ln-list-window="1000"
49
+ data-ln-list-selectable>
50
+
51
+ <!-- Items container -->
52
+ <ul class="grid-layout" data-ln-list-body></ul>
53
+
54
+ <!-- Row Template (Must contain an element with data-ln-item attribute) -->
55
+ <template data-ln-template="documents-row">
56
+ <li data-ln-item class="card-item">
57
+ <header>
58
+ <input type="checkbox" data-ln-item-select>
59
+ <h3 data-ln-field="title"></h3>
60
+ </header>
61
+ <p>{{ description }}</p>
62
+ <button type="button" data-ln-item-action="delete">Delete</button>
63
+ </li>
64
+ </template>
65
+
66
+ <!-- Empty States -->
67
+ <template data-ln-template="documents-empty">
68
+ <div class="empty-state">No documents found.</div>
69
+ </template>
70
+
71
+ <template data-ln-template="documents-empty-filtered">
72
+ <div class="empty-state">No matching documents found.</div>
73
+ </template>
74
+ </section>
75
+ ```
76
+
77
+ ---
78
+
79
+ ## 🛠️ Attributes Reference
80
+
81
+ | Attribute | Elements | Description |
82
+ | :--- | :--- | :--- |
83
+ | `data-ln-list` | Root wrapper | Component identifier. Target must carry a unique `id`. |
84
+ | `data-ln-list-source` | Root wrapper | Opt-in indicator for Data-Driven Mode (points to Store ID). |
85
+ | `data-ln-list-selectable` | Root wrapper | Enables checkbox-based item selections. |
86
+ | `data-ln-list-window="N"` | Root wrapper | Opt-in server-side sliding-window virtualization. `N` sets the resident-row cap (default 1000). Requires Data-Driven Mode. |
87
+ | `data-ln-list-window-page="N"` | Root wrapper | Chunk/page fetch size for windowed requests (default 200). |
88
+ | `data-ln-list-window-threshold="N"` | Root wrapper | Prefetch margin threshold in rows before reaching edge (default 25). |
89
+ | `data-ln-list-count="N"` | Root wrapper | Declares unfiltered grand total for windowed lists. |
90
+ | `data-ln-list-body` | Sub-element | Target container where items are rendered (falls back to root). |
91
+ | `data-ln-item` | Template element | Identifies an item root inside a template or hydrated markup. |
92
+ | `data-ln-item-id` | `[data-ln-item]` | Unique ID of the row item. |
93
+ | `data-ln-item-select` | `<input>` | Checkbox inside item template for row selection. |
94
+ | `data-ln-item-action="name"` | `<button>` | Item action button (dispatches `ln-list:item-action`). |
95
+ | `data-ln-list-select-all` | `<input>` | Global select-all checkbox for list items. |
96
+ | `data-ln-list-field="key"` | Sub-element | Maps element value (via `readValue()`) to record property for sorting/filtering. |
97
+ | `data-ln-list-total` | `<span>` | Target element to display total record count. |
98
+ | `data-ln-list-filtered` | `<span>` | Target element to display filtered count. |
99
+ | `data-ln-list-selected` | `<span>` | Target element to display active selection count. |
100
+ | `data-ln-list-empty` | `<template>` | Empty state template in SSR mode. |
101
+ | `data-ln-empty` | `<template>` | Generic empty state template in Data-Driven mode. |
102
+ | `data-ln-empty-when="initial\|search"` | Sub-element | Conditional empty state view inside `template[data-ln-empty]`. |
103
+
104
+ ---
105
+
106
+ ## ⚡ DOM Events
107
+
108
+ ### Listened Events
109
+
110
+ * `ln-list:set-search` `{ query }`: Layer 1 command to set list search term.
111
+ * `ln-list:set-data` `{ data, total, filtered }`: Hydrates/renders the items in Data-Driven mode.
112
+ * `ln-list:set-loading` `{ loading: true|false }`: Toggles the loading dimming overlay class (`.ln-list--loading`).
113
+ * `ln-list:page-failed` `{ offset }`: Windowed mode — the coordinator reports the page fetch at `offset` failed.
114
+ * `ln-list:request-revalidate`: Windowed mode — asks the cache to revalidate the currently visible page after a local mutation.
115
+ * `ln-list:request-invalidate`: Windowed mode — invalidates window cache and resets to page 0.
116
+ * `ln-list:request-clear-filters`: Layer 1 command to clear search and active filters.
117
+ * `ln-search:change` `{ term }`: Top-level search change. In Data-Driven mode, triggers query refetch via `_requestData()`. In SSR mode, filters in-memory records and updates DOM.
118
+ * `ln-filter:change` `{ key, values }`: SSR mode — filters in-memory records by field / data attributes.
119
+ * `ln-sort:change` `{ field, direction }`: In Data-Driven mode, sets `currentSort` and triggers query refetch via `_requestData()`. In SSR mode, sorts in-memory records and updates virtual scroll.
120
+
121
+ ### Emitted Events
122
+
123
+ * `ln-list:request-data` `{ list, sort, filters, search }`: Requests data query from the Coordinator. When windowed, includes `{ offset, limit, queryGen }`.
124
+ * `ln-list:search` `{ list, query }`: Fired in Data-Driven mode when search term updates.
125
+ * `ln-list:ready` `{ total }`: Fired when initial markup parsing completes.
126
+ * `ln-list:rendered` `{ list, total, visible }`: Fired after items have been drawn to DOM.
127
+ * `ln-list:filter` `{ term, matched, total }`: Fired in SSR mode when search/filter narrows visible items.
128
+ * `ln-list:sorted` `{ field, direction, matched, total }`: Fired in SSR mode when items are sorted.
129
+ * `ln-list:item-click` `{ list, id, record }`: Fired when clicking item body (excluding buttons, anchors, inputs).
130
+ * `ln-list:item-action` `{ list, id, action, record }`: Fired when clicking `[data-ln-item-action]`.
131
+ * `ln-list:select` `{ list, selectedIds, count }`: Fired when selection updates.
132
+ * `ln-list:select-all` `{ list, selected: true|false }`: Fired when select-all triggers.
133
+ * `ln-list:empty` `{ term, total }`: Fired when the list becomes empty.
134
+ * `ln-list:clear-filters` `{ list }`: Fired in Data-Driven mode when filters are cleared.
135
+
136
+ ---
137
+
138
+ ## 🔧 Internals
139
+
140
+ Source: `components/ln-list/src/ln-list.js`.
141
+
142
+ ### Spacer element matches container semantics
143
+
144
+ Virtual scroll needs top/bottom spacer elements to preserve scroll height without rendering off-screen rows. If `[data-ln-list-body]` is a `<ul>`/`<ol>`, spacers are `<li class="ln-list__spacer" aria-hidden="true">` to stay HTML5-valid and accessible; any other container gets `<div class="ln-list__spacer" aria-hidden="true">`.
145
+
146
+ ### Slice / Windowed virtualization
147
+
148
+ When windowed virtualization is enabled (`data-ln-list-window`), `ln-list` operates with slice rendering via `createWindowCache`. Only a sliding window of records is kept resident in the view. When the user scrolls, `ln-list` renders placeholder items for records that are not yet loaded and dispatches `ln-list:request-data` with `{ offset, limit }` to fetch the missing slice from the coordinator.
149
+
150
+ ### `_parseChildren()`
151
+
152
+ Parses static children inside `[data-ln-list-body]` into `this._data` at mount (excluding existing spacers), extracting `searchText` and structured values via `readValue()` (`data-ln-value`), and measures the first child's height for `this._itemHeight`.
@@ -1,8 +1,8 @@
1
- @use '../../theme/config/mixins' as *;
2
-
3
- [data-ln-debug] {
4
- // 1. List Integration: missing ID warning for sort/search mapping
5
- [data-ln-list]:not([id]) {
6
- @include dev-dom-error("[data-ln-list] is missing a required 'id' attribute for sort/search mapping.");
7
- }
8
- }
1
+ @use '../../theme/config/mixins' as *;
2
+
3
+ [data-ln-debug] {
4
+ // 1. List Integration: missing ID warning for sort/search mapping
5
+ [data-ln-list]:not([id]) {
6
+ @include dev-dom-error("[data-ln-list] is missing a required 'id' attribute for sort/search mapping.");
7
+ }
8
+ }