@dodlhuat/basix 1.4.2 → 1.5.0
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 +55 -9
- package/css/alert.scss +9 -9
- package/css/badge.scss +5 -25
- package/css/bottom-sheet.scss +2 -6
- package/css/breadcrumb.scss +18 -9
- package/css/calendar.scss +19 -29
- package/css/carousel.scss +3 -3
- package/css/chart.scss +1 -6
- package/css/checkbox.scss +1 -1
- package/css/chips.scss +13 -23
- package/css/code-viewer.scss +2 -2
- package/css/color-picker.scss +3 -5
- package/css/context-menu.scss +3 -8
- package/css/datepicker.scss +84 -71
- package/css/defaults.scss +25 -0
- package/css/docs.scss +6 -6
- package/css/dropdown.scss +3 -8
- package/css/editor.scss +15 -18
- package/css/file-uploader.scss +6 -17
- package/css/flyout-menu.scss +5 -1
- package/css/form.scss +43 -57
- package/css/gallery.scss +15 -0
- package/css/group-picker.scss +28 -17
- package/css/icons.scss +7 -327
- package/css/lightbox.scss +7 -7
- package/css/mixins.scss +77 -0
- package/css/modal.scss +4 -8
- package/css/parameters.scss +8 -2
- package/css/placeholder.scss +2 -17
- package/css/popover.scss +2 -7
- package/css/properties.scss +0 -5
- package/css/push-menu.scss +1 -1
- package/css/range-slider.scss +7 -6
- package/css/stepper.scss +4 -3
- package/css/style.css +279 -554
- package/css/style.css.map +1 -1
- package/css/style.min.css +1 -1
- package/css/style.min.css.map +1 -1
- package/css/tabs.scss +3 -7
- package/css/timepicker.scss +3 -3
- package/css/tooltip.scss +1 -1
- package/css/typography.scss +3 -3
- package/css/virtual-dropdown.scss +12 -27
- package/js/bottom-sheet.d.ts +5 -5
- package/js/bottom-sheet.js +41 -58
- package/js/calendar.d.ts +1 -2
- package/js/calendar.js +77 -84
- package/js/carousel.d.ts +2 -1
- package/js/carousel.js +25 -16
- package/js/chart.d.ts +1 -1
- package/js/chart.js +104 -65
- package/js/code-viewer.d.ts +1 -1
- package/js/code-viewer.js +7 -18
- package/js/color-picker.d.ts +2 -2
- package/js/color-picker.js +20 -22
- package/js/context-menu.d.ts +1 -1
- package/js/context-menu.js +10 -12
- package/js/datepicker.d.ts +14 -3
- package/js/datepicker.js +180 -99
- package/js/docs-nav.js +1 -1
- package/js/dropdown.d.ts +1 -1
- package/js/dropdown.js +4 -5
- package/js/editor.d.ts +1 -1
- package/js/editor.js +30 -34
- package/js/file-uploader.d.ts +2 -9
- package/js/file-uploader.js +57 -86
- package/js/flyout-menu.d.ts +3 -3
- package/js/flyout-menu.js +20 -22
- package/js/gallery.d.ts +6 -2
- package/js/gallery.js +49 -20
- package/js/group-picker.d.ts +2 -1
- package/js/group-picker.js +30 -34
- package/js/lightbox.d.ts +5 -3
- package/js/lightbox.js +36 -31
- package/js/listeners.d.ts +7 -0
- package/js/listeners.js +14 -0
- package/js/modal.d.ts +4 -1
- package/js/modal.js +17 -22
- package/js/popover.d.ts +2 -2
- package/js/popover.js +42 -37
- package/js/position.js +3 -5
- package/js/push-menu.d.ts +8 -2
- package/js/push-menu.js +34 -23
- package/js/range-slider.d.ts +2 -2
- package/js/range-slider.js +7 -6
- package/js/scroll.js +4 -7
- package/js/scrollbar.d.ts +3 -3
- package/js/scrollbar.js +39 -42
- package/js/select.d.ts +1 -1
- package/js/select.js +20 -24
- package/js/sidebar-nav.d.ts +2 -1
- package/js/sidebar-nav.js +15 -10
- package/js/stepper.d.ts +1 -1
- package/js/stepper.js +9 -11
- package/js/table.d.ts +1 -1
- package/js/table.js +24 -23
- package/js/tabs.d.ts +1 -1
- package/js/tabs.js +10 -17
- package/js/theme.d.ts +1 -0
- package/js/theme.js +6 -15
- package/js/timepicker.d.ts +8 -6
- package/js/timepicker.js +36 -36
- package/js/toast.d.ts +4 -1
- package/js/toast.js +13 -5
- package/js/tooltip.d.ts +1 -4
- package/js/tooltip.js +14 -23
- package/js/tree.d.ts +0 -1
- package/js/tree.js +6 -11
- package/js/utils.js +7 -8
- package/js/virtual-dropdown.d.ts +1 -1
- package/js/virtual-dropdown.js +26 -28
- package/package.json +2 -1
- package/svg-icons/chevron_right.svg +1 -0
- package/svg-icons/keyboard_arrow_down.svg +1 -0
- package/css/calendar.css +0 -928
- package/css/guitar-chords.css +0 -251
- package/fonts/MaterialSymbolsOutlined.woff2 +0 -0
- package/js/form-builder.js +0 -107
- package/js/guitar-chords.js +0 -268
- package/js/lazy-loader.js +0 -121
- package/js/request.js +0 -51
package/js/popover.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { computePosition } from './position.js';
|
|
2
2
|
import { sanitizeHtml } from './utils.js';
|
|
3
|
+
import { ListenerGroup } from './listeners.js';
|
|
3
4
|
const ARROW_SIZE = 6;
|
|
4
5
|
class Popover {
|
|
5
6
|
static openPopovers = new Set();
|
|
@@ -7,12 +8,11 @@ class Popover {
|
|
|
7
8
|
trigger;
|
|
8
9
|
opts;
|
|
9
10
|
popoverEl = null;
|
|
10
|
-
_isOpen = false;
|
|
11
11
|
hoverTimer = null;
|
|
12
|
+
listeners = new ListenerGroup();
|
|
13
|
+
openListeners = null;
|
|
12
14
|
constructor(triggerEl, options) {
|
|
13
|
-
const el = typeof triggerEl === 'string'
|
|
14
|
-
? document.querySelector(triggerEl)
|
|
15
|
-
: triggerEl;
|
|
15
|
+
const el = typeof triggerEl === 'string' ? document.querySelector(triggerEl) : triggerEl;
|
|
16
16
|
if (!el)
|
|
17
17
|
throw new Error('Popover: trigger element not found');
|
|
18
18
|
this.trigger = el;
|
|
@@ -31,9 +31,11 @@ class Popover {
|
|
|
31
31
|
};
|
|
32
32
|
this.attachTrigger();
|
|
33
33
|
}
|
|
34
|
-
get isOpen() {
|
|
34
|
+
get isOpen() {
|
|
35
|
+
return this.popoverEl !== null;
|
|
36
|
+
}
|
|
35
37
|
open() {
|
|
36
|
-
if (this.
|
|
38
|
+
if (this.popoverEl)
|
|
37
39
|
return;
|
|
38
40
|
if (this.opts.triggerMode === 'click')
|
|
39
41
|
Popover.closeAll();
|
|
@@ -42,40 +44,47 @@ class Popover {
|
|
|
42
44
|
this.reposition();
|
|
43
45
|
requestAnimationFrame(() => {
|
|
44
46
|
this.popoverEl?.classList.add('is-open');
|
|
45
|
-
this._isOpen = true;
|
|
46
47
|
Popover.openPopovers.add(this);
|
|
47
48
|
this.opts.onOpen();
|
|
49
|
+
this.openListeners = new ListenerGroup();
|
|
50
|
+
const openSig = { signal: this.openListeners.signal };
|
|
48
51
|
if (this.opts.closeOnOutsideClick)
|
|
49
|
-
document.addEventListener('pointerdown', this.onOutsideClick, { capture: true });
|
|
52
|
+
document.addEventListener('pointerdown', (e) => this.onOutsideClick(e), { ...openSig, capture: true });
|
|
50
53
|
if (this.opts.closeOnEscape)
|
|
51
|
-
document.addEventListener('keydown', this.onEscape);
|
|
54
|
+
document.addEventListener('keydown', (e) => this.onEscape(e), openSig);
|
|
52
55
|
});
|
|
53
56
|
}
|
|
54
57
|
close() {
|
|
55
|
-
if (!this.
|
|
58
|
+
if (!this.popoverEl)
|
|
56
59
|
return;
|
|
57
60
|
this.popoverEl.classList.remove('is-open');
|
|
58
|
-
this._isOpen = false;
|
|
59
61
|
Popover.openPopovers.delete(this);
|
|
60
62
|
this.opts.onClose();
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
this.openListeners?.destroy();
|
|
64
|
+
this.openListeners = null;
|
|
63
65
|
this.trigger.removeAttribute('aria-expanded');
|
|
64
66
|
this.trigger.removeAttribute('aria-controls');
|
|
65
67
|
const el = this.popoverEl;
|
|
66
68
|
setTimeout(() => el.remove(), 200);
|
|
67
69
|
this.popoverEl = null;
|
|
68
70
|
}
|
|
69
|
-
toggle() {
|
|
71
|
+
toggle() {
|
|
72
|
+
if (this.popoverEl) {
|
|
73
|
+
this.close();
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
this.open();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
70
79
|
destroy() {
|
|
71
80
|
this.close();
|
|
72
|
-
this.
|
|
81
|
+
this.listeners.destroy();
|
|
73
82
|
}
|
|
74
83
|
static closeAll() {
|
|
75
|
-
Popover.openPopovers.forEach(p => p.close());
|
|
84
|
+
Popover.openPopovers.forEach((p) => p.close());
|
|
76
85
|
}
|
|
77
86
|
static initAll() {
|
|
78
|
-
document.querySelectorAll('[data-popover]').forEach(trigger => {
|
|
87
|
+
document.querySelectorAll('[data-popover]').forEach((trigger) => {
|
|
79
88
|
const sel = trigger.getAttribute('data-popover');
|
|
80
89
|
if (!sel)
|
|
81
90
|
return;
|
|
@@ -100,9 +109,7 @@ class Popover {
|
|
|
100
109
|
el.setAttribute('data-arrow', String(this.opts.arrow));
|
|
101
110
|
const hasStructure = /class="popover-(header|body|footer|menu)/.test(this.opts.content);
|
|
102
111
|
const safeContent = sanitizeHtml(this.opts.content);
|
|
103
|
-
el.innerHTML = hasStructure
|
|
104
|
-
? safeContent
|
|
105
|
-
: `<div class="popover-body">${safeContent}</div>`;
|
|
112
|
+
el.innerHTML = hasStructure ? safeContent : `<div class="popover-body">${safeContent}</div>`;
|
|
106
113
|
this.trigger.setAttribute('aria-expanded', 'true');
|
|
107
114
|
this.trigger.setAttribute('aria-controls', id);
|
|
108
115
|
return el;
|
|
@@ -123,37 +130,35 @@ class Popover {
|
|
|
123
130
|
this.popoverEl.style.left = `${left}px`;
|
|
124
131
|
this.popoverEl.style.top = `${top}px`;
|
|
125
132
|
}
|
|
126
|
-
onClick
|
|
127
|
-
|
|
133
|
+
onClick() {
|
|
134
|
+
this.toggle();
|
|
135
|
+
}
|
|
136
|
+
onMouseEnter() {
|
|
128
137
|
if (this.hoverTimer !== null)
|
|
129
138
|
clearTimeout(this.hoverTimer);
|
|
130
139
|
this.open();
|
|
131
|
-
}
|
|
132
|
-
onMouseLeave
|
|
140
|
+
}
|
|
141
|
+
onMouseLeave() {
|
|
133
142
|
this.hoverTimer = window.setTimeout(() => this.close(), 120);
|
|
134
|
-
}
|
|
135
|
-
onOutsideClick
|
|
143
|
+
}
|
|
144
|
+
onOutsideClick(e) {
|
|
136
145
|
const t = e.target;
|
|
137
146
|
if (!this.popoverEl?.contains(t) && !this.trigger.contains(t))
|
|
138
147
|
this.close();
|
|
139
|
-
}
|
|
140
|
-
onEscape
|
|
148
|
+
}
|
|
149
|
+
onEscape(e) {
|
|
141
150
|
if (e.key === 'Escape')
|
|
142
151
|
this.close();
|
|
143
|
-
}
|
|
152
|
+
}
|
|
144
153
|
attachTrigger() {
|
|
154
|
+
const sig = { signal: this.listeners.signal };
|
|
145
155
|
if (this.opts.triggerMode === 'click') {
|
|
146
|
-
this.trigger.addEventListener('click', this.onClick);
|
|
156
|
+
this.trigger.addEventListener('click', () => this.onClick(), sig);
|
|
147
157
|
}
|
|
148
158
|
else {
|
|
149
|
-
this.trigger.addEventListener('mouseenter', this.onMouseEnter);
|
|
150
|
-
this.trigger.addEventListener('mouseleave', this.onMouseLeave);
|
|
159
|
+
this.trigger.addEventListener('mouseenter', () => this.onMouseEnter(), sig);
|
|
160
|
+
this.trigger.addEventListener('mouseleave', () => this.onMouseLeave(), sig);
|
|
151
161
|
}
|
|
152
162
|
}
|
|
153
|
-
detachTrigger() {
|
|
154
|
-
this.trigger.removeEventListener('click', this.onClick);
|
|
155
|
-
this.trigger.removeEventListener('mouseenter', this.onMouseEnter);
|
|
156
|
-
this.trigger.removeEventListener('mouseleave', this.onMouseLeave);
|
|
157
|
-
}
|
|
158
163
|
}
|
|
159
164
|
export { Popover };
|
package/js/position.js
CHANGED
|
@@ -13,7 +13,7 @@ function bestPlacement(trigger, floating, offset) {
|
|
|
13
13
|
return 'right';
|
|
14
14
|
if (space.left >= floating.width)
|
|
15
15
|
return 'left';
|
|
16
|
-
return
|
|
16
|
+
return Object.entries(space).sort((a, b) => b[1] - a[1])[0][0];
|
|
17
17
|
}
|
|
18
18
|
function maybeFlip(placement, trigger, floating, offset) {
|
|
19
19
|
const fits = {
|
|
@@ -23,15 +23,13 @@ function maybeFlip(placement, trigger, floating, offset) {
|
|
|
23
23
|
right: window.innerWidth - trigger.right - offset >= floating.width,
|
|
24
24
|
};
|
|
25
25
|
const opp = { top: 'bottom', bottom: 'top', left: 'right', right: 'left' };
|
|
26
|
-
return
|
|
26
|
+
return !fits[placement] && fits[opp[placement]] ? opp[placement] : placement;
|
|
27
27
|
}
|
|
28
28
|
function computePosition(trigger, floating, opts) {
|
|
29
29
|
const offset = opts.offset ?? 8;
|
|
30
30
|
const margin = opts.margin ?? 8;
|
|
31
31
|
const align = opts.align ?? 'center';
|
|
32
|
-
const placement = opts.placement === 'auto'
|
|
33
|
-
? bestPlacement(trigger, floating, offset)
|
|
34
|
-
: maybeFlip(opts.placement, trigger, floating, offset);
|
|
32
|
+
const placement = opts.placement === 'auto' ? bestPlacement(trigger, floating, offset) : maybeFlip(opts.placement, trigger, floating, offset);
|
|
35
33
|
let left = 0, top = 0;
|
|
36
34
|
switch (placement) {
|
|
37
35
|
case 'top':
|
package/js/push-menu.d.ts
CHANGED
|
@@ -6,11 +6,17 @@ interface PushMenuElements {
|
|
|
6
6
|
controlIcon: HTMLElement | null;
|
|
7
7
|
backdrop: HTMLElement | null;
|
|
8
8
|
}
|
|
9
|
+
interface PushMenuOptions {
|
|
10
|
+
iconBasePath?: string;
|
|
11
|
+
}
|
|
9
12
|
declare class PushMenu {
|
|
13
|
+
private static iconBasePath;
|
|
10
14
|
private static elements;
|
|
11
15
|
private static initialized;
|
|
12
16
|
private static panelStack;
|
|
13
|
-
static
|
|
17
|
+
private static listeners;
|
|
18
|
+
private static clickNavListeners;
|
|
19
|
+
static init(options?: PushMenuOptions): void;
|
|
14
20
|
private static buildPanels;
|
|
15
21
|
private static extractSubPanels;
|
|
16
22
|
static openPanel(panel: HTMLElement): void;
|
|
@@ -26,4 +32,4 @@ declare class PushMenu {
|
|
|
26
32
|
static destroy(): void;
|
|
27
33
|
static refresh(): void;
|
|
28
34
|
}
|
|
29
|
-
export { PushMenu, type PushMenuElements };
|
|
35
|
+
export { PushMenu, type PushMenuElements, type PushMenuOptions };
|
package/js/push-menu.js
CHANGED
|
@@ -1,26 +1,32 @@
|
|
|
1
|
+
import { ListenerGroup } from './listeners.js';
|
|
1
2
|
class PushMenu {
|
|
3
|
+
static iconBasePath = 'svg-icons/';
|
|
2
4
|
static elements = {
|
|
3
5
|
navigation: null,
|
|
4
6
|
content: null,
|
|
5
7
|
menu: null,
|
|
6
8
|
header: null,
|
|
7
9
|
controlIcon: null,
|
|
8
|
-
backdrop: null
|
|
10
|
+
backdrop: null,
|
|
9
11
|
};
|
|
10
12
|
static initialized = false;
|
|
11
13
|
static panelStack = [];
|
|
12
|
-
static
|
|
14
|
+
static listeners = new ListenerGroup();
|
|
15
|
+
static clickNavListeners = null;
|
|
16
|
+
static init(options = {}) {
|
|
13
17
|
if (this.initialized) {
|
|
14
18
|
console.warn('PushMenu: Already initialized');
|
|
15
19
|
return;
|
|
16
20
|
}
|
|
21
|
+
this.iconBasePath = options.iconBasePath ?? 'svg-icons/';
|
|
17
22
|
this.refresh();
|
|
18
23
|
if (!this.elements.navigation || !this.elements.content) {
|
|
19
24
|
throw new Error('PushMenu: Required elements not found (.navigation, .push-content)');
|
|
20
25
|
}
|
|
21
26
|
this.buildPanels();
|
|
22
|
-
this.
|
|
23
|
-
this.elements.
|
|
27
|
+
const sig = { signal: this.listeners.signal };
|
|
28
|
+
this.elements.navigation.addEventListener('change', () => this.handleNavigationChange(), sig);
|
|
29
|
+
this.elements.backdrop?.addEventListener('click', () => this.handleBackdropClick(), sig);
|
|
24
30
|
this.initialized = true;
|
|
25
31
|
}
|
|
26
32
|
static buildPanels() {
|
|
@@ -56,7 +62,7 @@ class PushMenu {
|
|
|
56
62
|
const backBtn = document.createElement('button');
|
|
57
63
|
backBtn.classList.add('push-menu-back');
|
|
58
64
|
backBtn.setAttribute('aria-label', 'Back');
|
|
59
|
-
backBtn.innerHTML = `<
|
|
65
|
+
backBtn.innerHTML = `<svg class="icon-svg" aria-hidden="true"><use href="${PushMenu.iconBasePath}icons.svg#chevron_left"/></svg>`;
|
|
60
66
|
header.addEventListener('click', () => PushMenu.goBack());
|
|
61
67
|
const titleEl = document.createElement('span');
|
|
62
68
|
titleEl.classList.add('push-menu-panel-title');
|
|
@@ -72,7 +78,7 @@ class PushMenu {
|
|
|
72
78
|
const chevron = document.createElement('span');
|
|
73
79
|
chevron.classList.add('push-menu-chevron');
|
|
74
80
|
chevron.setAttribute('aria-hidden', 'true');
|
|
75
|
-
chevron.innerHTML = `<
|
|
81
|
+
chevron.innerHTML = `<svg class="icon-svg" aria-hidden="true"><use href="${PushMenu.iconBasePath}icons.svg#chevron_right"/></svg>`;
|
|
76
82
|
trigger.appendChild(chevron);
|
|
77
83
|
if (parentAnchor) {
|
|
78
84
|
parentAnchor.replaceWith(trigger);
|
|
@@ -117,17 +123,19 @@ class PushMenu {
|
|
|
117
123
|
}
|
|
118
124
|
}, 300);
|
|
119
125
|
}
|
|
120
|
-
static handleNavigationChange
|
|
126
|
+
static handleNavigationChange() {
|
|
121
127
|
const isPushed = this.elements.content?.classList.contains('pushed') ?? false;
|
|
122
128
|
if (!isPushed) {
|
|
123
|
-
this.
|
|
129
|
+
this.clickNavListeners = new ListenerGroup();
|
|
130
|
+
this.elements.content?.addEventListener('click', () => this.clickNav(), { signal: this.clickNavListeners.signal });
|
|
124
131
|
}
|
|
125
132
|
else {
|
|
126
|
-
this.
|
|
133
|
+
this.clickNavListeners?.destroy();
|
|
134
|
+
this.clickNavListeners = null;
|
|
127
135
|
this.resetPanels();
|
|
128
136
|
}
|
|
129
137
|
this.pushToggle();
|
|
130
|
-
}
|
|
138
|
+
}
|
|
131
139
|
static pushToggle() {
|
|
132
140
|
if (!this.elements.content || !this.elements.menu) {
|
|
133
141
|
throw new Error('PushMenu: Required elements not found (.push-content, .push-menu)');
|
|
@@ -138,24 +146,27 @@ class PushMenu {
|
|
|
138
146
|
this.elements.header?.classList.toggle('pushed', !isPushed);
|
|
139
147
|
this.elements.backdrop?.classList.toggle('pushed', !isPushed);
|
|
140
148
|
if (this.elements.controlIcon) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
149
|
+
const iconName = isPushed ? 'menu' : 'menu_open';
|
|
150
|
+
const useEl = this.elements.controlIcon.querySelector('use');
|
|
151
|
+
if (useEl) {
|
|
152
|
+
const existingHref = useEl.getAttribute('href') ?? '';
|
|
153
|
+
const basePath = existingHref.includes('#') ? existingHref.split('#')[0] : PushMenu.iconBasePath + 'icons.svg';
|
|
154
|
+
useEl.setAttribute('href', `${basePath}#${iconName}`);
|
|
144
155
|
}
|
|
145
156
|
else {
|
|
146
|
-
this.elements.controlIcon.classList.
|
|
147
|
-
this.elements.controlIcon.classList.
|
|
157
|
+
this.elements.controlIcon.classList.remove('icon-menu_open', 'icon-menu');
|
|
158
|
+
this.elements.controlIcon.classList.add(`icon-${iconName}`);
|
|
148
159
|
}
|
|
149
160
|
}
|
|
150
161
|
}
|
|
151
|
-
static clickNav
|
|
162
|
+
static clickNav() {
|
|
152
163
|
PushMenu.elements.navigation.click();
|
|
153
|
-
}
|
|
154
|
-
static handleBackdropClick
|
|
164
|
+
}
|
|
165
|
+
static handleBackdropClick() {
|
|
155
166
|
if (PushMenu.isOpen()) {
|
|
156
167
|
PushMenu.elements.navigation.click();
|
|
157
168
|
}
|
|
158
|
-
}
|
|
169
|
+
}
|
|
159
170
|
static open() {
|
|
160
171
|
if (!this.elements.content?.classList.contains('pushed')) {
|
|
161
172
|
this.pushToggle();
|
|
@@ -172,9 +183,9 @@ class PushMenu {
|
|
|
172
183
|
static destroy() {
|
|
173
184
|
if (!this.initialized)
|
|
174
185
|
return;
|
|
175
|
-
this.
|
|
176
|
-
this.
|
|
177
|
-
this.
|
|
186
|
+
this.listeners.reset();
|
|
187
|
+
this.clickNavListeners?.destroy();
|
|
188
|
+
this.clickNavListeners = null;
|
|
178
189
|
this.close();
|
|
179
190
|
this.elements = {
|
|
180
191
|
navigation: null,
|
|
@@ -182,7 +193,7 @@ class PushMenu {
|
|
|
182
193
|
menu: null,
|
|
183
194
|
header: null,
|
|
184
195
|
controlIcon: null,
|
|
185
|
-
backdrop: null
|
|
196
|
+
backdrop: null,
|
|
186
197
|
};
|
|
187
198
|
this.panelStack = [];
|
|
188
199
|
this.initialized = false;
|
package/js/range-slider.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
declare class RangeSlider {
|
|
2
2
|
private readonly input;
|
|
3
|
-
private
|
|
3
|
+
private listeners;
|
|
4
4
|
constructor(input: HTMLInputElement);
|
|
5
5
|
static initAll(selector?: string): void;
|
|
6
6
|
private update;
|
|
@@ -12,7 +12,7 @@ declare class RangeSliderRange {
|
|
|
12
12
|
private readonly endInput;
|
|
13
13
|
private readonly fill;
|
|
14
14
|
private readonly fillCreatedByUs;
|
|
15
|
-
private
|
|
15
|
+
private listeners;
|
|
16
16
|
constructor(container: HTMLElement);
|
|
17
17
|
static initAll(selector?: string): void;
|
|
18
18
|
values(): [number, number];
|
package/js/range-slider.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { ListenerGroup } from './listeners.js';
|
|
1
2
|
class RangeSlider {
|
|
2
3
|
input;
|
|
3
|
-
|
|
4
|
+
listeners = new ListenerGroup();
|
|
4
5
|
constructor(input) {
|
|
5
6
|
this.input = input;
|
|
6
7
|
this.update();
|
|
7
|
-
this.input.addEventListener('input', () => this.update(), { signal: this.
|
|
8
|
+
this.input.addEventListener('input', () => this.update(), { signal: this.listeners.signal });
|
|
8
9
|
}
|
|
9
10
|
static initAll(selector = '.range-slider input[type="range"]') {
|
|
10
11
|
document.querySelectorAll(selector).forEach((input) => {
|
|
@@ -18,7 +19,7 @@ class RangeSlider {
|
|
|
18
19
|
this.input.style.setProperty('--range-fill', `${pct}%`);
|
|
19
20
|
}
|
|
20
21
|
destroy() {
|
|
21
|
-
this.
|
|
22
|
+
this.listeners.destroy();
|
|
22
23
|
this.input.style.removeProperty('--range-fill');
|
|
23
24
|
}
|
|
24
25
|
}
|
|
@@ -28,7 +29,7 @@ class RangeSliderRange {
|
|
|
28
29
|
endInput;
|
|
29
30
|
fill;
|
|
30
31
|
fillCreatedByUs;
|
|
31
|
-
|
|
32
|
+
listeners = new ListenerGroup();
|
|
32
33
|
constructor(container) {
|
|
33
34
|
const inputs = container.querySelectorAll('input[type="range"]');
|
|
34
35
|
if (inputs.length !== 2) {
|
|
@@ -45,7 +46,7 @@ class RangeSliderRange {
|
|
|
45
46
|
container.insertBefore(this.fill, container.firstChild);
|
|
46
47
|
}
|
|
47
48
|
this.update();
|
|
48
|
-
const signal = this.
|
|
49
|
+
const signal = this.listeners.signal;
|
|
49
50
|
this.startInput.addEventListener('input', () => this.handleInput(this.startInput), { signal });
|
|
50
51
|
this.endInput.addEventListener('input', () => this.handleInput(this.endInput), { signal });
|
|
51
52
|
}
|
|
@@ -75,7 +76,7 @@ class RangeSliderRange {
|
|
|
75
76
|
this.container.style.setProperty('--range-end', `${endPct}%`);
|
|
76
77
|
}
|
|
77
78
|
destroy() {
|
|
78
|
-
this.
|
|
79
|
+
this.listeners.destroy();
|
|
79
80
|
this.container.style.removeProperty('--range-start');
|
|
80
81
|
this.container.style.removeProperty('--range-end');
|
|
81
82
|
if (this.fillCreatedByUs) {
|
package/js/scroll.js
CHANGED
|
@@ -4,14 +4,11 @@ class Scroll {
|
|
|
4
4
|
const offset = fixedHeader ? fixedHeader.offsetHeight : 0;
|
|
5
5
|
const settings = {
|
|
6
6
|
behavior: 'smooth',
|
|
7
|
-
offset
|
|
7
|
+
offset,
|
|
8
8
|
block: 'start',
|
|
9
|
-
...options
|
|
9
|
+
...options,
|
|
10
10
|
};
|
|
11
|
-
|
|
12
|
-
if (typeof target === 'string') {
|
|
13
|
-
el = document.querySelector(target);
|
|
14
|
-
}
|
|
11
|
+
const el = typeof target === 'string' ? document.querySelector(target) : target;
|
|
15
12
|
if (!el)
|
|
16
13
|
return;
|
|
17
14
|
const rect = el.getBoundingClientRect();
|
|
@@ -19,7 +16,7 @@ class Scroll {
|
|
|
19
16
|
const offsetTop = rect.top + scrollTop - settings.offset;
|
|
20
17
|
window.scrollTo({
|
|
21
18
|
top: offsetTop,
|
|
22
|
-
behavior: settings.behavior
|
|
19
|
+
behavior: settings.behavior,
|
|
23
20
|
});
|
|
24
21
|
}
|
|
25
22
|
}
|
package/js/scrollbar.d.ts
CHANGED
|
@@ -9,19 +9,19 @@ declare class Scrollbar {
|
|
|
9
9
|
private static activeInstance;
|
|
10
10
|
private static globalListenersInstalled;
|
|
11
11
|
private static instanceCount;
|
|
12
|
-
private static
|
|
12
|
+
private static globalListeners;
|
|
13
13
|
private readonly container;
|
|
14
14
|
private readonly viewport;
|
|
15
15
|
private readonly content;
|
|
16
16
|
private readonly track;
|
|
17
17
|
private readonly thumb;
|
|
18
18
|
private readonly MIN_THUMB_HEIGHT;
|
|
19
|
-
private readonly
|
|
19
|
+
private readonly resizeObserver;
|
|
20
20
|
private dragging;
|
|
21
21
|
private activePointerId;
|
|
22
22
|
private startPointerY;
|
|
23
23
|
private startThumbTop;
|
|
24
|
-
private
|
|
24
|
+
private listeners;
|
|
25
25
|
private constructor();
|
|
26
26
|
private getRequiredElements;
|
|
27
27
|
private getMinThumbHeight;
|
package/js/scrollbar.js
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
|
+
import { ListenerGroup } from './listeners.js';
|
|
1
2
|
class Scrollbar {
|
|
2
3
|
static instances = new WeakMap();
|
|
3
4
|
static activeInstance = null;
|
|
4
5
|
static globalListenersInstalled = false;
|
|
5
6
|
static instanceCount = 0;
|
|
6
|
-
static
|
|
7
|
+
static globalListeners = null;
|
|
7
8
|
container;
|
|
8
9
|
viewport;
|
|
9
10
|
content;
|
|
10
11
|
track;
|
|
11
12
|
thumb;
|
|
12
13
|
MIN_THUMB_HEIGHT;
|
|
13
|
-
|
|
14
|
+
resizeObserver;
|
|
14
15
|
dragging = false;
|
|
15
16
|
activePointerId = null;
|
|
16
17
|
startPointerY = 0;
|
|
17
18
|
startThumbTop = 0;
|
|
18
|
-
|
|
19
|
+
listeners = new ListenerGroup();
|
|
19
20
|
constructor(container) {
|
|
20
21
|
this.container = container;
|
|
21
22
|
const elements = this.getRequiredElements(container);
|
|
@@ -24,14 +25,14 @@ class Scrollbar {
|
|
|
24
25
|
this.track = elements.track;
|
|
25
26
|
this.thumb = elements.thumb;
|
|
26
27
|
this.MIN_THUMB_HEIGHT = this.getMinThumbHeight();
|
|
27
|
-
this.
|
|
28
|
+
this.resizeObserver = new ResizeObserver(() => this.updateThumb());
|
|
28
29
|
this.attachEventListeners();
|
|
29
30
|
Scrollbar.instances.set(container, this);
|
|
30
31
|
Scrollbar.instanceCount++;
|
|
31
32
|
if (!Scrollbar.globalListenersInstalled) {
|
|
32
33
|
Scrollbar.installGlobalListeners();
|
|
33
34
|
}
|
|
34
|
-
requestAnimationFrame(this.updateThumb);
|
|
35
|
+
requestAnimationFrame(() => this.updateThumb());
|
|
35
36
|
}
|
|
36
37
|
getRequiredElements(container) {
|
|
37
38
|
const viewport = container.querySelector('.viewport');
|
|
@@ -44,39 +45,37 @@ class Scrollbar {
|
|
|
44
45
|
return { viewport, content, track, thumb };
|
|
45
46
|
}
|
|
46
47
|
getMinThumbHeight() {
|
|
47
|
-
const cssValue = getComputedStyle(document.documentElement)
|
|
48
|
-
.getPropertyValue('--thumb-min')
|
|
49
|
-
.trim();
|
|
48
|
+
const cssValue = getComputedStyle(document.documentElement).getPropertyValue('--thumb-min').trim();
|
|
50
49
|
const parsed = parseInt(cssValue, 10);
|
|
51
50
|
const defaultMin = 28;
|
|
52
51
|
const absoluteMin = 16;
|
|
53
52
|
return Math.max(absoluteMin, parsed || defaultMin);
|
|
54
53
|
}
|
|
55
54
|
static installGlobalListeners() {
|
|
56
|
-
const
|
|
57
|
-
Scrollbar.
|
|
55
|
+
const listeners = new ListenerGroup();
|
|
56
|
+
Scrollbar.globalListeners = listeners;
|
|
58
57
|
document.addEventListener('pointermove', (e) => {
|
|
59
58
|
Scrollbar.activeInstance?.handlePointerMove(e);
|
|
60
|
-
}, { passive: false, signal:
|
|
59
|
+
}, { passive: false, signal: listeners.signal });
|
|
61
60
|
document.addEventListener('pointerup', (e) => {
|
|
62
61
|
Scrollbar.activeInstance?.handlePointerUp(e);
|
|
63
|
-
}, { signal:
|
|
62
|
+
}, { signal: listeners.signal });
|
|
64
63
|
document.addEventListener('pointercancel', (e) => {
|
|
65
64
|
Scrollbar.activeInstance?.handlePointerUp(e);
|
|
66
|
-
}, { signal:
|
|
65
|
+
}, { signal: listeners.signal });
|
|
67
66
|
Scrollbar.globalListenersInstalled = true;
|
|
68
67
|
}
|
|
69
68
|
attachEventListeners() {
|
|
70
|
-
const sig = { signal: this.
|
|
71
|
-
this.viewport.addEventListener('scroll', this.updateThumb, { passive: true
|
|
72
|
-
this.thumb.addEventListener('pointerdown', this.handleThumbPointerDown, sig);
|
|
73
|
-
this.track.addEventListener('click', this.handleTrackClick, sig);
|
|
74
|
-
this.container.addEventListener('wheel', this.handleContainerWheel, { passive: false
|
|
75
|
-
window.addEventListener('resize', this.updateThumb, sig);
|
|
76
|
-
this.
|
|
77
|
-
this.
|
|
78
|
-
}
|
|
79
|
-
updateThumb
|
|
69
|
+
const sig = { signal: this.listeners.signal };
|
|
70
|
+
this.viewport.addEventListener('scroll', () => this.updateThumb(), { ...sig, passive: true });
|
|
71
|
+
this.thumb.addEventListener('pointerdown', (e) => this.handleThumbPointerDown(e), sig);
|
|
72
|
+
this.track.addEventListener('click', (e) => this.handleTrackClick(e), sig);
|
|
73
|
+
this.container.addEventListener('wheel', (e) => this.handleContainerWheel(e), { ...sig, passive: false });
|
|
74
|
+
window.addEventListener('resize', () => this.updateThumb(), sig);
|
|
75
|
+
this.resizeObserver.observe(this.viewport);
|
|
76
|
+
this.resizeObserver.observe(this.content);
|
|
77
|
+
}
|
|
78
|
+
updateThumb() {
|
|
80
79
|
const viewportHeight = this.viewport.clientHeight;
|
|
81
80
|
const contentHeight = this.content.scrollHeight;
|
|
82
81
|
const trackHeight = this.track.clientHeight;
|
|
@@ -93,8 +92,8 @@ class Scrollbar {
|
|
|
93
92
|
const scrollRatio = this.viewport.scrollTop / (maxScroll || 1);
|
|
94
93
|
const thumbTop = scrollRatio * (maxThumbTop || 0);
|
|
95
94
|
this.thumb.style.top = `${thumbTop}px`;
|
|
96
|
-
}
|
|
97
|
-
handleThumbPointerDown
|
|
95
|
+
}
|
|
96
|
+
handleThumbPointerDown(e) {
|
|
98
97
|
e.preventDefault();
|
|
99
98
|
this.dragging = true;
|
|
100
99
|
this.activePointerId = e.pointerId;
|
|
@@ -110,8 +109,8 @@ class Scrollbar {
|
|
|
110
109
|
const trackRect = this.track.getBoundingClientRect();
|
|
111
110
|
this.startThumbTop = thumbRect.top - trackRect.top;
|
|
112
111
|
document.body.style.userSelect = 'none';
|
|
113
|
-
}
|
|
114
|
-
handlePointerMove
|
|
112
|
+
}
|
|
113
|
+
handlePointerMove(e) {
|
|
115
114
|
if (!this.dragging || this.activePointerId !== e.pointerId) {
|
|
116
115
|
return;
|
|
117
116
|
}
|
|
@@ -127,8 +126,8 @@ class Scrollbar {
|
|
|
127
126
|
const maxScroll = contentHeight - viewportHeight;
|
|
128
127
|
const scrollRatio = newThumbTop / (maxThumbTop || 1);
|
|
129
128
|
this.viewport.scrollTop = scrollRatio * (maxScroll || 0);
|
|
130
|
-
}
|
|
131
|
-
handlePointerUp
|
|
129
|
+
}
|
|
130
|
+
handlePointerUp(e) {
|
|
132
131
|
if (!this.dragging || this.activePointerId !== e.pointerId) {
|
|
133
132
|
return;
|
|
134
133
|
}
|
|
@@ -142,8 +141,8 @@ class Scrollbar {
|
|
|
142
141
|
this.activePointerId = null;
|
|
143
142
|
Scrollbar.activeInstance = null;
|
|
144
143
|
document.body.style.userSelect = '';
|
|
145
|
-
}
|
|
146
|
-
handleTrackClick
|
|
144
|
+
}
|
|
145
|
+
handleTrackClick(e) {
|
|
147
146
|
if (e.target === this.thumb) {
|
|
148
147
|
return;
|
|
149
148
|
}
|
|
@@ -160,8 +159,8 @@ class Scrollbar {
|
|
|
160
159
|
const scrollRatio = clampedThumbTop / (maxThumbTop || 1);
|
|
161
160
|
const scrollTop = scrollRatio * (maxScroll || 0);
|
|
162
161
|
this.viewport.scrollTo({ top: scrollTop, behavior: 'smooth' });
|
|
163
|
-
}
|
|
164
|
-
handleContainerWheel
|
|
162
|
+
}
|
|
163
|
+
handleContainerWheel(e) {
|
|
165
164
|
const { scrollTop, scrollHeight, clientHeight } = this.viewport;
|
|
166
165
|
const scrollable = scrollHeight > clientHeight;
|
|
167
166
|
const atTop = scrollTop === 0 && e.deltaY < 0;
|
|
@@ -170,25 +169,23 @@ class Scrollbar {
|
|
|
170
169
|
e.preventDefault();
|
|
171
170
|
}
|
|
172
171
|
this.viewport.scrollTop += e.deltaY;
|
|
173
|
-
}
|
|
172
|
+
}
|
|
174
173
|
destroy() {
|
|
175
|
-
this.
|
|
176
|
-
this.
|
|
174
|
+
this.listeners.destroy();
|
|
175
|
+
this.resizeObserver.disconnect();
|
|
177
176
|
Scrollbar.instances.delete(this.container);
|
|
178
177
|
if (Scrollbar.activeInstance === this) {
|
|
179
178
|
Scrollbar.activeInstance = null;
|
|
180
179
|
}
|
|
181
180
|
Scrollbar.instanceCount--;
|
|
182
181
|
if (Scrollbar.instanceCount === 0) {
|
|
183
|
-
Scrollbar.
|
|
184
|
-
Scrollbar.
|
|
182
|
+
Scrollbar.globalListeners?.destroy();
|
|
183
|
+
Scrollbar.globalListeners = null;
|
|
185
184
|
Scrollbar.globalListenersInstalled = false;
|
|
186
185
|
}
|
|
187
186
|
}
|
|
188
187
|
static create(elementOrSelector) {
|
|
189
|
-
const container = typeof elementOrSelector === 'string'
|
|
190
|
-
? document.querySelector(elementOrSelector)
|
|
191
|
-
: elementOrSelector;
|
|
188
|
+
const container = typeof elementOrSelector === 'string' ? document.querySelector(elementOrSelector) : elementOrSelector;
|
|
192
189
|
if (!container) {
|
|
193
190
|
throw new Error(`Scrollbar: Element not found for selector "${elementOrSelector}"`);
|
|
194
191
|
}
|
|
@@ -199,7 +196,7 @@ class Scrollbar {
|
|
|
199
196
|
}
|
|
200
197
|
static initAll(selector) {
|
|
201
198
|
const containers = document.querySelectorAll(selector);
|
|
202
|
-
return Array.from(containers).map(container => Scrollbar.create(container));
|
|
199
|
+
return Array.from(containers).map((container) => Scrollbar.create(container));
|
|
203
200
|
}
|
|
204
201
|
static initOne(elementOrSelector) {
|
|
205
202
|
return Scrollbar.create(elementOrSelector);
|
package/js/select.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ declare class Select {
|
|
|
2
2
|
private readonly element;
|
|
3
3
|
private readonly isMultiselect;
|
|
4
4
|
private readonly dropdown;
|
|
5
|
-
private
|
|
5
|
+
private listeners;
|
|
6
6
|
constructor(elementOrSelector: string | HTMLSelectElement);
|
|
7
7
|
destroy(): void;
|
|
8
8
|
value(): string | string[];
|