@dodlhuat/basix 1.3.5 → 1.4.1
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 +92 -7
- package/css/checkbox.scss +15 -2
- package/css/color-picker.scss +278 -0
- package/css/datepicker.scss +5 -3
- package/css/push-menu.scss +7 -0
- package/css/stepper.scss +1 -1
- package/css/style.css +291 -6
- package/css/style.css.map +1 -1
- package/css/style.min.css +1 -1
- package/css/style.min.css.map +1 -1
- package/css/style.scss +1 -0
- package/css/table.scss +33 -0
- package/js/bottom-sheet.d.ts +0 -2
- package/js/bottom-sheet.js +0 -2
- package/js/calendar.d.ts +9 -17
- package/js/calendar.js +4 -7
- package/js/carousel.d.ts +0 -2
- package/js/carousel.js +1 -3
- package/js/chart.d.ts +6 -14
- package/js/chart.js +3 -5
- package/js/code-viewer.d.ts +2 -1
- package/js/code-viewer.js +8 -2
- package/js/color-picker.d.ts +50 -0
- package/js/color-picker.js +291 -0
- package/js/context-menu.d.ts +0 -3
- package/js/context-menu.js +0 -3
- package/js/datepicker.d.ts +0 -4
- package/js/datepicker.js +0 -1
- package/js/docs-nav.js +1 -0
- package/js/dropdown.d.ts +1 -4
- package/js/dropdown.js +0 -1
- package/js/editor.d.ts +0 -4
- package/js/editor.js +3 -5
- package/js/file-uploader.d.ts +0 -4
- package/js/file-uploader.js +0 -1
- package/js/flyout-menu.d.ts +0 -2
- package/js/flyout-menu.js +0 -1
- package/js/gallery.d.ts +1 -4
- package/js/gallery.js +18 -23
- package/js/group-picker.d.ts +0 -5
- package/js/group-picker.js +6 -8
- package/js/lightbox.d.ts +1 -4
- package/js/lightbox.js +6 -10
- package/js/modal.d.ts +0 -2
- package/js/modal.js +0 -1
- package/js/popover.d.ts +0 -3
- package/js/popover.js +0 -2
- package/js/position.d.ts +0 -13
- package/js/position.js +0 -12
- package/js/push-menu.d.ts +0 -3
- package/js/push-menu.js +6 -11
- package/js/range-slider.d.ts +0 -1
- package/js/range-slider.js +2 -3
- package/js/scroll.d.ts +0 -2
- package/js/scroll.js +5 -6
- package/js/scrollbar.d.ts +2 -10
- package/js/scrollbar.js +25 -42
- package/js/select.d.ts +2 -3
- package/js/select.js +6 -9
- package/js/sidebar-nav.d.ts +4 -15
- package/js/sidebar-nav.js +21 -35
- package/js/stepper.d.ts +5 -2
- package/js/stepper.js +42 -6
- package/js/table.d.ts +1 -56
- package/js/table.js +4 -56
- package/js/tabs.d.ts +1 -32
- package/js/tabs.js +7 -39
- package/js/theme.d.ts +0 -44
- package/js/theme.js +0 -44
- package/js/timepicker.d.ts +1 -4
- package/js/timepicker.js +1 -2
- package/js/toast.d.ts +0 -2
- package/js/toast.js +0 -1
- package/js/tooltip.d.ts +0 -4
- package/js/tooltip.js +0 -1
- package/js/tree.d.ts +0 -3
- package/js/tree.js +9 -11
- package/js/utils.d.ts +0 -10
- package/js/utils.js +2 -42
- package/js/virtual-dropdown.d.ts +3 -5
- package/js/virtual-dropdown.js +17 -66
- package/package.json +6 -2
package/js/tabs.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
/** Tabbed content component with horizontal/vertical layouts and keyboard navigation. */
|
|
2
1
|
class Tabs {
|
|
3
2
|
container;
|
|
4
3
|
options;
|
|
5
4
|
tabItems;
|
|
6
5
|
tabPanels;
|
|
7
6
|
currentTab;
|
|
7
|
+
abortController = new AbortController();
|
|
8
8
|
constructor(elementOrSelector, options = {}) {
|
|
9
9
|
const element = typeof elementOrSelector === 'string'
|
|
10
10
|
? document.querySelector(elementOrSelector)
|
|
@@ -13,11 +13,11 @@ class Tabs {
|
|
|
13
13
|
throw new Error(`Tabs: Element not found for selector "${elementOrSelector}"`);
|
|
14
14
|
}
|
|
15
15
|
this.container = element;
|
|
16
|
-
const layout = options.layout
|
|
16
|
+
const layout = options.layout ?? 'horizontal';
|
|
17
17
|
this.options = {
|
|
18
18
|
layout,
|
|
19
19
|
defaultTab: options.defaultTab ?? 0,
|
|
20
|
-
menuPos: options.menuPos
|
|
20
|
+
menuPos: options.menuPos ?? (layout === 'vertical' ? 'left' : 'top'),
|
|
21
21
|
onChange: options.onChange
|
|
22
22
|
};
|
|
23
23
|
this.currentTab = this.options.defaultTab;
|
|
@@ -25,9 +25,6 @@ class Tabs {
|
|
|
25
25
|
this.tabPanels = this.container.querySelectorAll('.tab-panel');
|
|
26
26
|
this.init();
|
|
27
27
|
}
|
|
28
|
-
/**
|
|
29
|
-
* Initializes the tabs component
|
|
30
|
-
*/
|
|
31
28
|
init() {
|
|
32
29
|
if (this.options.layout === 'vertical') {
|
|
33
30
|
this.container.classList.add('tabs-vertical');
|
|
@@ -48,19 +45,17 @@ class Tabs {
|
|
|
48
45
|
this.bindEvents();
|
|
49
46
|
this.activateTab(this.options.defaultTab);
|
|
50
47
|
}
|
|
51
|
-
/**
|
|
52
|
-
* Binds click events to tab items
|
|
53
|
-
*/
|
|
54
48
|
bindEvents() {
|
|
49
|
+
const sig = { signal: this.abortController.signal };
|
|
55
50
|
this.tabItems.forEach((item, index) => {
|
|
56
51
|
item.addEventListener('click', (e) => {
|
|
57
52
|
e.preventDefault();
|
|
58
53
|
this.activateTab(index);
|
|
59
|
-
});
|
|
54
|
+
}, sig);
|
|
60
55
|
item.addEventListener('keydown', (e) => {
|
|
61
56
|
const keyEvent = e;
|
|
62
57
|
this.handleKeyboardNavigation(keyEvent, index);
|
|
63
|
-
});
|
|
58
|
+
}, sig);
|
|
64
59
|
item.setAttribute('role', 'tab');
|
|
65
60
|
item.setAttribute('tabindex', index === this.options.defaultTab ? '0' : '-1');
|
|
66
61
|
item.setAttribute('aria-selected', index === this.options.defaultTab ? 'true' : 'false');
|
|
@@ -70,9 +65,6 @@ class Tabs {
|
|
|
70
65
|
panel.setAttribute('aria-hidden', index === this.options.defaultTab ? 'false' : 'true');
|
|
71
66
|
});
|
|
72
67
|
}
|
|
73
|
-
/**
|
|
74
|
-
* Handles keyboard navigation (Arrow keys, Home, End)
|
|
75
|
-
*/
|
|
76
68
|
handleKeyboardNavigation(e, currentIndex) {
|
|
77
69
|
let newIndex = currentIndex;
|
|
78
70
|
const isVertical = this.options.layout === 'vertical';
|
|
@@ -117,9 +109,6 @@ class Tabs {
|
|
|
117
109
|
this.tabItems[newIndex].focus();
|
|
118
110
|
}
|
|
119
111
|
}
|
|
120
|
-
/**
|
|
121
|
-
* Activates a tab by index
|
|
122
|
-
*/
|
|
123
112
|
activateTab(index) {
|
|
124
113
|
if (index < 0 || index >= this.tabItems.length) {
|
|
125
114
|
console.warn(`Invalid tab index: ${index}`);
|
|
@@ -145,30 +134,18 @@ class Tabs {
|
|
|
145
134
|
this.options.onChange(index);
|
|
146
135
|
}
|
|
147
136
|
}
|
|
148
|
-
/**
|
|
149
|
-
* Public API: Programmatically activate a tab
|
|
150
|
-
*/
|
|
151
137
|
goToTab(index) {
|
|
152
138
|
this.activateTab(index);
|
|
153
139
|
if (this.tabItems[index]) {
|
|
154
140
|
this.tabItems[index].focus();
|
|
155
141
|
}
|
|
156
142
|
}
|
|
157
|
-
/**
|
|
158
|
-
* Public API: Get the currently active tab index
|
|
159
|
-
*/
|
|
160
143
|
getCurrentTab() {
|
|
161
144
|
return this.currentTab;
|
|
162
145
|
}
|
|
163
|
-
/**
|
|
164
|
-
* Public API: Get the total number of tabs
|
|
165
|
-
*/
|
|
166
146
|
getTabCount() {
|
|
167
147
|
return this.tabItems.length;
|
|
168
148
|
}
|
|
169
|
-
/**
|
|
170
|
-
* Public API: Enable a tab
|
|
171
|
-
*/
|
|
172
149
|
enableTab(index) {
|
|
173
150
|
if (index < 0 || index >= this.tabItems.length)
|
|
174
151
|
return;
|
|
@@ -177,9 +154,6 @@ class Tabs {
|
|
|
177
154
|
tab.removeAttribute('aria-disabled');
|
|
178
155
|
tab.style.pointerEvents = '';
|
|
179
156
|
}
|
|
180
|
-
/**
|
|
181
|
-
* Public API: Disable a tab
|
|
182
|
-
*/
|
|
183
157
|
disableTab(index) {
|
|
184
158
|
if (index < 0 || index >= this.tabItems.length)
|
|
185
159
|
return;
|
|
@@ -194,14 +168,8 @@ class Tabs {
|
|
|
194
168
|
}
|
|
195
169
|
}
|
|
196
170
|
}
|
|
197
|
-
/**
|
|
198
|
-
* Public API: Destroy the tabs instance and clean up
|
|
199
|
-
*/
|
|
200
171
|
destroy() {
|
|
201
|
-
this.
|
|
202
|
-
const newItem = item.cloneNode(true);
|
|
203
|
-
item.parentNode?.replaceChild(newItem, item);
|
|
204
|
-
});
|
|
172
|
+
this.abortController.abort();
|
|
205
173
|
this.container.classList.remove('tabs-vertical');
|
|
206
174
|
this.tabItems.forEach((item) => {
|
|
207
175
|
item.removeAttribute('role');
|
package/js/theme.d.ts
CHANGED
|
@@ -1,66 +1,22 @@
|
|
|
1
1
|
type ThemeMode = 'light' | 'dark';
|
|
2
|
-
/** Static class for managing light/dark theme switching with system preference and localStorage persistence. */
|
|
3
2
|
declare class Theme {
|
|
4
3
|
private static readonly STORAGE_KEY;
|
|
5
4
|
private static root;
|
|
6
5
|
private static elements;
|
|
7
6
|
private static mediaQuery;
|
|
8
|
-
/**
|
|
9
|
-
* Initializes the theme system with toggle functionality and system preference detection
|
|
10
|
-
*/
|
|
11
7
|
static init(): void;
|
|
12
|
-
/**
|
|
13
|
-
* Safely retrieves the saved theme from localStorage
|
|
14
|
-
*/
|
|
15
8
|
private static getSavedTheme;
|
|
16
|
-
/**
|
|
17
|
-
* Safely saves the theme to localStorage
|
|
18
|
-
*/
|
|
19
9
|
private static saveTheme;
|
|
20
|
-
/**
|
|
21
|
-
* Gets the system-preferred theme
|
|
22
|
-
*/
|
|
23
10
|
private static getSystemTheme;
|
|
24
|
-
/**
|
|
25
|
-
* Gets the current active theme
|
|
26
|
-
*/
|
|
27
11
|
private static getCurrentTheme;
|
|
28
|
-
/**
|
|
29
|
-
* Applies a theme to the document
|
|
30
|
-
*/
|
|
31
12
|
private static applyTheme;
|
|
32
|
-
/**
|
|
33
|
-
* Toggles between light and dark theme
|
|
34
|
-
*/
|
|
35
13
|
private static toggleTheme;
|
|
36
|
-
/**
|
|
37
|
-
* Binds click event to toggle button
|
|
38
|
-
*/
|
|
39
14
|
private static bindToggleClick;
|
|
40
|
-
/**
|
|
41
|
-
* Binds keyboard shortcut (Ctrl/Cmd+J) for theme toggle
|
|
42
|
-
*/
|
|
43
15
|
private static bindKeyboardShortcut;
|
|
44
|
-
/**
|
|
45
|
-
* Binds listener for system theme changes
|
|
46
|
-
* Only applies if user hasn't explicitly saved a preference
|
|
47
|
-
*/
|
|
48
16
|
private static bindSystemThemeChange;
|
|
49
|
-
/**
|
|
50
|
-
* Public API: Get the current theme
|
|
51
|
-
*/
|
|
52
17
|
static getTheme(): ThemeMode;
|
|
53
|
-
/**
|
|
54
|
-
* Public API: Set the theme programmatically
|
|
55
|
-
*/
|
|
56
18
|
static setTheme(theme: ThemeMode): void;
|
|
57
|
-
/**
|
|
58
|
-
* Public API: Reset to system preference
|
|
59
|
-
*/
|
|
60
19
|
static resetToSystem(): void;
|
|
61
|
-
/**
|
|
62
|
-
* Public API: Check if user has a saved preference
|
|
63
|
-
*/
|
|
64
20
|
static hasSavedPreference(): boolean;
|
|
65
21
|
}
|
|
66
22
|
export { Theme };
|
package/js/theme.js
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
/** Static class for managing light/dark theme switching with system preference and localStorage persistence. */
|
|
2
1
|
class Theme {
|
|
3
2
|
static STORAGE_KEY = 'theme';
|
|
4
3
|
static root;
|
|
5
4
|
static elements = null;
|
|
6
5
|
static mediaQuery = null;
|
|
7
|
-
/**
|
|
8
|
-
* Initializes the theme system with toggle functionality and system preference detection
|
|
9
|
-
*/
|
|
10
6
|
static init() {
|
|
11
7
|
this.root = document.documentElement;
|
|
12
8
|
const toggleBtn = document.getElementById('theme-toggle');
|
|
@@ -31,9 +27,6 @@ class Theme {
|
|
|
31
27
|
this.bindKeyboardShortcut();
|
|
32
28
|
this.bindSystemThemeChange();
|
|
33
29
|
}
|
|
34
|
-
/**
|
|
35
|
-
* Safely retrieves the saved theme from localStorage
|
|
36
|
-
*/
|
|
37
30
|
static getSavedTheme() {
|
|
38
31
|
try {
|
|
39
32
|
const saved = localStorage.getItem(this.STORAGE_KEY);
|
|
@@ -44,9 +37,6 @@ class Theme {
|
|
|
44
37
|
return null;
|
|
45
38
|
}
|
|
46
39
|
}
|
|
47
|
-
/**
|
|
48
|
-
* Safely saves the theme to localStorage
|
|
49
|
-
*/
|
|
50
40
|
static saveTheme(theme) {
|
|
51
41
|
try {
|
|
52
42
|
localStorage.setItem(this.STORAGE_KEY, theme);
|
|
@@ -55,22 +45,13 @@ class Theme {
|
|
|
55
45
|
console.warn('localStorage.setItem failed', e);
|
|
56
46
|
}
|
|
57
47
|
}
|
|
58
|
-
/**
|
|
59
|
-
* Gets the system-preferred theme
|
|
60
|
-
*/
|
|
61
48
|
static getSystemTheme() {
|
|
62
49
|
return this.mediaQuery?.matches ? 'dark' : 'light';
|
|
63
50
|
}
|
|
64
|
-
/**
|
|
65
|
-
* Gets the current active theme
|
|
66
|
-
*/
|
|
67
51
|
static getCurrentTheme() {
|
|
68
52
|
const current = this.root.getAttribute('data-theme');
|
|
69
53
|
return current === 'dark' ? 'dark' : 'light';
|
|
70
54
|
}
|
|
71
|
-
/**
|
|
72
|
-
* Applies a theme to the document
|
|
73
|
-
*/
|
|
74
55
|
static applyTheme(theme) {
|
|
75
56
|
if (!this.elements)
|
|
76
57
|
return;
|
|
@@ -99,9 +80,6 @@ class Theme {
|
|
|
99
80
|
}
|
|
100
81
|
}
|
|
101
82
|
}
|
|
102
|
-
/**
|
|
103
|
-
* Toggles between light and dark theme
|
|
104
|
-
*/
|
|
105
83
|
static toggleTheme() {
|
|
106
84
|
if (!this.elements)
|
|
107
85
|
return;
|
|
@@ -118,9 +96,6 @@ class Theme {
|
|
|
118
96
|
}
|
|
119
97
|
}
|
|
120
98
|
}
|
|
121
|
-
/**
|
|
122
|
-
* Binds click event to toggle button
|
|
123
|
-
*/
|
|
124
99
|
static bindToggleClick() {
|
|
125
100
|
if (!this.elements)
|
|
126
101
|
return;
|
|
@@ -128,9 +103,6 @@ class Theme {
|
|
|
128
103
|
this.toggleTheme();
|
|
129
104
|
});
|
|
130
105
|
}
|
|
131
|
-
/**
|
|
132
|
-
* Binds keyboard shortcut (Ctrl/Cmd+J) for theme toggle
|
|
133
|
-
*/
|
|
134
106
|
static bindKeyboardShortcut() {
|
|
135
107
|
window.addEventListener('keydown', (ev) => {
|
|
136
108
|
const isMac = /Mac|iPhone|iPod|iPad/i.test(navigator.platform);
|
|
@@ -141,10 +113,6 @@ class Theme {
|
|
|
141
113
|
}
|
|
142
114
|
});
|
|
143
115
|
}
|
|
144
|
-
/**
|
|
145
|
-
* Binds listener for system theme changes
|
|
146
|
-
* Only applies if user hasn't explicitly saved a preference
|
|
147
|
-
*/
|
|
148
116
|
static bindSystemThemeChange() {
|
|
149
117
|
if (!this.mediaQuery)
|
|
150
118
|
return;
|
|
@@ -161,22 +129,13 @@ class Theme {
|
|
|
161
129
|
this.mediaQuery.addListener(handler);
|
|
162
130
|
}
|
|
163
131
|
}
|
|
164
|
-
/**
|
|
165
|
-
* Public API: Get the current theme
|
|
166
|
-
*/
|
|
167
132
|
static getTheme() {
|
|
168
133
|
return this.getCurrentTheme();
|
|
169
134
|
}
|
|
170
|
-
/**
|
|
171
|
-
* Public API: Set the theme programmatically
|
|
172
|
-
*/
|
|
173
135
|
static setTheme(theme) {
|
|
174
136
|
this.saveTheme(theme);
|
|
175
137
|
this.applyTheme(theme);
|
|
176
138
|
}
|
|
177
|
-
/**
|
|
178
|
-
* Public API: Reset to system preference
|
|
179
|
-
*/
|
|
180
139
|
static resetToSystem() {
|
|
181
140
|
try {
|
|
182
141
|
localStorage.removeItem(this.STORAGE_KEY);
|
|
@@ -187,9 +146,6 @@ class Theme {
|
|
|
187
146
|
console.warn('Failed to reset theme', e);
|
|
188
147
|
}
|
|
189
148
|
}
|
|
190
|
-
/**
|
|
191
|
-
* Public API: Check if user has a saved preference
|
|
192
|
-
*/
|
|
193
149
|
static hasSavedPreference() {
|
|
194
150
|
return this.getSavedTheme() !== null;
|
|
195
151
|
}
|
package/js/timepicker.d.ts
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
/** A start/end time pair as HH:MM strings. */
|
|
2
1
|
interface TimeSpan {
|
|
3
2
|
start: string;
|
|
4
3
|
end: string;
|
|
5
4
|
}
|
|
6
|
-
/** Configuration options for a TimeSpanPicker instance. */
|
|
7
5
|
interface TimeSpanPickerOptions {
|
|
8
6
|
onChange?: (start: string, end: string) => void;
|
|
9
7
|
defaultStart?: string;
|
|
10
8
|
defaultEnd?: string;
|
|
11
9
|
fromString?: string;
|
|
12
|
-
|
|
10
|
+
toLabel?: string;
|
|
13
11
|
}
|
|
14
|
-
/** Interactive time-range picker with a draggable bar and dual time inputs. */
|
|
15
12
|
declare class TimeSpanPicker {
|
|
16
13
|
private container;
|
|
17
14
|
private startTimeInput;
|
package/js/timepicker.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/** Interactive time-range picker with a draggable bar and dual time inputs. */
|
|
2
1
|
class TimeSpanPicker {
|
|
3
2
|
container;
|
|
4
3
|
startTimeInput;
|
|
@@ -27,7 +26,7 @@ class TimeSpanPicker {
|
|
|
27
26
|
this.onChange = options?.onChange;
|
|
28
27
|
this.uid = `tsp-${Math.random().toString(36).slice(2, 9)}`;
|
|
29
28
|
this.fromString = options?.fromString ?? 'From';
|
|
30
|
-
this.toLabel = options?.
|
|
29
|
+
this.toLabel = options?.toLabel ?? 'To';
|
|
31
30
|
this.render();
|
|
32
31
|
this.startTimeInput = this.queryEl('.timespan-start');
|
|
33
32
|
this.endTimeInput = this.queryEl('.timespan-end');
|
package/js/toast.d.ts
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
type ToastType = 'success' | 'error' | 'warning' | 'info';
|
|
2
|
-
/** Options for creating a Toast notification. */
|
|
3
2
|
interface ToastOptions {
|
|
4
3
|
content: string;
|
|
5
4
|
header?: string;
|
|
6
5
|
type?: ToastType;
|
|
7
6
|
closeable?: boolean;
|
|
8
7
|
}
|
|
9
|
-
/** Dismissible notification banner with optional auto-hide timer and progress bar. */
|
|
10
8
|
declare class Toast {
|
|
11
9
|
private readonly content;
|
|
12
10
|
private readonly header;
|
package/js/toast.js
CHANGED
package/js/tooltip.d.ts
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
/** Configuration options for a Tooltip instance. */
|
|
2
1
|
interface TooltipOptions {
|
|
3
2
|
position?: 'top' | 'bottom' | 'left' | 'right' | 'auto';
|
|
4
3
|
offset?: number;
|
|
5
4
|
delay?: number;
|
|
6
5
|
className?: string;
|
|
7
|
-
/** Set to true when content is trusted HTML (e.g. from data-tooltip-id).
|
|
8
|
-
* Defaults to false — content is treated as plain text and escaped. */
|
|
9
6
|
isHtml?: boolean;
|
|
10
7
|
}
|
|
11
|
-
/** Lightweight tooltip that positions itself relative to a trigger element. */
|
|
12
8
|
declare class Tooltip {
|
|
13
9
|
private static activeTooltip;
|
|
14
10
|
private static idCounter;
|
package/js/tooltip.js
CHANGED
package/js/tree.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
type NodeType = 'file' | 'folder';
|
|
2
|
-
/** Configuration options for a TreeComponent instance. */
|
|
3
2
|
interface TreeOptions {
|
|
4
3
|
onSelect?: (node: TreeNode) => void;
|
|
5
4
|
}
|
|
6
|
-
/** Represents a single node in a tree structure, either a file or folder. */
|
|
7
5
|
declare class TreeNode {
|
|
8
6
|
label: string;
|
|
9
7
|
type: NodeType;
|
|
@@ -14,7 +12,6 @@ declare class TreeNode {
|
|
|
14
12
|
childrenContainer: HTMLUListElement | null;
|
|
15
13
|
constructor(label: string, type?: NodeType, children?: TreeNode[]);
|
|
16
14
|
}
|
|
17
|
-
/** Renders an interactive collapsible tree view from a list of TreeNode objects. */
|
|
18
15
|
declare class TreeComponent {
|
|
19
16
|
private container;
|
|
20
17
|
private data;
|
package/js/tree.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/** Represents a single node in a tree structure, either a file or folder. */
|
|
2
1
|
class TreeNode {
|
|
3
2
|
label;
|
|
4
3
|
type;
|
|
@@ -17,7 +16,6 @@ class TreeNode {
|
|
|
17
16
|
this.childrenContainer = null;
|
|
18
17
|
}
|
|
19
18
|
}
|
|
20
|
-
/** Renders an interactive collapsible tree view from a list of TreeNode objects. */
|
|
21
19
|
class TreeComponent {
|
|
22
20
|
container;
|
|
23
21
|
data;
|
|
@@ -81,18 +79,18 @@ class TreeComponent {
|
|
|
81
79
|
iconDiv.className = 'tree-icon';
|
|
82
80
|
if (type === 'folder') {
|
|
83
81
|
iconDiv.innerHTML = `
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
<svg class="chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
83
|
+
<path d="M9 18l6-6-6-6" stroke-linecap="round" stroke-linejoin="round"/>
|
|
84
|
+
</svg>
|
|
85
|
+
`;
|
|
88
86
|
}
|
|
89
87
|
else {
|
|
90
88
|
iconDiv.innerHTML = `
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
89
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
90
|
+
<path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z" stroke-linecap="round" stroke-linejoin="round"/>
|
|
91
|
+
<path d="M13 2v7h7" stroke-linecap="round" stroke-linejoin="round"/>
|
|
92
|
+
</svg>
|
|
93
|
+
`;
|
|
96
94
|
}
|
|
97
95
|
return iconDiv;
|
|
98
96
|
}
|
package/js/utils.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/** Shape of the `utils` helper object. */
|
|
2
1
|
interface Utils {
|
|
3
2
|
ready(fn: () => void): void;
|
|
4
3
|
value(element: HTMLElement): string;
|
|
@@ -8,15 +7,6 @@ interface Utils {
|
|
|
8
7
|
isHidden(element: HTMLElement): boolean;
|
|
9
8
|
}
|
|
10
9
|
declare const utils: Utils;
|
|
11
|
-
/**
|
|
12
|
-
* Escape a plain-text string so it is safe to inject into innerHTML.
|
|
13
|
-
* Use this whenever inserting user-controlled strings into HTML templates.
|
|
14
|
-
*/
|
|
15
10
|
declare function escapeHtml(text: string): string;
|
|
16
|
-
/**
|
|
17
|
-
* Sanitize an HTML string by removing dangerous elements and attributes
|
|
18
|
-
* (script, iframe, on* handlers, javascript: hrefs) while preserving safe markup.
|
|
19
|
-
* Use this when a component intentionally accepts rich HTML from callers.
|
|
20
|
-
*/
|
|
21
11
|
declare function sanitizeHtml(html: string): string;
|
|
22
12
|
export { utils, escapeHtml, sanitizeHtml };
|
package/js/utils.js
CHANGED
|
@@ -1,22 +1,12 @@
|
|
|
1
1
|
const utils = {
|
|
2
|
-
/**
|
|
3
|
-
* Execute a function when the DOM is ready
|
|
4
|
-
* @param fn - Callback function to execute
|
|
5
|
-
*/
|
|
6
2
|
ready(fn) {
|
|
7
|
-
if (document.readyState ===
|
|
3
|
+
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
|
8
4
|
setTimeout(fn, 1);
|
|
9
5
|
}
|
|
10
6
|
else {
|
|
11
|
-
document.addEventListener(
|
|
7
|
+
document.addEventListener('DOMContentLoaded', fn);
|
|
12
8
|
}
|
|
13
9
|
},
|
|
14
|
-
/**
|
|
15
|
-
* Get the value of an element from various sources
|
|
16
|
-
* Priority: value attribute > data-value attribute > innerText
|
|
17
|
-
* @param element - HTML element to get value from
|
|
18
|
-
* @returns The element's value as a string
|
|
19
|
-
*/
|
|
20
10
|
value(element) {
|
|
21
11
|
if (element.hasAttribute('value')) {
|
|
22
12
|
return element.getAttribute('value') || '';
|
|
@@ -26,57 +16,27 @@ const utils = {
|
|
|
26
16
|
}
|
|
27
17
|
return element.innerText;
|
|
28
18
|
},
|
|
29
|
-
/**
|
|
30
|
-
* Get the text content of an element
|
|
31
|
-
* @param element - HTML element to get text from
|
|
32
|
-
* @returns The element's inner text
|
|
33
|
-
*/
|
|
34
19
|
text(element) {
|
|
35
20
|
return element.innerText;
|
|
36
21
|
},
|
|
37
|
-
/**
|
|
38
|
-
* Get an attribute value from an element
|
|
39
|
-
* @param element - HTML element to get attribute from
|
|
40
|
-
* @param attribute - Name of the attribute to retrieve
|
|
41
|
-
* @returns The attribute value or undefined if not present
|
|
42
|
-
*/
|
|
43
22
|
attribute(element, attribute) {
|
|
44
23
|
if (element.hasAttribute(attribute)) {
|
|
45
24
|
return element.getAttribute(attribute) || undefined;
|
|
46
25
|
}
|
|
47
26
|
return undefined;
|
|
48
27
|
},
|
|
49
|
-
/**
|
|
50
|
-
* Check if an element is a NodeList
|
|
51
|
-
* @param element - Element or NodeList to check
|
|
52
|
-
* @returns True if the element is a NodeList
|
|
53
|
-
*/
|
|
54
28
|
isList(element) {
|
|
55
29
|
return NodeList.prototype.isPrototypeOf(element);
|
|
56
30
|
},
|
|
57
|
-
/**
|
|
58
|
-
* Check if an element is hidden
|
|
59
|
-
* @param element - HTML element to check
|
|
60
|
-
* @returns True if the element is hidden
|
|
61
|
-
*/
|
|
62
31
|
isHidden(element) {
|
|
63
32
|
return element.offsetParent === null;
|
|
64
33
|
}
|
|
65
34
|
};
|
|
66
|
-
/**
|
|
67
|
-
* Escape a plain-text string so it is safe to inject into innerHTML.
|
|
68
|
-
* Use this whenever inserting user-controlled strings into HTML templates.
|
|
69
|
-
*/
|
|
70
35
|
function escapeHtml(text) {
|
|
71
36
|
const div = document.createElement('div');
|
|
72
37
|
div.textContent = text;
|
|
73
38
|
return div.innerHTML;
|
|
74
39
|
}
|
|
75
|
-
/**
|
|
76
|
-
* Sanitize an HTML string by removing dangerous elements and attributes
|
|
77
|
-
* (script, iframe, on* handlers, javascript: hrefs) while preserving safe markup.
|
|
78
|
-
* Use this when a component intentionally accepts rich HTML from callers.
|
|
79
|
-
*/
|
|
80
40
|
function sanitizeHtml(html) {
|
|
81
41
|
const parser = new DOMParser();
|
|
82
42
|
const doc = parser.parseFromString(html, 'text/html');
|
package/js/virtual-dropdown.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
/** A single selectable option for a VirtualDropdown. */
|
|
2
1
|
interface DropdownOption {
|
|
3
2
|
label: string;
|
|
4
3
|
value: string | number;
|
|
5
4
|
}
|
|
6
|
-
/** Configuration for a VirtualDropdown instance. */
|
|
7
5
|
interface VirtualDropdownConfig {
|
|
8
6
|
container: string | HTMLElement;
|
|
9
7
|
options: DropdownOption[];
|
|
@@ -14,7 +12,6 @@ interface VirtualDropdownConfig {
|
|
|
14
12
|
itemHeight?: number;
|
|
15
13
|
onSelect?: (selectedValues: Array<string | number>) => void;
|
|
16
14
|
}
|
|
17
|
-
/** Virtualised dropdown that renders only visible items for performance with large option lists. */
|
|
18
15
|
declare class VirtualDropdown {
|
|
19
16
|
private readonly container;
|
|
20
17
|
private readonly options;
|
|
@@ -37,7 +34,7 @@ declare class VirtualDropdown {
|
|
|
37
34
|
private filteredOptions;
|
|
38
35
|
private isOpen;
|
|
39
36
|
private scrollTop;
|
|
40
|
-
private
|
|
37
|
+
private abortController;
|
|
41
38
|
constructor(config: VirtualDropdownConfig);
|
|
42
39
|
private init;
|
|
43
40
|
private renderBase;
|
|
@@ -55,4 +52,5 @@ declare class VirtualDropdown {
|
|
|
55
52
|
clearSelection(): void;
|
|
56
53
|
destroy(): void;
|
|
57
54
|
}
|
|
58
|
-
export { VirtualDropdown
|
|
55
|
+
export { VirtualDropdown };
|
|
56
|
+
export type { DropdownOption, VirtualDropdownConfig };
|