composite-select 1.0.9 → 1.0.10
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/dist/cjs/CenterAndHeightResizer.cjs +268 -0
- package/dist/cjs/CenterResizer.cjs +195 -0
- package/dist/cjs/composite-select/ContainerManager.html.cjs +650 -0
- package/dist/cjs/composite-select/composite-select.html.cjs +651 -0
- package/dist/cjs/options-section/OptionsSectionManager.html.cjs +362 -0
- package/dist/cjs/options-section/OptionsSectionManagerWebComponent.attributes.html.cjs +346 -0
- package/dist/cjs/options-section/OptionsSectionManagerWebComponent.html.cjs +354 -0
- package/dist/cjs/options-section/OptionsSectionManagerWebComponent.nocssrequest.html.cjs +345 -0
- package/dist/cjs/selected-section/SelectedSectionManager.html.cjs +336 -0
- package/dist/cjs/selected-section/SelectedSectionManager.templates.html.cjs +353 -0
- package/dist/cjs/selected-section/SelectedSectionManagerWebComponent.attributes.html.cjs +353 -0
- package/dist/cjs/selected-section/SelectedSectionManagerWebComponent.html.cjs +335 -0
- package/dist/cjs/selected-section/SelectedSectionManagerWebComponent.nocssrequest.html.cjs +341 -0
- package/dist/esm/CenterAndHeightResizer.js +268 -0
- package/dist/esm/CenterResizer.js +195 -0
- package/dist/types/CenterAndHeightResizer.d.ts +18 -0
- package/dist/types/CenterResizer.d.ts +16 -0
- package/dist/types/composite-select/ContainerManager.html.d.ts +1 -1
- package/dist/types/composite-select/composite-select.html.d.ts +1 -1
- package/dist/types/options-section/OptionsSectionManager.html.d.ts +1 -1
- package/dist/types/options-section/OptionsSectionManagerWebComponent.attributes.html.d.ts +1 -1
- package/dist/types/options-section/OptionsSectionManagerWebComponent.html.d.ts +1 -1
- package/dist/types/options-section/OptionsSectionManagerWebComponent.nocssrequest.html.d.ts +1 -1
- package/dist/types/selected-section/SelectedSectionManager.html.d.ts +1 -1
- package/dist/types/selected-section/SelectedSectionManager.templates.html.d.ts +1 -1
- package/dist/types/selected-section/SelectedSectionManagerWebComponent.attributes.html.d.ts +1 -1
- package/dist/types/selected-section/SelectedSectionManagerWebComponent.html.d.ts +1 -1
- package/package.json +1 -1
- package/js/CenterAndHeightResizer.js +0 -263
- package/js/CenterResizer.js +0 -190
- /package/dist/cjs/composite-select/{CompositeManager.js → CompositeManager.cjs} +0 -0
- /package/dist/cjs/composite-select/{composite-select.js → composite-select.cjs} +0 -0
- /package/dist/cjs/composite-select/{debounce.js → debounce.cjs} +0 -0
- /package/dist/cjs/composite-select/{helpers.js → helpers.cjs} +0 -0
- /package/dist/cjs/composite-select/{react.js → react.cjs} +0 -0
- /package/dist/cjs/container/{ContainerManager.js → ContainerManager.cjs} +0 -0
- /package/dist/cjs/options-section/{OptionsSectionManager.js → OptionsSectionManager.cjs} +0 -0
- /package/dist/cjs/options-section/{options-section.js → options-section.cjs} +0 -0
- /package/dist/cjs/options-section/{react.js → react.cjs} +0 -0
- /package/dist/cjs/selected-section/{SelectedSectionManager.js → SelectedSectionManager.cjs} +0 -0
- /package/dist/cjs/selected-section/{react.js → react.cjs} +0 -0
- /package/dist/cjs/selected-section/{selected-section.js → selected-section.cjs} +0 -0
- /package/dist/cjs/unbind/{clickOutside.js → clickOutside.cjs} +0 -0
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
import "../CenterAndHeightResizer.js";
|
|
2
|
+
import { OptionsSectionManager } from "./OptionsSectionManager.js";
|
|
3
|
+
import { urlStateConfig, getNextId, setNextId } from "./urlManager.js";
|
|
4
|
+
import { getSafeFreeOffset } from "../composite-select/namesSource.js";
|
|
5
|
+
const reloadLink = document.getElementById("reload-link");
|
|
6
|
+
if (reloadLink) {
|
|
7
|
+
reloadLink.href = window.location.pathname;
|
|
8
|
+
}
|
|
9
|
+
let instanceCounter = 0;
|
|
10
|
+
const updateUrlDisplay = (url = window.location.href) => {
|
|
11
|
+
const el = document.getElementById("url-display");
|
|
12
|
+
if (el)
|
|
13
|
+
el.textContent = url;
|
|
14
|
+
};
|
|
15
|
+
const init = (initialOptions = [], states = {}) => {
|
|
16
|
+
instanceCounter++;
|
|
17
|
+
const id = instanceCounter;
|
|
18
|
+
const resizerLeft = states.left || "50px";
|
|
19
|
+
const resizerCenter = states.center || "350px";
|
|
20
|
+
const resizerHeight = states.height || "";
|
|
21
|
+
const section = document.createElement("div");
|
|
22
|
+
section.className = "demo-section";
|
|
23
|
+
section.innerHTML = `
|
|
24
|
+
<h2>Instance #${id}</h2>
|
|
25
|
+
<button class="gcp-css white destroy-btn" data-role="destroy">Destroy</button>
|
|
26
|
+
|
|
27
|
+
<div class="resizer-container">
|
|
28
|
+
<center-and-height-resizer data-role="resizer" left="${resizerLeft}" center="${resizerCenter}" ${resizerHeight ? `height="${resizerHeight}"` : ""}>
|
|
29
|
+
<div data-role="container" style="height: 100%;"></div>
|
|
30
|
+
</center-and-height-resizer>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<div class="controls gcp-css" style="margin-bottom: 8px;">
|
|
34
|
+
<div class="controls-label">OptionsSectionManager</div>
|
|
35
|
+
|
|
36
|
+
<div style="display: flex; gap: 10px; flex-wrap: wrap;">
|
|
37
|
+
<div class="gcp-css checkbox-wrapper">
|
|
38
|
+
<div class="checkbox-row">
|
|
39
|
+
<input type="checkbox" id="disabled-opt-${id}" data-role="disabled-opt" ${states.disabled ? "checked" : ""}>
|
|
40
|
+
<div class="content-cell"><label for="disabled-opt-${id}">Disabled</label></div>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<div class="gcp-css checkbox-wrapper">
|
|
45
|
+
<div class="checkbox-row">
|
|
46
|
+
<input type="checkbox" id="loading-opt-${id}" data-role="loading-opt" ${states.loading ? "checked" : ""}>
|
|
47
|
+
<div class="content-cell"><label for="loading-opt-${id}">Loading</label></div>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<div class="gcp-css checkbox-wrapper">
|
|
52
|
+
<div class="checkbox-row">
|
|
53
|
+
<input type="checkbox" id="footer-opt-${id}" data-role="footer-opt" ${states.setShowFooter !== false ? "checked" : ""}>
|
|
54
|
+
<div class="content-cell"><label for="footer-opt-${id}">Show Footer</label></div>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<div class="gcp-css checkbox-wrapper">
|
|
59
|
+
<div class="checkbox-row">
|
|
60
|
+
<input type="checkbox" id="filter-opt-${id}" data-role="filter-opt" ${states.setShowFilter !== false ? "checked" : ""}>
|
|
61
|
+
<div class="content-cell"><label for="filter-opt-${id}">Show Filter</label></div>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<div class="gcp-css checkbox-wrapper">
|
|
66
|
+
<div class="checkbox-row">
|
|
67
|
+
<input type="checkbox" id="empty-list-${id}" data-role="empty-list-cb" ${states.emptyList ? "checked" : ""}>
|
|
68
|
+
<div class="content-cell"><label for="empty-list-${id}">Empty list (sim search)</label></div>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
<div style="display: flex; gap: 10px; flex-wrap: wrap; margin-top: 10px;">
|
|
74
|
+
<div class="gcp-css input-wrapper">
|
|
75
|
+
<input type="text" id="label-input-opt-${id}" data-role="label-input-opt" placeholder=" " value="${states.label || ""}">
|
|
76
|
+
<label for="label-input-opt-${id}">Label</label>
|
|
77
|
+
</div>
|
|
78
|
+
<div class="gcp-css input-wrapper">
|
|
79
|
+
<input type="text" id="value-input-opt-${id}" data-role="value-input-opt" placeholder=" " value="${states.value || ""}">
|
|
80
|
+
<label for="value-input-opt-${id}">Value</label>
|
|
81
|
+
</div>
|
|
82
|
+
<button class="gcp-css white" data-role="focus-btn">Focus</button>
|
|
83
|
+
<button class="gcp-css white" data-role="add-btn">Add Random</button>
|
|
84
|
+
<button class="gcp-css white" data-role="clear-btn">Clear All</button>
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
<div style="display: flex; gap: 5px; align-items: center; width: 100%; margin-top: 10px; flex-wrap: wrap;">
|
|
88
|
+
<span style="min-width: 120px;">📏 <strong>Max Height</strong>:</span>
|
|
89
|
+
<div style="display: flex; gap: 2px;">
|
|
90
|
+
<button class="gcp-css white" data-role="mh-down" style="padding: 0 8px; min-width: auto;">▼</button>
|
|
91
|
+
<div class="gcp-css input-wrapper" style="max-width: 100px; margin-bottom: 0;">
|
|
92
|
+
<input type="text" id="mh-input-${id}" data-role="mh-input" placeholder=" " value="${states.maxHeight || ""}">
|
|
93
|
+
<label for="mh-input-${id}">Height</label>
|
|
94
|
+
</div>
|
|
95
|
+
<button class="gcp-css white" data-role="mh-up" style="padding: 0 8px; min-width: auto;">▲</button>
|
|
96
|
+
</div>
|
|
97
|
+
<button class="gcp-css white" data-role="mh-set-btn">Set</button>
|
|
98
|
+
<button class="gcp-css white" data-role="mh-preset" data-value="200px">200px</button>
|
|
99
|
+
<button class="gcp-css white" data-role="mh-preset" data-value="300px">300px</button>
|
|
100
|
+
<button class="gcp-css white" data-role="mh-preset" data-value="400px">400px</button>
|
|
101
|
+
<button class="gcp-css white" data-role="mh-preset" data-value="600px">600px</button>
|
|
102
|
+
<button class="gcp-css white" data-role="mh-preset" data-value="" data-reset>Reset</button>
|
|
103
|
+
</div>
|
|
104
|
+
|
|
105
|
+
<div style="display: flex; gap: 5px; align-items: center; width: 100%; margin-top: 10px; flex-wrap: wrap;">
|
|
106
|
+
<span style="min-width: 120px;">🎨 <strong>Render</strong>:</span>
|
|
107
|
+
<button class="gcp-css white" data-role="opt-render-btn">Set Custom Render</button>
|
|
108
|
+
<button class="gcp-css white" data-role="opt-string-render-btn">Set String Render</button>
|
|
109
|
+
<button class="gcp-css white" data-role="opt-default-render-btn">Set Default Render</button>
|
|
110
|
+
<button class="gcp-css white" data-role="opt-empty-btn">Set Custom Empty</button>
|
|
111
|
+
<button class="gcp-css white" data-role="opt-default-empty-btn">Set Default Empty</button>
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
<div style="width: 100%; margin-top: 10px;">
|
|
115
|
+
(onInputChange triggers: <span data-role="onchange-count" style="font-weight: bold;">0</span>,
|
|
116
|
+
onItemPick: <span data-role="onpick-count" style="font-weight: bold;">0</span>,
|
|
117
|
+
onOk: <span data-role="onok-count" style="font-weight: bold;">0</span>,
|
|
118
|
+
onCancel: <span data-role="oncancel-count" style="font-weight: bold;">0</span>,
|
|
119
|
+
onHighlightChange: <span data-role="onhighlight-count" style="font-weight: bold;">0</span>)
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
|
|
123
|
+
<pre data-role="dump" style="background:#f8f8f8;padding:10px;border:1px solid #eee;border-radius:4px;font-size:12px;margin:0;overflow:auto;"></pre>
|
|
124
|
+
`;
|
|
125
|
+
const instancesArea = document.getElementById("instances-area");
|
|
126
|
+
instancesArea?.appendChild(section);
|
|
127
|
+
const container = section.querySelector('[data-role="container"]');
|
|
128
|
+
const resizer = section.querySelector('[data-role="resizer"]');
|
|
129
|
+
const destroyBtn = section.querySelector('[data-role="destroy"]');
|
|
130
|
+
const dump = section.querySelector('[data-role="dump"]');
|
|
131
|
+
const disabledOptCb = section.querySelector('[data-role="disabled-opt"]');
|
|
132
|
+
const loadingOptCb = section.querySelector('[data-role="loading-opt"]');
|
|
133
|
+
const footerOptCb = section.querySelector('[data-role="footer-opt"]');
|
|
134
|
+
const filterOptCb = section.querySelector('[data-role="filter-opt"]');
|
|
135
|
+
const emptyListCb = section.querySelector('[data-role="empty-list-cb"]');
|
|
136
|
+
const labelInputOpt = section.querySelector('[data-role="label-input-opt"]');
|
|
137
|
+
const valueInputOpt = section.querySelector('[data-role="value-input-opt"]');
|
|
138
|
+
const focusBtn = section.querySelector('[data-role="focus-btn"]');
|
|
139
|
+
const addBtn = section.querySelector('[data-role="add-btn"]');
|
|
140
|
+
const clearBtn = section.querySelector('[data-role="clear-btn"]');
|
|
141
|
+
const mhInput = section.querySelector('[data-role="mh-input"]');
|
|
142
|
+
const mhSetBtn = section.querySelector('[data-role="mh-set-btn"]');
|
|
143
|
+
const mhUp = section.querySelector('[data-role="mh-up"]');
|
|
144
|
+
const mhDown = section.querySelector('[data-role="mh-down"]');
|
|
145
|
+
const optRenderBtn = section.querySelector('[data-role="opt-render-btn"]');
|
|
146
|
+
const optStringRenderBtn = section.querySelector('[data-role="opt-string-render-btn"]');
|
|
147
|
+
const optDefaultRenderBtn = section.querySelector('[data-role="opt-default-render-btn"]');
|
|
148
|
+
const optEmptyBtn = section.querySelector('[data-role="opt-empty-btn"]');
|
|
149
|
+
const optDefaultEmptyBtn = section.querySelector('[data-role="opt-default-empty-btn"]');
|
|
150
|
+
const inc = (role) => {
|
|
151
|
+
const el = section.querySelector(`[data-role="${role}"]`);
|
|
152
|
+
if (el) {
|
|
153
|
+
el.textContent = String(parseInt(el.textContent || "0", 10) + 1);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
const updateDump = (options) => {
|
|
157
|
+
dump.textContent = JSON.stringify(options.filter((o) => o.selected), null, 2);
|
|
158
|
+
};
|
|
159
|
+
let mgr;
|
|
160
|
+
const syncUrl = () => {
|
|
161
|
+
const url = new URL(window.location.href);
|
|
162
|
+
urlStateConfig.toUrl(url, id, {
|
|
163
|
+
options: mgr.getOptions(),
|
|
164
|
+
left: resizer.getAttribute("left") || "50px",
|
|
165
|
+
center: resizer.getAttribute("center") || "350px",
|
|
166
|
+
height: resizer.getAttribute("height") || "",
|
|
167
|
+
disabled: disabledOptCb.checked,
|
|
168
|
+
loading: loadingOptCb.checked,
|
|
169
|
+
setShowFooter: footerOptCb.checked,
|
|
170
|
+
setShowFilter: filterOptCb.checked,
|
|
171
|
+
emptyList: emptyListCb.checked,
|
|
172
|
+
label: labelInputOpt.value || "",
|
|
173
|
+
value: valueInputOpt.value || "",
|
|
174
|
+
maxHeight: mhInput.value || "",
|
|
175
|
+
highlight: String(mgr.propHighlightedId || ""),
|
|
176
|
+
});
|
|
177
|
+
window.history.replaceState({}, "", url);
|
|
178
|
+
updateUrlDisplay(url.toString());
|
|
179
|
+
};
|
|
180
|
+
mgr = new OptionsSectionManager(container, {
|
|
181
|
+
options: initialOptions,
|
|
182
|
+
loading: !!states.loading,
|
|
183
|
+
disabled: !!states.disabled,
|
|
184
|
+
showFooter: states.setShowFooter !== false,
|
|
185
|
+
showFilter: states.setShowFilter !== false,
|
|
186
|
+
label: states.label || "Search...",
|
|
187
|
+
value: states.value || "",
|
|
188
|
+
maxHeight: states.maxHeight || "",
|
|
189
|
+
onInputChange: (e) => {
|
|
190
|
+
inc("onchange-count");
|
|
191
|
+
valueInputOpt.value = e.target.value;
|
|
192
|
+
syncUrl();
|
|
193
|
+
},
|
|
194
|
+
onItemPick: (item) => {
|
|
195
|
+
inc("onpick-count");
|
|
196
|
+
const nextOptions = mgr.getOptions().map((o) => {
|
|
197
|
+
if (String(o.id) === String(item.id))
|
|
198
|
+
return { ...o, selected: !o.selected };
|
|
199
|
+
return o;
|
|
200
|
+
});
|
|
201
|
+
mgr.setOptions(nextOptions);
|
|
202
|
+
updateDump(nextOptions);
|
|
203
|
+
syncUrl();
|
|
204
|
+
},
|
|
205
|
+
onCancel: () => inc("oncancel-count"),
|
|
206
|
+
onOk: () => inc("onok-count"),
|
|
207
|
+
onHighlightChange: (id) => {
|
|
208
|
+
inc("onhighlight-count");
|
|
209
|
+
syncUrl();
|
|
210
|
+
},
|
|
211
|
+
onComponentChange: (opt) => {
|
|
212
|
+
disabledOptCb.checked = !!opt.disabled;
|
|
213
|
+
loadingOptCb.checked = !!opt.loading;
|
|
214
|
+
footerOptCb.checked = opt.showFooter !== false;
|
|
215
|
+
filterOptCb.checked = opt.showFilter !== false;
|
|
216
|
+
labelInputOpt.value = opt.label || "";
|
|
217
|
+
valueInputOpt.value = opt.value || "";
|
|
218
|
+
mhInput.value = opt.maxHeight || "";
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
updateDump(mgr.getOptions());
|
|
222
|
+
disabledOptCb.addEventListener("change", () => {
|
|
223
|
+
mgr.setDisabled(disabledOptCb.checked);
|
|
224
|
+
syncUrl();
|
|
225
|
+
});
|
|
226
|
+
loadingOptCb.addEventListener("change", () => {
|
|
227
|
+
mgr.setLoading(loadingOptCb.checked);
|
|
228
|
+
syncUrl();
|
|
229
|
+
});
|
|
230
|
+
footerOptCb.addEventListener("change", () => {
|
|
231
|
+
mgr.setShowFooter(footerOptCb.checked);
|
|
232
|
+
syncUrl();
|
|
233
|
+
});
|
|
234
|
+
filterOptCb.addEventListener("change", () => {
|
|
235
|
+
mgr.setShowFilter(filterOptCb.checked);
|
|
236
|
+
syncUrl();
|
|
237
|
+
});
|
|
238
|
+
let savedOptions = mgr.getOptions();
|
|
239
|
+
emptyListCb.addEventListener("change", () => {
|
|
240
|
+
if (emptyListCb.checked) {
|
|
241
|
+
savedOptions = mgr.getOptions();
|
|
242
|
+
mgr.setOptions([]);
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
mgr.setOptions(savedOptions);
|
|
246
|
+
}
|
|
247
|
+
syncUrl();
|
|
248
|
+
});
|
|
249
|
+
labelInputOpt.addEventListener("input", () => {
|
|
250
|
+
mgr.setLabel(labelInputOpt.value);
|
|
251
|
+
syncUrl();
|
|
252
|
+
});
|
|
253
|
+
valueInputOpt.addEventListener("input", () => {
|
|
254
|
+
mgr.setValue(valueInputOpt.value);
|
|
255
|
+
syncUrl();
|
|
256
|
+
});
|
|
257
|
+
focusBtn.addEventListener("click", () => mgr.setFocus());
|
|
258
|
+
addBtn.addEventListener("click", () => {
|
|
259
|
+
const id = getNextId();
|
|
260
|
+
setNextId(id + 1);
|
|
261
|
+
const next = [...mgr.getOptions(), { id, label: `Option ${id}` }];
|
|
262
|
+
mgr.setOptions(next);
|
|
263
|
+
syncUrl();
|
|
264
|
+
});
|
|
265
|
+
clearBtn.addEventListener("click", () => {
|
|
266
|
+
mgr.setOptions([]);
|
|
267
|
+
syncUrl();
|
|
268
|
+
});
|
|
269
|
+
const setMH = (val) => {
|
|
270
|
+
mhInput.value = val;
|
|
271
|
+
mgr.setMaxHeight(val);
|
|
272
|
+
syncUrl();
|
|
273
|
+
};
|
|
274
|
+
mhSetBtn.addEventListener("click", () => setMH(mhInput.value));
|
|
275
|
+
mhUp.addEventListener("click", () => {
|
|
276
|
+
const val = parseInt(mhInput.value) || 200;
|
|
277
|
+
setMH(val + 10 + "px");
|
|
278
|
+
});
|
|
279
|
+
mhDown.addEventListener("click", () => {
|
|
280
|
+
const val = parseInt(mhInput.value) || 200;
|
|
281
|
+
setMH(Math.max(0, val - 10) + "px");
|
|
282
|
+
});
|
|
283
|
+
section.querySelectorAll('[data-role="mh-preset"]').forEach((btn) => {
|
|
284
|
+
btn.addEventListener("click", () => setMH(btn.dataset.value || ""));
|
|
285
|
+
});
|
|
286
|
+
optRenderBtn.addEventListener("click", () => {
|
|
287
|
+
mgr.setRenderItem((item) => {
|
|
288
|
+
const el = document.createElement("div");
|
|
289
|
+
el.className = "element";
|
|
290
|
+
el.dataset.id = String(item.id);
|
|
291
|
+
el.style.padding = "8px";
|
|
292
|
+
el.style.borderLeft = item.selected ? "4px solid orange" : "4px solid transparent";
|
|
293
|
+
el.innerHTML = `<strong>${item.label}</strong> ${item.selected ? "✅" : ""}`;
|
|
294
|
+
return el;
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
optStringRenderBtn.addEventListener("click", () => {
|
|
298
|
+
mgr.setRenderItem((item) => `<div class="element" data-id="${item.id}" style="color: blue;">STRING: ${item.label}</div>`);
|
|
299
|
+
});
|
|
300
|
+
optDefaultRenderBtn.addEventListener("click", () => {
|
|
301
|
+
mgr.setRenderItem();
|
|
302
|
+
});
|
|
303
|
+
optEmptyBtn.addEventListener("click", () => {
|
|
304
|
+
mgr.setRenderEmpty(() => `<div style="color: red; padding: 20px;">NOTHING FOUND!</div>`);
|
|
305
|
+
});
|
|
306
|
+
optDefaultEmptyBtn.addEventListener("click", () => {
|
|
307
|
+
mgr.setRenderEmpty();
|
|
308
|
+
});
|
|
309
|
+
resizer.addEventListener("onLeft", () => syncUrl());
|
|
310
|
+
resizer.addEventListener("onCenter", () => syncUrl());
|
|
311
|
+
resizer.addEventListener("onHeight", () => syncUrl());
|
|
312
|
+
destroyBtn.addEventListener("click", () => {
|
|
313
|
+
mgr.destroy();
|
|
314
|
+
section.remove();
|
|
315
|
+
});
|
|
316
|
+
if (states.highlight) {
|
|
317
|
+
mgr.highlightAndScrollToElementOnTheList(states.highlight);
|
|
318
|
+
}
|
|
319
|
+
return mgr;
|
|
320
|
+
};
|
|
321
|
+
const initBtn = document.getElementById("init-btn");
|
|
322
|
+
if (initBtn) {
|
|
323
|
+
initBtn.addEventListener("click", () => {
|
|
324
|
+
init([
|
|
325
|
+
{ id: 101, label: "Option A" },
|
|
326
|
+
{ id: 102, label: "Option B", selected: true },
|
|
327
|
+
{ id: 103, label: "Option C" },
|
|
328
|
+
]);
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
const loadFromUrl = () => {
|
|
332
|
+
const instancesArea = document.getElementById("instances-area");
|
|
333
|
+
if (instancesArea) {
|
|
334
|
+
instancesArea.innerHTML = "";
|
|
335
|
+
}
|
|
336
|
+
instanceCounter = 0;
|
|
337
|
+
setNextId(getSafeFreeOffset());
|
|
338
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
339
|
+
const allIds = urlStateConfig.getAllIds(urlParams);
|
|
340
|
+
if (allIds.length === 0) {
|
|
341
|
+
init([
|
|
342
|
+
{ id: 1, label: "Initial Option 1" },
|
|
343
|
+
{ id: 2, label: "Initial Option 2" },
|
|
344
|
+
], {});
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
allIds.forEach((id) => {
|
|
348
|
+
const state = urlStateConfig.fromUrl(urlParams, id);
|
|
349
|
+
if (state.options) {
|
|
350
|
+
state.options.forEach((o) => {
|
|
351
|
+
const numId = typeof o.id === "number" ? o.id : parseInt(String(o.id), 10);
|
|
352
|
+
if (!isNaN(numId) && numId >= getNextId())
|
|
353
|
+
setNextId(numId + 1);
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
init(state.options || [], state);
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
updateUrlDisplay();
|
|
360
|
+
};
|
|
361
|
+
window.addEventListener("popstate", loadFromUrl);
|
|
362
|
+
loadFromUrl();
|