@livenetworks/ashlar 2.0.7 → 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 (207) 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-ajax/ln-ajax-dev.scss +8 -8
  8. package/components/ln-ajax/ln-ajax.js +1 -1
  9. package/components/ln-ajax/ln-ajax.schema.json +30 -30
  10. package/components/ln-api-connector/ln-api-connector.js +1 -1
  11. package/components/ln-api-connector/ln-api-connector.schema.json +96 -96
  12. package/components/ln-api-connector/src/ln-api-connector.js +1 -0
  13. package/components/ln-api-queue/ln-api-queue.js +1 -1
  14. package/components/ln-api-queue/ln-api-queue.schema.json +34 -34
  15. package/components/ln-api-queue/src/ln-api-queue.js +3 -13
  16. package/components/ln-autoresize/ln-autoresize-dev.scss +8 -8
  17. package/components/ln-autoresize/ln-autoresize.js +1 -1
  18. package/components/ln-autoresize/ln-autoresize.schema.json +22 -22
  19. package/components/ln-autosave/ln-autosave-dev.scss +13 -13
  20. package/components/ln-autosave/ln-autosave.js +1 -1
  21. package/components/ln-autosave/ln-autosave.schema.json +48 -48
  22. package/components/ln-autosave/src/autosave-model.js +34 -34
  23. package/components/ln-chart/ln-chart.js +1 -1
  24. package/components/ln-chart/ln-chart.schema.json +146 -146
  25. package/components/ln-chart/src/chart-model.js +154 -154
  26. package/components/ln-circular-progress/ln-circular-progress.js +1 -1
  27. package/components/ln-circular-progress/ln-circular-progress.schema.json +42 -42
  28. package/components/ln-confirm/ln-confirm-dev.scss +24 -24
  29. package/components/ln-confirm/ln-confirm.js +1 -1
  30. package/components/ln-confirm/ln-confirm.schema.json +66 -66
  31. package/components/ln-confirm/src/ln-confirm.js +178 -178
  32. package/components/ln-core/crypto.js +286 -265
  33. package/components/ln-core/dom.js +115 -115
  34. package/components/ln-core/form.js +136 -136
  35. package/components/ln-core/helpers.js +33 -33
  36. package/components/ln-core/http.js +48 -48
  37. package/components/ln-core/index.js +1 -1
  38. package/components/ln-core/ln-core.schema.json +109 -109
  39. package/components/ln-core/locale.js +55 -55
  40. package/components/ln-core/matching.js +78 -78
  41. package/components/ln-core/number.js +125 -125
  42. package/components/ln-core/template.js +206 -206
  43. package/components/ln-couchdb-connector/ln-couchdb-connector.js +1 -1
  44. package/components/ln-couchdb-connector/ln-couchdb-connector.schema.json +50 -50
  45. package/components/ln-couchdb-connector/src/ln-couchdb-connector.js +1 -0
  46. package/components/ln-data-coordinator/README.md +9 -38
  47. package/components/ln-data-coordinator/ln-data-coordinator-dev.scss +8 -8
  48. package/components/ln-data-coordinator/ln-data-coordinator.js +1 -1
  49. package/components/ln-data-coordinator/ln-data-coordinator.schema.json +16 -16
  50. package/components/ln-data-coordinator/src/data-read-policy.js +0 -7
  51. package/components/ln-data-coordinator/src/ln-data-coordinator.js +428 -1308
  52. package/components/ln-data-store/ln-data-store-dev.scss +13 -13
  53. package/components/ln-data-store/ln-data-store.js +1 -1
  54. package/components/ln-data-store/ln-data-store.schema.json +84 -84
  55. package/components/ln-data-store/src/data-store-model.js +184 -184
  56. package/components/ln-data-store/src/ln-data-store.js +1 -1
  57. package/components/ln-date/ln-date.js +1 -1
  58. package/components/ln-date/ln-date.schema.json +92 -92
  59. package/components/ln-date/src/date-model.js +186 -186
  60. package/components/ln-debug/ln-debug.js +1 -1
  61. package/components/ln-debug/ln-debug.schema.json +28 -28
  62. package/components/ln-debug/src/console-sink.js +19 -19
  63. package/components/ln-debug/src/gate.js +95 -95
  64. package/components/ln-debug/src/generated-attributes.js +2 -2
  65. package/components/ln-dropdown/ln-dropdown-dev.scss +13 -13
  66. package/components/ln-dropdown/ln-dropdown.js +1 -1
  67. package/components/ln-dropdown/ln-dropdown.schema.json +90 -90
  68. package/components/ln-editor/ln-editor.js +1 -1
  69. package/components/ln-editor/ln-editor.schema.json +58 -58
  70. package/components/ln-external-links/ln-external-links.js +1 -1
  71. package/components/ln-external-links/ln-external-links.schema.json +18 -18
  72. package/components/ln-fill/ln-fill.js +1 -1
  73. package/components/ln-fill/ln-fill.schema.json +23 -23
  74. package/components/ln-filter/ln-filter.js +1 -1
  75. package/components/ln-filter/ln-filter.schema.json +153 -153
  76. package/components/ln-filter/src/filter-model.js +185 -185
  77. package/components/ln-form/ln-form-dev.scss +8 -8
  78. package/components/ln-form/ln-form.js +1 -1
  79. package/components/ln-form/ln-form.schema.json +45 -45
  80. package/components/ln-http/ln-http.js +1 -1
  81. package/components/ln-http/ln-http.schema.json +6 -6
  82. package/components/ln-icon/ln-icon.schema.json +6 -6
  83. package/components/ln-include/ln-include.js +1 -1
  84. package/components/ln-include/ln-include.schema.json +23 -23
  85. package/components/ln-key/ln-key-dev.scss +18 -18
  86. package/components/ln-key/ln-key.js +1 -1
  87. package/components/ln-key/ln-key.schema.json +56 -56
  88. package/components/ln-key/src/ln-key.js +10 -10
  89. package/components/ln-link/ln-link-dev.scss +8 -8
  90. package/components/ln-link/ln-link.js +1 -1
  91. package/components/ln-link/ln-link.schema.json +22 -22
  92. package/components/ln-list/README.md +152 -152
  93. package/components/ln-list/ln-list-dev.scss +8 -8
  94. package/components/ln-list/ln-list.js +1 -1
  95. package/components/ln-list/ln-list.schema.json +166 -166
  96. package/components/ln-modal/ln-modal.js +1 -1
  97. package/components/ln-modal/ln-modal.schema.json +65 -65
  98. package/components/ln-nav/ln-nav.js +1 -1
  99. package/components/ln-nav/ln-nav.schema.json +25 -25
  100. package/components/ln-number/ln-number.js +1 -1
  101. package/components/ln-number/ln-number.schema.json +63 -63
  102. package/components/ln-number/src/number-model.js +31 -31
  103. package/components/ln-obfuscator/README.md +60 -60
  104. package/components/ln-obfuscator/ln-obfuscator.js +1 -1
  105. package/components/ln-obfuscator/ln-obfuscator.schema.json +49 -49
  106. package/components/ln-obfuscator/src/ln-obfuscator.js +159 -159
  107. package/components/ln-obfuscator/src/obfuscator-model.js +250 -250
  108. package/components/ln-options/ln-options.js +1 -1
  109. package/components/ln-options/ln-options.schema.json +41 -41
  110. package/components/ln-persist/README.md +151 -151
  111. package/components/ln-persist/ln-persist.js +1 -1
  112. package/components/ln-persist/ln-persist.schema.json +28 -28
  113. package/components/ln-persist/src/ln-persist.js +83 -83
  114. package/components/ln-picklist/README.md +230 -230
  115. package/components/ln-picklist/ln-picklist-dev.scss +22 -22
  116. package/components/ln-picklist/ln-picklist.js +1 -1
  117. package/components/ln-picklist/ln-picklist.schema.json +49 -49
  118. package/components/ln-picklist/src/ln-picklist.js +228 -228
  119. package/components/ln-popover/ln-popover-dev.scss +13 -13
  120. package/components/ln-popover/ln-popover.js +1 -1
  121. package/components/ln-popover/ln-popover.schema.json +82 -82
  122. package/components/ln-progress/ln-progress-dev.scss +8 -8
  123. package/components/ln-progress/ln-progress.js +1 -1
  124. package/components/ln-progress/ln-progress.schema.json +40 -40
  125. package/components/ln-router/ln-router.js +1 -1
  126. package/components/ln-router/ln-router.schema.json +76 -76
  127. package/components/ln-scroll/README.md +45 -45
  128. package/components/ln-scroll/ln-scroll.js +1 -1
  129. package/components/ln-scroll/ln-scroll.schema.json +85 -85
  130. package/components/ln-scroll/src/ln-scroll.js +150 -150
  131. package/components/ln-search/README.md +188 -188
  132. package/components/ln-search/ln-search.js +1 -1
  133. package/components/ln-search/ln-search.schema.json +103 -103
  134. package/components/ln-slug/ln-slug.js +1 -1
  135. package/components/ln-slug/ln-slug.schema.json +23 -23
  136. package/components/ln-sort/ln-sort.js +1 -1
  137. package/components/ln-sort/ln-sort.schema.json +104 -104
  138. package/components/ln-sort/src/ln-sort.js +321 -321
  139. package/components/ln-sort/src/sort-model.js +117 -117
  140. package/components/ln-sortable/ln-sortable-dev.scss +13 -13
  141. package/components/ln-sortable/ln-sortable.js +1 -1
  142. package/components/ln-sortable/ln-sortable.schema.json +36 -36
  143. package/components/ln-stat/ln-stat-dev.scss +8 -8
  144. package/components/ln-stat/ln-stat.js +1 -1
  145. package/components/ln-stat/ln-stat.schema.json +32 -32
  146. package/components/ln-stat/src/stat-model.js +28 -28
  147. package/components/ln-table/ln-table.js +1 -1
  148. package/components/ln-table/ln-table.schema.json +211 -211
  149. package/components/ln-table/src/table-model.js +98 -98
  150. package/components/ln-table-coordinator/ln-table-coordinator.js +1 -1
  151. package/components/ln-table-coordinator/ln-table-coordinator.schema.json +93 -93
  152. package/components/ln-tabs/ln-tabs.js +1 -1
  153. package/components/ln-tabs/ln-tabs.schema.json +75 -75
  154. package/components/ln-tabs/src/ln-tabs.js +208 -208
  155. package/components/ln-tabs/src/tabs-model.js +82 -82
  156. package/components/ln-time/ln-time-dev.scss +13 -13
  157. package/components/ln-time/ln-time.js +1 -1
  158. package/components/ln-time/ln-time.schema.json +38 -38
  159. package/components/ln-toast/ln-toast.js +1 -1
  160. package/components/ln-toast/ln-toast.schema.json +65 -65
  161. package/components/ln-toggle/ln-toggle.js +1 -1
  162. package/components/ln-toggle/ln-toggle.schema.json +52 -52
  163. package/components/ln-tooltip/ln-tooltip.js +1 -1
  164. package/components/ln-tooltip/ln-tooltip.schema.json +86 -86
  165. package/components/ln-translations/ln-translations.js +1 -1
  166. package/components/ln-translations/ln-translations.schema.json +120 -120
  167. package/components/ln-ui-coordinator/README.md +62 -62
  168. package/components/ln-ui-coordinator/ln-ui-coordinator.js +1 -1
  169. package/components/ln-ui-coordinator/ln-ui-coordinator.schema.json +28 -28
  170. package/components/ln-ui-coordinator/src/ln-ui-coordinator.js +140 -140
  171. package/components/ln-upload/ln-upload.js +1 -1
  172. package/components/ln-upload/ln-upload.schema.json +193 -193
  173. package/components/ln-upload/src/upload-model.js +78 -78
  174. package/components/ln-validate/ln-validate.js +1 -1
  175. package/components/ln-validate/ln-validate.schema.json +50 -50
  176. package/components/ln-validate/src/validate-model.js +64 -64
  177. package/components/ln-websocket-connector/README.md +166 -166
  178. package/components/ln-websocket-connector/ln-websocket-connector.js +1 -1
  179. package/components/ln-websocket-connector/ln-websocket-connector.schema.json +29 -29
  180. package/components/ln-websocket-connector/src/ln-websocket-connector.js +283 -279
  181. package/ln-ashlar.html-data.json +7 -8
  182. package/package.json +84 -84
  183. package/theme/brand.css +73 -73
  184. package/theme/components/_confirm.scss +6 -6
  185. package/theme/components/_picklist.scss +3 -3
  186. package/theme/config/_palette.scss +274 -274
  187. package/theme/config/_theme.scss +292 -292
  188. package/theme/config/_tokens.scss +285 -285
  189. package/theme/config/mixins/_index.scss +62 -62
  190. package/theme/config/mixins/_picklist.scss +66 -66
  191. package/theme/ln-ashlar-dev.scss +66 -66
  192. package/theme/ln-ashlar-landing.scss +56 -56
  193. package/theme/ln-ashlar-theme.scss +63 -63
  194. package/theme/presentation/_bento.scss +151 -151
  195. package/theme/presentation/_cta.scss +111 -111
  196. package/theme/presentation/_effects.scss +216 -216
  197. package/theme/presentation/_features.scss +108 -108
  198. package/theme/presentation/_footer.scss +129 -129
  199. package/theme/presentation/_hero.scss +158 -158
  200. package/theme/presentation/_layout.scss +170 -170
  201. package/theme/presentation/_navbar.scss +140 -140
  202. package/theme/presentation/_pricing.scss +262 -262
  203. package/theme/presentation/_stats.scss +87 -87
  204. package/theme/presentation/_testimonials.scss +124 -124
  205. package/theme/presentation/_tokens.scss +39 -39
  206. package/theme/presentation/_typography.scss +163 -163
  207. 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';