@livenetworks/ashlar 2.0.7 → 2.0.9

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 (213) 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 +9 -0
  12. package/components/ln-api-connector/src/ln-api-connector.js +2 -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/attrs.js +13 -0
  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 +146 -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/lifecycle.js +5 -0
  40. package/components/ln-core/ln-core.schema.json +3 -2
  41. package/components/ln-core/locale.js +55 -55
  42. package/components/ln-core/matching.js +78 -78
  43. package/components/ln-core/number.js +125 -125
  44. package/components/ln-core/template.js +206 -206
  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 +1 -0
  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 +432 -1308
  54. package/components/ln-data-store/ln-data-store-dev.scss +13 -13
  55. package/components/ln-data-store/ln-data-store.js +1 -1
  56. package/components/ln-data-store/ln-data-store.schema.json +84 -84
  57. package/components/ln-data-store/src/data-store-model.js +184 -184
  58. package/components/ln-data-store/src/ln-data-store.js +1 -1
  59. package/components/ln-date/ln-date.js +1 -1
  60. package/components/ln-date/ln-date.schema.json +92 -92
  61. package/components/ln-date/src/date-model.js +186 -186
  62. package/components/ln-debug/ln-debug.js +1 -1
  63. package/components/ln-debug/ln-debug.schema.json +28 -28
  64. package/components/ln-debug/src/console-sink.js +19 -19
  65. package/components/ln-debug/src/gate.js +95 -95
  66. package/components/ln-debug/src/generated-attributes.js +4 -2
  67. package/components/ln-dropdown/ln-dropdown-dev.scss +13 -13
  68. package/components/ln-dropdown/ln-dropdown.js +1 -1
  69. package/components/ln-dropdown/ln-dropdown.schema.json +90 -90
  70. package/components/ln-editor/ln-editor.js +1 -1
  71. package/components/ln-editor/ln-editor.schema.json +58 -58
  72. package/components/ln-external-links/ln-external-links.js +1 -1
  73. package/components/ln-external-links/ln-external-links.schema.json +18 -18
  74. package/components/ln-fill/ln-fill.js +1 -1
  75. package/components/ln-fill/ln-fill.schema.json +23 -23
  76. package/components/ln-filter/ln-filter.js +1 -1
  77. package/components/ln-filter/ln-filter.schema.json +153 -153
  78. package/components/ln-filter/src/filter-model.js +185 -185
  79. package/components/ln-form/ln-form-dev.scss +8 -8
  80. package/components/ln-form/ln-form.js +1 -1
  81. package/components/ln-form/ln-form.schema.json +6 -0
  82. package/components/ln-form/src/ln-form.js +21 -0
  83. package/components/ln-http/ln-http.js +1 -1
  84. package/components/ln-http/ln-http.schema.json +6 -6
  85. package/components/ln-icon/ln-icon.schema.json +6 -6
  86. package/components/ln-include/ln-include.js +1 -1
  87. package/components/ln-include/ln-include.schema.json +23 -23
  88. package/components/ln-key/ln-key-dev.scss +18 -18
  89. package/components/ln-key/ln-key.js +1 -1
  90. package/components/ln-key/ln-key.schema.json +56 -56
  91. package/components/ln-key/src/ln-key.js +10 -10
  92. package/components/ln-link/ln-link-dev.scss +8 -8
  93. package/components/ln-link/ln-link.js +1 -1
  94. package/components/ln-link/ln-link.schema.json +22 -22
  95. package/components/ln-list/README.md +152 -152
  96. package/components/ln-list/ln-list-dev.scss +8 -8
  97. package/components/ln-list/ln-list.js +1 -1
  98. package/components/ln-list/ln-list.schema.json +166 -166
  99. package/components/ln-modal/ln-modal.js +1 -1
  100. package/components/ln-modal/ln-modal.schema.json +65 -65
  101. package/components/ln-nav/ln-nav.js +1 -1
  102. package/components/ln-nav/ln-nav.schema.json +25 -25
  103. package/components/ln-number/ln-number.js +1 -1
  104. package/components/ln-number/ln-number.schema.json +63 -63
  105. package/components/ln-number/src/ln-number.js +26 -0
  106. package/components/ln-number/src/number-model.js +31 -31
  107. package/components/ln-obfuscator/README.md +60 -60
  108. package/components/ln-obfuscator/ln-obfuscator.js +1 -1
  109. package/components/ln-obfuscator/ln-obfuscator.schema.json +49 -49
  110. package/components/ln-obfuscator/src/ln-obfuscator.js +159 -159
  111. package/components/ln-obfuscator/src/obfuscator-model.js +250 -250
  112. package/components/ln-options/ln-options.js +1 -1
  113. package/components/ln-options/ln-options.schema.json +6 -0
  114. package/components/ln-options/src/ln-options.js +4 -4
  115. package/components/ln-persist/README.md +151 -151
  116. package/components/ln-persist/ln-persist.js +1 -1
  117. package/components/ln-persist/ln-persist.schema.json +28 -28
  118. package/components/ln-persist/src/ln-persist.js +83 -83
  119. package/components/ln-picklist/README.md +230 -230
  120. package/components/ln-picklist/ln-picklist-dev.scss +22 -22
  121. package/components/ln-picklist/ln-picklist.js +1 -1
  122. package/components/ln-picklist/ln-picklist.schema.json +49 -49
  123. package/components/ln-picklist/src/ln-picklist.js +228 -228
  124. package/components/ln-popover/ln-popover-dev.scss +13 -13
  125. package/components/ln-popover/ln-popover.js +1 -1
  126. package/components/ln-popover/ln-popover.schema.json +82 -82
  127. package/components/ln-progress/ln-progress-dev.scss +8 -8
  128. package/components/ln-progress/ln-progress.js +1 -1
  129. package/components/ln-progress/ln-progress.schema.json +40 -40
  130. package/components/ln-router/ln-router.js +1 -1
  131. package/components/ln-router/ln-router.schema.json +76 -76
  132. package/components/ln-scroll/README.md +45 -45
  133. package/components/ln-scroll/ln-scroll.js +1 -1
  134. package/components/ln-scroll/ln-scroll.schema.json +85 -85
  135. package/components/ln-scroll/src/ln-scroll.js +150 -150
  136. package/components/ln-search/README.md +188 -188
  137. package/components/ln-search/ln-search.js +1 -1
  138. package/components/ln-search/ln-search.schema.json +103 -103
  139. package/components/ln-slug/ln-slug.js +1 -1
  140. package/components/ln-slug/ln-slug.schema.json +23 -23
  141. package/components/ln-slug/src/ln-slug.js +25 -1
  142. package/components/ln-sort/ln-sort.js +1 -1
  143. package/components/ln-sort/ln-sort.schema.json +104 -104
  144. package/components/ln-sort/src/ln-sort.js +321 -321
  145. package/components/ln-sort/src/sort-model.js +117 -117
  146. package/components/ln-sortable/ln-sortable-dev.scss +13 -13
  147. package/components/ln-sortable/ln-sortable.js +1 -1
  148. package/components/ln-sortable/ln-sortable.schema.json +36 -36
  149. package/components/ln-stat/ln-stat-dev.scss +8 -8
  150. package/components/ln-stat/ln-stat.js +1 -1
  151. package/components/ln-stat/ln-stat.schema.json +32 -32
  152. package/components/ln-stat/src/stat-model.js +28 -28
  153. package/components/ln-table/ln-table.js +1 -1
  154. package/components/ln-table/ln-table.schema.json +211 -211
  155. package/components/ln-table/src/table-model.js +98 -98
  156. package/components/ln-table-coordinator/ln-table-coordinator.js +1 -1
  157. package/components/ln-table-coordinator/ln-table-coordinator.schema.json +93 -93
  158. package/components/ln-tabs/ln-tabs.js +1 -1
  159. package/components/ln-tabs/ln-tabs.schema.json +75 -75
  160. package/components/ln-tabs/src/ln-tabs.js +208 -208
  161. package/components/ln-tabs/src/tabs-model.js +82 -82
  162. package/components/ln-time/ln-time-dev.scss +13 -13
  163. package/components/ln-time/ln-time.js +1 -1
  164. package/components/ln-time/ln-time.schema.json +38 -38
  165. package/components/ln-toast/ln-toast.js +1 -1
  166. package/components/ln-toast/ln-toast.schema.json +65 -65
  167. package/components/ln-toggle/ln-toggle.js +1 -1
  168. package/components/ln-toggle/ln-toggle.schema.json +52 -52
  169. package/components/ln-tooltip/ln-tooltip.js +1 -1
  170. package/components/ln-tooltip/ln-tooltip.schema.json +86 -86
  171. package/components/ln-translations/ln-translations.js +1 -1
  172. package/components/ln-translations/ln-translations.schema.json +120 -120
  173. package/components/ln-ui-coordinator/README.md +62 -62
  174. package/components/ln-ui-coordinator/ln-ui-coordinator.js +1 -1
  175. package/components/ln-ui-coordinator/ln-ui-coordinator.schema.json +28 -28
  176. package/components/ln-ui-coordinator/src/ln-ui-coordinator.js +140 -140
  177. package/components/ln-upload/ln-upload.js +1 -1
  178. package/components/ln-upload/ln-upload.schema.json +193 -193
  179. package/components/ln-upload/src/upload-model.js +78 -78
  180. package/components/ln-validate/ln-validate.js +1 -1
  181. package/components/ln-validate/ln-validate.schema.json +50 -50
  182. package/components/ln-validate/src/validate-model.js +64 -64
  183. package/components/ln-websocket-connector/README.md +166 -166
  184. package/components/ln-websocket-connector/ln-websocket-connector.js +1 -1
  185. package/components/ln-websocket-connector/ln-websocket-connector.schema.json +29 -29
  186. package/components/ln-websocket-connector/src/ln-websocket-connector.js +283 -279
  187. package/ln-ashlar.html-data.json +15 -8
  188. package/package.json +85 -84
  189. package/theme/brand.css +73 -73
  190. package/theme/components/_confirm.scss +6 -6
  191. package/theme/components/_picklist.scss +3 -3
  192. package/theme/config/_palette.scss +274 -274
  193. package/theme/config/_theme.scss +292 -292
  194. package/theme/config/_tokens.scss +285 -285
  195. package/theme/config/mixins/_index.scss +62 -62
  196. package/theme/config/mixins/_picklist.scss +66 -66
  197. package/theme/ln-ashlar-dev.scss +66 -66
  198. package/theme/ln-ashlar-landing.scss +56 -56
  199. package/theme/ln-ashlar-theme.scss +63 -63
  200. package/theme/presentation/_bento.scss +151 -151
  201. package/theme/presentation/_cta.scss +111 -111
  202. package/theme/presentation/_effects.scss +216 -216
  203. package/theme/presentation/_features.scss +108 -108
  204. package/theme/presentation/_footer.scss +129 -129
  205. package/theme/presentation/_hero.scss +158 -158
  206. package/theme/presentation/_layout.scss +170 -170
  207. package/theme/presentation/_navbar.scss +140 -140
  208. package/theme/presentation/_pricing.scss +262 -262
  209. package/theme/presentation/_stats.scss +87 -87
  210. package/theme/presentation/_testimonials.scss +124 -124
  211. package/theme/presentation/_tokens.scss +39 -39
  212. package/theme/presentation/_typography.scss +163 -163
  213. package/web-types.json +26 -12
@@ -1,178 +1,178 @@
1
- import { registerComponent, dispatch, shouldIgnoreClick, defineAttrs, attrSpec } from '../../ln-core';
2
-
3
- (function () {
4
- const DOM_SELECTOR = 'data-ln-confirm';
5
- const DOM_ATTRIBUTE = 'lnConfirm';
6
- const STATE_ATTR = 'data-ln-confirm-state';
7
- const ANNOUNCER_ATTR = 'data-ln-confirm-announcer';
8
- const DEFAULT_TIMEOUT = 3;
9
-
10
- if (window[DOM_ATTRIBUTE] !== undefined) return;
11
-
12
- // `attrStr` would keep an empty attribute as '' and blank the button.
13
- function _readPrompt(el, name, fallback) {
14
- return el.getAttribute(name) || fallback;
15
- }
16
-
17
- // Seconds, fractional allowed; non-positive or unparseable counts as unset.
18
- // `attrInt` does neither.
19
- function _readTimeout(el, name, fallback) {
20
- const val = parseFloat(el.getAttribute(name));
21
- return (isNaN(val) || val <= 0) ? fallback : val;
22
- }
23
-
24
- // The bubble is a CSS ::after — invisible to AT. `role="alert"` is its own
25
- // assertive live region, so the button must NOT also be one: a live region
26
- // nested in a live region gets announced twice.
27
- function _makeAnnouncer(text) {
28
- const el = document.createElement('span');
29
- el.setAttribute(ANNOUNCER_ATTR, '');
30
- el.setAttribute('role', 'alert');
31
- el.textContent = text;
32
- return el;
33
- }
34
-
35
- // ─── Attribute Contract (SSOT) ──────────────────────────
36
- const ATTRIBUTES = {
37
- 'data-ln-confirm': { prop: 'confirmText', type: 'string', read: _readPrompt, fallback: 'Confirm?', description: 'Prompt text or confirmation action trigger' },
38
- 'data-ln-confirm-timeout': { prop: 'timeout', type: 'float', read: _readTimeout, fallback: DEFAULT_TIMEOUT, min: 0.1, description: 'Confirmation timeout in seconds before reverting' },
39
- 'data-ln-confirm-state': { prop: 'confirming', type: 'enum', values: ['confirming'], read: (el, name) => el.getAttribute(name) === 'confirming', description: 'Active confirmation state marker on button ("confirming")' }
40
- };
41
- const ATTR_SPEC = attrSpec(ATTRIBUTES);
42
-
43
- // ─── Component ─────────────────────────────────────────────
44
-
45
- function _component(dom) {
46
- this.dom = dom;
47
- defineAttrs(this, dom, ATTR_SPEC);
48
- this.revertTimer = null;
49
- this._submitted = false;
50
-
51
- // Detect two-element mode
52
- this.idleEl = dom.querySelector('[data-ln-confirm-idle]');
53
- this.activeEl = dom.querySelector('[data-ln-confirm-active]');
54
- this.isTwoElementMode = Boolean(this.idleEl || this.activeEl);
55
-
56
- // Not an attribute — a snapshot of the authored label, restored on revert.
57
- this.originalText = this.isTwoElementMode ? '' : dom.textContent.trim();
58
-
59
- const self = this;
60
- this._onClick = function (e) {
61
- if (shouldIgnoreClick(e)) return;
62
-
63
- if (!self.confirming) {
64
- e.preventDefault();
65
- e.stopImmediatePropagation();
66
- self._enterConfirm();
67
- } else {
68
- if (self._submitted) return;
69
- self._submitted = true;
70
- // Second click — the gate opens for THIS button's own default
71
- // action (submit / href) and delegated listeners.
72
- self._reset();
73
- }
74
- };
75
-
76
- dom.addEventListener('click', this._onClick);
77
- return this;
78
- }
79
-
80
- _component.prototype._enterConfirm = function () {
81
- this.dom.setAttribute(STATE_ATTR, 'confirming');
82
-
83
- this.originalAriaLabel = this.dom.getAttribute('aria-label');
84
- this.originalAriaLive = this.dom.getAttribute('aria-live');
85
-
86
- if (this.isTwoElementMode) {
87
- if (this.idleEl) this.idleEl.setAttribute('hidden', 'true');
88
- if (this.activeEl) this.activeEl.removeAttribute('hidden');
89
-
90
- const promptText = this.activeEl ? this.activeEl.textContent.trim() : '';
91
- if (promptText) {
92
- this.dom.setAttribute('aria-label', promptText);
93
- this.dom.setAttribute('aria-live', 'polite');
94
- }
95
- } else {
96
- const iconUse = this.dom.querySelector('svg.ln-icon use');
97
- if (iconUse && this.originalText === '') {
98
- this.isIconButton = true;
99
- this.originalIconHref = iconUse.getAttribute('href');
100
- iconUse.setAttribute('href', '#ln-icon-check');
101
- this.dom.setAttribute('aria-label', this.confirmText);
102
- this.dom.appendChild(_makeAnnouncer(this.confirmText));
103
- } else {
104
- this.dom.textContent = this.confirmText;
105
- }
106
- }
107
-
108
- this._startTimer();
109
- dispatch(this.dom, 'ln-confirm:waiting', { target: this.dom });
110
- };
111
-
112
- _component.prototype._startTimer = function () {
113
- if (this.revertTimer) {
114
- clearTimeout(this.revertTimer);
115
- }
116
- const self = this;
117
- const ms = this.timeout * 1000;
118
- this.revertTimer = setTimeout(function () {
119
- self._reset();
120
- }, ms);
121
- };
122
-
123
- _component.prototype._reset = function () {
124
- this._submitted = false;
125
- this.dom.removeAttribute(STATE_ATTR);
126
-
127
- if (this.isTwoElementMode) {
128
- if (this.idleEl) this.idleEl.removeAttribute('hidden');
129
- if (this.activeEl) this.activeEl.setAttribute('hidden', 'true');
130
- } else {
131
- if (this.isIconButton) {
132
- const iconUse = this.dom.querySelector('svg.ln-icon use');
133
- if (iconUse && this.originalIconHref) {
134
- iconUse.setAttribute('href', this.originalIconHref);
135
- }
136
- const announcer = this.dom.querySelector('[' + ANNOUNCER_ATTR + ']');
137
- if (announcer) announcer.remove();
138
- this.isIconButton = false;
139
- this.originalIconHref = null;
140
- } else {
141
- this.dom.textContent = this.originalText;
142
- }
143
- }
144
-
145
- // Restore Accessibility Attributes directly on host button
146
- if (this.originalAriaLabel !== null && this.originalAriaLabel !== undefined) {
147
- this.dom.setAttribute('aria-label', this.originalAriaLabel);
148
- } else {
149
- this.dom.removeAttribute('aria-label');
150
- }
151
- this.originalAriaLabel = null;
152
-
153
- if (this.originalAriaLive !== null && this.originalAriaLive !== undefined) {
154
- this.dom.setAttribute('aria-live', this.originalAriaLive);
155
- } else {
156
- this.dom.removeAttribute('aria-live');
157
- }
158
- this.originalAriaLive = null;
159
-
160
- if (this.revertTimer) {
161
- clearTimeout(this.revertTimer);
162
- this.revertTimer = null;
163
- }
164
- };
165
-
166
- _component.prototype.destroy = function () {
167
- if (!this.dom[DOM_ATTRIBUTE]) return;
168
- if (this.confirming) this._reset();
169
- this.dom.removeEventListener('click', this._onClick);
170
- delete this.dom[DOM_ATTRIBUTE];
171
- };
172
-
173
- // ─── Init ──────────────────────────────────────────────────
174
-
175
- registerComponent(DOM_SELECTOR, DOM_ATTRIBUTE, _component, 'ln-confirm', {
176
- attributes: ATTRIBUTES
177
- });
178
- })();
1
+ import { registerComponent, dispatch, shouldIgnoreClick, defineAttrs, attrSpec } from '../../ln-core';
2
+
3
+ (function () {
4
+ const DOM_SELECTOR = 'data-ln-confirm';
5
+ const DOM_ATTRIBUTE = 'lnConfirm';
6
+ const STATE_ATTR = 'data-ln-confirm-state';
7
+ const ANNOUNCER_ATTR = 'data-ln-confirm-announcer';
8
+ const DEFAULT_TIMEOUT = 3;
9
+
10
+ if (window[DOM_ATTRIBUTE] !== undefined) return;
11
+
12
+ // `attrStr` would keep an empty attribute as '' and blank the button.
13
+ function _readPrompt(el, name, fallback) {
14
+ return el.getAttribute(name) || fallback;
15
+ }
16
+
17
+ // Seconds, fractional allowed; non-positive or unparseable counts as unset.
18
+ // `attrInt` does neither.
19
+ function _readTimeout(el, name, fallback) {
20
+ const val = parseFloat(el.getAttribute(name));
21
+ return (isNaN(val) || val <= 0) ? fallback : val;
22
+ }
23
+
24
+ // The bubble is a CSS ::after — invisible to AT. `role="alert"` is its own
25
+ // assertive live region, so the button must NOT also be one: a live region
26
+ // nested in a live region gets announced twice.
27
+ function _makeAnnouncer(text) {
28
+ const el = document.createElement('span');
29
+ el.setAttribute(ANNOUNCER_ATTR, '');
30
+ el.setAttribute('role', 'alert');
31
+ el.textContent = text;
32
+ return el;
33
+ }
34
+
35
+ // ─── Attribute Contract (SSOT) ──────────────────────────
36
+ const ATTRIBUTES = {
37
+ 'data-ln-confirm': { prop: 'confirmText', type: 'string', read: _readPrompt, fallback: 'Confirm?', description: 'Prompt text or confirmation action trigger' },
38
+ 'data-ln-confirm-timeout': { prop: 'timeout', type: 'float', read: _readTimeout, fallback: DEFAULT_TIMEOUT, min: 0.1, description: 'Confirmation timeout in seconds before reverting' },
39
+ 'data-ln-confirm-state': { prop: 'confirming', type: 'enum', values: ['confirming'], read: (el, name) => el.getAttribute(name) === 'confirming', description: 'Active confirmation state marker on button ("confirming")' }
40
+ };
41
+ const ATTR_SPEC = attrSpec(ATTRIBUTES);
42
+
43
+ // ─── Component ─────────────────────────────────────────────
44
+
45
+ function _component(dom) {
46
+ this.dom = dom;
47
+ defineAttrs(this, dom, ATTR_SPEC);
48
+ this.revertTimer = null;
49
+ this._submitted = false;
50
+
51
+ // Detect two-element mode
52
+ this.idleEl = dom.querySelector('[data-ln-confirm-idle]');
53
+ this.activeEl = dom.querySelector('[data-ln-confirm-active]');
54
+ this.isTwoElementMode = Boolean(this.idleEl || this.activeEl);
55
+
56
+ // Not an attribute — a snapshot of the authored label, restored on revert.
57
+ this.originalText = this.isTwoElementMode ? '' : dom.textContent.trim();
58
+
59
+ const self = this;
60
+ this._onClick = function (e) {
61
+ if (shouldIgnoreClick(e)) return;
62
+
63
+ if (!self.confirming) {
64
+ e.preventDefault();
65
+ e.stopImmediatePropagation();
66
+ self._enterConfirm();
67
+ } else {
68
+ if (self._submitted) return;
69
+ self._submitted = true;
70
+ // Second click — the gate opens for THIS button's own default
71
+ // action (submit / href) and delegated listeners.
72
+ self._reset();
73
+ }
74
+ };
75
+
76
+ dom.addEventListener('click', this._onClick);
77
+ return this;
78
+ }
79
+
80
+ _component.prototype._enterConfirm = function () {
81
+ this.dom.setAttribute(STATE_ATTR, 'confirming');
82
+
83
+ this.originalAriaLabel = this.dom.getAttribute('aria-label');
84
+ this.originalAriaLive = this.dom.getAttribute('aria-live');
85
+
86
+ if (this.isTwoElementMode) {
87
+ if (this.idleEl) this.idleEl.setAttribute('hidden', 'true');
88
+ if (this.activeEl) this.activeEl.removeAttribute('hidden');
89
+
90
+ const promptText = this.activeEl ? this.activeEl.textContent.trim() : '';
91
+ if (promptText) {
92
+ this.dom.setAttribute('aria-label', promptText);
93
+ this.dom.setAttribute('aria-live', 'polite');
94
+ }
95
+ } else {
96
+ const iconUse = this.dom.querySelector('svg.ln-icon use');
97
+ if (iconUse && this.originalText === '') {
98
+ this.isIconButton = true;
99
+ this.originalIconHref = iconUse.getAttribute('href');
100
+ iconUse.setAttribute('href', '#ln-icon-check');
101
+ this.dom.setAttribute('aria-label', this.confirmText);
102
+ this.dom.appendChild(_makeAnnouncer(this.confirmText));
103
+ } else {
104
+ this.dom.textContent = this.confirmText;
105
+ }
106
+ }
107
+
108
+ this._startTimer();
109
+ dispatch(this.dom, 'ln-confirm:waiting', { target: this.dom });
110
+ };
111
+
112
+ _component.prototype._startTimer = function () {
113
+ if (this.revertTimer) {
114
+ clearTimeout(this.revertTimer);
115
+ }
116
+ const self = this;
117
+ const ms = this.timeout * 1000;
118
+ this.revertTimer = setTimeout(function () {
119
+ self._reset();
120
+ }, ms);
121
+ };
122
+
123
+ _component.prototype._reset = function () {
124
+ this._submitted = false;
125
+ this.dom.removeAttribute(STATE_ATTR);
126
+
127
+ if (this.isTwoElementMode) {
128
+ if (this.idleEl) this.idleEl.removeAttribute('hidden');
129
+ if (this.activeEl) this.activeEl.setAttribute('hidden', 'true');
130
+ } else {
131
+ if (this.isIconButton) {
132
+ const iconUse = this.dom.querySelector('svg.ln-icon use');
133
+ if (iconUse && this.originalIconHref) {
134
+ iconUse.setAttribute('href', this.originalIconHref);
135
+ }
136
+ const announcer = this.dom.querySelector('[' + ANNOUNCER_ATTR + ']');
137
+ if (announcer) announcer.remove();
138
+ this.isIconButton = false;
139
+ this.originalIconHref = null;
140
+ } else {
141
+ this.dom.textContent = this.originalText;
142
+ }
143
+ }
144
+
145
+ // Restore Accessibility Attributes directly on host button
146
+ if (this.originalAriaLabel !== null && this.originalAriaLabel !== undefined) {
147
+ this.dom.setAttribute('aria-label', this.originalAriaLabel);
148
+ } else {
149
+ this.dom.removeAttribute('aria-label');
150
+ }
151
+ this.originalAriaLabel = null;
152
+
153
+ if (this.originalAriaLive !== null && this.originalAriaLive !== undefined) {
154
+ this.dom.setAttribute('aria-live', this.originalAriaLive);
155
+ } else {
156
+ this.dom.removeAttribute('aria-live');
157
+ }
158
+ this.originalAriaLive = null;
159
+
160
+ if (this.revertTimer) {
161
+ clearTimeout(this.revertTimer);
162
+ this.revertTimer = null;
163
+ }
164
+ };
165
+
166
+ _component.prototype.destroy = function () {
167
+ if (!this.dom[DOM_ATTRIBUTE]) return;
168
+ if (this.confirming) this._reset();
169
+ this.dom.removeEventListener('click', this._onClick);
170
+ delete this.dom[DOM_ATTRIBUTE];
171
+ };
172
+
173
+ // ─── Init ──────────────────────────────────────────────────
174
+
175
+ registerComponent(DOM_SELECTOR, DOM_ATTRIBUTE, _component, 'ln-confirm', {
176
+ attributes: ATTRIBUTES
177
+ });
178
+ })();
@@ -271,3 +271,16 @@ export function reactiveNames(entry) {
271
271
  return names;
272
272
  }
273
273
 
274
+ if (typeof window !== 'undefined') {
275
+ window.lnCore = window.lnCore || {};
276
+ window.lnCore.defineAttrs = defineAttrs;
277
+ window.lnCore.attrSpec = attrSpec;
278
+ window.lnCore.attrStr = attrStr;
279
+ window.lnCore.attrInt = attrInt;
280
+ window.lnCore.attrBool = attrBool;
281
+ window.lnCore.attrList = attrList;
282
+ window.lnCore.attrEnum = attrEnum;
283
+ window.lnCore.attrFloat = attrFloat;
284
+ window.lnCore.attrJson = attrJson;
285
+ }
286
+