@dodlhuat/basix 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/README.md +266 -6
  2. package/css/accordion.scss +86 -87
  3. package/css/alert.scss +137 -137
  4. package/css/button.scss +48 -0
  5. package/css/calendar.scss +957 -0
  6. package/css/card.scss +65 -65
  7. package/css/chart.scss +270 -157
  8. package/css/chat-bubbles.scss +134 -68
  9. package/css/chips.scss +109 -19
  10. package/css/colors.scss +32 -32
  11. package/css/datepicker.scss +336 -336
  12. package/css/defaults.scss +90 -90
  13. package/css/docs.scss +529 -0
  14. package/css/editor.scss +36 -0
  15. package/css/file-uploader.scss +1 -1
  16. package/css/flyout-menu.scss +361 -361
  17. package/css/form.scss +0 -15
  18. package/css/gallery.scss +65 -6
  19. package/css/grid.scss +41 -40
  20. package/css/group-picker.scss +345 -0
  21. package/css/guitar-chords.css +250 -250
  22. package/css/icons.scss +330 -330
  23. package/css/parameters.scss +3 -3
  24. package/css/placeholder.scss +33 -33
  25. package/css/popover.scss +206 -0
  26. package/css/progress.scss +76 -32
  27. package/css/properties.scss +51 -36
  28. package/css/push-menu.scss +302 -174
  29. package/css/reset.scss +39 -39
  30. package/css/scrollbar.scss +62 -5
  31. package/css/sidebar-nav.scss +92 -0
  32. package/css/spinner.scss +65 -65
  33. package/css/stepper.scss +48 -12
  34. package/css/style.css +3155 -254
  35. package/css/style.css.map +1 -1
  36. package/css/style.min.css +1 -1
  37. package/css/style.scss +51 -45
  38. package/css/table.scss +199 -199
  39. package/css/tabs.scss +154 -123
  40. package/css/timeline.scss +83 -38
  41. package/css/timepicker.scss +100 -5
  42. package/css/toast.scss +81 -81
  43. package/css/virtual-dropdown.scss +35 -29
  44. package/js/calendar.js +532 -0
  45. package/js/calendar.ts +706 -0
  46. package/js/chart.js +573 -257
  47. package/js/chart.ts +692 -0
  48. package/js/code-viewer.js +10 -10
  49. package/js/code-viewer.ts +188 -188
  50. package/js/datepicker.ts +627 -627
  51. package/js/docs-nav.js +204 -0
  52. package/js/dropdown.ts +179 -179
  53. package/js/editor.js +50 -6
  54. package/js/editor.ts +483 -444
  55. package/js/file-uploader.js +1 -0
  56. package/js/file-uploader.ts +1 -0
  57. package/js/flyout-menu.js +14 -14
  58. package/js/flyout-menu.ts +249 -249
  59. package/js/form-builder.js +106 -106
  60. package/js/gallery.js +14 -8
  61. package/js/gallery.ts +245 -236
  62. package/js/group-picker.js +342 -0
  63. package/js/group-picker.ts +447 -0
  64. package/js/guitar-chords.js +268 -268
  65. package/js/lazy-loader.js +121 -121
  66. package/js/modal.ts +166 -166
  67. package/js/popover.js +163 -0
  68. package/js/popover.ts +219 -0
  69. package/js/position.js +108 -0
  70. package/js/position.ts +111 -0
  71. package/js/push-menu.js +113 -0
  72. package/js/push-menu.ts +284 -145
  73. package/js/request.js +50 -50
  74. package/js/scroll.ts +47 -47
  75. package/js/scrollbar.js +13 -0
  76. package/js/scrollbar.ts +324 -307
  77. package/js/select.ts +216 -216
  78. package/js/sidebar-nav.js +41 -0
  79. package/js/sidebar-nav.ts +66 -0
  80. package/js/table.ts +452 -452
  81. package/js/tabs.ts +279 -279
  82. package/js/theme.js +17 -6
  83. package/js/theme.ts +234 -224
  84. package/js/toast.ts +137 -137
  85. package/js/tooltip.js +6 -60
  86. package/js/tooltip.ts +184 -251
  87. package/js/tsconfig.json +18 -18
  88. package/js/utils.ts +83 -83
  89. package/js/virtual-dropdown.js +25 -25
  90. package/js/virtual-dropdown.ts +365 -365
  91. package/package.json +37 -39
  92. package/js/index.js +0 -816
  93. package/js/index.ts +0 -987
package/js/theme.ts CHANGED
@@ -1,225 +1,235 @@
1
- type ThemeMode = 'light' | 'dark';
2
-
3
- interface ThemeElements {
4
- toggleBtn: HTMLElement;
5
- icon: HTMLElement;
6
- status: HTMLElement | null;
7
- }
8
-
9
- class Theme {
10
- private static readonly STORAGE_KEY = 'theme';
11
- private static root: HTMLElement;
12
- private static elements: ThemeElements | null = null;
13
- private static mediaQuery: MediaQueryList | null = null;
14
-
15
- /**
16
- * Initializes the theme system with toggle functionality and system preference detection
17
- */
18
- public static init(): void {
19
- this.root = document.documentElement;
20
-
21
- // Get DOM elements
22
- const toggleBtn = document.getElementById('theme-toggle');
23
- const icon = document.getElementById('theme-icon');
24
- const status = document.getElementById('status');
25
-
26
- // Validate required elements
27
- if (!toggleBtn || !icon) {
28
- console.error('Theme toggle: missing DOM elements', { toggleBtn, icon });
29
- if (status) {
30
- status.textContent = 'Error: missing toggle elements (check IDs).';
31
- }
32
- return;
33
- }
34
-
35
- this.elements = { toggleBtn, icon, status };
36
-
37
- // Initialize media query
38
- if (window.matchMedia) {
39
- this.mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
40
- }
41
-
42
- // Apply initial theme
43
- const savedTheme = this.getSavedTheme();
44
- const systemTheme = this.getSystemTheme();
45
- const initialTheme = savedTheme || systemTheme;
46
- this.applyTheme(initialTheme);
47
-
48
- // Bind event listeners
49
- this.bindToggleClick();
50
- this.bindKeyboardShortcut();
51
- this.bindSystemThemeChange();
52
- }
53
-
54
- /**
55
- * Safely retrieves the saved theme from localStorage
56
- */
57
- private static getSavedTheme(): ThemeMode | null {
58
- try {
59
- const saved = localStorage.getItem(this.STORAGE_KEY);
60
- return saved === 'dark' || saved === 'light' ? saved : null;
61
- } catch (e) {
62
- console.warn('localStorage.getItem failed', e);
63
- return null;
64
- }
65
- }
66
-
67
- /**
68
- * Safely saves the theme to localStorage
69
- */
70
- private static saveTheme(theme: ThemeMode): void {
71
- try {
72
- localStorage.setItem(this.STORAGE_KEY, theme);
73
- } catch (e) {
74
- console.warn('localStorage.setItem failed', e);
75
- }
76
- }
77
-
78
- /**
79
- * Gets the system-preferred theme
80
- */
81
- private static getSystemTheme(): ThemeMode {
82
- return this.mediaQuery?.matches ? 'dark' : 'light';
83
- }
84
-
85
- /**
86
- * Gets the current active theme
87
- */
88
- private static getCurrentTheme(): ThemeMode {
89
- const current = this.root.getAttribute('data-theme');
90
- return current === 'dark' ? 'dark' : 'light';
91
- }
92
-
93
- /**
94
- * Applies a theme to the document
95
- */
96
- private static applyTheme(theme: ThemeMode): void {
97
- if (!this.elements) return;
98
-
99
- this.root.setAttribute('data-theme', theme);
100
-
101
- const isDark = theme === 'dark';
102
- const { toggleBtn, icon } = this.elements;
103
-
104
- // Update button state
105
- toggleBtn.setAttribute('aria-pressed', String(isDark));
106
- toggleBtn.setAttribute('aria-label', `Switch to ${isDark ? 'light' : 'dark'} mode`);
107
-
108
- // Update icon classes
109
- if (isDark) {
110
- icon.classList.remove('icon-light');
111
- icon.classList.add('icon-dark');
112
- } else {
113
- icon.classList.remove('icon-dark');
114
- icon.classList.add('icon-light');
115
- }
116
- }
117
-
118
- /**
119
- * Toggles between light and dark theme
120
- */
121
- private static toggleTheme(): void {
122
- if (!this.elements) return;
123
-
124
- try {
125
- const current = this.getCurrentTheme();
126
- const next: ThemeMode = current === 'dark' ? 'light' : 'dark';
127
-
128
- this.saveTheme(next);
129
- this.applyTheme(next);
130
- } catch (err) {
131
- console.error('Error toggling theme', err);
132
- if (this.elements.status) {
133
- this.elements.status.textContent = 'Error toggling theme (see console).';
134
- }
135
- }
136
- }
137
-
138
- /**
139
- * Binds click event to toggle button
140
- */
141
- private static bindToggleClick(): void {
142
- if (!this.elements) return;
143
-
144
- this.elements.toggleBtn.addEventListener('click', () => {
145
- this.toggleTheme();
146
- });
147
- }
148
-
149
- /**
150
- * Binds keyboard shortcut (Ctrl/Cmd+J) for theme toggle
151
- */
152
- private static bindKeyboardShortcut(): void {
153
- window.addEventListener('keydown', (ev: KeyboardEvent) => {
154
- const isMac = /Mac|iPhone|iPod|iPad/i.test(navigator.platform);
155
- const modifierPressed = isMac ? ev.metaKey : ev.ctrlKey;
156
-
157
- if (modifierPressed && ev.key.toLowerCase() === 'j') {
158
- ev.preventDefault();
159
- this.toggleTheme();
160
- }
161
- });
162
- }
163
-
164
- /**
165
- * Binds listener for system theme changes
166
- * Only applies if user hasn't explicitly saved a preference
167
- */
168
- private static bindSystemThemeChange(): void {
169
- if (!this.mediaQuery) return;
170
-
171
- const handler = (e: MediaQueryListEvent | MediaQueryList): void => {
172
- // Only apply system theme if user hasn't saved a preference
173
- if (!this.getSavedTheme()) {
174
- const matches = 'matches' in e ? e.matches : (e as MediaQueryList).matches;
175
- this.applyTheme(matches ? 'dark' : 'light');
176
- }
177
- };
178
-
179
- // Modern API
180
- if ('addEventListener' in this.mediaQuery) {
181
- this.mediaQuery.addEventListener('change', handler as (e: MediaQueryListEvent) => void);
182
- }
183
- // Legacy API (deprecated but still supported in older browsers)
184
- else if ('addListener' in this.mediaQuery) {
185
- (this.mediaQuery as any).addListener(handler);
186
- }
187
- }
188
-
189
- /**
190
- * Public API: Get the current theme
191
- */
192
- public static getTheme(): ThemeMode {
193
- return this.getCurrentTheme();
194
- }
195
-
196
- /**
197
- * Public API: Set the theme programmatically
198
- */
199
- public static setTheme(theme: ThemeMode): void {
200
- this.saveTheme(theme);
201
- this.applyTheme(theme);
202
- }
203
-
204
- /**
205
- * Public API: Reset to system preference
206
- */
207
- public static resetToSystem(): void {
208
- try {
209
- localStorage.removeItem(this.STORAGE_KEY);
210
- const systemTheme = this.getSystemTheme();
211
- this.applyTheme(systemTheme);
212
- } catch (e) {
213
- console.warn('Failed to reset theme', e);
214
- }
215
- }
216
-
217
- /**
218
- * Public API: Check if user has a saved preference
219
- */
220
- public static hasSavedPreference(): boolean {
221
- return this.getSavedTheme() !== null;
222
- }
223
- }
224
-
1
+ type ThemeMode = 'light' | 'dark';
2
+
3
+ interface ThemeElements {
4
+ toggleBtn: HTMLElement;
5
+ icon: HTMLElement;
6
+ status: HTMLElement | null;
7
+ }
8
+
9
+ class Theme {
10
+ private static readonly STORAGE_KEY = 'theme';
11
+ private static root: HTMLElement;
12
+ private static elements: ThemeElements | null = null;
13
+ private static mediaQuery: MediaQueryList | null = null;
14
+
15
+ /**
16
+ * Initializes the theme system with toggle functionality and system preference detection
17
+ */
18
+ public static init(): void {
19
+ this.root = document.documentElement;
20
+
21
+ // Get DOM elements
22
+ const toggleBtn = document.getElementById('theme-toggle');
23
+ const icon = document.getElementById('theme-icon');
24
+ const status = document.getElementById('status');
25
+
26
+ // Validate required elements
27
+ if (!toggleBtn || !icon) {
28
+ console.error('Theme toggle: missing DOM elements', { toggleBtn, icon });
29
+ if (status) {
30
+ status.textContent = 'Error: missing toggle elements (check IDs).';
31
+ }
32
+ return;
33
+ }
34
+
35
+ this.elements = { toggleBtn, icon, status };
36
+
37
+ // Initialize media query
38
+ if (window.matchMedia) {
39
+ this.mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
40
+ }
41
+
42
+ // Apply initial theme
43
+ const savedTheme = this.getSavedTheme();
44
+ const systemTheme = this.getSystemTheme();
45
+ const initialTheme = savedTheme || systemTheme;
46
+ this.applyTheme(initialTheme);
47
+
48
+ // Bind event listeners
49
+ this.bindToggleClick();
50
+ this.bindKeyboardShortcut();
51
+ this.bindSystemThemeChange();
52
+ }
53
+
54
+ /**
55
+ * Safely retrieves the saved theme from localStorage
56
+ */
57
+ private static getSavedTheme(): ThemeMode | null {
58
+ try {
59
+ const saved = localStorage.getItem(this.STORAGE_KEY);
60
+ return saved === 'dark' || saved === 'light' ? saved : null;
61
+ } catch (e) {
62
+ console.warn('localStorage.getItem failed', e);
63
+ return null;
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Safely saves the theme to localStorage
69
+ */
70
+ private static saveTheme(theme: ThemeMode): void {
71
+ try {
72
+ localStorage.setItem(this.STORAGE_KEY, theme);
73
+ } catch (e) {
74
+ console.warn('localStorage.setItem failed', e);
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Gets the system-preferred theme
80
+ */
81
+ private static getSystemTheme(): ThemeMode {
82
+ return this.mediaQuery?.matches ? 'dark' : 'light';
83
+ }
84
+
85
+ /**
86
+ * Gets the current active theme
87
+ */
88
+ private static getCurrentTheme(): ThemeMode {
89
+ const current = this.root.getAttribute('data-theme');
90
+ return current === 'dark' ? 'dark' : 'light';
91
+ }
92
+
93
+ /**
94
+ * Applies a theme to the document
95
+ */
96
+ private static applyTheme(theme: ThemeMode): void {
97
+ if (!this.elements) return;
98
+
99
+ this.root.setAttribute('data-theme', theme);
100
+
101
+ const isDark = theme === 'dark';
102
+ const { toggleBtn, icon } = this.elements;
103
+
104
+ // Update button state
105
+ toggleBtn.setAttribute('aria-pressed', String(isDark));
106
+ toggleBtn.setAttribute('aria-label', `Switch to ${isDark ? 'light' : 'dark'} mode`);
107
+
108
+ // Update icon — SVG sprite via <use> or font icon via class
109
+ const useEl = icon.querySelector('use');
110
+ if (useEl) {
111
+ const iconName = isDark ? icon.dataset.iconDark : icon.dataset.iconLight;
112
+ if (iconName) {
113
+ const existingHref = useEl.getAttribute('href') ?? '';
114
+ const basePath = existingHref.includes('#') ? existingHref.split('#')[0] : '';
115
+ useEl.setAttribute('href', `${basePath}#${iconName}`);
116
+ }
117
+ } else {
118
+ if (isDark) {
119
+ icon.classList.remove('icon-light');
120
+ icon.classList.add('icon-dark');
121
+ } else {
122
+ icon.classList.remove('icon-dark');
123
+ icon.classList.add('icon-light');
124
+ }
125
+ }
126
+ }
127
+
128
+ /**
129
+ * Toggles between light and dark theme
130
+ */
131
+ private static toggleTheme(): void {
132
+ if (!this.elements) return;
133
+
134
+ try {
135
+ const current = this.getCurrentTheme();
136
+ const next: ThemeMode = current === 'dark' ? 'light' : 'dark';
137
+
138
+ this.saveTheme(next);
139
+ this.applyTheme(next);
140
+ } catch (err) {
141
+ console.error('Error toggling theme', err);
142
+ if (this.elements.status) {
143
+ this.elements.status.textContent = 'Error toggling theme (see console).';
144
+ }
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Binds click event to toggle button
150
+ */
151
+ private static bindToggleClick(): void {
152
+ if (!this.elements) return;
153
+
154
+ this.elements.toggleBtn.addEventListener('click', () => {
155
+ this.toggleTheme();
156
+ });
157
+ }
158
+
159
+ /**
160
+ * Binds keyboard shortcut (Ctrl/Cmd+J) for theme toggle
161
+ */
162
+ private static bindKeyboardShortcut(): void {
163
+ window.addEventListener('keydown', (ev: KeyboardEvent) => {
164
+ const isMac = /Mac|iPhone|iPod|iPad/i.test(navigator.platform);
165
+ const modifierPressed = isMac ? ev.metaKey : ev.ctrlKey;
166
+
167
+ if (modifierPressed && ev.key.toLowerCase() === 'j') {
168
+ ev.preventDefault();
169
+ this.toggleTheme();
170
+ }
171
+ });
172
+ }
173
+
174
+ /**
175
+ * Binds listener for system theme changes
176
+ * Only applies if user hasn't explicitly saved a preference
177
+ */
178
+ private static bindSystemThemeChange(): void {
179
+ if (!this.mediaQuery) return;
180
+
181
+ const handler = (e: MediaQueryListEvent | MediaQueryList): void => {
182
+ // Only apply system theme if user hasn't saved a preference
183
+ if (!this.getSavedTheme()) {
184
+ const matches = 'matches' in e ? e.matches : (e as MediaQueryList).matches;
185
+ this.applyTheme(matches ? 'dark' : 'light');
186
+ }
187
+ };
188
+
189
+ // Modern API
190
+ if ('addEventListener' in this.mediaQuery) {
191
+ this.mediaQuery.addEventListener('change', handler as (e: MediaQueryListEvent) => void);
192
+ }
193
+ // Legacy API (deprecated but still supported in older browsers)
194
+ else if ('addListener' in this.mediaQuery) {
195
+ (this.mediaQuery as any).addListener(handler);
196
+ }
197
+ }
198
+
199
+ /**
200
+ * Public API: Get the current theme
201
+ */
202
+ public static getTheme(): ThemeMode {
203
+ return this.getCurrentTheme();
204
+ }
205
+
206
+ /**
207
+ * Public API: Set the theme programmatically
208
+ */
209
+ public static setTheme(theme: ThemeMode): void {
210
+ this.saveTheme(theme);
211
+ this.applyTheme(theme);
212
+ }
213
+
214
+ /**
215
+ * Public API: Reset to system preference
216
+ */
217
+ public static resetToSystem(): void {
218
+ try {
219
+ localStorage.removeItem(this.STORAGE_KEY);
220
+ const systemTheme = this.getSystemTheme();
221
+ this.applyTheme(systemTheme);
222
+ } catch (e) {
223
+ console.warn('Failed to reset theme', e);
224
+ }
225
+ }
226
+
227
+ /**
228
+ * Public API: Check if user has a saved preference
229
+ */
230
+ public static hasSavedPreference(): boolean {
231
+ return this.getSavedTheme() !== null;
232
+ }
233
+ }
234
+
225
235
  export { Theme };