@livenetworks/ashlar 1.6.1 → 2.0.1

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 +190 -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,788 +0,0 @@
1
- // ─── Global Console Warning Interceptor (Production Mode) ──
2
- if (typeof window !== 'undefined') {
3
- const originalWarn = console.warn;
4
- console.warn = function (...args) {
5
- const isLibraryWarning = typeof args[0] === 'string' &&
6
- (args[0].startsWith('[ln-') || args[0].startsWith('[lnCore'));
7
-
8
- if (isLibraryWarning) {
9
- const isDebug =
10
- document.documentElement.hasAttribute('data-ln-debug') ||
11
- (document.body && document.body.hasAttribute('data-ln-debug'));
12
-
13
- if (!isDebug) {
14
- return;
15
- }
16
- }
17
- originalWarn.apply(console, args);
18
- };
19
- }
20
-
21
- // ─── Template Cache ────────────────────────────────────────
22
- const _tmplCache = {};
23
-
24
- /**
25
- * Clone a <template data-ln-template="name"> element.
26
- * Cached after first lookup.
27
- */
28
- export function cloneTemplate(name, componentTag) {
29
- if (!_tmplCache[name]) {
30
- _tmplCache[name] = document.querySelector('[data-ln-template="' + name + '"]');
31
- }
32
- const tmpl = _tmplCache[name];
33
- if (!tmpl) {
34
- console.warn('[' + (componentTag || 'ln-core') + '] Template "' + name + '" not found');
35
- return null;
36
- }
37
- return tmpl.content.cloneNode(true);
38
- }
39
-
40
- // ─── Event Dispatch ────────────────────────────────────────
41
-
42
- export function dispatch(element, eventName, detail) {
43
- element.dispatchEvent(new CustomEvent(eventName, {
44
- bubbles: true,
45
- detail: detail || {}
46
- }));
47
- }
48
-
49
- export function dispatchCancelable(element, eventName, detail) {
50
- const event = new CustomEvent(eventName, {
51
- bubbles: true,
52
- cancelable: true,
53
- detail: detail || {}
54
- });
55
- element.dispatchEvent(event);
56
- return event;
57
- }
58
-
59
- /**
60
- * Re-filter / re-sort / re-render a data-driven list-like component, then
61
- * notify the coordinator that fresh data is requested.
62
- *
63
- * Shared by ln-list and ln-table. The passed `component` MUST expose this
64
- * instance contract:
65
- * - _applyFilterAndSort() method
66
- * - _render() method
67
- * - _updateFooter() method
68
- * - _vStart, _vEnd number (reset to -1 to force a full re-render)
69
- * - dom the component root element (dispatch target)
70
- * - name the component's name (becomes detail[keyName])
71
- * - currentSort, currentFilters, currentSearch
72
- *
73
- * @param {Object} component component instance satisfying the contract above
74
- * @param {string} eventName e.g. 'ln-table:request-data' / 'ln-list:request-data'
75
- * @param {string} keyName payload key for the name, e.g. 'table' / 'list'
76
- */
77
- export function requestData(component, eventName, keyName) {
78
- component._applyFilterAndSort();
79
- component._vStart = -1;
80
- component._vEnd = -1;
81
- component._render();
82
- component._updateFooter();
83
-
84
- const detail = {
85
- sort: component.currentSort,
86
- filters: component.currentFilters,
87
- search: component.currentSearch
88
- };
89
- detail[keyName] = component.name;
90
- dispatch(component.dom, eventName, detail);
91
- }
92
-
93
- // ─── Declarative DOM Binding ───────────────────────────────
94
-
95
- export function fill(root, data) {
96
- if (!root || !data) return root;
97
-
98
- // data-ln-field="prop" → textContent
99
- const fields = root.querySelectorAll('[data-ln-field]');
100
- for (let i = 0; i < fields.length; i++) {
101
- const el = fields[i];
102
- const prop = el.getAttribute('data-ln-field');
103
- if (data[prop] != null) {
104
- el.textContent = data[prop];
105
- }
106
- }
107
-
108
- // data-ln-attr="attr:prop, attr:prop" → setAttribute
109
- const attrs = root.querySelectorAll('[data-ln-attr]');
110
- for (let i = 0; i < attrs.length; i++) {
111
- const el = attrs[i];
112
- const pairs = el.getAttribute('data-ln-attr').split(',');
113
- for (let j = 0; j < pairs.length; j++) {
114
- const parts = pairs[j].trim().split(':');
115
- if (parts.length !== 2) continue;
116
- const attr = parts[0].trim();
117
- const prop = parts[1].trim();
118
- if (data[prop] != null) {
119
- el.setAttribute(attr, data[prop]);
120
- }
121
- }
122
- }
123
-
124
- // data-ln-show="prop" → classList.toggle('hidden', !value)
125
- const shows = root.querySelectorAll('[data-ln-show]');
126
- for (let i = 0; i < shows.length; i++) {
127
- const el = shows[i];
128
- const prop = el.getAttribute('data-ln-show');
129
- if (prop in data) {
130
- el.classList.toggle('hidden', !data[prop]);
131
- }
132
- }
133
-
134
- // data-ln-class="cls:prop, cls:prop" → classList.toggle(cls, !!value)
135
- const classes = root.querySelectorAll('[data-ln-class]');
136
- for (let i = 0; i < classes.length; i++) {
137
- const el = classes[i];
138
- const pairs = el.getAttribute('data-ln-class').split(',');
139
- for (let j = 0; j < pairs.length; j++) {
140
- const parts = pairs[j].trim().split(':');
141
- if (parts.length !== 2) continue;
142
- const cls = parts[0].trim();
143
- const prop = parts[1].trim();
144
- if (prop in data) {
145
- el.classList.toggle(cls, !!data[prop]);
146
- }
147
- }
148
- }
149
-
150
- return root;
151
- }
152
-
153
- // ─── Event-driven fill fan-out ─────────────────────────────
154
-
155
- /**
156
- * Dispatch `ln-fill` at every [data-ln-form] and [data-ln-fillable]
157
- * descendant of `container`. Fillables self-handle; null → clear/reset.
158
- */
159
- export function lnFill(container, record) {
160
- // Dispatch at container itself when it is a form or fillable.
161
- // Enables lnFill(formEl, record) to reach ln-form's listener, which
162
- // guards e.target === self.dom. Modal callers (lnFill(modalEl, …)
163
- // where modalEl is [data-ln-modal]) do not match, so they are unaffected.
164
- if (container.matches && container.matches('[data-ln-form], [data-ln-fillable]')) {
165
- container.dispatchEvent(new CustomEvent('ln-fill', { detail: record ?? null, bubbles: true }));
166
- }
167
- const targets = container.querySelectorAll('[data-ln-form], [data-ln-fillable]');
168
- for (let i = 0; i < targets.length; i++) {
169
- targets[i].dispatchEvent(new CustomEvent('ln-fill', { detail: record ?? null, bubbles: true }));
170
- }
171
- return container;
172
- }
173
-
174
- // Delegated display-fillable handler — installed once per page (idempotent
175
- // across standalone component bundles that each inline ln-core helpers).
176
- // Forms are NOT [data-ln-fillable]; ln-form's own listener handles them.
177
- if (typeof window !== 'undefined') {
178
- window.lnCore = window.lnCore || {};
179
- if (!window.lnCore._fillBound) {
180
- window.lnCore._fillBound = true;
181
- document.addEventListener('ln-fill', function (e) {
182
- if (!e.target.matches || !e.target.matches('[data-ln-fillable]')) return;
183
- if (e.detail) {
184
- fill(e.target, e.detail);
185
- } else {
186
- const fields = e.target.querySelectorAll('[data-ln-field]');
187
- for (let i = 0; i < fields.length; i++) {
188
- fields[i].textContent = '';
189
- }
190
- }
191
- });
192
- }
193
- }
194
-
195
- // ─── Template Text-Node Placeholders ──────────────────────
196
-
197
- export function fillTemplate(clone, data) {
198
- if (!clone || !data) return clone;
199
-
200
- // ── Pass 1: text nodes ──────────────────────────────────
201
- const walker = document.createTreeWalker(clone, NodeFilter.SHOW_TEXT);
202
- while (walker.nextNode()) {
203
- const node = walker.currentNode;
204
- if (node.textContent.indexOf('{{') !== -1) {
205
- node.textContent = node.textContent.replace(
206
- /\{\{\s*(\w+)\s*\}\}/g,
207
- function (_, key) { return data[key] !== undefined ? data[key] : ''; }
208
- );
209
- }
210
- }
211
-
212
- // ── Pass 2: element attributes ──────────────────────────
213
- // Uses setAttribute — never innerHTML — so injection risk is the same
214
- // as data-ln-attr (the existing declarative attribute-fill mechanism).
215
- // Complements data-ln-table-cell-attr (field→attr stamping); both coexist.
216
- const _replaceTokens = function (_, key) { return data[key] !== undefined ? data[key] : ''; };
217
- const elements = Array.from(clone.querySelectorAll('*'));
218
- // Include the root itself when clone is an Element (e.g. a <tr> passed
219
- // directly by ln-table._fillRow) — querySelectorAll does not include root.
220
- if (clone.nodeType === 1) elements.push(clone);
221
- for (let i = 0; i < elements.length; i++) {
222
- const el = elements[i];
223
- const attrs = el.attributes;
224
- for (let j = 0; j < attrs.length; j++) {
225
- const attr = attrs[j];
226
- if (attr.value.indexOf('{{') !== -1) {
227
- el.setAttribute(attr.name, attr.value.replace(/\{\{\s*(\w+)\s*\}\}/g, _replaceTokens));
228
- }
229
- }
230
- }
231
-
232
- return clone;
233
- }
234
-
235
- // ─── Keyed List Rendering ──────────────────────────────────
236
-
237
- export function renderList(container, items, templateName, keyFn, fillFn, componentTag) {
238
- // Index existing children by data-ln-key
239
- const existingByKey = {};
240
- for (let i = 0; i < container.children.length; i++) {
241
- const child = container.children[i];
242
- const key = child.getAttribute('data-ln-key');
243
- if (key) existingByKey[key] = child;
244
- }
245
-
246
- // Build ordered fragment — reuse or clone
247
- const frag = document.createDocumentFragment();
248
-
249
- for (let i = 0; i < items.length; i++) {
250
- const item = items[i];
251
- const key = String(keyFn(item));
252
- let el = existingByKey[key];
253
-
254
- if (el) {
255
- fillFn(el, item, i);
256
- } else {
257
- const clone = cloneTemplate(templateName, componentTag);
258
- if (!clone) continue;
259
- fillTemplate(clone, item);
260
- el = clone.firstElementChild;
261
- if (!el) continue;
262
- el.setAttribute('data-ln-key', key);
263
- fillFn(el, item, i);
264
- }
265
- frag.appendChild(el);
266
- }
267
-
268
- // Atomic update: orphans still in container, reused nodes already moved to frag
269
- container.textContent = '';
270
- container.appendChild(frag);
271
- }
272
-
273
- // ─── Guard Body ────────────────────────────────────────
274
-
275
- export function guardBody(setupFn, componentTag) {
276
- if (!document.body) {
277
- document.addEventListener('DOMContentLoaded', function () {
278
- guardBody(setupFn, componentTag);
279
- });
280
- console.warn('[' + componentTag + '] Script loaded before <body> — add "defer" to your <script> tag');
281
- return;
282
- }
283
- setupFn();
284
- }
285
-
286
- export function cloneTemplateScoped(root, name, componentTag) {
287
- if (root) {
288
- const local = root.querySelector('[data-ln-template="' + name + '"]');
289
- if (local) return local.content.cloneNode(true);
290
- }
291
- return cloneTemplate(name, componentTag);
292
- }
293
-
294
- // ─── Dictionary (i18n) ────────────────────────────────────
295
-
296
- /**
297
- * Build a plain object from hidden dictionary elements.
298
- * Reads all [selector] elements once, extracts key→textContent,
299
- * removes them from DOM. Returns dictionary object.
300
- *
301
- * HTML: <ul hidden>
302
- * <li data-ln-upload-dict="remove">Remove</li>
303
- * </ul>
304
- * JS: const dict = buildDict(container, 'data-ln-upload-dict');
305
- * dict.remove → 'Remove'
306
- */
307
- export function buildDict(root, selector) {
308
- const dict = {};
309
- const els = root.querySelectorAll('[' + selector + ']');
310
- for (let i = 0; i < els.length; i++) {
311
- dict[els[i].getAttribute(selector)] = els[i].textContent;
312
- els[i].remove();
313
- }
314
- return dict;
315
- }
316
-
317
- // ─── Find Elements ─────────────────────────────────────────
318
-
319
- export function findElements(root, selector, attribute, ComponentClass) {
320
- if (root.nodeType !== 1) return;
321
-
322
- // Support both simple attribute names and full CSS selectors
323
- const isComplex = selector.indexOf('[') !== -1 || selector.indexOf('.') !== -1 || selector.indexOf('#') !== -1;
324
- const query = isComplex ? selector : '[' + selector + ']';
325
-
326
- const items = Array.from(root.querySelectorAll(query));
327
- if (root.matches && root.matches(query)) {
328
- items.push(root);
329
- }
330
- for (const el of items) {
331
- if (!el[attribute]) {
332
- el[attribute] = new ComponentClass(el);
333
- }
334
- }
335
- }
336
-
337
- // ─── Visibility Check ─────────────────────────────────────
338
-
339
- export function isVisible(el) {
340
- return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length);
341
- }
342
-
343
- // ─── Form Serialization ───────────────────────────────────
344
-
345
- // Effective HTTP method for a form: hidden _method input (non-empty) wins,
346
- // else the form's own `method` attribute. Shared by ln-form's submit gate
347
- // and ln-data-coordinator's native-submit claim so both read the identical
348
- // literal DOM state — no drift between the two independent checks.
349
- export function resolveFormMethod(form) {
350
- const methodInput = form.querySelector('input[name="_method"]');
351
- const raw = (methodInput && methodInput.value !== '') ? methodInput.value : form.method;
352
- return (raw || '').toUpperCase();
353
- }
354
-
355
- export function serializeForm(form, opts) {
356
- const typed = !!(opts && opts.typed);
357
- const exclude = opts && opts.exclude;
358
- const data = {};
359
- const elements = form.elements;
360
-
361
- // Pre-count checkbox names in typed mode to distinguish single-checkbox
362
- // (→ boolean) from same-name checkbox groups (→ array of checked values).
363
- const checkboxCounts = {};
364
- if (typed) {
365
- for (let i = 0; i < elements.length; i++) {
366
- const el = elements[i];
367
- if (el.name && el.type === 'checkbox' && !el.disabled) {
368
- checkboxCounts[el.name] = (checkboxCounts[el.name] || 0) + 1;
369
- }
370
- }
371
- }
372
-
373
- for (let i = 0; i < elements.length; i++) {
374
- const el = elements[i];
375
- if (!el.name || el.disabled || el.type === 'file' || el.type === 'submit' || el.type === 'button') continue;
376
- if (exclude && el.matches && el.matches(exclude)) continue;
377
-
378
- if (el.type === 'checkbox') {
379
- if (typed && checkboxCounts[el.name] === 1) {
380
- data[el.name] = el.checked; // single checkbox → boolean
381
- } else {
382
- if (!data[el.name]) data[el.name] = [];
383
- if (el.checked) data[el.name].push(el.value); // group → array (unchanged)
384
- }
385
- } else if (el.type === 'radio') {
386
- if (el.checked) data[el.name] = el.value;
387
- } else if (el.type === 'select-multiple') {
388
- data[el.name] = [];
389
- for (let j = 0; j < el.options.length; j++) {
390
- if (el.options[j].selected) data[el.name].push(el.options[j].value);
391
- }
392
- } else if (typed && el.type === 'hidden') {
393
- data[el.name] = el.value; // hidden → always string (never coerce)
394
- } else if (typed && (el.type === 'number' || el.type === 'range')) {
395
- const n = Number(el.value);
396
- data[el.name] = (el.value === '' || isNaN(n)) ? null : n; // number/range → Number | null
397
- } else {
398
- data[el.name] = el.value;
399
- }
400
- }
401
-
402
- return data;
403
- }
404
-
405
- // Coerce a value to boolean for single-checkbox fill.
406
- // Flat data-* values arrive as strings; "false", "0", "", "off", "no"
407
- // (case-insensitive, trimmed) are treated as unchecked.
408
- function _coerceBool(value) {
409
- if (typeof value !== 'string') return !!value;
410
- const v = value.trim().toLowerCase();
411
- return v !== 'false' && v !== '0' && v !== '' && v !== 'off' && v !== 'no';
412
- }
413
-
414
- export function populateForm(form, data) {
415
- const elements = form.elements;
416
- const filled = [];
417
-
418
- // Pre-count checkbox names to distinguish single-checkbox (→ bool)
419
- // from same-name checkbox groups (→ comma-separated list membership).
420
- // NOTE: unlike serializeForm, populateForm fills disabled elements too,
421
- // so the count must include disabled members (no !el.disabled guard) —
422
- // otherwise a group with a disabled box reverts to single-checkbox coercion.
423
- const checkboxCounts = {};
424
- for (let i = 0; i < elements.length; i++) {
425
- const el = elements[i];
426
- if (el.name && el.type === 'checkbox') {
427
- checkboxCounts[el.name] = (checkboxCounts[el.name] || 0) + 1;
428
- }
429
- }
430
-
431
- for (let i = 0; i < elements.length; i++) {
432
- const el = elements[i];
433
- if (el.type === 'file' || el.type === 'submit' || el.type === 'button') continue;
434
-
435
- // Decoupled-key fill: data-ln-fill-as wins over name for record matching.
436
- // Write (fill) path only — serializeForm stays name-based.
437
- const matchKey = el.getAttribute('data-ln-fill-as') || el.name;
438
- if (!matchKey || !(matchKey in data)) continue;
439
-
440
- const value = data[matchKey];
441
-
442
- if (el.type === 'checkbox') {
443
- if (Array.isArray(value)) {
444
- // Programmatic array path — membership check.
445
- el.checked = value.indexOf(el.value) !== -1;
446
- } else if (checkboxCounts[el.name] > 1) {
447
- // Same-name checkbox group + scalar: treat as comma-separated list.
448
- // "admin,editor" → ['admin','editor'] → membership check.
449
- const list = String(value).split(',').map(function (s) { return s.trim(); });
450
- el.checked = list.indexOf(el.value) !== -1;
451
- } else {
452
- // Single checkbox — boolean coercion.
453
- // "false"/"0"/"off"/"no"/"" → unchecked; anything else → checked.
454
- el.checked = _coerceBool(value);
455
- }
456
- filled.push(el);
457
- } else if (el.type === 'radio') {
458
- el.checked = el.value === String(value);
459
- filled.push(el);
460
- } else if (el.type === 'select-multiple') {
461
- if (Array.isArray(value)) {
462
- for (let j = 0; j < el.options.length; j++) {
463
- el.options[j].selected = value.indexOf(el.options[j].value) !== -1;
464
- }
465
- }
466
- filled.push(el);
467
- } else {
468
- el.value = value;
469
- filled.push(el);
470
- }
471
- }
472
-
473
- return filled;
474
- }
475
-
476
- // ─── Locale Detection ─────────────────────────────────────
477
-
478
- const _standardTerritories = {
479
- mk: 'mk-MK',
480
- de: 'de-DE',
481
- fr: 'fr-FR',
482
- es: 'es-ES',
483
- it: 'it-IT',
484
- nl: 'nl-NL',
485
- pt: 'pt-PT',
486
- ru: 'ru-RU',
487
- bg: 'bg-BG',
488
- hr: 'hr-HR',
489
- sr: 'sr-RS',
490
- sq: 'sq-AL',
491
- el: 'el-GR',
492
- en: 'en-US'
493
- };
494
-
495
- export function getLocale(el) {
496
- const langEl = el ? el.closest('[lang]') : null;
497
- const raw = (langEl ? (langEl.getAttribute('lang') || langEl.lang) : null)
498
- || (document.documentElement ? (document.documentElement.getAttribute('lang') || document.documentElement.lang) : null)
499
- || navigator.language;
500
- if (!raw) return 'en-US';
501
- const lower = raw.trim().toLowerCase();
502
- if (lower.indexOf('-') === -1 && _standardTerritories[lower]) {
503
- return _standardTerritories[lower];
504
- }
505
- return raw;
506
- }
507
-
508
- // ─── Raw Value Read ───────────────────────────────────────
509
-
510
- /**
511
- * Read the raw machine value behind a formatted cell/item display.
512
- * Returns the `data-ln-value` attribute if present, else trimmed textContent.
513
- * Single read path for value-based sort/filter across components.
514
- */
515
- export function readValue(el) {
516
- return el.hasAttribute('data-ln-value')
517
- ? el.getAttribute('data-ln-value')
518
- : el.textContent.trim();
519
- }
520
-
521
- // ─── Value Comparison Primitives ───────────────────────────
522
-
523
- /**
524
- * Detect the comparison type for a column/field from its current value set.
525
- * Type is locked ONCE per sort operation (not per pair) — comparing types
526
- * per-pair breaks comparator transitivity and produces wrong ordering.
527
- * All non-empty values must be finite numbers for 'number'; otherwise 'string'.
528
- */
529
- export function detectValueType(values) {
530
- let hasValue = false;
531
- for (let i = 0; i < values.length; i++) {
532
- const v = values[i];
533
- if (v === '' || v == null) continue;
534
- hasValue = true;
535
- if (!Number.isFinite(Number(v))) return 'string';
536
- }
537
- return hasValue ? 'number' : 'string';
538
- }
539
-
540
- /**
541
- * Compare two raw values given a pre-locked type (see detectValueType).
542
- * Pass an Intl.Collator instance for locale-aware string comparison —
543
- * built once by the caller outside the sort loop, never per pair.
544
- */
545
- export function compareValues(a, b, type, collator) {
546
- if (type === 'number') {
547
- const na = parseFloat(a);
548
- const nb = parseFloat(b);
549
- return (isNaN(na) ? 0 : na) - (isNaN(nb) ? 0 : nb);
550
- }
551
- const strA = a != null ? String(a) : '';
552
- const strB = b != null ? String(b) : '';
553
- if (collator) return collator.compare(strA, strB);
554
- return strA < strB ? -1 : strA > strB ? 1 : 0;
555
- }
556
-
557
- // ─── Value Property Interception ───────────────────────────
558
-
559
- /**
560
- * Intercept the programmatic `value` getter/setter on an input element.
561
- * Useful for custom components that need to sync/format programmatic changes.
562
- * @param {HTMLInputElement} dom - The visible input element.
563
- * @param {Object} descriptor - The original property descriptor of HTMLInputElement.prototype.value.
564
- * @param {Object} callbacks - Getter and setter callbacks.
565
- */
566
- export function interceptValueProperty(dom, descriptor, { get, set }) {
567
- Object.defineProperty(dom, 'value', {
568
- get: function () {
569
- if (get) {
570
- return get.call(this);
571
- }
572
- return descriptor.get.call(this);
573
- },
574
- set: function (val) {
575
- if (set) {
576
- set.call(this, val, (originalVal) => descriptor.set.call(this, originalVal));
577
- } else {
578
- descriptor.set.call(this, val);
579
- }
580
- },
581
- configurable: true
582
- });
583
- }
584
-
585
- // ─── Component Registration ───────────────────────────────
586
-
587
- export function registerComponent(selector, attribute, ComponentFn, componentTag, options = {}) {
588
- const extraAttributes = options.extraAttributes || [];
589
- const onAttributeChange = options.onAttributeChange || null;
590
- const onInit = options.onInit || null;
591
-
592
- function constructor(domRoot) {
593
- const root = domRoot || document.body;
594
- findElements(root, selector, attribute, ComponentFn);
595
- if (onInit) onInit(root);
596
- }
597
-
598
- guardBody(function () {
599
- const observer = new MutationObserver(function (mutations) {
600
- for (let i = 0; i < mutations.length; i++) {
601
- const mutation = mutations[i];
602
- if (mutation.type === 'childList') {
603
- for (let j = 0; j < mutation.addedNodes.length; j++) {
604
- const node = mutation.addedNodes[j];
605
- if (node.nodeType === 1) {
606
- findElements(node, selector, attribute, ComponentFn);
607
- if (onInit) onInit(node);
608
- }
609
- }
610
- for (let j = 0; j < mutation.removedNodes.length; j++) {
611
- const node = mutation.removedNodes[j];
612
- if (node.nodeType === 1) {
613
- const isComplex = selector.indexOf('[') !== -1 || selector.indexOf('.') !== -1 || selector.indexOf('#') !== -1;
614
- const query = isComplex ? selector : '[' + selector + ']';
615
- const items = Array.from(node.querySelectorAll(query));
616
- if (node.matches && node.matches(query)) {
617
- items.push(node);
618
- }
619
- for (let k = 0; k < items.length; k++) {
620
- const item = items[k];
621
- if (!document.contains(item)) {
622
- const inst = item[attribute];
623
- if (inst && typeof inst.destroy === 'function') {
624
- inst.destroy();
625
- }
626
- }
627
- }
628
- }
629
- }
630
- } else if (mutation.type === 'attributes') {
631
- if (onAttributeChange && mutation.target[attribute]) {
632
- onAttributeChange(mutation.target, mutation.attributeName);
633
- } else {
634
- findElements(mutation.target, selector, attribute, ComponentFn);
635
- if (onInit) onInit(mutation.target);
636
- }
637
- }
638
- }
639
- });
640
-
641
- // Extract attribute names from selector for attributeFilter
642
- let observedAttributes = [];
643
- if (selector.indexOf('[') !== -1) {
644
- const re = /\[([\w-]+)/g;
645
- let match;
646
- while ((match = re.exec(selector)) !== null) {
647
- observedAttributes.push(match[1]);
648
- }
649
- } else {
650
- observedAttributes.push(selector);
651
- }
652
-
653
- observer.observe(document.body, {
654
- childList: true,
655
- subtree: true,
656
- attributes: true,
657
- attributeFilter: observedAttributes.concat(extraAttributes)
658
- });
659
- }, componentTag || (selector.indexOf('[') === -1 ? selector.replace('data-', '') : 'component'));
660
-
661
- window[attribute] = constructor;
662
-
663
- if (document.readyState === 'loading') {
664
- document.addEventListener('DOMContentLoaded', function () {
665
- constructor(document.body);
666
- });
667
- } else {
668
- constructor(document.body);
669
- }
670
-
671
- return constructor;
672
- }
673
-
674
- // ─── HTTP / URL Helpers ────────────────────────────────────
675
-
676
- /**
677
- * Check if a click event on a link should be intercepted by an in-app navigator.
678
- * Intercept only left clicks, same-origin, not target="_blank", no download,
679
- * not mailto/tel, and not pure hash/empty.
680
- *
681
- * @param {MouseEvent} event
682
- * @param {HTMLAnchorElement} anchor
683
- * @returns {boolean}
684
- */
685
- export function shouldInterceptLink(event, anchor) {
686
- if (event.ctrlKey || event.metaKey || event.shiftKey || event.altKey || event.button !== 0) {
687
- return false;
688
- }
689
- if (!anchor) return false;
690
- const href = anchor.getAttribute('href');
691
- if (!href) return false;
692
- if (anchor.getAttribute('target') === '_blank') return false;
693
- if (anchor.hasAttribute('download')) return false;
694
- if (href.startsWith('mailto:') || href.startsWith('tel:')) return false;
695
- if (href === '#' || href.startsWith('#')) return false;
696
- if (anchor.hostname && anchor.hostname !== window.location.hostname) return false;
697
- return true;
698
- }
699
-
700
- /**
701
- * Build a URL from segments, stripping duplicate slashes.
702
- */
703
- export function buildUrl(...segments) {
704
- return segments
705
- .filter(x => x !== undefined && x !== null && x !== '')
706
- .map((part, index) => {
707
- if (index === 0) return part.replace(/\/+$/, '');
708
- return part.replace(/^\/+/, '').replace(/\/+$/, '');
709
- })
710
- .filter(Boolean)
711
- .join('/');
712
- }
713
-
714
- /**
715
- * Compile standard JSON request headers.
716
- */
717
- export function getHeaders(customHeaders, auth) {
718
- return Object.assign({
719
- 'Content-Type': 'application/json',
720
- 'Accept': 'application/json'
721
- }, customHeaders, auth ? { 'Authorization': auth } : null);
722
- }
723
-
724
- /**
725
- * Safely parse headers from JSON string.
726
- */
727
- export function parseHeaders(str, componentName = 'ln-core') {
728
- try { return str ? JSON.parse(str) : {}; }
729
- catch (e) { return console.error(`[${componentName}] Invalid headers JSON:`, e), {}; }
730
- }
731
-
732
- // ─── Domain Data Mapper Registry ───────────────────────────
733
- const _dataMappers = {};
734
-
735
- export function registerDataMapper(name, mapper) {
736
- _dataMappers[name] = mapper;
737
- }
738
-
739
- export function getDataMapper(name) {
740
- return _dataMappers[name] || { ingress: r => r, egress: r => r };
741
- }
742
-
743
- // ─── Locale Fallback Registry ───────────────────────────────
744
- const _localeFallbacks = {};
745
-
746
- export function registerLocaleFallback(langPrefix, dictionary) {
747
- if (!langPrefix || typeof dictionary !== 'object') return;
748
- const prefix = langPrefix.toLowerCase().split('-')[0];
749
- _localeFallbacks[prefix] = dictionary;
750
- }
751
-
752
- export function getLocaleFallback(lang) {
753
- if (!lang) return null;
754
- const prefix = lang.toLowerCase().split('-')[0];
755
- return _localeFallbacks[prefix] || null;
756
- }
757
-
758
- // Default Macedonian locale fallback registration
759
- registerLocaleFallback('mk', {
760
- monthsLong: [
761
- 'јануари', 'февруари', 'март', 'април', 'мај', 'јуни',
762
- 'јули', 'август', 'септември', 'октомври', 'ноември', 'декември'
763
- ],
764
- monthsShort: [
765
- 'јан', 'фев', 'мар', 'апр', 'мај', 'јун',
766
- 'јул', 'авг', 'септ', 'окт', 'ноем', 'дек'
767
- ],
768
- daysLong: [
769
- 'недела', 'понеделник', 'вторник', 'среда', 'четврток', 'петок', 'сабота'
770
- ],
771
- daysShort: [
772
- 'нед', 'пон', 'вт', 'ср', 'чет', 'пет', 'саб'
773
- ]
774
- });
775
-
776
- if (typeof window !== 'undefined') {
777
- window.lnCore = window.lnCore || {};
778
- window.lnCore.registerDataMapper = registerDataMapper;
779
- window.lnCore.getDataMapper = getDataMapper;
780
- window.lnCore.registerLocaleFallback = registerLocaleFallback;
781
- window.lnCore.getLocaleFallback = getLocaleFallback;
782
- window.lnCore.fillTemplate = fillTemplate;
783
- window.lnCore.fill = fill;
784
- window.lnCore.lnFill = lnFill;
785
- window.lnCore.renderList = renderList;
786
- }
787
-
788
-