@livenetworks/ashlar 2.0.6 → 2.0.8

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 (221) hide show
  1. package/LICENSE +641 -641
  2. package/components/COMPONENTS.md +1116 -1116
  3. package/components/index.js +81 -81
  4. package/components/ln-accordion/ln-accordion-dev.scss +8 -8
  5. package/components/ln-accordion/ln-accordion.js +1 -1
  6. package/components/ln-accordion/ln-accordion.schema.json +30 -30
  7. package/components/ln-accordion/src/ln-accordion.js +1 -0
  8. package/components/ln-ajax/ln-ajax-dev.scss +8 -8
  9. package/components/ln-ajax/ln-ajax.js +1 -1
  10. package/components/ln-ajax/ln-ajax.schema.json +30 -30
  11. package/components/ln-api-connector/ln-api-connector.js +1 -1
  12. package/components/ln-api-connector/ln-api-connector.schema.json +96 -96
  13. package/components/ln-api-connector/src/ln-api-connector.js +1 -0
  14. package/components/ln-api-queue/ln-api-queue.js +1 -1
  15. package/components/ln-api-queue/ln-api-queue.schema.json +34 -34
  16. package/components/ln-api-queue/src/ln-api-queue.js +3 -13
  17. package/components/ln-autoresize/ln-autoresize-dev.scss +8 -8
  18. package/components/ln-autoresize/ln-autoresize.js +1 -1
  19. package/components/ln-autoresize/ln-autoresize.schema.json +22 -22
  20. package/components/ln-autosave/ln-autosave-dev.scss +13 -13
  21. package/components/ln-autosave/ln-autosave.js +1 -1
  22. package/components/ln-autosave/ln-autosave.schema.json +48 -48
  23. package/components/ln-autosave/src/autosave-model.js +34 -34
  24. package/components/ln-chart/ln-chart.js +1 -1
  25. package/components/ln-chart/ln-chart.schema.json +146 -146
  26. package/components/ln-chart/src/chart-model.js +154 -154
  27. package/components/ln-circular-progress/ln-circular-progress.js +1 -1
  28. package/components/ln-circular-progress/ln-circular-progress.schema.json +42 -42
  29. package/components/ln-confirm/ln-confirm-dev.scss +24 -24
  30. package/components/ln-confirm/ln-confirm.js +1 -1
  31. package/components/ln-confirm/ln-confirm.schema.json +66 -66
  32. package/components/ln-confirm/src/ln-confirm.js +178 -178
  33. package/components/ln-core/crypto.js +286 -265
  34. package/components/ln-core/dom.js +115 -115
  35. package/components/ln-core/form.js +136 -136
  36. package/components/ln-core/helpers.js +33 -33
  37. package/components/ln-core/http.js +48 -48
  38. package/components/ln-core/index.js +1 -1
  39. package/components/ln-core/ln-core.schema.json +109 -109
  40. package/components/ln-core/locale.js +55 -55
  41. package/components/ln-core/matching.js +78 -78
  42. package/components/ln-core/number.js +125 -125
  43. package/components/ln-core/template.js +206 -206
  44. package/components/ln-couchdb-connector/README.md +4 -0
  45. package/components/ln-couchdb-connector/ln-couchdb-connector.js +1 -1
  46. package/components/ln-couchdb-connector/ln-couchdb-connector.schema.json +50 -50
  47. package/components/ln-couchdb-connector/src/ln-couchdb-connector.js +19 -1
  48. package/components/ln-data-coordinator/README.md +9 -38
  49. package/components/ln-data-coordinator/ln-data-coordinator-dev.scss +8 -8
  50. package/components/ln-data-coordinator/ln-data-coordinator.js +1 -1
  51. package/components/ln-data-coordinator/ln-data-coordinator.schema.json +16 -16
  52. package/components/ln-data-coordinator/src/data-read-policy.js +0 -7
  53. package/components/ln-data-coordinator/src/ln-data-coordinator.js +428 -1299
  54. package/components/ln-data-store/README.md +3 -2
  55. package/components/ln-data-store/ln-data-store-dev.scss +13 -13
  56. package/components/ln-data-store/ln-data-store.js +1 -1
  57. package/components/ln-data-store/ln-data-store.schema.json +84 -84
  58. package/components/ln-data-store/src/data-store-model.js +184 -155
  59. package/components/ln-data-store/src/ln-data-store.js +58 -11
  60. package/components/ln-date/README.md +4 -0
  61. package/components/ln-date/ln-date.js +1 -1
  62. package/components/ln-date/ln-date.schema.json +92 -92
  63. package/components/ln-date/src/date-model.js +186 -186
  64. package/components/ln-date/src/ln-date.js +3 -3
  65. package/components/ln-debug/ln-debug.js +1 -1
  66. package/components/ln-debug/ln-debug.schema.json +28 -28
  67. package/components/ln-debug/src/console-sink.js +19 -19
  68. package/components/ln-debug/src/gate.js +95 -95
  69. package/components/ln-debug/src/generated-attributes.js +2 -2
  70. package/components/ln-dropdown/ln-dropdown-dev.scss +13 -13
  71. package/components/ln-dropdown/ln-dropdown.js +1 -1
  72. package/components/ln-dropdown/ln-dropdown.schema.json +90 -90
  73. package/components/ln-editor/ln-editor.js +1 -1
  74. package/components/ln-editor/ln-editor.schema.json +58 -58
  75. package/components/ln-external-links/ln-external-links.js +1 -1
  76. package/components/ln-external-links/ln-external-links.schema.json +18 -18
  77. package/components/ln-fill/ln-fill.js +1 -1
  78. package/components/ln-fill/ln-fill.schema.json +23 -23
  79. package/components/ln-filter/ln-filter.js +1 -1
  80. package/components/ln-filter/ln-filter.schema.json +153 -153
  81. package/components/ln-filter/src/filter-model.js +185 -185
  82. package/components/ln-form/ln-form-dev.scss +8 -8
  83. package/components/ln-form/ln-form.js +1 -1
  84. package/components/ln-form/ln-form.schema.json +45 -45
  85. package/components/ln-http/ln-http.js +1 -1
  86. package/components/ln-http/ln-http.schema.json +6 -6
  87. package/components/ln-icon/ln-icon.schema.json +6 -6
  88. package/components/ln-include/ln-include.js +1 -1
  89. package/components/ln-include/ln-include.schema.json +23 -23
  90. package/components/ln-key/ln-key-dev.scss +18 -18
  91. package/components/ln-key/ln-key.js +1 -1
  92. package/components/ln-key/ln-key.schema.json +56 -56
  93. package/components/ln-key/src/ln-key.js +10 -10
  94. package/components/ln-link/ln-link-dev.scss +8 -8
  95. package/components/ln-link/ln-link.js +1 -1
  96. package/components/ln-link/ln-link.schema.json +22 -22
  97. package/components/ln-list/README.md +152 -152
  98. package/components/ln-list/ln-list-dev.scss +8 -8
  99. package/components/ln-list/ln-list.js +1 -1
  100. package/components/ln-list/ln-list.schema.json +166 -166
  101. package/components/ln-list/src/ln-list.js +4 -4
  102. package/components/ln-modal/README.md +4 -6
  103. package/components/ln-modal/ln-modal.js +1 -1
  104. package/components/ln-modal/ln-modal.schema.json +65 -65
  105. package/components/ln-modal/src/ln-modal.js +28 -8
  106. package/components/ln-nav/ln-nav.js +1 -1
  107. package/components/ln-nav/ln-nav.schema.json +25 -25
  108. package/components/ln-number/ln-number.js +1 -1
  109. package/components/ln-number/ln-number.schema.json +63 -63
  110. package/components/ln-number/src/number-model.js +31 -31
  111. package/components/ln-obfuscator/README.md +60 -60
  112. package/components/ln-obfuscator/ln-obfuscator.js +1 -1
  113. package/components/ln-obfuscator/ln-obfuscator.schema.json +49 -49
  114. package/components/ln-obfuscator/src/ln-obfuscator.js +159 -159
  115. package/components/ln-obfuscator/src/obfuscator-model.js +250 -250
  116. package/components/ln-options/ln-options.js +1 -1
  117. package/components/ln-options/ln-options.schema.json +41 -41
  118. package/components/ln-options/src/ln-options.js +1 -0
  119. package/components/ln-persist/README.md +151 -151
  120. package/components/ln-persist/ln-persist.js +1 -1
  121. package/components/ln-persist/ln-persist.schema.json +28 -28
  122. package/components/ln-persist/src/ln-persist.js +83 -83
  123. package/components/ln-picklist/README.md +230 -230
  124. package/components/ln-picklist/ln-picklist-dev.scss +22 -22
  125. package/components/ln-picklist/ln-picklist.js +1 -1
  126. package/components/ln-picklist/ln-picklist.schema.json +49 -49
  127. package/components/ln-picklist/src/ln-picklist.js +228 -228
  128. package/components/ln-popover/README.md +4 -0
  129. package/components/ln-popover/ln-popover-dev.scss +13 -13
  130. package/components/ln-popover/ln-popover.js +1 -1
  131. package/components/ln-popover/ln-popover.schema.json +82 -82
  132. package/components/ln-popover/src/ln-popover.js +9 -0
  133. package/components/ln-progress/ln-progress-dev.scss +8 -8
  134. package/components/ln-progress/ln-progress.js +1 -1
  135. package/components/ln-progress/ln-progress.schema.json +40 -40
  136. package/components/ln-router/ln-router.js +1 -1
  137. package/components/ln-router/ln-router.schema.json +76 -76
  138. package/components/ln-scroll/README.md +45 -45
  139. package/components/ln-scroll/ln-scroll.js +1 -1
  140. package/components/ln-scroll/ln-scroll.schema.json +85 -85
  141. package/components/ln-scroll/src/ln-scroll.js +150 -150
  142. package/components/ln-search/README.md +188 -188
  143. package/components/ln-search/ln-search.js +1 -1
  144. package/components/ln-search/ln-search.schema.json +103 -103
  145. package/components/ln-slug/ln-slug.js +1 -1
  146. package/components/ln-slug/ln-slug.schema.json +23 -23
  147. package/components/ln-sort/ln-sort.js +1 -1
  148. package/components/ln-sort/ln-sort.schema.json +104 -104
  149. package/components/ln-sort/src/ln-sort.js +321 -321
  150. package/components/ln-sort/src/sort-model.js +117 -117
  151. package/components/ln-sortable/ln-sortable-dev.scss +13 -13
  152. package/components/ln-sortable/ln-sortable.js +1 -1
  153. package/components/ln-sortable/ln-sortable.schema.json +36 -36
  154. package/components/ln-stat/ln-stat-dev.scss +8 -8
  155. package/components/ln-stat/ln-stat.js +1 -1
  156. package/components/ln-stat/ln-stat.schema.json +32 -32
  157. package/components/ln-stat/src/stat-model.js +28 -28
  158. package/components/ln-table/ln-table.js +1 -1
  159. package/components/ln-table/ln-table.schema.json +211 -211
  160. package/components/ln-table/src/ln-table.js +2 -0
  161. package/components/ln-table/src/table-model.js +98 -98
  162. package/components/ln-table-coordinator/ln-table-coordinator.js +1 -1
  163. package/components/ln-table-coordinator/ln-table-coordinator.schema.json +93 -93
  164. package/components/ln-table-coordinator/src/ln-table-coordinator.js +3 -3
  165. package/components/ln-tabs/README.md +2 -2
  166. package/components/ln-tabs/ln-tabs.js +1 -1
  167. package/components/ln-tabs/ln-tabs.schema.json +75 -75
  168. package/components/ln-tabs/src/ln-tabs.js +208 -207
  169. package/components/ln-tabs/src/tabs-model.js +82 -82
  170. package/components/ln-time/ln-time-dev.scss +13 -13
  171. package/components/ln-time/ln-time.js +1 -1
  172. package/components/ln-time/ln-time.schema.json +38 -38
  173. package/components/ln-toast/ln-toast.js +1 -1
  174. package/components/ln-toast/ln-toast.schema.json +65 -65
  175. package/components/ln-toggle/ln-toggle.js +1 -1
  176. package/components/ln-toggle/ln-toggle.schema.json +52 -52
  177. package/components/ln-tooltip/ln-tooltip.js +1 -1
  178. package/components/ln-tooltip/ln-tooltip.schema.json +86 -86
  179. package/components/ln-translations/ln-translations.js +1 -1
  180. package/components/ln-translations/ln-translations.schema.json +120 -120
  181. package/components/ln-ui-coordinator/README.md +62 -62
  182. package/components/ln-ui-coordinator/ln-ui-coordinator.js +1 -1
  183. package/components/ln-ui-coordinator/ln-ui-coordinator.schema.json +28 -28
  184. package/components/ln-ui-coordinator/src/ln-ui-coordinator.js +140 -140
  185. package/components/ln-upload/ln-upload.js +1 -1
  186. package/components/ln-upload/ln-upload.schema.json +193 -193
  187. package/components/ln-upload/src/upload-model.js +78 -78
  188. package/components/ln-validate/ln-validate.js +1 -1
  189. package/components/ln-validate/ln-validate.schema.json +50 -50
  190. package/components/ln-validate/src/validate-model.js +64 -64
  191. package/components/ln-websocket-connector/README.md +166 -166
  192. package/components/ln-websocket-connector/ln-websocket-connector.js +1 -1
  193. package/components/ln-websocket-connector/ln-websocket-connector.schema.json +29 -29
  194. package/components/ln-websocket-connector/src/ln-websocket-connector.js +283 -279
  195. package/ln-ashlar.html-data.json +7 -8
  196. package/package.json +84 -84
  197. package/theme/brand.css +73 -73
  198. package/theme/components/_confirm.scss +6 -6
  199. package/theme/components/_picklist.scss +3 -3
  200. package/theme/config/_palette.scss +274 -274
  201. package/theme/config/_theme.scss +292 -292
  202. package/theme/config/_tokens.scss +285 -285
  203. package/theme/config/mixins/_index.scss +62 -62
  204. package/theme/config/mixins/_picklist.scss +66 -66
  205. package/theme/ln-ashlar-dev.scss +66 -66
  206. package/theme/ln-ashlar-landing.scss +56 -56
  207. package/theme/ln-ashlar-theme.scss +63 -63
  208. package/theme/presentation/_bento.scss +151 -151
  209. package/theme/presentation/_cta.scss +111 -111
  210. package/theme/presentation/_effects.scss +216 -216
  211. package/theme/presentation/_features.scss +108 -108
  212. package/theme/presentation/_footer.scss +129 -129
  213. package/theme/presentation/_hero.scss +158 -158
  214. package/theme/presentation/_layout.scss +170 -170
  215. package/theme/presentation/_navbar.scss +140 -140
  216. package/theme/presentation/_pricing.scss +262 -262
  217. package/theme/presentation/_stats.scss +87 -87
  218. package/theme/presentation/_testimonials.scss +124 -124
  219. package/theme/presentation/_tokens.scss +39 -39
  220. package/theme/presentation/_typography.scss +163 -163
  221. package/web-types.json +12 -12
@@ -1,115 +1,115 @@
1
- // ─── Guard Body ────────────────────────────────────────
2
-
3
- export function guardBody(setupFn, componentTag) {
4
- if (!document.body) {
5
- document.addEventListener('DOMContentLoaded', function () {
6
- guardBody(setupFn, componentTag);
7
- });
8
- console.warn('[' + componentTag + '] Script loaded before <body> — add "defer" to your <script> tag');
9
- return;
10
- }
11
- setupFn();
12
- }
13
-
14
- // ─── Visibility Check ─────────────────────────────────────
15
-
16
- export function isVisible(el) {
17
- return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length);
18
- }
19
-
20
- /**
21
- * Determines whether a mouse click event should be ignored (modified click or non-primary button).
22
- * @param {MouseEvent|Object} [event]
23
- * @returns {boolean}
24
- */
25
- export function shouldIgnoreClick(event) {
26
- if (!event) return true;
27
- if (event.ctrlKey || event.metaKey || event.shiftKey || event.altKey) return true;
28
- if (typeof event.button === 'number' && event.button !== 0) return true;
29
- return false;
30
- }
31
-
32
- /**
33
- * Checks if a target element is an active editable field or contenteditable element.
34
- * @param {Element|Object} [target]
35
- * @returns {boolean}
36
- */
37
- export function isEditableTarget(target) {
38
- if (!target) return false;
39
- if (typeof target.closest === 'function') {
40
- return Boolean(target.closest('input, textarea, select, [contenteditable]:not([contenteditable="false"])'));
41
- }
42
- const tag = String(target.tagName || '').toLowerCase();
43
- return tag === 'input' || tag === 'textarea' || tag === 'select' || Boolean(target.isContentEditable);
44
- }
45
-
46
- /**
47
- * Checks if a target element is disabled, aria-disabled, or inside an inert container.
48
- * @param {Element|Object} [target]
49
- * @returns {boolean}
50
- */
51
- export function isTargetDisabled(target) {
52
- if (!target) return true;
53
- if (target.disabled || (typeof target.getAttribute === 'function' && target.getAttribute('aria-disabled') === 'true')) {
54
- return true;
55
- }
56
- if (typeof target.closest === 'function' && target.closest('[inert]')) {
57
- return true;
58
- }
59
- return false;
60
- }
61
-
62
- /**
63
- * Checks if a target element is connected, enabled, not inert, visible, and optionally supports an action method.
64
- * @param {Element} target
65
- * @param {string} [action]
66
- * @returns {boolean}
67
- */
68
- export function isUsableTarget(target, action) {
69
- if (!target || !document.contains(target)) return false;
70
- if (isTargetDisabled(target)) return false;
71
- if (action && typeof target[action] !== 'function') return false;
72
- return isVisible(target);
73
- }
74
-
75
- /**
76
- * Checks if a link click should be intercepted by client-side routing.
77
- * Must be standard navigation click (left button, no modifiers), same origin,
78
- * not mailto/tel, and not pure hash/empty.
79
- *
80
- * @param {MouseEvent} event
81
- * @param {HTMLAnchorElement} anchor
82
- * @returns {boolean}
83
- */
84
- export function shouldInterceptLink(event, anchor) {
85
- if (event.ctrlKey || event.metaKey || event.shiftKey || event.altKey || event.button !== 0) {
86
- return false;
87
- }
88
- if (!anchor) return false;
89
- const href = anchor.getAttribute('href');
90
- if (!href) return false;
91
- if (anchor.getAttribute('target') === '_blank') return false;
92
- if (anchor.hasAttribute('download')) return false;
93
- if (href.startsWith('mailto:') || href.startsWith('tel:')) return false;
94
- if (href === '#' || href.startsWith('#')) return false;
95
- if (anchor.hostname && anchor.hostname !== window.location.hostname) return false;
96
- return true;
97
- }
98
-
99
- /**
100
- * Read the raw machine value behind a formatted cell/item display.
101
- * Returns the `data-ln-value` attribute if present, else trimmed textContent.
102
- * Single read path for value-based sort/filter across components.
103
- */
104
- export function readValue(el) {
105
- if (el.hasAttribute('data-ln-value')) {
106
- return el.getAttribute('data-ln-value');
107
- }
108
- if (el.tagName === 'TIME' && el.hasAttribute('datetime')) {
109
- return el.getAttribute('datetime');
110
- }
111
- if (el.tagName === 'DATA' && el.hasAttribute('value')) {
112
- return el.getAttribute('value');
113
- }
114
- return el.textContent.trim();
115
- }
1
+ // ─── Guard Body ────────────────────────────────────────
2
+
3
+ export function guardBody(setupFn, componentTag) {
4
+ if (!document.body) {
5
+ document.addEventListener('DOMContentLoaded', function () {
6
+ guardBody(setupFn, componentTag);
7
+ });
8
+ console.warn('[' + componentTag + '] Script loaded before <body> — add "defer" to your <script> tag');
9
+ return;
10
+ }
11
+ setupFn();
12
+ }
13
+
14
+ // ─── Visibility Check ─────────────────────────────────────
15
+
16
+ export function isVisible(el) {
17
+ return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length);
18
+ }
19
+
20
+ /**
21
+ * Determines whether a mouse click event should be ignored (modified click or non-primary button).
22
+ * @param {MouseEvent|Object} [event]
23
+ * @returns {boolean}
24
+ */
25
+ export function shouldIgnoreClick(event) {
26
+ if (!event) return true;
27
+ if (event.ctrlKey || event.metaKey || event.shiftKey || event.altKey) return true;
28
+ if (typeof event.button === 'number' && event.button !== 0) return true;
29
+ return false;
30
+ }
31
+
32
+ /**
33
+ * Checks if a target element is an active editable field or contenteditable element.
34
+ * @param {Element|Object} [target]
35
+ * @returns {boolean}
36
+ */
37
+ export function isEditableTarget(target) {
38
+ if (!target) return false;
39
+ if (typeof target.closest === 'function') {
40
+ return Boolean(target.closest('input, textarea, select, [contenteditable]:not([contenteditable="false"])'));
41
+ }
42
+ const tag = String(target.tagName || '').toLowerCase();
43
+ return tag === 'input' || tag === 'textarea' || tag === 'select' || Boolean(target.isContentEditable);
44
+ }
45
+
46
+ /**
47
+ * Checks if a target element is disabled, aria-disabled, or inside an inert container.
48
+ * @param {Element|Object} [target]
49
+ * @returns {boolean}
50
+ */
51
+ export function isTargetDisabled(target) {
52
+ if (!target) return true;
53
+ if (target.disabled || (typeof target.getAttribute === 'function' && target.getAttribute('aria-disabled') === 'true')) {
54
+ return true;
55
+ }
56
+ if (typeof target.closest === 'function' && target.closest('[inert]')) {
57
+ return true;
58
+ }
59
+ return false;
60
+ }
61
+
62
+ /**
63
+ * Checks if a target element is connected, enabled, not inert, visible, and optionally supports an action method.
64
+ * @param {Element} target
65
+ * @param {string} [action]
66
+ * @returns {boolean}
67
+ */
68
+ export function isUsableTarget(target, action) {
69
+ if (!target || !document.contains(target)) return false;
70
+ if (isTargetDisabled(target)) return false;
71
+ if (action && typeof target[action] !== 'function') return false;
72
+ return isVisible(target);
73
+ }
74
+
75
+ /**
76
+ * Checks if a link click should be intercepted by client-side routing.
77
+ * Must be standard navigation click (left button, no modifiers), same origin,
78
+ * not mailto/tel, and not pure hash/empty.
79
+ *
80
+ * @param {MouseEvent} event
81
+ * @param {HTMLAnchorElement} anchor
82
+ * @returns {boolean}
83
+ */
84
+ export function shouldInterceptLink(event, anchor) {
85
+ if (event.ctrlKey || event.metaKey || event.shiftKey || event.altKey || event.button !== 0) {
86
+ return false;
87
+ }
88
+ if (!anchor) return false;
89
+ const href = anchor.getAttribute('href');
90
+ if (!href) return false;
91
+ if (anchor.getAttribute('target') === '_blank') return false;
92
+ if (anchor.hasAttribute('download')) return false;
93
+ if (href.startsWith('mailto:') || href.startsWith('tel:')) return false;
94
+ if (href === '#' || href.startsWith('#')) return false;
95
+ if (anchor.hostname && anchor.hostname !== window.location.hostname) return false;
96
+ return true;
97
+ }
98
+
99
+ /**
100
+ * Read the raw machine value behind a formatted cell/item display.
101
+ * Returns the `data-ln-value` attribute if present, else trimmed textContent.
102
+ * Single read path for value-based sort/filter across components.
103
+ */
104
+ export function readValue(el) {
105
+ if (el.hasAttribute('data-ln-value')) {
106
+ return el.getAttribute('data-ln-value');
107
+ }
108
+ if (el.tagName === 'TIME' && el.hasAttribute('datetime')) {
109
+ return el.getAttribute('datetime');
110
+ }
111
+ if (el.tagName === 'DATA' && el.hasAttribute('value')) {
112
+ return el.getAttribute('value');
113
+ }
114
+ return el.textContent.trim();
115
+ }
@@ -1,136 +1,136 @@
1
- // ─── Form Method Resolution ────────────────────────────────
2
-
3
- export function resolveFormMethod(form) {
4
- const methodInput = form.querySelector('input[name="_method"]');
5
- const raw = (methodInput && methodInput.value !== '') ? methodInput.value : form.method;
6
- return (raw || '').toUpperCase();
7
- }
8
-
9
- // ─── Form Serialization ───────────────────────────────────
10
-
11
- export function serializeForm(form, opts) {
12
- const typed = !!(opts && opts.typed);
13
- const exclude = opts && opts.exclude;
14
- const data = {};
15
- const elements = form.elements;
16
-
17
- const checkboxCounts = {};
18
- if (typed) {
19
- for (let i = 0; i < elements.length; i++) {
20
- const el = elements[i];
21
- if (el.name && el.type === 'checkbox' && !el.disabled) {
22
- checkboxCounts[el.name] = (checkboxCounts[el.name] || 0) + 1;
23
- }
24
- }
25
- }
26
-
27
- for (let i = 0; i < elements.length; i++) {
28
- const el = elements[i];
29
- if (!el.name || el.disabled || el.type === 'file' || el.type === 'submit' || el.type === 'button') continue;
30
- if (exclude && el.matches && el.matches(exclude)) continue;
31
-
32
- if (el.type === 'checkbox') {
33
- if (typed && checkboxCounts[el.name] === 1) {
34
- data[el.name] = el.checked;
35
- } else {
36
- if (!data[el.name]) data[el.name] = [];
37
- if (el.checked) data[el.name].push(el.value);
38
- }
39
- } else if (el.type === 'radio') {
40
- if (el.checked) data[el.name] = el.value;
41
- } else if (el.type === 'select-multiple') {
42
- data[el.name] = [];
43
- for (let j = 0; j < el.options.length; j++) {
44
- if (el.options[j].selected) data[el.name].push(el.options[j].value);
45
- }
46
- } else if (typed && el.type === 'hidden') {
47
- data[el.name] = el.value;
48
- } else if (typed && (el.type === 'number' || el.type === 'range')) {
49
- const n = Number(el.value);
50
- data[el.name] = (el.value === '' || isNaN(n)) ? null : n;
51
- } else {
52
- data[el.name] = el.value;
53
- }
54
- }
55
-
56
- return data;
57
- }
58
-
59
- // ─── Form Population ──────────────────────────────────────
60
-
61
- function _coerceBool(value) {
62
- if (typeof value !== 'string') return !!value;
63
- const v = value.trim().toLowerCase();
64
- return v !== 'false' && v !== '0' && v !== '' && v !== 'off' && v !== 'no';
65
- }
66
-
67
- export function populateForm(form, data) {
68
- const elements = form.elements;
69
- const filled = [];
70
-
71
- const checkboxCounts = {};
72
- for (let i = 0; i < elements.length; i++) {
73
- const el = elements[i];
74
- if (el.name && el.type === 'checkbox') {
75
- checkboxCounts[el.name] = (checkboxCounts[el.name] || 0) + 1;
76
- }
77
- }
78
-
79
- for (let i = 0; i < elements.length; i++) {
80
- const el = elements[i];
81
- if (el.type === 'file' || el.type === 'submit' || el.type === 'button') continue;
82
-
83
- const matchKey = el.getAttribute('data-ln-fill-as') || el.name;
84
- if (!matchKey || !(matchKey in data)) continue;
85
-
86
- const value = data[matchKey];
87
-
88
- if (el.type === 'checkbox') {
89
- if (Array.isArray(value)) {
90
- el.checked = value.indexOf(el.value) !== -1;
91
- } else if (checkboxCounts[el.name] > 1) {
92
- const list = String(value).split(',').map(function (s) { return s.trim(); });
93
- el.checked = list.indexOf(el.value) !== -1;
94
- } else {
95
- el.checked = _coerceBool(value);
96
- }
97
- filled.push(el);
98
- } else if (el.type === 'radio') {
99
- el.checked = el.value === String(value);
100
- filled.push(el);
101
- } else if (el.type === 'select-multiple') {
102
- if (Array.isArray(value)) {
103
- for (let j = 0; j < el.options.length; j++) {
104
- el.options[j].selected = value.indexOf(el.options[j].value) !== -1;
105
- }
106
- }
107
- filled.push(el);
108
- } else {
109
- el.value = value;
110
- filled.push(el);
111
- }
112
- }
113
-
114
- return filled;
115
- }
116
-
117
- // ─── Value Property Interception ───────────────────────────
118
-
119
- export function interceptValueProperty(dom, descriptor, { get, set }) {
120
- Object.defineProperty(dom, 'value', {
121
- get: function () {
122
- if (get) {
123
- return get.call(this);
124
- }
125
- return descriptor.get.call(this);
126
- },
127
- set: function (val) {
128
- if (set) {
129
- set.call(this, val, (originalVal) => descriptor.set.call(this, originalVal));
130
- } else {
131
- descriptor.set.call(this, val);
132
- }
133
- },
134
- configurable: true
135
- });
136
- }
1
+ // ─── Form Method Resolution ────────────────────────────────
2
+
3
+ export function resolveFormMethod(form) {
4
+ const methodInput = form.querySelector('input[name="_method"]');
5
+ const raw = (methodInput && methodInput.value !== '') ? methodInput.value : form.method;
6
+ return (raw || '').toUpperCase();
7
+ }
8
+
9
+ // ─── Form Serialization ───────────────────────────────────
10
+
11
+ export function serializeForm(form, opts) {
12
+ const typed = !!(opts && opts.typed);
13
+ const exclude = opts && opts.exclude;
14
+ const data = {};
15
+ const elements = form.elements;
16
+
17
+ const checkboxCounts = {};
18
+ if (typed) {
19
+ for (let i = 0; i < elements.length; i++) {
20
+ const el = elements[i];
21
+ if (el.name && el.type === 'checkbox' && !el.disabled) {
22
+ checkboxCounts[el.name] = (checkboxCounts[el.name] || 0) + 1;
23
+ }
24
+ }
25
+ }
26
+
27
+ for (let i = 0; i < elements.length; i++) {
28
+ const el = elements[i];
29
+ if (!el.name || el.disabled || el.type === 'file' || el.type === 'submit' || el.type === 'button') continue;
30
+ if (exclude && el.matches && el.matches(exclude)) continue;
31
+
32
+ if (el.type === 'checkbox') {
33
+ if (typed && checkboxCounts[el.name] === 1) {
34
+ data[el.name] = el.checked;
35
+ } else {
36
+ if (!data[el.name]) data[el.name] = [];
37
+ if (el.checked) data[el.name].push(el.value);
38
+ }
39
+ } else if (el.type === 'radio') {
40
+ if (el.checked) data[el.name] = el.value;
41
+ } else if (el.type === 'select-multiple') {
42
+ data[el.name] = [];
43
+ for (let j = 0; j < el.options.length; j++) {
44
+ if (el.options[j].selected) data[el.name].push(el.options[j].value);
45
+ }
46
+ } else if (typed && el.type === 'hidden') {
47
+ data[el.name] = el.value;
48
+ } else if (typed && (el.type === 'number' || el.type === 'range')) {
49
+ const n = Number(el.value);
50
+ data[el.name] = (el.value === '' || isNaN(n)) ? null : n;
51
+ } else {
52
+ data[el.name] = el.value;
53
+ }
54
+ }
55
+
56
+ return data;
57
+ }
58
+
59
+ // ─── Form Population ──────────────────────────────────────
60
+
61
+ function _coerceBool(value) {
62
+ if (typeof value !== 'string') return !!value;
63
+ const v = value.trim().toLowerCase();
64
+ return v !== 'false' && v !== '0' && v !== '' && v !== 'off' && v !== 'no';
65
+ }
66
+
67
+ export function populateForm(form, data) {
68
+ const elements = form.elements;
69
+ const filled = [];
70
+
71
+ const checkboxCounts = {};
72
+ for (let i = 0; i < elements.length; i++) {
73
+ const el = elements[i];
74
+ if (el.name && el.type === 'checkbox') {
75
+ checkboxCounts[el.name] = (checkboxCounts[el.name] || 0) + 1;
76
+ }
77
+ }
78
+
79
+ for (let i = 0; i < elements.length; i++) {
80
+ const el = elements[i];
81
+ if (el.type === 'file' || el.type === 'submit' || el.type === 'button') continue;
82
+
83
+ const matchKey = el.getAttribute('data-ln-fill-as') || el.name;
84
+ if (!matchKey || !(matchKey in data)) continue;
85
+
86
+ const value = data[matchKey];
87
+
88
+ if (el.type === 'checkbox') {
89
+ if (Array.isArray(value)) {
90
+ el.checked = value.indexOf(el.value) !== -1;
91
+ } else if (checkboxCounts[el.name] > 1) {
92
+ const list = String(value).split(',').map(function (s) { return s.trim(); });
93
+ el.checked = list.indexOf(el.value) !== -1;
94
+ } else {
95
+ el.checked = _coerceBool(value);
96
+ }
97
+ filled.push(el);
98
+ } else if (el.type === 'radio') {
99
+ el.checked = el.value === String(value);
100
+ filled.push(el);
101
+ } else if (el.type === 'select-multiple') {
102
+ if (Array.isArray(value)) {
103
+ for (let j = 0; j < el.options.length; j++) {
104
+ el.options[j].selected = value.indexOf(el.options[j].value) !== -1;
105
+ }
106
+ }
107
+ filled.push(el);
108
+ } else {
109
+ el.value = value;
110
+ filled.push(el);
111
+ }
112
+ }
113
+
114
+ return filled;
115
+ }
116
+
117
+ // ─── Value Property Interception ───────────────────────────
118
+
119
+ export function interceptValueProperty(dom, descriptor, { get, set }) {
120
+ Object.defineProperty(dom, 'value', {
121
+ get: function () {
122
+ if (get) {
123
+ return get.call(this);
124
+ }
125
+ return descriptor.get.call(this);
126
+ },
127
+ set: function (val) {
128
+ if (set) {
129
+ set.call(this, val, (originalVal) => descriptor.set.call(this, originalVal));
130
+ } else {
131
+ descriptor.set.call(this, val);
132
+ }
133
+ },
134
+ configurable: true
135
+ });
136
+ }
@@ -1,33 +1,33 @@
1
- // ==========================================================================
2
- // ln-core — Shared Helpers & Runtime Kernel Facade (Barrel File)
3
- // ==========================================================================
4
- // All primitives are modularized into cohesive single-responsibility modules.
5
- // This barrel re-exports the entire public surface with 100% backward
6
- // compatibility. Evaluation order preserves module initialization invariants:
7
- // events.js evaluates first to ensure window.lnCore and console warning
8
- // interception are established before subsequent modules load.
9
- // ==========================================================================
10
-
11
- // Events & Debug
12
- export { dispatch, dispatchCancelable, requestData, setDebugSink, setPersistSink, hasActiveDebug, isDevMode } from './events.js';
13
-
14
- // DOM & Target Predicates
15
- export { guardBody, isVisible, shouldIgnoreClick, isEditableTarget, isTargetDisabled, isUsableTarget, shouldInterceptLink, readValue } from './dom.js';
16
-
17
- // Form Utilities
18
- export { resolveFormMethod, serializeForm, populateForm, interceptValueProperty } from './form.js';
19
-
20
- // HTTP & Data Mappers
21
- export { buildUrl, getHeaders, parseHeaders, registerDataMapper, getDataMapper } from './http.js';
22
-
23
- // Locale & i18n
24
- export { getLocale, ensureLocaleObserver, registerLocaleFallback, getLocaleFallback } from './locale.js';
25
-
26
- // Templates & DOM Fill
27
- export { cloneTemplate, cloneTemplateScoped, fill, lnFill, fillTemplate, renderList, buildDict } from './template.js';
28
-
29
- // Lifecycle & Kernel Registration
30
- export { findElements, holdInit, releaseInit, pendingCount, queueBoot, observeAttributes, registerComponent } from './lifecycle.js';
31
-
32
- // Value Comparison Primitives (re-exported from compare.js for backward compatibility)
33
- export { compareValues, detectValueType } from './compare.js';
1
+ // ==========================================================================
2
+ // ln-core — Shared Helpers & Runtime Kernel Facade (Barrel File)
3
+ // ==========================================================================
4
+ // All primitives are modularized into cohesive single-responsibility modules.
5
+ // This barrel re-exports the entire public surface with 100% backward
6
+ // compatibility. Evaluation order preserves module initialization invariants:
7
+ // events.js evaluates first to ensure window.lnCore and console warning
8
+ // interception are established before subsequent modules load.
9
+ // ==========================================================================
10
+
11
+ // Events & Debug
12
+ export { dispatch, dispatchCancelable, requestData, setDebugSink, setPersistSink, hasActiveDebug, isDevMode } from './events.js';
13
+
14
+ // DOM & Target Predicates
15
+ export { guardBody, isVisible, shouldIgnoreClick, isEditableTarget, isTargetDisabled, isUsableTarget, shouldInterceptLink, readValue } from './dom.js';
16
+
17
+ // Form Utilities
18
+ export { resolveFormMethod, serializeForm, populateForm, interceptValueProperty } from './form.js';
19
+
20
+ // HTTP & Data Mappers
21
+ export { buildUrl, getHeaders, parseHeaders, registerDataMapper, getDataMapper } from './http.js';
22
+
23
+ // Locale & i18n
24
+ export { getLocale, ensureLocaleObserver, registerLocaleFallback, getLocaleFallback } from './locale.js';
25
+
26
+ // Templates & DOM Fill
27
+ export { cloneTemplate, cloneTemplateScoped, fill, lnFill, fillTemplate, renderList, buildDict } from './template.js';
28
+
29
+ // Lifecycle & Kernel Registration
30
+ export { findElements, holdInit, releaseInit, pendingCount, queueBoot, observeAttributes, registerComponent } from './lifecycle.js';
31
+
32
+ // Value Comparison Primitives (re-exported from compare.js for backward compatibility)
33
+ export { compareValues, detectValueType } from './compare.js';