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