@kupola/kupola 1.4.2 → 1.4.4
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/README.md +28 -3
- package/css/components-ext.css +1 -1
- package/css/kupola.css +3 -2
- package/css/table.css +74 -0
- package/dist/css/components-ext.css +158 -1
- package/dist/css/components.css +93 -1
- package/dist/css/kupola.css +13 -1
- package/dist/css/table.css +74 -0
- package/dist/css/theme-dark.css +5 -5
- package/dist/css/utilities.css +159 -1
- package/dist/kupola.cjs.js +214 -17409
- package/dist/kupola.cjs.js.map +1 -1
- package/dist/kupola.css +101 -4
- package/dist/kupola.esm.js +8196 -17225
- package/dist/kupola.esm.js.map +1 -1
- package/dist/kupola.min.css +1 -1
- package/dist/kupola.umd.js +214 -17415
- package/dist/kupola.umd.js.map +1 -1
- package/dist/types/kupola.d.ts +41 -25
- package/js/calendar.js +3 -10
- package/js/carousel.js +3 -10
- package/js/collapse.js +3 -10
- package/js/color-picker.js +5 -16
- package/js/component.js +4 -18
- package/js/countdown.js +3 -10
- package/js/data-bind.js +56 -36
- package/js/datepicker.js +16 -24
- package/js/depends.js +27 -16
- package/js/dialog.js +1 -5
- package/js/drawer.js +3 -11
- package/js/dropdown.js +11 -18
- package/js/dynamic-tags.js +3 -10
- package/js/fileupload.js +10 -12
- package/js/form.js +26 -20
- package/js/global-events.js +1 -14
- package/js/heatmap.js +3 -12
- package/js/i18n.js +1 -14
- package/js/icons.js +2 -2
- package/js/image-preview.js +1 -7
- package/js/initializer.js +0 -43
- package/js/kupola-core.js +1 -13
- package/js/kupola-lifecycle.js +1 -9
- package/js/message.js +1 -6
- package/js/modal.js +22 -20
- package/js/notification.js +1 -6
- package/js/numberinput.js +3 -10
- package/js/pagination.js +0 -5
- package/js/registry.js +0 -4
- package/js/select.js +5 -16
- package/js/slide-captcha.js +8 -21
- package/js/slider.js +3 -10
- package/js/statcard.js +3 -11
- package/js/table.js +240 -262
- package/js/tag.js +3 -10
- package/js/theme.js +11 -16
- package/js/timepicker.js +6 -19
- package/js/tooltip.js +3 -10
- package/js/utils.js +281 -1439
- package/js/validation.js +2 -7
- package/js/virtual-list.js +13 -38
- package/js/web-components.js +0 -9
- package/package.json +12 -7
- package/scripts/build-css.cjs +3 -2
- package/types/kupola.d.ts +41 -25
- package/version.json +10 -0
- package/dist/css/kupola.min.css +0 -1
- package/dist/icons.svg +0 -284
- package/dist/kupola.min.js +0 -2
- package/dist/kupola.min.js.map +0 -1
- /package/css/{colors_and_type.css → colors-and-type.css} +0 -0
- /package/dist/css/{colors_and_type.css → colors-and-type.css} +0 -0
package/js/dropdown.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { globalEvents } from './global-events.js';
|
|
2
|
+
import { kupolaInitializer } from './initializer.js';
|
|
3
|
+
|
|
1
4
|
class Dropdown {
|
|
2
5
|
constructor(element, options = {}) {
|
|
3
6
|
this.element = element;
|
|
@@ -30,6 +33,7 @@ class Dropdown {
|
|
|
30
33
|
this._mouseleaveHandler = null;
|
|
31
34
|
this._triggerMouseenterHandler = null;
|
|
32
35
|
this._triggerMouseleaveHandler = null;
|
|
36
|
+
this._triggerKeydownHandler = null;
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
init() {
|
|
@@ -139,13 +143,14 @@ class Dropdown {
|
|
|
139
143
|
}
|
|
140
144
|
|
|
141
145
|
// Keyboard on trigger
|
|
142
|
-
this.
|
|
146
|
+
this._triggerKeydownHandler = (e) => {
|
|
143
147
|
if (this.disabled) return;
|
|
144
148
|
if (e.key === 'Enter' || e.key === ' ' || e.key === 'ArrowDown') {
|
|
145
149
|
e.preventDefault();
|
|
146
150
|
this.showMenu();
|
|
147
151
|
}
|
|
148
|
-
}
|
|
152
|
+
};
|
|
153
|
+
this.trigger.addEventListener('keydown', this._triggerKeydownHandler);
|
|
149
154
|
|
|
150
155
|
document.addEventListener('keydown', this._keydownHandler);
|
|
151
156
|
|
|
@@ -156,11 +161,7 @@ class Dropdown {
|
|
|
156
161
|
}
|
|
157
162
|
};
|
|
158
163
|
|
|
159
|
-
|
|
160
|
-
this._documentClickListener = window.globalEvents.on(document, 'click', this._documentClickHandler, { scope: this.scope });
|
|
161
|
-
} else {
|
|
162
|
-
document.addEventListener('click', this._documentClickHandler);
|
|
163
|
-
}
|
|
164
|
+
this._documentClickListener = globalEvents.on(document, 'click', this._documentClickHandler, { scope: this.scope });
|
|
164
165
|
|
|
165
166
|
this.menu.style.display = 'none';
|
|
166
167
|
this.element.__kupolaInitialized = true;
|
|
@@ -304,6 +305,7 @@ class Dropdown {
|
|
|
304
305
|
if (this._triggerClickHandler) this.trigger.removeEventListener('click', this._triggerClickHandler);
|
|
305
306
|
if (this._triggerMouseenterHandler) this.trigger.removeEventListener('mouseenter', this._triggerMouseenterHandler);
|
|
306
307
|
if (this._triggerMouseleaveHandler) this.trigger.removeEventListener('mouseleave', this._triggerMouseleaveHandler);
|
|
308
|
+
if (this._triggerKeydownHandler) this.trigger.removeEventListener('keydown', this._triggerKeydownHandler);
|
|
307
309
|
}
|
|
308
310
|
|
|
309
311
|
if (this.menu) {
|
|
@@ -333,6 +335,7 @@ class Dropdown {
|
|
|
333
335
|
this._mouseleaveHandler = null;
|
|
334
336
|
this._triggerMouseenterHandler = null;
|
|
335
337
|
this._triggerMouseleaveHandler = null;
|
|
338
|
+
this._triggerKeydownHandler = null;
|
|
336
339
|
this.element.__kupolaInitialized = false;
|
|
337
340
|
}
|
|
338
341
|
}
|
|
@@ -364,14 +367,4 @@ function cleanupAllDropdowns() {
|
|
|
364
367
|
|
|
365
368
|
export { Dropdown, initDropdown, initDropdowns, cleanupDropdown, cleanupAllDropdowns };
|
|
366
369
|
|
|
367
|
-
|
|
368
|
-
window.Dropdown = Dropdown;
|
|
369
|
-
window.initDropdown = initDropdown;
|
|
370
|
-
window.initDropdowns = initDropdowns;
|
|
371
|
-
window.cleanupDropdown = cleanupDropdown;
|
|
372
|
-
window.cleanupAllDropdowns = cleanupAllDropdowns;
|
|
373
|
-
|
|
374
|
-
if (window.kupolaInitializer) {
|
|
375
|
-
window.kupolaInitializer.register('dropdown', initDropdown, cleanupDropdown);
|
|
376
|
-
}
|
|
377
|
-
}
|
|
370
|
+
kupolaInitializer.register('dropdown', initDropdown, cleanupDropdown);
|
package/js/dynamic-tags.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { kupolaInitializer } from './initializer.js';
|
|
2
|
+
|
|
1
3
|
class DynamicTags {
|
|
2
4
|
constructor(element, options = {}) {
|
|
3
5
|
this.element = element;
|
|
@@ -260,13 +262,4 @@ function initDynamicTagsAll() {
|
|
|
260
262
|
|
|
261
263
|
export { DynamicTags, initDynamicTagsAll, initDynamicTags, cleanupDynamicTags };
|
|
262
264
|
|
|
263
|
-
|
|
264
|
-
window.DynamicTags = DynamicTags;
|
|
265
|
-
window.initDynamicTags = initDynamicTags;
|
|
266
|
-
window.cleanupDynamicTags = cleanupDynamicTags;
|
|
267
|
-
window.initDynamicTagsAll = initDynamicTagsAll;
|
|
268
|
-
|
|
269
|
-
if (window.kupolaInitializer) {
|
|
270
|
-
window.kupolaInitializer.register('dynamic-tags', initDynamicTags, cleanupDynamicTags);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
265
|
+
kupolaInitializer.register('dynamic-tags', initDynamicTags, cleanupDynamicTags);
|
package/js/fileupload.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import { kupolaInitializer } from './initializer.js';
|
|
2
|
+
|
|
3
|
+
function _escapeHtml(str) {
|
|
4
|
+
if (!str) return '';
|
|
5
|
+
return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
|
|
6
|
+
}
|
|
7
|
+
|
|
1
8
|
class FileUpload {
|
|
2
9
|
constructor(element) {
|
|
3
10
|
this.element = element;
|
|
@@ -126,7 +133,7 @@ class FileUpload {
|
|
|
126
133
|
<div class="ds-fileupload__icon" style="width: 24px; height: 24px; border-radius: 4px;">
|
|
127
134
|
${fileIcon}
|
|
128
135
|
</div>
|
|
129
|
-
<span class="ds-fileupload__filename">${this.truncateFilename(file.name)}</span>
|
|
136
|
+
<span class="ds-fileupload__filename">${this.truncateFilename(_escapeHtml(file.name))}</span>
|
|
130
137
|
<span class="ds-fileupload__size">${this.formatSize(file.size)}</span>
|
|
131
138
|
<button class="ds-fileupload__remove" type="button" aria-label="Remove file">
|
|
132
139
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
@@ -254,7 +261,7 @@ class FileUpload {
|
|
|
254
261
|
const previewItem = document.createElement('div');
|
|
255
262
|
previewItem.className = 'ds-fileupload__preview-item';
|
|
256
263
|
previewItem.innerHTML = `
|
|
257
|
-
<img src="${e.target.result}" alt="${file.name}">
|
|
264
|
+
<img src="${e.target.result}" alt="${_escapeHtml(file.name)}">
|
|
258
265
|
<button class="ds-fileupload__preview-remove" type="button" aria-label="Remove preview">
|
|
259
266
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
260
267
|
<path d="M18 6L6 18"/>
|
|
@@ -381,13 +388,4 @@ function initFileUploads() {
|
|
|
381
388
|
|
|
382
389
|
export { FileUpload, initFileUploads, initFileUpload, cleanupFileUpload };
|
|
383
390
|
|
|
384
|
-
|
|
385
|
-
window.FileUpload = FileUpload;
|
|
386
|
-
window.initFileUpload = initFileUpload;
|
|
387
|
-
window.cleanupFileUpload = cleanupFileUpload;
|
|
388
|
-
window.initFileUploads = initFileUploads;
|
|
389
|
-
|
|
390
|
-
if (window.kupolaInitializer) {
|
|
391
|
-
window.kupolaInitializer.register('fileupload', initFileUpload, cleanupFileUpload);
|
|
392
|
-
}
|
|
393
|
-
}
|
|
391
|
+
kupolaInitializer.register('fileupload', initFileUpload, cleanupFileUpload);
|
package/js/form.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import { kupolaInitializer } from './initializer.js';
|
|
2
|
+
|
|
1
3
|
class KupolaForm {
|
|
2
4
|
constructor(formElement) {
|
|
3
5
|
this.form = formElement;
|
|
4
6
|
this.fields = [];
|
|
5
7
|
this.validators = {};
|
|
6
8
|
this.errorMessages = {};
|
|
9
|
+
this._submitHandler = null;
|
|
10
|
+
this._fieldHandlers = new Map(); // field → { blur, input }
|
|
7
11
|
this._init();
|
|
8
12
|
}
|
|
9
13
|
|
|
@@ -100,15 +104,19 @@ class KupolaForm {
|
|
|
100
104
|
}
|
|
101
105
|
|
|
102
106
|
_bindEvents() {
|
|
103
|
-
this.
|
|
107
|
+
this._submitHandler = (e) => {
|
|
104
108
|
if (!this.validate()) {
|
|
105
109
|
e.preventDefault();
|
|
106
110
|
}
|
|
107
|
-
}
|
|
111
|
+
};
|
|
112
|
+
this.form.addEventListener('submit', this._submitHandler);
|
|
108
113
|
|
|
109
114
|
this.fields.forEach(field => {
|
|
110
|
-
|
|
111
|
-
|
|
115
|
+
const blurHandler = () => this.validateField(field);
|
|
116
|
+
const inputHandler = () => this.clearError(field);
|
|
117
|
+
this._fieldHandlers.set(field, { blur: blurHandler, input: inputHandler });
|
|
118
|
+
field.addEventListener('blur', blurHandler);
|
|
119
|
+
field.addEventListener('input', inputHandler);
|
|
112
120
|
});
|
|
113
121
|
}
|
|
114
122
|
|
|
@@ -264,13 +272,20 @@ class KupolaForm {
|
|
|
264
272
|
}
|
|
265
273
|
|
|
266
274
|
destroy() {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
275
|
+
// 移除 submit handler
|
|
276
|
+
if (this._submitHandler && this.form) {
|
|
277
|
+
this.form.removeEventListener('submit', this._submitHandler);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// 移除每个字段的 blur/input handlers
|
|
281
|
+
this._fieldHandlers.forEach((handlers, field) => {
|
|
282
|
+
field.removeEventListener('blur', handlers.blur);
|
|
283
|
+
field.removeEventListener('input', handlers.input);
|
|
270
284
|
});
|
|
271
|
-
|
|
272
|
-
this.
|
|
273
|
-
|
|
285
|
+
|
|
286
|
+
this._submitHandler = null;
|
|
287
|
+
this._fieldHandlers.clear();
|
|
288
|
+
this._fieldHandlers = null;
|
|
274
289
|
this.fields = null;
|
|
275
290
|
this.validators = null;
|
|
276
291
|
this.errorMessages = null;
|
|
@@ -305,13 +320,4 @@ function validateForm(formElement) {
|
|
|
305
320
|
|
|
306
321
|
export { KupolaForm, initFormValidation, getFormInstance, validateForm };
|
|
307
322
|
|
|
308
|
-
|
|
309
|
-
window.KupolaForm = KupolaForm;
|
|
310
|
-
window.initFormValidation = initFormValidation;
|
|
311
|
-
window.getFormInstance = getFormInstance;
|
|
312
|
-
window.validateForm = validateForm;
|
|
313
|
-
|
|
314
|
-
if (window.kupolaInitializer) {
|
|
315
|
-
window.kupolaInitializer.register('form-validation', initFormValidation);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
323
|
+
kupolaInitializer.register('form-validation', initFormValidation);
|
package/js/global-events.js
CHANGED
|
@@ -280,17 +280,4 @@ function getListenerCount(target, eventName) {
|
|
|
280
280
|
return globalEvents.getListenerCount(target, eventName);
|
|
281
281
|
}
|
|
282
282
|
|
|
283
|
-
export { GlobalEvents, globalEvents, on, once, off, emit, emitGlobal, offByScope, offAll, getListenerCount };
|
|
284
|
-
|
|
285
|
-
if (typeof window !== 'undefined') {
|
|
286
|
-
window.GlobalEvents = GlobalEvents;
|
|
287
|
-
window.globalEvents = globalEvents;
|
|
288
|
-
window.kupolaOn = on;
|
|
289
|
-
window.kupolaOnce = once;
|
|
290
|
-
window.kupolaOff = off;
|
|
291
|
-
window.kupolaEmit = emit;
|
|
292
|
-
window.kupolaEmitGlobal = emitGlobal;
|
|
293
|
-
window.kupolaOffByScope = offByScope;
|
|
294
|
-
window.kupolaOffAll = offAll;
|
|
295
|
-
window.kupolaGetListenerCount = getListenerCount;
|
|
296
|
-
}
|
|
283
|
+
export { GlobalEvents, globalEvents, on, once, off, emit, emitGlobal, offByScope, offAll, getListenerCount };
|
package/js/heatmap.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { kupolaInitializer } from './initializer.js';
|
|
2
|
+
|
|
1
3
|
class Heatmap {
|
|
2
4
|
constructor(element, options = {}) {
|
|
3
5
|
this.element = element;
|
|
@@ -394,15 +396,4 @@ function createHeatmap(selector, options = {}) {
|
|
|
394
396
|
|
|
395
397
|
export { Heatmap, initHeatmaps, initHeatmap, cleanupHeatmap, createHeatmap, generateMockHeatmapData };
|
|
396
398
|
|
|
397
|
-
|
|
398
|
-
window.Heatmap = Heatmap;
|
|
399
|
-
window.initHeatmap = initHeatmap;
|
|
400
|
-
window.cleanupHeatmap = cleanupHeatmap;
|
|
401
|
-
window.initHeatmaps = initHeatmaps;
|
|
402
|
-
window.createHeatmap = createHeatmap;
|
|
403
|
-
window.generateMockHeatmapData = generateMockHeatmapData;
|
|
404
|
-
|
|
405
|
-
if (window.kupolaInitializer) {
|
|
406
|
-
window.kupolaInitializer.register('heatmap', initHeatmap, cleanupHeatmap);
|
|
407
|
-
}
|
|
408
|
-
}
|
|
399
|
+
kupolaInitializer.register('heatmap', initHeatmap, cleanupHeatmap);
|
package/js/i18n.js
CHANGED
|
@@ -220,17 +220,4 @@ export {
|
|
|
220
220
|
KupolaI18n, kupolaI18n, createI18n,
|
|
221
221
|
t, n, setLocale, getLocale,
|
|
222
222
|
formatDate, formatNumber, formatCurrency
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
if (typeof window !== 'undefined') {
|
|
226
|
-
window.KupolaI18n = KupolaI18n;
|
|
227
|
-
window.kupolaI18n = kupolaI18n;
|
|
228
|
-
window.createI18n = createI18n;
|
|
229
|
-
window.t = t;
|
|
230
|
-
window.n = n;
|
|
231
|
-
window.setLocale = setLocale;
|
|
232
|
-
window.getLocale = getLocale;
|
|
233
|
-
window.formatDate = formatDate;
|
|
234
|
-
window.formatNumber = formatNumber;
|
|
235
|
-
window.formatCurrency = formatCurrency;
|
|
236
|
-
}
|
|
223
|
+
};
|
package/js/icons.js
CHANGED
|
@@ -135,8 +135,8 @@ const Icons = { svg, render, PATHS };
|
|
|
135
135
|
|
|
136
136
|
export { Icons, svg, render, PATHS };
|
|
137
137
|
|
|
138
|
-
|
|
139
|
-
|
|
138
|
+
// Auto-render SVG sprite on DOM ready
|
|
139
|
+
if (typeof document !== 'undefined') {
|
|
140
140
|
if (document.readyState !== 'loading') {
|
|
141
141
|
render();
|
|
142
142
|
} else {
|
package/js/image-preview.js
CHANGED
|
@@ -353,10 +353,4 @@ function showImagePreview(images, index = 0) {
|
|
|
353
353
|
imagePreviewInstance.show(images, index);
|
|
354
354
|
}
|
|
355
355
|
|
|
356
|
-
export { ImagePreview, initImagePreview, showImagePreview };
|
|
357
|
-
|
|
358
|
-
if (typeof window !== 'undefined') {
|
|
359
|
-
window.ImagePreview = ImagePreview;
|
|
360
|
-
window.initImagePreview = initImagePreview;
|
|
361
|
-
window.showImagePreview = showImagePreview;
|
|
362
|
-
}
|
|
356
|
+
export { ImagePreview, initImagePreview, showImagePreview };
|
package/js/initializer.js
CHANGED
|
@@ -197,46 +197,3 @@ for (const comp of knownComponents) {
|
|
|
197
197
|
}
|
|
198
198
|
|
|
199
199
|
export { ComponentInitializerRegistry, kupolaInitializer };
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Kupola global namespace — convenience API for external consumers.
|
|
203
|
-
* Provides Kupola.refresh(root) to re-initialize dynamically inserted DOM.
|
|
204
|
-
*/
|
|
205
|
-
if (typeof window !== 'undefined') {
|
|
206
|
-
window.Kupola = window.Kupola || {};
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Re-scan and initialize components within a given scope.
|
|
210
|
-
* @param {Element|Document} [root=document] - Scope to scan
|
|
211
|
-
* @returns {Promise<void>}
|
|
212
|
-
*/
|
|
213
|
-
window.Kupola.refresh = async function refresh(root) {
|
|
214
|
-
return kupolaInitializer.initializeAll(root || document);
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Initialize a single element or container.
|
|
219
|
-
* @param {Element} element
|
|
220
|
-
* @returns {Promise<void>}
|
|
221
|
-
*/
|
|
222
|
-
window.Kupola.init = async function init(element) {
|
|
223
|
-
return kupolaInitializer.initialize(element);
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Cleanup a single element.
|
|
228
|
-
* @param {Element} element
|
|
229
|
-
*/
|
|
230
|
-
window.Kupola.cleanup = function cleanup(element) {
|
|
231
|
-
return kupolaInitializer.cleanup(element);
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
/** Expose the initializer registry directly */
|
|
235
|
-
window.Kupola.initializer = kupolaInitializer;
|
|
236
|
-
window.Kupola.ComponentInitializerRegistry = ComponentInitializerRegistry;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
if (typeof window !== 'undefined') {
|
|
240
|
-
window.ComponentInitializerRegistry = ComponentInitializerRegistry;
|
|
241
|
-
window.kupolaInitializer = kupolaInitializer;
|
|
242
|
-
}
|
package/js/kupola-core.js
CHANGED
|
@@ -129,16 +129,4 @@ export {
|
|
|
129
129
|
defineMixin,
|
|
130
130
|
useMixin,
|
|
131
131
|
defineComponent
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
if (typeof window !== 'undefined') {
|
|
135
|
-
window.kupolaRegistry = kupolaRegistry;
|
|
136
|
-
window.kupolaInitializer = kupolaInitializer;
|
|
137
|
-
window.kupolaBootstrap = kupolaBootstrap;
|
|
138
|
-
window.registerComponent = registerComponent;
|
|
139
|
-
window.registerLazyComponent = registerLazyComponent;
|
|
140
|
-
window.bootstrapComponents = bootstrapComponents;
|
|
141
|
-
window.defineMixin = defineMixin;
|
|
142
|
-
window.useMixin = useMixin;
|
|
143
|
-
window.defineComponent = defineComponent;
|
|
144
|
-
}
|
|
132
|
+
};
|
package/js/kupola-lifecycle.js
CHANGED
|
@@ -477,7 +477,7 @@ export class KupolaPluginManager {
|
|
|
477
477
|
const pluginHooks = this.pluginHooks.get(pluginName);
|
|
478
478
|
|
|
479
479
|
Object.keys(hooks).forEach(phase => {
|
|
480
|
-
const unsubscribe =
|
|
480
|
+
const unsubscribe = kupolaLifecycle?.on(phase, hooks[phase], { name: `${pluginName}:${phase}` });
|
|
481
481
|
if (unsubscribe) {
|
|
482
482
|
pluginHooks.push({ phase, unsubscribe });
|
|
483
483
|
}
|
|
@@ -501,12 +501,4 @@ export const kupolaPluginManager = new KupolaPluginManager();
|
|
|
501
501
|
|
|
502
502
|
export function createLifecycle(scope = 'app') {
|
|
503
503
|
return new KupolaLifecycle(scope);
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
if (typeof window !== 'undefined') {
|
|
507
|
-
window.KupolaLifecycle = KupolaLifecycle;
|
|
508
|
-
window.KupolaPluginManager = KupolaPluginManager;
|
|
509
|
-
window.kupolaLifecycle = kupolaLifecycle;
|
|
510
|
-
window.kupolaPluginManager = kupolaPluginManager;
|
|
511
|
-
window.createLifecycle = createLifecycle;
|
|
512
504
|
}
|
package/js/message.js
CHANGED
package/js/modal.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { kupolaInitializer } from './initializer.js';
|
|
2
|
+
|
|
1
3
|
class Modal {
|
|
2
4
|
constructor(element, options = {}) {
|
|
3
5
|
this.element = element;
|
|
@@ -16,6 +18,8 @@ class Modal {
|
|
|
16
18
|
this.onOpened = options.onOpened || null;
|
|
17
19
|
this.onClosed = options.onClosed || null;
|
|
18
20
|
|
|
21
|
+
this._isOpen = false; // 实例级跟踪,防止 _openCount 不匹配
|
|
22
|
+
|
|
19
23
|
this._keydownHandler = (e) => {
|
|
20
24
|
if (this.escClose && e.key === 'Escape' && this.isVisible()) {
|
|
21
25
|
this.close();
|
|
@@ -75,7 +79,10 @@ class Modal {
|
|
|
75
79
|
});
|
|
76
80
|
}
|
|
77
81
|
|
|
78
|
-
|
|
82
|
+
if (!this._isOpen) {
|
|
83
|
+
Modal._openCount = (Modal._openCount || 0) + 1;
|
|
84
|
+
this._isOpen = true;
|
|
85
|
+
}
|
|
79
86
|
document.body.style.overflow = 'hidden';
|
|
80
87
|
|
|
81
88
|
if (this.onOpened) {
|
|
@@ -109,9 +116,12 @@ class Modal {
|
|
|
109
116
|
}
|
|
110
117
|
}, 300);
|
|
111
118
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
119
|
+
if (this._isOpen) {
|
|
120
|
+
Modal._openCount = Math.max(0, (Modal._openCount || 0) - 1);
|
|
121
|
+
this._isOpen = false;
|
|
122
|
+
if (Modal._openCount === 0) {
|
|
123
|
+
document.body.style.overflow = '';
|
|
124
|
+
}
|
|
115
125
|
}
|
|
116
126
|
|
|
117
127
|
if (this.onClosed) {
|
|
@@ -140,8 +150,13 @@ class Modal {
|
|
|
140
150
|
if (this.mask) {
|
|
141
151
|
this.mask.removeEventListener('click', this._maskClickHandler);
|
|
142
152
|
}
|
|
143
|
-
|
|
144
|
-
|
|
153
|
+
// 防御性:如果 destroy 时 modal 仍处于打开状态,强制修正计数
|
|
154
|
+
if (this._isOpen) {
|
|
155
|
+
Modal._openCount = Math.max(0, (Modal._openCount || 0) - 1);
|
|
156
|
+
this._isOpen = false;
|
|
157
|
+
if (Modal._openCount === 0) {
|
|
158
|
+
document.body.style.overflow = '';
|
|
159
|
+
}
|
|
145
160
|
}
|
|
146
161
|
}
|
|
147
162
|
}
|
|
@@ -323,17 +338,4 @@ function initModals() {
|
|
|
323
338
|
|
|
324
339
|
export { Modal, initModals, initModal, cleanupModal, createModal, confirmModal, alertModal };
|
|
325
340
|
|
|
326
|
-
|
|
327
|
-
window.Modal = Modal;
|
|
328
|
-
window.initModal = initModal;
|
|
329
|
-
window.cleanupModal = cleanupModal;
|
|
330
|
-
window.initModals = initModals;
|
|
331
|
-
window.createModal = createModal;
|
|
332
|
-
window.confirmModal = confirmModal;
|
|
333
|
-
window.alertModal = alertModal;
|
|
334
|
-
|
|
335
|
-
if (window.kupolaInitializer) {
|
|
336
|
-
window.kupolaInitializer.register('modal', initModal, cleanupModal);
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
|
|
341
|
+
kupolaInitializer.register('modal', initModal, cleanupModal);
|
package/js/notification.js
CHANGED
|
@@ -72,9 +72,4 @@ const Notification = {
|
|
|
72
72
|
|
|
73
73
|
function initNotifications() {}
|
|
74
74
|
|
|
75
|
-
export { Notification, initNotifications };
|
|
76
|
-
|
|
77
|
-
if (typeof window !== 'undefined') {
|
|
78
|
-
window.Notification = Notification;
|
|
79
|
-
window.initNotifications = initNotifications;
|
|
80
|
-
}
|
|
75
|
+
export { Notification, initNotifications };
|
package/js/numberinput.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { kupolaInitializer } from './initializer.js';
|
|
2
|
+
|
|
1
3
|
class NumberInput {
|
|
2
4
|
constructor(element) {
|
|
3
5
|
this.element = element;
|
|
@@ -135,13 +137,4 @@ function initNumberInputs() {
|
|
|
135
137
|
|
|
136
138
|
export { NumberInput, initNumberInputs, initNumberInput, cleanupNumberInput };
|
|
137
139
|
|
|
138
|
-
|
|
139
|
-
window.NumberInput = NumberInput;
|
|
140
|
-
window.initNumberInput = initNumberInput;
|
|
141
|
-
window.cleanupNumberInput = cleanupNumberInput;
|
|
142
|
-
window.initNumberInputs = initNumberInputs;
|
|
143
|
-
|
|
144
|
-
if (window.kupolaInitializer) {
|
|
145
|
-
window.kupolaInitializer.register('number-input', initNumberInput, cleanupNumberInput);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
140
|
+
kupolaInitializer.register('number-input', initNumberInput, cleanupNumberInput);
|
package/js/pagination.js
CHANGED
package/js/registry.js
CHANGED
package/js/select.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { globalEvents } from './global-events.js';
|
|
2
|
+
import { kupolaInitializer } from './initializer.js';
|
|
3
|
+
|
|
1
4
|
class Select {
|
|
2
5
|
constructor(element, options = {}) {
|
|
3
6
|
this.element = element;
|
|
@@ -130,11 +133,7 @@ class Select {
|
|
|
130
133
|
}
|
|
131
134
|
};
|
|
132
135
|
|
|
133
|
-
|
|
134
|
-
this._documentClickListener = window.globalEvents.on(document, 'click', this._documentClickHandler, { scope: this.scope });
|
|
135
|
-
} else {
|
|
136
|
-
document.addEventListener('click', this._documentClickHandler);
|
|
137
|
-
}
|
|
136
|
+
this._documentClickListener = globalEvents.on(document, 'click', this._documentClickHandler, { scope: this.scope });
|
|
138
137
|
|
|
139
138
|
// Restore selected state from native select or data attributes
|
|
140
139
|
this._restoreSelectedState();
|
|
@@ -585,14 +584,4 @@ function cleanupAllSelects() {
|
|
|
585
584
|
|
|
586
585
|
export { Select, initSelect, initSelects, cleanupSelect, cleanupAllSelects };
|
|
587
586
|
|
|
588
|
-
|
|
589
|
-
window.Select = Select;
|
|
590
|
-
window.initSelect = initSelect;
|
|
591
|
-
window.initSelects = initSelects;
|
|
592
|
-
window.cleanupSelect = cleanupSelect;
|
|
593
|
-
window.cleanupAllSelects = cleanupAllSelects;
|
|
594
|
-
|
|
595
|
-
if (window.kupolaInitializer) {
|
|
596
|
-
window.kupolaInitializer.register('select', initSelect, cleanupSelect);
|
|
597
|
-
}
|
|
598
|
-
}
|
|
587
|
+
kupolaInitializer.register('select', initSelect, cleanupSelect);
|
package/js/slide-captcha.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { globalEvents } from './global-events.js';
|
|
2
|
+
import { kupolaInitializer } from './initializer.js';
|
|
3
|
+
|
|
1
4
|
class SlideCaptcha {
|
|
2
5
|
constructor(container) {
|
|
3
6
|
this.container = container;
|
|
@@ -139,17 +142,10 @@ class SlideCaptcha {
|
|
|
139
142
|
|
|
140
143
|
this.btn.addEventListener('mousedown', this._mouseDownHandler);
|
|
141
144
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
this._touchEndListener = window.globalEvents.on(document, 'touchend', this._touchEndHandler, { scope: this.scope });
|
|
147
|
-
} else {
|
|
148
|
-
document.addEventListener('mousemove', this._mouseMoveHandler);
|
|
149
|
-
document.addEventListener('mouseup', this._mouseUpHandler);
|
|
150
|
-
document.addEventListener('touchmove', this._touchMoveHandler, { passive: false });
|
|
151
|
-
document.addEventListener('touchend', this._touchEndHandler);
|
|
152
|
-
}
|
|
145
|
+
this._mouseMoveListener = globalEvents.on(document, 'mousemove', this._mouseMoveHandler, { scope: this.scope });
|
|
146
|
+
this._mouseUpListener = globalEvents.on(document, 'mouseup', this._mouseUpHandler, { scope: this.scope });
|
|
147
|
+
this._touchMoveListener = globalEvents.on(document, 'touchmove', this._touchMoveHandler, { scope: this.scope, passive: false });
|
|
148
|
+
this._touchEndListener = globalEvents.on(document, 'touchend', this._touchEndHandler, { scope: this.scope });
|
|
153
149
|
|
|
154
150
|
this.btn.addEventListener('touchstart', this._touchStartHandler, { passive: false });
|
|
155
151
|
|
|
@@ -501,13 +497,4 @@ function cleanupAllSlideCaptchas() {
|
|
|
501
497
|
|
|
502
498
|
export { SlideCaptcha, initSlideCaptchas, cleanupSlideCaptcha, cleanupAllSlideCaptchas };
|
|
503
499
|
|
|
504
|
-
|
|
505
|
-
window.SlideCaptcha = SlideCaptcha;
|
|
506
|
-
window.initSlideCaptchas = initSlideCaptchas;
|
|
507
|
-
window.cleanupSlideCaptcha = cleanupSlideCaptcha;
|
|
508
|
-
window.cleanupAllSlideCaptchas = cleanupAllSlideCaptchas;
|
|
509
|
-
|
|
510
|
-
if (window.kupolaInitializer) {
|
|
511
|
-
window.kupolaInitializer.register('slide-captcha', initSlideCaptchas, cleanupAllSlideCaptchas);
|
|
512
|
-
}
|
|
513
|
-
}
|
|
500
|
+
kupolaInitializer.register('slide-captcha', initSlideCaptchas, cleanupAllSlideCaptchas);
|
package/js/slider.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { kupolaInitializer } from './initializer.js';
|
|
2
|
+
|
|
1
3
|
class Slider {
|
|
2
4
|
constructor(element, options = {}) {
|
|
3
5
|
this.element = element;
|
|
@@ -499,13 +501,4 @@ function initSliders() {
|
|
|
499
501
|
|
|
500
502
|
export { Slider, initSlider, initSliders, cleanupSlider };
|
|
501
503
|
|
|
502
|
-
|
|
503
|
-
window.Slider = Slider;
|
|
504
|
-
window.initSlider = initSlider;
|
|
505
|
-
window.initSliders = initSliders;
|
|
506
|
-
window.cleanupSlider = cleanupSlider;
|
|
507
|
-
|
|
508
|
-
if (window.kupolaInitializer) {
|
|
509
|
-
window.kupolaInitializer.register('slider', initSlider, cleanupSlider);
|
|
510
|
-
}
|
|
511
|
-
}
|
|
504
|
+
kupolaInitializer.register('slider', initSlider, cleanupSlider);
|
package/js/statcard.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { kupolaInitializer } from './initializer.js';
|
|
2
|
+
|
|
1
3
|
class StatCard {
|
|
2
4
|
constructor(element) {
|
|
3
5
|
this.element = element;
|
|
@@ -208,14 +210,4 @@ function updateStatCard(selector, newValue) {
|
|
|
208
210
|
|
|
209
211
|
export { StatCard, initStatCards, initStatCard, cleanupStatCard, updateStatCard };
|
|
210
212
|
|
|
211
|
-
|
|
212
|
-
window.StatCard = StatCard;
|
|
213
|
-
window.initStatCard = initStatCard;
|
|
214
|
-
window.cleanupStatCard = cleanupStatCard;
|
|
215
|
-
window.initStatCards = initStatCards;
|
|
216
|
-
window.updateStatCard = updateStatCard;
|
|
217
|
-
|
|
218
|
-
if (window.kupolaInitializer) {
|
|
219
|
-
window.kupolaInitializer.register('statcard', initStatCard, cleanupStatCard);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
213
|
+
kupolaInitializer.register('statcard', initStatCard, cleanupStatCard);
|