@livenetworks/ashlar 1.6.0 → 2.0.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.
Files changed (560) hide show
  1. package/LICENSE +641 -0
  2. package/README.md +202 -86
  3. package/{js → components}/COMPONENTS.md +1116 -1108
  4. package/{js → components}/index.js +81 -58
  5. package/{js → components}/ln-accordion/README.md +7 -6
  6. package/components/ln-accordion/ln-accordion-dev.scss +8 -0
  7. package/components/ln-accordion/ln-accordion.js +1 -0
  8. package/components/ln-accordion/ln-accordion.schema.json +30 -0
  9. package/components/ln-accordion/ln-accordion.scss +8 -0
  10. package/{js → components}/ln-accordion/src/ln-accordion.js +8 -2
  11. package/{js → components}/ln-ajax/README.md +171 -160
  12. package/components/ln-ajax/ln-ajax-dev.scss +8 -0
  13. package/components/ln-ajax/ln-ajax.js +1 -0
  14. package/components/ln-ajax/ln-ajax.schema.json +30 -0
  15. package/{js → components}/ln-ajax/src/ln-ajax.js +65 -30
  16. package/{js → components}/ln-api-connector/README.md +27 -5
  17. package/components/ln-api-connector/ln-api-connector.js +1 -0
  18. package/components/ln-api-connector/ln-api-connector.schema.json +96 -0
  19. package/components/ln-api-connector/src/connector-core.js +97 -0
  20. package/components/ln-api-connector/src/ln-api-connector.js +447 -0
  21. package/{js → components}/ln-api-queue/README.md +12 -9
  22. package/components/ln-api-queue/ln-api-queue.js +1 -0
  23. package/components/ln-api-queue/ln-api-queue.schema.json +34 -0
  24. package/{js → components}/ln-api-queue/src/ln-api-queue.js +33 -14
  25. package/{js → components}/ln-api-queue/src/queue-storage.js +7 -3
  26. package/{js → components}/ln-autoresize/README.md +129 -127
  27. package/components/ln-autoresize/ln-autoresize-dev.scss +8 -0
  28. package/components/ln-autoresize/ln-autoresize.js +1 -0
  29. package/components/ln-autoresize/ln-autoresize.schema.json +22 -0
  30. package/{js → components}/ln-autoresize/src/ln-autoresize.js +8 -1
  31. package/{js → components}/ln-autosave/README.md +127 -124
  32. package/components/ln-autosave/ln-autosave-dev.scss +13 -0
  33. package/components/ln-autosave/ln-autosave.js +1 -0
  34. package/components/ln-autosave/ln-autosave.schema.json +48 -0
  35. package/components/ln-autosave/src/autosave-model.js +34 -0
  36. package/{js → components}/ln-autosave/src/ln-autosave.js +65 -58
  37. package/components/ln-chart/README.md +145 -0
  38. package/components/ln-chart/ln-chart-dev.scss +20 -0
  39. package/components/ln-chart/ln-chart.js +1 -0
  40. package/components/ln-chart/ln-chart.schema.json +146 -0
  41. package/components/ln-chart/ln-chart.scss +8 -0
  42. package/components/ln-chart/src/chart-model.js +154 -0
  43. package/components/ln-chart/src/ln-chart.js +176 -0
  44. package/{js → components}/ln-circular-progress/README.md +15 -14
  45. package/components/ln-circular-progress/ln-circular-progress-dev.scss +8 -0
  46. package/components/ln-circular-progress/ln-circular-progress.js +1 -0
  47. package/components/ln-circular-progress/ln-circular-progress.schema.json +42 -0
  48. package/{js → components}/ln-circular-progress/src/ln-circular-progress.js +32 -50
  49. package/components/ln-confirm/README.md +216 -0
  50. package/components/ln-confirm/ln-confirm-dev.scss +24 -0
  51. package/components/ln-confirm/ln-confirm.js +1 -0
  52. package/components/ln-confirm/ln-confirm.schema.json +66 -0
  53. package/components/ln-confirm/ln-confirm.scss +24 -0
  54. package/{js → components}/ln-confirm/src/ln-confirm.js +180 -167
  55. package/{js → components}/ln-core/README.md +374 -149
  56. package/components/ln-core/attrs.js +273 -0
  57. package/components/ln-core/compare.js +40 -0
  58. package/components/ln-core/crypto.js +265 -0
  59. package/components/ln-core/date.js +50 -0
  60. package/components/ln-core/dom.js +115 -0
  61. package/components/ln-core/events.js +122 -0
  62. package/components/ln-core/form.js +136 -0
  63. package/{js → components}/ln-core/hash.js +149 -92
  64. package/components/ln-core/helpers.js +33 -0
  65. package/components/ln-core/http.js +48 -0
  66. package/components/ln-core/index.js +11 -0
  67. package/components/ln-core/lifecycle.js +403 -0
  68. package/components/ln-core/ln-core.schema.json +109 -0
  69. package/components/ln-core/locale.js +55 -0
  70. package/components/ln-core/matching.js +78 -0
  71. package/components/ln-core/number.js +125 -0
  72. package/components/ln-core/progress.js +30 -0
  73. package/components/ln-core/template.js +206 -0
  74. package/{js → components}/ln-core/window-cache.js +247 -213
  75. package/{js → components}/ln-couchdb-connector/README.md +7 -5
  76. package/components/ln-couchdb-connector/ln-couchdb-connector.js +1 -0
  77. package/components/ln-couchdb-connector/ln-couchdb-connector.schema.json +50 -0
  78. package/{js → components}/ln-couchdb-connector/src/ln-couchdb-connector.js +29 -43
  79. package/{js → components}/ln-data-coordinator/README.md +109 -73
  80. package/components/ln-data-coordinator/ln-data-coordinator-dev.scss +8 -0
  81. package/components/ln-data-coordinator/ln-data-coordinator.js +1 -0
  82. package/components/ln-data-coordinator/ln-data-coordinator.schema.json +196 -0
  83. package/components/ln-data-coordinator/src/data-read-policy.js +41 -0
  84. package/{js → components}/ln-data-coordinator/src/ln-data-coordinator.js +411 -154
  85. package/{js → components}/ln-data-coordinator/src/mutation-receipts.js +0 -5
  86. package/{js → components}/ln-data-store/README.md +42 -17
  87. package/components/ln-data-store/ln-data-store-dev.scss +13 -0
  88. package/components/ln-data-store/ln-data-store.js +1 -0
  89. package/components/ln-data-store/ln-data-store.schema.json +84 -0
  90. package/components/ln-data-store/src/data-store-model.js +155 -0
  91. package/{js → components}/ln-data-store/src/ln-data-store.js +407 -105
  92. package/components/ln-data-store/src/window-index.js +119 -0
  93. package/{js → components}/ln-date/README.md +17 -7
  94. package/{js → components}/ln-date/ln-date-dev.scss +14 -14
  95. package/components/ln-date/ln-date.js +1 -0
  96. package/components/ln-date/ln-date.schema.json +92 -0
  97. package/components/ln-date/src/date-model.js +186 -0
  98. package/components/ln-date/src/ln-date.js +486 -0
  99. package/components/ln-debug/README.md +132 -0
  100. package/components/ln-debug/ln-debug.js +1 -0
  101. package/components/ln-debug/ln-debug.schema.json +28 -0
  102. package/components/ln-debug/src/console-sink.js +19 -0
  103. package/components/ln-debug/src/debug-verifier.js +331 -0
  104. package/components/ln-debug/src/gate.js +95 -0
  105. package/components/ln-debug/src/generated-attributes.js +299 -0
  106. package/components/ln-debug/src/ln-debug.js +60 -0
  107. package/{js → components}/ln-dropdown/README.md +150 -140
  108. package/components/ln-dropdown/ln-dropdown-dev.scss +13 -0
  109. package/components/ln-dropdown/ln-dropdown.js +1 -0
  110. package/components/ln-dropdown/ln-dropdown.schema.json +90 -0
  111. package/components/ln-dropdown/ln-dropdown.scss +18 -0
  112. package/{js → components}/ln-dropdown/src/ln-dropdown.js +114 -11
  113. package/{js → components}/ln-editor/README.md +11 -9
  114. package/components/ln-editor/ln-editor-dev.scss +18 -0
  115. package/components/ln-editor/ln-editor.js +1 -0
  116. package/components/ln-editor/ln-editor.schema.json +58 -0
  117. package/components/ln-editor/ln-editor.scss +13 -0
  118. package/{js → components}/ln-editor/src/ln-editor.js +59 -11
  119. package/{js → components}/ln-external-links/README.md +10 -8
  120. package/components/ln-external-links/ln-external-links.js +1 -0
  121. package/components/ln-external-links/ln-external-links.schema.json +18 -0
  122. package/{js → components}/ln-external-links/src/ln-external-links.js +13 -11
  123. package/{js → components}/ln-fill/README.md +6 -8
  124. package/components/ln-fill/ln-fill.js +1 -0
  125. package/components/ln-fill/ln-fill.schema.json +23 -0
  126. package/{js → components}/ln-fill/src/ln-fill.js +7 -1
  127. package/components/ln-filter/README.md +131 -0
  128. package/components/ln-filter/ln-filter-dev.scss +13 -0
  129. package/components/ln-filter/ln-filter.js +1 -0
  130. package/components/ln-filter/ln-filter.schema.json +153 -0
  131. package/components/ln-filter/src/filter-model.js +185 -0
  132. package/components/ln-filter/src/ln-filter.js +435 -0
  133. package/{js → components}/ln-form/README.md +260 -264
  134. package/components/ln-form/ln-form-dev.scss +8 -0
  135. package/components/ln-form/ln-form.js +1 -0
  136. package/components/ln-form/ln-form.schema.json +45 -0
  137. package/{js → components}/ln-form/src/ln-form.js +107 -99
  138. package/{js → components}/ln-http/README.md +11 -6
  139. package/components/ln-http/ln-http.js +1 -0
  140. package/components/ln-http/ln-http.schema.json +6 -0
  141. package/components/ln-http/src/http-core.js +51 -0
  142. package/{js → components}/ln-http/src/ln-http.js +28 -33
  143. package/{js → components}/ln-icon/README.md +16 -9
  144. package/components/ln-icon/ln-icon.schema.json +6 -0
  145. package/components/ln-include/README.md +75 -0
  146. package/components/ln-include/ln-include-dev.scss +13 -0
  147. package/components/ln-include/ln-include.js +1 -0
  148. package/components/ln-include/ln-include.schema.json +23 -0
  149. package/components/ln-include/src/ln-include.js +111 -0
  150. package/components/ln-key/README.md +130 -0
  151. package/components/ln-key/ln-key-dev.scss +18 -0
  152. package/components/ln-key/ln-key.js +1 -0
  153. package/components/ln-key/ln-key.schema.json +56 -0
  154. package/components/ln-key/src/key-model.js +146 -0
  155. package/components/ln-key/src/ln-key.js +201 -0
  156. package/{js → components}/ln-link/README.md +7 -9
  157. package/components/ln-link/ln-link-dev.scss +8 -0
  158. package/components/ln-link/ln-link.js +1 -0
  159. package/components/ln-link/ln-link.schema.json +22 -0
  160. package/{js → components}/ln-link/src/ln-link.js +16 -11
  161. package/components/ln-list/README.md +152 -0
  162. package/components/ln-list/ln-list-dev.scss +8 -0
  163. package/components/ln-list/ln-list.js +1 -0
  164. package/components/ln-list/ln-list.schema.json +166 -0
  165. package/components/ln-list/ln-list.scss +25 -0
  166. package/{js → components}/ln-list/src/ln-list.js +1301 -1216
  167. package/{js → components}/ln-modal/README.md +13 -10
  168. package/components/ln-modal/ln-modal-dev.scss +18 -0
  169. package/components/ln-modal/ln-modal.js +1 -0
  170. package/components/ln-modal/ln-modal.schema.json +54 -0
  171. package/components/ln-modal/ln-modal.scss +51 -0
  172. package/{js → components}/ln-modal/src/ln-modal.js +164 -137
  173. package/{js → components}/ln-nav/README.md +11 -11
  174. package/components/ln-nav/ln-nav.js +1 -0
  175. package/components/ln-nav/ln-nav.schema.json +25 -0
  176. package/{js → components}/ln-nav/src/ln-nav.js +25 -14
  177. package/components/ln-number/README.md +205 -0
  178. package/{js → components}/ln-number/ln-number-dev.scss +13 -13
  179. package/components/ln-number/ln-number.js +1 -0
  180. package/components/ln-number/ln-number.schema.json +63 -0
  181. package/components/ln-number/src/ln-number.js +400 -0
  182. package/components/ln-number/src/number-model.js +31 -0
  183. package/components/ln-obfuscator/README.md +60 -0
  184. package/components/ln-obfuscator/ln-obfuscator.js +1 -0
  185. package/components/ln-obfuscator/ln-obfuscator.schema.json +49 -0
  186. package/components/ln-obfuscator/src/ln-obfuscator.js +159 -0
  187. package/components/ln-obfuscator/src/obfuscator-model.js +250 -0
  188. package/{js → components}/ln-options/README.md +3 -1
  189. package/components/ln-options/ln-options-dev.scss +13 -0
  190. package/components/ln-options/ln-options.js +1 -0
  191. package/components/ln-options/ln-options.schema.json +41 -0
  192. package/{js → components}/ln-options/src/ln-options.js +13 -5
  193. package/components/ln-persist/README.md +151 -0
  194. package/components/ln-persist/ln-persist.js +1 -0
  195. package/components/ln-persist/ln-persist.schema.json +28 -0
  196. package/components/ln-persist/src/ln-persist.js +83 -0
  197. package/components/ln-picklist/README.md +230 -0
  198. package/components/ln-picklist/ln-picklist-dev.scss +22 -0
  199. package/components/ln-picklist/ln-picklist.js +1 -0
  200. package/components/ln-picklist/ln-picklist.schema.json +49 -0
  201. package/components/ln-picklist/src/ln-picklist.js +228 -0
  202. package/{js → components}/ln-popover/README.md +164 -162
  203. package/components/ln-popover/ln-popover-dev.scss +13 -0
  204. package/components/ln-popover/ln-popover.js +1 -0
  205. package/components/ln-popover/ln-popover.schema.json +82 -0
  206. package/components/ln-popover/ln-popover.scss +18 -0
  207. package/{js → components}/ln-popover/src/ln-popover.js +42 -36
  208. package/{js → components}/ln-progress/README.md +410 -413
  209. package/components/ln-progress/ln-progress-dev.scss +8 -0
  210. package/components/ln-progress/ln-progress.js +1 -0
  211. package/components/ln-progress/ln-progress.schema.json +40 -0
  212. package/components/ln-progress/src/ln-progress.js +91 -0
  213. package/components/ln-progress/src/progress-model.js +20 -0
  214. package/{js → components}/ln-router/README.md +443 -432
  215. package/components/ln-router/ln-router-dev.scss +13 -0
  216. package/components/ln-router/ln-router.js +1 -0
  217. package/components/ln-router/ln-router.schema.json +68 -0
  218. package/{js → components}/ln-router/src/ln-router.js +585 -539
  219. package/components/ln-router/src/router-model.js +50 -0
  220. package/components/ln-scroll/README.md +45 -0
  221. package/components/ln-scroll/ln-scroll.js +1 -0
  222. package/components/ln-scroll/ln-scroll.schema.json +85 -0
  223. package/components/ln-scroll/src/ln-scroll.js +150 -0
  224. package/components/ln-search/README.md +188 -0
  225. package/components/ln-search/ln-search-dev.scss +13 -0
  226. package/components/ln-search/ln-search.js +1 -0
  227. package/components/ln-search/ln-search.schema.json +103 -0
  228. package/components/ln-search/src/ln-search.js +330 -0
  229. package/{js → components}/ln-slug/README.md +6 -3
  230. package/components/ln-slug/ln-slug-dev.scss +18 -0
  231. package/components/ln-slug/ln-slug.js +1 -0
  232. package/components/ln-slug/ln-slug.schema.json +23 -0
  233. package/{js → components}/ln-slug/src/ln-slug.js +20 -13
  234. package/components/ln-slug/src/slug-model.js +21 -0
  235. package/{js → components}/ln-sort/README.md +178 -170
  236. package/{js → components}/ln-sort/ln-sort-dev.scss +8 -8
  237. package/components/ln-sort/ln-sort.js +1 -0
  238. package/components/ln-sort/ln-sort.schema.json +104 -0
  239. package/components/ln-sort/src/ln-sort.js +321 -0
  240. package/components/ln-sort/src/sort-model.js +117 -0
  241. package/{js → components}/ln-sortable/README.md +7 -11
  242. package/components/ln-sortable/ln-sortable-dev.scss +13 -0
  243. package/components/ln-sortable/ln-sortable.js +1 -0
  244. package/components/ln-sortable/ln-sortable.schema.json +36 -0
  245. package/{js → components}/ln-sortable/src/ln-sortable.js +8 -13
  246. package/{js → components}/ln-stat/README.md +3 -1
  247. package/components/ln-stat/ln-stat-dev.scss +8 -0
  248. package/components/ln-stat/ln-stat.js +1 -0
  249. package/components/ln-stat/ln-stat.schema.json +32 -0
  250. package/{js → components}/ln-stat/src/ln-stat.js +14 -18
  251. package/components/ln-stat/src/stat-model.js +28 -0
  252. package/{js → components}/ln-table/README.md +37 -24
  253. package/{js → components}/ln-table/ln-table-dev.scss +17 -17
  254. package/components/ln-table/ln-table.js +1 -0
  255. package/components/ln-table/ln-table.schema.json +211 -0
  256. package/components/ln-table/ln-table.scss +15 -0
  257. package/{js → components}/ln-table/src/ln-table.js +1365 -1493
  258. package/components/ln-table/src/table-model.js +98 -0
  259. package/components/ln-table-coordinator/README.md +61 -0
  260. package/components/ln-table-coordinator/ln-table-coordinator.js +1 -0
  261. package/components/ln-table-coordinator/ln-table-coordinator.schema.json +93 -0
  262. package/components/ln-table-coordinator/src/ln-table-coordinator.js +193 -0
  263. package/{js → components}/ln-tabs/README.md +32 -14
  264. package/components/ln-tabs/ln-tabs-dev.scss +24 -0
  265. package/components/ln-tabs/ln-tabs.js +1 -0
  266. package/components/ln-tabs/ln-tabs.schema.json +75 -0
  267. package/components/ln-tabs/ln-tabs.scss +8 -0
  268. package/components/ln-tabs/src/ln-tabs.js +207 -0
  269. package/components/ln-tabs/src/tabs-model.js +82 -0
  270. package/{js → components}/ln-time/README.md +96 -95
  271. package/components/ln-time/ln-time-dev.scss +13 -0
  272. package/components/ln-time/ln-time.js +1 -0
  273. package/components/ln-time/ln-time.schema.json +38 -0
  274. package/{js → components}/ln-time/src/ln-time.js +206 -223
  275. package/components/ln-time/src/time-model.js +64 -0
  276. package/{js → components}/ln-toast/README.md +23 -5
  277. package/components/ln-toast/ln-toast-dev.scss +8 -0
  278. package/components/ln-toast/ln-toast.js +1 -0
  279. package/components/ln-toast/ln-toast.schema.json +65 -0
  280. package/components/ln-toast/ln-toast.scss +59 -0
  281. package/{js → components}/ln-toast/src/ln-toast.js +233 -232
  282. package/{js → components}/ln-toggle/README.md +198 -196
  283. package/{js → components}/ln-toggle/ln-toggle-dev.scss +13 -13
  284. package/components/ln-toggle/ln-toggle.js +1 -0
  285. package/components/ln-toggle/ln-toggle.schema.json +52 -0
  286. package/components/ln-toggle/ln-toggle.scss +37 -0
  287. package/{js → components}/ln-toggle/src/ln-toggle.js +61 -46
  288. package/{js → components}/ln-tooltip/README.md +6 -6
  289. package/{js → components}/ln-tooltip/ln-tooltip-dev.scss +9 -9
  290. package/components/ln-tooltip/ln-tooltip.js +1 -0
  291. package/components/ln-tooltip/ln-tooltip.schema.json +86 -0
  292. package/components/ln-tooltip/ln-tooltip.scss +9 -0
  293. package/{js → components}/ln-tooltip/src/ln-tooltip.js +14 -3
  294. package/{js → components}/ln-translations/README.md +3 -1
  295. package/components/ln-translations/ln-translations-dev.scss +13 -0
  296. package/components/ln-translations/ln-translations.js +1 -0
  297. package/components/ln-translations/ln-translations.schema.json +120 -0
  298. package/{js → components}/ln-translations/src/ln-translations.js +25 -10
  299. package/components/ln-ui-coordinator/README.md +101 -0
  300. package/components/ln-ui-coordinator/ln-ui-coordinator-dev.scss +8 -0
  301. package/components/ln-ui-coordinator/ln-ui-coordinator.js +1 -0
  302. package/components/ln-ui-coordinator/ln-ui-coordinator.schema.json +60 -0
  303. package/{js/ln-modal-coordinator/src/ln-modal-coordinator.js → components/ln-ui-coordinator/src/ln-ui-coordinator.js} +403 -345
  304. package/components/ln-upload/README.md +133 -0
  305. package/components/ln-upload/ln-upload-dev.scss +18 -0
  306. package/components/ln-upload/ln-upload.js +1 -0
  307. package/components/ln-upload/ln-upload.schema.json +193 -0
  308. package/components/ln-upload/ln-upload.scss +20 -0
  309. package/components/ln-upload/src/ln-upload.js +652 -0
  310. package/components/ln-upload/src/upload-model.js +78 -0
  311. package/{js → components}/ln-validate/README.md +182 -180
  312. package/{js → components}/ln-validate/ln-validate-dev.scss +15 -15
  313. package/components/ln-validate/ln-validate.js +1 -0
  314. package/components/ln-validate/ln-validate.schema.json +50 -0
  315. package/components/ln-validate/ln-validate.scss +7 -0
  316. package/{js → components}/ln-validate/src/ln-validate.js +23 -45
  317. package/components/ln-validate/src/validate-model.js +64 -0
  318. package/components/ln-websocket-connector/README.md +166 -0
  319. package/components/ln-websocket-connector/ln-websocket-connector.js +1 -0
  320. package/components/ln-websocket-connector/ln-websocket-connector.schema.json +29 -0
  321. package/components/ln-websocket-connector/src/ln-websocket-connector.js +279 -0
  322. package/ln-ashlar.html-data.json +1796 -0
  323. package/package.json +84 -61
  324. package/{scss → theme}/base/_global.scss +1 -2
  325. package/{scss → theme}/base/_reset.scss +1 -1
  326. package/{scss → theme}/base/_typography.scss +2 -0
  327. package/theme/brand.css +73 -0
  328. package/{scss → theme}/components/_app-shell.scss +8 -0
  329. package/theme/components/_button.scss +24 -0
  330. package/theme/components/_chart.scss +5 -0
  331. package/theme/components/_confirm.scss +6 -0
  332. package/{scss → theme}/components/_date.scss +30 -22
  333. package/{scss → theme}/components/_dropdown.scss +6 -1
  334. package/theme/components/_form.scss +140 -0
  335. package/{scss → theme}/components/_layout.scss +6 -0
  336. package/{scss → theme}/components/_ln-table.scss +1 -6
  337. package/theme/components/_picklist.scss +3 -0
  338. package/{scss → theme}/components/_sort.scss +10 -10
  339. package/theme/components/_status-badge.scss +6 -0
  340. package/{scss → theme}/components/_table.scss +16 -0
  341. package/{scss → theme}/components/_tabs.scss +0 -4
  342. package/theme/components/_toast.scss +48 -0
  343. package/{scss → theme}/components/_toggle.scss +1 -1
  344. package/theme/components/_upload.scss +45 -0
  345. package/{scss → theme}/config/_breakpoints.scss +1 -1
  346. package/theme/config/_contrast.scss +128 -0
  347. package/{scss → theme}/config/_density.scss +191 -205
  348. package/theme/config/_palette.scss +274 -0
  349. package/theme/config/_theme.scss +293 -0
  350. package/{scss → theme}/config/_tokens.scss +285 -441
  351. package/{scss → theme}/config/mixins/_accordion.scss +1 -1
  352. package/{scss → theme}/config/mixins/_alert.scss +1 -0
  353. package/{scss → theme}/config/mixins/_app-shell.scss +4 -2
  354. package/{scss → theme}/config/mixins/_borders.scss +2 -0
  355. package/theme/config/mixins/_btn.scss +175 -0
  356. package/{scss → theme}/config/mixins/_card.scss +55 -46
  357. package/theme/config/mixins/_chart.scss +82 -0
  358. package/{scss → theme}/config/mixins/_collapsible.scss +2 -1
  359. package/{scss → theme}/config/mixins/_colors.scss +8 -14
  360. package/{scss → theme}/config/mixins/_diagnostics.scss +48 -48
  361. package/theme/config/mixins/_dropdown.scss +169 -0
  362. package/{scss → theme}/config/mixins/_editor.scss +0 -7
  363. package/{scss → theme}/config/mixins/_filter.scss +47 -47
  364. package/{scss → theme}/config/mixins/_footer.scss +1 -1
  365. package/{scss → theme}/config/mixins/_form.scss +49 -18
  366. package/{scss → theme}/config/mixins/_index.scss +62 -61
  367. package/{scss → theme}/config/mixins/_layout.scss +6 -2
  368. package/{scss → theme}/config/mixins/_ln-table.scss +31 -10
  369. package/{scss → theme}/config/mixins/_loader.scss +1 -1
  370. package/{scss → theme}/config/mixins/_modal.scss +145 -149
  371. package/{scss → theme}/config/mixins/_motion.scss +13 -0
  372. package/{scss → theme}/config/mixins/_nav.scss +7 -7
  373. package/theme/config/mixins/_picklist.scss +66 -0
  374. package/theme/config/mixins/_popover.scss +96 -0
  375. package/{scss → theme}/config/mixins/_sidebar.scss +7 -4
  376. package/{scss → theme}/config/mixins/_sort.scss +43 -42
  377. package/{scss → theme}/config/mixins/_status-badge.scss +15 -2
  378. package/{scss → theme}/config/mixins/_table.scss +25 -14
  379. package/{scss → theme}/config/mixins/_tabs.scss +1 -1
  380. package/{scss → theme}/config/mixins/_toast.scss +174 -179
  381. package/{scss → theme}/config/mixins/_tooltip.scss +2 -2
  382. package/{scss → theme}/config/mixins/_typography.scss +16 -5
  383. package/{scss → theme}/config/mixins/_upload.scss +8 -6
  384. package/theme/ln-ashlar-core.scss +24 -0
  385. package/theme/ln-ashlar-dev.scss +66 -0
  386. package/theme/ln-ashlar-landing.scss +56 -0
  387. package/{scss/ln-ashlar.scss → theme/ln-ashlar-theme.scss} +63 -69
  388. package/theme/ln-ashlar.scss +8 -0
  389. package/theme/presentation/_bento.scss +151 -0
  390. package/theme/presentation/_cta.scss +111 -0
  391. package/theme/presentation/_effects.scss +216 -0
  392. package/theme/presentation/_features.scss +108 -0
  393. package/theme/presentation/_footer.scss +129 -0
  394. package/theme/presentation/_hero.scss +158 -0
  395. package/theme/presentation/_layout.scss +170 -0
  396. package/theme/presentation/_navbar.scss +140 -0
  397. package/theme/presentation/_pricing.scss +262 -0
  398. package/theme/presentation/_stats.scss +87 -0
  399. package/theme/presentation/_testimonials.scss +124 -0
  400. package/theme/presentation/_tokens.scss +39 -0
  401. package/theme/presentation/_typography.scss +163 -0
  402. package/{scss → theme}/utilities/_animations.scss +38 -0
  403. package/{scss → theme}/utilities/_utilities.scss +6 -0
  404. package/web-types.json +2312 -0
  405. package/js/ln-accordion/ln-accordion.js +0 -1
  406. package/js/ln-ajax/ln-ajax.js +0 -1
  407. package/js/ln-api-connector/ln-api-connector.js +0 -1
  408. package/js/ln-api-connector/src/ln-api-connector.js +0 -368
  409. package/js/ln-api-queue/ln-api-queue.js +0 -1
  410. package/js/ln-autoresize/ln-autoresize.js +0 -1
  411. package/js/ln-autosave/ln-autosave.js +0 -1
  412. package/js/ln-circular-progress/ln-circular-progress.js +0 -1
  413. package/js/ln-confirm/README.md +0 -162
  414. package/js/ln-confirm/_ln-confirm.scss +0 -24
  415. package/js/ln-confirm/ln-confirm.js +0 -1
  416. package/js/ln-core/crypto.js +0 -83
  417. package/js/ln-core/helpers.js +0 -788
  418. package/js/ln-core/index.js +0 -7
  419. package/js/ln-core/persist.js +0 -97
  420. package/js/ln-couchdb-connector/ln-couchdb-connector.js +0 -1
  421. package/js/ln-data-coordinator/ln-data-coordinator.js +0 -1
  422. package/js/ln-data-coordinator/src/data-read-policy.js +0 -18
  423. package/js/ln-data-store/ln-data-store.js +0 -1
  424. package/js/ln-date/ln-date.js +0 -1
  425. package/js/ln-date/src/ln-date.js +0 -603
  426. package/js/ln-debug/README.md +0 -58
  427. package/js/ln-debug/ln-debug.js +0 -1
  428. package/js/ln-debug/src/ln-debug.js +0 -19
  429. package/js/ln-dropdown/ln-dropdown.js +0 -1
  430. package/js/ln-dropdown/ln-dropdown.scss +0 -15
  431. package/js/ln-editor/ln-editor.js +0 -1
  432. package/js/ln-editor/ln-editor.scss +0 -43
  433. package/js/ln-external-links/ln-external-links.js +0 -1
  434. package/js/ln-fill/ln-fill.js +0 -1
  435. package/js/ln-filter/README.md +0 -189
  436. package/js/ln-filter/ln-filter-dev.scss +0 -8
  437. package/js/ln-filter/ln-filter.js +0 -1
  438. package/js/ln-filter/src/ln-filter.js +0 -419
  439. package/js/ln-form/ln-form.js +0 -1
  440. package/js/ln-http/ln-http.js +0 -1
  441. package/js/ln-link/ln-link.js +0 -1
  442. package/js/ln-list/README.md +0 -129
  443. package/js/ln-list/ln-list.js +0 -1
  444. package/js/ln-list/ln-list.scss +0 -28
  445. package/js/ln-modal/ln-modal-dev.scss +0 -13
  446. package/js/ln-modal/ln-modal.js +0 -1
  447. package/js/ln-modal/ln-modal.scss +0 -35
  448. package/js/ln-modal-coordinator/README.md +0 -99
  449. package/js/ln-modal-coordinator/ln-modal-coordinator-dev.scss +0 -8
  450. package/js/ln-modal-coordinator/ln-modal-coordinator.js +0 -1
  451. package/js/ln-nav/ln-nav.js +0 -1
  452. package/js/ln-number/README.md +0 -149
  453. package/js/ln-number/ln-number.js +0 -1
  454. package/js/ln-number/src/ln-number.js +0 -443
  455. package/js/ln-options/ln-options.js +0 -1
  456. package/js/ln-popover/ln-popover.js +0 -1
  457. package/js/ln-progress/ln-progress.js +0 -1
  458. package/js/ln-progress/src/ln-progress.js +0 -98
  459. package/js/ln-router/ln-router.js +0 -1
  460. package/js/ln-search/README.md +0 -158
  461. package/js/ln-search/ln-search-dev.scss +0 -8
  462. package/js/ln-search/ln-search.js +0 -1
  463. package/js/ln-search/src/ln-search.js +0 -117
  464. package/js/ln-slug/ln-slug.js +0 -1
  465. package/js/ln-sort/ln-sort.js +0 -1
  466. package/js/ln-sort/src/ln-sort.js +0 -178
  467. package/js/ln-sortable/ln-sortable.js +0 -1
  468. package/js/ln-stat/ln-stat.js +0 -1
  469. package/js/ln-table/ln-table.js +0 -1
  470. package/js/ln-table/ln-table.scss +0 -11
  471. package/js/ln-table-coordinator/README.md +0 -73
  472. package/js/ln-table-coordinator/ln-table-coordinator.js +0 -1
  473. package/js/ln-table-coordinator/src/ln-table-coordinator.js +0 -160
  474. package/js/ln-tabs/ln-tabs-dev.scss +0 -18
  475. package/js/ln-tabs/ln-tabs.js +0 -1
  476. package/js/ln-tabs/src/ln-tabs.js +0 -188
  477. package/js/ln-time/ln-time.js +0 -1
  478. package/js/ln-toast/ln-toast.js +0 -1
  479. package/js/ln-toggle/ln-toggle.js +0 -1
  480. package/js/ln-tooltip/ln-tooltip.js +0 -1
  481. package/js/ln-tooltip/ln-tooltip.scss +0 -9
  482. package/js/ln-translations/ln-translations.js +0 -1
  483. package/js/ln-upload/README.md +0 -255
  484. package/js/ln-upload/ln-upload.js +0 -1
  485. package/js/ln-upload/ln-upload.scss +0 -20
  486. package/js/ln-upload/src/ln-upload.js +0 -423
  487. package/js/ln-validate/ln-validate.js +0 -1
  488. package/scss/components/_button.scss +0 -20
  489. package/scss/components/_confirm.scss +0 -5
  490. package/scss/components/_form.scss +0 -107
  491. package/scss/components/_status-badge.scss +0 -4
  492. package/scss/components/_toast.scss +0 -68
  493. package/scss/components/_upload.scss +0 -51
  494. package/scss/config/_theme.scss +0 -216
  495. package/scss/config/mixins/_btn.scss +0 -179
  496. package/scss/config/mixins/_confirm.scss +0 -31
  497. package/scss/config/mixins/_dropdown.scss +0 -141
  498. package/scss/config/mixins/_popover.scss +0 -64
  499. package/scss/ln-ashlar-dev.scss +0 -39
  500. /package/{js → components}/ln-core/positioning.js +0 -0
  501. /package/{js → components}/ln-core/reactive.js +0 -0
  502. /package/{js → components}/ln-filter/ln-filter.scss +0 -0
  503. /package/{js → components}/ln-icon/ln-icon.js +0 -0
  504. /package/{js → components}/ln-icon/src/ln-icon.js +0 -0
  505. /package/{js → components}/ln-search/ln-search.scss +0 -0
  506. /package/{js → components}/ln-toast/template.html +0 -0
  507. /package/{scss → theme}/components/_accordion.scss +0 -0
  508. /package/{scss → theme}/components/_ajax.scss +0 -0
  509. /package/{scss → theme}/components/_alert.scss +0 -0
  510. /package/{scss → theme}/components/_avatar.scss +0 -0
  511. /package/{scss → theme}/components/_breadcrumbs.scss +0 -0
  512. /package/{scss → theme}/components/_card.scss +0 -0
  513. /package/{scss → theme}/components/_chip.scss +0 -0
  514. /package/{scss → theme}/components/_circular-progress.scss +0 -0
  515. /package/{scss → theme}/components/_editor.scss +0 -0
  516. /package/{scss → theme}/components/_empty-state.scss +0 -0
  517. /package/{scss → theme}/components/_filter.scss +0 -0
  518. /package/{scss → theme}/components/_link.scss +0 -0
  519. /package/{scss → theme}/components/_loader.scss +0 -0
  520. /package/{scss → theme}/components/_modal.scss +0 -0
  521. /package/{scss → theme}/components/_nav.scss +0 -0
  522. /package/{scss → theme}/components/_page-header.scss +0 -0
  523. /package/{scss → theme}/components/_popover.scss +0 -0
  524. /package/{scss → theme}/components/_progress.scss +0 -0
  525. /package/{scss → theme}/components/_prose.scss +0 -0
  526. /package/{scss → theme}/components/_scrollbar.scss +0 -0
  527. /package/{scss → theme}/components/_sections.scss +0 -0
  528. /package/{scss → theme}/components/_sidebar.scss +0 -0
  529. /package/{scss → theme}/components/_stat-card.scss +0 -0
  530. /package/{scss → theme}/components/_stepper.scss +0 -0
  531. /package/{scss → theme}/components/_timeline.scss +0 -0
  532. /package/{scss → theme}/components/_tooltip.scss +0 -0
  533. /package/{scss → theme}/components/_translations.scss +0 -0
  534. /package/{scss → theme}/config/_icons.scss +0 -0
  535. /package/{scss → theme}/config/_mixins.scss +0 -0
  536. /package/{scss → theme}/config/mixins/_ajax.scss +0 -0
  537. /package/{scss → theme}/config/mixins/_avatar.scss +0 -0
  538. /package/{scss → theme}/config/mixins/_breadcrumbs.scss +0 -0
  539. /package/{scss → theme}/config/mixins/_breakpoints.scss +0 -0
  540. /package/{scss → theme}/config/mixins/_chip.scss +0 -0
  541. /package/{scss → theme}/config/mixins/_circular-progress.scss +0 -0
  542. /package/{scss → theme}/config/mixins/_display.scss +0 -0
  543. /package/{scss → theme}/config/mixins/_empty-state.scss +0 -0
  544. /package/{scss → theme}/config/mixins/_focus.scss +0 -0
  545. /package/{scss → theme}/config/mixins/_interaction.scss +0 -0
  546. /package/{scss → theme}/config/mixins/_kbd.scss +0 -0
  547. /package/{scss → theme}/config/mixins/_link.scss +0 -0
  548. /package/{scss → theme}/config/mixins/_page-header.scss +0 -0
  549. /package/{scss → theme}/config/mixins/_position.scss +0 -0
  550. /package/{scss → theme}/config/mixins/_progress.scss +0 -0
  551. /package/{scss → theme}/config/mixins/_prose.scss +0 -0
  552. /package/{scss → theme}/config/mixins/_shadows.scss +0 -0
  553. /package/{scss → theme}/config/mixins/_sizing.scss +0 -0
  554. /package/{scss → theme}/config/mixins/_spacing.scss +0 -0
  555. /package/{scss → theme}/config/mixins/_stat-card.scss +0 -0
  556. /package/{scss → theme}/config/mixins/_stepper.scss +0 -0
  557. /package/{scss → theme}/config/mixins/_timeline.scss +0 -0
  558. /package/{scss → theme}/config/mixins/_transitions.scss +0 -0
  559. /package/{scss → theme}/config/mixins/_translations.scss +0 -0
  560. /package/{scss → theme}/tabler-icons.txt +0 -0
@@ -0,0 +1 @@
1
+ (function(){"use strict";function S(){return typeof window>"u"?!1:window.lnDebug===!0||window.lnCore&&window.lnCore._debugSink?!0:typeof document<"u"&&document.body?document.body.hasAttribute("data-ln-debug")||document.body.querySelector("[data-ln-debug]")!==null:!1}function g(e){if(typeof window>"u")return!1;if(window.lnDebug===!0)return!0;if(window.lnCore&&window.lnCore._debugIsContained)return e?window.lnCore._debugIsContained(e):window.lnCore._debugSink!==null;if(e&&e.closest){const t=e.closest("[data-ln-debug]");return!(!t||typeof document<"u"&&t===document.documentElement)}return typeof document<"u"&&document.body?document.body.hasAttribute("data-ln-debug"):!1}if(typeof window<"u"&&(window.lnCore=window.lnCore||{},!window.lnCore._warnBound)){window.lnCore._warnBound=!0;const e=console.warn;console.warn=function(...t){if(typeof t[0]=="string"&&(t[0].startsWith("[ln-")||t[0].startsWith("[lnCore"))){let l=null;for(let a=1;a<t.length;a++)if(t[a]&&t[a].nodeType===1){l=t[a];break}if(!g(l))return}e.apply(console,t)}}function b(e,t,n){const l=n||{};window.lnCore._debugSink&&window.lnCore._debugSink("event",t,e,l),e.dispatchEvent(new CustomEvent(t,{bubbles:!0,detail:l}))}function w(e,t){if(!document.body){document.addEventListener("DOMContentLoaded",function(){w(e,t)}),console.warn("["+t+'] Script loaded before <body> — add "defer" to your <script> tag');return}e()}const C={};function x(e,t){C[e]=t}function L(e){return C[e]||{ingress:t=>t,egress:t=>t}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerDataMapper=x,window.lnCore.getDataMapper=L);function $(){typeof window>"u"||(window.lnCore=window.lnCore||{},!window.lnCore._localeObserverBound&&(window.lnCore._localeObserverBound=!0,w(function(){new MutationObserver(function(){b(document,"ln-core:locale-change",{})}).observe(document.documentElement,{attributes:!0,attributeFilter:["lang"],subtree:!0})},"ln-core")))}const m={};function O(e,t){if(!e||typeof t!="object")return;const n=e.toLowerCase().split("-")[0];m[n]=t}function D(e){if(!e)return null;const t=e.toLowerCase().split("-")[0];return m[t]||null}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerLocaleFallback=O,window.lnCore.getLocaleFallback=D,window.lnCore.ensureLocaleObserver=$);const h={};function E(e,t){h[e]||(h[e]=document.querySelector('[data-ln-template="'+e+'"]'));const n=h[e];return n?n.content.cloneNode(!0):(console.warn("["+(t||"ln-core")+'] Template "'+e+'" not found'),null)}function y(e,t){if(!e||!t)return e;const n=e.querySelectorAll("[data-ln-field]");for(let o=0;o<n.length;o++){const i=n[o],r=i.getAttribute("data-ln-field");t[r]!=null&&(i.textContent=t[r])}const l=e.querySelectorAll("[data-ln-attr]");for(let o=0;o<l.length;o++){const i=l[o],r=i.getAttribute("data-ln-attr").split(",");for(let c=0;c<r.length;c++){const u=r[c].trim().split(":");if(u.length!==2)continue;const d=u[0].trim(),f=u[1].trim();t[f]!=null&&i.setAttribute(d,t[f])}}const a=e.querySelectorAll("[data-ln-show]");for(let o=0;o<a.length;o++){const i=a[o],r=i.getAttribute("data-ln-show");r in t&&i.classList.toggle("hidden",!t[r])}const s=e.querySelectorAll("[data-ln-class]");for(let o=0;o<s.length;o++){const i=s[o],r=i.getAttribute("data-ln-class").split(",");for(let c=0;c<r.length;c++){const u=r[c].trim().split(":");if(u.length!==2)continue;const d=u[0].trim(),f=u[1].trim();f in t&&i.classList.toggle(d,!!t[f])}}return e}function T(e,t){e.matches&&e.matches("[data-ln-form], [data-ln-fillable]")&&(window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",e,t??null),e.dispatchEvent(new CustomEvent("ln-fill",{detail:t??null,bubbles:!0})));const n=e.querySelectorAll("[data-ln-form], [data-ln-fillable]");for(let l=0;l<n.length;l++)window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",n[l],t??null),n[l].dispatchEvent(new CustomEvent("ln-fill",{detail:t??null,bubbles:!0}));return e}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._fillBound||(window.lnCore._fillBound=!0,document.addEventListener("ln-fill",function(e){if(!(!e.target.matches||!e.target.matches("[data-ln-fillable]")))if(e.detail)y(e.target,e.detail);else{const t=e.target.querySelectorAll("[data-ln-field]");for(let n=0;n<t.length;n++)t[n].textContent=""}})));function A(e,t){if(!e||!t)return e;const n=document.createTreeWalker(e,NodeFilter.SHOW_TEXT);for(;n.nextNode();){const s=n.currentNode;s.textContent.indexOf("{{")!==-1&&(s.textContent=s.textContent.replace(/\{\{\s*(\w+)\s*\}\}/g,function(o,i){return t[i]!==void 0?t[i]:""}))}const l=function(s,o){return t[o]!==void 0?t[o]:""},a=Array.from(e.querySelectorAll("*"));e.nodeType===1&&a.push(e);for(let s=0;s<a.length;s++){const o=a[s],i=o.attributes;for(let r=0;r<i.length;r++){const c=i[r];c.value.indexOf("{{")!==-1&&o.setAttribute(c.name,c.value.replace(/\{\{\s*(\w+)\s*\}\}/g,l))}}return e}function F(e,t,n,l,a,s){const o={};for(let r=0;r<e.children.length;r++){const c=e.children[r],u=c.getAttribute("data-ln-render-key");u&&(o[u]=c)}const i=document.createDocumentFragment();for(let r=0;r<t.length;r++){const c=t[r],u=String(l(c));let d=o[u];if(d)a(d,c,r);else{const f=E(n,s);if(!f||(A(f,c),d=f.firstElementChild,!d))continue;d.setAttribute("data-ln-render-key",u),a(d,c,r)}i.appendChild(d)}e.textContent="",e.appendChild(i)}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.fillTemplate=A,window.lnCore.fill=y,window.lnCore.lnFill=T,window.lnCore.renderList=F);function I(e,t,n,l,a){if(!e||t===null)return!0;const s=l||"ln-component",o=e.type;if(o==="trigger"||o==="marker"||o==="string"||o==="list"||!o||t===""&&e.fallback!==void 0)return!0;const i=r=>{a?console.warn(r,a):console.warn(r)};if(o==="boolean"){const r=t.trim().toLowerCase();return r!==""&&r!=="true"&&r!=="false"&&r!=="1"&&r!=="0"?(i(`[${s}] Invalid value "${t}" for boolean attribute "${n}". Allowed: "true", "false", or presence-only.`),!1):!0}if(o==="enum"){const r=e.values||[];return r.includes(t)?!0:(i(`[${s}] Invalid value "${t}" for attribute "${n}". Allowed: ${r.join(", ")}. Fallback: "${e.fallback}".`),!1)}if(o==="integer"){if(!/^-?\d+$/.test(t))return i(`[${s}] Invalid integer "${t}" for attribute "${n}". Fallback: ${e.fallback}.`),!1;const r=parseInt(t,10);return e.min!==void 0&&r<e.min?(i(`[${s}] Value ${r} for attribute "${n}" is less than min (${e.min}).`),!1):e.max!==void 0&&r>e.max?(i(`[${s}] Value ${r} for attribute "${n}" is greater than max (${e.max}).`),!1):!0}if(o==="float")return isNaN(Number(t))?(i(`[${s}] Invalid float "${t}" for attribute "${n}". Fallback: ${e.fallback}.`),!1):!0;if(o==="json")try{return JSON.parse(t),!0}catch(r){return i(`[${s}] Invalid JSON for attribute "${n}": ${r.message}. Fallback: ${e.fallback}.`),!1}return!0}function M(e){if(e.onAttrChange&&!e.declared)return null;const t=new Set;if(e.effects)for(const n in e.effects)t.add(n);if(e.onAttrChange&&e.declared)for(const n of e.declared)t.add(n);return t}function R(e,t,n,l){if(e.nodeType!==1)return;const s=t.indexOf("[")!==-1||t.indexOf(".")!==-1||t.indexOf("#")!==-1?t:"["+t+"]",o=Array.from(e.querySelectorAll(s));e.matches&&e.matches(s)&&o.push(e);for(const i of o)if(!i[n]){window.lnCore._persistSink&&i.hasAttribute("data-ln-persist")&&window.lnCore._persistSink(i,t);try{i[n]=new l(i)}catch(r){console.error("["+n+"] init failed",i,r)}}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._bootHolds=window.lnCore._bootHolds||0,window.lnCore._bootQueue=window.lnCore._bootQueue||[]);function k(){window.lnCore=window.lnCore||{};const e=window.lnCore._attrRegistry=window.lnCore._attrRegistry||{byAttr:new Map,reactive:[],persist:[]};return e.byReactive=e.byReactive||new Map,e.reactiveWildcard=e.reactiveWildcard||[],e}function W(e){const t=k(),n=e.observed||[];for(let l=0;l<n.length;l++){const a=n[l];t.byAttr.has(a)||t.byAttr.set(a,[]),t.byAttr.get(a).push(e)}if(t.byDeclaredAttr=t.byDeclaredAttr||new Map,e.attributes)for(const l in e.attributes){t.byDeclaredAttr.has(l)||t.byDeclaredAttr.set(l,[]);const a=t.byDeclaredAttr.get(l);a.some(s=>s.componentTag===e.componentTag)||a.push({spec:e.attributes[l],componentTag:e.componentTag})}if(e.onAttrChange||e.effects){t.reactive.push(e);const l=M(e);if(l===null)t.reactiveWildcard.push(e);else for(const a of l)t.byReactive.has(a)||t.byReactive.set(a,[]),t.byReactive.get(a).push(e)}e.persist&&t.persist.push(e)}function _(e,t,n,l){for(let a=0;a<e.length;a++){const s=e[a];if(!t[s.attribute])continue;const o=s.effects&&s.effects[n];o?o(t,n,l):s.onAttrChange&&(!s.declared||s.declared.has(n))&&s.onAttrChange(t,n,l)}}function q(e){const t=e.target,n=e.attributeName;if(e.oldValue===t.getAttribute(n))return;const l=k(),a=l.byAttr.get(n);if(S()&&l.byDeclaredAttr&&l.byDeclaredAttr.has(n)&&g(t)){const s=l.byDeclaredAttr.get(n),o=t.getAttribute(n);for(let i=0;i<s.length;i++)I(s[i].spec,o,n,s[i].componentTag,t)}if(window.lnCore._debugSink&&(n.indexOf("data-ln-")===0||a)&&window.lnCore._debugSink("attr",n,t,{oldValue:e.oldValue,newValue:t.getAttribute(n)}),n.indexOf("data-ln-")===0){const s=l.byReactive.get(n);s&&_(s,t,n,e.oldValue),l.reactiveWildcard.length&&_(l.reactiveWildcard,t,n,e.oldValue)}if(a)for(let s=0;s<a.length;s++){const o=a[s];if(o.handler){o.handler(t,n,e.oldValue);continue}o.onAttributeChange&&t[o.attribute]?o.onAttributeChange(t,n):(R(t,o.selector,o.attribute,o.ComponentFn),o.onInit&&o.onInit(t))}}function B(){window.lnCore=window.lnCore||{},!window.lnCore._attrObserverBound&&(window.lnCore._attrObserverBound=!0,w(function(){new MutationObserver(function(t){for(let n=0;n<t.length;n++)try{q(t[n])}catch(l){console.error("[ln-core] mutation handler failed",t[n].target,l)}}).observe(document.body,{attributes:!0,subtree:!0,attributeOldValue:!0})},"ln-core"))}function V(e,t){W({observed:e,handler:t}),B()}function v(e){return(e||"").replace(/^#/,"")}function p(e){const t=e===void 0?location.hash:e,n={},l=v(t);if(!l)return n;const a=l.split("&");for(let s=0;s<a.length;s++){const o=a[s];if(!o)continue;const i=o.indexOf(":"),r=i>-1?o.slice(0,i):o,c=i>-1?o.slice(i+1):"";if(r)try{n[r]=decodeURIComponent(c)}catch{n[r]=c}}return n}function j(e){if(!e)return null;const t=p();return e in t?t[e]:null}function N(e,t){if(!e)return;const n=p();t==null?delete n[e]:n[e]=String(t);const a=Object.keys(n).map(function(s){const o=n[s];return o===""?s:s+":"+encodeURIComponent(o)}).join("&");v(location.hash)!==a&&(location.hash=a)}function H(e){return e.button===1||e.ctrlKey||e.metaKey||e.shiftKey?!1:(e.preventDefault(),!0)}function U(e,t){if(!e||!e.hasAttribute("data-ln-hash"))return null;const n=e.getAttribute("data-ln-hash");if(n&&n.trim()!=="")return n.trim();const l=e.getAttribute("data-ln-sort")||e.getAttribute("data-ln-search-for")||e.getAttribute("data-ln-search")||e.getAttribute("data-ln-filter")||e.id;return l?t?l+"-"+t:l:t||null}function K(e,t){return!t||t==="none"||e===null||e===void 0?null:String(e)+"."+t}function G(e){return!e||typeof e!="string"?null:e.endsWith(".asc")?{fieldOrColumn:e.slice(0,-4),direction:"asc"}:e.endsWith(".desc")?{fieldOrColumn:e.slice(0,-5),direction:"desc"}:null}function J(e,t){return!e||!Array.isArray(t)||t.length===0?null:e+":"+t.map(encodeURIComponent).join(",")}function Q(e){if(!e||typeof e!="string")return null;const t=e.indexOf(":");if(t===-1)return null;const n=e.slice(0,t),l=e.slice(t+1),a=l?l.split(",").map(function(s){try{return decodeURIComponent(s)}catch{return s}}).filter(Boolean):[];return{key:n,values:a}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.hashParse=p,window.lnCore.hashGet=j,window.lnCore.hashSet=N,window.lnCore.hashLinkClick=H,window.lnCore.resolveHashNamespace=U,window.lnCore.hashSortEncode=K,window.lnCore.hashSortDecode=G,window.lnCore.hashFilterEncode=J,window.lnCore.hashFilterDecode=Q),(function(){const e="lnExternalLinks";if(window[e]!==void 0)return;function t(i){return i.hostname&&i.hostname!==window.location.hostname}function n(i){if(i.getAttribute("data-ln-external-link")==="processed"||!t(i))return;i.target="_blank";const r=(i.rel||"").split(/\s+/).filter(Boolean);r.includes("noopener")||r.push("noopener"),r.includes("noreferrer")||r.push("noreferrer"),i.rel=r.join(" ");const c=document.createElement("span");c.className="sr-only",c.textContent="(opens in new tab)",i.appendChild(c),i.setAttribute("data-ln-external-link","processed"),b(i,"ln-external-links:processed",{link:i,href:i.href})}function l(i){i=i||document.body;for(const r of i.querySelectorAll("a, area"))n(r)}function a(){w(function(){document.body.addEventListener("click",function(i){const r=i.target.closest("a, area");r&&r.getAttribute("data-ln-external-link")==="processed"&&b(r,"ln-external-links:clicked",{link:r,href:r.href,text:r.textContent||r.title||""})})},"ln-external-links")}function s(){w(function(){new MutationObserver(function(r){for(const c of r)if(c.type==="childList"){for(const u of c.addedNodes)if(u.nodeType===1&&(u.matches&&(u.matches("a")||u.matches("area"))&&n(u),u.querySelectorAll))for(const d of u.querySelectorAll("a, area"))n(d)}}).observe(document.body,{childList:!0,subtree:!0}),V(["href"],function(r){r.matches&&(r.matches("a")||r.matches("area"))&&n(r)})},"ln-external-links")}function o(){a(),s(),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",function(){l()}):l()}window[e]={process:l},o()})()})();
@@ -0,0 +1,18 @@
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-external-links",
4
+ "generator": "scripts/sync-ln-schemas.mjs",
5
+ "attributes": {
6
+ "data-ln-external-link": {
7
+ "direction": "both",
8
+ "sources": [
9
+ "src/ln-external-links.js"
10
+ ],
11
+ "type": "enum",
12
+ "values": [
13
+ "processed"
14
+ ],
15
+ "description": "Marker indicating link was identified and processed as external"
16
+ }
17
+ }
18
+ }
@@ -1,10 +1,15 @@
1
- import { dispatch, guardBody } from '../../ln-core';
1
+ import { dispatch, guardBody, observeAttributes } from '../../ln-core';
2
2
 
3
3
  (function() {
4
4
  const DOM_ATTRIBUTE = 'lnExternalLinks';
5
5
 
6
6
  if (window[DOM_ATTRIBUTE] !== undefined) return;
7
7
 
8
+ // ─── Attribute Contract (SSOT) ──────────────────────────
9
+ const ATTRIBUTES = {
10
+ 'data-ln-external-link': { type: 'enum', values: ['processed'], description: 'Marker indicating link was identified and processed as external' }
11
+ };
12
+
8
13
  function _isExternalLink(link) {
9
14
  return link.hostname && link.hostname !== window.location.hostname;
10
15
  }
@@ -76,21 +81,18 @@ import { dispatch, guardBody } from '../../ln-core';
76
81
  }
77
82
  }
78
83
  }
79
-
80
- if (mutation.type === 'attributes' && mutation.attributeName === 'href') {
81
- const target = mutation.target;
82
- if (target.matches && (target.matches('a') || target.matches('area'))) {
83
- _processLink(target);
84
- }
85
- }
86
84
  }
87
85
  });
88
86
 
89
87
  observer.observe(document.body, {
90
88
  childList: true,
91
- subtree: true,
92
- attributes: true,
93
- attributeFilter: ['href']
89
+ subtree: true
90
+ });
91
+
92
+ observeAttributes(['href'], function (el) {
93
+ if (el.matches && (el.matches('a') || el.matches('area'))) {
94
+ _processLink(el);
95
+ }
94
96
  });
95
97
  }, 'ln-external-links');
96
98
  }
@@ -1,8 +1,6 @@
1
1
  # ln-fill
2
2
 
3
- > Declarative click-triggered form/display fill. A document-level delegated
4
- > click listener — not a per-element component. Composes with `data-ln-modal-for`
5
- > on the same button.
3
+ > Applied declaratively to clickable triggers (`<button data-ln-fill-form="formId" data-ln-fill-key="value">`). It catches delegated document click events, normalizes `data-ln-fill-*` attributes into a payload object, and invokes targeted dispatch via `lnCore.lnFill()` to fire `ln-fill` CustomEvents directly at the addressed form or container. It manages no form validation, modal toggling, or backend storage, serving strictly as an event-driven DOM field populator.
6
4
 
7
5
  ---
8
6
 
@@ -40,7 +38,7 @@ form plus display fillables — without the producer knowing a single id, which
40
38
  a flat id-addressed broadcast cannot express. Single payload contract: the
41
39
  `record ?? null` normalization (null = reset) and `bubbles: true` are defined
42
40
  in one place, shared by every producer (the declarative click trigger,
43
- `ln-modal-coordinator`, store-sync coordinators).
41
+ `ln-ui-coordinator`, store-sync coordinators).
44
42
 
45
43
  So `lnFill()` is not an imperative bypass of the event model — it IS the
46
44
  event dispatcher. The targeted fan-out loop and the payload contract have to
@@ -112,7 +110,7 @@ Order of side-effects per click (both listeners are on `document`):
112
110
  2. `ln-fill` click listener → fills form via `lnFill(form, record)`.
113
111
 
114
112
  ### Double-Fill Prevention for Hash-Bound triggers
115
- If a clickable trigger is an anchor link that points to a hash segment (i.e., its `href` attribute contains `#`, such as `<a href="#event-modal:42" ...>`), `ln-fill`'s click listener will **ignore** the click. The fill process is instead delegated entirely to the `ln-modal-coordinator`, which will map the resulting hash change and `ln-modal:open` event to an `ln-fill:request` event. This prevents redundant, parallel form-filling operations.
113
+ If a clickable trigger is an anchor link that points to a hash segment (i.e., its `href` attribute contains `#`, such as `<a href="#event-modal:42" ...>`), `ln-fill`'s click listener will **ignore** the click. The fill process is instead delegated entirely to the `ln-ui-coordinator`, which will map the resulting hash change and `ln-modal:open` event to an `ln-fill:request` event. This prevents redundant, parallel form-filling operations.
116
114
 
117
115
  ---
118
116
 
@@ -185,9 +183,9 @@ Decision rule:
185
183
  ```
186
184
  - **Standalone IIFE** — for lightweight pages:
187
185
  ```html
188
- <script src="js/ln-fill/ln-fill.js" defer></script>
186
+ <script src="components/ln-fill/ln-fill.js" defer></script>
189
187
  ```
190
- - **Active Source (ESM)**: `js/ln-fill/src/ln-fill.js`
188
+ - **Active Source (ESM)**: `components/ln-fill/src/ln-fill.js`
191
189
 
192
190
  ---
193
191
 
@@ -196,4 +194,4 @@ Decision rule:
196
194
  - **[`ln-form`](../ln-form/README.md)** — the fill target; `data-ln-fill-as` decoupled key.
197
195
  - **[`ln-modal`](../ln-modal/README.md)** — `data-ln-modal-*` display namespace fill.
198
196
  - **[`docs/architecture/data-flow.md §5.7`](../../docs/architecture/data-flow.md)** — `lnFill` primitive reference.
199
- - **[`js/ln-core/README.md`](../ln-core/README.md)** — `lnFill`, `fillTemplate`, `populateForm` helpers.
197
+ - **[`components/ln-core/README.md`](../ln-core/README.md)** — `lnFill`, `fillTemplate`, `populateForm` helpers.
@@ -0,0 +1 @@
1
+ (function(){"use strict";function S(e){if(typeof window>"u")return!1;if(window.lnDebug===!0)return!0;if(window.lnCore&&window.lnCore._debugIsContained)return e?window.lnCore._debugIsContained(e):window.lnCore._debugSink!==null;if(e&&e.closest){const n=e.closest("[data-ln-debug]");return!(!n||typeof document<"u"&&n===document.documentElement)}return typeof document<"u"&&document.body?document.body.hasAttribute("data-ln-debug"):!1}if(typeof window<"u"&&(window.lnCore=window.lnCore||{},!window.lnCore._warnBound)){window.lnCore._warnBound=!0;const e=console.warn;console.warn=function(...n){if(typeof n[0]=="string"&&(n[0].startsWith("[ln-")||n[0].startsWith("[lnCore"))){let u=null;for(let s=1;s<n.length;s++)if(n[s]&&n[s].nodeType===1){u=n[s];break}if(!S(u))return}e.apply(console,n)}}function A(e,n,r){const u=r||{};window.lnCore._debugSink&&window.lnCore._debugSink("event",n,e,u),e.dispatchEvent(new CustomEvent(n,{bubbles:!0,detail:u}))}function p(e,n){if(!document.body){document.addEventListener("DOMContentLoaded",function(){p(e,n)}),console.warn("["+n+'] Script loaded before <body> — add "defer" to your <script> tag');return}e()}const C={};function _(e,n){C[e]=n}function k(e){return C[e]||{ingress:n=>n,egress:n=>n}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerDataMapper=_,window.lnCore.getDataMapper=k);function E(){typeof window>"u"||(window.lnCore=window.lnCore||{},!window.lnCore._localeObserverBound&&(window.lnCore._localeObserverBound=!0,p(function(){new MutationObserver(function(){A(document,"ln-core:locale-change",{})}).observe(document.documentElement,{attributes:!0,attributeFilter:["lang"],subtree:!0})},"ln-core")))}const g={};function L(e,n){if(!e||typeof n!="object")return;const r=e.toLowerCase().split("-")[0];g[r]=n}function F(e){if(!e)return null;const n=e.toLowerCase().split("-")[0];return g[n]||null}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerLocaleFallback=L,window.lnCore.getLocaleFallback=F,window.lnCore.ensureLocaleObserver=E);const w={};function v(e,n){w[e]||(w[e]=document.querySelector('[data-ln-template="'+e+'"]'));const r=w[e];return r?r.content.cloneNode(!0):(console.warn("["+(n||"ln-core")+'] Template "'+e+'" not found'),null)}function b(e,n){if(!e||!n)return e;const r=e.querySelectorAll("[data-ln-field]");for(let t=0;t<r.length;t++){const i=r[t],o=i.getAttribute("data-ln-field");n[o]!=null&&(i.textContent=n[o])}const u=e.querySelectorAll("[data-ln-attr]");for(let t=0;t<u.length;t++){const i=u[t],o=i.getAttribute("data-ln-attr").split(",");for(let c=0;c<o.length;c++){const d=o[c].trim().split(":");if(d.length!==2)continue;const f=d[0].trim(),a=d[1].trim();n[a]!=null&&i.setAttribute(f,n[a])}}const s=e.querySelectorAll("[data-ln-show]");for(let t=0;t<s.length;t++){const i=s[t],o=i.getAttribute("data-ln-show");o in n&&i.classList.toggle("hidden",!n[o])}const l=e.querySelectorAll("[data-ln-class]");for(let t=0;t<l.length;t++){const i=l[t],o=i.getAttribute("data-ln-class").split(",");for(let c=0;c<o.length;c++){const d=o[c].trim().split(":");if(d.length!==2)continue;const f=d[0].trim(),a=d[1].trim();a in n&&i.classList.toggle(f,!!n[a])}}return e}function x(e,n){e.matches&&e.matches("[data-ln-form], [data-ln-fillable]")&&(window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",e,n??null),e.dispatchEvent(new CustomEvent("ln-fill",{detail:n??null,bubbles:!0})));const r=e.querySelectorAll("[data-ln-form], [data-ln-fillable]");for(let u=0;u<r.length;u++)window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",r[u],n??null),r[u].dispatchEvent(new CustomEvent("ln-fill",{detail:n??null,bubbles:!0}));return e}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._fillBound||(window.lnCore._fillBound=!0,document.addEventListener("ln-fill",function(e){if(!(!e.target.matches||!e.target.matches("[data-ln-fillable]")))if(e.detail)b(e.target,e.detail);else{const n=e.target.querySelectorAll("[data-ln-field]");for(let r=0;r<n.length;r++)n[r].textContent=""}})));function m(e,n){if(!e||!n)return e;const r=document.createTreeWalker(e,NodeFilter.SHOW_TEXT);for(;r.nextNode();){const l=r.currentNode;l.textContent.indexOf("{{")!==-1&&(l.textContent=l.textContent.replace(/\{\{\s*(\w+)\s*\}\}/g,function(t,i){return n[i]!==void 0?n[i]:""}))}const u=function(l,t){return n[t]!==void 0?n[t]:""},s=Array.from(e.querySelectorAll("*"));e.nodeType===1&&s.push(e);for(let l=0;l<s.length;l++){const t=s[l],i=t.attributes;for(let o=0;o<i.length;o++){const c=i[o];c.value.indexOf("{{")!==-1&&t.setAttribute(c.name,c.value.replace(/\{\{\s*(\w+)\s*\}\}/g,u))}}return e}function D(e,n,r,u,s,l){const t={};for(let o=0;o<e.children.length;o++){const c=e.children[o],d=c.getAttribute("data-ln-render-key");d&&(t[d]=c)}const i=document.createDocumentFragment();for(let o=0;o<n.length;o++){const c=n[o],d=String(u(c));let f=t[d];if(f)s(f,c,o);else{const a=v(r,l);if(!a||(m(a,c),f=a.firstElementChild,!f))continue;f.setAttribute("data-ln-render-key",d),s(f,c,o)}i.appendChild(f)}e.textContent="",e.appendChild(i)}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.fillTemplate=m,window.lnCore.fill=b,window.lnCore.lnFill=x,window.lnCore.renderList=D),typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._bootHolds=window.lnCore._bootHolds||0,window.lnCore._bootQueue=window.lnCore._bootQueue||[]);function y(e){return(e||"").replace(/^#/,"")}function h(e){const n=e===void 0?location.hash:e,r={},u=y(n);if(!u)return r;const s=u.split("&");for(let l=0;l<s.length;l++){const t=s[l];if(!t)continue;const i=t.indexOf(":"),o=i>-1?t.slice(0,i):t,c=i>-1?t.slice(i+1):"";if(o)try{r[o]=decodeURIComponent(c)}catch{r[o]=c}}return r}function O(e){if(!e)return null;const n=h();return e in n?n[e]:null}function B(e,n){if(!e)return;const r=h();n==null?delete r[e]:r[e]=String(n);const s=Object.keys(r).map(function(l){const t=r[l];return t===""?l:l+":"+encodeURIComponent(t)}).join("&");y(location.hash)!==s&&(location.hash=s)}function I(e){return e.button===1||e.ctrlKey||e.metaKey||e.shiftKey?!1:(e.preventDefault(),!0)}function T(e,n){if(!e||!e.hasAttribute("data-ln-hash"))return null;const r=e.getAttribute("data-ln-hash");if(r&&r.trim()!=="")return r.trim();const u=e.getAttribute("data-ln-sort")||e.getAttribute("data-ln-search-for")||e.getAttribute("data-ln-search")||e.getAttribute("data-ln-filter")||e.id;return u?n?u+"-"+n:u:n||null}function q(e,n){return!n||n==="none"||e===null||e===void 0?null:String(e)+"."+n}function W(e){return!e||typeof e!="string"?null:e.endsWith(".asc")?{fieldOrColumn:e.slice(0,-4),direction:"asc"}:e.endsWith(".desc")?{fieldOrColumn:e.slice(0,-5),direction:"desc"}:null}function M(e,n){return!e||!Array.isArray(n)||n.length===0?null:e+":"+n.map(encodeURIComponent).join(",")}function j(e){if(!e||typeof e!="string")return null;const n=e.indexOf(":");if(n===-1)return null;const r=e.slice(0,n),u=e.slice(n+1),s=u?u.split(",").map(function(l){try{return decodeURIComponent(l)}catch{return l}}).filter(Boolean):[];return{key:r,values:s}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.hashParse=h,window.lnCore.hashGet=O,window.lnCore.hashSet=B,window.lnCore.hashLinkClick=I,window.lnCore.resolveHashNamespace=T,window.lnCore.hashSortEncode=q,window.lnCore.hashSortDecode=W,window.lnCore.hashFilterEncode=M,window.lnCore.hashFilterDecode=j),(function(){const e="lnFill";if(window[e]!==void 0)return;const n={lnFillForm:!0,lnFillStore:!0};function r(s){const l={},t=s.dataset;for(const i in t){if(!i.startsWith("lnFill")||n[i])continue;const o=i.slice(6);o&&(l[o.charAt(0).toLowerCase()+o.slice(1)]=t[i])}return l}function u(s,l){const t=window.CSS&&CSS.escape?CSS.escape(l):l,i=document.querySelectorAll('[data-ln-fill-id="'+t+'"]');if(i.length===0)return null;for(let o=0;o<i.length;o++){const c=i[o].getAttribute("data-ln-fill-form");if(c){const d=document.getElementById(c);if(d&&s.contains(d))return i[o]}}return i[0]}document.addEventListener("click",function(s){if(s.ctrlKey||s.metaKey||s.button===1)return;const l=s.target.closest("[data-ln-fill-form]");if(!l)return;const t=l.getAttribute("href");if(t&&t.indexOf("#")!==-1)return;const i=l.getAttribute("data-ln-fill-form"),o=document.getElementById(i);if(!o)return;const c=r(l),d=Object.keys(c).length>0;window.lnCore.lnFill(o,d?c:null)}),document.addEventListener("ln-fill:request",function(s){const l=s.detail;if(!l)return;const t=s.target,i=l.id;if(i==null){window.lnCore.lnFill(t,null);return}const o=u(t,i);if(!o)return;const c=r(o);window.lnCore.lnFill(t,c)}),window[e]=!0})()})();
@@ -0,0 +1,23 @@
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-fill",
4
+ "generator": "scripts/sync-ln-schemas.mjs",
5
+ "attributes": {
6
+ "data-ln-fill-form": {
7
+ "direction": "author",
8
+ "sources": [
9
+ "src/ln-fill.js"
10
+ ],
11
+ "type": "string",
12
+ "description": "ID of target form populated with source element dataset properties"
13
+ },
14
+ "data-ln-fill-id": {
15
+ "direction": "author",
16
+ "sources": [
17
+ "src/ln-fill.js"
18
+ ],
19
+ "type": "string",
20
+ "description": "Unique identifier of data source element providing fill attributes"
21
+ }
22
+ }
23
+ }
@@ -5,6 +5,12 @@ import { } from '../../ln-core';
5
5
 
6
6
  if (window[DOM_ATTRIBUTE] !== undefined) return;
7
7
 
8
+ // ─── Attribute Contract (SSOT) ──────────────────────────
9
+ const ATTRIBUTES = {
10
+ 'data-ln-fill-form': { type: 'string', description: 'ID of target form populated with source element dataset properties' },
11
+ 'data-ln-fill-id': { type: 'string', description: 'Unique identifier of data source element providing fill attributes' }
12
+ };
13
+
8
14
  // data-ln-fill-store is RESERVED for a future store-source seam.
9
15
  // When implemented, the click handler will look up a record from a named
10
16
  // store (e.g. window.lnCore stores) instead of reading flat data-* attributes.
@@ -46,7 +52,7 @@ import { } from '../../ln-core';
46
52
 
47
53
  // Prevent double fill: if this trigger is a hash-bound anchor (e.g. href="#user-modal:142"),
48
54
  // we skip the click-based fill. The resulting hash change will trigger ln-modal:open,
49
- // and the ln-modal-coordinator will request the fill via ln-fill:request.
55
+ // and the ln-ui-coordinator will request the fill via ln-fill:request.
50
56
  const href = trigger.getAttribute('href');
51
57
  if (href && href.indexOf('#') !== -1) return;
52
58
 
@@ -0,0 +1,131 @@
1
+ # ln-filter
2
+
3
+ > Applied to a `<nav data-ln-filter="targetId">` control containing `<input type="checkbox">` filters with `data-ln-filter-value`
4
+ > and a `data-ln-filter-reset` sentinel. On checkbox `change`, it updates active values and keeps the sentinel in sync. It evaluates
5
+ > items on the target container or table by dataset attributes or column index, sets `data-ln-filter-hide` and `.hidden` on non-matching
6
+ > elements, and emits a cancelable `ln-filter:change` CustomEvent.
7
+
8
+ ---
9
+
10
+ ## 🧭 Philosophy & Architecture
11
+
12
+ 1. **Declarative State Model:** The component has no custom imperative state-change methods. Filter state is driven entirely by native checkboxes. External scripts update selections by writing `input.checked = true` and dispatching a standard bubbled `change` event.
13
+ 2. **Sentinel Rules:** The `data-ln-filter-reset` ("All") checkbox is kept in sync automatically through mutual exclusion and collapse rules:
14
+ - **Check sentinel** → unchecks all value inputs (resets to All).
15
+ - **Uncheck last value** → re-checks the sentinel (never allows empty selection).
16
+ - **Check all values** → collapses to sentinel: unchecks all values, re-checks sentinel.
17
+ 3. **Plain Table Column Filtering:** By defining `data-ln-filter-col="N"`, the component filters plain HTML `<table>` rows by column cell text with AND logic across columns and OR logic within columns.
18
+ 4. **Local State Persistence:** Adding the `data-ln-persist` attribute saves the active filter values (`data-ln-filter-values`) to `localStorage` under `ln:{id}:data-ln-filter-values` (global by default), or `ln:{id}:{path}:data-ln-filter-values` when `data-ln-persist-scope="page"` is present. The filter *key* is never persisted — only the active values.
19
+ 5. **Decoupled Two-Host Bridge:** Dispatches cancelable `ln-filter:change` events. Consumers (such as `ln-table` in SSR mode or `ln-data-store`) call `e.preventDefault()` to claim filtering and prevent default DOM item hiding.
20
+
21
+ ---
22
+
23
+ ## 📦 Minimal Blueprint
24
+
25
+ ### Generic List Attribute Filter (Zero-JS)
26
+ Bind the filter to a container `id`. Target items declare attributes matching the filter key.
27
+ ```html
28
+ <nav data-ln-filter="employees-list">
29
+ <!-- Reset Sentinel -->
30
+ <label><input type="checkbox" data-ln-filter-key="category" data-ln-filter-reset checked> All</label>
31
+ <!-- Values -->
32
+ <label><input type="checkbox" data-ln-filter-key="category" data-ln-filter-value="design"> Design</label>
33
+ <label><input type="checkbox" data-ln-filter-key="category" data-ln-filter-value="dev"> Development</label>
34
+ </nav>
35
+
36
+ <ul id="employees-list">
37
+ <li data-category="design">Ana Petrova — UI Designer</li>
38
+ <li data-category="dev">Marko Nikolov — Developer</li>
39
+ </ul>
40
+ ```
41
+
42
+ ### Table Column Filter with Plain HTML Table
43
+ Filters plain `<table>` rows by Column Index `2` (Department) and saves state to storage.
44
+ ```html
45
+ <nav id="dept-filter" data-ln-filter="users-table" data-ln-filter-col="2" data-ln-persist>
46
+ <label><input type="checkbox" data-ln-filter-key="dept" data-ln-filter-reset checked> All Departments</label>
47
+ <label><input type="checkbox" data-ln-filter-key="dept" data-ln-filter-value="Engineering"> Engineering</label>
48
+ <label><input type="checkbox" data-ln-filter-key="dept" data-ln-filter-value="Design"> Design</label>
49
+ </nav>
50
+
51
+ <table id="users-table">
52
+ <thead>
53
+ <tr><th>ID</th><th>Name</th><th>Department</th></tr>
54
+ </thead>
55
+ <tbody>
56
+ <tr><td>1</td><td>Ana Petrova</td><td>Engineering</td></tr>
57
+ <tr><td>2</td><td>Marko Nikolov</td><td>Design</td></tr>
58
+ </tbody>
59
+ </table>
60
+ ```
61
+
62
+ ---
63
+
64
+ ## 🛠️ Declarative API Contract
65
+
66
+ ### HTML Attributes
67
+
68
+ | Attribute | Elements | Description |
69
+ | :--- | :--- | :--- |
70
+ | `data-ln-filter` | Container root | Component root. Value is the `id` of the target container whose items are filtered. |
71
+ | `data-ln-filter-key` | `<input type="checkbox">` | The field name representing the target dataset attribute (e.g. `category` matches `data-category`). |
72
+ | `data-ln-filter-value` | `<input type="checkbox">` | The value to match. Active checkboxes show matching items; others are hidden. |
73
+ | `data-ln-filter-reset` | `<input type="checkbox">` | Marks the reset ("All") sentinel. |
74
+ | `data-ln-filter-col` | Container root | Opt-in. 0-based column index to filter plain `<table>` rows by column cell text. |
75
+ | `data-ln-persist` | Container root | Opt-in. Persists active checkbox selections (`data-ln-filter-values`) in `localStorage`. |
76
+ | `data-ln-persist-scope` | Container root | Opt-in, independent attribute. `"page"` scopes the persisted key to the current URL pathname. |
77
+ | `data-ln-hash` | Container root | Opt-in. Synchronizes active filters to URL hash fragment (e.g. `#users-filter:status:active,pending`). Value is custom namespace; if empty defaults to `[targetId]-filter`. |
78
+ | `data-ln-filter-values` | Container root | *State*. Comma-joined, percent-encoded list of currently active filter values. Written by the component, read by `ln-persist` for restore/save. |
79
+ | `data-ln-filter-hide` | Children of target | *State*. Automatically toggled on non-matching elements (`display: none !important`). |
80
+
81
+
82
+ ---
83
+
84
+ ## ⚡ DOM Events
85
+
86
+ ### `ln-filter:change`
87
+ Fired when any filter selection is modified.
88
+ - **Cancelable**: Yes (`preventDefault`)
89
+ - **Payload (`detail`)**: `{ key: string, values: string[], targetId: string }`
90
+
91
+ ### `ln-filter:reset`
92
+ Fired when the reset sentinel is activated.
93
+ - **Payload (`detail`)**: `{ targetId: string }`
94
+
95
+ ---
96
+
97
+ ## Table Column Filter with Popover
98
+
99
+ The canonical composition for table per-column filters.
100
+
101
+ ```html
102
+ <th data-ln-table-filter-col="department">
103
+ Department
104
+ <button class="table-filter" type="button"
105
+ data-ln-table-col-filter
106
+ data-ln-popover-for="filter-my-table-dept"
107
+ aria-label="Filter department">
108
+ <svg class="ln-icon" aria-hidden="true"><use href="#ln-icon-filter"></use></svg>
109
+ </button>
110
+ </th>
111
+
112
+ <div data-ln-popover id="filter-my-table-dept">
113
+ <ul id="filter-my-table-dept-list" data-ln-filter="my-table">
114
+ <li><label><input type="checkbox" data-ln-filter-key="department" data-ln-filter-reset checked> All</label></li>
115
+ <li><label><input type="checkbox" data-ln-filter-key="department" data-ln-filter-value="Engineering"> Engineering</label></li>
116
+ <li><label><input type="checkbox" data-ln-filter-key="department" data-ln-filter-value="Legal"> Legal</label></li>
117
+ </ul>
118
+ </div>
119
+ ```
120
+
121
+ ---
122
+
123
+ ## ⚠️ Common Pitfalls
124
+
125
+ - **Driving State Programmatically Without Events:** Changing `input.checked = true` using JavaScript does not trigger browser `change` listeners. You must explicitly dispatch the event:
126
+ ```javascript
127
+ input.checked = true;
128
+ input.dispatchEvent(new Event('change', { bubbles: true }));
129
+ ```
130
+ - **Missing `id` on Persisted Filters:** The `data-ln-persist` storage key relies on the filter element's ID (e.g. `<nav id="my-filter" data-ln-persist>`), unless an explicit `data-ln-persist="key"` value is given. If neither exists, `ln-persist` warns once and skips persistence for that element.
131
+ - **Using `data-ln-filter-col` for ln-table column filters:** The `data-ln-filter-col` attribute (0-based column index for plain table row filtering) is for standalone `ln-filter` targeting a plain `<table>` — not for the `ln-table` component. For `ln-table`, use `data-ln-filter="<tableId>"` on the `<ul>` and `data-ln-table-filter-col="<fieldName>"` on the `<th>`.
@@ -0,0 +1,13 @@
1
+ @use '../../theme/config/mixins' as *;
2
+
3
+ [data-ln-debug] {
4
+ // 1. Filter Trigger Check: data-ln-filter must target a component ID and cannot be empty
5
+ [data-ln-filter=""] {
6
+ @include dev-inline-error("data-ln-filter target is empty");
7
+ }
8
+
9
+ // 2. Filter Key Check: filter input must have a non-empty key name
10
+ [data-ln-filter-key=""] {
11
+ @include dev-inline-error("data-ln-filter-key cannot be empty");
12
+ }
13
+ }
@@ -0,0 +1 @@
1
+ (function(){"use strict";function U(){return typeof window>"u"?!1:window.lnDebug===!0||window.lnCore&&window.lnCore._debugSink?!0:typeof document<"u"&&document.body?document.body.hasAttribute("data-ln-debug")||document.body.querySelector("[data-ln-debug]")!==null:!1}function N(e){if(typeof window>"u")return!1;if(window.lnDebug===!0)return!0;if(window.lnCore&&window.lnCore._debugIsContained)return e?window.lnCore._debugIsContained(e):window.lnCore._debugSink!==null;if(e&&e.closest){const t=e.closest("[data-ln-debug]");return!(!t||typeof document<"u"&&t===document.documentElement)}return typeof document<"u"&&document.body?document.body.hasAttribute("data-ln-debug"):!1}if(typeof window<"u"&&(window.lnCore=window.lnCore||{},!window.lnCore._warnBound)){window.lnCore._warnBound=!0;const e=console.warn;console.warn=function(...t){if(typeof t[0]=="string"&&(t[0].startsWith("[ln-")||t[0].startsWith("[lnCore"))){let r=null;for(let o=1;o<t.length;o++)if(t[o]&&t[o].nodeType===1){r=t[o];break}if(!N(r))return}e.apply(console,t)}}function T(e,t,n){const r=n||{};window.lnCore._debugSink&&window.lnCore._debugSink("event",t,e,r),e.dispatchEvent(new CustomEvent(t,{bubbles:!0,detail:r}))}function ce(e,t,n){const r=n||{};window.lnCore._debugSink&&window.lnCore._debugSink("event",t,e,r);const o=new CustomEvent(t,{bubbles:!0,cancelable:!0,detail:r});return e.dispatchEvent(o),o}function x(e,t){if(!document.body){document.addEventListener("DOMContentLoaded",function(){x(e,t)}),console.warn("["+t+'] Script loaded before <body> — add "defer" to your <script> tag');return}e()}function P(e){return e.hasAttribute("data-ln-value")?e.getAttribute("data-ln-value"):e.tagName==="TIME"&&e.hasAttribute("datetime")?e.getAttribute("datetime"):e.tagName==="DATA"&&e.hasAttribute("value")?e.getAttribute("value"):e.textContent.trim()}const Q={};function ue(e,t){Q[e]=t}function de(e){return Q[e]||{ingress:t=>t,egress:t=>t}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerDataMapper=ue,window.lnCore.getDataMapper=de);function fe(){typeof window>"u"||(window.lnCore=window.lnCore||{},!window.lnCore._localeObserverBound&&(window.lnCore._localeObserverBound=!0,x(function(){new MutationObserver(function(){T(document,"ln-core:locale-change",{})}).observe(document.documentElement,{attributes:!0,attributeFilter:["lang"],subtree:!0})},"ln-core")))}const J={};function he(e,t){if(!e||typeof t!="object")return;const n=e.toLowerCase().split("-")[0];J[n]=t}function ge(e){if(!e)return null;const t=e.toLowerCase().split("-")[0];return J[t]||null}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerLocaleFallback=he,window.lnCore.getLocaleFallback=ge,window.lnCore.ensureLocaleObserver=fe);const D={};function be(e,t){D[e]||(D[e]=document.querySelector('[data-ln-template="'+e+'"]'));const n=D[e];return n?n.content.cloneNode(!0):(console.warn("["+(t||"ln-core")+'] Template "'+e+'" not found'),null)}function G(e,t){if(!e||!t)return e;const n=e.querySelectorAll("[data-ln-field]");for(let i=0;i<n.length;i++){const a=n[i],s=a.getAttribute("data-ln-field");t[s]!=null&&(a.textContent=t[s])}const r=e.querySelectorAll("[data-ln-attr]");for(let i=0;i<r.length;i++){const a=r[i],s=a.getAttribute("data-ln-attr").split(",");for(let h=0;h<s.length;h++){const y=s[h].trim().split(":");if(y.length!==2)continue;const p=y[0].trim(),m=y[1].trim();t[m]!=null&&a.setAttribute(p,t[m])}}const o=e.querySelectorAll("[data-ln-show]");for(let i=0;i<o.length;i++){const a=o[i],s=a.getAttribute("data-ln-show");s in t&&a.classList.toggle("hidden",!t[s])}const l=e.querySelectorAll("[data-ln-class]");for(let i=0;i<l.length;i++){const a=l[i],s=a.getAttribute("data-ln-class").split(",");for(let h=0;h<s.length;h++){const y=s[h].trim().split(":");if(y.length!==2)continue;const p=y[0].trim(),m=y[1].trim();m in t&&a.classList.toggle(p,!!t[m])}}return e}function we(e,t){e.matches&&e.matches("[data-ln-form], [data-ln-fillable]")&&(window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",e,t??null),e.dispatchEvent(new CustomEvent("ln-fill",{detail:t??null,bubbles:!0})));const n=e.querySelectorAll("[data-ln-form], [data-ln-fillable]");for(let r=0;r<n.length;r++)window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",n[r],t??null),n[r].dispatchEvent(new CustomEvent("ln-fill",{detail:t??null,bubbles:!0}));return e}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._fillBound||(window.lnCore._fillBound=!0,document.addEventListener("ln-fill",function(e){if(!(!e.target.matches||!e.target.matches("[data-ln-fillable]")))if(e.detail)G(e.target,e.detail);else{const t=e.target.querySelectorAll("[data-ln-field]");for(let n=0;n<t.length;n++)t[n].textContent=""}})));function X(e,t){if(!e||!t)return e;const n=document.createTreeWalker(e,NodeFilter.SHOW_TEXT);for(;n.nextNode();){const l=n.currentNode;l.textContent.indexOf("{{")!==-1&&(l.textContent=l.textContent.replace(/\{\{\s*(\w+)\s*\}\}/g,function(i,a){return t[a]!==void 0?t[a]:""}))}const r=function(l,i){return t[i]!==void 0?t[i]:""},o=Array.from(e.querySelectorAll("*"));e.nodeType===1&&o.push(e);for(let l=0;l<o.length;l++){const i=o[l],a=i.attributes;for(let s=0;s<a.length;s++){const h=a[s];h.value.indexOf("{{")!==-1&&i.setAttribute(h.name,h.value.replace(/\{\{\s*(\w+)\s*\}\}/g,r))}}return e}function pe(e,t,n,r,o,l){const i={};for(let s=0;s<e.children.length;s++){const h=e.children[s],y=h.getAttribute("data-ln-render-key");y&&(i[y]=h)}const a=document.createDocumentFragment();for(let s=0;s<t.length;s++){const h=t[s],y=String(r(h));let p=i[y];if(p)o(p,h,s);else{const m=be(n,l);if(!m||(X(m,h),p=m.firstElementChild,!p))continue;p.setAttribute("data-ln-render-key",y),o(p,h,s)}a.appendChild(p)}e.textContent="",e.appendChild(a)}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.fillTemplate=X,window.lnCore.fill=G,window.lnCore.lnFill=we,window.lnCore.renderList=pe);function F(e,t,n){const r=e.getAttribute(t);return r===null?n:r}function ye(e,t,n){const r=parseInt(e.getAttribute(t),10);return isNaN(r)?n:r}function me(e,t,n=!1){const r=e.getAttribute(t);if(r===null)return!!n;const o=r.trim().toLowerCase();return!(o==="false"||o==="0")}function Ce(e,t){return(e.getAttribute(t)||"").split(",").map(n=>n.trim()).filter(Boolean)}const $=new Map;function Ae(e,t){const n=(e?e.join("|"):"")+"::"+t;if($.has(n))return $.get(n);const r=new Set(e||[]),o=function(l,i){const a=l.getAttribute(i);return a!==null&&r.has(a)?a:t};return $.set(n,o),o}function ve(e,t,n){const r=parseFloat(e.getAttribute(t));return isNaN(r)?n:r}function ke(e,t,n){const r=e.getAttribute(t);if(!r)return n;try{return JSON.parse(r)}catch{return n}}function Y(e,t,n,r,o){if(!e||t===null)return!0;const l=r||"ln-component",i=e.type;if(i==="trigger"||i==="marker"||i==="string"||i==="list"||!i||t===""&&e.fallback!==void 0)return!0;const a=s=>{o?console.warn(s,o):console.warn(s)};if(i==="boolean"){const s=t.trim().toLowerCase();return s!==""&&s!=="true"&&s!=="false"&&s!=="1"&&s!=="0"?(a(`[${l}] Invalid value "${t}" for boolean attribute "${n}". Allowed: "true", "false", or presence-only.`),!1):!0}if(i==="enum"){const s=e.values||[];return s.includes(t)?!0:(a(`[${l}] Invalid value "${t}" for attribute "${n}". Allowed: ${s.join(", ")}. Fallback: "${e.fallback}".`),!1)}if(i==="integer"){if(!/^-?\d+$/.test(t))return a(`[${l}] Invalid integer "${t}" for attribute "${n}". Fallback: ${e.fallback}.`),!1;const s=parseInt(t,10);return e.min!==void 0&&s<e.min?(a(`[${l}] Value ${s} for attribute "${n}" is less than min (${e.min}).`),!1):e.max!==void 0&&s>e.max?(a(`[${l}] Value ${s} for attribute "${n}" is greater than max (${e.max}).`),!1):!0}if(i==="float")return isNaN(Number(t))?(a(`[${l}] Invalid float "${t}" for attribute "${n}". Fallback: ${e.fallback}.`),!1):!0;if(i==="json")try{return JSON.parse(t),!0}catch(s){return a(`[${l}] Invalid JSON for attribute "${n}": ${s.message}. Fallback: ${e.fallback}.`),!1}return!0}function _e(e,t,n){for(const r in n){const[o,l,i]=n[r];Object.defineProperty(e,r,{get:function(){return o(t,l,i)},enumerable:!0,configurable:!0})}return e}function Se(e){const t={};for(const n in e){const r=e[n];if(!r||!r.prop)continue;let o=r.read;if(!o&&r.type)switch(r.type){case"enum":o=Ae(r.values,r.fallback);break;case"integer":o=ye;break;case"float":o=ve;break;case"boolean":o=me;break;case"list":o=Ce;break;case"json":o=ke;break;case"string":default:o=F;break}o||(o=F),t[r.prop]=[o,n,r.fallback]}return t}function Ie(e){const t={};for(const n in e){const r=e[n];r&&r.effect&&(t[n]=r.effect)}return Object.keys(t).length?t:null}function Ee(e){if(e.onAttrChange&&!e.declared)return null;const t=new Set;if(e.effects)for(const n in e.effects)t.add(n);if(e.onAttrChange&&e.declared)for(const n of e.declared)t.add(n);return t}function B(e,t,n,r){if(e.nodeType!==1)return;const l=t.indexOf("[")!==-1||t.indexOf(".")!==-1||t.indexOf("#")!==-1?t:"["+t+"]",i=Array.from(e.querySelectorAll(l));e.matches&&e.matches(l)&&i.push(e);for(const a of i)if(!a[n]){window.lnCore._persistSink&&a.hasAttribute("data-ln-persist")&&window.lnCore._persistSink(a,t);try{a[n]=new r(a)}catch(s){console.error("["+n+"] init failed",a,s)}}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._bootHolds=window.lnCore._bootHolds||0,window.lnCore._bootQueue=window.lnCore._bootQueue||[]);function Te(){return typeof window<"u"&&window.lnCore&&window.lnCore._bootHolds||0}function L(e){typeof window<"u"?(window.lnCore=window.lnCore||{},window.lnCore._bootHolds=window.lnCore._bootHolds||0,window.lnCore._bootQueue=window.lnCore._bootQueue||[],window.lnCore._bootHolds>0?window.lnCore._bootQueue.push(e):setTimeout(e,0)):e()}function z(){window.lnCore=window.lnCore||{};const e=window.lnCore._attrRegistry=window.lnCore._attrRegistry||{byAttr:new Map,reactive:[],persist:[]};return e.byReactive=e.byReactive||new Map,e.reactiveWildcard=e.reactiveWildcard||[],e}function xe(e){const t=z(),n=e.observed||[];for(let r=0;r<n.length;r++){const o=n[r];t.byAttr.has(o)||t.byAttr.set(o,[]),t.byAttr.get(o).push(e)}if(t.byDeclaredAttr=t.byDeclaredAttr||new Map,e.attributes)for(const r in e.attributes){t.byDeclaredAttr.has(r)||t.byDeclaredAttr.set(r,[]);const o=t.byDeclaredAttr.get(r);o.some(l=>l.componentTag===e.componentTag)||o.push({spec:e.attributes[r],componentTag:e.componentTag})}if(e.onAttrChange||e.effects){t.reactive.push(e);const r=Ee(e);if(r===null)t.reactiveWildcard.push(e);else for(const o of r)t.byReactive.has(o)||t.byReactive.set(o,[]),t.byReactive.get(o).push(e)}e.persist&&t.persist.push(e)}function Z(e,t,n,r){for(let o=0;o<e.length;o++){const l=e[o];if(!t[l.attribute])continue;const i=l.effects&&l.effects[n];i?i(t,n,r):l.onAttrChange&&(!l.declared||l.declared.has(n))&&l.onAttrChange(t,n,r)}}function Le(e){const t=e.target,n=e.attributeName;if(e.oldValue===t.getAttribute(n))return;const r=z(),o=r.byAttr.get(n);if(U()&&r.byDeclaredAttr&&r.byDeclaredAttr.has(n)&&N(t)){const l=r.byDeclaredAttr.get(n),i=t.getAttribute(n);for(let a=0;a<l.length;a++)Y(l[a].spec,i,n,l[a].componentTag,t)}if(window.lnCore._debugSink&&(n.indexOf("data-ln-")===0||o)&&window.lnCore._debugSink("attr",n,t,{oldValue:e.oldValue,newValue:t.getAttribute(n)}),n.indexOf("data-ln-")===0){const l=r.byReactive.get(n);l&&Z(l,t,n,e.oldValue),r.reactiveWildcard.length&&Z(r.reactiveWildcard,t,n,e.oldValue)}if(o)for(let l=0;l<o.length;l++){const i=o[l];if(i.handler){i.handler(t,n,e.oldValue);continue}i.onAttributeChange&&t[i.attribute]?i.onAttributeChange(t,n):(B(t,i.selector,i.attribute,i.ComponentFn),i.onInit&&i.onInit(t))}}function Re(){window.lnCore=window.lnCore||{},!window.lnCore._attrObserverBound&&(window.lnCore._attrObserverBound=!0,x(function(){new MutationObserver(function(t){for(let n=0;n<t.length;n++)try{Le(t[n])}catch(r){console.error("[ln-core] mutation handler failed",t[n].target,r)}}).observe(document.body,{attributes:!0,subtree:!0,attributeOldValue:!0})},"ln-core"))}function ee(){return window.lnCore=window.lnCore||{},window.lnCore._lifecycleRegistry=window.lnCore._lifecycleRegistry||[]}function qe(e){const t=ee();if(t.length){if(e.target)for(let n=0;n<t.length;n++){const r=t[n];if(r.onSubtreeChange){const o=r.query,l=e.target.nodeType===1?e.target.matches(o)?e.target:e.target.closest(o):e.target.parentElement?e.target.parentElement.closest(o):null;l&&r.onSubtreeChange(l,e)}}for(let n=0;n<e.addedNodes.length;n++){const r=e.addedNodes[n];if(r.nodeType===1)for(let o=0;o<t.length;o++){const l=t[o];B(r,l.selector,l.attribute,l.ComponentFn),l.onInit&&l.onInit(r)}}for(let n=0;n<e.removedNodes.length;n++){const r=e.removedNodes[n];if(r.nodeType===1)for(let o=0;o<t.length;o++){const l=t[o],i=l.query,a=Array.from(r.querySelectorAll(i));r.matches&&r.matches(i)&&a.push(r);for(let s=0;s<a.length;s++){const h=a[s];if(!document.contains(h)){const y=h[l.attribute];if(y&&typeof y.destroy=="function")try{y.destroy()}catch(p){console.error("["+l.attribute+"] destroy failed",h,p)}delete h[l.attribute]}}}}}}function Oe(){window.lnCore=window.lnCore||{},!window.lnCore._lifecycleObserverBound&&(window.lnCore._lifecycleObserverBound=!0,x(function(){new MutationObserver(function(t){for(let n=0;n<t.length;n++){const r=t[n];if(r.type==="childList")try{qe(r)}catch(o){console.error("[ln-core] lifecycle handler failed",r.target,o)}}}).observe(document.body,{childList:!0,subtree:!0})},"ln-core"))}function Ne(e,t,n,r,o={}){const l=o.extraAttributes||[],i=o.onAttributeChange||null,a=o.onSubtreeChange||null,s=o.onInit||null,h=o.onAttrChange||null,y=o.effects||null,p=o.attributes||null,m=p?Ie(p):y,H=p?new Set(Object.keys(p)):null,_=o.persist||null;function v(f){const d=f||document.body;if(B(d,e,t,n),p&&U())for(const g in p){const w=p[g],u=Array.from(d.querySelectorAll("["+g+"]"));d.matches&&d.matches("["+g+"]")&&u.push(d);for(let b=0;b<u.length;b++){const C=u[b];N(C)&&Y(w,C.getAttribute(g),g,r,C)}}s&&s(d)}const S=[];if(e.indexOf("[")!==-1){const f=/\[([\w-]+)/g;let d;for(;(d=f.exec(e))!==null;)S.push(d[1])}else S.push(e);xe({selector:e,attribute:t,componentTag:r,attributes:p,ComponentFn:n,onInit:s,observed:S.concat(l),onAttributeChange:i,onAttrChange:h,effects:m,declared:H,persist:_}),Re();const q=e.indexOf("[")!==-1||e.indexOf(".")!==-1||e.indexOf("#")!==-1?e:"["+e+"]";ee().push({selector:e,attribute:t,ComponentFn:n,onInit:s,onSubtreeChange:a,query:q}),Oe(),window[t]=v;function c(){Te()>0?L(function(){v(document.body)}):v(document.body)}return document.readyState==="loading"?document.addEventListener("DOMContentLoaded",c):c(),v}function De(e,t){let n=!1;return function(){n||(n=!0,queueMicrotask(function(){n=!1,e()}))}}function te(e){return(e||"").replace(/^#/,"")}function M(e){const t=e===void 0?location.hash:e,n={},r=te(t);if(!r)return n;const o=r.split("&");for(let l=0;l<o.length;l++){const i=o[l];if(!i)continue;const a=i.indexOf(":"),s=a>-1?i.slice(0,a):i,h=a>-1?i.slice(a+1):"";if(s)try{n[s]=decodeURIComponent(h)}catch{n[s]=h}}return n}function V(e){if(!e)return null;const t=M();return e in t?t[e]:null}function ne(e,t){if(!e)return;const n=M();t==null?delete n[e]:n[e]=String(t);const o=Object.keys(n).map(function(l){const i=n[l];return i===""?l:l+":"+encodeURIComponent(i)}).join("&");te(location.hash)!==o&&(location.hash=o)}function Fe(e){return e.button===1||e.ctrlKey||e.metaKey||e.shiftKey?!1:(e.preventDefault(),!0)}function R(e,t){if(!e||!e.hasAttribute("data-ln-hash"))return null;const n=e.getAttribute("data-ln-hash");if(n&&n.trim()!=="")return n.trim();const r=e.getAttribute("data-ln-sort")||e.getAttribute("data-ln-search-for")||e.getAttribute("data-ln-search")||e.getAttribute("data-ln-filter")||e.id;return r?t?r+"-"+t:r:t||null}function $e(e,t){return!t||t==="none"||e===null||e===void 0?null:String(e)+"."+t}function Be(e){return!e||typeof e!="string"?null:e.endsWith(".asc")?{fieldOrColumn:e.slice(0,-4),direction:"asc"}:e.endsWith(".desc")?{fieldOrColumn:e.slice(0,-5),direction:"desc"}:null}function re(e,t){return!e||!Array.isArray(t)||t.length===0?null:e+":"+t.map(encodeURIComponent).join(",")}function j(e){if(!e||typeof e!="string")return null;const t=e.indexOf(":");if(t===-1)return null;const n=e.slice(0,t),r=e.slice(t+1),o=r?r.split(",").map(function(l){try{return decodeURIComponent(l)}catch{return l}}).filter(Boolean):[];return{key:n,values:o}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.hashParse=M,window.lnCore.hashGet=V,window.lnCore.hashSet=ne,window.lnCore.hashLinkClick=Fe,window.lnCore.resolveHashNamespace=R,window.lnCore.hashSortEncode=$e,window.lnCore.hashSortDecode=Be,window.lnCore.hashFilterEncode=re,window.lnCore.hashFilterDecode=j);function oe(e,t){if(!t||t.length===0)return!0;if(e==null)return!1;const n=String(e).trim().toLowerCase();for(let r=0;r<t.length;r++)if(String(t[r]).trim().toLowerCase()===n)return!0;return!1}function Me(e,t){if(!Array.isArray(e)||!Array.isArray(t))return e!==t;if(e.length!==t.length)return!0;for(let n=0;n<e.length;n++)if(e[n]!==t[n])return!0;return!1}function Ve(e,t,n){if(!t||typeof t!="object")return!0;const r=Object.keys(t);if(r.length===0)return!0;for(let o=0;o<r.length;o++){const l=t[r[o]];let i="";if(l.col!==null&&l.col!==void 0?i=e[l.col]||"":l.attr&&n&&typeof n.getAttribute=="function"&&(i=n.getAttribute(l.attr)||""),!oe(i,l.values))return!1}return!0}function ie(e,t,n,r){if(r!=null&&!isNaN(r))return parseInt(r,10);if(t&&typeof t.getAttribute=="function"){const o=t.getAttribute("data-ln-filter-col");if(o!==null&&!isNaN(parseInt(o,10)))return parseInt(o,10);if(typeof t.closest=="function"){const l=t.closest("th");if(l&&typeof l.cellIndex=="number")return l.cellIndex;const i=t.closest("[data-ln-popover], [id]");if(i&&i.id){const a=e&&e.ownerDocument?e.ownerDocument:t.ownerDocument||(typeof document<"u"?document:null);if(a&&typeof a.querySelector=="function"){const s=a.querySelector('[data-ln-popover-for="'+i.id+'"]');if(s&&typeof s.closest=="function"){const h=s.closest("th");if(h&&typeof h.cellIndex=="number")return h.cellIndex}}}}}if(e&&n&&typeof e.querySelectorAll=="function"){const o=e.querySelectorAll("thead th, tr:first-child th"),l=String(n).trim().toLowerCase();for(let i=0;i<o.length;i++){const a=o[i],s=a.getAttribute("data-ln-table-filter-col")||a.getAttribute("data-ln-filter-col")||a.getAttribute("data-ln-filter-key")||a.getAttribute("data-ln-table-col")||a.getAttribute("data-ln-col")||a.getAttribute("data-ln-field");if(s&&s.trim().toLowerCase()===l)return typeof a.cellIndex=="number"?a.cellIndex:i}if(t){const i=t.closest?t.closest("[data-ln-popover], [id]"):null,a=i&&i.id||t.id||null;if(a)for(let s=0;s<o.length;s++){const h=o[s];if(typeof h.querySelector=="function"&&h.querySelector('[data-ln-popover-for="'+a+'"]'))return typeof h.cellIndex=="number"?h.cellIndex:s}}for(let i=0;i<o.length;i++){const a=o[i],h=Array.from(a.childNodes||[]).filter(p=>p.nodeType===3),y=(h.length>0?h.map(p=>p.textContent.trim()).join(" "):a.textContent||"").trim().toLowerCase();if(y&&y===l)return typeof a.cellIndex=="number"?a.cellIndex:i}}return null}function je(e){if(!Array.isArray(e))return{key:null,values:[]};let t=null;const n=[];for(let r=0;r<e.length;r++){const o=e[r];!t&&o.key&&(t=o.key),o.checked&&!o.isReset&&o.value&&n.push(o.value)}return{key:t,values:n}}function He(e){return!Array.isArray(e)||e.length===0?null:e.map(encodeURIComponent).join(",")}function le(e){return e?e.split(",").map(function(t){try{return decodeURIComponent(t)}catch{return t}}).filter(Boolean):[]}(function(){const e="data-ln-filter",t="lnFilter",n="data-ln-filter-key",r="data-ln-filter-value",o="data-ln-filter-hide",l="data-ln-filter-reset",i="data-ln-filter-col",a="data-ln-hash",s="data-ln-filter-values",h=new WeakMap;if(window[t]!==void 0)return;const y={"data-ln-filter":{prop:"targetId",type:"string",read:F,fallback:null,description:"Target table or list element ID to filter"},"data-ln-hash":{type:"string",effect:q,description:"URL hash routing key for filter state persistence"},"data-ln-filter-values":{type:"string",effect:q,description:"Encoded active filter values"},"data-ln-filter-col":{type:"string",description:"Column name or index filter specifier"},"data-ln-filter-key":{type:"string",description:"Field key for filter matching"},"data-ln-filter-reset":{type:"trigger",description:"Filter reset button or option trigger"},"data-ln-filter-value":{type:"string",description:"Value to match for this filter input"},"data-ln-filter-hide":{type:"enum",values:["collapse","none"],fallback:"collapse",description:"CSS hiding strategy for non-matching rows"}},p=Se(y);function m(c){return c.hasAttribute(l)||!c.getAttribute(r)}function H(c){const f=c.dom.querySelectorAll("["+n+"]"),d=[];for(let w=0;w<f.length;w++){const u=f[w];d.push({key:u.getAttribute(n),value:u.getAttribute(r)||"",checked:u.checked,isReset:m(u)})}const g=je(d);return{key:g.key,values:g.values,targetId:c.targetId}}function _(c,f,d){const g=c.querySelectorAll("["+n+"]"),w=Array.isArray(d)&&d.length>0;for(let u=0;u<g.length;u++){const b=g[u];m(b)?b.checked=!w:w&&b.getAttribute(n)===f&&d.indexOf(b.getAttribute(r))!==-1?b.checked=!0:b.checked=!1}}function v(c){this.dom=c,_e(this,c,p);const f=c.getAttribute(i);this.colIndex=f!==null?parseInt(f,10):null,this._lastSnapshot=null,this._destroyed=!1,this.nsKey=R(c,"filter"),this.hashEnabled=!!this.nsKey;const d=this,g=De(function(){d._render()});this._queueRender=g,this._attachHandlers(),this._onHashChange=function(){if(d._destroyed||!d.hashEnabled)return;const u=V(d.nsKey),b=j(u);b&&b.key&&b.values.length>0?_(d.dom,b.key,b.values):_(d.dom,null,[]),d._render()},this.hashEnabled&&window.addEventListener("hashchange",this._onHashChange);let w=!1;if(this.hashEnabled){const u=V(this.nsKey),b=j(u);b&&b.key&&b.values.length>0&&(_(c,b.key,b.values),L(function(){d._destroyed||d._render()}),w=!0)}if(!w){const u=le(c.getAttribute(s));if(u.length>0){const b=c.querySelector("["+n+"]"),C=b?b.getAttribute(n):null;C&&(_(c,C,u),L(function(){d._destroyed||d._render()}),w=!0)}}if(!w){const u=c.querySelectorAll("["+n+"]");for(let b=0;b<u.length;b++)if(u[b].checked&&!m(u[b])){L(function(){d._destroyed||d._render()});break}}return this}v.prototype._attachHandlers=function(){const c=this;this._onDomChange=function(f){const d=f.target;if(!d||!d.hasAttribute||!d.hasAttribute(n))return;const g=Array.from(c.dom.querySelectorAll("["+n+"]"));if(m(d)){for(let w=0;w<g.length;w++)m(g[w])||(g[w].checked=!1);d.checked=!0,c._queueRender();return}if(d.checked){for(let u=0;u<g.length;u++)m(g[u])&&(g[u].checked=!1);let w=!1;for(let u=0;u<g.length;u++)if(m(g[u])){w=!0;break}if(w){let u=!0;for(let b=0;b<g.length;b++)if(!m(g[b])&&!g[b].checked){u=!1;break}if(u)for(let b=0;b<g.length;b++)m(g[b])?g[b].checked=!0:g[b].checked=!1}}else{let w=!1;for(let u=0;u<g.length;u++)if(!m(g[u])&&g[u].checked){w=!0;break}if(!w)for(let u=0;u<g.length;u++)m(g[u])&&(g[u].checked=!0)}c._queueRender()},this.dom.addEventListener("change",this._onDomChange)},v.prototype._render=function(){const c=this,f=H(this),d=this._lastSnapshot;if(!(!d||d.key!==f.key||Me(d.values,f.values)))return;const w=f.key===null||f.values.length===0,u=document.getElementById(c.targetId),b={key:f.key,values:f.values.slice(),targetId:c.targetId};T(c.dom,"ln-filter:change",b);let C=!1;u&&u!==c.dom&&ce(u,"ln-filter:change",b).defaultPrevented&&(C=!0);const O=d&&d.values.length>0,I=f.values.length===0;if(O&&I){const A={targetId:c.targetId};T(c.dom,"ln-filter:reset",A),u&&u!==c.dom&&T(u,"ln-filter:reset",A)}this._lastSnapshot={key:f.key,values:f.values.slice()};const k=He(f.values);if(k?this.dom.setAttribute(s,k):this.dom.removeAttribute(s),this.hashEnabled){const A=re(f.key,f.values);ne(this.nsKey,A)}if(C)return;const E=u&&(u.tagName==="TABLE"?u:u.querySelector?u.querySelector("table"):null);if(E)c._filterTableRows(f,E);else{if(!u)return;const A=u.children;for(let W=0;W<A.length;W++){const K=A[W];if(K.removeAttribute(o),w)continue;const ae=K.getAttribute("data-"+f.key);ae!==null&&(oe(ae,f.values)||K.setAttribute(o,"true"))}}};function S(c){if(!c)return"";const f=c.querySelector?c.querySelector("[data-ln-value]"):null;return P(f||c)}function se(c){return!!(!c||typeof c!="object"||c.tagName==="TEMPLATE"||typeof c.hasAttribute=="function"&&(c.hasAttribute("data-ln-sort-exclude")||c.hasAttribute("hidden"))||c.classList&&c.classList.contains("hidden")||c.style&&c.style.display==="none"||typeof c.matches=="function"&&c.matches(".empty-state, .ln-table__empty, .ln-table__empty-state, [data-ln-empty], [data-ln-empty-state], [data-ln-table-empty]")||typeof c.querySelector=="function"&&c.querySelector(".empty-state, [data-ln-empty], [data-ln-empty-state]"))}v.prototype._filterTableRows=function(c,f){if(!f){const C=document.getElementById(this.targetId);if(!C||(f=C.tagName==="TABLE"?C:C.querySelector?C.querySelector("table"):null,!f))return}const d=ie(f,this.dom,c.key,this.colIndex),g=c.key||this.dom.getAttribute("data-ln-filter-key")||(d!==null?"col"+d:"attr-filter"),w=c.values;h.has(f)||h.set(f,{});const u=h.get(f);g&&w.length>0?u[g]={col:d,values:w.slice(),attr:"data-"+g}:g&&delete u[g];const b=f.tBodies;for(let C=0;C<b.length;C++){const O=b[C].rows;for(let I=0;I<O.length;I++){const k=O[I];if(se(k))continue;const E={};for(let A=0;A<k.cells.length;A++)E[A]=S(k.cells[A]);Ve(E,u,k)?k.removeAttribute(o):k.setAttribute(o,"true")}}},v.prototype.destroy=function(){if(!this.dom[t])return;this._destroyed=!0;const c=document.getElementById(this.targetId);if(c){const f=c.tagName==="TABLE"?c:c.querySelector?c.querySelector("table"):null;if(f&&h.has(f)){const d=h.get(f),g=ie(f,this.dom,this.dom.getAttribute("data-ln-filter-key"),this.colIndex),w=this.dom.getAttribute("data-ln-filter-key")||(g!==null?"col"+g:this.colIndex!==null?"col"+this.colIndex:null);w&&d[w]&&(delete d[w],this._filterTableRows({key:null,values:[]},f)),Object.keys(d).length===0&&h.delete(f)}}this._onDomChange&&(this.dom.removeEventListener("change",this._onDomChange),delete this._onDomChange),this.hashEnabled&&this._onHashChange&&window.removeEventListener("hashchange",this._onHashChange),delete this.dom[t]};function q(c,f){const d=c[t];if(!(!d||d._destroyed)){if(f===a)d.hashEnabled&&d._onHashChange&&window.removeEventListener("hashchange",d._onHashChange),d.nsKey=R(c,"filter"),d.hashEnabled=!!d.nsKey,d.hashEnabled&&window.addEventListener("hashchange",d._onHashChange);else if(f===s){const g=le(c.getAttribute(s)),w=c.querySelector("["+n+"]"),u=w?w.getAttribute(n):null;u&&(_(c,u,g),d._render())}}}Ne(e,t,v,"ln-filter",{attributes:y,persist:{attr:s,hashActive:function(c){return!!R(c,"filter")}}})})()})();
@@ -0,0 +1,153 @@
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-filter",
4
+ "generator": "scripts/sync-ln-schemas.mjs",
5
+ "attributes": {
6
+ "data-ln-col": {
7
+ "direction": "author",
8
+ "sources": [
9
+ "src/filter-model.js"
10
+ ]
11
+ },
12
+ "data-ln-debug": {
13
+ "direction": null,
14
+ "sources": [
15
+ "ln-filter-dev.scss"
16
+ ]
17
+ },
18
+ "data-ln-empty": {
19
+ "direction": "author",
20
+ "sources": [
21
+ "src/ln-filter.js"
22
+ ]
23
+ },
24
+ "data-ln-empty-state": {
25
+ "direction": "author",
26
+ "sources": [
27
+ "src/ln-filter.js"
28
+ ]
29
+ },
30
+ "data-ln-field": {
31
+ "direction": "author",
32
+ "sources": [
33
+ "src/filter-model.js"
34
+ ]
35
+ },
36
+ "data-ln-filter": {
37
+ "direction": null,
38
+ "sources": [
39
+ "ln-filter-dev.scss",
40
+ "src/ln-filter.js"
41
+ ],
42
+ "type": "string",
43
+ "description": "Target table or list element ID to filter"
44
+ },
45
+ "data-ln-filter-col": {
46
+ "direction": "author",
47
+ "sources": [
48
+ "src/filter-model.js",
49
+ "src/ln-filter.js"
50
+ ],
51
+ "type": "string",
52
+ "description": "Column name or index filter specifier"
53
+ },
54
+ "data-ln-filter-hide": {
55
+ "direction": "runtime",
56
+ "sources": [
57
+ "ln-filter.scss",
58
+ "src/ln-filter.js"
59
+ ],
60
+ "type": "enum",
61
+ "values": [
62
+ "collapse",
63
+ "none"
64
+ ],
65
+ "fallback": "collapse",
66
+ "description": "CSS hiding strategy for non-matching rows"
67
+ },
68
+ "data-ln-filter-key": {
69
+ "direction": "author",
70
+ "sources": [
71
+ "ln-filter-dev.scss",
72
+ "src/filter-model.js",
73
+ "src/ln-filter.js"
74
+ ],
75
+ "type": "string",
76
+ "description": "Field key for filter matching"
77
+ },
78
+ "data-ln-filter-reset": {
79
+ "direction": "author",
80
+ "sources": [
81
+ "src/ln-filter.js"
82
+ ],
83
+ "type": "trigger",
84
+ "description": "Filter reset button or option trigger"
85
+ },
86
+ "data-ln-filter-value": {
87
+ "direction": "author",
88
+ "sources": [
89
+ "src/ln-filter.js"
90
+ ],
91
+ "type": "string",
92
+ "description": "Value to match for this filter input"
93
+ },
94
+ "data-ln-filter-values": {
95
+ "direction": "both",
96
+ "sources": [
97
+ "src/ln-filter.js"
98
+ ],
99
+ "type": "string",
100
+ "description": "Encoded active filter values"
101
+ },
102
+ "data-ln-hash": {
103
+ "direction": null,
104
+ "sources": [
105
+ "src/ln-filter.js"
106
+ ],
107
+ "type": "string",
108
+ "description": "URL hash routing key for filter state persistence"
109
+ },
110
+ "data-ln-popover": {
111
+ "direction": "author",
112
+ "sources": [
113
+ "src/filter-model.js"
114
+ ]
115
+ },
116
+ "data-ln-popover-for": {
117
+ "direction": "author",
118
+ "sources": [
119
+ "src/filter-model.js"
120
+ ]
121
+ },
122
+ "data-ln-sort-exclude": {
123
+ "direction": "author",
124
+ "sources": [
125
+ "src/ln-filter.js"
126
+ ]
127
+ },
128
+ "data-ln-table-col": {
129
+ "direction": "author",
130
+ "sources": [
131
+ "src/filter-model.js"
132
+ ]
133
+ },
134
+ "data-ln-table-empty": {
135
+ "direction": "author",
136
+ "sources": [
137
+ "src/ln-filter.js"
138
+ ]
139
+ },
140
+ "data-ln-table-filter-col": {
141
+ "direction": "author",
142
+ "sources": [
143
+ "src/filter-model.js"
144
+ ]
145
+ },
146
+ "data-ln-value": {
147
+ "direction": "author",
148
+ "sources": [
149
+ "src/ln-filter.js"
150
+ ]
151
+ }
152
+ }
153
+ }