@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/select.ts CHANGED
@@ -1,217 +1,217 @@
1
- class Select {
2
- private readonly element: HTMLSelectElement;
3
- private readonly isMultiselect: boolean;
4
-
5
- constructor(elementOrSelector: string | HTMLSelectElement) {
6
- const element = typeof elementOrSelector === 'string'
7
- ? document.querySelector<HTMLSelectElement>(elementOrSelector)
8
- : elementOrSelector;
9
-
10
- if (!element) {
11
- throw new Error(`Select: Element not found for selector "${elementOrSelector}"`);
12
- }
13
-
14
- this.element = element;
15
- const result = Select.initElement(element);
16
-
17
- if (result === null) {
18
- throw new Error(`Select: Failed to initialize select for "${elementOrSelector}"`);
19
- }
20
-
21
- this.isMultiselect = result;
22
- }
23
-
24
- public value(): string | string[] | undefined {
25
- if (!this.element) {
26
- return undefined;
27
- }
28
-
29
- const selectedValues = Array.from(this.element.options)
30
- .filter(option => option.selected)
31
- .map(option => option.value);
32
-
33
- return this.isMultiselect ? selectedValues : selectedValues[0];
34
- }
35
-
36
- public static init(elementOrSelector: string | HTMLSelectElement): boolean | null {
37
- const element = typeof elementOrSelector === 'string'
38
- ? document.querySelector<HTMLSelectElement>(elementOrSelector)
39
- : elementOrSelector;
40
-
41
- if (!element) {
42
- return null;
43
- }
44
-
45
- return Select.initElement(element);
46
- }
47
-
48
- private static initElement(element: HTMLSelectElement): boolean | null {
49
- if (!Select.transformSelect(element)) {
50
- return null;
51
- }
52
-
53
- const selectGroup = element.closest('.select-group');
54
- if (!selectGroup) {
55
- throw new Error(`Select: Parent .select-group not found for "${element}"`);
56
- }
57
-
58
- const dropdown = selectGroup.querySelector('.dropdown') as HTMLElement | null;
59
- if (!dropdown) {
60
- throw new Error(`Select: Dropdown element not found for "${element}"`);
61
- }
62
-
63
- const selected = dropdown.querySelector('.dropdown-selected') as HTMLElement | null;
64
- const options = dropdown.querySelector('.dropdown-options') as HTMLElement | null;
65
-
66
- if (!selected || !options) {
67
- throw new Error(`Select: Required dropdown elements not found for "${element}"`);
68
- }
69
-
70
- const isMulti = dropdown.dataset.multi === 'true';
71
-
72
- // Toggle dropdown on selected element click
73
- selected.addEventListener('click', () => {
74
- Select.closeAllDropdowns(dropdown);
75
- dropdown.classList.toggle('open');
76
- });
77
-
78
- // Handle option selection
79
- options.addEventListener('click', (e: Event) => {
80
- const target = e.target as HTMLElement;
81
-
82
- if (!target.classList.contains('dropdown-option')) {
83
- return;
84
- }
85
-
86
- if (isMulti) {
87
- Select.handleMultiSelect(target, options, selected, element);
88
- } else {
89
- Select.handleSingleSelect(target, options, selected, dropdown, element);
90
- }
91
- });
92
-
93
- // Close dropdown when clicking the close icon
94
- const closeIcon = options.querySelector('.dropdown-options-icon') as HTMLElement | null;
95
- if (closeIcon) {
96
- closeIcon.addEventListener('click', () => {
97
- dropdown.classList.remove('open');
98
- });
99
- }
100
-
101
- // Close dropdown when clicking outside
102
- document.addEventListener('click', (e: Event) => {
103
- if (!dropdown.contains(e.target as Node)) {
104
- dropdown.classList.remove('open');
105
- }
106
- });
107
-
108
- return isMulti;
109
- }
110
-
111
- private static closeAllDropdowns(exceptDropdown?: HTMLElement): void {
112
- document.querySelectorAll('.dropdown').forEach(dropdown => {
113
- if (dropdown !== exceptDropdown) {
114
- dropdown.classList.remove('open');
115
- }
116
- });
117
- }
118
-
119
- private static handleMultiSelect(
120
- option: HTMLElement,
121
- optionsContainer: HTMLElement,
122
- selected: HTMLElement,
123
- selectElement: HTMLSelectElement
124
- ): void {
125
- option.classList.toggle('selected');
126
-
127
- const selectedOptions = Array.from(
128
- optionsContainer.querySelectorAll('.dropdown-option.selected')
129
- ) as HTMLElement[];
130
-
131
- const values = selectedOptions.map(opt => opt.textContent?.trim() || '');
132
- selected.textContent = values.length ? values.join(', ') : 'Select options';
133
-
134
- const selectedValues = selectedOptions.map(opt => opt.dataset.value || '');
135
- Array.from(selectElement.options).forEach(opt => {
136
- opt.selected = selectedValues.includes(opt.value);
137
- });
138
- }
139
-
140
- private static handleSingleSelect(
141
- option: HTMLElement,
142
- optionsContainer: HTMLElement,
143
- selected: HTMLElement,
144
- dropdown: HTMLElement,
145
- selectElement: HTMLSelectElement
146
- ): void {
147
- optionsContainer.querySelectorAll('.dropdown-option').forEach(opt => {
148
- opt.classList.remove('selected');
149
- });
150
-
151
- option.classList.add('selected');
152
- selected.textContent = option.textContent?.trim() || '';
153
- dropdown.classList.remove('open');
154
- selectElement.value = option.dataset.value || '';
155
- }
156
-
157
- private static transformSelect(select: HTMLSelectElement): boolean {
158
- const parent = select.closest('.select-group') as HTMLElement | null;
159
-
160
- if (!parent) {
161
- return false;
162
- }
163
-
164
- const label = parent.querySelector('label');
165
- const isMulti = select.hasAttribute('multiple');
166
- const labelText = label?.textContent?.trim() || 'Select';
167
-
168
- // Create hidden wrapper for original select
169
- const hiddenWrapper = document.createElement('div');
170
- hiddenWrapper.classList.add('hidden');
171
-
172
- if (label) {
173
- hiddenWrapper.appendChild(label);
174
- }
175
- hiddenWrapper.appendChild(select);
176
-
177
- // Create dropdown structure
178
- const dropdown = document.createElement('div');
179
- dropdown.className = 'dropdown';
180
- dropdown.dataset.multi = String(isMulti);
181
-
182
- const dropdownSelected = document.createElement('div');
183
- dropdownSelected.className = 'dropdown-selected';
184
- dropdownSelected.textContent = labelText;
185
-
186
- const dropdownOptions = document.createElement('div');
187
- dropdownOptions.className = 'dropdown-options';
188
-
189
- // Add mobile menu
190
- const optionsMenu = document.createElement('div');
191
- optionsMenu.className = 'dropdown-options-menu hidden';
192
- optionsMenu.innerHTML = 'Select options<span class="dropdown-options-icon icon icon-close"></span>';
193
- dropdownOptions.appendChild(optionsMenu);
194
-
195
- // Create option elements
196
- Array.from(select.options).forEach(opt => {
197
- const optDiv = document.createElement('div');
198
- optDiv.className = 'dropdown-option';
199
- optDiv.dataset.value = opt.value;
200
- optDiv.textContent = opt.textContent;
201
- dropdownOptions.appendChild(optDiv);
202
- });
203
-
204
- // Assemble dropdown
205
- dropdown.appendChild(dropdownSelected);
206
- dropdown.appendChild(dropdownOptions);
207
-
208
- // Replace original content
209
- parent.innerHTML = '';
210
- parent.appendChild(hiddenWrapper);
211
- parent.appendChild(dropdown);
212
-
213
- return true;
214
- }
215
- }
216
-
1
+ class Select {
2
+ private readonly element: HTMLSelectElement;
3
+ private readonly isMultiselect: boolean;
4
+
5
+ constructor(elementOrSelector: string | HTMLSelectElement) {
6
+ const element = typeof elementOrSelector === 'string'
7
+ ? document.querySelector<HTMLSelectElement>(elementOrSelector)
8
+ : elementOrSelector;
9
+
10
+ if (!element) {
11
+ throw new Error(`Select: Element not found for selector "${elementOrSelector}"`);
12
+ }
13
+
14
+ this.element = element;
15
+ const result = Select.initElement(element);
16
+
17
+ if (result === null) {
18
+ throw new Error(`Select: Failed to initialize select for "${elementOrSelector}"`);
19
+ }
20
+
21
+ this.isMultiselect = result;
22
+ }
23
+
24
+ public value(): string | string[] | undefined {
25
+ if (!this.element) {
26
+ return undefined;
27
+ }
28
+
29
+ const selectedValues = Array.from(this.element.options)
30
+ .filter(option => option.selected)
31
+ .map(option => option.value);
32
+
33
+ return this.isMultiselect ? selectedValues : selectedValues[0];
34
+ }
35
+
36
+ public static init(elementOrSelector: string | HTMLSelectElement): boolean | null {
37
+ const element = typeof elementOrSelector === 'string'
38
+ ? document.querySelector<HTMLSelectElement>(elementOrSelector)
39
+ : elementOrSelector;
40
+
41
+ if (!element) {
42
+ return null;
43
+ }
44
+
45
+ return Select.initElement(element);
46
+ }
47
+
48
+ private static initElement(element: HTMLSelectElement): boolean | null {
49
+ if (!Select.transformSelect(element)) {
50
+ return null;
51
+ }
52
+
53
+ const selectGroup = element.closest('.select-group');
54
+ if (!selectGroup) {
55
+ throw new Error(`Select: Parent .select-group not found for "${element}"`);
56
+ }
57
+
58
+ const dropdown = selectGroup.querySelector('.dropdown') as HTMLElement | null;
59
+ if (!dropdown) {
60
+ throw new Error(`Select: Dropdown element not found for "${element}"`);
61
+ }
62
+
63
+ const selected = dropdown.querySelector('.dropdown-selected') as HTMLElement | null;
64
+ const options = dropdown.querySelector('.dropdown-options') as HTMLElement | null;
65
+
66
+ if (!selected || !options) {
67
+ throw new Error(`Select: Required dropdown elements not found for "${element}"`);
68
+ }
69
+
70
+ const isMulti = dropdown.dataset.multi === 'true';
71
+
72
+ // Toggle dropdown on selected element click
73
+ selected.addEventListener('click', () => {
74
+ Select.closeAllDropdowns(dropdown);
75
+ dropdown.classList.toggle('open');
76
+ });
77
+
78
+ // Handle option selection
79
+ options.addEventListener('click', (e: Event) => {
80
+ const target = e.target as HTMLElement;
81
+
82
+ if (!target.classList.contains('dropdown-option')) {
83
+ return;
84
+ }
85
+
86
+ if (isMulti) {
87
+ Select.handleMultiSelect(target, options, selected, element);
88
+ } else {
89
+ Select.handleSingleSelect(target, options, selected, dropdown, element);
90
+ }
91
+ });
92
+
93
+ // Close dropdown when clicking the close icon
94
+ const closeIcon = options.querySelector('.dropdown-options-icon') as HTMLElement | null;
95
+ if (closeIcon) {
96
+ closeIcon.addEventListener('click', () => {
97
+ dropdown.classList.remove('open');
98
+ });
99
+ }
100
+
101
+ // Close dropdown when clicking outside
102
+ document.addEventListener('click', (e: Event) => {
103
+ if (!dropdown.contains(e.target as Node)) {
104
+ dropdown.classList.remove('open');
105
+ }
106
+ });
107
+
108
+ return isMulti;
109
+ }
110
+
111
+ private static closeAllDropdowns(exceptDropdown?: HTMLElement): void {
112
+ document.querySelectorAll('.dropdown').forEach(dropdown => {
113
+ if (dropdown !== exceptDropdown) {
114
+ dropdown.classList.remove('open');
115
+ }
116
+ });
117
+ }
118
+
119
+ private static handleMultiSelect(
120
+ option: HTMLElement,
121
+ optionsContainer: HTMLElement,
122
+ selected: HTMLElement,
123
+ selectElement: HTMLSelectElement
124
+ ): void {
125
+ option.classList.toggle('selected');
126
+
127
+ const selectedOptions = Array.from(
128
+ optionsContainer.querySelectorAll('.dropdown-option.selected')
129
+ ) as HTMLElement[];
130
+
131
+ const values = selectedOptions.map(opt => opt.textContent?.trim() || '');
132
+ selected.textContent = values.length ? values.join(', ') : 'Select options';
133
+
134
+ const selectedValues = selectedOptions.map(opt => opt.dataset.value || '');
135
+ Array.from(selectElement.options).forEach(opt => {
136
+ opt.selected = selectedValues.includes(opt.value);
137
+ });
138
+ }
139
+
140
+ private static handleSingleSelect(
141
+ option: HTMLElement,
142
+ optionsContainer: HTMLElement,
143
+ selected: HTMLElement,
144
+ dropdown: HTMLElement,
145
+ selectElement: HTMLSelectElement
146
+ ): void {
147
+ optionsContainer.querySelectorAll('.dropdown-option').forEach(opt => {
148
+ opt.classList.remove('selected');
149
+ });
150
+
151
+ option.classList.add('selected');
152
+ selected.textContent = option.textContent?.trim() || '';
153
+ dropdown.classList.remove('open');
154
+ selectElement.value = option.dataset.value || '';
155
+ }
156
+
157
+ private static transformSelect(select: HTMLSelectElement): boolean {
158
+ const parent = select.closest('.select-group') as HTMLElement | null;
159
+
160
+ if (!parent) {
161
+ return false;
162
+ }
163
+
164
+ const label = parent.querySelector('label');
165
+ const isMulti = select.hasAttribute('multiple');
166
+ const labelText = label?.textContent?.trim() || 'Select';
167
+
168
+ // Create hidden wrapper for original select
169
+ const hiddenWrapper = document.createElement('div');
170
+ hiddenWrapper.classList.add('hidden');
171
+
172
+ if (label) {
173
+ hiddenWrapper.appendChild(label);
174
+ }
175
+ hiddenWrapper.appendChild(select);
176
+
177
+ // Create dropdown structure
178
+ const dropdown = document.createElement('div');
179
+ dropdown.className = 'dropdown';
180
+ dropdown.dataset.multi = String(isMulti);
181
+
182
+ const dropdownSelected = document.createElement('div');
183
+ dropdownSelected.className = 'dropdown-selected';
184
+ dropdownSelected.textContent = labelText;
185
+
186
+ const dropdownOptions = document.createElement('div');
187
+ dropdownOptions.className = 'dropdown-options';
188
+
189
+ // Add mobile menu
190
+ const optionsMenu = document.createElement('div');
191
+ optionsMenu.className = 'dropdown-options-menu hidden';
192
+ optionsMenu.innerHTML = 'Select options<span class="dropdown-options-icon icon icon-close"></span>';
193
+ dropdownOptions.appendChild(optionsMenu);
194
+
195
+ // Create option elements
196
+ Array.from(select.options).forEach(opt => {
197
+ const optDiv = document.createElement('div');
198
+ optDiv.className = 'dropdown-option';
199
+ optDiv.dataset.value = opt.value;
200
+ optDiv.textContent = opt.textContent;
201
+ dropdownOptions.appendChild(optDiv);
202
+ });
203
+
204
+ // Assemble dropdown
205
+ dropdown.appendChild(dropdownSelected);
206
+ dropdown.appendChild(dropdownOptions);
207
+
208
+ // Replace original content
209
+ parent.innerHTML = '';
210
+ parent.appendChild(hiddenWrapper);
211
+ parent.appendChild(dropdown);
212
+
213
+ return true;
214
+ }
215
+ }
216
+
217
217
  export { Select };
@@ -0,0 +1,41 @@
1
+ class SidebarNav {
2
+ constructor(containerOrSelector, options = {}) {
3
+ const container = typeof containerOrSelector === 'string'
4
+ ? document.querySelector(containerOrSelector)
5
+ : containerOrSelector;
6
+ this.opts = {
7
+ toggleSelector: options.toggleSelector ?? '.sidebar-toggle',
8
+ breakpoint: options.breakpoint ?? 768,
9
+ };
10
+ this.nav = container?.querySelector('.sidebar-nav') ?? null;
11
+ this.backdrop = container?.querySelector('.sidebar-backdrop') ?? null;
12
+ this.toggleBtn = document.querySelector(this.opts.toggleSelector);
13
+ this._onToggle = () => this.toggle();
14
+ this._onBackdrop = () => this.close();
15
+ this._onResize = () => { if (window.innerWidth > this.opts.breakpoint)
16
+ this.close(); };
17
+ this.toggleBtn?.addEventListener('click', this._onToggle);
18
+ this.backdrop?.addEventListener('click', this._onBackdrop);
19
+ window.addEventListener('resize', this._onResize);
20
+ }
21
+ open() {
22
+ this.nav?.classList.add('is-open');
23
+ this.backdrop?.classList.add('is-visible');
24
+ }
25
+ close() {
26
+ this.nav?.classList.remove('is-open');
27
+ this.backdrop?.classList.remove('is-visible');
28
+ }
29
+ toggle() {
30
+ this.nav?.classList.contains('is-open') ? this.close() : this.open();
31
+ }
32
+ isOpen() {
33
+ return this.nav?.classList.contains('is-open') ?? false;
34
+ }
35
+ destroy() {
36
+ this.toggleBtn?.removeEventListener('click', this._onToggle);
37
+ this.backdrop?.removeEventListener('click', this._onBackdrop);
38
+ window.removeEventListener('resize', this._onResize);
39
+ }
40
+ }
41
+ export { SidebarNav };
@@ -0,0 +1,66 @@
1
+ interface SidebarNavOptions {
2
+ /** Selector for the toggle button. Default: '.sidebar-toggle' */
3
+ toggleSelector?: string;
4
+ /** Breakpoint (px) above which the sidebar is always visible. Default: 768 */
5
+ breakpoint?: number;
6
+ }
7
+
8
+ class SidebarNav {
9
+ private nav: HTMLElement | null;
10
+ private backdrop: HTMLElement | null;
11
+ private toggleBtn: HTMLElement | null;
12
+ private opts: Required<SidebarNavOptions>;
13
+ private _onToggle: () => void;
14
+ private _onBackdrop: () => void;
15
+ private _onResize: () => void;
16
+
17
+ constructor(containerOrSelector: string | HTMLElement, options: SidebarNavOptions = {}) {
18
+ const container: HTMLElement | null =
19
+ typeof containerOrSelector === 'string'
20
+ ? (document.querySelector(containerOrSelector) as HTMLElement | null)
21
+ : containerOrSelector;
22
+
23
+ this.opts = {
24
+ toggleSelector: options.toggleSelector ?? '.sidebar-toggle',
25
+ breakpoint: options.breakpoint ?? 768,
26
+ };
27
+
28
+ this.nav = container?.querySelector('.sidebar-nav') ?? null;
29
+ this.backdrop = container?.querySelector('.sidebar-backdrop') ?? null;
30
+ this.toggleBtn = document.querySelector(this.opts.toggleSelector);
31
+
32
+ this._onToggle = () => this.toggle();
33
+ this._onBackdrop = () => this.close();
34
+ this._onResize = () => { if (window.innerWidth > this.opts.breakpoint) this.close(); };
35
+
36
+ this.toggleBtn?.addEventListener('click', this._onToggle);
37
+ this.backdrop?.addEventListener('click', this._onBackdrop);
38
+ window.addEventListener('resize', this._onResize);
39
+ }
40
+
41
+ open(): void {
42
+ this.nav?.classList.add('is-open');
43
+ this.backdrop?.classList.add('is-visible');
44
+ }
45
+
46
+ close(): void {
47
+ this.nav?.classList.remove('is-open');
48
+ this.backdrop?.classList.remove('is-visible');
49
+ }
50
+
51
+ toggle(): void {
52
+ this.nav?.classList.contains('is-open') ? this.close() : this.open();
53
+ }
54
+
55
+ isOpen(): boolean {
56
+ return this.nav?.classList.contains('is-open') ?? false;
57
+ }
58
+
59
+ destroy(): void {
60
+ this.toggleBtn?.removeEventListener('click', this._onToggle);
61
+ this.backdrop?.removeEventListener('click', this._onBackdrop);
62
+ window.removeEventListener('resize', this._onResize);
63
+ }
64
+ }
65
+
66
+ export { SidebarNav, SidebarNavOptions };