composite-select 1.0.8 → 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.
Files changed (43) hide show
  1. package/dist/cjs/CenterAndHeightResizer.cjs +268 -0
  2. package/dist/cjs/CenterResizer.cjs +195 -0
  3. package/dist/cjs/composite-select/ContainerManager.html.cjs +650 -0
  4. package/dist/cjs/composite-select/composite-select.html.cjs +651 -0
  5. package/dist/cjs/options-section/OptionsSectionManager.html.cjs +362 -0
  6. package/dist/cjs/options-section/OptionsSectionManagerWebComponent.attributes.html.cjs +346 -0
  7. package/dist/cjs/options-section/OptionsSectionManagerWebComponent.html.cjs +354 -0
  8. package/dist/cjs/options-section/OptionsSectionManagerWebComponent.nocssrequest.html.cjs +345 -0
  9. package/dist/cjs/selected-section/SelectedSectionManager.html.cjs +336 -0
  10. package/dist/cjs/selected-section/SelectedSectionManager.templates.html.cjs +353 -0
  11. package/dist/cjs/selected-section/SelectedSectionManagerWebComponent.attributes.html.cjs +353 -0
  12. package/dist/cjs/selected-section/SelectedSectionManagerWebComponent.html.cjs +335 -0
  13. package/dist/cjs/selected-section/SelectedSectionManagerWebComponent.nocssrequest.html.cjs +341 -0
  14. package/dist/esm/CenterAndHeightResizer.js +268 -0
  15. package/dist/esm/CenterResizer.js +195 -0
  16. package/dist/types/CenterAndHeightResizer.d.ts +18 -0
  17. package/dist/types/CenterResizer.d.ts +16 -0
  18. package/dist/types/composite-select/ContainerManager.html.d.ts +1 -1
  19. package/dist/types/composite-select/composite-select.html.d.ts +1 -1
  20. package/dist/types/options-section/OptionsSectionManager.html.d.ts +1 -1
  21. package/dist/types/options-section/OptionsSectionManagerWebComponent.attributes.html.d.ts +1 -1
  22. package/dist/types/options-section/OptionsSectionManagerWebComponent.html.d.ts +1 -1
  23. package/dist/types/options-section/OptionsSectionManagerWebComponent.nocssrequest.html.d.ts +1 -1
  24. package/dist/types/selected-section/SelectedSectionManager.html.d.ts +1 -1
  25. package/dist/types/selected-section/SelectedSectionManager.templates.html.d.ts +1 -1
  26. package/dist/types/selected-section/SelectedSectionManagerWebComponent.attributes.html.d.ts +1 -1
  27. package/dist/types/selected-section/SelectedSectionManagerWebComponent.html.d.ts +1 -1
  28. package/package.json +1 -1
  29. package/js/CenterAndHeightResizer.js +0 -263
  30. package/js/CenterResizer.js +0 -190
  31. /package/dist/cjs/composite-select/{CompositeManager.js → CompositeManager.cjs} +0 -0
  32. /package/dist/cjs/composite-select/{composite-select.js → composite-select.cjs} +0 -0
  33. /package/dist/cjs/composite-select/{debounce.js → debounce.cjs} +0 -0
  34. /package/dist/cjs/composite-select/{helpers.js → helpers.cjs} +0 -0
  35. /package/dist/cjs/composite-select/{react.js → react.cjs} +0 -0
  36. /package/dist/cjs/container/{ContainerManager.js → ContainerManager.cjs} +0 -0
  37. /package/dist/cjs/options-section/{OptionsSectionManager.js → OptionsSectionManager.cjs} +0 -0
  38. /package/dist/cjs/options-section/{options-section.js → options-section.cjs} +0 -0
  39. /package/dist/cjs/options-section/{react.js → react.cjs} +0 -0
  40. /package/dist/cjs/selected-section/{SelectedSectionManager.js → SelectedSectionManager.cjs} +0 -0
  41. /package/dist/cjs/selected-section/{react.js → react.cjs} +0 -0
  42. /package/dist/cjs/selected-section/{selected-section.js → selected-section.cjs} +0 -0
  43. /package/dist/cjs/unbind/{clickOutside.js → clickOutside.cjs} +0 -0
@@ -0,0 +1,353 @@
1
+ import "../CenterResizer.js";
2
+ import { SelectedSection } from "./selected-section.js";
3
+ import { SelectedSectionManager } from "./SelectedSectionManager.js";
4
+ import { urlStateConfig, getNextId, setNextId } from "./urlManager.js";
5
+ import { getSafeFreeOffset } from "../composite-select/namesSource.js";
6
+ const imgData = await fetch("../img/img.json").then((r) => r.json());
7
+ const reloadLink = document.getElementById("reload-link");
8
+ if (reloadLink) {
9
+ reloadLink.href = window.location.pathname;
10
+ }
11
+ let instanceCounter = 0;
12
+ const updateUrlDisplay = (url = window.location.href) => {
13
+ const el = document.getElementById("url-display");
14
+ if (el)
15
+ el.textContent = url;
16
+ };
17
+ const init = (initialSelected = [], states = {}) => {
18
+ instanceCounter++;
19
+ const id = instanceCounter;
20
+ const resizerLeft = states.left || "50px";
21
+ const resizerCenter = states.center || "350px";
22
+ const section = document.createElement("div");
23
+ section.className = "demo-section";
24
+ let templateButtonsHtml = "";
25
+ for (const [color, images] of Object.entries(imgData)) {
26
+ images.forEach((img) => {
27
+ templateButtonsHtml += `<button class="gcp-css white" data-role="template-btn" data-color="${color}" data-img="${img}" style="color: ${color}; padding: 2px 8px; font-size: 11px;">${img}</button>`;
28
+ });
29
+ }
30
+ section.innerHTML = `
31
+ <h2>Instance #${id} (Attributes)</h2>
32
+ <button class="gcp-css white destroy-btn" data-role="destroy">Destroy</button>
33
+
34
+ <div class="resizer-container">
35
+ <center-resizer data-role="resizer" left="${resizerLeft}" center="${resizerCenter}" style="padding: 12px;">
36
+ <selected-section
37
+ label="${states.label || "Select options"}"
38
+ ${states.error ? "error" : ""}
39
+ ${states.disabled ? "disabled" : ""}
40
+ ${states.loading ? "loading" : ""}
41
+ ${states.showInput !== false ? "show-input" : ""}
42
+ ></selected-section>
43
+ </center-resizer>
44
+ </div>
45
+
46
+ <div class="controls gcp-css" style="margin-bottom: 8px;">
47
+ <div class="controls-label">SelectedSectionManager (Attributes)</div>
48
+
49
+ <div style="display: flex; gap: 10px; flex-wrap: wrap;">
50
+ <div class="gcp-css checkbox-wrapper">
51
+ <div class="checkbox-row">
52
+ <input type="checkbox" id="disabled-sel-${id}" data-role="disabled-sel" ${states.disabled ? "checked" : ""}>
53
+ <div class="content-cell"><label for="disabled-sel-${id}">Disabled</label></div>
54
+ </div>
55
+ </div>
56
+
57
+ <div class="gcp-css checkbox-wrapper">
58
+ <div class="checkbox-row">
59
+ <input type="checkbox" id="loading-sel-${id}" data-role="loading-sel" ${states.loading ? "checked" : ""}>
60
+ <div class="content-cell"><label for="loading-sel-${id}">Loading</label></div>
61
+ </div>
62
+ </div>
63
+
64
+ <div class="gcp-css checkbox-wrapper">
65
+ <div class="checkbox-row">
66
+ <input type="checkbox" id="error-sel-${id}" data-role="error-sel" ${states.error ? "checked" : ""}>
67
+ <div class="content-cell"><label for="error-sel-${id}">Error</label></div>
68
+ </div>
69
+ </div>
70
+
71
+ <div class="gcp-css checkbox-wrapper">
72
+ <div class="checkbox-row">
73
+ <input type="checkbox" id="show-input-sel-${id}" data-role="show-input-sel" ${states.showInput !== false ? "checked" : ""}>
74
+ <div class="content-cell"><label for="show-input-sel-${id}">Show Input</label></div>
75
+ </div>
76
+ </div>
77
+ </div>
78
+
79
+ <div style="display: flex; gap: 10px; flex-wrap: wrap; margin-top: 10px;">
80
+ <div class="gcp-css input-wrapper">
81
+ <input type="text" id="label-input-sel-${id}" data-role="label-input-opt" placeholder="&nbsp;" value="${states.label || ""}">
82
+ <label for="label-input-sel-${id}">Label</label>
83
+ </div>
84
+ <div class="gcp-css input-wrapper">
85
+ <input type="text" id="value-input-sel-${id}" data-role="value-input-opt" placeholder="&nbsp;" value="${states.value || ""}">
86
+ <label for="value-input-sel-${id}">Value</label>
87
+ </div>
88
+ <button class="gcp-css white" data-role="focus-btn">Focus</button>
89
+ <button class="gcp-css white" data-role="add-btn">Add Random</button>
90
+ <button class="gcp-css white" data-role="clear-btn">Clear All</button>
91
+ </div>
92
+
93
+ <div style="display: flex; gap: 5px; align-items: center; width: 100%; margin-top: 10px; flex-wrap: wrap;">
94
+ <span style="min-width: 120px;">🖼️ <strong>Templates</strong>:</span>
95
+ ${templateButtonsHtml}
96
+ </div>
97
+
98
+ <div style="display: flex; gap: 5px; align-items: center; width: 100%; margin-top: 10px; flex-wrap: wrap;">
99
+ <span style="min-width: 120px;">🎨 <strong>Render</strong>:</span>
100
+ <button class="gcp-css white" data-role="opt-render-btn">Set Custom Render</button>
101
+ <button class="gcp-css white" data-role="opt-string-render-btn">Set String Render</button>
102
+ <button class="gcp-css white" data-role="opt-default-render-btn">Set Default Render</button>
103
+ </div>
104
+
105
+ <div style="width: 100%; margin-top: 10px;">
106
+ (onInputChange triggers: <span data-role="onchange-count" style="font-weight: bold;">0</span>,
107
+ onDelete triggers: <span data-role="ondelete-count" style="font-weight: bold;">0</span>,
108
+ onClear triggers: <span data-role="onclear-count" style="font-weight: bold;">0</span>,
109
+ onChange triggers: <span data-role="onitemchange-count" style="font-weight: bold;">0</span>,
110
+ onFocus triggers: <span data-role="onfocus-count" style="font-weight: bold;">0</span>)
111
+ </div>
112
+ </div>
113
+
114
+ <pre data-role="dump" style="background:#f8f8f8;padding:10px;border:1px solid #eee;border-radius:4px;font-size:12px;margin:0;overflow:auto;"></pre>
115
+ `;
116
+ document.getElementById("instances-area").appendChild(section);
117
+ const wc = section.querySelector("selected-section");
118
+ const resizer = section.querySelector('[data-role="resizer"]');
119
+ const destroyBtn = section.querySelector('[data-role="destroy"]');
120
+ const dump = section.querySelector('[data-role="dump"]');
121
+ const disabledSelCb = section.querySelector('[data-role="disabled-sel"]');
122
+ const loadingSelCb = section.querySelector('[data-role="loading-sel"]');
123
+ const errorSelCb = section.querySelector('[data-role="error-sel"]');
124
+ const showInputSelCb = section.querySelector('[data-role="show-input-sel"]');
125
+ const labelInputSel = section.querySelector('[data-role="label-input-opt"]');
126
+ const valueInputSel = section.querySelector('[data-role="value-input-opt"]');
127
+ const focusBtn = section.querySelector('[data-role="focus-btn"]');
128
+ const addBtn = section.querySelector('[data-role="add-btn"]');
129
+ const clearBtn = section.querySelector('[data-role="clear-btn"]');
130
+ const optRenderBtn = section.querySelector('[data-role="opt-render-btn"]');
131
+ const optStringRenderBtn = section.querySelector('[data-role="opt-string-render-btn"]');
132
+ const optDefaultRenderBtn = section.querySelector('[data-role="opt-default-render-btn"]');
133
+ const inc = (role) => {
134
+ const el = section.querySelector(`[data-role="${role}"]`);
135
+ if (el) {
136
+ el.textContent = String(parseInt(el.textContent || "0", 10) + 1);
137
+ }
138
+ };
139
+ const updateDump = (list) => {
140
+ dump.textContent = JSON.stringify(list, null, 2);
141
+ };
142
+ let mgr;
143
+ const syncUrl = () => {
144
+ const url = new URL(window.location.href);
145
+ urlStateConfig.toUrl(url, id, {
146
+ selected: mgr ? mgr.getSelected() : [],
147
+ left: resizer.getAttribute("left") || "50px",
148
+ center: resizer.getAttribute("center") || "350px",
149
+ disabled: disabledSelCb.checked,
150
+ loading: loadingSelCb.checked,
151
+ label: labelInputSel.value || "",
152
+ value: valueInputSel.value || "",
153
+ error: errorSelCb.checked,
154
+ showInput: showInputSelCb.checked,
155
+ });
156
+ window.history.replaceState({}, "", url);
157
+ updateUrlDisplay(url.toString());
158
+ };
159
+ wc.setAttribute("selected", JSON.stringify(initialSelected));
160
+ mgr = wc.getManager();
161
+ const sub = mgr.getSubscriber();
162
+ sub.bind("onFocus", () => {
163
+ inc("onfocus-count");
164
+ });
165
+ sub.bind("onInputChange", (e) => {
166
+ inc("onchange-count");
167
+ const val = e.target.value;
168
+ valueInputSel.value = val;
169
+ if (e.key === "Enter" && val.trim() !== "") {
170
+ const currentSelected = JSON.parse(wc.getAttribute("selected") || "[]");
171
+ const id = getNextId();
172
+ setNextId(id + 1);
173
+ const newItem = { id, label: val.trim() };
174
+ wc.setAttribute("selected", JSON.stringify([...currentSelected, newItem]));
175
+ wc.setAttribute("value", "");
176
+ syncUrl();
177
+ }
178
+ if (e.key === "Backspace" && val === "" && JSON.parse(wc.getAttribute("selected") || "[]").length > 0) {
179
+ const currentSelected = JSON.parse(wc.getAttribute("selected") || "[]");
180
+ currentSelected.pop();
181
+ wc.setAttribute("selected", JSON.stringify(currentSelected));
182
+ syncUrl();
183
+ }
184
+ });
185
+ sub.bind("onDelete", (idToDelete) => {
186
+ inc("ondelete-count");
187
+ const currentSelected = JSON.parse(wc.getAttribute("selected") || "[]");
188
+ const nextSelected = currentSelected.filter((i) => String(i.id) !== String(idToDelete));
189
+ wc.setAttribute("selected", JSON.stringify(nextSelected));
190
+ syncUrl();
191
+ });
192
+ sub.bind("onClear", () => {
193
+ inc("onclear-count");
194
+ wc.setAttribute("selected", "[]");
195
+ wc.setAttribute("value", "");
196
+ syncUrl();
197
+ });
198
+ sub.bind("onChange", (selected) => {
199
+ inc("onitemchange-count");
200
+ updateDump(selected);
201
+ });
202
+ wc.getManager()
203
+ ?.getSubscriber()
204
+ .bind("onComponentChange", (opt) => {
205
+ disabledSelCb.checked = !!opt.disabled;
206
+ loadingSelCb.checked = !!opt.loading;
207
+ errorSelCb.checked = !!opt.error;
208
+ showInputSelCb.checked = opt.showInput !== false;
209
+ labelInputSel.value = opt.label || "";
210
+ valueInputSel.value = opt.value || "";
211
+ });
212
+ updateDump(initialSelected);
213
+ disabledSelCb.addEventListener("change", () => {
214
+ if (disabledSelCb.checked)
215
+ wc.setAttribute("disabled", "");
216
+ else
217
+ wc.removeAttribute("disabled");
218
+ syncUrl();
219
+ });
220
+ loadingSelCb.addEventListener("change", () => {
221
+ if (loadingSelCb.checked)
222
+ wc.setAttribute("loading", "");
223
+ else
224
+ wc.removeAttribute("loading");
225
+ syncUrl();
226
+ });
227
+ errorSelCb.addEventListener("change", () => {
228
+ if (errorSelCb.checked)
229
+ wc.setAttribute("error", "");
230
+ else
231
+ wc.removeAttribute("error");
232
+ syncUrl();
233
+ });
234
+ showInputSelCb.addEventListener("change", () => {
235
+ if (showInputSelCb.checked)
236
+ wc.setAttribute("show-input", "");
237
+ else
238
+ wc.removeAttribute("show-input");
239
+ syncUrl();
240
+ });
241
+ labelInputSel.addEventListener("input", () => {
242
+ wc.setAttribute("label", labelInputSel.value);
243
+ syncUrl();
244
+ });
245
+ valueInputSel.addEventListener("input", () => {
246
+ wc.setAttribute("value", valueInputSel.value);
247
+ syncUrl();
248
+ });
249
+ focusBtn.addEventListener("click", () => wc.setFocus());
250
+ addBtn.addEventListener("click", () => {
251
+ const currentSelected = JSON.parse(wc.getAttribute("selected") || "[]");
252
+ const id = getNextId();
253
+ setNextId(id + 1);
254
+ const newItem = { id, label: `Attr Item ${id}` };
255
+ wc.setAttribute("selected", JSON.stringify([...currentSelected, newItem]));
256
+ syncUrl();
257
+ });
258
+ clearBtn.addEventListener("click", () => {
259
+ wc.setAttribute("selected", "[]");
260
+ wc.setAttribute("value", "");
261
+ syncUrl();
262
+ });
263
+ optRenderBtn.addEventListener("click", () => {
264
+ wc.getManager()?.setRenderItem((item, def) => {
265
+ const el = def(item);
266
+ if (item.color) {
267
+ el.style.border = `1px solid ${item.color}`;
268
+ el.style.background = `${item.color}11`;
269
+ }
270
+ if (item.img) {
271
+ const img = document.createElement("img");
272
+ img.src = `../img/${item.img}`;
273
+ img.style.width = "14px";
274
+ img.style.height = "14px";
275
+ img.style.objectFit = "contain";
276
+ img.style.marginRight = "5px";
277
+ el.insertBefore(img, el.firstChild);
278
+ }
279
+ return el;
280
+ });
281
+ });
282
+ section.querySelectorAll('[data-role="template-btn"]').forEach((btn) => {
283
+ btn.addEventListener("click", () => {
284
+ const b = btn;
285
+ const currentSelected = JSON.parse(wc.getAttribute("selected") || "[]");
286
+ const id = getNextId();
287
+ setNextId(id + 1);
288
+ const newItem = {
289
+ id,
290
+ label: b.dataset.img ? b.dataset.img.split(".")[0] : `Template ${id}`,
291
+ color: b.dataset.color,
292
+ img: b.dataset.img,
293
+ };
294
+ wc.setAttribute("selected", JSON.stringify([...currentSelected, newItem]));
295
+ syncUrl();
296
+ });
297
+ });
298
+ optStringRenderBtn.addEventListener("click", () => {
299
+ wc.getManager()?.setRenderItem((item) => {
300
+ const el = document.createElement("div");
301
+ el.className = "element";
302
+ el.dataset.id = String(item.id);
303
+ el.innerHTML = `<strong>ATTR: ${item.label}</strong> <span data-remove="${item.id}" style="cursor:pointer; margin-left: 5px;">[x]</span>`;
304
+ return el;
305
+ });
306
+ });
307
+ optDefaultRenderBtn.addEventListener("click", () => {
308
+ wc.getManager()?.setRenderItem();
309
+ });
310
+ resizer.addEventListener("onLeft", () => syncUrl());
311
+ resizer.addEventListener("onCenter", () => syncUrl());
312
+ destroyBtn.addEventListener("click", () => {
313
+ wc.getManager()?.destroy();
314
+ section.remove();
315
+ });
316
+ return wc.getManager();
317
+ };
318
+ const initBtn = document.getElementById("init-btn");
319
+ if (initBtn) {
320
+ initBtn.addEventListener("click", () => init());
321
+ }
322
+ const loadFromUrl = () => {
323
+ const instancesArea = document.getElementById("instances-area");
324
+ if (!instancesArea)
325
+ return;
326
+ instancesArea.innerHTML = "";
327
+ instanceCounter = 0;
328
+ setNextId(getSafeFreeOffset());
329
+ const urlParams = new URLSearchParams(window.location.search);
330
+ const allIds = urlStateConfig.getAllIds(urlParams);
331
+ if (allIds.length === 0) {
332
+ init([
333
+ { id: 1, label: "Initial 1" },
334
+ { id: 2, label: "Initial 2" },
335
+ ], {});
336
+ }
337
+ else {
338
+ allIds.forEach((id) => {
339
+ const state = urlStateConfig.fromUrl(urlParams, id);
340
+ if (state.selected) {
341
+ state.selected.forEach((item) => {
342
+ const numId = typeof item.id === "number" ? item.id : parseInt(String(item.id), 10);
343
+ if (!isNaN(numId) && numId >= getNextId())
344
+ setNextId(numId + 1);
345
+ });
346
+ }
347
+ init(state.selected || [], state);
348
+ });
349
+ }
350
+ updateUrlDisplay();
351
+ };
352
+ window.addEventListener("popstate", loadFromUrl);
353
+ loadFromUrl();