@livenetworks/ashlar 1.6.1 → 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 (559) 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/{js → components}/ln-confirm/README.md +69 -18
  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 -171
  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/_ln-confirm.scss +0 -24
  414. package/js/ln-confirm/ln-confirm.js +0 -1
  415. package/js/ln-core/crypto.js +0 -83
  416. package/js/ln-core/helpers.js +0 -788
  417. package/js/ln-core/index.js +0 -7
  418. package/js/ln-core/persist.js +0 -97
  419. package/js/ln-couchdb-connector/ln-couchdb-connector.js +0 -1
  420. package/js/ln-data-coordinator/ln-data-coordinator.js +0 -1
  421. package/js/ln-data-coordinator/src/data-read-policy.js +0 -18
  422. package/js/ln-data-store/ln-data-store.js +0 -1
  423. package/js/ln-date/ln-date.js +0 -1
  424. package/js/ln-date/src/ln-date.js +0 -603
  425. package/js/ln-debug/README.md +0 -58
  426. package/js/ln-debug/ln-debug.js +0 -1
  427. package/js/ln-debug/src/ln-debug.js +0 -19
  428. package/js/ln-dropdown/ln-dropdown.js +0 -1
  429. package/js/ln-dropdown/ln-dropdown.scss +0 -15
  430. package/js/ln-editor/ln-editor.js +0 -1
  431. package/js/ln-editor/ln-editor.scss +0 -43
  432. package/js/ln-external-links/ln-external-links.js +0 -1
  433. package/js/ln-fill/ln-fill.js +0 -1
  434. package/js/ln-filter/README.md +0 -189
  435. package/js/ln-filter/ln-filter-dev.scss +0 -8
  436. package/js/ln-filter/ln-filter.js +0 -1
  437. package/js/ln-filter/src/ln-filter.js +0 -419
  438. package/js/ln-form/ln-form.js +0 -1
  439. package/js/ln-http/ln-http.js +0 -1
  440. package/js/ln-link/ln-link.js +0 -1
  441. package/js/ln-list/README.md +0 -129
  442. package/js/ln-list/ln-list.js +0 -1
  443. package/js/ln-list/ln-list.scss +0 -28
  444. package/js/ln-modal/ln-modal-dev.scss +0 -13
  445. package/js/ln-modal/ln-modal.js +0 -1
  446. package/js/ln-modal/ln-modal.scss +0 -35
  447. package/js/ln-modal-coordinator/README.md +0 -99
  448. package/js/ln-modal-coordinator/ln-modal-coordinator-dev.scss +0 -8
  449. package/js/ln-modal-coordinator/ln-modal-coordinator.js +0 -1
  450. package/js/ln-nav/ln-nav.js +0 -1
  451. package/js/ln-number/README.md +0 -149
  452. package/js/ln-number/ln-number.js +0 -1
  453. package/js/ln-number/src/ln-number.js +0 -443
  454. package/js/ln-options/ln-options.js +0 -1
  455. package/js/ln-popover/ln-popover.js +0 -1
  456. package/js/ln-progress/ln-progress.js +0 -1
  457. package/js/ln-progress/src/ln-progress.js +0 -98
  458. package/js/ln-router/ln-router.js +0 -1
  459. package/js/ln-search/README.md +0 -158
  460. package/js/ln-search/ln-search-dev.scss +0 -8
  461. package/js/ln-search/ln-search.js +0 -1
  462. package/js/ln-search/src/ln-search.js +0 -117
  463. package/js/ln-slug/ln-slug.js +0 -1
  464. package/js/ln-sort/ln-sort.js +0 -1
  465. package/js/ln-sort/src/ln-sort.js +0 -178
  466. package/js/ln-sortable/ln-sortable.js +0 -1
  467. package/js/ln-stat/ln-stat.js +0 -1
  468. package/js/ln-table/ln-table.js +0 -1
  469. package/js/ln-table/ln-table.scss +0 -11
  470. package/js/ln-table-coordinator/README.md +0 -73
  471. package/js/ln-table-coordinator/ln-table-coordinator.js +0 -1
  472. package/js/ln-table-coordinator/src/ln-table-coordinator.js +0 -160
  473. package/js/ln-tabs/ln-tabs-dev.scss +0 -18
  474. package/js/ln-tabs/ln-tabs.js +0 -1
  475. package/js/ln-tabs/src/ln-tabs.js +0 -188
  476. package/js/ln-time/ln-time.js +0 -1
  477. package/js/ln-toast/ln-toast.js +0 -1
  478. package/js/ln-toggle/ln-toggle.js +0 -1
  479. package/js/ln-tooltip/ln-tooltip.js +0 -1
  480. package/js/ln-tooltip/ln-tooltip.scss +0 -9
  481. package/js/ln-translations/ln-translations.js +0 -1
  482. package/js/ln-upload/README.md +0 -255
  483. package/js/ln-upload/ln-upload.js +0 -1
  484. package/js/ln-upload/ln-upload.scss +0 -20
  485. package/js/ln-upload/src/ln-upload.js +0 -423
  486. package/js/ln-validate/ln-validate.js +0 -1
  487. package/scss/components/_button.scss +0 -20
  488. package/scss/components/_confirm.scss +0 -5
  489. package/scss/components/_form.scss +0 -107
  490. package/scss/components/_status-badge.scss +0 -4
  491. package/scss/components/_toast.scss +0 -68
  492. package/scss/components/_upload.scss +0 -51
  493. package/scss/config/_theme.scss +0 -216
  494. package/scss/config/mixins/_btn.scss +0 -179
  495. package/scss/config/mixins/_confirm.scss +0 -31
  496. package/scss/config/mixins/_dropdown.scss +0 -141
  497. package/scss/config/mixins/_popover.scss +0 -64
  498. package/scss/ln-ashlar-dev.scss +0 -39
  499. /package/{js → components}/ln-core/positioning.js +0 -0
  500. /package/{js → components}/ln-core/reactive.js +0 -0
  501. /package/{js → components}/ln-filter/ln-filter.scss +0 -0
  502. /package/{js → components}/ln-icon/ln-icon.js +0 -0
  503. /package/{js → components}/ln-icon/src/ln-icon.js +0 -0
  504. /package/{js → components}/ln-search/ln-search.scss +0 -0
  505. /package/{js → components}/ln-toast/template.html +0 -0
  506. /package/{scss → theme}/components/_accordion.scss +0 -0
  507. /package/{scss → theme}/components/_ajax.scss +0 -0
  508. /package/{scss → theme}/components/_alert.scss +0 -0
  509. /package/{scss → theme}/components/_avatar.scss +0 -0
  510. /package/{scss → theme}/components/_breadcrumbs.scss +0 -0
  511. /package/{scss → theme}/components/_card.scss +0 -0
  512. /package/{scss → theme}/components/_chip.scss +0 -0
  513. /package/{scss → theme}/components/_circular-progress.scss +0 -0
  514. /package/{scss → theme}/components/_editor.scss +0 -0
  515. /package/{scss → theme}/components/_empty-state.scss +0 -0
  516. /package/{scss → theme}/components/_filter.scss +0 -0
  517. /package/{scss → theme}/components/_link.scss +0 -0
  518. /package/{scss → theme}/components/_loader.scss +0 -0
  519. /package/{scss → theme}/components/_modal.scss +0 -0
  520. /package/{scss → theme}/components/_nav.scss +0 -0
  521. /package/{scss → theme}/components/_page-header.scss +0 -0
  522. /package/{scss → theme}/components/_popover.scss +0 -0
  523. /package/{scss → theme}/components/_progress.scss +0 -0
  524. /package/{scss → theme}/components/_prose.scss +0 -0
  525. /package/{scss → theme}/components/_scrollbar.scss +0 -0
  526. /package/{scss → theme}/components/_sections.scss +0 -0
  527. /package/{scss → theme}/components/_sidebar.scss +0 -0
  528. /package/{scss → theme}/components/_stat-card.scss +0 -0
  529. /package/{scss → theme}/components/_stepper.scss +0 -0
  530. /package/{scss → theme}/components/_timeline.scss +0 -0
  531. /package/{scss → theme}/components/_tooltip.scss +0 -0
  532. /package/{scss → theme}/components/_translations.scss +0 -0
  533. /package/{scss → theme}/config/_icons.scss +0 -0
  534. /package/{scss → theme}/config/_mixins.scss +0 -0
  535. /package/{scss → theme}/config/mixins/_ajax.scss +0 -0
  536. /package/{scss → theme}/config/mixins/_avatar.scss +0 -0
  537. /package/{scss → theme}/config/mixins/_breadcrumbs.scss +0 -0
  538. /package/{scss → theme}/config/mixins/_breakpoints.scss +0 -0
  539. /package/{scss → theme}/config/mixins/_chip.scss +0 -0
  540. /package/{scss → theme}/config/mixins/_circular-progress.scss +0 -0
  541. /package/{scss → theme}/config/mixins/_display.scss +0 -0
  542. /package/{scss → theme}/config/mixins/_empty-state.scss +0 -0
  543. /package/{scss → theme}/config/mixins/_focus.scss +0 -0
  544. /package/{scss → theme}/config/mixins/_interaction.scss +0 -0
  545. /package/{scss → theme}/config/mixins/_kbd.scss +0 -0
  546. /package/{scss → theme}/config/mixins/_link.scss +0 -0
  547. /package/{scss → theme}/config/mixins/_page-header.scss +0 -0
  548. /package/{scss → theme}/config/mixins/_position.scss +0 -0
  549. /package/{scss → theme}/config/mixins/_progress.scss +0 -0
  550. /package/{scss → theme}/config/mixins/_prose.scss +0 -0
  551. /package/{scss → theme}/config/mixins/_shadows.scss +0 -0
  552. /package/{scss → theme}/config/mixins/_sizing.scss +0 -0
  553. /package/{scss → theme}/config/mixins/_spacing.scss +0 -0
  554. /package/{scss → theme}/config/mixins/_stat-card.scss +0 -0
  555. /package/{scss → theme}/config/mixins/_stepper.scss +0 -0
  556. /package/{scss → theme}/config/mixins/_timeline.scss +0 -0
  557. /package/{scss → theme}/config/mixins/_transitions.scss +0 -0
  558. /package/{scss → theme}/config/mixins/_translations.scss +0 -0
  559. /package/{scss → theme}/tabler-icons.txt +0 -0
@@ -1,419 +0,0 @@
1
- import { dispatch, fillTemplate, registerComponent } from '../../ln-core';
2
- import { createBatcher } from '../../ln-core';
3
- import { persistGet, persistSet } from '../../ln-core';
4
-
5
- (function () {
6
- const DOM_SELECTOR = 'data-ln-filter';
7
- const DOM_ATTRIBUTE = 'lnFilter';
8
- const KEY_ATTR = 'data-ln-filter-key';
9
- const VALUE_ATTR = 'data-ln-filter-value';
10
- const HIDE_ATTR = 'data-ln-filter-hide';
11
- const RESET_ATTR = 'data-ln-filter-reset';
12
- const COL_ATTR = 'data-ln-filter-col';
13
-
14
- // Shared column filter state per table (AND across columns, OR within column)
15
- const _tableFilters = new WeakMap();
16
-
17
- if (window[DOM_ATTRIBUTE] !== undefined) return;
18
-
19
- function _isReset(input) {
20
- return input.hasAttribute(RESET_ATTR) || input.getAttribute(VALUE_ATTR) === '';
21
- }
22
-
23
- function _deriveActive(self) {
24
- let key = self._filterKey;
25
- const values = [];
26
- for (let i = 0; i < self.inputs.length; i++) {
27
- const input = self.inputs[i];
28
- if (input.checked && !_isReset(input)) {
29
- const v = input.getAttribute(VALUE_ATTR);
30
- if (v) values.push(v);
31
- }
32
- }
33
- return { key: key, values: values };
34
- }
35
-
36
- function _arraysDiffer(a, b) {
37
- if (a.length !== b.length) return true;
38
- for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return true;
39
- return false;
40
- }
41
-
42
- // ─── Auto-populate from table column ───────────────────────
43
-
44
- function _populateFromColumn(instance) {
45
- const dom = instance.dom;
46
- const colIndex = instance.colIndex;
47
- const tmpl = dom.querySelector('template');
48
- if (!tmpl || colIndex === null) return;
49
-
50
- const target = document.getElementById(instance.targetId);
51
- if (!target) return;
52
-
53
- const table = target.tagName === 'TABLE' ? target : target.querySelector('table');
54
- if (!table || target.hasAttribute('data-ln-table')) return;
55
-
56
- // Collect unique values from column
57
- const seen = {};
58
- const values = [];
59
- const bodies = table.tBodies;
60
- for (let b = 0; b < bodies.length; b++) {
61
- const rows = bodies[b].rows;
62
- for (let r = 0; r < rows.length; r++) {
63
- const cell = rows[r].cells[colIndex];
64
- const text = cell ? cell.textContent.trim() : '';
65
- if (text && !seen[text]) {
66
- seen[text] = true;
67
- values.push(text);
68
- }
69
- }
70
- }
71
- values.sort(function (a, b) {
72
- return a.localeCompare(b);
73
- });
74
-
75
- // Determine the filter key from existing inputs or dom attribute
76
- const existingInput = dom.querySelector('[' + KEY_ATTR + ']');
77
- const filterKey = existingInput
78
- ? existingInput.getAttribute(KEY_ATTR)
79
- : (dom.getAttribute('data-ln-filter-key') || 'col' + colIndex);
80
-
81
- // Clone template for each value
82
- for (let i = 0; i < values.length; i++) {
83
- const clone = tmpl.content.cloneNode(true);
84
- const input = clone.querySelector('input');
85
- if (!input) continue;
86
- input.setAttribute(KEY_ATTR, filterKey);
87
- input.setAttribute(VALUE_ATTR, values[i]);
88
- fillTemplate(clone, { text: values[i] });
89
- dom.appendChild(clone);
90
- }
91
- }
92
-
93
- // ─── Component ─────────────────────────────────────────────
94
-
95
- function _component(dom) {
96
- this.dom = dom;
97
- this.targetId = dom.getAttribute(DOM_SELECTOR);
98
-
99
- // Column index for table filtering (null = not a table column filter)
100
- const colAttr = dom.getAttribute(COL_ATTR);
101
- this.colIndex = colAttr !== null ? parseInt(colAttr, 10) : null;
102
-
103
- // Auto-populate from table column if template present
104
- _populateFromColumn(this);
105
-
106
- // Collect inputs AFTER auto-populate (new inputs may have been added)
107
- this.inputs = Array.from(dom.querySelectorAll('[' + KEY_ATTR + ']'));
108
- this._filterKey = this.inputs.length > 0 ? this.inputs[0].getAttribute(KEY_ATTR) : null;
109
-
110
- // Event-diff cache — null means never dispatched yet
111
- this._lastSnapshot = null;
112
-
113
- const self = this;
114
-
115
- const queueRender = createBatcher(
116
- function () { self._render(); },
117
- function () { self._afterRender(); }
118
- );
119
-
120
- // Stash for use in change handler
121
- this._queueRender = queueRender;
122
-
123
- this._attachHandlers();
124
-
125
- // ─── Restore persisted filter ─────────────────────────────
126
- let _persistRestored = false;
127
- if (dom.hasAttribute('data-ln-persist')) {
128
- const saved = persistGet('filter', dom);
129
- if (saved && saved.key && Array.isArray(saved.values) && saved.values.length > 0) {
130
- // Write input.checked on matching inputs
131
- for (let i = 0; i < this.inputs.length; i++) {
132
- const input = this.inputs[i];
133
- if (_isReset(input)) {
134
- input.checked = false;
135
- } else if (input.getAttribute(KEY_ATTR) === saved.key &&
136
- saved.values.indexOf(input.getAttribute(VALUE_ATTR)) !== -1) {
137
- input.checked = true;
138
- } else {
139
- input.checked = false;
140
- }
141
- }
142
- queueRender();
143
- _persistRestored = true;
144
- }
145
- }
146
-
147
- if (!_persistRestored) {
148
- // DOM is already canonical — only schedule render if anything is pre-checked
149
- // so visibility is applied and the initial ln-filter:changed fires (via
150
- // null-snapshot diff in _afterRender).
151
- for (let i = 0; i < this.inputs.length; i++) {
152
- if (this.inputs[i].checked && !_isReset(this.inputs[i])) {
153
- queueRender();
154
- break;
155
- }
156
- }
157
- }
158
-
159
- return this;
160
- }
161
-
162
- // ─── Handlers ──────────────────────────────────────────────
163
-
164
- _component.prototype._attachHandlers = function () {
165
- const self = this;
166
-
167
- this.inputs.forEach(function (input) {
168
- if (input[DOM_ATTRIBUTE + 'Bound']) return;
169
- input[DOM_ATTRIBUTE + 'Bound'] = true;
170
-
171
- input._lnFilterChange = function () {
172
- if (_isReset(input)) {
173
- // Reset sentinel — regardless of direction, enforce checked + clear values
174
- for (let i = 0; i < self.inputs.length; i++) {
175
- if (!_isReset(self.inputs[i])) self.inputs[i].checked = false;
176
- }
177
- // Force sentinel back to checked (clicking an already-checked sentinel
178
- // would natively uncheck it; force back to checked)
179
- input.checked = true;
180
- self._queueRender();
181
- return;
182
- }
183
-
184
- if (input.checked) {
185
- // Mutual exclusion: uncheck all reset sentinels
186
- for (let i = 0; i < self.inputs.length; i++) {
187
- if (_isReset(self.inputs[i])) self.inputs[i].checked = false;
188
- }
189
- // If all non-reset inputs are now checked → collapse to sentinel
190
- // (only when a reset sentinel exists; lists without one skip this)
191
- let hasReset = false;
192
- for (let ri = 0; ri < self.inputs.length; ri++) {
193
- if (_isReset(self.inputs[ri])) { hasReset = true; break; }
194
- }
195
- if (hasReset) {
196
- let allChecked = true;
197
- for (let ci = 0; ci < self.inputs.length; ci++) {
198
- if (!_isReset(self.inputs[ci]) && !self.inputs[ci].checked) {
199
- allChecked = false;
200
- break;
201
- }
202
- }
203
- if (allChecked) {
204
- for (let mi = 0; mi < self.inputs.length; mi++) {
205
- if (_isReset(self.inputs[mi])) self.inputs[mi].checked = true;
206
- else self.inputs[mi].checked = false;
207
- }
208
- }
209
- }
210
- } else {
211
- // If no non-reset values remain checked, fall back to reset
212
- let anyChecked = false;
213
- for (let i = 0; i < self.inputs.length; i++) {
214
- if (!_isReset(self.inputs[i]) && self.inputs[i].checked) {
215
- anyChecked = true;
216
- break;
217
- }
218
- }
219
- if (!anyChecked) {
220
- for (let i = 0; i < self.inputs.length; i++) {
221
- if (_isReset(self.inputs[i])) self.inputs[i].checked = true;
222
- }
223
- }
224
- }
225
-
226
- self._queueRender();
227
- };
228
- input.addEventListener('change', input._lnFilterChange);
229
- });
230
- };
231
-
232
- // ─── Render ────────────────────────────────────────────────
233
-
234
- _component.prototype._render = function () {
235
- const self = this;
236
- const active = _deriveActive(this);
237
- const isReset = active.key === null || active.values.length === 0;
238
-
239
- // Build lowercase lookup for target filtering
240
- const lowerValues = [];
241
- for (let i = 0; i < active.values.length; i++) {
242
- lowerValues.push(active.values[i].toLowerCase());
243
- }
244
-
245
- // Apply filter
246
- if (self.colIndex !== null) {
247
- // Table column filtering — shared multi-column logic
248
- self._filterTableRows(active);
249
- } else {
250
- // Standard target-children filtering by data attribute
251
- const target = document.getElementById(self.targetId);
252
- if (!target) return;
253
-
254
- const children = target.children;
255
- for (let i = 0; i < children.length; i++) {
256
- const el = children[i];
257
-
258
- if (isReset) {
259
- el.removeAttribute(HIDE_ATTR);
260
- continue;
261
- }
262
-
263
- const attr = el.getAttribute('data-' + active.key);
264
- el.removeAttribute(HIDE_ATTR);
265
-
266
- if (attr === null) continue;
267
-
268
- // OR logic: visible if attr matches ANY active value
269
- if (lowerValues.indexOf(attr.toLowerCase()) === -1) {
270
- el.setAttribute(HIDE_ATTR, 'true');
271
- }
272
- }
273
- }
274
- };
275
-
276
- _component.prototype._afterRender = function () {
277
- const active = _deriveActive(this);
278
- const prev = this._lastSnapshot;
279
- const changed = !prev
280
- || prev.key !== active.key
281
- || _arraysDiffer(prev.values, active.values);
282
-
283
- if (changed) {
284
- // ln-filter:changed always fires when state moves
285
- this._dispatchOnBoth('ln-filter:changed', {
286
- key: active.key,
287
- values: active.values.slice()
288
- });
289
-
290
- // ln-filter:reset fires only on transition into reset state
291
- const wasActive = prev && prev.values.length > 0;
292
- const nowReset = active.values.length === 0;
293
- if (wasActive && nowReset) {
294
- this._dispatchOnBoth('ln-filter:reset', {});
295
- }
296
-
297
- this._lastSnapshot = { key: active.key, values: active.values.slice() };
298
- }
299
-
300
- // Persist current filter state
301
- if (this.dom.hasAttribute('data-ln-persist')) {
302
- if (active.key && active.values.length > 0) {
303
- persistSet('filter', this.dom, { key: active.key, values: active.values.slice() });
304
- } else {
305
- persistSet('filter', this.dom, null);
306
- }
307
- }
308
- };
309
-
310
- _component.prototype._dispatchOnBoth = function (eventName, detail) {
311
- dispatch(this.dom, eventName, detail);
312
- const target = document.getElementById(this.targetId);
313
- if (target && target !== this.dom) {
314
- dispatch(target, eventName, detail);
315
- }
316
- };
317
-
318
- // ─── Table Row Filtering ───────────────────────────────────
319
-
320
- _component.prototype._filterTableRows = function (active) {
321
- const target = document.getElementById(this.targetId);
322
- if (!target) return;
323
-
324
- const table = target.tagName === 'TABLE' ? target : target.querySelector('table');
325
- if (!table) return;
326
-
327
- // Guard: don't filter if this is an ln-table (it handles its own filtering)
328
- if (target.hasAttribute('data-ln-table')) return;
329
-
330
- const key = active.key || this._filterKey;
331
- const values = active.values;
332
-
333
- // Get or create shared filter map for this table
334
- if (!_tableFilters.has(table)) {
335
- _tableFilters.set(table, {});
336
- }
337
- const filters = _tableFilters.get(table);
338
-
339
- // Update this filter's entry
340
- if (key && values.length > 0) {
341
- const lower = [];
342
- for (let i = 0; i < values.length; i++) {
343
- lower.push(values[i].toLowerCase());
344
- }
345
- filters[key] = { col: this.colIndex, values: lower };
346
- } else if (key) {
347
- delete filters[key];
348
- }
349
-
350
- // Check if any column filters are active
351
- const filterKeys = Object.keys(filters);
352
- const hasFilters = filterKeys.length > 0;
353
-
354
- // Apply all active filters to all rows (AND across columns, OR within column)
355
- const bodies = table.tBodies;
356
- for (let b = 0; b < bodies.length; b++) {
357
- const rows = bodies[b].rows;
358
- for (let r = 0; r < rows.length; r++) {
359
- const row = rows[r];
360
-
361
- if (!hasFilters) {
362
- row.removeAttribute(HIDE_ATTR);
363
- continue;
364
- }
365
-
366
- let visible = true;
367
- for (let f = 0; f < filterKeys.length; f++) {
368
- const filter = filters[filterKeys[f]];
369
- const cell = row.cells[filter.col];
370
- const cellText = cell ? cell.textContent.trim().toLowerCase() : '';
371
- // OR within column: visible if cell text matches ANY filter value
372
- if (filter.values.indexOf(cellText) === -1) {
373
- visible = false;
374
- break; // AND across columns: fail fast
375
- }
376
- }
377
-
378
- if (visible) {
379
- row.removeAttribute(HIDE_ATTR);
380
- } else {
381
- row.setAttribute(HIDE_ATTR, 'true');
382
- }
383
- }
384
- }
385
- };
386
-
387
- // ─── Destroy ───────────────────────────────────────────────
388
-
389
- _component.prototype.destroy = function () {
390
- if (!this.dom[DOM_ATTRIBUTE]) return;
391
-
392
- // Clean up table filter registry
393
- if (this.colIndex !== null) {
394
- const target = document.getElementById(this.targetId);
395
- if (target) {
396
- const table = target.tagName === 'TABLE' ? target : target.querySelector('table');
397
- if (table && _tableFilters.has(table)) {
398
- const filters = _tableFilters.get(table);
399
- const key = this._filterKey;
400
- if (key && filters[key]) delete filters[key];
401
- if (Object.keys(filters).length === 0) _tableFilters.delete(table);
402
- }
403
- }
404
- }
405
-
406
- this.inputs.forEach(function (input) {
407
- if (input._lnFilterChange) {
408
- input.removeEventListener('change', input._lnFilterChange);
409
- delete input._lnFilterChange;
410
- }
411
- delete input[DOM_ATTRIBUTE + 'Bound'];
412
- });
413
- delete this.dom[DOM_ATTRIBUTE];
414
- };
415
-
416
- // ─── Init ──────────────────────────────────────────────────
417
-
418
- registerComponent(DOM_SELECTOR, DOM_ATTRIBUTE, _component, 'ln-filter');
419
- })();
@@ -1 +0,0 @@
1
- (function(){"use strict";if(typeof window<"u"){const t=console.warn;console.warn=function(...e){typeof e[0]=="string"&&(e[0].startsWith("[ln-")||e[0].startsWith("[lnCore"))&&!(document.documentElement.hasAttribute("data-ln-debug")||document.body&&document.body.hasAttribute("data-ln-debug"))||t.apply(console,e)}}const y={};function M(t,e){y[t]||(y[t]=document.querySelector('[data-ln-template="'+t+'"]'));const s=y[t];return s?s.content.cloneNode(!0):(console.warn("["+(e||"ln-core")+'] Template "'+t+'" not found'),null)}function D(t,e,s){t.dispatchEvent(new CustomEvent(e,{bubbles:!0,detail:s||{}}))}function v(t,e){if(!t||!e)return t;const s=t.querySelectorAll("[data-ln-field]");for(let n=0;n<s.length;n++){const i=s[n],l=i.getAttribute("data-ln-field");e[l]!=null&&(i.textContent=e[l])}const d=t.querySelectorAll("[data-ln-attr]");for(let n=0;n<d.length;n++){const i=d[n],l=i.getAttribute("data-ln-attr").split(",");for(let r=0;r<l.length;r++){const u=l[r].trim().split(":");if(u.length!==2)continue;const a=u[0].trim(),f=u[1].trim();e[f]!=null&&i.setAttribute(a,e[f])}}const c=t.querySelectorAll("[data-ln-show]");for(let n=0;n<c.length;n++){const i=c[n],l=i.getAttribute("data-ln-show");l in e&&i.classList.toggle("hidden",!e[l])}const o=t.querySelectorAll("[data-ln-class]");for(let n=0;n<o.length;n++){const i=o[n],l=i.getAttribute("data-ln-class").split(",");for(let r=0;r<l.length;r++){const u=l[r].trim().split(":");if(u.length!==2)continue;const a=u[0].trim(),f=u[1].trim();f in e&&i.classList.toggle(a,!!e[f])}}return t}function q(t,e){t.matches&&t.matches("[data-ln-form], [data-ln-fillable]")&&t.dispatchEvent(new CustomEvent("ln-fill",{detail:e??null,bubbles:!0}));const s=t.querySelectorAll("[data-ln-form], [data-ln-fillable]");for(let d=0;d<s.length;d++)s[d].dispatchEvent(new CustomEvent("ln-fill",{detail:e??null,bubbles:!0}));return t}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._fillBound||(window.lnCore._fillBound=!0,document.addEventListener("ln-fill",function(t){if(!(!t.target.matches||!t.target.matches("[data-ln-fillable]")))if(t.detail)v(t.target,t.detail);else{const e=t.target.querySelectorAll("[data-ln-field]");for(let s=0;s<e.length;s++)e[s].textContent=""}})));function x(t,e){if(!t||!e)return t;const s=document.createTreeWalker(t,NodeFilter.SHOW_TEXT);for(;s.nextNode();){const o=s.currentNode;o.textContent.indexOf("{{")!==-1&&(o.textContent=o.textContent.replace(/\{\{\s*(\w+)\s*\}\}/g,function(n,i){return e[i]!==void 0?e[i]:""}))}const d=function(o,n){return e[n]!==void 0?e[n]:""},c=Array.from(t.querySelectorAll("*"));t.nodeType===1&&c.push(t);for(let o=0;o<c.length;o++){const n=c[o],i=n.attributes;for(let l=0;l<i.length;l++){const r=i[l];r.value.indexOf("{{")!==-1&&n.setAttribute(r.name,r.value.replace(/\{\{\s*(\w+)\s*\}\}/g,d))}}return t}function I(t,e,s,d,c,o){const n={};for(let l=0;l<t.children.length;l++){const r=t.children[l],u=r.getAttribute("data-ln-key");u&&(n[u]=r)}const i=document.createDocumentFragment();for(let l=0;l<e.length;l++){const r=e[l],u=String(d(r));let a=n[u];if(a)c(a,r,l);else{const f=M(s,o);if(!f||(x(f,r),a=f.firstElementChild,!a))continue;a.setAttribute("data-ln-key",u),c(a,r,l)}i.appendChild(a)}t.textContent="",t.appendChild(i)}function _(t,e){if(!document.body){document.addEventListener("DOMContentLoaded",function(){_(t,e)}),console.warn("["+e+'] Script loaded before <body> — add "defer" to your <script> tag');return}t()}function g(t,e,s,d){if(t.nodeType!==1)return;const o=e.indexOf("[")!==-1||e.indexOf(".")!==-1||e.indexOf("#")!==-1?e:"["+e+"]",n=Array.from(t.querySelectorAll(o));t.matches&&t.matches(o)&&n.push(t);for(const i of n)i[s]||(i[s]=new d(i))}function N(t){if(typeof t!="string")return!!t;const e=t.trim().toLowerCase();return e!=="false"&&e!=="0"&&e!==""&&e!=="off"&&e!=="no"}function F(t,e){const s=t.elements,d=[],c={};for(let o=0;o<s.length;o++){const n=s[o];n.name&&n.type==="checkbox"&&(c[n.name]=(c[n.name]||0)+1)}for(let o=0;o<s.length;o++){const n=s[o];if(n.type==="file"||n.type==="submit"||n.type==="button")continue;const i=n.getAttribute("data-ln-fill-as")||n.name;if(!i||!(i in e))continue;const l=e[i];if(n.type==="checkbox"){if(Array.isArray(l))n.checked=l.indexOf(n.value)!==-1;else if(c[n.name]>1){const r=String(l).split(",").map(function(u){return u.trim()});n.checked=r.indexOf(n.value)!==-1}else n.checked=N(l);d.push(n)}else if(n.type==="radio")n.checked=n.value===String(l),d.push(n);else if(n.type==="select-multiple"){if(Array.isArray(l))for(let r=0;r<n.options.length;r++)n.options[r].selected=l.indexOf(n.options[r].value)!==-1;d.push(n)}else n.value=l,d.push(n)}return d}function R(t,e,s,d,c={}){const o=c.extraAttributes||[],n=c.onAttributeChange||null,i=c.onInit||null;function l(r){const u=r||document.body;g(u,t,e,s),i&&i(u)}return _(function(){const r=new MutationObserver(function(a){for(let f=0;f<a.length;f++){const h=a[f];if(h.type==="childList"){for(let m=0;m<h.addedNodes.length;m++){const p=h.addedNodes[m];p.nodeType===1&&(g(p,t,e,s),i&&i(p))}for(let m=0;m<h.removedNodes.length;m++){const p=h.removedNodes[m];if(p.nodeType===1){const O=t.indexOf("[")!==-1||t.indexOf(".")!==-1||t.indexOf("#")!==-1?t:"["+t+"]",b=Array.from(p.querySelectorAll(O));p.matches&&p.matches(O)&&b.push(p);for(let C=0;C<b.length;C++){const S=b[C];if(!document.contains(S)){const A=S[e];A&&typeof A.destroy=="function"&&A.destroy()}}}}}else h.type==="attributes"&&(n&&h.target[e]?n(h.target,h.attributeName):(g(h.target,t,e,s),i&&i(h.target)))}});let u=[];if(t.indexOf("[")!==-1){const a=/\[([\w-]+)/g;let f;for(;(f=a.exec(t))!==null;)u.push(f[1])}else u.push(t);r.observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:u.concat(o)})},d),window[e]=l,document.readyState==="loading"?document.addEventListener("DOMContentLoaded",function(){l(document.body)}):l(document.body),l}const L={};function j(t,e){L[t]=e}function B(t){return L[t]||{ingress:e=>e,egress:e=>e}}const E={};function k(t,e){if(!t||typeof e!="object")return;const s=t.toLowerCase().split("-")[0];E[s]=e}function W(t){if(!t)return null;const e=t.toLowerCase().split("-")[0];return E[e]||null}k("mk",{monthsLong:["јануари","февруари","март","април","мај","јуни","јули","август","септември","октомври","ноември","декември"],monthsShort:["јан","фев","мар","апр","мај","јун","јул","авг","септ","окт","ноем","дек"],daysLong:["недела","понеделник","вторник","среда","четврток","петок","сабота"],daysShort:["нед","пон","вт","ср","чет","пет","саб"]}),typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerDataMapper=j,window.lnCore.getDataMapper=B,window.lnCore.registerLocaleFallback=k,window.lnCore.getLocaleFallback=W,window.lnCore.fillTemplate=x,window.lnCore.fill=v,window.lnCore.lnFill=q,window.lnCore.renderList=I);function T(t){return(t||"").replace(/^#/,"")}function w(t){const e=t===void 0?location.hash:t,s={},d=T(e);if(!d)return s;const c=d.split("&");for(let o=0;o<c.length;o++){const n=c[o];if(!n)continue;const i=n.indexOf(":"),l=i>-1?n.slice(0,i):n,r=i>-1?n.slice(i+1):"";if(l)try{s[l]=decodeURIComponent(r)}catch{s[l]=r}}return s}function U(t){if(!t)return null;const e=w();return t in e?e[t]:null}function K(t,e){if(!t)return;const s=w();e==null?delete s[t]:s[t]=String(e);const c=Object.keys(s).map(function(o){const n=s[o];return n===""?o:o+":"+encodeURIComponent(n)}).join("&");T(location.hash)!==c&&(location.hash=c)}function G(t){return t.button===1||t.ctrlKey||t.metaKey||t.shiftKey?!1:(t.preventDefault(),!0)}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.hashParse=w,window.lnCore.hashGet=U,window.lnCore.hashSet=K,window.lnCore.hashLinkClick=G),(function(){const t="data-ln-form",e="lnForm",s="data-ln-form-action-edit",d="data-ln-form-action-method";if(window[e]!==void 0)return;function c(o){this.dom=o,this._baseAction=o.getAttribute("action")||"";const n=this;return this._onLnFill=function(i){i.target===n.dom&&(i.detail?(n.fill(i.detail),n._applyActionMode(i.detail)):n.dom.reset())},this._onReset=function(){n._applyActionMode(null)},o.addEventListener("ln-fill",this._onLnFill),o.addEventListener("reset",this._onReset),this}c.prototype.fill=function(o){const n=F(this.dom,o);for(let i=0;i<n.length;i++){const l=n[i],r=l.tagName==="SELECT"||l.type==="checkbox"||l.type==="radio";l.dispatchEvent(new Event(r?"change":"input",{bubbles:!0}))}},c.prototype._ensureMethodInput=function(){let o=this.dom.querySelector('input[name="_method"]');return o||(o=document.createElement("input"),o.type="hidden",o.name="_method",o.value="",this.dom.appendChild(o)),o},c.prototype._applyActionMode=function(o){if(!this.dom.hasAttribute(s))return;const n=o&&o.id!=null&&o.id!==""?o.id:null,i=this._ensureMethodInput();if(n!==null){const l=this.dom.getAttribute(s);l?this.dom.setAttribute("action",l.replace(":id",encodeURIComponent(n))):this.dom.setAttribute("action",this._baseAction.replace(/\/$/,"")+"/"+encodeURIComponent(n)),i.value=this.dom.getAttribute(d)||"PUT"}else this.dom.setAttribute("action",this._baseAction),i.value=""},c.prototype.destroy=function(){this.dom[e]&&(this.dom.removeEventListener("ln-fill",this._onLnFill),this.dom.removeEventListener("reset",this._onReset),D(this.dom,"ln-form:destroyed",{target:this.dom}),delete this.dom[e])},R(t,e,c,"ln-form")})()})();
@@ -1 +0,0 @@
1
- (function(){"use strict";if(typeof window<"u"){const t=console.warn;console.warn=function(...n){typeof n[0]=="string"&&(n[0].startsWith("[ln-")||n[0].startsWith("[lnCore"))&&!(document.documentElement.hasAttribute("data-ln-debug")||document.body&&document.body.hasAttribute("data-ln-debug"))||t.apply(console,n)}}const m={};function _(t,n){m[t]||(m[t]=document.querySelector('[data-ln-template="'+t+'"]'));const o=m[t];return o?o.content.cloneNode(!0):(console.warn("["+(n||"ln-core")+'] Template "'+t+'" not found'),null)}function y(t,n,o){t.dispatchEvent(new CustomEvent(n,{bubbles:!0,detail:o||{}}))}function E(t,n){if(!t||!n)return t;const o=t.querySelectorAll("[data-ln-field]");for(let l=0;l<o.length;l++){const c=o[l],r=c.getAttribute("data-ln-field");n[r]!=null&&(c.textContent=n[r])}const u=t.querySelectorAll("[data-ln-attr]");for(let l=0;l<u.length;l++){const c=u[l],r=c.getAttribute("data-ln-attr").split(",");for(let e=0;e<r.length;e++){const i=r[e].trim().split(":");if(i.length!==2)continue;const f=i[0].trim(),s=i[1].trim();n[s]!=null&&c.setAttribute(f,n[s])}}const d=t.querySelectorAll("[data-ln-show]");for(let l=0;l<d.length;l++){const c=d[l],r=c.getAttribute("data-ln-show");r in n&&c.classList.toggle("hidden",!n[r])}const a=t.querySelectorAll("[data-ln-class]");for(let l=0;l<a.length;l++){const c=a[l],r=c.getAttribute("data-ln-class").split(",");for(let e=0;e<r.length;e++){const i=r[e].trim().split(":");if(i.length!==2)continue;const f=i[0].trim(),s=i[1].trim();s in n&&c.classList.toggle(f,!!n[s])}}return t}function x(t,n){t.matches&&t.matches("[data-ln-form], [data-ln-fillable]")&&t.dispatchEvent(new CustomEvent("ln-fill",{detail:n??null,bubbles:!0}));const o=t.querySelectorAll("[data-ln-form], [data-ln-fillable]");for(let u=0;u<o.length;u++)o[u].dispatchEvent(new CustomEvent("ln-fill",{detail:n??null,bubbles:!0}));return t}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._fillBound||(window.lnCore._fillBound=!0,document.addEventListener("ln-fill",function(t){if(!(!t.target.matches||!t.target.matches("[data-ln-fillable]")))if(t.detail)E(t.target,t.detail);else{const n=t.target.querySelectorAll("[data-ln-field]");for(let o=0;o<n.length;o++)n[o].textContent=""}})));function L(t,n){if(!t||!n)return t;const o=document.createTreeWalker(t,NodeFilter.SHOW_TEXT);for(;o.nextNode();){const a=o.currentNode;a.textContent.indexOf("{{")!==-1&&(a.textContent=a.textContent.replace(/\{\{\s*(\w+)\s*\}\}/g,function(l,c){return n[c]!==void 0?n[c]:""}))}const u=function(a,l){return n[l]!==void 0?n[l]:""},d=Array.from(t.querySelectorAll("*"));t.nodeType===1&&d.push(t);for(let a=0;a<d.length;a++){const l=d[a],c=l.attributes;for(let r=0;r<c.length;r++){const e=c[r];e.value.indexOf("{{")!==-1&&l.setAttribute(e.name,e.value.replace(/\{\{\s*(\w+)\s*\}\}/g,u))}}return t}function q(t,n,o,u,d,a){const l={};for(let r=0;r<t.children.length;r++){const e=t.children[r],i=e.getAttribute("data-ln-key");i&&(l[i]=e)}const c=document.createDocumentFragment();for(let r=0;r<n.length;r++){const e=n[r],i=String(u(e));let f=l[i];if(f)d(f,e,r);else{const s=_(o,a);if(!s||(L(s,e),f=s.firstElementChild,!f))continue;f.setAttribute("data-ln-key",i),d(f,e,r)}c.appendChild(f)}t.textContent="",t.appendChild(c)}const A={};function T(t,n){A[t]=n}function F(t){return A[t]||{ingress:n=>n,egress:n=>n}}const k={};function v(t,n){if(!t||typeof n!="object")return;const o=t.toLowerCase().split("-")[0];k[o]=n}function D(t){if(!t)return null;const n=t.toLowerCase().split("-")[0];return k[n]||null}v("mk",{monthsLong:["јануари","февруари","март","април","мај","јуни","јули","август","септември","октомври","ноември","декември"],monthsShort:["јан","фев","мар","апр","мај","јун","јул","авг","септ","окт","ноем","дек"],daysLong:["недела","понеделник","вторник","среда","четврток","петок","сабота"],daysShort:["нед","пон","вт","ср","чет","пет","саб"]}),typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerDataMapper=T,window.lnCore.getDataMapper=F,window.lnCore.registerLocaleFallback=v,window.lnCore.getLocaleFallback=D,window.lnCore.fillTemplate=L,window.lnCore.fill=E,window.lnCore.lnFill=x,window.lnCore.renderList=q);function S(t){return(t||"").replace(/^#/,"")}function C(t){const n=t===void 0?location.hash:t,o={},u=S(n);if(!u)return o;const d=u.split("&");for(let a=0;a<d.length;a++){const l=d[a];if(!l)continue;const c=l.indexOf(":"),r=c>-1?l.slice(0,c):l,e=c>-1?l.slice(c+1):"";if(r)try{o[r]=decodeURIComponent(e)}catch{o[r]=e}}return o}function O(t){if(!t)return null;const n=C();return t in n?n[t]:null}function H(t,n){if(!t)return;const o=C();n==null?delete o[t]:o[t]=String(n);const d=Object.keys(o).map(function(a){const l=o[a];return l===""?a:a+":"+encodeURIComponent(l)}).join("&");S(location.hash)!==d&&(location.hash=d)}function M(t){return t.button===1||t.ctrlKey||t.metaKey||t.shiftKey?!1:(t.preventDefault(),!0)}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.hashParse=C,window.lnCore.hashGet=O,window.lnCore.hashSet=H,window.lnCore.hashLinkClick=M),(function(){if(window.lnHttp)return;const t=window.fetch.bind(window),n=new Map,o=new Map;function u(e){return typeof e=="string"?e:e instanceof URL?e.href:e instanceof Request?e.url:String(e)}function d(e,i){return i&&i.method?String(i.method).toUpperCase():e instanceof Request?e.method.toUpperCase():"GET"}function a(e,i){return i+" "+e}function l(e){return e==="GET"||e==="HEAD"}function c(e,i){i=i||{};const f=u(e),s=d(e,i),w=a(f,s);l(s)&&n.has(w)&&(n.get(w).abort(),n.delete(w));const h=new AbortController,p=i.signal;let b=null;p&&(p.aborted?h.abort(p.reason):(b=function(){h.abort(p.reason)},p.addEventListener("abort",b,{once:!0})));const g=Object.assign({},i,{signal:h.signal});return n.set(w,h),t(e,g).finally(function(){p&&b&&p.removeEventListener("abort",b),n.get(w)===h&&n.delete(w)})}c.toString=function(){return"function fetch() { [ln-http wrapped] }"},window.fetch=c;function r(e){if(!e.detail||!e.detail.url)return;const i=e.target,f=(e.detail.method||(e.detail.body?"POST":"GET")).toUpperCase(),s=e.detail.key;s&&o.has(s)&&(o.get(s).abort(),o.delete(s));const w=new AbortController,h=e.detail.signal;let p=null;h&&(h.aborted?w.abort(h.reason):(p=function(){w.abort(h.reason)},h.addEventListener("abort",p,{once:!0}))),s&&o.set(s,w);const b={method:f,signal:w.signal};e.detail.body!==void 0&&(b.body=e.detail.body),window.fetch(e.detail.url,b).then(function(g){h&&p&&h.removeEventListener("abort",p),s&&o.get(s)===w&&o.delete(s),y(i,"ln-http:response",{ok:g.ok,status:g.status,response:g})}).catch(function(g){h&&p&&h.removeEventListener("abort",p),s&&o.get(s)===w&&o.delete(s),!(g&&g.name==="AbortError")&&y(i,"ln-http:error",{ok:!1,status:0,error:g})})}document.addEventListener("ln-http:request",r),window.lnHttp={cancel:function(e){let i=!1;return n.forEach(function(f,s){s.endsWith(" "+e)&&(f.abort(),n.delete(s),i=!0)}),i},cancelByKey:function(e){return o.has(e)?(o.get(e).abort(),o.delete(e),!0):!1},cancelAll:function(){n.forEach(function(e){e.abort()}),n.clear(),o.forEach(function(e){e.abort()}),o.clear()},get inflight(){const e=[];return n.forEach(function(i,f){const s=f.indexOf(" ");e.push({method:f.slice(0,s),url:f.slice(s+1)})}),o.forEach(function(i,f){e.push({key:f})}),e},destroy:function(){window.lnHttp.cancelAll(),document.removeEventListener("ln-http:request",r),window.fetch=t,delete window.lnHttp}}})()})();
@@ -1 +0,0 @@
1
- (function(){"use strict";if(typeof window<"u"){const t=console.warn;console.warn=function(...e){typeof e[0]=="string"&&(e[0].startsWith("[ln-")||e[0].startsWith("[lnCore"))&&!(document.documentElement.hasAttribute("data-ln-debug")||document.body&&document.body.hasAttribute("data-ln-debug"))||t.apply(console,e)}}const m={};function D(t,e){m[t]||(m[t]=document.querySelector('[data-ln-template="'+t+'"]'));const l=m[t];return l?l.content.cloneNode(!0):(console.warn("["+(e||"ln-core")+'] Template "'+t+'" not found'),null)}function O(t,e,l){const a=new CustomEvent(e,{bubbles:!0,cancelable:!0,detail:l||{}});return t.dispatchEvent(a),a}function L(t,e){if(!t||!e)return t;const l=t.querySelectorAll("[data-ln-field]");for(let i=0;i<l.length;i++){const r=l[i],o=r.getAttribute("data-ln-field");e[o]!=null&&(r.textContent=e[o])}const a=t.querySelectorAll("[data-ln-attr]");for(let i=0;i<a.length;i++){const r=a[i],o=r.getAttribute("data-ln-attr").split(",");for(let s=0;s<o.length;s++){const h=o[s].trim().split(":");if(h.length!==2)continue;const b=h[0].trim(),g=h[1].trim();e[g]!=null&&r.setAttribute(b,e[g])}}const d=t.querySelectorAll("[data-ln-show]");for(let i=0;i<d.length;i++){const r=d[i],o=r.getAttribute("data-ln-show");o in e&&r.classList.toggle("hidden",!e[o])}const c=t.querySelectorAll("[data-ln-class]");for(let i=0;i<c.length;i++){const r=c[i],o=r.getAttribute("data-ln-class").split(",");for(let s=0;s<o.length;s++){const h=o[s].trim().split(":");if(h.length!==2)continue;const b=h[0].trim(),g=h[1].trim();g in e&&r.classList.toggle(b,!!e[g])}}return t}function B(t,e){t.matches&&t.matches("[data-ln-form], [data-ln-fillable]")&&t.dispatchEvent(new CustomEvent("ln-fill",{detail:e??null,bubbles:!0}));const l=t.querySelectorAll("[data-ln-form], [data-ln-fillable]");for(let a=0;a<l.length;a++)l[a].dispatchEvent(new CustomEvent("ln-fill",{detail:e??null,bubbles:!0}));return t}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._fillBound||(window.lnCore._fillBound=!0,document.addEventListener("ln-fill",function(t){if(!(!t.target.matches||!t.target.matches("[data-ln-fillable]")))if(t.detail)L(t.target,t.detail);else{const e=t.target.querySelectorAll("[data-ln-field]");for(let l=0;l<e.length;l++)e[l].textContent=""}})));function k(t,e){if(!t||!e)return t;const l=document.createTreeWalker(t,NodeFilter.SHOW_TEXT);for(;l.nextNode();){const c=l.currentNode;c.textContent.indexOf("{{")!==-1&&(c.textContent=c.textContent.replace(/\{\{\s*(\w+)\s*\}\}/g,function(i,r){return e[r]!==void 0?e[r]:""}))}const a=function(c,i){return e[i]!==void 0?e[i]:""},d=Array.from(t.querySelectorAll("*"));t.nodeType===1&&d.push(t);for(let c=0;c<d.length;c++){const i=d[c],r=i.attributes;for(let o=0;o<r.length;o++){const s=r[o];s.value.indexOf("{{")!==-1&&i.setAttribute(s.name,s.value.replace(/\{\{\s*(\w+)\s*\}\}/g,a))}}return t}function M(t,e,l,a,d,c){const i={};for(let o=0;o<t.children.length;o++){const s=t.children[o],h=s.getAttribute("data-ln-key");h&&(i[h]=s)}const r=document.createDocumentFragment();for(let o=0;o<e.length;o++){const s=e[o],h=String(a(s));let b=i[h];if(b)d(b,s,o);else{const g=D(l,c);if(!g||(k(g,s),b=g.firstElementChild,!b))continue;b.setAttribute("data-ln-key",h),d(b,s,o)}r.appendChild(b)}t.textContent="",t.appendChild(r)}function A(t,e){if(!document.body){document.addEventListener("DOMContentLoaded",function(){A(t,e)}),console.warn("["+e+'] Script loaded before <body> — add "defer" to your <script> tag');return}t()}const v={};function R(t,e){v[t]=e}function N(t){return v[t]||{ingress:e=>e,egress:e=>e}}const _={};function E(t,e){if(!t||typeof e!="object")return;const l=t.toLowerCase().split("-")[0];_[l]=e}function F(t){if(!t)return null;const e=t.toLowerCase().split("-")[0];return _[e]||null}E("mk",{monthsLong:["јануари","февруари","март","април","мај","јуни","јули","август","септември","октомври","ноември","декември"],monthsShort:["јан","фев","мар","апр","мај","јун","јул","авг","септ","окт","ноем","дек"],daysLong:["недела","понеделник","вторник","среда","четврток","петок","сабота"],daysShort:["нед","пон","вт","ср","чет","пет","саб"]}),typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerDataMapper=R,window.lnCore.getDataMapper=N,window.lnCore.registerLocaleFallback=E,window.lnCore.getLocaleFallback=F,window.lnCore.fillTemplate=k,window.lnCore.fill=L,window.lnCore.lnFill=B,window.lnCore.renderList=M);function S(t){return(t||"").replace(/^#/,"")}function y(t){const e=t===void 0?location.hash:t,l={},a=S(e);if(!a)return l;const d=a.split("&");for(let c=0;c<d.length;c++){const i=d[c];if(!i)continue;const r=i.indexOf(":"),o=r>-1?i.slice(0,r):i,s=r>-1?i.slice(r+1):"";if(o)try{l[o]=decodeURIComponent(s)}catch{l[o]=s}}return l}function I(t){if(!t)return null;const e=y();return t in e?e[t]:null}function W(t,e){if(!t)return;const l=y();e==null?delete l[t]:l[t]=String(e);const d=Object.keys(l).map(function(c){const i=l[c];return i===""?c:c+":"+encodeURIComponent(i)}).join("&");S(location.hash)!==d&&(location.hash=d)}function j(t){return t.button===1||t.ctrlKey||t.metaKey||t.shiftKey?!1:(t.preventDefault(),!0)}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.hashParse=y,window.lnCore.hashGet=I,window.lnCore.hashSet=W,window.lnCore.hashLinkClick=j),(function(){const t="data-ln-link",e="lnLink";if(window[e]!==void 0)return;let l=null;function a(){l=document.createElement("div"),l.className="ln-link-status",document.body.appendChild(l)}function d(n){l&&(l.textContent=n,l.classList.add("ln-link-status--visible"))}function c(){l&&l.classList.remove("ln-link-status--visible")}function i(n,f){if(f.target.closest("a, button, input, select, textarea"))return;const u=n.querySelector("a");if(!u)return;const p=u.getAttribute("href");if(!p)return;if(f.ctrlKey||f.metaKey||f.button===1){window.open(p,"_blank");return}O(n,"ln-link:navigate",{target:n,href:p,link:u}).defaultPrevented||u.click()}function r(n){const f=n.querySelector("a");if(!f)return;const u=f.getAttribute("href");u&&d(u)}function o(){c()}function s(n){n[e+"Row"]||!n.querySelector("a")||(n[e+"Row"]=!0,n._lnLinkClick=function(u){i(n,u)},n._lnLinkEnter=function(){r(n)},n.addEventListener("click",n._lnLinkClick),n.addEventListener("mouseenter",n._lnLinkEnter),n.addEventListener("mouseleave",o))}function h(n){n[e+"Row"]&&(n._lnLinkClick&&n.removeEventListener("click",n._lnLinkClick),n._lnLinkEnter&&n.removeEventListener("mouseenter",n._lnLinkEnter),n.removeEventListener("mouseleave",o),delete n._lnLinkClick,delete n._lnLinkEnter,delete n[e+"Row"])}function b(n){if(!n[e+"Init"])return;const f=n.tagName;if(f==="TABLE"||f==="TBODY"){const u=f==="TABLE"&&n.querySelector("tbody")||n;for(const p of u.querySelectorAll("tr"))h(p)}else h(n);delete n[e+"Init"]}function g(n){if(n[e+"Init"])return;n[e+"Init"]=!0;const f=n.tagName;if(f==="TABLE"||f==="TBODY"){const u=f==="TABLE"&&n.querySelector("tbody")||n;for(const p of u.querySelectorAll("tr"))s(p)}else s(n)}function w(n){n.hasAttribute&&n.hasAttribute(t)&&g(n);const f=n.querySelectorAll?n.querySelectorAll("["+t+"]"):[];for(const u of f)g(u)}function K(){A(function(){new MutationObserver(function(f){for(const u of f)if(u.type==="childList"){for(const p of u.addedNodes)if(p.nodeType===1){w(p);const C=p.closest("["+t+"]");if(C)if(p.tagName==="TR")s(p);else{const x=C.tagName;if(x==="TABLE"||x==="TBODY"){const U=p.querySelectorAll?p.querySelectorAll("tr"):[];for(const Y of U)s(Y)}}}}else u.type==="attributes"&&(u.target.hasAttribute&&u.target.hasAttribute(t)?w(u.target):b(u.target))}).observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[t]})},"ln-link")}function T(n){w(n)}window[e]={init:T,destroy:b};function q(){a(),K(),T(document.body)}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",q):q()})()})();
@@ -1,129 +0,0 @@
1
- # ln-list
2
-
3
- A unified, structure-agnostic, and local-first **Data Presenter Component** designed to render datasets in list, card, section, or grid layouts. It connects to `ln-data-store` via CustomEvents using the **Coordinator Pattern**, supporting client-side filtering, sorting, searching, and high-performance **Virtual Scrolling** for large datasets.
4
-
5
- ---
6
-
7
- ## 📦 Declarative Setup in HTML
8
-
9
- ### 1. Simple SSR List
10
- For a server-rendered list where the backend outputs `<li>` elements directly:
11
-
12
- ```html
13
- <form role="search" onsubmit="return false;">
14
- <input type="search" data-ln-search="documents-list" placeholder="Search...">
15
- </form>
16
-
17
- <ul id="documents-list" data-ln-list="documents">
18
- <li data-ln-item-id="1">Document A</li>
19
- <li data-ln-item-id="2">Document B</li>
20
- </ul>
21
- ```
22
-
23
- ### 2. Data-Driven Grid List (with Virtual Scroll)
24
- Opted-in by adding the `data-ln-list-source` attribute. It clones and renders the specified `<template>`:
25
-
26
- ```html
27
- <form role="search" onsubmit="return false;">
28
- <input type="search" data-ln-search="documents-grid" placeholder="Search...">
29
- </form>
30
-
31
- <section id="documents-grid"
32
- data-ln-list="documents"
33
- data-ln-list-source="documents"
34
- data-ln-list-selectable>
35
-
36
- <!-- Items container -->
37
- <ul class="grid-layout" data-ln-list-body></ul>
38
-
39
- <!-- Row Template (Must contain an element with data-ln-item attribute) -->
40
- <template data-ln-template="documents-row">
41
- <li data-ln-item class="card-item">
42
- <header>
43
- <input type="checkbox" data-ln-item-select>
44
- <h3 data-ln-field="title"></h3>
45
- </header>
46
- <p>{{ description }}</p>
47
- <button type="button" data-ln-item-action="delete">Delete</button>
48
- </li>
49
- </template>
50
-
51
- <!-- Empty States -->
52
- <template data-ln-template="documents-empty">
53
- <div class="empty-state">No documents found.</div>
54
- </template>
55
-
56
- <template data-ln-template="documents-empty-filtered">
57
- <div class="empty-state">No matching documents found.</div>
58
- </template>
59
- </section>
60
- ```
61
-
62
- ---
63
-
64
- ## 🛠️ Attributes Reference
65
-
66
- | Attribute | Elements | Description |
67
- | :--- | :--- | :--- |
68
- | `data-ln-list` | Root wrapper | Component identifier. Target must carry a unique `id`. |
69
- | `data-ln-list-source` | Root wrapper | Opt-in indicator for Data-Driven Mode. |
70
- | `data-ln-list-selectable` | Root wrapper | Enables checkbox-based item selections. |
71
- | `data-ln-list-window="N"` | Root wrapper | Opt-in server-side sliding-window virtualization. `N` sets the resident-item cap (default 1000). Requires Data-Driven Mode. Observable: add/remove toggles windowed mode ON/OFF live; changing `N` while windowed reconfigures the live cache. `data-ln-list-window-page`, `data-ln-list-window-threshold`, and `data-ln-list-count` are likewise observable. |
72
-
73
- ---
74
-
75
- ## ⚡ DOM Events
76
-
77
- ### Listened Events
78
-
79
- * `ln-list:set-data` `{ data, total, filtered }`: Hydrates/renders the items. Windowed mode expects `{ offset, queryGen }` echoed back — routed into the internal window cache.
80
- * `ln-list:set-loading` `{ loading: true|false }`: Toggles the loading dimming overlay class (`.ln-list--loading`).
81
- * `ln-list:page-failed` `{ offset }`: Windowed mode — the coordinator reports the page fetch at `offset` failed. Releases it from the cache's in-flight set; no auto-retry, the next `ensure()` requests it again.
82
- * `ln-list:request-revalidate`: Windowed mode — the coordinator asks the cache to revalidate the currently visible page after a local mutation. Stale rows stay visible, no jump to page 0.
83
- * `ln-search:change` `{ term }`: Captures search query from `data-ln-search` inputs.
84
- * `ln-sort:change` `{ field, column, direction }`: Sets `currentSort` and re-sorts (data-driven only). Ignored when `field` is `null` (index-only events have nothing to key a record by).
85
-
86
- ### Emitted Events
87
-
88
- * `ln-list:request-data` `{ list, search, sort, filters }`: Requests data query from the Coordinator. Windowed mode (`data-ln-list-window`) adds `{ offset, limit, queryGen }`. Disabling windowed mode live issues a fresh full `ln-list:request-data` (no `offset`/`limit`) to repopulate the complete dataset.
89
- * `ln-list:ready` `{ total }`: Fired when initial markup parsing completes.
90
- * `ln-list:rendered` `{ list, total, visible }`: Fired after items have been drawn to DOM.
91
- * `ln-list:item-click` `{ list, id, record }`: Fired when clicking item body (excluding buttons, anchors, inputs).
92
- * `ln-list:item-action` `{ list, id, action, record }`: Fired when clicking `[data-ln-item-action]`.
93
- * `ln-list:select` `{ list, selectedIds, count }`: Fired when selection updates.
94
- * `ln-list:select-all` `{ list, selected: true|false }`: Fired when select-all triggers.
95
-
96
- ---
97
-
98
- ## 🔧 Internals
99
-
100
- Source: `js/ln-list/src/ln-list.js`.
101
-
102
- ### Spacer element matches container semantics
103
-
104
- Virtual scroll (both plain and windowed) needs top/bottom spacer elements to preserve scroll height without rendering off-screen rows. If `[data-ln-list-body]` is a `<ul>`/`<ol>`, spacers are `<li class="ln-list__spacer">` to stay HTML5-valid; any other container gets `<div class="ln-list__spacer">`.
105
-
106
- ### `_renderVirtual()` vs `_renderWindowed()`
107
-
108
- Both compute the visible `start`/`end` index range from the measured first-child height and the nearest scrollable ancestor's viewport, then mount spacers and clone the row template for the visible slice via `fillTemplate`/`fill`. They differ only in row source: `_renderVirtual()` reads `this._data[i]` (the full parsed/fetched dataset); `_renderWindowed()` reads `this._cache.get(i)` (the resident sliding window) and renders a blank placeholder spacer — no shimmer — for indices outside the cache, calling `this._cache.ensure(startRow, endRow)` every pass to debounce-fetch missing rows.
109
-
110
- ### Windowed mode (`data-ln-list-window="N"`)
111
-
112
- Owns an `ln-core.createWindowCache` instance (`N` = resident cap, default 1000) instead of the full dataset. `ln-list:request-data` gains `{offset, limit, queryGen}`; `ln-list:set-data` echoes `{offset, queryGen}` back into `cache.ingest()`. Select-all is hidden under `data-ln-list-selectable` + windowed mode together — a windowed list can't select rows it hasn't fetched.
113
-
114
- Every windowing attribute is live-observable, no re-init required: `data-ln-list-window-page`/`-threshold`/`data-ln-list-count` reconfigure the cache via `configure()`/`setGrandTotal()`. Adding `data-ln-list-window` to an already-initialized, non-windowed, data-driven list seeds the cache from resident items and enables windowing live. Removing it destroys the cache and issues one full (no `offset`/`limit`) `ln-list:request-data` to repopulate before rendering non-windowed again.
115
-
116
- ### `_parseChildren()`
117
-
118
- Parses static children inside `[data-ln-list-body]` into `this._data` at mount (excluding existing spacers), and measures the first child's height for `this._itemHeight`.
119
-
120
- ### Sort (`ln-sort:change`)
121
-
122
- Data-driven only — the SSR branch has no sort logic. `field === null` events (index-only, from an
123
- `ln-sort` instance authored without `data-ln-sort-field`) are ignored; `ln-list` records are
124
- field-keyed, not positional, so there is nothing to sort by without a field name. On a matching
125
- event: `preventDefault()`, `currentSort = { field, direction }` (or `null` on `direction: 'none'`),
126
- then mirrors `ln-table`'s own data-driven sort handling exactly — windowed lists call
127
- `_requestData()` (cache invalidate + re-fetch, same scheme as `ln-table`'s windowed
128
- `_requestData()`); non-windowed lists re-sort the already-fetched in-memory data directly
129
- (`_applyFilterAndSort()` + `_render()`, no server round-trip).