@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.
- package/LICENSE +641 -641
- package/components/COMPONENTS.md +1116 -1116
- package/components/index.js +81 -81
- package/components/ln-accordion/ln-accordion-dev.scss +8 -8
- package/components/ln-accordion/ln-accordion.js +1 -1
- package/components/ln-accordion/ln-accordion.schema.json +30 -30
- package/components/ln-ajax/ln-ajax-dev.scss +8 -8
- package/components/ln-ajax/ln-ajax.js +1 -1
- package/components/ln-ajax/ln-ajax.schema.json +30 -30
- package/components/ln-api-connector/ln-api-connector.js +1 -1
- package/components/ln-api-connector/ln-api-connector.schema.json +96 -96
- package/components/ln-api-connector/src/ln-api-connector.js +1 -0
- package/components/ln-api-queue/ln-api-queue.js +1 -1
- package/components/ln-api-queue/ln-api-queue.schema.json +34 -34
- package/components/ln-api-queue/src/ln-api-queue.js +3 -13
- package/components/ln-autoresize/ln-autoresize-dev.scss +8 -8
- package/components/ln-autoresize/ln-autoresize.js +1 -1
- package/components/ln-autoresize/ln-autoresize.schema.json +22 -22
- package/components/ln-autosave/ln-autosave-dev.scss +13 -13
- package/components/ln-autosave/ln-autosave.js +1 -1
- package/components/ln-autosave/ln-autosave.schema.json +48 -48
- package/components/ln-autosave/src/autosave-model.js +34 -34
- package/components/ln-chart/ln-chart.js +1 -1
- package/components/ln-chart/ln-chart.schema.json +146 -146
- package/components/ln-chart/src/chart-model.js +154 -154
- package/components/ln-circular-progress/ln-circular-progress.js +1 -1
- package/components/ln-circular-progress/ln-circular-progress.schema.json +42 -42
- package/components/ln-confirm/ln-confirm-dev.scss +24 -24
- package/components/ln-confirm/ln-confirm.js +1 -1
- package/components/ln-confirm/ln-confirm.schema.json +66 -66
- package/components/ln-confirm/src/ln-confirm.js +178 -178
- package/components/ln-core/crypto.js +286 -265
- package/components/ln-core/dom.js +115 -115
- package/components/ln-core/form.js +136 -136
- package/components/ln-core/helpers.js +33 -33
- package/components/ln-core/http.js +48 -48
- package/components/ln-core/index.js +1 -1
- package/components/ln-core/ln-core.schema.json +109 -109
- package/components/ln-core/locale.js +55 -55
- package/components/ln-core/matching.js +78 -78
- package/components/ln-core/number.js +125 -125
- package/components/ln-core/template.js +206 -206
- package/components/ln-couchdb-connector/ln-couchdb-connector.js +1 -1
- package/components/ln-couchdb-connector/ln-couchdb-connector.schema.json +50 -50
- package/components/ln-couchdb-connector/src/ln-couchdb-connector.js +1 -0
- package/components/ln-data-coordinator/README.md +9 -38
- package/components/ln-data-coordinator/ln-data-coordinator-dev.scss +8 -8
- package/components/ln-data-coordinator/ln-data-coordinator.js +1 -1
- package/components/ln-data-coordinator/ln-data-coordinator.schema.json +16 -16
- package/components/ln-data-coordinator/src/data-read-policy.js +0 -7
- package/components/ln-data-coordinator/src/ln-data-coordinator.js +428 -1308
- package/components/ln-data-store/ln-data-store-dev.scss +13 -13
- package/components/ln-data-store/ln-data-store.js +1 -1
- package/components/ln-data-store/ln-data-store.schema.json +84 -84
- package/components/ln-data-store/src/data-store-model.js +184 -184
- package/components/ln-data-store/src/ln-data-store.js +1 -1
- package/components/ln-date/ln-date.js +1 -1
- package/components/ln-date/ln-date.schema.json +92 -92
- package/components/ln-date/src/date-model.js +186 -186
- package/components/ln-debug/ln-debug.js +1 -1
- package/components/ln-debug/ln-debug.schema.json +28 -28
- package/components/ln-debug/src/console-sink.js +19 -19
- package/components/ln-debug/src/gate.js +95 -95
- package/components/ln-debug/src/generated-attributes.js +2 -2
- package/components/ln-dropdown/ln-dropdown-dev.scss +13 -13
- package/components/ln-dropdown/ln-dropdown.js +1 -1
- package/components/ln-dropdown/ln-dropdown.schema.json +90 -90
- package/components/ln-editor/ln-editor.js +1 -1
- package/components/ln-editor/ln-editor.schema.json +58 -58
- package/components/ln-external-links/ln-external-links.js +1 -1
- package/components/ln-external-links/ln-external-links.schema.json +18 -18
- package/components/ln-fill/ln-fill.js +1 -1
- package/components/ln-fill/ln-fill.schema.json +23 -23
- package/components/ln-filter/ln-filter.js +1 -1
- package/components/ln-filter/ln-filter.schema.json +153 -153
- package/components/ln-filter/src/filter-model.js +185 -185
- package/components/ln-form/ln-form-dev.scss +8 -8
- package/components/ln-form/ln-form.js +1 -1
- package/components/ln-form/ln-form.schema.json +45 -45
- package/components/ln-http/ln-http.js +1 -1
- package/components/ln-http/ln-http.schema.json +6 -6
- package/components/ln-icon/ln-icon.schema.json +6 -6
- package/components/ln-include/ln-include.js +1 -1
- package/components/ln-include/ln-include.schema.json +23 -23
- package/components/ln-key/ln-key-dev.scss +18 -18
- package/components/ln-key/ln-key.js +1 -1
- package/components/ln-key/ln-key.schema.json +56 -56
- package/components/ln-key/src/ln-key.js +10 -10
- package/components/ln-link/ln-link-dev.scss +8 -8
- package/components/ln-link/ln-link.js +1 -1
- package/components/ln-link/ln-link.schema.json +22 -22
- package/components/ln-list/README.md +152 -152
- package/components/ln-list/ln-list-dev.scss +8 -8
- package/components/ln-list/ln-list.js +1 -1
- package/components/ln-list/ln-list.schema.json +166 -166
- package/components/ln-modal/ln-modal.js +1 -1
- package/components/ln-modal/ln-modal.schema.json +65 -65
- package/components/ln-nav/ln-nav.js +1 -1
- package/components/ln-nav/ln-nav.schema.json +25 -25
- package/components/ln-number/ln-number.js +1 -1
- package/components/ln-number/ln-number.schema.json +63 -63
- package/components/ln-number/src/number-model.js +31 -31
- package/components/ln-obfuscator/README.md +60 -60
- package/components/ln-obfuscator/ln-obfuscator.js +1 -1
- package/components/ln-obfuscator/ln-obfuscator.schema.json +49 -49
- package/components/ln-obfuscator/src/ln-obfuscator.js +159 -159
- package/components/ln-obfuscator/src/obfuscator-model.js +250 -250
- package/components/ln-options/ln-options.js +1 -1
- package/components/ln-options/ln-options.schema.json +41 -41
- package/components/ln-persist/README.md +151 -151
- package/components/ln-persist/ln-persist.js +1 -1
- package/components/ln-persist/ln-persist.schema.json +28 -28
- package/components/ln-persist/src/ln-persist.js +83 -83
- package/components/ln-picklist/README.md +230 -230
- package/components/ln-picklist/ln-picklist-dev.scss +22 -22
- package/components/ln-picklist/ln-picklist.js +1 -1
- package/components/ln-picklist/ln-picklist.schema.json +49 -49
- package/components/ln-picklist/src/ln-picklist.js +228 -228
- package/components/ln-popover/ln-popover-dev.scss +13 -13
- package/components/ln-popover/ln-popover.js +1 -1
- package/components/ln-popover/ln-popover.schema.json +82 -82
- package/components/ln-progress/ln-progress-dev.scss +8 -8
- package/components/ln-progress/ln-progress.js +1 -1
- package/components/ln-progress/ln-progress.schema.json +40 -40
- package/components/ln-router/ln-router.js +1 -1
- package/components/ln-router/ln-router.schema.json +76 -76
- package/components/ln-scroll/README.md +45 -45
- package/components/ln-scroll/ln-scroll.js +1 -1
- package/components/ln-scroll/ln-scroll.schema.json +85 -85
- package/components/ln-scroll/src/ln-scroll.js +150 -150
- package/components/ln-search/README.md +188 -188
- package/components/ln-search/ln-search.js +1 -1
- package/components/ln-search/ln-search.schema.json +103 -103
- package/components/ln-slug/ln-slug.js +1 -1
- package/components/ln-slug/ln-slug.schema.json +23 -23
- package/components/ln-sort/ln-sort.js +1 -1
- package/components/ln-sort/ln-sort.schema.json +104 -104
- package/components/ln-sort/src/ln-sort.js +321 -321
- package/components/ln-sort/src/sort-model.js +117 -117
- package/components/ln-sortable/ln-sortable-dev.scss +13 -13
- package/components/ln-sortable/ln-sortable.js +1 -1
- package/components/ln-sortable/ln-sortable.schema.json +36 -36
- package/components/ln-stat/ln-stat-dev.scss +8 -8
- package/components/ln-stat/ln-stat.js +1 -1
- package/components/ln-stat/ln-stat.schema.json +32 -32
- package/components/ln-stat/src/stat-model.js +28 -28
- package/components/ln-table/ln-table.js +1 -1
- package/components/ln-table/ln-table.schema.json +211 -211
- package/components/ln-table/src/table-model.js +98 -98
- package/components/ln-table-coordinator/ln-table-coordinator.js +1 -1
- package/components/ln-table-coordinator/ln-table-coordinator.schema.json +93 -93
- package/components/ln-tabs/ln-tabs.js +1 -1
- package/components/ln-tabs/ln-tabs.schema.json +75 -75
- package/components/ln-tabs/src/ln-tabs.js +208 -208
- package/components/ln-tabs/src/tabs-model.js +82 -82
- package/components/ln-time/ln-time-dev.scss +13 -13
- package/components/ln-time/ln-time.js +1 -1
- package/components/ln-time/ln-time.schema.json +38 -38
- package/components/ln-toast/ln-toast.js +1 -1
- package/components/ln-toast/ln-toast.schema.json +65 -65
- package/components/ln-toggle/ln-toggle.js +1 -1
- package/components/ln-toggle/ln-toggle.schema.json +52 -52
- package/components/ln-tooltip/ln-tooltip.js +1 -1
- package/components/ln-tooltip/ln-tooltip.schema.json +86 -86
- package/components/ln-translations/ln-translations.js +1 -1
- package/components/ln-translations/ln-translations.schema.json +120 -120
- package/components/ln-ui-coordinator/README.md +62 -62
- package/components/ln-ui-coordinator/ln-ui-coordinator.js +1 -1
- package/components/ln-ui-coordinator/ln-ui-coordinator.schema.json +28 -28
- package/components/ln-ui-coordinator/src/ln-ui-coordinator.js +140 -140
- package/components/ln-upload/ln-upload.js +1 -1
- package/components/ln-upload/ln-upload.schema.json +193 -193
- package/components/ln-upload/src/upload-model.js +78 -78
- package/components/ln-validate/ln-validate.js +1 -1
- package/components/ln-validate/ln-validate.schema.json +50 -50
- package/components/ln-validate/src/validate-model.js +64 -64
- package/components/ln-websocket-connector/README.md +166 -166
- package/components/ln-websocket-connector/ln-websocket-connector.js +1 -1
- package/components/ln-websocket-connector/ln-websocket-connector.schema.json +29 -29
- package/components/ln-websocket-connector/src/ln-websocket-connector.js +283 -279
- package/ln-ashlar.html-data.json +7 -8
- package/package.json +84 -84
- package/theme/brand.css +73 -73
- package/theme/components/_confirm.scss +6 -6
- package/theme/components/_picklist.scss +3 -3
- package/theme/config/_palette.scss +274 -274
- package/theme/config/_theme.scss +292 -292
- package/theme/config/_tokens.scss +285 -285
- package/theme/config/mixins/_index.scss +62 -62
- package/theme/config/mixins/_picklist.scss +66 -66
- package/theme/ln-ashlar-dev.scss +66 -66
- package/theme/ln-ashlar-landing.scss +56 -56
- package/theme/ln-ashlar-theme.scss +63 -63
- package/theme/presentation/_bento.scss +151 -151
- package/theme/presentation/_cta.scss +111 -111
- package/theme/presentation/_effects.scss +216 -216
- package/theme/presentation/_features.scss +108 -108
- package/theme/presentation/_footer.scss +129 -129
- package/theme/presentation/_hero.scss +158 -158
- package/theme/presentation/_layout.scss +170 -170
- package/theme/presentation/_navbar.scss +140 -140
- package/theme/presentation/_pricing.scss +262 -262
- package/theme/presentation/_stats.scss +87 -87
- package/theme/presentation/_testimonials.scss +124 -124
- package/theme/presentation/_tokens.scss +39 -39
- package/theme/presentation/_typography.scss +163 -163
- package/web-types.json +12 -12
|
@@ -1,228 +1,228 @@
|
|
|
1
|
-
import { registerComponent, dispatch, dispatchCancelable } from '../../ln-core';
|
|
2
|
-
|
|
3
|
-
(function () {
|
|
4
|
-
'use strict';
|
|
5
|
-
|
|
6
|
-
const DOM_SELECTOR = 'data-ln-picklist';
|
|
7
|
-
const DOM_ATTRIBUTE = 'lnPicklist';
|
|
8
|
-
const LIST_ATTR = 'data-ln-picklist-list';
|
|
9
|
-
const MAX_ATTR = 'data-ln-picklist-max';
|
|
10
|
-
|
|
11
|
-
if (window[DOM_ATTRIBUTE] !== undefined) return;
|
|
12
|
-
|
|
13
|
-
// ─── Attribute Contract (SSOT) ──────────────────────────
|
|
14
|
-
const ATTRIBUTES = {
|
|
15
|
-
'data-ln-picklist': { type: 'enum', values: ['enabled', 'disabled'], fallback: 'enabled', effect: _syncEnabled, description: 'Controls enabled/disabled state of the dual-list picklist' },
|
|
16
|
-
'data-ln-picklist-max': { type: 'integer', fallback: Infinity, min: 1, effect: _syncMax, description: 'Maximum selectable items in the selected list' },
|
|
17
|
-
'data-ln-picklist-list': { type: 'enum', values: ['available', 'selected'], description: 'Role marker for available or selected picklist columns' }
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
// ─── Component ─────────────────────────────────────────────
|
|
21
|
-
//
|
|
22
|
-
// The checkbox IS the state. Its `checked` property and the list the item
|
|
23
|
-
// currently sits in are the same fact, and `name`/`value` carry the
|
|
24
|
-
// selection to the server natively — unchecked boxes are not submitted.
|
|
25
|
-
// Hence no hidden inputs, no state attribute and no JS mirror.
|
|
26
|
-
|
|
27
|
-
function _component(dom) {
|
|
28
|
-
this.dom = dom;
|
|
29
|
-
this.isEnabled = dom.getAttribute(DOM_SELECTOR) !== 'disabled';
|
|
30
|
-
this.max = _readMax(dom);
|
|
31
|
-
|
|
32
|
-
this.available = dom.querySelector('[' + LIST_ATTR + '="available"]');
|
|
33
|
-
this.selected = dom.querySelector('[' + LIST_ATTR + '="selected"]');
|
|
34
|
-
|
|
35
|
-
// Report the gap rather than failing on the first click.
|
|
36
|
-
if (!this.available || !this.selected) {
|
|
37
|
-
console.warn('[ln-picklist] requires both [' + LIST_ATTR + '="available"] and [' + LIST_ATTR + '="selected"]', dom);
|
|
38
|
-
return this;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Bound once so destroy() can detach the same reference.
|
|
42
|
-
this._onChange = this._onChange.bind(this);
|
|
43
|
-
dom.addEventListener('change', this._onChange);
|
|
44
|
-
|
|
45
|
-
// Snapshot the authored items in document order.
|
|
46
|
-
this._initial = [];
|
|
47
|
-
for (const list of [this.available, this.selected]) {
|
|
48
|
-
for (const item of list.children) {
|
|
49
|
-
this._initial.push(item);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Initial sync: transfer checked items to selected, unchecked to available.
|
|
54
|
-
this.sync();
|
|
55
|
-
|
|
56
|
-
this._form = dom.closest('form');
|
|
57
|
-
if (this._form) {
|
|
58
|
-
this._onFormReset = this._onFormReset.bind(this);
|
|
59
|
-
this._form.addEventListener('reset', this._onFormReset);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return this;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// ─── Lifecycle ─────────────────────────────────────────────
|
|
66
|
-
|
|
67
|
-
_component.prototype.destroy = function () {
|
|
68
|
-
if (!this.dom[DOM_ATTRIBUTE]) return;
|
|
69
|
-
this._destroyed = true;
|
|
70
|
-
if (this._onChange) this.dom.removeEventListener('change', this._onChange);
|
|
71
|
-
if (this._form) this._form.removeEventListener('reset', this._onFormReset);
|
|
72
|
-
delete this.dom[DOM_ATTRIBUTE];
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
// ─── Instance API ──────────────────────────────────────────
|
|
76
|
-
|
|
77
|
-
_component.prototype.enable = function () {
|
|
78
|
-
this.dom.setAttribute(DOM_SELECTOR, '');
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
_component.prototype.disable = function () {
|
|
82
|
-
this.dom.setAttribute(DOM_SELECTOR, 'disabled');
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
_component.prototype.sync = function () {
|
|
86
|
-
if (!this.available || !this.selected) return;
|
|
87
|
-
|
|
88
|
-
// Include any dynamically added items not yet tracked
|
|
89
|
-
const currentItems = Array.from(this.available.children).concat(Array.from(this.selected.children));
|
|
90
|
-
for (let i = 0; i < currentItems.length; i++) {
|
|
91
|
-
if (!this._initial.includes(currentItems[i])) {
|
|
92
|
-
this._initial.push(currentItems[i]);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
let selectedCount = 0;
|
|
97
|
-
for (let i = 0; i < this._initial.length; i++) {
|
|
98
|
-
const item = this._initial[i];
|
|
99
|
-
if (!item.isConnected) continue;
|
|
100
|
-
const checkbox = item.querySelector('input[type="checkbox"]');
|
|
101
|
-
if (!checkbox) continue;
|
|
102
|
-
|
|
103
|
-
let targetList;
|
|
104
|
-
if (checkbox.checked) {
|
|
105
|
-
if (this.max === null || selectedCount < this.max) {
|
|
106
|
-
targetList = this.selected;
|
|
107
|
-
selectedCount++;
|
|
108
|
-
} else {
|
|
109
|
-
checkbox.checked = false;
|
|
110
|
-
targetList = this.available;
|
|
111
|
-
}
|
|
112
|
-
} else {
|
|
113
|
-
targetList = this.available;
|
|
114
|
-
}
|
|
115
|
-
targetList.appendChild(item);
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
// ─── Form Reset ────────────────────────────────────────────
|
|
120
|
-
//
|
|
121
|
-
// Resetting a form restores every control to its default SILENTLY — the
|
|
122
|
-
// spec fires no `change` and no `input` for them, only `reset` on the form
|
|
123
|
-
// itself. Re-syncing in recorded order rebuilds both lists according to
|
|
124
|
-
// defaultChecked.
|
|
125
|
-
|
|
126
|
-
_component.prototype._onFormReset = function (e) {
|
|
127
|
-
const self = this;
|
|
128
|
-
|
|
129
|
-
// `reset` fires BEFORE the controls are restored, and it is cancelable,
|
|
130
|
-
// so the work is deferred and re-checked — the same shape ln-editor
|
|
131
|
-
// uses to re-read its textarea.
|
|
132
|
-
setTimeout(function () {
|
|
133
|
-
if (self._destroyed || e.defaultPrevented) return;
|
|
134
|
-
self.sync();
|
|
135
|
-
}, 0);
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
// ─── Change Handler ────────────────────────────────────────
|
|
139
|
-
|
|
140
|
-
_component.prototype._onChange = function (e) {
|
|
141
|
-
// `change` bubbles, so anything the author composes inside the root —
|
|
142
|
-
// an ln-search input, a select — reaches this listener. Filter hard.
|
|
143
|
-
const checkbox = e.target.closest('input[type="checkbox"]');
|
|
144
|
-
if (!checkbox) return;
|
|
145
|
-
|
|
146
|
-
const item = checkbox.closest('li');
|
|
147
|
-
if (!item) return;
|
|
148
|
-
|
|
149
|
-
const from = item.parentElement;
|
|
150
|
-
if (from !== this.available && from !== this.selected) return;
|
|
151
|
-
|
|
152
|
-
// The browser has already toggled the box by the time this runs, so a
|
|
153
|
-
// bare return would leave it checked while the item stays put — which
|
|
154
|
-
// is exactly the contradiction this component exists to avoid.
|
|
155
|
-
if (!this.isEnabled) {
|
|
156
|
-
checkbox.checked = !checkbox.checked;
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
const to = checkbox.checked ? this.selected : this.available;
|
|
161
|
-
|
|
162
|
-
// Inconsistent authored markup (a checked item rendered on the left),
|
|
163
|
-
// or a synthetic change that did not flip the box, would otherwise
|
|
164
|
-
// re-append in place and emit a move that never happened.
|
|
165
|
-
if (from === to) return;
|
|
166
|
-
|
|
167
|
-
// Enforce maximum selection limit if configured
|
|
168
|
-
if (to === this.selected && this.max !== null && this.selected.children.length >= this.max) {
|
|
169
|
-
checkbox.checked = !checkbox.checked;
|
|
170
|
-
dispatch(this.dom, 'ln-picklist:max-reached', {
|
|
171
|
-
max: this.max,
|
|
172
|
-
item: item,
|
|
173
|
-
checkbox: checkbox,
|
|
174
|
-
count: this.selected.children.length
|
|
175
|
-
});
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// One record, both events — they describe the same move.
|
|
180
|
-
const detail = { item: item, from: from, to: to, checkbox: checkbox };
|
|
181
|
-
|
|
182
|
-
if (dispatchCancelable(this.dom, 'ln-picklist:before-move', detail).defaultPrevented) {
|
|
183
|
-
checkbox.checked = !checkbox.checked;
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// Re-parenting a node that holds focus blurs it to <body> in Chromium.
|
|
188
|
-
// Only restore when the focus really was here: a synthetic change from
|
|
189
|
-
// a script must not steal focus away from whatever the user is using.
|
|
190
|
-
const hadFocus = document.activeElement === checkbox;
|
|
191
|
-
|
|
192
|
-
to.appendChild(item);
|
|
193
|
-
|
|
194
|
-
if (hadFocus) checkbox.focus();
|
|
195
|
-
|
|
196
|
-
dispatch(this.dom, 'ln-picklist:move', detail);
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
// ─── Attribute Sync ────────────────────────────────────────
|
|
200
|
-
|
|
201
|
-
function _readMax(el) {
|
|
202
|
-
const raw = el.getAttribute(MAX_ATTR);
|
|
203
|
-
if (raw === null || raw === '') return null;
|
|
204
|
-
const parsed = parseInt(raw, 10);
|
|
205
|
-
return isNaN(parsed) || parsed < 0 ? null : parsed;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
function _syncEnabled(el) {
|
|
209
|
-
const instance = el[DOM_ATTRIBUTE];
|
|
210
|
-
if (!instance) return;
|
|
211
|
-
const shouldBeEnabled = el.getAttribute(DOM_SELECTOR) !== 'disabled';
|
|
212
|
-
if (shouldBeEnabled === instance.isEnabled) return;
|
|
213
|
-
instance.isEnabled = shouldBeEnabled;
|
|
214
|
-
dispatch(el, shouldBeEnabled ? 'ln-picklist:enabled' : 'ln-picklist:disabled', { target: el });
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
function _syncMax(el) {
|
|
218
|
-
const instance = el[DOM_ATTRIBUTE];
|
|
219
|
-
if (!instance) return;
|
|
220
|
-
instance.max = _readMax(el);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// ─── Init ──────────────────────────────────────────────────
|
|
224
|
-
|
|
225
|
-
registerComponent(DOM_SELECTOR, DOM_ATTRIBUTE, _component, 'ln-picklist', {
|
|
226
|
-
attributes: ATTRIBUTES
|
|
227
|
-
});
|
|
228
|
-
})();
|
|
1
|
+
import { registerComponent, dispatch, dispatchCancelable } from '../../ln-core';
|
|
2
|
+
|
|
3
|
+
(function () {
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
const DOM_SELECTOR = 'data-ln-picklist';
|
|
7
|
+
const DOM_ATTRIBUTE = 'lnPicklist';
|
|
8
|
+
const LIST_ATTR = 'data-ln-picklist-list';
|
|
9
|
+
const MAX_ATTR = 'data-ln-picklist-max';
|
|
10
|
+
|
|
11
|
+
if (window[DOM_ATTRIBUTE] !== undefined) return;
|
|
12
|
+
|
|
13
|
+
// ─── Attribute Contract (SSOT) ──────────────────────────
|
|
14
|
+
const ATTRIBUTES = {
|
|
15
|
+
'data-ln-picklist': { type: 'enum', values: ['enabled', 'disabled'], fallback: 'enabled', effect: _syncEnabled, description: 'Controls enabled/disabled state of the dual-list picklist' },
|
|
16
|
+
'data-ln-picklist-max': { type: 'integer', fallback: Infinity, min: 1, effect: _syncMax, description: 'Maximum selectable items in the selected list' },
|
|
17
|
+
'data-ln-picklist-list': { type: 'enum', values: ['available', 'selected'], description: 'Role marker for available or selected picklist columns' }
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// ─── Component ─────────────────────────────────────────────
|
|
21
|
+
//
|
|
22
|
+
// The checkbox IS the state. Its `checked` property and the list the item
|
|
23
|
+
// currently sits in are the same fact, and `name`/`value` carry the
|
|
24
|
+
// selection to the server natively — unchecked boxes are not submitted.
|
|
25
|
+
// Hence no hidden inputs, no state attribute and no JS mirror.
|
|
26
|
+
|
|
27
|
+
function _component(dom) {
|
|
28
|
+
this.dom = dom;
|
|
29
|
+
this.isEnabled = dom.getAttribute(DOM_SELECTOR) !== 'disabled';
|
|
30
|
+
this.max = _readMax(dom);
|
|
31
|
+
|
|
32
|
+
this.available = dom.querySelector('[' + LIST_ATTR + '="available"]');
|
|
33
|
+
this.selected = dom.querySelector('[' + LIST_ATTR + '="selected"]');
|
|
34
|
+
|
|
35
|
+
// Report the gap rather than failing on the first click.
|
|
36
|
+
if (!this.available || !this.selected) {
|
|
37
|
+
console.warn('[ln-picklist] requires both [' + LIST_ATTR + '="available"] and [' + LIST_ATTR + '="selected"]', dom);
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Bound once so destroy() can detach the same reference.
|
|
42
|
+
this._onChange = this._onChange.bind(this);
|
|
43
|
+
dom.addEventListener('change', this._onChange);
|
|
44
|
+
|
|
45
|
+
// Snapshot the authored items in document order.
|
|
46
|
+
this._initial = [];
|
|
47
|
+
for (const list of [this.available, this.selected]) {
|
|
48
|
+
for (const item of list.children) {
|
|
49
|
+
this._initial.push(item);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Initial sync: transfer checked items to selected, unchecked to available.
|
|
54
|
+
this.sync();
|
|
55
|
+
|
|
56
|
+
this._form = dom.closest('form');
|
|
57
|
+
if (this._form) {
|
|
58
|
+
this._onFormReset = this._onFormReset.bind(this);
|
|
59
|
+
this._form.addEventListener('reset', this._onFormReset);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return this;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ─── Lifecycle ─────────────────────────────────────────────
|
|
66
|
+
|
|
67
|
+
_component.prototype.destroy = function () {
|
|
68
|
+
if (!this.dom[DOM_ATTRIBUTE]) return;
|
|
69
|
+
this._destroyed = true;
|
|
70
|
+
if (this._onChange) this.dom.removeEventListener('change', this._onChange);
|
|
71
|
+
if (this._form) this._form.removeEventListener('reset', this._onFormReset);
|
|
72
|
+
delete this.dom[DOM_ATTRIBUTE];
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// ─── Instance API ──────────────────────────────────────────
|
|
76
|
+
|
|
77
|
+
_component.prototype.enable = function () {
|
|
78
|
+
this.dom.setAttribute(DOM_SELECTOR, '');
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
_component.prototype.disable = function () {
|
|
82
|
+
this.dom.setAttribute(DOM_SELECTOR, 'disabled');
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
_component.prototype.sync = function () {
|
|
86
|
+
if (!this.available || !this.selected) return;
|
|
87
|
+
|
|
88
|
+
// Include any dynamically added items not yet tracked
|
|
89
|
+
const currentItems = Array.from(this.available.children).concat(Array.from(this.selected.children));
|
|
90
|
+
for (let i = 0; i < currentItems.length; i++) {
|
|
91
|
+
if (!this._initial.includes(currentItems[i])) {
|
|
92
|
+
this._initial.push(currentItems[i]);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
let selectedCount = 0;
|
|
97
|
+
for (let i = 0; i < this._initial.length; i++) {
|
|
98
|
+
const item = this._initial[i];
|
|
99
|
+
if (!item.isConnected) continue;
|
|
100
|
+
const checkbox = item.querySelector('input[type="checkbox"]');
|
|
101
|
+
if (!checkbox) continue;
|
|
102
|
+
|
|
103
|
+
let targetList;
|
|
104
|
+
if (checkbox.checked) {
|
|
105
|
+
if (this.max === null || selectedCount < this.max) {
|
|
106
|
+
targetList = this.selected;
|
|
107
|
+
selectedCount++;
|
|
108
|
+
} else {
|
|
109
|
+
checkbox.checked = false;
|
|
110
|
+
targetList = this.available;
|
|
111
|
+
}
|
|
112
|
+
} else {
|
|
113
|
+
targetList = this.available;
|
|
114
|
+
}
|
|
115
|
+
targetList.appendChild(item);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// ─── Form Reset ────────────────────────────────────────────
|
|
120
|
+
//
|
|
121
|
+
// Resetting a form restores every control to its default SILENTLY — the
|
|
122
|
+
// spec fires no `change` and no `input` for them, only `reset` on the form
|
|
123
|
+
// itself. Re-syncing in recorded order rebuilds both lists according to
|
|
124
|
+
// defaultChecked.
|
|
125
|
+
|
|
126
|
+
_component.prototype._onFormReset = function (e) {
|
|
127
|
+
const self = this;
|
|
128
|
+
|
|
129
|
+
// `reset` fires BEFORE the controls are restored, and it is cancelable,
|
|
130
|
+
// so the work is deferred and re-checked — the same shape ln-editor
|
|
131
|
+
// uses to re-read its textarea.
|
|
132
|
+
setTimeout(function () {
|
|
133
|
+
if (self._destroyed || e.defaultPrevented) return;
|
|
134
|
+
self.sync();
|
|
135
|
+
}, 0);
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// ─── Change Handler ────────────────────────────────────────
|
|
139
|
+
|
|
140
|
+
_component.prototype._onChange = function (e) {
|
|
141
|
+
// `change` bubbles, so anything the author composes inside the root —
|
|
142
|
+
// an ln-search input, a select — reaches this listener. Filter hard.
|
|
143
|
+
const checkbox = e.target.closest('input[type="checkbox"]');
|
|
144
|
+
if (!checkbox) return;
|
|
145
|
+
|
|
146
|
+
const item = checkbox.closest('li');
|
|
147
|
+
if (!item) return;
|
|
148
|
+
|
|
149
|
+
const from = item.parentElement;
|
|
150
|
+
if (from !== this.available && from !== this.selected) return;
|
|
151
|
+
|
|
152
|
+
// The browser has already toggled the box by the time this runs, so a
|
|
153
|
+
// bare return would leave it checked while the item stays put — which
|
|
154
|
+
// is exactly the contradiction this component exists to avoid.
|
|
155
|
+
if (!this.isEnabled) {
|
|
156
|
+
checkbox.checked = !checkbox.checked;
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const to = checkbox.checked ? this.selected : this.available;
|
|
161
|
+
|
|
162
|
+
// Inconsistent authored markup (a checked item rendered on the left),
|
|
163
|
+
// or a synthetic change that did not flip the box, would otherwise
|
|
164
|
+
// re-append in place and emit a move that never happened.
|
|
165
|
+
if (from === to) return;
|
|
166
|
+
|
|
167
|
+
// Enforce maximum selection limit if configured
|
|
168
|
+
if (to === this.selected && this.max !== null && this.selected.children.length >= this.max) {
|
|
169
|
+
checkbox.checked = !checkbox.checked;
|
|
170
|
+
dispatch(this.dom, 'ln-picklist:max-reached', {
|
|
171
|
+
max: this.max,
|
|
172
|
+
item: item,
|
|
173
|
+
checkbox: checkbox,
|
|
174
|
+
count: this.selected.children.length
|
|
175
|
+
});
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// One record, both events — they describe the same move.
|
|
180
|
+
const detail = { item: item, from: from, to: to, checkbox: checkbox };
|
|
181
|
+
|
|
182
|
+
if (dispatchCancelable(this.dom, 'ln-picklist:before-move', detail).defaultPrevented) {
|
|
183
|
+
checkbox.checked = !checkbox.checked;
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Re-parenting a node that holds focus blurs it to <body> in Chromium.
|
|
188
|
+
// Only restore when the focus really was here: a synthetic change from
|
|
189
|
+
// a script must not steal focus away from whatever the user is using.
|
|
190
|
+
const hadFocus = document.activeElement === checkbox;
|
|
191
|
+
|
|
192
|
+
to.appendChild(item);
|
|
193
|
+
|
|
194
|
+
if (hadFocus) checkbox.focus();
|
|
195
|
+
|
|
196
|
+
dispatch(this.dom, 'ln-picklist:move', detail);
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// ─── Attribute Sync ────────────────────────────────────────
|
|
200
|
+
|
|
201
|
+
function _readMax(el) {
|
|
202
|
+
const raw = el.getAttribute(MAX_ATTR);
|
|
203
|
+
if (raw === null || raw === '') return null;
|
|
204
|
+
const parsed = parseInt(raw, 10);
|
|
205
|
+
return isNaN(parsed) || parsed < 0 ? null : parsed;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function _syncEnabled(el) {
|
|
209
|
+
const instance = el[DOM_ATTRIBUTE];
|
|
210
|
+
if (!instance) return;
|
|
211
|
+
const shouldBeEnabled = el.getAttribute(DOM_SELECTOR) !== 'disabled';
|
|
212
|
+
if (shouldBeEnabled === instance.isEnabled) return;
|
|
213
|
+
instance.isEnabled = shouldBeEnabled;
|
|
214
|
+
dispatch(el, shouldBeEnabled ? 'ln-picklist:enabled' : 'ln-picklist:disabled', { target: el });
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function _syncMax(el) {
|
|
218
|
+
const instance = el[DOM_ATTRIBUTE];
|
|
219
|
+
if (!instance) return;
|
|
220
|
+
instance.max = _readMax(el);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// ─── Init ──────────────────────────────────────────────────
|
|
224
|
+
|
|
225
|
+
registerComponent(DOM_SELECTOR, DOM_ATTRIBUTE, _component, 'ln-picklist', {
|
|
226
|
+
attributes: ATTRIBUTES
|
|
227
|
+
});
|
|
228
|
+
})();
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
@use '../../theme/config/mixins' as *;
|
|
2
|
-
|
|
3
|
-
[data-ln-debug] {
|
|
4
|
-
// 1. Popover Missing ID: popovers controlled by data-ln-popover must have an id for trigger linking
|
|
5
|
-
[data-ln-popover]:not([id]) {
|
|
6
|
-
@include dev-dom-error("[data-ln-popover] is missing a required 'id' attribute for trigger linking.");
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
// 2. Popover Trigger Empty ID: trigger elements must point to a target popover ID
|
|
10
|
-
[data-ln-popover-for=""] {
|
|
11
|
-
@include dev-inline-error("data-ln-popover-for target ID cannot be empty");
|
|
12
|
-
}
|
|
13
|
-
}
|
|
1
|
+
@use '../../theme/config/mixins' as *;
|
|
2
|
+
|
|
3
|
+
[data-ln-debug] {
|
|
4
|
+
// 1. Popover Missing ID: popovers controlled by data-ln-popover must have an id for trigger linking
|
|
5
|
+
[data-ln-popover]:not([id]) {
|
|
6
|
+
@include dev-dom-error("[data-ln-popover] is missing a required 'id' attribute for trigger linking.");
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// 2. Popover Trigger Empty ID: trigger elements must point to a target popover ID
|
|
10
|
+
[data-ln-popover-for=""] {
|
|
11
|
+
@include dev-inline-error("data-ln-popover-for target ID cannot be empty");
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(){"use strict";function D(){return typeof window>"u"?!1:window.lnDebug===!0||window.lnCore&&window.lnCore._debugSink?!0:typeof document<"u"&&document.body?document.body.hasAttribute("data-ln-debug")||document.body.querySelector("[data-ln-debug]")!==null:!1}function k(e){if(typeof window>"u")return!1;if(window.lnDebug===!0)return!0;if(window.lnCore&&window.lnCore._debugIsContained)return e?window.lnCore._debugIsContained(e):window.lnCore._debugSink!==null;if(e&&e.closest){const t=e.closest("[data-ln-debug]");return!(!t||typeof document<"u"&&t===document.documentElement)}return typeof document<"u"&&document.body?document.body.hasAttribute("data-ln-debug"):!1}if(typeof window<"u"&&(window.lnCore=window.lnCore||{},!window.lnCore._warnBound)){window.lnCore._warnBound=!0;const e=console.warn;console.warn=function(...t){if(typeof t[0]=="string"&&(t[0].startsWith("[ln-")||t[0].startsWith("[lnCore"))){let o=null;for(let s=1;s<t.length;s++)if(t[s]&&t[s].nodeType===1){o=t[s];break}if(!k(o))return}e.apply(console,t)}}function O(e,t,n){const o=n||{};window.lnCore._debugSink&&window.lnCore._debugSink("event",t,e,o),e.dispatchEvent(new CustomEvent(t,{bubbles:!0,detail:o}))}function R(e,t,n){const o=n||{};window.lnCore._debugSink&&window.lnCore._debugSink("event",t,e,o);const s=new CustomEvent(t,{bubbles:!0,cancelable:!0,detail:o});return e.dispatchEvent(s),s}function A(e,t){if(!document.body){document.addEventListener("DOMContentLoaded",function(){A(e,t)}),console.warn("["+t+'] Script loaded before <body> — add "defer" to your <script> tag');return}e()}function U(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)}const I={};function Q(e,t){I[e]=t}function G(e){return I[e]||{ingress:t=>t,egress:t=>t}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerDataMapper=Q,window.lnCore.getDataMapper=G);function z(){typeof window>"u"||(window.lnCore=window.lnCore||{},!window.lnCore._localeObserverBound&&(window.lnCore._localeObserverBound=!0,A(function(){new MutationObserver(function(){O(document,"ln-core:locale-change",{})}).observe(document.documentElement,{attributes:!0,attributeFilter:["lang"],subtree:!0})},"ln-core")))}const $={};function J(e,t){if(!e||typeof t!="object")return;const n=e.toLowerCase().split("-")[0];$[n]=t}function X(e){if(!e)return null;const t=e.toLowerCase().split("-")[0];return $[t]||null}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerLocaleFallback=J,window.lnCore.getLocaleFallback=X,window.lnCore.ensureLocaleObserver=z);const E={};function Y(e,t){E[e]||(E[e]=document.querySelector('[data-ln-template="'+e+'"]'));const n=E[e];return n?n.content.cloneNode(!0):(console.warn("["+(t||"ln-core")+'] Template "'+e+'" not found'),null)}function F(e,t){if(!e||!t)return e;const n=e.querySelectorAll("[data-ln-field]");for(let r=0;r<n.length;r++){const u=n[r],l=u.getAttribute("data-ln-field");t[l]!=null&&(u.textContent=t[l])}const o=e.querySelectorAll("[data-ln-attr]");for(let r=0;r<o.length;r++){const u=o[r],l=u.getAttribute("data-ln-attr").split(",");for(let d=0;d<l.length;d++){const h=l[d].trim().split(":");if(h.length!==2)continue;const f=h[0].trim(),c=h[1].trim();t[c]!=null&&u.setAttribute(f,t[c])}}const s=e.querySelectorAll("[data-ln-show]");for(let r=0;r<s.length;r++){const u=s[r],l=u.getAttribute("data-ln-show");l in t&&u.classList.toggle("hidden",!t[l])}const i=e.querySelectorAll("[data-ln-class]");for(let r=0;r<i.length;r++){const u=i[r],l=u.getAttribute("data-ln-class").split(",");for(let d=0;d<l.length;d++){const h=l[d].trim().split(":");if(h.length!==2)continue;const f=h[0].trim(),c=h[1].trim();c in t&&u.classList.toggle(f,!!t[c])}}return e}function Z(e,t){e.matches&&e.matches("[data-ln-form], [data-ln-fillable]")&&(window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",e,t??null),e.dispatchEvent(new CustomEvent("ln-fill",{detail:t??null,bubbles:!0})));const n=e.querySelectorAll("[data-ln-form], [data-ln-fillable]");for(let o=0;o<n.length;o++)window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",n[o],t??null),n[o].dispatchEvent(new CustomEvent("ln-fill",{detail:t??null,bubbles:!0}));return e}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._fillBound||(window.lnCore._fillBound=!0,document.addEventListener("ln-fill",function(e){if(!(!e.target.matches||!e.target.matches("[data-ln-fillable]")))if(e.detail)F(e.target,e.detail);else{const t=e.target.querySelectorAll("[data-ln-field]");for(let n=0;n<t.length;n++)t[n].textContent=""}})));function B(e,t){if(!e||!t)return e;const n=document.createTreeWalker(e,NodeFilter.SHOW_TEXT);for(;n.nextNode();){const i=n.currentNode;i.textContent.indexOf("{{")!==-1&&(i.textContent=i.textContent.replace(/\{\{\s*(\w+)\s*\}\}/g,function(r,u){return t[u]!==void 0?t[u]:""}))}const o=function(i,r){return t[r]!==void 0?t[r]:""},s=Array.from(e.querySelectorAll("*"));e.nodeType===1&&s.push(e);for(let i=0;i<s.length;i++){const r=s[i],u=r.attributes;for(let l=0;l<u.length;l++){const d=u[l];d.value.indexOf("{{")!==-1&&r.setAttribute(d.name,d.value.replace(/\{\{\s*(\w+)\s*\}\}/g,o))}}return e}function ee(e,t,n,o,s,i){const r={};for(let l=0;l<e.children.length;l++){const d=e.children[l],h=d.getAttribute("data-ln-render-key");h&&(r[h]=d)}const u=document.createDocumentFragment();for(let l=0;l<t.length;l++){const d=t[l],h=String(o(d));let f=r[h];if(f)s(f,d,l);else{const c=Y(n,i);if(!c||(B(c,d),f=c.firstElementChild,!f))continue;f.setAttribute("data-ln-render-key",h),s(f,d,l)}u.appendChild(f)}e.textContent="",e.appendChild(u)}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.fillTemplate=B,window.lnCore.fill=F,window.lnCore.lnFill=Z,window.lnCore.renderList=ee);function M(e,t,n,o,s){if(!e||t===null)return!0;const i=o||"ln-component",r=e.type;if(r==="trigger"||r==="marker"||r==="string"||r==="list"||!r||t===""&&e.fallback!==void 0)return!0;const u=l=>{s?console.warn(l,s):console.warn(l)};if(r==="boolean"){const l=t.trim().toLowerCase();return l!==""&&l!=="true"&&l!=="false"&&l!=="1"&&l!=="0"?(u(`[${i}] Invalid value "${t}" for boolean attribute "${n}". Allowed: "true", "false", or presence-only.`),!1):!0}if(r==="enum"){const l=e.values||[];return l.includes(t)?!0:(u(`[${i}] Invalid value "${t}" for attribute "${n}". Allowed: ${l.join(", ")}. Fallback: "${e.fallback}".`),!1)}if(r==="integer"){if(!/^-?\d+$/.test(t))return u(`[${i}] Invalid integer "${t}" for attribute "${n}". Fallback: ${e.fallback}.`),!1;const l=parseInt(t,10);return e.min!==void 0&&l<e.min?(u(`[${i}] Value ${l} for attribute "${n}" is less than min (${e.min}).`),!1):e.max!==void 0&&l>e.max?(u(`[${i}] Value ${l} for attribute "${n}" is greater than max (${e.max}).`),!1):!0}if(r==="float")return isNaN(Number(t))?(u(`[${i}] Invalid float "${t}" for attribute "${n}". Fallback: ${e.fallback}.`),!1):!0;if(r==="json")try{return JSON.parse(t),!0}catch(l){return u(`[${i}] Invalid JSON for attribute "${n}": ${l.message}. Fallback: ${e.fallback}.`),!1}return!0}function te(e){const t={};for(const n in e){const o=e[n];o&&o.effect&&(t[n]=o.effect)}return Object.keys(t).length?t:null}function ne(e){if(e.onAttrChange&&!e.declared)return null;const t=new Set;if(e.effects)for(const n in e.effects)t.add(n);if(e.onAttrChange&&e.declared)for(const n of e.declared)t.add(n);return t}function S(e,t,n,o){if(e.nodeType!==1)return;const i=t.indexOf("[")!==-1||t.indexOf(".")!==-1||t.indexOf("#")!==-1?t:"["+t+"]",r=Array.from(e.querySelectorAll(i));e.matches&&e.matches(i)&&r.push(e);for(const u of r)if(!u[n]){window.lnCore._persistSink&&u.hasAttribute("data-ln-persist")&&window.lnCore._persistSink(u,t);try{u[n]=new o(u)}catch(l){console.error("["+n+"] init failed",u,l)}}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._bootHolds=window.lnCore._bootHolds||0,window.lnCore._bootQueue=window.lnCore._bootQueue||[]);function oe(){return typeof window<"u"&&window.lnCore&&window.lnCore._bootHolds||0}function ie(e){typeof window<"u"?(window.lnCore=window.lnCore||{},window.lnCore._bootHolds=window.lnCore._bootHolds||0,window.lnCore._bootQueue=window.lnCore._bootQueue||[],window.lnCore._bootHolds>0?window.lnCore._bootQueue.push(e):setTimeout(e,0)):e()}function W(){window.lnCore=window.lnCore||{};const e=window.lnCore._attrRegistry=window.lnCore._attrRegistry||{byAttr:new Map,reactive:[],persist:[]};return e.byReactive=e.byReactive||new Map,e.reactiveWildcard=e.reactiveWildcard||[],e}function re(e){const t=W(),n=e.observed||[];for(let o=0;o<n.length;o++){const s=n[o];t.byAttr.has(s)||t.byAttr.set(s,[]),t.byAttr.get(s).push(e)}if(t.byDeclaredAttr=t.byDeclaredAttr||new Map,e.attributes)for(const o in e.attributes){t.byDeclaredAttr.has(o)||t.byDeclaredAttr.set(o,[]);const s=t.byDeclaredAttr.get(o);s.some(i=>i.componentTag===e.componentTag)||s.push({spec:e.attributes[o],componentTag:e.componentTag})}if(e.onAttrChange||e.effects){t.reactive.push(e);const o=ne(e);if(o===null)t.reactiveWildcard.push(e);else for(const s of o)t.byReactive.has(s)||t.byReactive.set(s,[]),t.byReactive.get(s).push(e)}e.persist&&t.persist.push(e)}function N(e,t,n,o){for(let s=0;s<e.length;s++){const i=e[s];if(!t[i.attribute])continue;const r=i.effects&&i.effects[n];r?r(t,n,o):i.onAttrChange&&(!i.declared||i.declared.has(n))&&i.onAttrChange(t,n,o)}}function se(e){const t=e.target,n=e.attributeName;if(e.oldValue===t.getAttribute(n))return;const o=W(),s=o.byAttr.get(n);if(D()&&o.byDeclaredAttr&&o.byDeclaredAttr.has(n)&&k(t)){const i=o.byDeclaredAttr.get(n),r=t.getAttribute(n);for(let u=0;u<i.length;u++)M(i[u].spec,r,n,i[u].componentTag,t)}if(window.lnCore._debugSink&&(n.indexOf("data-ln-")===0||s)&&window.lnCore._debugSink("attr",n,t,{oldValue:e.oldValue,newValue:t.getAttribute(n)}),n.indexOf("data-ln-")===0){const i=o.byReactive.get(n);i&&N(i,t,n,e.oldValue),o.reactiveWildcard.length&&N(o.reactiveWildcard,t,n,e.oldValue)}if(s)for(let i=0;i<s.length;i++){const r=s[i];if(r.handler){r.handler(t,n,e.oldValue);continue}r.onAttributeChange&&t[r.attribute]?r.onAttributeChange(t,n):(S(t,r.selector,r.attribute,r.ComponentFn),r.onInit&&r.onInit(t))}}function le(){window.lnCore=window.lnCore||{},!window.lnCore._attrObserverBound&&(window.lnCore._attrObserverBound=!0,A(function(){new MutationObserver(function(t){for(let n=0;n<t.length;n++)try{se(t[n])}catch(o){console.error("[ln-core] mutation handler failed",t[n].target,o)}}).observe(document.body,{attributes:!0,subtree:!0,attributeOldValue:!0})},"ln-core"))}function j(){return window.lnCore=window.lnCore||{},window.lnCore._lifecycleRegistry=window.lnCore._lifecycleRegistry||[]}function ue(e){const t=j();if(t.length){if(e.target)for(let n=0;n<t.length;n++){const o=t[n];if(o.onSubtreeChange){const s=o.query,i=e.target.nodeType===1?e.target.matches(s)?e.target:e.target.closest(s):e.target.parentElement?e.target.parentElement.closest(s):null;i&&o.onSubtreeChange(i,e)}}for(let n=0;n<e.addedNodes.length;n++){const o=e.addedNodes[n];if(o.nodeType===1)for(let s=0;s<t.length;s++){const i=t[s];S(o,i.selector,i.attribute,i.ComponentFn),i.onInit&&i.onInit(o)}}for(let n=0;n<e.removedNodes.length;n++){const o=e.removedNodes[n];if(o.nodeType===1)for(let s=0;s<t.length;s++){const i=t[s],r=i.query,u=Array.from(o.querySelectorAll(r));o.matches&&o.matches(r)&&u.push(o);for(let l=0;l<u.length;l++){const d=u[l];if(!document.contains(d)){const h=d[i.attribute];if(h&&typeof h.destroy=="function")try{h.destroy()}catch(f){console.error("["+i.attribute+"] destroy failed",d,f)}delete d[i.attribute]}}}}}}function ce(){window.lnCore=window.lnCore||{},!window.lnCore._lifecycleObserverBound&&(window.lnCore._lifecycleObserverBound=!0,A(function(){new MutationObserver(function(t){for(let n=0;n<t.length;n++){const o=t[n];if(o.type==="childList")try{ue(o)}catch(s){console.error("[ln-core] lifecycle handler failed",o.target,s)}}}).observe(document.body,{childList:!0,subtree:!0})},"ln-core"))}function H(e,t,n,o,s={}){const i=s.extraAttributes||[],r=s.onAttributeChange||null,u=s.onSubtreeChange||null,l=s.onInit||null,d=s.onAttrChange||null,h=s.effects||null,f=s.attributes||null,c=f?te(f):h,p=f?new Set(Object.keys(f)):null,g=s.persist||null;function w(m){const C=m||document.body;if(S(C,e,t,n),f&&D())for(const _ in f){const me=f[_],x=Array.from(C.querySelectorAll("["+_+"]"));C.matches&&C.matches("["+_+"]")&&x.push(C);for(let T=0;T<x.length;T++){const q=x[T];k(q)&&M(me,q.getAttribute(_),_,o,q)}}l&&l(C)}const a=[];if(e.indexOf("[")!==-1){const m=/\[([\w-]+)/g;let C;for(;(C=m.exec(e))!==null;)a.push(C[1])}else a.push(e);re({selector:e,attribute:t,componentTag:o,attributes:f,ComponentFn:n,onInit:l,observed:a.concat(i),onAttributeChange:r,onAttrChange:d,effects:c,declared:p,persist:g}),le();const v=e.indexOf("[")!==-1||e.indexOf(".")!==-1||e.indexOf("#")!==-1?e:"["+e+"]";j().push({selector:e,attribute:t,ComponentFn:n,onInit:l,onSubtreeChange:u,query:v}),ce(),window[t]=w;function b(){oe()>0?ie(function(){w(document.body)}):w(document.body)}return document.readyState==="loading"?document.addEventListener("DOMContentLoaded",b):b(),w}function P(e){return(e||"").replace(/^#/,"")}function L(e){const t=e===void 0?location.hash:e,n={},o=P(t);if(!o)return n;const s=o.split("&");for(let i=0;i<s.length;i++){const r=s[i];if(!r)continue;const u=r.indexOf(":"),l=u>-1?r.slice(0,u):r,d=u>-1?r.slice(u+1):"";if(l)try{n[l]=decodeURIComponent(d)}catch{n[l]=d}}return n}function de(e){if(!e)return null;const t=L();return e in t?t[e]:null}function fe(e,t){if(!e)return;const n=L();t==null?delete n[e]:n[e]=String(t);const s=Object.keys(n).map(function(i){const r=n[i];return r===""?i:i+":"+encodeURIComponent(r)}).join("&");P(location.hash)!==s&&(location.hash=s)}function ae(e){return e.button===1||e.ctrlKey||e.metaKey||e.shiftKey?!1:(e.preventDefault(),!0)}function pe(e,t){if(!e||!e.hasAttribute("data-ln-hash"))return null;const n=e.getAttribute("data-ln-hash");if(n&&n.trim()!=="")return n.trim();const o=e.getAttribute("data-ln-sort")||e.getAttribute("data-ln-search-for")||e.getAttribute("data-ln-search")||e.getAttribute("data-ln-filter")||e.id;return o?t?o+"-"+t:o:t||null}function he(e,t){return!t||t==="none"||e===null||e===void 0?null:String(e)+"."+t}function ge(e){return!e||typeof e!="string"?null:e.endsWith(".asc")?{fieldOrColumn:e.slice(0,-4),direction:"asc"}:e.endsWith(".desc")?{fieldOrColumn:e.slice(0,-5),direction:"desc"}:null}function be(e,t){return!e||!Array.isArray(t)||t.length===0?null:e+":"+t.map(encodeURIComponent).join(",")}function we(e){if(!e||typeof e!="string")return null;const t=e.indexOf(":");if(t===-1)return null;const n=e.slice(0,t),o=e.slice(t+1),s=o?o.split(",").map(function(i){try{return decodeURIComponent(i)}catch{return i}}).filter(Boolean):[];return{key:n,values:s}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.hashParse=L,window.lnCore.hashGet=de,window.lnCore.hashSet=fe,window.lnCore.hashLinkClick=ae,window.lnCore.resolveHashNamespace=pe,window.lnCore.hashSortEncode=he,window.lnCore.hashSortDecode=ge,window.lnCore.hashFilterEncode=be,window.lnCore.hashFilterDecode=we);function V(e,t,n,o){const s=o,i=window.innerWidth,r=window.innerHeight,u=t.width,l=t.height,d=(n||"bottom").split("-"),h=d[0],f=d[1]==="start"||d[1]==="end"?d[1]:"center",c={top:["top","bottom","right","left"],bottom:["bottom","top","right","left"],left:["left","right","top","bottom"],right:["right","left","top","bottom"]},p=c[h]||c.bottom;function g(b){return b==="top"||b==="bottom"?f==="start"?e.left:f==="end"?e.right-u:e.left+(e.width-u)/2:f==="start"?e.top:f==="end"?e.bottom-l:e.top+(e.height-l)/2}function w(b){let m,C,_=!0;return b==="top"?(m=e.top-s-l,C=g(b),m<0&&(_=!1)):b==="bottom"?(m=e.bottom+s,C=g(b),m+l>r&&(_=!1)):b==="left"?(m=g(b),C=e.left-s-u,C<0&&(_=!1)):(m=g(b),C=e.right+s,C+u>i&&(_=!1)),{top:m,left:C,side:b,fits:_}}let a=null;for(let b=0;b<p.length;b++){const m=w(p[b]);if(m.fits){a=m;break}}a||(a=w(p[0]));let y=a.top,v=a.left;return u>=i?v=0:(v<0&&(v=0),v+u>i&&(v=i-u)),l>=r?y=0:(y<0&&(y=0),y+l>r&&(y=r-l)),{top:y,left:v,placement:a.side}}function K(e){if(!e)return{width:0,height:0};const t=e.style,n=t.visibility,o=t.display,s=t.position;t.visibility="hidden",t.display="block",t.position="fixed";const i=e.offsetWidth,r=e.offsetHeight;return t.visibility=n,t.display=o,t.position=s,{width:i,height:r}}(function(){const e="data-ln-popover",t="lnPopover",n="data-ln-popover-for",o="data-ln-popover-position";if(window[t]!==void 0)return;const s={"data-ln-popover":{type:"enum",values:["open","close"],fallback:"close",effect:f,description:"Control state of the popover"},"data-ln-popover-for":{type:"string",description:"Target element ID that this trigger controls"},"data-ln-popover-position":{type:"enum",values:["top","top-start","top-end","bottom","bottom-start","bottom-end","left","left-start","left-end","right","right-start","right-end"],fallback:"bottom",description:"Preferred positioning anchor"},"data-ln-popover-placement":{type:"enum",values:["top","top-start","top-end","bottom","bottom-start","bottom-end","left","left-start","left-end","right","right-start","right-end"],description:"Active calculated placement applied at runtime"}},i=[];let r=null;function u(){r||(r=function(c){if(c.key!=="Escape"||i.length===0)return;i[i.length-1].close()},document.addEventListener("keydown",r))}function l(){i.length>0||r&&(document.removeEventListener("keydown",r),r=null)}function d(c){this.dom=c,this.isOpen=c.getAttribute(e)==="open",this.trigger=null,this._previousFocus=null,this._boundDocClick=null,this._docClickTimeout=null,this._boundReposition=null;const p=this;return this._onRequestOpen=function(g){const w=g.detail&&g.detail.trigger?g.detail.trigger:null;p.open(w)},this._onRequestClose=function(){p.close()},this._onRequestToggle=function(g){const w=g.detail&&g.detail.trigger?g.detail.trigger:null;p.toggle(w)},this._onNativeToggle=function(g){g.newState==="closed"&&p.isOpen&&(p._applyClose(),p.dom.setAttribute(e,"closed"))},c.addEventListener("ln-popover:request-open",this._onRequestOpen),c.addEventListener("ln-popover:request-close",this._onRequestClose),c.addEventListener("ln-popover:request-toggle",this._onRequestToggle),c.addEventListener("toggle",this._onNativeToggle),c.hasAttribute("tabindex")||c.setAttribute("tabindex","-1"),c.hasAttribute("role")||c.setAttribute("role","dialog"),c.hasAttribute("popover")||c.setAttribute("popover","manual"),this.isOpen&&this._applyOpen(null),this}d.prototype.open=function(c){this.isOpen||(this.trigger=c||null,this.dom.setAttribute(e,"open"))},d.prototype.close=function(){this.isOpen&&this.dom.setAttribute(e,"closed")},d.prototype.toggle=function(c){this.isOpen?this.close():this.open(c)},d.prototype._applyOpen=function(c){this.isOpen=!0,c&&(this.trigger=c),this._previousFocus=document.activeElement,typeof this.dom.showPopover=="function"&&this.dom.showPopover();const p=K(this.dom);if(this.trigger){const y=this.trigger.getBoundingClientRect(),v=this.dom.getAttribute(o)||"bottom",b=V(y,p,v,8);this.dom.style.top=b.top+"px",this.dom.style.left=b.left+"px",this.dom.setAttribute("data-ln-popover-placement",b.placement),this.trigger.setAttribute("aria-expanded","true")}const g=this.dom.querySelectorAll('a[href], button:not([disabled]), input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'),w=Array.prototype.find.call(g,U);w?w.focus():this.dom.focus();const a=this;this._boundDocClick=function(y){a.dom.contains(y.target)||a.trigger&&a.trigger.contains(y.target)||a.close()},a._docClickTimeout=setTimeout(function(){a._docClickTimeout=null,document.addEventListener("click",a._boundDocClick)},0),this._boundReposition=function(){if(!a.trigger)return;const y=a.trigger.getBoundingClientRect(),v=K(a.dom),b=a.dom.getAttribute(o)||"bottom",m=V(y,v,b,8);a.dom.style.top=m.top+"px",a.dom.style.left=m.left+"px",a.dom.setAttribute("data-ln-popover-placement",m.placement)},window.addEventListener("scroll",this._boundReposition,{passive:!0,capture:!0}),window.addEventListener("resize",this._boundReposition),i.push(this),u(),O(this.dom,"ln-popover:open",{popoverId:this.dom.id,target:this.dom,trigger:this.trigger})},d.prototype._applyClose=function(){this.isOpen=!1,this._docClickTimeout&&(clearTimeout(this._docClickTimeout),this._docClickTimeout=null),this._boundDocClick&&(document.removeEventListener("click",this._boundDocClick),this._boundDocClick=null),this._boundReposition&&(window.removeEventListener("scroll",this._boundReposition,{capture:!0}),window.removeEventListener("resize",this._boundReposition),this._boundReposition=null),this.dom.style.top="",this.dom.style.left="",this.dom.removeAttribute("data-ln-popover-placement"),this.trigger&&this.trigger.setAttribute("aria-expanded","false"),typeof this.dom.hidePopover=="function"&&this.dom.matches(":popover-open")&&this.dom.hidePopover();const c=i.indexOf(this);c!==-1&&i.splice(c,1),l(),this._previousFocus&&this.trigger&&this._previousFocus===this.trigger?this.trigger.focus():this.trigger&&document.activeElement===document.body&&this.trigger.focus(),this._previousFocus=null,O(this.dom,"ln-popover:close",{popoverId:this.dom.id,target:this.dom,trigger:this.trigger}),this.trigger=null},d.prototype.destroy=function(){this.dom[t]&&(this.dom.removeEventListener("ln-popover:request-open",this._onRequestOpen),this.dom.removeEventListener("ln-popover:request-close",this._onRequestClose),this.dom.removeEventListener("ln-popover:request-toggle",this._onRequestToggle),this.dom.removeEventListener("toggle",this._onNativeToggle),this.isOpen&&this._applyClose(),delete this.dom[t])};function h(c){this.dom=c;const p=c.getAttribute(n);return c.setAttribute("aria-haspopup","dialog"),c.setAttribute("aria-expanded","false"),c.setAttribute("aria-controls",p),this._onClick=function(g){if(g.ctrlKey||g.metaKey||g.button===1)return;g.preventDefault();const w=document.getElementById(p);if(!w)return;w[t]&&(w[t].trigger=c);const a=w.getAttribute(e);w.setAttribute(e,a==="open"?"closed":"open")},c.addEventListener("click",this._onClick),this}h.prototype.destroy=function(){this.dom.removeEventListener("click",this._onClick),delete this.dom[t+"Trigger"]};function f(c){const p=c[t];if(!p)return;const w=c.getAttribute(e)==="open";if(w!==p.isOpen)if(w){if(R(c,"ln-popover:before-open",{popoverId:c.id,target:c,trigger:p.trigger}).defaultPrevented){c.setAttribute(e,"closed");return}p._applyOpen(p.trigger)}else{if(R(c,"ln-popover:before-close",{popoverId:c.id,target:c,trigger:p.trigger}).defaultPrevented){c.setAttribute(e,"open");return}p._applyClose()}}H(e,t,d,"ln-popover",{attributes:s}),H(n,t+"Trigger",h,"ln-popover-trigger")})()})();
|
|
1
|
+
(function(){"use strict";function q(){return typeof window>"u"?!1:window.lnDebug===!0||window.lnCore&&window.lnCore._debugSink?!0:typeof document<"u"&&document.body?document.body.hasAttribute("data-ln-debug")||document.body.querySelector("[data-ln-debug]")!==null:!1}function x(e){if(typeof window>"u")return!1;if(window.lnDebug===!0)return!0;if(window.lnCore&&window.lnCore._debugIsContained)return e?window.lnCore._debugIsContained(e):window.lnCore._debugSink!==null;if(e&&e.closest){const t=e.closest("[data-ln-debug]");return!(!t||typeof document<"u"&&t===document.documentElement)}return typeof document<"u"&&document.body?document.body.hasAttribute("data-ln-debug"):!1}if(typeof window<"u"&&(window.lnCore=window.lnCore||{},!window.lnCore._warnBound)){window.lnCore._warnBound=!0;const e=console.warn;console.warn=function(...t){if(typeof t[0]=="string"&&(t[0].startsWith("[ln-")||t[0].startsWith("[lnCore"))){let o=null;for(let s=1;s<t.length;s++)if(t[s]&&t[s].nodeType===1){o=t[s];break}if(!x(o))return}e.apply(console,t)}}function k(e,t,n){const o=n||{};window.lnCore._debugSink&&window.lnCore._debugSink("event",t,e,o),e.dispatchEvent(new CustomEvent(t,{bubbles:!0,detail:o}))}function I(e,t,n){const o=n||{};window.lnCore._debugSink&&window.lnCore._debugSink("event",t,e,o);const s=new CustomEvent(t,{bubbles:!0,cancelable:!0,detail:o});return e.dispatchEvent(s),s}function A(e,t){if(!document.body){document.addEventListener("DOMContentLoaded",function(){A(e,t)}),console.warn("["+t+'] Script loaded before <body> — add "defer" to your <script> tag');return}e()}function K(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)}const R={};function Q(e,t){R[e]=t}function G(e){return R[e]||{ingress:t=>t,egress:t=>t}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerDataMapper=Q,window.lnCore.getDataMapper=G);function z(){typeof window>"u"||(window.lnCore=window.lnCore||{},!window.lnCore._localeObserverBound&&(window.lnCore._localeObserverBound=!0,A(function(){new MutationObserver(function(){k(document,"ln-core:locale-change",{})}).observe(document.documentElement,{attributes:!0,attributeFilter:["lang"],subtree:!0})},"ln-core")))}const $={};function J(e,t){if(!e||typeof t!="object")return;const n=e.toLowerCase().split("-")[0];$[n]=t}function X(e){if(!e)return null;const t=e.toLowerCase().split("-")[0];return $[t]||null}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.registerLocaleFallback=J,window.lnCore.getLocaleFallback=X,window.lnCore.ensureLocaleObserver=z);const O={};function Y(e,t){O[e]||(O[e]=document.querySelector('[data-ln-template="'+e+'"]'));const n=O[e];return n?n.content.cloneNode(!0):(console.warn("["+(t||"ln-core")+'] Template "'+e+'" not found'),null)}function F(e,t){if(!e||!t)return e;const n=e.querySelectorAll("[data-ln-field]");for(let r=0;r<n.length;r++){const u=n[r],l=u.getAttribute("data-ln-field");t[l]!=null&&(u.textContent=t[l])}const o=e.querySelectorAll("[data-ln-attr]");for(let r=0;r<o.length;r++){const u=o[r],l=u.getAttribute("data-ln-attr").split(",");for(let d=0;d<l.length;d++){const h=l[d].trim().split(":");if(h.length!==2)continue;const f=h[0].trim(),c=h[1].trim();t[c]!=null&&u.setAttribute(f,t[c])}}const s=e.querySelectorAll("[data-ln-show]");for(let r=0;r<s.length;r++){const u=s[r],l=u.getAttribute("data-ln-show");l in t&&u.classList.toggle("hidden",!t[l])}const i=e.querySelectorAll("[data-ln-class]");for(let r=0;r<i.length;r++){const u=i[r],l=u.getAttribute("data-ln-class").split(",");for(let d=0;d<l.length;d++){const h=l[d].trim().split(":");if(h.length!==2)continue;const f=h[0].trim(),c=h[1].trim();c in t&&u.classList.toggle(f,!!t[c])}}return e}function Z(e,t){e.matches&&e.matches("[data-ln-form], [data-ln-fillable]")&&(window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",e,t??null),e.dispatchEvent(new CustomEvent("ln-fill",{detail:t??null,bubbles:!0})));const n=e.querySelectorAll("[data-ln-form], [data-ln-fillable]");for(let o=0;o<n.length;o++)window.lnCore._debugSink&&window.lnCore._debugSink("event","ln-fill",n[o],t??null),n[o].dispatchEvent(new CustomEvent("ln-fill",{detail:t??null,bubbles:!0}));return e}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._fillBound||(window.lnCore._fillBound=!0,document.addEventListener("ln-fill",function(e){if(!(!e.target.matches||!e.target.matches("[data-ln-fillable]")))if(e.detail)F(e.target,e.detail);else{const t=e.target.querySelectorAll("[data-ln-field]");for(let n=0;n<t.length;n++)t[n].textContent=""}})));function B(e,t){if(!e||!t)return e;const n=document.createTreeWalker(e,NodeFilter.SHOW_TEXT);for(;n.nextNode();){const i=n.currentNode;i.textContent.indexOf("{{")!==-1&&(i.textContent=i.textContent.replace(/\{\{\s*(\w+)\s*\}\}/g,function(r,u){return t[u]!==void 0?t[u]:""}))}const o=function(i,r){return t[r]!==void 0?t[r]:""},s=Array.from(e.querySelectorAll("*"));e.nodeType===1&&s.push(e);for(let i=0;i<s.length;i++){const r=s[i],u=r.attributes;for(let l=0;l<u.length;l++){const d=u[l];d.value.indexOf("{{")!==-1&&r.setAttribute(d.name,d.value.replace(/\{\{\s*(\w+)\s*\}\}/g,o))}}return e}function ee(e,t,n,o,s,i){const r={};for(let l=0;l<e.children.length;l++){const d=e.children[l],h=d.getAttribute("data-ln-render-key");h&&(r[h]=d)}const u=document.createDocumentFragment();for(let l=0;l<t.length;l++){const d=t[l],h=String(o(d));let f=r[h];if(f)s(f,d,l);else{const c=Y(n,i);if(!c||(B(c,d),f=c.firstElementChild,!f))continue;f.setAttribute("data-ln-render-key",h),s(f,d,l)}u.appendChild(f)}e.textContent="",e.appendChild(u)}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.fillTemplate=B,window.lnCore.fill=F,window.lnCore.lnFill=Z,window.lnCore.renderList=ee);function M(e,t,n,o,s){if(!e||t===null)return!0;const i=o||"ln-component",r=e.type;if(r==="trigger"||r==="marker"||r==="string"||r==="list"||!r||t===""&&e.fallback!==void 0)return!0;const u=l=>{s?console.warn(l,s):console.warn(l)};if(r==="boolean"){const l=t.trim().toLowerCase();return l!==""&&l!=="true"&&l!=="false"&&l!=="1"&&l!=="0"?(u(`[${i}] Invalid value "${t}" for boolean attribute "${n}". Allowed: "true", "false", or presence-only.`),!1):!0}if(r==="enum"){const l=e.values||[];return l.includes(t)?!0:(u(`[${i}] Invalid value "${t}" for attribute "${n}". Allowed: ${l.join(", ")}. Fallback: "${e.fallback}".`),!1)}if(r==="integer"){if(!/^-?\d+$/.test(t))return u(`[${i}] Invalid integer "${t}" for attribute "${n}". Fallback: ${e.fallback}.`),!1;const l=parseInt(t,10);return e.min!==void 0&&l<e.min?(u(`[${i}] Value ${l} for attribute "${n}" is less than min (${e.min}).`),!1):e.max!==void 0&&l>e.max?(u(`[${i}] Value ${l} for attribute "${n}" is greater than max (${e.max}).`),!1):!0}if(r==="float")return isNaN(Number(t))?(u(`[${i}] Invalid float "${t}" for attribute "${n}". Fallback: ${e.fallback}.`),!1):!0;if(r==="json")try{return JSON.parse(t),!0}catch(l){return u(`[${i}] Invalid JSON for attribute "${n}": ${l.message}. Fallback: ${e.fallback}.`),!1}return!0}function te(e){const t={};for(const n in e){const o=e[n];o&&o.effect&&(t[n]=o.effect)}return Object.keys(t).length?t:null}function ne(e){if(e.onAttrChange&&!e.declared)return null;const t=new Set;if(e.effects)for(const n in e.effects)t.add(n);if(e.onAttrChange&&e.declared)for(const n of e.declared)t.add(n);return t}function E(e,t,n,o){if(e.nodeType!==1)return;const i=t.indexOf("[")!==-1||t.indexOf(".")!==-1||t.indexOf("#")!==-1?t:"["+t+"]",r=Array.from(e.querySelectorAll(i));e.matches&&e.matches(i)&&r.push(e);for(const u of r)if(!u[n]){window.lnCore._persistSink&&u.hasAttribute("data-ln-persist")&&window.lnCore._persistSink(u,t);try{u[n]=new o(u)}catch(l){console.error("["+n+"] init failed",u,l)}}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore._bootHolds=window.lnCore._bootHolds||0,window.lnCore._bootQueue=window.lnCore._bootQueue||[]);function oe(){return typeof window<"u"&&window.lnCore&&window.lnCore._bootHolds||0}function ie(e){typeof window<"u"?(window.lnCore=window.lnCore||{},window.lnCore._bootHolds=window.lnCore._bootHolds||0,window.lnCore._bootQueue=window.lnCore._bootQueue||[],window.lnCore._bootHolds>0?window.lnCore._bootQueue.push(e):setTimeout(e,0)):e()}function W(){window.lnCore=window.lnCore||{};const e=window.lnCore._attrRegistry=window.lnCore._attrRegistry||{byAttr:new Map,reactive:[],persist:[]};return e.byReactive=e.byReactive||new Map,e.reactiveWildcard=e.reactiveWildcard||[],e}function re(e){const t=W(),n=e.observed||[];for(let o=0;o<n.length;o++){const s=n[o];t.byAttr.has(s)||t.byAttr.set(s,[]),t.byAttr.get(s).push(e)}if(t.byDeclaredAttr=t.byDeclaredAttr||new Map,e.attributes)for(const o in e.attributes){t.byDeclaredAttr.has(o)||t.byDeclaredAttr.set(o,[]);const s=t.byDeclaredAttr.get(o);s.some(i=>i.componentTag===e.componentTag)||s.push({spec:e.attributes[o],componentTag:e.componentTag})}if(e.onAttrChange||e.effects){t.reactive.push(e);const o=ne(e);if(o===null)t.reactiveWildcard.push(e);else for(const s of o)t.byReactive.has(s)||t.byReactive.set(s,[]),t.byReactive.get(s).push(e)}e.persist&&t.persist.push(e)}function N(e,t,n,o){for(let s=0;s<e.length;s++){const i=e[s];if(!t[i.attribute])continue;const r=i.effects&&i.effects[n];r?r(t,n,o):i.onAttrChange&&(!i.declared||i.declared.has(n))&&i.onAttrChange(t,n,o)}}function se(e){const t=e.target,n=e.attributeName;if(e.oldValue===t.getAttribute(n))return;const o=W(),s=o.byAttr.get(n);if(q()&&o.byDeclaredAttr&&o.byDeclaredAttr.has(n)&&x(t)){const i=o.byDeclaredAttr.get(n),r=t.getAttribute(n);for(let u=0;u<i.length;u++)M(i[u].spec,r,n,i[u].componentTag,t)}if(window.lnCore._debugSink&&(n.indexOf("data-ln-")===0||s)&&window.lnCore._debugSink("attr",n,t,{oldValue:e.oldValue,newValue:t.getAttribute(n)}),n.indexOf("data-ln-")===0){const i=o.byReactive.get(n);i&&N(i,t,n,e.oldValue),o.reactiveWildcard.length&&N(o.reactiveWildcard,t,n,e.oldValue)}if(s)for(let i=0;i<s.length;i++){const r=s[i];if(r.handler){r.handler(t,n,e.oldValue);continue}r.onAttributeChange&&t[r.attribute]?r.onAttributeChange(t,n):(E(t,r.selector,r.attribute,r.ComponentFn),r.onInit&&r.onInit(t))}}function le(){window.lnCore=window.lnCore||{},!window.lnCore._attrObserverBound&&(window.lnCore._attrObserverBound=!0,A(function(){new MutationObserver(function(t){for(let n=0;n<t.length;n++)try{se(t[n])}catch(o){console.error("[ln-core] mutation handler failed",t[n].target,o)}}).observe(document.body,{attributes:!0,subtree:!0,attributeOldValue:!0})},"ln-core"))}function j(){return window.lnCore=window.lnCore||{},window.lnCore._lifecycleRegistry=window.lnCore._lifecycleRegistry||[]}function ue(e){const t=j();if(t.length){if(e.target)for(let n=0;n<t.length;n++){const o=t[n];if(o.onSubtreeChange){const s=o.query,i=e.target.nodeType===1?e.target.matches(s)?e.target:e.target.closest(s):e.target.parentElement?e.target.parentElement.closest(s):null;i&&o.onSubtreeChange(i,e)}}for(let n=0;n<e.addedNodes.length;n++){const o=e.addedNodes[n];if(o.nodeType===1)for(let s=0;s<t.length;s++){const i=t[s];E(o,i.selector,i.attribute,i.ComponentFn),i.onInit&&i.onInit(o)}}for(let n=0;n<e.removedNodes.length;n++){const o=e.removedNodes[n];if(o.nodeType===1)for(let s=0;s<t.length;s++){const i=t[s],r=i.query,u=Array.from(o.querySelectorAll(r));o.matches&&o.matches(r)&&u.push(o);for(let l=0;l<u.length;l++){const d=u[l];if(!document.contains(d)){const h=d[i.attribute];if(h&&typeof h.destroy=="function")try{h.destroy()}catch(f){console.error("["+i.attribute+"] destroy failed",d,f)}delete d[i.attribute]}}}}}}function ce(){window.lnCore=window.lnCore||{},!window.lnCore._lifecycleObserverBound&&(window.lnCore._lifecycleObserverBound=!0,A(function(){new MutationObserver(function(t){for(let n=0;n<t.length;n++){const o=t[n];if(o.type==="childList")try{ue(o)}catch(s){console.error("[ln-core] lifecycle handler failed",o.target,s)}}}).observe(document.body,{childList:!0,subtree:!0})},"ln-core"))}function H(e,t,n,o,s={}){const i=s.extraAttributes||[],r=s.onAttributeChange||null,u=s.onSubtreeChange||null,l=s.onInit||null,d=s.onAttrChange||null,h=s.effects||null,f=s.attributes||null,c=f?te(f):h,p=f?new Set(Object.keys(f)):null,g=s.persist||null;function w(m){const C=m||document.body;if(E(C,e,t,n),f&&q())for(const _ in f){const Ce=f[_],L=Array.from(C.querySelectorAll("["+_+"]"));C.matches&&C.matches("["+_+"]")&&L.push(C);for(let T=0;T<L.length;T++){const D=L[T];x(D)&&M(Ce,D.getAttribute(_),_,o,D)}}l&&l(C)}const a=[];if(e.indexOf("[")!==-1){const m=/\[([\w-]+)/g;let C;for(;(C=m.exec(e))!==null;)a.push(C[1])}else a.push(e);re({selector:e,attribute:t,componentTag:o,attributes:f,ComponentFn:n,onInit:l,observed:a.concat(i),onAttributeChange:r,onAttrChange:d,effects:c,declared:p,persist:g}),le();const v=e.indexOf("[")!==-1||e.indexOf(".")!==-1||e.indexOf("#")!==-1?e:"["+e+"]";j().push({selector:e,attribute:t,ComponentFn:n,onInit:l,onSubtreeChange:u,query:v}),ce(),window[t]=w;function b(){oe()>0?ie(function(){w(document.body)}):w(document.body)}return document.readyState==="loading"?document.addEventListener("DOMContentLoaded",b):b(),w}function P(e){return(e||"").replace(/^#/,"")}function S(e){const t=e===void 0?location.hash:e,n={},o=P(t);if(!o)return n;const s=o.split("&");for(let i=0;i<s.length;i++){const r=s[i];if(!r)continue;const u=r.indexOf(":"),l=u>-1?r.slice(0,u):r,d=u>-1?r.slice(u+1):"";if(l)try{n[l]=decodeURIComponent(d)}catch{n[l]=d}}return n}function de(e){if(!e)return null;const t=S();return e in t?t[e]:null}function fe(e,t){if(!e)return;const n=S();t==null?delete n[e]:n[e]=String(t);const s=Object.keys(n).map(function(i){const r=n[i];return r===""?i:i+":"+encodeURIComponent(r)}).join("&");P(location.hash)!==s&&(location.hash=s)}function ae(e){return e.button===1||e.ctrlKey||e.metaKey||e.shiftKey?!1:(e.preventDefault(),!0)}function pe(e,t){if(!e||!e.hasAttribute("data-ln-hash"))return null;const n=e.getAttribute("data-ln-hash");if(n&&n.trim()!=="")return n.trim();const o=e.getAttribute("data-ln-sort")||e.getAttribute("data-ln-search-for")||e.getAttribute("data-ln-search")||e.getAttribute("data-ln-filter")||e.id;return o?t?o+"-"+t:o:t||null}function he(e,t){return!t||t==="none"||e===null||e===void 0?null:String(e)+"."+t}function ge(e){return!e||typeof e!="string"?null:e.endsWith(".asc")?{fieldOrColumn:e.slice(0,-4),direction:"asc"}:e.endsWith(".desc")?{fieldOrColumn:e.slice(0,-5),direction:"desc"}:null}function be(e,t){return!e||!Array.isArray(t)||t.length===0?null:e+":"+t.map(encodeURIComponent).join(",")}function we(e){if(!e||typeof e!="string")return null;const t=e.indexOf(":");if(t===-1)return null;const n=e.slice(0,t),o=e.slice(t+1),s=o?o.split(",").map(function(i){try{return decodeURIComponent(i)}catch{return i}}).filter(Boolean):[];return{key:n,values:s}}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.hashParse=S,window.lnCore.hashGet=de,window.lnCore.hashSet=fe,window.lnCore.hashLinkClick=ae,window.lnCore.resolveHashNamespace=pe,window.lnCore.hashSortEncode=he,window.lnCore.hashSortDecode=ge,window.lnCore.hashFilterEncode=be,window.lnCore.hashFilterDecode=we);function V(e,t,n,o){const s=o,i=window.innerWidth,r=window.innerHeight,u=t.width,l=t.height,d=(n||"bottom").split("-"),h=d[0],f=d[1]==="start"||d[1]==="end"?d[1]:"center",c={top:["top","bottom","right","left"],bottom:["bottom","top","right","left"],left:["left","right","top","bottom"],right:["right","left","top","bottom"]},p=c[h]||c.bottom;function g(b){return b==="top"||b==="bottom"?f==="start"?e.left:f==="end"?e.right-u:e.left+(e.width-u)/2:f==="start"?e.top:f==="end"?e.bottom-l:e.top+(e.height-l)/2}function w(b){let m,C,_=!0;return b==="top"?(m=e.top-s-l,C=g(b),m<0&&(_=!1)):b==="bottom"?(m=e.bottom+s,C=g(b),m+l>r&&(_=!1)):b==="left"?(m=g(b),C=e.left-s-u,C<0&&(_=!1)):(m=g(b),C=e.right+s,C+u>i&&(_=!1)),{top:m,left:C,side:b,fits:_}}let a=null;for(let b=0;b<p.length;b++){const m=w(p[b]);if(m.fits){a=m;break}}a||(a=w(p[0]));let y=a.top,v=a.left;return u>=i?v=0:(v<0&&(v=0),v+u>i&&(v=i-u)),l>=r?y=0:(y<0&&(y=0),y+l>r&&(y=r-l)),{top:y,left:v,placement:a.side}}function U(e){if(!e)return{width:0,height:0};const t=e.style,n=t.visibility,o=t.display,s=t.position;t.visibility="hidden",t.display="block",t.position="fixed";const i=e.offsetWidth,r=e.offsetHeight;return t.visibility=n,t.display=o,t.position=s,{width:i,height:r}}function me(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}typeof window<"u"&&(window.lnCore=window.lnCore||{},window.lnCore.uuid=me),(function(){const e="data-ln-popover",t="lnPopover",n="data-ln-popover-for",o="data-ln-popover-position";if(window[t]!==void 0)return;const s={"data-ln-popover":{type:"enum",values:["open","close"],fallback:"close",effect:f,description:"Control state of the popover"},"data-ln-popover-for":{type:"string",description:"Target element ID that this trigger controls"},"data-ln-popover-position":{type:"enum",values:["top","top-start","top-end","bottom","bottom-start","bottom-end","left","left-start","left-end","right","right-start","right-end"],fallback:"bottom",description:"Preferred positioning anchor"},"data-ln-popover-placement":{type:"enum",values:["top","top-start","top-end","bottom","bottom-start","bottom-end","left","left-start","left-end","right","right-start","right-end"],description:"Active calculated placement applied at runtime"}},i=[];let r=null;function u(){r||(r=function(c){if(c.key!=="Escape"||i.length===0)return;i[i.length-1].close()},document.addEventListener("keydown",r))}function l(){i.length>0||r&&(document.removeEventListener("keydown",r),r=null)}function d(c){this.dom=c,this.isOpen=c.getAttribute(e)==="open",this.trigger=null,this._previousFocus=null,this._boundDocClick=null,this._docClickTimeout=null,this._boundReposition=null;const p=this;return this._onRequestOpen=function(g){const w=g.detail&&g.detail.trigger?g.detail.trigger:null;p.open(w)},this._onRequestClose=function(){p.close()},this._onRequestToggle=function(g){const w=g.detail&&g.detail.trigger?g.detail.trigger:null;p.toggle(w)},this._onNativeToggle=function(g){g.newState==="closed"&&p.isOpen&&(p._applyClose(),p.dom.setAttribute(e,"closed"))},c.addEventListener("ln-popover:request-open",this._onRequestOpen),c.addEventListener("ln-popover:request-close",this._onRequestClose),c.addEventListener("ln-popover:request-toggle",this._onRequestToggle),c.addEventListener("toggle",this._onNativeToggle),c.hasAttribute("tabindex")||c.setAttribute("tabindex","-1"),c.hasAttribute("role")||c.setAttribute("role","dialog"),c.hasAttribute("popover")||c.setAttribute("popover","manual"),this.isOpen&&this._applyOpen(null),this}d.prototype.open=function(c){this.isOpen||(this.trigger=c||null,this.dom.setAttribute(e,"open"))},d.prototype.close=function(){this.isOpen&&this.dom.setAttribute(e,"closed")},d.prototype.toggle=function(c){this.isOpen?this.close():this.open(c)},d.prototype._applyOpen=function(c){this.isOpen=!0,c&&(this.trigger=c),this._previousFocus=document.activeElement,typeof this.dom.showPopover=="function"&&this.dom.showPopover();const p=U(this.dom);if(this.trigger){const y=this.trigger.getBoundingClientRect(),v=this.dom.getAttribute(o)||"bottom",b=V(y,p,v,8);this.dom.style.top=b.top+"px",this.dom.style.left=b.left+"px",this.dom.setAttribute("data-ln-popover-placement",b.placement),this.trigger.setAttribute("aria-expanded","true")}const g=this.dom.querySelectorAll('a[href], button:not([disabled]), input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'),w=Array.prototype.find.call(g,K);w?w.focus():this.dom.focus();const a=this;this._boundDocClick=function(y){a.dom.contains(y.target)||a.trigger&&a.trigger.contains(y.target)||a.close()},a._docClickTimeout=setTimeout(function(){a._docClickTimeout=null,document.addEventListener("click",a._boundDocClick)},0),this._boundReposition=function(){if(!a.trigger)return;const y=a.trigger.getBoundingClientRect(),v=U(a.dom),b=a.dom.getAttribute(o)||"bottom",m=V(y,v,b,8);a.dom.style.top=m.top+"px",a.dom.style.left=m.left+"px",a.dom.setAttribute("data-ln-popover-placement",m.placement)},window.addEventListener("scroll",this._boundReposition,{passive:!0,capture:!0}),window.addEventListener("resize",this._boundReposition),i.push(this),u(),k(this.dom,"ln-popover:open",{popoverId:this.dom.id,target:this.dom,trigger:this.trigger})},d.prototype._applyClose=function(){this.isOpen=!1,this._docClickTimeout&&(clearTimeout(this._docClickTimeout),this._docClickTimeout=null),this._boundDocClick&&(document.removeEventListener("click",this._boundDocClick),this._boundDocClick=null),this._boundReposition&&(window.removeEventListener("scroll",this._boundReposition,{capture:!0}),window.removeEventListener("resize",this._boundReposition),this._boundReposition=null),this.dom.style.top="",this.dom.style.left="",this.dom.removeAttribute("data-ln-popover-placement"),this.trigger&&this.trigger.setAttribute("aria-expanded","false"),typeof this.dom.hidePopover=="function"&&this.dom.matches(":popover-open")&&this.dom.hidePopover();const c=i.indexOf(this);c!==-1&&i.splice(c,1),l(),this._previousFocus&&this.trigger&&this._previousFocus===this.trigger?this.trigger.focus():this.trigger&&document.activeElement===document.body&&this.trigger.focus(),this._previousFocus=null,k(this.dom,"ln-popover:close",{popoverId:this.dom.id,target:this.dom,trigger:this.trigger}),this.trigger=null},d.prototype.destroy=function(){this.dom[t]&&(this.dom.removeEventListener("ln-popover:request-open",this._onRequestOpen),this.dom.removeEventListener("ln-popover:request-close",this._onRequestClose),this.dom.removeEventListener("ln-popover:request-toggle",this._onRequestToggle),this.dom.removeEventListener("toggle",this._onNativeToggle),this.isOpen&&this._applyClose(),delete this.dom[t])};function h(c){this.dom=c;const p=c.getAttribute(n);return c.setAttribute("aria-haspopup","dialog"),c.setAttribute("aria-expanded","false"),c.setAttribute("aria-controls",p),this._onClick=function(g){if(g.ctrlKey||g.metaKey||g.button===1)return;g.preventDefault();const w=document.getElementById(p);if(!w)return;w[t]&&(w[t].trigger=c);const a=w.getAttribute(e);w.setAttribute(e,a==="open"?"closed":"open")},c.addEventListener("click",this._onClick),this}h.prototype.destroy=function(){this.dom.removeEventListener("click",this._onClick),delete this.dom[t+"Trigger"]};function f(c){const p=c[t];if(!p)return;const w=c.getAttribute(e)==="open";if(w!==p.isOpen)if(w){if(I(c,"ln-popover:before-open",{popoverId:c.id,target:c,trigger:p.trigger}).defaultPrevented){c.setAttribute(e,"closed");return}p._applyOpen(p.trigger)}else{if(I(c,"ln-popover:before-close",{popoverId:c.id,target:c,trigger:p.trigger}).defaultPrevented){c.setAttribute(e,"open");return}p._applyClose()}}H(e,t,d,"ln-popover",{attributes:s}),H(n,t+"Trigger",h,"ln-popover-trigger")})()})();
|