@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
@@ -0,0 +1 @@
1
+ (function(){"use strict";function E(){return typeof window>"u"?!1:window.lnDebug===!0||window.lnCore&&window.lnCore._debugSink?!0:typeof document<"u"&&document.body?document.body.hasAttribute("data-ln-debug")||document.body.querySelector("[data-ln-debug]")!==null:!1}function m(e){if(typeof window>"u")return!1;if(window.lnDebug===!0)return!0;if(window.lnCore&&window.lnCore._debugIsContained)return e?window.lnCore._debugIsContained(e):window.lnCore._debugSink!==null;if(e&&e.closest){const t=e.closest("[data-ln-debug]");return!(!t||typeof document<"u"&&t===document.documentElement)}return typeof document<"u"&&document.body?document.body.hasAttribute("data-ln-debug"):!1}if(typeof window<"u"&&(window.lnCore=window.lnCore||{},!window.lnCore._warnBound)){window.lnCore._warnBound=!0;const e=console.warn;console.warn=function(...t){if(typeof t[0]=="string"&&(t[0].startsWith("[ln-")||t[0].startsWith("[lnCore"))){let r=null;for(let o=1;o<t.length;o++)if(t[o]&&t[o].nodeType===1){r=t[o];break}if(!m(r))return}e.apply(console,t)}}function $(e,t,n){const r=n||{};window.lnCore._debugSink&&window.lnCore._debugSink("event",t,e,r),e.dispatchEvent(new CustomEvent(t,{bubbles:!0,detail:r}))}function V(e,t,n){const r=n||{};window.lnCore._debugSink&&window.lnCore._debugSink("event",t,e,r);const o=new CustomEvent(t,{bubbles:!0,cancelable:!0,detail:r});return e.dispatchEvent(o),o}function y(e,t){if(!document.body){document.addEventListener("DOMContentLoaded",function(){y(e,t)}),console.warn("["+t+'] Script loaded before <body> — add "defer" to your <script> tag');return}e()}const N={};function P(e,t){N[e]=t}function U(e){return N[e]||{ingress:t=>t,egress:t=>t}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerDataMapper=P,window.lnCore.getDataMapper=U);function Q(){typeof window>"u"||(window.lnCore=window.lnCore||{},!window.lnCore._localeObserverBound&&(window.lnCore._localeObserverBound=!0,y(function(){new MutationObserver(function(){$(document,"ln-core:locale-change",{})}).observe(document.documentElement,{attributes:!0,attributeFilter:["lang"],subtree:!0})},"ln-core")))}const T={};function J(e,t){if(!e||typeof t!="object")return;const n=e.toLowerCase().split("-")[0];T[n]=t}function K(e){if(!e)return null;const t=e.toLowerCase().split("-")[0];return T[t]||null}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerLocaleFallback=J,window.lnCore.getLocaleFallback=K,window.lnCore.ensureLocaleObserver=Q);const v={};function z(e,t){v[e]||(v[e]=document.querySelector('[data-ln-template="'+e+'"]'));const n=v[e];return n?n.content.cloneNode(!0):(console.warn("["+(t||"ln-core")+'] Template "'+e+'" not found'),null)}function D(e,t){if(!e||!t)return e;const n=e.querySelectorAll("[data-ln-field]");for(let l=0;l<n.length;l++){const s=n[l],a=s.getAttribute("data-ln-field");t[a]!=null&&(s.textContent=t[a])}const r=e.querySelectorAll("[data-ln-attr]");for(let l=0;l<r.length;l++){const s=r[l],a=s.getAttribute("data-ln-attr").split(",");for(let c=0;c<a.length;c++){const d=a[c].trim().split(":");if(d.length!==2)continue;const u=d[0].trim(),f=d[1].trim();t[f]!=null&&s.setAttribute(u,t[f])}}const o=e.querySelectorAll("[data-ln-show]");for(let l=0;l<o.length;l++){const s=o[l],a=s.getAttribute("data-ln-show");a in t&&s.classList.toggle("hidden",!t[a])}const i=e.querySelectorAll("[data-ln-class]");for(let l=0;l<i.length;l++){const s=i[l],a=s.getAttribute("data-ln-class").split(",");for(let c=0;c<a.length;c++){const d=a[c].trim().split(":");if(d.length!==2)continue;const u=d[0].trim(),f=d[1].trim();f in t&&s.classList.toggle(u,!!t[f])}}return e}function G(e,t){e.matches&&e.matches("[data-ln-form], [data-ln-fillable]")&&(window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",e,t??null),e.dispatchEvent(new CustomEvent("ln-fill",{detail:t??null,bubbles:!0})));const n=e.querySelectorAll("[data-ln-form], [data-ln-fillable]");for(let r=0;r<n.length;r++)window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",n[r],t??null),n[r].dispatchEvent(new CustomEvent("ln-fill",{detail:t??null,bubbles:!0}));return e}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._fillBound||(window.lnCore._fillBound=!0,document.addEventListener("ln-fill",function(e){if(!(!e.target.matches||!e.target.matches("[data-ln-fillable]")))if(e.detail)D(e.target,e.detail);else{const t=e.target.querySelectorAll("[data-ln-field]");for(let n=0;n<t.length;n++)t[n].textContent=""}})));function I(e,t){if(!e||!t)return e;const n=document.createTreeWalker(e,NodeFilter.SHOW_TEXT);for(;n.nextNode();){const i=n.currentNode;i.textContent.indexOf("{{")!==-1&&(i.textContent=i.textContent.replace(/\{\{\s*(\w+)\s*\}\}/g,function(l,s){return t[s]!==void 0?t[s]:""}))}const r=function(i,l){return t[l]!==void 0?t[l]:""},o=Array.from(e.querySelectorAll("*"));e.nodeType===1&&o.push(e);for(let i=0;i<o.length;i++){const l=o[i],s=l.attributes;for(let a=0;a<s.length;a++){const c=s[a];c.value.indexOf("{{")!==-1&&l.setAttribute(c.name,c.value.replace(/\{\{\s*(\w+)\s*\}\}/g,r))}}return e}function X(e,t,n,r,o,i){const l={};for(let a=0;a<e.children.length;a++){const c=e.children[a],d=c.getAttribute("data-ln-render-key");d&&(l[d]=c)}const s=document.createDocumentFragment();for(let a=0;a<t.length;a++){const c=t[a],d=String(r(c));let u=l[d];if(u)o(u,c,a);else{const f=z(n,i);if(!f||(I(f,c),u=f.firstElementChild,!u))continue;u.setAttribute("data-ln-render-key",d),o(u,c,a)}s.appendChild(u)}e.textContent="",e.appendChild(s)}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.fillTemplate=I,window.lnCore.fill=D,window.lnCore.lnFill=G,window.lnCore.renderList=X);function R(e,t,n){const r=e.getAttribute(t);return r===null?n:r}function Y(e,t,n){const r=parseInt(e.getAttribute(t),10);return isNaN(r)?n:r}function q(e,t,n=!1){const r=e.getAttribute(t);if(r===null)return!!n;const o=r.trim().toLowerCase();return!(o==="false"||o==="0")}function Z(e,t){return(e.getAttribute(t)||"").split(",").map(n=>n.trim()).filter(Boolean)}const A=new Map;function ee(e,t){const n=(e?e.join("|"):"")+"::"+t;if(A.has(n))return A.get(n);const r=new Set(e||[]),o=function(i,l){const s=i.getAttribute(l);return s!==null&&r.has(s)?s:t};return A.set(n,o),o}function te(e,t,n){const r=parseFloat(e.getAttribute(t));return isNaN(r)?n:r}function ne(e,t,n){const r=e.getAttribute(t);if(!r)return n;try{return JSON.parse(r)}catch{return n}}function M(e,t,n,r,o){if(!e||t===null)return!0;const i=r||"ln-component",l=e.type;if(l==="trigger"||l==="marker"||l==="string"||l==="list"||!l||t===""&&e.fallback!==void 0)return!0;const s=a=>{o?console.warn(a,o):console.warn(a)};if(l==="boolean"){const a=t.trim().toLowerCase();return a!==""&&a!=="true"&&a!=="false"&&a!=="1"&&a!=="0"?(s(`[${i}] Invalid value "${t}" for boolean attribute "${n}". Allowed: "true", "false", or presence-only.`),!1):!0}if(l==="enum"){const a=e.values||[];return a.includes(t)?!0:(s(`[${i}] Invalid value "${t}" for attribute "${n}". Allowed: ${a.join(", ")}. Fallback: "${e.fallback}".`),!1)}if(l==="integer"){if(!/^-?\d+$/.test(t))return s(`[${i}] Invalid integer "${t}" for attribute "${n}". Fallback: ${e.fallback}.`),!1;const a=parseInt(t,10);return e.min!==void 0&&a<e.min?(s(`[${i}] Value ${a} for attribute "${n}" is less than min (${e.min}).`),!1):e.max!==void 0&&a>e.max?(s(`[${i}] Value ${a} for attribute "${n}" is greater than max (${e.max}).`),!1):!0}if(l==="float")return isNaN(Number(t))?(s(`[${i}] Invalid float "${t}" for attribute "${n}". Fallback: ${e.fallback}.`),!1):!0;if(l==="json")try{return JSON.parse(t),!0}catch(a){return s(`[${i}] Invalid JSON for attribute "${n}": ${a.message}. Fallback: ${e.fallback}.`),!1}return!0}function re(e,t,n){for(const r in n){const[o,i,l]=n[r];Object.defineProperty(e,r,{get:function(){return o(t,i,l)},enumerable:!0,configurable:!0})}return e}function oe(e){const t={};for(const n in e){const r=e[n];if(!r||!r.prop)continue;let o=r.read;if(!o&&r.type)switch(r.type){case"enum":o=ee(r.values,r.fallback);break;case"integer":o=Y;break;case"float":o=te;break;case"boolean":o=q;break;case"list":o=Z;break;case"json":o=ne;break;case"string":default:o=R;break}o||(o=R),t[r.prop]=[o,n,r.fallback]}return t}function ie(e){const t={};for(const n in e){const r=e[n];r&&r.effect&&(t[n]=r.effect)}return Object.keys(t).length?t:null}function le(e){if(e.onAttrChange&&!e.declared)return null;const t=new Set;if(e.effects)for(const n in e.effects)t.add(n);if(e.onAttrChange&&e.declared)for(const n of e.declared)t.add(n);return t}function _(e,t,n,r){if(e.nodeType!==1)return;const i=t.indexOf("[")!==-1||t.indexOf(".")!==-1||t.indexOf("#")!==-1?t:"["+t+"]",l=Array.from(e.querySelectorAll(i));e.matches&&e.matches(i)&&l.push(e);for(const s of l)if(!s[n]){window.lnCore._persistSink&&s.hasAttribute("data-ln-persist")&&window.lnCore._persistSink(s,t);try{s[n]=new r(s)}catch(a){console.error("["+n+"] init failed",s,a)}}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._bootHolds=window.lnCore._bootHolds||0,window.lnCore._bootQueue=window.lnCore._bootQueue||[]);function se(){return typeof window<"u"&&window.lnCore&&window.lnCore._bootHolds||0}function ae(e){typeof window<"u"?(window.lnCore=window.lnCore||{},window.lnCore._bootHolds=window.lnCore._bootHolds||0,window.lnCore._bootQueue=window.lnCore._bootQueue||[],window.lnCore._bootHolds>0?window.lnCore._bootQueue.push(e):setTimeout(e,0)):e()}function F(){window.lnCore=window.lnCore||{};const e=window.lnCore._attrRegistry=window.lnCore._attrRegistry||{byAttr:new Map,reactive:[],persist:[]};return e.byReactive=e.byReactive||new Map,e.reactiveWildcard=e.reactiveWildcard||[],e}function ce(e){const t=F(),n=e.observed||[];for(let r=0;r<n.length;r++){const o=n[r];t.byAttr.has(o)||t.byAttr.set(o,[]),t.byAttr.get(o).push(e)}if(t.byDeclaredAttr=t.byDeclaredAttr||new Map,e.attributes)for(const r in e.attributes){t.byDeclaredAttr.has(r)||t.byDeclaredAttr.set(r,[]);const o=t.byDeclaredAttr.get(r);o.some(i=>i.componentTag===e.componentTag)||o.push({spec:e.attributes[r],componentTag:e.componentTag})}if(e.onAttrChange||e.effects){t.reactive.push(e);const r=le(e);if(r===null)t.reactiveWildcard.push(e);else for(const o of r)t.byReactive.has(o)||t.byReactive.set(o,[]),t.byReactive.get(o).push(e)}e.persist&&t.persist.push(e)}function W(e,t,n,r){for(let o=0;o<e.length;o++){const i=e[o];if(!t[i.attribute])continue;const l=i.effects&&i.effects[n];l?l(t,n,r):i.onAttrChange&&(!i.declared||i.declared.has(n))&&i.onAttrChange(t,n,r)}}function ue(e){const t=e.target,n=e.attributeName;if(e.oldValue===t.getAttribute(n))return;const r=F(),o=r.byAttr.get(n);if(E()&&r.byDeclaredAttr&&r.byDeclaredAttr.has(n)&&m(t)){const i=r.byDeclaredAttr.get(n),l=t.getAttribute(n);for(let s=0;s<i.length;s++)M(i[s].spec,l,n,i[s].componentTag,t)}if(window.lnCore._debugSink&&(n.indexOf("data-ln-")===0||o)&&window.lnCore._debugSink("attr",n,t,{oldValue:e.oldValue,newValue:t.getAttribute(n)}),n.indexOf("data-ln-")===0){const i=r.byReactive.get(n);i&&W(i,t,n,e.oldValue),r.reactiveWildcard.length&&W(r.reactiveWildcard,t,n,e.oldValue)}if(o)for(let i=0;i<o.length;i++){const l=o[i];if(l.handler){l.handler(t,n,e.oldValue);continue}l.onAttributeChange&&t[l.attribute]?l.onAttributeChange(t,n):(_(t,l.selector,l.attribute,l.ComponentFn),l.onInit&&l.onInit(t))}}function de(){window.lnCore=window.lnCore||{},!window.lnCore._attrObserverBound&&(window.lnCore._attrObserverBound=!0,y(function(){new MutationObserver(function(t){for(let n=0;n<t.length;n++)try{ue(t[n])}catch(r){console.error("[ln-core] mutation handler failed",t[n].target,r)}}).observe(document.body,{attributes:!0,subtree:!0,attributeOldValue:!0})},"ln-core"))}function j(){return window.lnCore=window.lnCore||{},window.lnCore._lifecycleRegistry=window.lnCore._lifecycleRegistry||[]}function fe(e){const t=j();if(t.length){if(e.target)for(let n=0;n<t.length;n++){const r=t[n];if(r.onSubtreeChange){const o=r.query,i=e.target.nodeType===1?e.target.matches(o)?e.target:e.target.closest(o):e.target.parentElement?e.target.parentElement.closest(o):null;i&&r.onSubtreeChange(i,e)}}for(let n=0;n<e.addedNodes.length;n++){const r=e.addedNodes[n];if(r.nodeType===1)for(let o=0;o<t.length;o++){const i=t[o];_(r,i.selector,i.attribute,i.ComponentFn),i.onInit&&i.onInit(r)}}for(let n=0;n<e.removedNodes.length;n++){const r=e.removedNodes[n];if(r.nodeType===1)for(let o=0;o<t.length;o++){const i=t[o],l=i.query,s=Array.from(r.querySelectorAll(l));r.matches&&r.matches(l)&&s.push(r);for(let a=0;a<s.length;a++){const c=s[a];if(!document.contains(c)){const d=c[i.attribute];if(d&&typeof d.destroy=="function")try{d.destroy()}catch(u){console.error("["+i.attribute+"] destroy failed",c,u)}delete c[i.attribute]}}}}}}function we(){window.lnCore=window.lnCore||{},!window.lnCore._lifecycleObserverBound&&(window.lnCore._lifecycleObserverBound=!0,y(function(){new MutationObserver(function(t){for(let n=0;n<t.length;n++){const r=t[n];if(r.type==="childList")try{fe(r)}catch(o){console.error("[ln-core] lifecycle handler failed",r.target,o)}}}).observe(document.body,{childList:!0,subtree:!0})},"ln-core"))}function he(e,t,n,r,o={}){const i=o.extraAttributes||[],l=o.onAttributeChange||null,s=o.onSubtreeChange||null,a=o.onInit||null,c=o.onAttrChange||null,d=o.effects||null,u=o.attributes||null,f=u?ie(u):d,w=u?new Set(Object.keys(u)):null,p=o.persist||null;function b(S){const h=S||document.body;if(_(h,e,t,n),u&&E())for(const C in u){const ke=u[C],O=Array.from(h.querySelectorAll("["+C+"]"));h.matches&&h.matches("["+C+"]")&&O.push(h);for(let x=0;x<O.length;x++){const L=O[x];m(L)&&M(ke,L.getAttribute(C),C,r,L)}}a&&a(h)}const g=[];if(e.indexOf("[")!==-1){const S=/\[([\w-]+)/g;let h;for(;(h=S.exec(e))!==null;)g.push(h[1])}else g.push(e);ce({selector:e,attribute:t,componentTag:r,attributes:u,ComponentFn:n,onInit:a,observed:g.concat(i),onAttributeChange:l,onAttrChange:c,effects:f,declared:w,persist:p}),de();const _e=e.indexOf("[")!==-1||e.indexOf(".")!==-1||e.indexOf("#")!==-1?e:"["+e+"]";j().push({selector:e,attribute:t,ComponentFn:n,onInit:a,onSubtreeChange:s,query:_e}),we(),window[t]=b;function H(){se()>0?ae(function(){b(document.body)}):b(document.body)}return document.readyState==="loading"?document.addEventListener("DOMContentLoaded",H):H(),b}function B(e){return(e||"").replace(/^#/,"")}function k(e){const t=e===void 0?location.hash:e,n={},r=B(t);if(!r)return n;const o=r.split("&");for(let i=0;i<o.length;i++){const l=o[i];if(!l)continue;const s=l.indexOf(":"),a=s>-1?l.slice(0,s):l,c=s>-1?l.slice(s+1):"";if(a)try{n[a]=decodeURIComponent(c)}catch{n[a]=c}}return n}function be(e){if(!e)return null;const t=k();return e in t?t[e]:null}function pe(e,t){if(!e)return;const n=k();t==null?delete n[e]:n[e]=String(t);const o=Object.keys(n).map(function(i){const l=n[i];return l===""?i:i+":"+encodeURIComponent(l)}).join("&");B(location.hash)!==o&&(location.hash=o)}function ge(e){return e.button===1||e.ctrlKey||e.metaKey||e.shiftKey?!1:(e.preventDefault(),!0)}function Ce(e,t){if(!e||!e.hasAttribute("data-ln-hash"))return null;const n=e.getAttribute("data-ln-hash");if(n&&n.trim()!=="")return n.trim();const r=e.getAttribute("data-ln-sort")||e.getAttribute("data-ln-search-for")||e.getAttribute("data-ln-search")||e.getAttribute("data-ln-filter")||e.id;return r?t?r+"-"+t:r:t||null}function ye(e,t){return!t||t==="none"||e===null||e===void 0?null:String(e)+"."+t}function me(e){return!e||typeof e!="string"?null:e.endsWith(".asc")?{fieldOrColumn:e.slice(0,-4),direction:"asc"}:e.endsWith(".desc")?{fieldOrColumn:e.slice(0,-5),direction:"desc"}:null}function ve(e,t){return!e||!Array.isArray(t)||t.length===0?null:e+":"+t.map(encodeURIComponent).join(",")}function Ae(e){if(!e||typeof e!="string")return null;const t=e.indexOf(":");if(t===-1)return null;const n=e.slice(0,t),r=e.slice(t+1),o=r?r.split(",").map(function(i){try{return decodeURIComponent(i)}catch{return i}}).filter(Boolean):[];return{key:n,values:o}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.hashParse=k,window.lnCore.hashGet=be,window.lnCore.hashSet=pe,window.lnCore.hashLinkClick=ge,window.lnCore.resolveHashNamespace=Ce,window.lnCore.hashSortEncode=ye,window.lnCore.hashSortDecode=me,window.lnCore.hashFilterEncode=ve,window.lnCore.hashFilterDecode=Ae),(function(){const e="data-ln-nav",t="lnNav";if(window[t]!==void 0)return;const n={"data-ln-nav":{effect:l,type:"string",fallback:"active",description:"CSS class name applied to active navigation links"},"data-ln-nav-exact":{prop:"exact",read:q,effect:l,type:"boolean",fallback:!1,description:"Match exact URL pathname instead of prefix matching"}},r=oe(n);if(history._lnNavCallbacks=history._lnNavCallbacks||[],!history._lnNavPatched){const s=history.pushState;history.pushState=function(){s.apply(history,arguments);for(const c of history._lnNavCallbacks)c()};const a=history.replaceState;history.replaceState=function(){a.apply(history,arguments);for(const c of history._lnNavCallbacks)c()},history._lnNavPatched=!0}function o(s){return this.dom=s,re(this,s,r),this.activeClass=s.getAttribute(e)||"active",this.updateHandler=()=>this.update(),window.addEventListener("popstate",this.updateHandler),history._lnNavCallbacks.push(this.updateHandler),this.observer=new MutationObserver(()=>this.update()),this.observer.observe(s,{childList:!0,subtree:!0}),this.update(),this}o.prototype.update=function(){if(!this.activeClass||V(this.dom,"ln-nav:before-update",{target:this.dom}).defaultPrevented)return;const a=Array.from(this.dom.querySelectorAll("a")),c=window.location.pathname,d=i(c),u=[];for(const f of a){const w=f.getAttribute("href");if(!w||w==="#"||w.startsWith("#")||w.startsWith("javascript:")||w.startsWith("mailto:")||w.startsWith("tel:")){f.classList.remove(this.activeClass),f.removeAttribute("aria-current");continue}if(f.hostname&&f.hostname!==window.location.hostname){f.classList.remove(this.activeClass),f.removeAttribute("aria-current");continue}const p=i(w),b=p===d,g=!this.exact&&p!=="/"&&d.startsWith(p+"/");b||g?(f.classList.add(this.activeClass),f.setAttribute("aria-current","page"),u.push(f)):(f.classList.remove(this.activeClass),f.removeAttribute("aria-current"))}$(this.dom,"ln-nav:update",{target:this.dom,activeLinks:u})},o.prototype.destroy=function(){if(!this.dom[t])return;this.observer&&this.observer.disconnect(),window.removeEventListener("popstate",this.updateHandler);const s=history._lnNavCallbacks.indexOf(this.updateHandler);s!==-1&&history._lnNavCallbacks.splice(s,1),delete this.dom[t]};function i(s){try{return new URL(s,window.location.href).pathname.replace(/\/$/,"")||"/"}catch{return s.replace(/\/$/,"")||"/"}}function l(s,a){const c=s[t];if(c){if(a===e){if(!s.hasAttribute(e)){c.destroy();return}const d=c.activeClass,u=s.getAttribute(e)||"active";if(d!==u){const f=s.querySelectorAll("a");for(const w of f)d&&w.classList.remove(d);c.activeClass=u}}c.update()}}he(e,t,o,"ln-nav",{attributes:n})})()})();
@@ -0,0 +1,25 @@
1
+ {
2
+ "$comment": "This file is partly generated. The $comment, component, generator, and each attribute's direction, sources, type, values, fallback, and description keys are owned by the generator and synchronized from JS source code. All other keys are preserved and safe to hand-author. Regenerate with `npm run sync:ln-schemas`.",
3
+ "component": "ln-nav",
4
+ "generator": "scripts/sync-ln-schemas.mjs",
5
+ "attributes": {
6
+ "data-ln-nav": {
7
+ "direction": "author",
8
+ "sources": [
9
+ "src/ln-nav.js"
10
+ ],
11
+ "type": "string",
12
+ "fallback": "active",
13
+ "description": "CSS class name applied to active navigation links"
14
+ },
15
+ "data-ln-nav-exact": {
16
+ "direction": null,
17
+ "sources": [
18
+ "src/ln-nav.js"
19
+ ],
20
+ "type": "boolean",
21
+ "fallback": false,
22
+ "description": "Match exact URL pathname instead of prefix matching"
23
+ }
24
+ }
25
+ }
@@ -1,4 +1,4 @@
1
- import { registerComponent, dispatch, dispatchCancelable } from '../../ln-core';
1
+ import { registerComponent, dispatch, dispatchCancelable, defineAttrs, attrSpec, attrBool } from '../../ln-core';
2
2
 
3
3
  (function () {
4
4
  const DOM_SELECTOR = 'data-ln-nav';
@@ -6,14 +6,27 @@ import { registerComponent, dispatch, dispatchCancelable } from '../../ln-core';
6
6
 
7
7
  if (window[DOM_ATTRIBUTE] !== undefined) return;
8
8
 
9
- // ─── pushState singleton patch ──────────────────────────────
10
- const _pushStateCallbacks = [];
9
+ // ─── Attribute Contract (SSOT) ──────────────────────────
10
+ const ATTRIBUTES = {
11
+ 'data-ln-nav': { effect: _syncAttribute, type: 'string', fallback: 'active', description: 'CSS class name applied to active navigation links' },
12
+ 'data-ln-nav-exact': { prop: 'exact', read: attrBool, effect: _syncAttribute, type: 'boolean', fallback: false, description: 'Match exact URL pathname instead of prefix matching' }
13
+ };
14
+
15
+ const ATTR_SPEC = attrSpec(ATTRIBUTES);
16
+
17
+ // ─── pushState / replaceState singleton patch ──────────────
18
+ history._lnNavCallbacks = history._lnNavCallbacks || [];
11
19
 
12
20
  if (!history._lnNavPatched) {
13
21
  const _origPushState = history.pushState;
14
22
  history.pushState = function () {
15
23
  _origPushState.apply(history, arguments);
16
- for (const cb of _pushStateCallbacks) { cb(); }
24
+ for (const cb of history._lnNavCallbacks) { cb(); }
25
+ };
26
+ const _origReplaceState = history.replaceState;
27
+ history.replaceState = function () {
28
+ _origReplaceState.apply(history, arguments);
29
+ for (const cb of history._lnNavCallbacks) { cb(); }
17
30
  };
18
31
  history._lnNavPatched = true;
19
32
  }
@@ -22,14 +35,14 @@ import { registerComponent, dispatch, dispatchCancelable } from '../../ln-core';
22
35
 
23
36
  function _component(dom) {
24
37
  this.dom = dom;
38
+ defineAttrs(this, dom, ATTR_SPEC);
25
39
  this.activeClass = dom.getAttribute(DOM_SELECTOR) || 'active';
26
- this.exact = dom.hasAttribute('data-ln-nav-exact');
27
40
 
28
41
  this.updateHandler = () => this.update();
29
42
 
30
43
  // Listen to navigation events
31
44
  window.addEventListener('popstate', this.updateHandler);
32
- _pushStateCallbacks.push(this.updateHandler);
45
+ history._lnNavCallbacks.push(this.updateHandler);
33
46
 
34
47
  // Observe DOM changes inside this nav element
35
48
  this.observer = new MutationObserver(() => this.update());
@@ -49,6 +62,7 @@ import { registerComponent, dispatch, dispatchCancelable } from '../../ln-core';
49
62
  const links = Array.from(this.dom.querySelectorAll('a'));
50
63
  const currentPath = window.location.pathname;
51
64
  const normalizedCurrent = _normalizeUrl(currentPath);
65
+ const activeLinks = [];
52
66
 
53
67
  for (const link of links) {
54
68
  const href = link.getAttribute('href');
@@ -72,13 +86,14 @@ import { registerComponent, dispatch, dispatchCancelable } from '../../ln-core';
72
86
  if (isExact || isParent) {
73
87
  link.classList.add(this.activeClass);
74
88
  link.setAttribute('aria-current', 'page');
89
+ activeLinks.push(link);
75
90
  } else {
76
91
  link.classList.remove(this.activeClass);
77
92
  link.removeAttribute('aria-current');
78
93
  }
79
94
  }
80
95
 
81
- dispatch(this.dom, 'ln-nav:update', { target: this.dom });
96
+ dispatch(this.dom, 'ln-nav:update', { target: this.dom, activeLinks: activeLinks });
82
97
  };
83
98
 
84
99
  _component.prototype.destroy = function () {
@@ -87,11 +102,10 @@ import { registerComponent, dispatch, dispatchCancelable } from '../../ln-core';
87
102
  this.observer.disconnect();
88
103
  }
89
104
  window.removeEventListener('popstate', this.updateHandler);
90
- const idx = _pushStateCallbacks.indexOf(this.updateHandler);
105
+ const idx = history._lnNavCallbacks.indexOf(this.updateHandler);
91
106
  if (idx !== -1) {
92
- _pushStateCallbacks.splice(idx, 1);
107
+ history._lnNavCallbacks.splice(idx, 1);
93
108
  }
94
- dispatch(this.dom, 'ln-nav:destroyed', { target: this.dom });
95
109
  delete this.dom[DOM_ATTRIBUTE];
96
110
  };
97
111
 
@@ -126,8 +140,6 @@ import { registerComponent, dispatch, dispatchCancelable } from '../../ln-core';
126
140
  }
127
141
  instance.activeClass = newClass;
128
142
  }
129
- } else if (attrName === 'data-ln-nav-exact') {
130
- instance.exact = el.hasAttribute('data-ln-nav-exact');
131
143
  }
132
144
 
133
145
  instance.update();
@@ -136,7 +148,6 @@ import { registerComponent, dispatch, dispatchCancelable } from '../../ln-core';
136
148
  // ─── Init ──────────────────────────────────────────────────
137
149
 
138
150
  registerComponent(DOM_SELECTOR, DOM_ATTRIBUTE, _component, 'ln-nav', {
139
- extraAttributes: ['data-ln-nav-exact'],
140
- onAttributeChange: _syncAttribute
151
+ attributes: ATTRIBUTES
141
152
  });
142
153
  })();
@@ -0,0 +1,205 @@
1
+ # ln-number
2
+
3
+ > Applied to an `<input type="number" name="..." data-ln-number>` or text input. On initialization, it converts the visible element
4
+ > to `<input type="text" inputmode="decimal">` and injects a hidden `<input type="hidden" name="...">` for form submission.
5
+ > On user `input`, it parses digits, writes the unformatted number to `hiddenInput.value`, and writes the formatted localized
6
+ > string (`Intl.NumberFormat`) into `visibleInput.value` while preserving cursor position.
7
+
8
+ ## Usage
9
+
10
+ ```html
11
+ <input type="number" name="amount" data-ln-number>
12
+ ```
13
+
14
+ The component creates a hidden input that holds the raw numeric value for form submission and formats the visible input with locale-aware thousand separators. After initialization:
15
+
16
+ ```html
17
+ <input type="text" inputmode="decimal" data-ln-number>
18
+ <input type="hidden" name="amount" value="1234567">
19
+ ```
20
+
21
+ ## Loading & Source Files
22
+
23
+ ### Loading the Component
24
+
25
+ #### 1. In-Bundle (Standard Integration)
26
+ To load `ln-number` as part of the main `ln-ashlar` bundle, include the compiled bundle script:
27
+ ```html
28
+ <script src="dist/ln-ashlar.iife.js" defer></script>
29
+ ```
30
+
31
+ #### 2. Standalone (Zero-Dependency IIFE)
32
+ To load `ln-number` as a standalone component, include its compiled IIFE under the component directory:
33
+ ```html
34
+ <script src="components/ln-number/ln-number.js" defer></script>
35
+ ```
36
+
37
+ ### Source Files
38
+
39
+ * **Active Development Source**: [components/ln-number/src/ln-number.js](file:///c:/laragon/www/ln-ashlar/components/ln-number/src/ln-number.js) (source of truth)
40
+ * **Pure Mathematical & Formatting Model**: [components/ln-number/src/number-model.js](file:///c:/laragon/www/ln-ashlar/components/ln-number/src/number-model.js)
41
+ * **Compiled Standalone**: [components/ln-number/ln-number.js](file:///c:/laragon/www/ln-ashlar/components/ln-number/ln-number.js)
42
+
43
+ ## Attributes
44
+
45
+ | Attribute | On | Description |
46
+ |-----------|-----|-------------|
47
+ | `data-ln-number` | `<input>` | Enables number formatting |
48
+ | `data-ln-number-decimals` | `<input>` | Max decimal places (default: unlimited) |
49
+ | `data-ln-number-min` | `<input>` | Minimum allowed value |
50
+ | `data-ln-number-max` | `<input>` | Maximum allowed value |
51
+
52
+ ## Events
53
+
54
+ | Event | Bubbles | Cancelable | Detail |
55
+ |-------|---------|------------|--------|
56
+ | `ln-number:input` | yes | no | `{ value: Number, formatted: String }` |
57
+
58
+ ## API
59
+
60
+ ```javascript
61
+ const el = document.querySelector('[data-ln-number]');
62
+
63
+ el.lnNumber.value; // get raw number (Number or NaN if empty)
64
+ el.lnNumber.value = 1234.56; // set value programmatically — formats display
65
+ el.lnNumber.formatted; // get formatted display string
66
+
67
+ el.lnNumber.destroy(); // remove component, restore original input
68
+ ```
69
+
70
+ ## Locale
71
+
72
+ The component reads the nearest ancestor `[lang]` attribute (typically `<html lang>`); falls back to `navigator.language`. Locale changes propagate live — re-formatting all instances when `<html lang>` changes.
73
+
74
+ | `lang` | Display |
75
+ |---|---|
76
+ | `mk` | `1.234.567` |
77
+ | `en-US` | `1,234,567` |
78
+
79
+ ## Machine vs. human input
80
+
81
+ Two different parsing rules apply depending on where a value comes from:
82
+
83
+ - **Machine channel** — a pre-filled `value=""`, an authored `data-ln-value`, an authored `data-ln-number`,
84
+ and programmatic `el.value = "1234.56"` assignments are parsed canonically: dot is always the decimal
85
+ point, no locale grouping. This matches the HTML spec for `<input type="number">.value` and keeps authored
86
+ markup and backend payloads locale-independent — the same `data-ln-value="123.45"` means the same number
87
+ under every `lang`.
88
+ - **Human channel** — pasting and typing into the field are parsed with the active locale's separators
89
+ (`getLocale`), because that reflects what the person actually typed.
90
+
91
+ ### Backend contract for `data-ln-value` / `data-ln-number`
92
+
93
+ This is the standing raw-format contract for `data-ln-value` (see
94
+ [`ln-core`'s `data-ln-value` primitive](file:///c:/laragon/www/ln-ashlar/components/ln-core/README.md#the-data-ln-value-primitive) —
95
+ "plain number, dot decimal, NO thousands grouping") — `ln-number` now actually reads its inputs this way
96
+ instead of running them through locale-aware parsing:
97
+
98
+ - Dot as the decimal separator — `12345.67`.
99
+ - No grouping separators, ever — never `12,345.67`, never `12.345,67`.
100
+ - No currency symbol, no whitespace.
101
+ - A leading minus is allowed; a bare integer is a valid value.
102
+ - Display text stays free-form — the backend may put anything in the element's `textContent` or the visible
103
+ input's initial value; `ln-number` overwrites it with the locale-formatted number on init.
104
+
105
+ ## Examples
106
+
107
+ ```html
108
+ <!-- Basic -->
109
+ <div class="form-element">
110
+ <label for="amount">Amount</label>
111
+ <input type="number" id="amount" name="amount" data-ln-number>
112
+ </div>
113
+
114
+ <!-- With decimal limit -->
115
+ <div class="form-element">
116
+ <label for="price">Price</label>
117
+ <input type="number" id="price" name="price"
118
+ data-ln-number data-ln-number-decimals="2">
119
+ </div>
120
+
121
+ <!-- With min/max -->
122
+ <div class="form-element">
123
+ <label for="quantity">Quantity</label>
124
+ <input type="number" id="quantity" name="quantity"
125
+ data-ln-number data-ln-number-min="0" data-ln-number-max="999999">
126
+ </div>
127
+
128
+ <!-- Pre-filled value -->
129
+ <div class="form-element">
130
+ <label for="budget">Budget</label>
131
+ <input type="number" id="budget" name="budget" value="1500000"
132
+ data-ln-number>
133
+ </div>
134
+ ```
135
+
136
+ ## Integration with ln-validate
137
+
138
+ Place `data-ln-validate` on the same input. The `required` attribute stays
139
+ on the visible input and works as expected:
140
+
141
+ ```html
142
+ <div class="form-element">
143
+ <label for="salary">Salary</label>
144
+ <input type="number" id="salary" name="salary"
145
+ required data-ln-validate data-ln-number>
146
+ <ul data-ln-validate-errors>
147
+ <li class="hidden" data-ln-validate-error="required">Required field</li>
148
+ </ul>
149
+ </div>
150
+ ```
151
+
152
+ ## Integration with ln-form
153
+
154
+ Works automatically. `serializeForm()` reads the hidden input (which has the
155
+ `name`). `populateForm()` sets the hidden input's value, which triggers the
156
+ display update.
157
+
158
+ ---
159
+
160
+ ## 🔧 Internals
161
+
162
+ Source: `components/ln-number/src/ln-number.js` and `components/ln-number/src/number-model.js`. Each `[data-ln-number]` gets a `_component` instance at `element.lnNumber`, holding `dom` (visible input), `_hidden` (hidden input), and bound `_onInput`/`_onKeyDown`/`_onPaste` handlers.
163
+
164
+ ### Formatter cache
165
+
166
+ One `Intl.NumberFormat` instance per unique locale, cached at module level (`_formatterCache[locale]`), storing the formatter plus `groupSep`/`decimalSep` extracted once via `formatToParts()`. Supports standard spaces, commas, dots, and Unicode narrow no-break space (`\u202F` for `fr-FR`). Separate cache keys exist for decimal-capped and user-decimal-preserving formatters.
167
+
168
+ ### Input flow
169
+
170
+ ```mermaid
171
+ flowchart TD
172
+ A["Read dom.value as raw"] --> B{"raw === '' or raw === '-'"}
173
+ B -->|Yes| C["Set _hidden = '', dispatch ln-number:input, Return"]
174
+ B -->|No| D["Extract locale separators and clean numeric string"]
175
+ D --> E{"isNaN(num)"}
176
+ E -->|Yes| F["Set _hidden = '', dispatch ln-number:input, Return"]
177
+ E -->|No| G["Transformation: Apply data-ln-number-decimals cap"]
178
+ G --> H{"maxAttr !== null && num > max"}
179
+ H -->|Yes| I["Clamp num = max, Format max, Set _hidden = max, Set dom.value = max, Dispatch ln-number:input, Return"]
180
+ H -->|No| J{"workingStr ends with decimalSep"}
181
+ J -->|Yes| K["Set _hidden = num, Keep workingStr, Dispatch ln-number:input, Return"]
182
+ J -->|No| L{"afterDecimal ends with '0'"}
183
+ L -->|Yes| M["Set _hidden = num, Keep workingStr, Dispatch ln-number:input, Return"]
184
+ L -->|No| N["Standard Format: Format num, Restore cursor, Set _hidden = num, Set dom.value = formatted, Dispatch ln-number:input"]
185
+ ```
186
+
187
+ On every `input` event:
188
+ 1. **Empty / Minus Sign:** Clears `_hidden` and dispatches `ln-number:input`.
189
+ 2. **Parsing & Cleaning:** Numeric strings are cleaned of separators and parsed according to active locale rules.
190
+ 3. **Decimal Cap Transformation:** `data-ln-number-decimals` truncates excessive decimal digits *before* trailing zero/separator checks.
191
+ 4. **Max Clamping:** Evaluated *before* trailing separators/zeros to strictly prevent typing values beyond `max`.
192
+ 5. **Trailing Decimals & Zeros:** Preserves input text during active progressive decimal typing, synchronizes `_hidden`, and dispatches `ln-number:input`.
193
+ 6. **Standard Formatting:** `Intl.NumberFormat` formats the display value, restores cursor position via digit-count index calculation, synchronizes `_hidden`, and dispatches `ln-number:input`.
194
+
195
+ ### Backspace Separator Interception
196
+
197
+ When the cursor is positioned directly after a thousand separator (e.g. `1,|234`), pressing Backspace is intercepted by `_onKeyDown` (guarded against active range selections). It deletes the preceding digit directly and dispatches a native `input` event, keeping parent form validations (`ln-validate`, `ln-autosave`) synchronized and preventing infinite cursor traps.
198
+
199
+ ### Hidden input value interceptor
200
+
201
+ `hidden.value` is wrapped via `Object.defineProperty` so programmatic sets (e.g. `populateForm()` writing `hidden.value = "1234"`) route through the same parse → format → display path as user input. Internal code writes through `_setHiddenRaw()`, which calls the prototype's original setter directly — bypassing the custom setter avoids the interceptor re-triggering itself (infinite loop).
202
+
203
+ ### Auto-init
204
+
205
+ A single `document.body` `MutationObserver` watches `childList` (subtree — new `[data-ln-number]` elements auto-initialize via `findElements`) and `attributes` on `data-ln-number` (attribute added to an existing element initializes it in place).
@@ -1,13 +1,13 @@
1
- @use '../../scss/config/mixins' as *;
2
-
3
- [data-ln-debug] {
4
- // 1. Number element misuse: data-ln-number belongs on <input>, <span>, <time>, or <td>
5
- [data-ln-number]:not(input, span, time, td, p, div, b, strong, data) {
6
- @include dev-inline-error("data-ln-number belongs on <input>, <span>, <time>, or <td>");
7
- }
8
-
9
- // 2. Number input missing ID: input[data-ln-number] must have an id for proper labeling/association
10
- input[data-ln-number]:not([id]) {
11
- @include dev-inline-error("data-ln-number is missing required 'id' attribute");
12
- }
13
- }
1
+ @use '../../theme/config/mixins' as *;
2
+
3
+ [data-ln-debug] {
4
+ // 1. Number element misuse: data-ln-number belongs on <input>, <span>, <time>, or <td>
5
+ [data-ln-number]:not(input, span, time, td, p, div, b, strong, data) {
6
+ @include dev-inline-error("data-ln-number belongs on <input>, <span>, <time>, or <td>");
7
+ }
8
+
9
+ // 2. Number input missing ID: input[data-ln-number] must have an id for proper labeling/association
10
+ input[data-ln-number]:not([id]) {
11
+ @include dev-inline-error("data-ln-number is missing required 'id' attribute");
12
+ }
13
+ }
@@ -0,0 +1 @@
1
+ (function(){"use strict";function H(){return typeof window>"u"?!1:window.lnDebug===!0||window.lnCore&&window.lnCore._debugSink?!0:typeof document<"u"&&document.body?document.body.hasAttribute("data-ln-debug")||document.body.querySelector("[data-ln-debug]")!==null:!1}function k(e){if(typeof window>"u")return!1;if(window.lnDebug===!0)return!0;if(window.lnCore&&window.lnCore._debugIsContained)return e?window.lnCore._debugIsContained(e):window.lnCore._debugSink!==null;if(e&&e.closest){const t=e.closest("[data-ln-debug]");return!(!t||typeof document<"u"&&t===document.documentElement)}return typeof document<"u"&&document.body?document.body.hasAttribute("data-ln-debug"):!1}if(typeof window<"u"&&(window.lnCore=window.lnCore||{},!window.lnCore._warnBound)){window.lnCore._warnBound=!0;const e=console.warn;console.warn=function(...t){if(typeof t[0]=="string"&&(t[0].startsWith("[ln-")||t[0].startsWith("[lnCore"))){let r=null;for(let o=1;o<t.length;o++)if(t[o]&&t[o].nodeType===1){r=t[o];break}if(!k(r))return}e.apply(console,t)}}function A(e,t,i){const r=i||{};window.lnCore._debugSink&&window.lnCore._debugSink("event",t,e,r),e.dispatchEvent(new CustomEvent(t,{bubbles:!0,detail:r}))}function E(e,t){if(!document.body){document.addEventListener("DOMContentLoaded",function(){E(e,t)}),console.warn("["+t+'] Script loaded before <body> — add "defer" to your <script> tag');return}e()}function J(e,t,{get:i,set:r}){Object.defineProperty(e,"value",{get:function(){return i?i.call(this):t.get.call(this)},set:function(o){r?r.call(this,o,l=>t.set.call(this,l)):t.set.call(this,o)},configurable:!0})}const V={};function z(e,t){V[e]=t}function X(e){return V[e]||{ingress:t=>t,egress:t=>t}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerDataMapper=z,window.lnCore.getDataMapper=X);function y(e){const t=e?e.closest("[lang]"):null,i=(t?t.getAttribute("lang")||t.lang:null)||(typeof document<"u"&&document.documentElement?document.documentElement.getAttribute("lang")||document.documentElement.lang:null)||(typeof navigator<"u"?navigator.language:null);return i?i.trim():"en-US"}function M(){typeof window>"u"||(window.lnCore=window.lnCore||{},!window.lnCore._localeObserverBound&&(window.lnCore._localeObserverBound=!0,E(function(){new MutationObserver(function(){A(document,"ln-core:locale-change",{})}).observe(document.documentElement,{attributes:!0,attributeFilter:["lang"],subtree:!0})},"ln-core")))}const j={};function Y(e,t){if(!e||typeof t!="object")return;const i=e.toLowerCase().split("-")[0];j[i]=t}function Z(e){if(!e)return null;const t=e.toLowerCase().split("-")[0];return j[t]||null}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerLocaleFallback=Y,window.lnCore.getLocaleFallback=Z,window.lnCore.ensureLocaleObserver=M);const O={};function ee(e,t){O[e]||(O[e]=document.querySelector('[data-ln-template="'+e+'"]'));const i=O[e];return i?i.content.cloneNode(!0):(console.warn("["+(t||"ln-core")+'] Template "'+e+'" not found'),null)}function q(e,t){if(!e||!t)return e;const i=e.querySelectorAll("[data-ln-field]");for(let n=0;n<i.length;n++){const s=i[n],a=s.getAttribute("data-ln-field");t[a]!=null&&(s.textContent=t[a])}const r=e.querySelectorAll("[data-ln-attr]");for(let n=0;n<r.length;n++){const s=r[n],a=s.getAttribute("data-ln-attr").split(",");for(let d=0;d<a.length;d++){const u=a[d].trim().split(":");if(u.length!==2)continue;const c=u[0].trim(),f=u[1].trim();t[f]!=null&&s.setAttribute(c,t[f])}}const o=e.querySelectorAll("[data-ln-show]");for(let n=0;n<o.length;n++){const s=o[n],a=s.getAttribute("data-ln-show");a in t&&s.classList.toggle("hidden",!t[a])}const l=e.querySelectorAll("[data-ln-class]");for(let n=0;n<l.length;n++){const s=l[n],a=s.getAttribute("data-ln-class").split(",");for(let d=0;d<a.length;d++){const u=a[d].trim().split(":");if(u.length!==2)continue;const c=u[0].trim(),f=u[1].trim();f in t&&s.classList.toggle(c,!!t[f])}}return e}function te(e,t){e.matches&&e.matches("[data-ln-form], [data-ln-fillable]")&&(window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",e,t??null),e.dispatchEvent(new CustomEvent("ln-fill",{detail:t??null,bubbles:!0})));const i=e.querySelectorAll("[data-ln-form], [data-ln-fillable]");for(let r=0;r<i.length;r++)window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",i[r],t??null),i[r].dispatchEvent(new CustomEvent("ln-fill",{detail:t??null,bubbles:!0}));return e}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._fillBound||(window.lnCore._fillBound=!0,document.addEventListener("ln-fill",function(e){if(!(!e.target.matches||!e.target.matches("[data-ln-fillable]")))if(e.detail)q(e.target,e.detail);else{const t=e.target.querySelectorAll("[data-ln-field]");for(let i=0;i<t.length;i++)t[i].textContent=""}})));function W(e,t){if(!e||!t)return e;const i=document.createTreeWalker(e,NodeFilter.SHOW_TEXT);for(;i.nextNode();){const l=i.currentNode;l.textContent.indexOf("{{")!==-1&&(l.textContent=l.textContent.replace(/\{\{\s*(\w+)\s*\}\}/g,function(n,s){return t[s]!==void 0?t[s]:""}))}const r=function(l,n){return t[n]!==void 0?t[n]:""},o=Array.from(e.querySelectorAll("*"));e.nodeType===1&&o.push(e);for(let l=0;l<o.length;l++){const n=o[l],s=n.attributes;for(let a=0;a<s.length;a++){const d=s[a];d.value.indexOf("{{")!==-1&&n.setAttribute(d.name,d.value.replace(/\{\{\s*(\w+)\s*\}\}/g,r))}}return e}function ne(e,t,i,r,o,l){const n={};for(let a=0;a<e.children.length;a++){const d=e.children[a],u=d.getAttribute("data-ln-render-key");u&&(n[u]=d)}const s=document.createDocumentFragment();for(let a=0;a<t.length;a++){const d=t[a],u=String(r(d));let c=n[u];if(c)o(c,d,a);else{const f=ee(i,l);if(!f||(W(f,d),c=f.firstElementChild,!c))continue;c.setAttribute("data-ln-render-key",u),o(c,d,a)}s.appendChild(c)}e.textContent="",e.appendChild(s)}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.fillTemplate=W,window.lnCore.fill=q,window.lnCore.lnFill=te,window.lnCore.renderList=ne);function B(e,t,i,r,o){if(!e||t===null)return!0;const l=r||"ln-component",n=e.type;if(n==="trigger"||n==="marker"||n==="string"||n==="list"||!n||t===""&&e.fallback!==void 0)return!0;const s=a=>{o?console.warn(a,o):console.warn(a)};if(n==="boolean"){const a=t.trim().toLowerCase();return a!==""&&a!=="true"&&a!=="false"&&a!=="1"&&a!=="0"?(s(`[${l}] Invalid value "${t}" for boolean attribute "${i}". Allowed: "true", "false", or presence-only.`),!1):!0}if(n==="enum"){const a=e.values||[];return a.includes(t)?!0:(s(`[${l}] Invalid value "${t}" for attribute "${i}". Allowed: ${a.join(", ")}. Fallback: "${e.fallback}".`),!1)}if(n==="integer"){if(!/^-?\d+$/.test(t))return s(`[${l}] Invalid integer "${t}" for attribute "${i}". Fallback: ${e.fallback}.`),!1;const a=parseInt(t,10);return e.min!==void 0&&a<e.min?(s(`[${l}] Value ${a} for attribute "${i}" is less than min (${e.min}).`),!1):e.max!==void 0&&a>e.max?(s(`[${l}] Value ${a} for attribute "${i}" is greater than max (${e.max}).`),!1):!0}if(n==="float")return isNaN(Number(t))?(s(`[${l}] Invalid float "${t}" for attribute "${i}". Fallback: ${e.fallback}.`),!1):!0;if(n==="json")try{return JSON.parse(t),!0}catch(a){return s(`[${l}] Invalid JSON for attribute "${i}": ${a.message}. Fallback: ${e.fallback}.`),!1}return!0}function ie(e){const t={};for(const i in e){const r=e[i];r&&r.effect&&(t[i]=r.effect)}return Object.keys(t).length?t:null}function re(e){if(e.onAttrChange&&!e.declared)return null;const t=new Set;if(e.effects)for(const i in e.effects)t.add(i);if(e.onAttrChange&&e.declared)for(const i of e.declared)t.add(i);return t}function T(e,t,i,r){if(e.nodeType!==1)return;const l=t.indexOf("[")!==-1||t.indexOf(".")!==-1||t.indexOf("#")!==-1?t:"["+t+"]",n=Array.from(e.querySelectorAll(l));e.matches&&e.matches(l)&&n.push(e);for(const s of n)if(!s[i]){window.lnCore._persistSink&&s.hasAttribute("data-ln-persist")&&window.lnCore._persistSink(s,t);try{s[i]=new r(s)}catch(a){console.error("["+i+"] init failed",s,a)}}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._bootHolds=window.lnCore._bootHolds||0,window.lnCore._bootQueue=window.lnCore._bootQueue||[]);function oe(){return typeof window<"u"&&window.lnCore&&window.lnCore._bootHolds||0}function le(e){typeof window<"u"?(window.lnCore=window.lnCore||{},window.lnCore._bootHolds=window.lnCore._bootHolds||0,window.lnCore._bootQueue=window.lnCore._bootQueue||[],window.lnCore._bootHolds>0?window.lnCore._bootQueue.push(e):setTimeout(e,0)):e()}function P(){window.lnCore=window.lnCore||{};const e=window.lnCore._attrRegistry=window.lnCore._attrRegistry||{byAttr:new Map,reactive:[],persist:[]};return e.byReactive=e.byReactive||new Map,e.reactiveWildcard=e.reactiveWildcard||[],e}function se(e){const t=P(),i=e.observed||[];for(let r=0;r<i.length;r++){const o=i[r];t.byAttr.has(o)||t.byAttr.set(o,[]),t.byAttr.get(o).push(e)}if(t.byDeclaredAttr=t.byDeclaredAttr||new Map,e.attributes)for(const r in e.attributes){t.byDeclaredAttr.has(r)||t.byDeclaredAttr.set(r,[]);const o=t.byDeclaredAttr.get(r);o.some(l=>l.componentTag===e.componentTag)||o.push({spec:e.attributes[r],componentTag:e.componentTag})}if(e.onAttrChange||e.effects){t.reactive.push(e);const r=re(e);if(r===null)t.reactiveWildcard.push(e);else for(const o of r)t.byReactive.has(o)||t.byReactive.set(o,[]),t.byReactive.get(o).push(e)}e.persist&&t.persist.push(e)}function K(e,t,i,r){for(let o=0;o<e.length;o++){const l=e[o];if(!t[l.attribute])continue;const n=l.effects&&l.effects[i];n?n(t,i,r):l.onAttrChange&&(!l.declared||l.declared.has(i))&&l.onAttrChange(t,i,r)}}function ae(e){const t=e.target,i=e.attributeName;if(e.oldValue===t.getAttribute(i))return;const r=P(),o=r.byAttr.get(i);if(H()&&r.byDeclaredAttr&&r.byDeclaredAttr.has(i)&&k(t)){const l=r.byDeclaredAttr.get(i),n=t.getAttribute(i);for(let s=0;s<l.length;s++)B(l[s].spec,n,i,l[s].componentTag,t)}if(window.lnCore._debugSink&&(i.indexOf("data-ln-")===0||o)&&window.lnCore._debugSink("attr",i,t,{oldValue:e.oldValue,newValue:t.getAttribute(i)}),i.indexOf("data-ln-")===0){const l=r.byReactive.get(i);l&&K(l,t,i,e.oldValue),r.reactiveWildcard.length&&K(r.reactiveWildcard,t,i,e.oldValue)}if(o)for(let l=0;l<o.length;l++){const n=o[l];if(n.handler){n.handler(t,i,e.oldValue);continue}n.onAttributeChange&&t[n.attribute]?n.onAttributeChange(t,i):(T(t,n.selector,n.attribute,n.ComponentFn),n.onInit&&n.onInit(t))}}function ue(){window.lnCore=window.lnCore||{},!window.lnCore._attrObserverBound&&(window.lnCore._attrObserverBound=!0,E(function(){new MutationObserver(function(t){for(let i=0;i<t.length;i++)try{ae(t[i])}catch(r){console.error("[ln-core] mutation handler failed",t[i].target,r)}}).observe(document.body,{attributes:!0,subtree:!0,attributeOldValue:!0})},"ln-core"))}function U(){return window.lnCore=window.lnCore||{},window.lnCore._lifecycleRegistry=window.lnCore._lifecycleRegistry||[]}function ce(e){const t=U();if(t.length){if(e.target)for(let i=0;i<t.length;i++){const r=t[i];if(r.onSubtreeChange){const o=r.query,l=e.target.nodeType===1?e.target.matches(o)?e.target:e.target.closest(o):e.target.parentElement?e.target.parentElement.closest(o):null;l&&r.onSubtreeChange(l,e)}}for(let i=0;i<e.addedNodes.length;i++){const r=e.addedNodes[i];if(r.nodeType===1)for(let o=0;o<t.length;o++){const l=t[o];T(r,l.selector,l.attribute,l.ComponentFn),l.onInit&&l.onInit(r)}}for(let i=0;i<e.removedNodes.length;i++){const r=e.removedNodes[i];if(r.nodeType===1)for(let o=0;o<t.length;o++){const l=t[o],n=l.query,s=Array.from(r.querySelectorAll(n));r.matches&&r.matches(n)&&s.push(r);for(let a=0;a<s.length;a++){const d=s[a];if(!document.contains(d)){const u=d[l.attribute];if(u&&typeof u.destroy=="function")try{u.destroy()}catch(c){console.error("["+l.attribute+"] destroy failed",d,c)}delete d[l.attribute]}}}}}}function de(){window.lnCore=window.lnCore||{},!window.lnCore._lifecycleObserverBound&&(window.lnCore._lifecycleObserverBound=!0,E(function(){new MutationObserver(function(t){for(let i=0;i<t.length;i++){const r=t[i];if(r.type==="childList")try{ce(r)}catch(o){console.error("[ln-core] lifecycle handler failed",r.target,o)}}}).observe(document.body,{childList:!0,subtree:!0})},"ln-core"))}function fe(e,t,i,r,o={}){const l=o.extraAttributes||[],n=o.onAttributeChange||null,s=o.onSubtreeChange||null,a=o.onInit||null,d=o.onAttrChange||null,u=o.effects||null,c=o.attributes||null,f=c?ie(c):u,p=c?new Set(Object.keys(c)):null,w=o.persist||null;function m(N){const h=N||document.body;if(T(h,e,t,i),c&&H())for(const g in c){const R=c[g],L=Array.from(h.querySelectorAll("["+g+"]"));h.matches&&h.matches("["+g+"]")&&L.push(h);for(let I=0;I<L.length;I++){const $=L[I];k($)&&B(R,$.getAttribute(g),g,r,$)}}a&&a(h)}const b=[];if(e.indexOf("[")!==-1){const N=/\[([\w-]+)/g;let h;for(;(h=N.exec(e))!==null;)b.push(h[1])}else b.push(e);se({selector:e,attribute:t,componentTag:r,attributes:c,ComponentFn:i,onInit:a,observed:b.concat(l),onAttributeChange:n,onAttrChange:d,effects:f,declared:p,persist:w}),ue();const D=e.indexOf("[")!==-1||e.indexOf(".")!==-1||e.indexOf("#")!==-1?e:"["+e+"]";U().push({selector:e,attribute:t,ComponentFn:i,onInit:a,onSubtreeChange:s,query:D}),de(),window[t]=m;function v(){oe()>0?le(function(){m(document.body)}):m(document.body)}return document.readyState==="loading"?document.addEventListener("DOMContentLoaded",v):v(),m}function G(e){return(e||"").replace(/^#/,"")}function F(e){const t=e===void 0?location.hash:e,i={},r=G(t);if(!r)return i;const o=r.split("&");for(let l=0;l<o.length;l++){const n=o[l];if(!n)continue;const s=n.indexOf(":"),a=s>-1?n.slice(0,s):n,d=s>-1?n.slice(s+1):"";if(a)try{i[a]=decodeURIComponent(d)}catch{i[a]=d}}return i}function he(e){if(!e)return null;const t=F();return e in t?t[e]:null}function we(e,t){if(!e)return;const i=F();t==null?delete i[e]:i[e]=String(t);const o=Object.keys(i).map(function(l){const n=i[l];return n===""?l:l+":"+encodeURIComponent(n)}).join("&");G(location.hash)!==o&&(location.hash=o)}function pe(e){return e.button===1||e.ctrlKey||e.metaKey||e.shiftKey?!1:(e.preventDefault(),!0)}function me(e,t){if(!e||!e.hasAttribute("data-ln-hash"))return null;const i=e.getAttribute("data-ln-hash");if(i&&i.trim()!=="")return i.trim();const r=e.getAttribute("data-ln-sort")||e.getAttribute("data-ln-search-for")||e.getAttribute("data-ln-search")||e.getAttribute("data-ln-filter")||e.id;return r?t?r+"-"+t:r:t||null}function be(e,t){return!t||t==="none"||e===null||e===void 0?null:String(e)+"."+t}function ge(e){return!e||typeof e!="string"?null:e.endsWith(".asc")?{fieldOrColumn:e.slice(0,-4),direction:"asc"}:e.endsWith(".desc")?{fieldOrColumn:e.slice(0,-5),direction:"desc"}:null}function ye(e,t){return!e||!Array.isArray(t)||t.length===0?null:e+":"+t.map(encodeURIComponent).join(",")}function Ce(e){if(!e||typeof e!="string")return null;const t=e.indexOf(":");if(t===-1)return null;const i=e.slice(0,t),r=e.slice(t+1),o=r?r.split(",").map(function(l){try{return decodeURIComponent(l)}catch{return l}}).filter(Boolean):[];return{key:i,values:o}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.hashParse=F,window.lnCore.hashGet=he,window.lnCore.hashSet=we,window.lnCore.hashLinkClick=pe,window.lnCore.resolveHashNamespace=me,window.lnCore.hashSortEncode=be,window.lnCore.hashSortDecode=ge,window.lnCore.hashFilterEncode=ye,window.lnCore.hashFilterDecode=Ce);const C={};function S(e){const t=e||"default";if(!C[t]){const i=new Intl.NumberFormat(e,{useGrouping:!0}),r=i.formatToParts(1234.5);let o="",l=".";for(let n=0;n<r.length;n++)r[n].type==="group"&&(o=r[n].value),r[n].type==="decimal"&&(l=r[n].value);C[t]={groupSep:o,decimalSep:l,fmt:i}}return C[t]}function Q(e,t,i){if(e==null||typeof e!="string")return"";let r=e.trim();return r===""?"":(r=r.replace(/[$€£¥]/g,""),t&&(r=r.split(t).join("")),r=r.replace(/\s/g,""),i&&i!=="."&&(r=r.replace(i,".")),r=r.replace(/[^\d.-]/g,""),r)}function _e(e,t){if(typeof e=="number")return isNaN(e)?NaN:e;if(e==null||typeof e!="string")return NaN;const i=e.trim();if(i===""||i==="-")return NaN;const r=S(t),o=Q(i,r.groupSep,r.decimalSep);if(o===""||o==="-")return NaN;const l=parseFloat(o);return isNaN(l)?NaN:l}function _(e,t,i={}){if(typeof e!="number"||isNaN(e)||!Number.isFinite(e))return"";const r=t||"default",o=i.maxDecimals!=null?parseInt(i.maxDecimals,10):null,l=i.userDecimals!=null?i.userDecimals:null;if(o!==null){const n=r+"|max:"+o;return C[n]||(C[n]=new Intl.NumberFormat(t,{useGrouping:!0,minimumFractionDigits:0,maximumFractionDigits:o})),C[n].format(e)}if(l!==null&&l>0){const n=r+"|exact:"+l;return C[n]||(C[n]=new Intl.NumberFormat(t,{useGrouping:!0,minimumFractionDigits:l,maximumFractionDigits:l})),C[n].format(e)}return S(t).fmt.format(e)}function Ae(e,t){if(!e)return 0;if(t<=0)return e.startsWith("-")?1:0;let i=t,r=0;for(let o=0;o<e.length&&i>0;o++)r=o+1,/[0-9]/.test(e[o])&&i--;return i>0&&(r=e.length),r}(function(){const e="data-ln-number",t="lnNumber";if(window[t]!==void 0)return;function i(n){const s=n[t];s&&(s.isTextElement?s._initTextElement():isNaN(s.value)||s._displayFormatted(s.value))}const r={"data-ln-number":{type:"marker",effect:i,description:"Activates localized number formatting on input or text element"},"data-ln-value":{type:"float",effect:i,description:"Raw unformatted numeric value"},"data-ln-number-decimals":{type:"integer",fallback:0,min:0,max:20,effect:i,description:"Number of decimal fraction digits"},"data-ln-number-min":{type:"float",effect:i,description:"Minimum allowed numeric value"},"data-ln-number-max":{type:"float",effect:i,description:"Maximum allowed numeric value"}},o=Object.getOwnPropertyDescriptor(HTMLInputElement.prototype,"value");function l(n){if(n[t])return n[t];n[t]=this,this.dom=n;const s=this;if(this._onLocaleChange=function(){s.isTextElement?s._formatTextContent():isNaN(s.value)||s._displayFormatted(s.value)},M(),document.addEventListener("ln-core:locale-change",this._onLocaleChange),n.tagName!=="INPUT")return this.isTextElement=!0,this._initTextElement(),this;const a=document.createElement("input");a.type="hidden",a.name=n.name,n.removeAttribute("name"),n.hasAttribute("data-ln-fill-as")&&a.setAttribute("data-ln-fill-as",n.getAttribute("data-ln-fill-as")),n.type="text",n.setAttribute("inputmode","decimal"),n.insertAdjacentElement("afterend",a),this._hidden=a,Object.defineProperty(a,"value",{get:function(){return o.get.call(a)},set:function(u){if(o.set.call(a,u),u!==""&&!isNaN(parseFloat(u))){const c=s.dom.getAttribute("data-ln-number-decimals");s._setDisplayRaw(_(parseFloat(u),y(s.dom),{maxDecimals:c}))}else s._setDisplayRaw("");s.dom.dispatchEvent(new Event("input",{bubbles:!0}))}}),J(n,o,{get:function(){return o.get.call(n)},set:function(u){if(u===""){s._setDisplayRaw(""),s._setHiddenRaw(""),n.dispatchEvent(new Event("input",{bubbles:!0}));return}const c=typeof u=="number"?u:parseFloat(String(u));if(isNaN(c))s._setDisplayRaw(String(u)),s._setHiddenRaw("");else{s._setHiddenRaw(c);const f=n.getAttribute("data-ln-number-decimals");s._setDisplayRaw(_(c,y(n),{maxDecimals:f}))}n.dispatchEvent(new Event("input",{bubbles:!0}))}}),this._onInput=function(){s._handleInput()},n.addEventListener("input",this._onInput),this._onKeyDown=function(u){if(u.key!=="Backspace")return;const c=n.selectionStart,f=n.selectionEnd;if(c!==f||c===0)return;const p=S(y(n)),w=o.get.call(n),m=w[c-1];if(m===p.groupSep||/\s/.test(m)){u.preventDefault();const b=c-2>=0?c-2:0,x=w.slice(0,b)+w.slice(c);o.set.call(n,x),n.setSelectionRange(b,b),n.dispatchEvent(new Event("input",{bubbles:!0}))}},n.addEventListener("keydown",this._onKeyDown),this._onPaste=function(u){u.preventDefault();const c=(u.clipboardData||window.clipboardData).getData("text"),f=_e(c,y(n));s.value=isNaN(f)?NaN:f},n.addEventListener("paste",this._onPaste);const d=n.value;if(d!==""){const u=parseFloat(d);if(!isNaN(u)){const c=n.getAttribute("data-ln-number-decimals");this._setHiddenRaw(u),this._setDisplayRaw(_(u,y(n),{maxDecimals:c})),n.dispatchEvent(new Event("input",{bubbles:!0}))}}return this}l.prototype._initTextElement=function(){const n=this.dom;let s=n.getAttribute("data-ln-value"),a=n.getAttribute("data-ln-number"),d=null;s!==null&&s!==""?d=s:a!==null&&a!==""&&a!=="true"?d=a:d=n.textContent.trim();const u=parseFloat(d);isNaN(u)?this._rawValue=null:(this._rawValue=u,n.hasAttribute("data-ln-value")||n.setAttribute("data-ln-value",String(u)),this._formatTextContent())},l.prototype._formatTextContent=function(){if(this._rawValue!==null&&!isNaN(this._rawValue)){const n=this.dom.getAttribute("data-ln-number-decimals");this.dom.textContent=_(this._rawValue,y(this.dom),{maxDecimals:n})}},l.prototype._handleInput=function(){const n=this.dom,s=o.get.call(n);if(s===""){this._setHiddenRaw(""),A(n,"ln-number:input",{value:NaN,formatted:""});return}if(s==="-"){this._setHiddenRaw(""),A(n,"ln-number:input",{value:NaN,formatted:"-"});return}const a=n.selectionStart;let d=0;for(let h=0;h<a;h++)/[0-9]/.test(s[h])&&d++;const u=y(n),c=S(u);let f=s,p=Q(s,c.groupSep,c.decimalSep),w=parseFloat(p);if(isNaN(w)){this._setHiddenRaw(""),A(n,"ln-number:input",{value:NaN,formatted:s});return}const m=n.getAttribute("data-ln-number-decimals"),b=p.indexOf(".");if(m!==null&&b!==-1){const h=parseInt(m,10),g=p.slice(b+1);if(h===0)p=p.slice(0,b),f=f.split(c.decimalSep)[0],w=parseFloat(p),this._setDisplayRaw(f);else if(g.length>h){p=p.slice(0,b+1+h);const R=f.split(c.decimalSep);f=R[0]+c.decimalSep+R[1].slice(0,h),w=parseFloat(p),this._setDisplayRaw(f)}}const x=n.getAttribute("data-ln-number-max");if(x!==null&&w>parseFloat(x)){const h=parseFloat(x),g=_(h,u,{maxDecimals:m});this._setDisplayRaw(g),this._setHiddenRaw(h),n.setSelectionRange(g.length,g.length),A(n,"ln-number:input",{value:h,formatted:g});return}if(f.endsWith(c.decimalSep)||c.decimalSep!=="."&&f.endsWith(".")){this._setHiddenRaw(w),A(n,"ln-number:input",{value:w,formatted:f});return}const D=p.indexOf(".");if(D!==-1&&p.slice(D+1).endsWith("0")){this._setHiddenRaw(w),A(n,"ln-number:input",{value:w,formatted:f});return}let v;if(m!==null)v=_(w,u,{maxDecimals:m});else{const h=D!==-1?p.slice(D+1).length:0;v=_(w,u,{userDecimals:h})}this._setDisplayRaw(v);const N=Ae(v,d);n.setSelectionRange(N,N),this._setHiddenRaw(w),A(n,"ln-number:input",{value:w,formatted:v})},l.prototype._setHiddenRaw=function(n){this._hidden&&o.set.call(this._hidden,String(n))},l.prototype._setDisplayRaw=function(n){this.isTextElement?this.dom.textContent=String(n):o.set.call(this.dom,String(n))},l.prototype._displayFormatted=function(n){if(this.isTextElement)this._formatTextContent();else{const s=this.dom.getAttribute("data-ln-number-decimals");this._setDisplayRaw(_(n,y(this.dom),{maxDecimals:s}))}},Object.defineProperty(l.prototype,"value",{get:function(){if(this.isTextElement)return this._rawValue;const n=o.get.call(this._hidden);return n===""?NaN:parseFloat(n)},set:function(n){const s=typeof n=="number"?n:parseFloat(n);if(this.isTextElement){isNaN(s)?(this._rawValue=null,this.dom.textContent=""):(this._rawValue=s,this.dom.setAttribute("data-ln-value",String(s)),this._formatTextContent());return}if(isNaN(s)){this._setDisplayRaw(""),this._setHiddenRaw(""),this.dom.dispatchEvent(new Event("input",{bubbles:!0}));return}this._setHiddenRaw(s);const a=this.dom.getAttribute("data-ln-number-decimals");this._setDisplayRaw(_(s,y(this.dom),{maxDecimals:a})),this.dom.dispatchEvent(new Event("input",{bubbles:!0}))}}),Object.defineProperty(l.prototype,"formatted",{get:function(){return this.isTextElement?this.dom.textContent:o.get.call(this.dom)}}),l.prototype.destroy=function(){this.dom[t]&&(this._onLocaleChange&&document.removeEventListener("ln-core:locale-change",this._onLocaleChange),this.isTextElement||(this.dom.removeEventListener("input",this._onInput),this.dom.removeEventListener("keydown",this._onKeyDown),this.dom.removeEventListener("paste",this._onPaste),this._hidden&&(this.dom.name=this._hidden.name,this._hidden.remove()),this.dom.type="number",this.dom.removeAttribute("inputmode")),delete this.dom[t])},fe(e,t,l,"ln-number",{attributes:r,extraAttributes:["lang"],onAttributeChange:i})})()})();
@@ -0,0 +1,63 @@
1
+ {
2
+ "$comment": "This file is partly generated. The $comment, component, generator, and each attribute's direction, sources, type, values, fallback, and description keys are owned by the generator and synchronized from JS source code. All other keys are preserved and safe to hand-author. Regenerate with `npm run sync:ln-schemas`.",
3
+ "component": "ln-number",
4
+ "generator": "scripts/sync-ln-schemas.mjs",
5
+ "attributes": {
6
+ "data-ln-debug": {
7
+ "direction": null,
8
+ "sources": [
9
+ "ln-number-dev.scss"
10
+ ]
11
+ },
12
+ "data-ln-fill-as": {
13
+ "direction": "both",
14
+ "sources": [
15
+ "src/ln-number.js"
16
+ ]
17
+ },
18
+ "data-ln-number": {
19
+ "direction": "author",
20
+ "sources": [
21
+ "ln-number-dev.scss",
22
+ "src/ln-number.js"
23
+ ],
24
+ "type": "marker",
25
+ "description": "Activates localized number formatting on input or text element"
26
+ },
27
+ "data-ln-number-decimals": {
28
+ "direction": "author",
29
+ "sources": [
30
+ "src/ln-number.js"
31
+ ],
32
+ "type": "integer",
33
+ "fallback": 0,
34
+ "min": 0,
35
+ "max": 20,
36
+ "description": "Number of decimal fraction digits"
37
+ },
38
+ "data-ln-number-max": {
39
+ "direction": "author",
40
+ "sources": [
41
+ "src/ln-number.js"
42
+ ],
43
+ "type": "float",
44
+ "description": "Maximum allowed numeric value"
45
+ },
46
+ "data-ln-number-min": {
47
+ "direction": null,
48
+ "sources": [
49
+ "src/ln-number.js"
50
+ ],
51
+ "type": "float",
52
+ "description": "Minimum allowed numeric value"
53
+ },
54
+ "data-ln-value": {
55
+ "direction": "both",
56
+ "sources": [
57
+ "src/ln-number.js"
58
+ ],
59
+ "type": "float",
60
+ "description": "Raw unformatted numeric value"
61
+ }
62
+ }
63
+ }