@dodlhuat/basix 1.3.2 → 1.3.3

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 (118) hide show
  1. package/README.md +13 -7
  2. package/css/accordion.scss +0 -5
  3. package/css/badge.scss +1 -6
  4. package/css/bottom-sheet.scss +3 -8
  5. package/css/breadcrumb.scss +6 -15
  6. package/css/button.scss +2 -1
  7. package/css/calendar.scss +0 -54
  8. package/css/card.scss +0 -5
  9. package/css/carousel.scss +0 -3
  10. package/css/chart.scss +0 -25
  11. package/css/chat-bubbles.scss +0 -15
  12. package/css/checkbox.scss +3 -2
  13. package/css/chips.scss +3 -7
  14. package/css/code-viewer.scss +1 -5
  15. package/css/context-menu.scss +4 -6
  16. package/css/datepicker.scss +4 -7
  17. package/css/docs.scss +0 -4
  18. package/css/dropdown.scss +1 -1
  19. package/css/editor.scss +1 -23
  20. package/css/file-uploader.scss +2 -2
  21. package/css/flyout-menu.scss +66 -44
  22. package/css/form.scss +0 -28
  23. package/css/gallery.scss +2 -3
  24. package/css/group-picker.scss +5 -35
  25. package/css/icons.scss +0 -3
  26. package/css/lightbox.scss +2 -4
  27. package/css/mixins.scss +8 -0
  28. package/css/modal.scss +3 -3
  29. package/css/parameters.scss +6 -1
  30. package/css/popover.scss +3 -15
  31. package/css/progress.scss +0 -6
  32. package/css/push-menu.scss +3 -28
  33. package/css/radiobutton.scss +2 -1
  34. package/css/range-slider.scss +1 -7
  35. package/css/scrollbar.scss +2 -6
  36. package/css/sidebar-nav.scss +0 -12
  37. package/css/stepper.scss +0 -4
  38. package/css/style.css +63 -68
  39. package/css/style.css.map +1 -1
  40. package/css/style.min.css +1 -1
  41. package/css/style.min.css.map +1 -1
  42. package/css/style.scss +1 -1
  43. package/css/table.scss +0 -4
  44. package/css/tabs.scss +0 -2
  45. package/css/timeline.scss +1 -13
  46. package/css/timepicker.scss +6 -7
  47. package/css/toast.scss +1 -1
  48. package/css/tooltip.scss +1 -5
  49. package/css/tree.scss +1 -1
  50. package/css/typography.scss +3 -3
  51. package/css/virtual-dropdown.scss +3 -28
  52. package/js/bottom-sheet.d.ts +3 -1
  53. package/js/bottom-sheet.js +26 -27
  54. package/js/calendar.d.ts +7 -0
  55. package/js/calendar.js +14 -33
  56. package/js/carousel.d.ts +2 -0
  57. package/js/carousel.js +13 -5
  58. package/js/chart.d.ts +4 -0
  59. package/js/chart.js +13 -31
  60. package/js/code-viewer.d.ts +1 -0
  61. package/js/code-viewer.js +4 -0
  62. package/js/context-menu.d.ts +9 -2
  63. package/js/context-menu.js +17 -14
  64. package/js/datepicker.d.ts +4 -0
  65. package/js/datepicker.js +26 -11
  66. package/js/dropdown.d.ts +3 -3
  67. package/js/dropdown.js +6 -9
  68. package/js/editor.d.ts +1 -0
  69. package/js/editor.js +9 -3
  70. package/js/file-uploader.d.ts +4 -0
  71. package/js/file-uploader.js +52 -43
  72. package/js/flyout-menu.d.ts +5 -3
  73. package/js/flyout-menu.js +23 -46
  74. package/js/gallery.d.ts +3 -0
  75. package/js/gallery.js +22 -24
  76. package/js/group-picker.d.ts +5 -0
  77. package/js/group-picker.js +12 -17
  78. package/js/lightbox.d.ts +3 -0
  79. package/js/lightbox.js +12 -6
  80. package/js/modal.d.ts +3 -1
  81. package/js/modal.js +14 -11
  82. package/js/popover.d.ts +2 -0
  83. package/js/popover.js +26 -30
  84. package/js/position.d.ts +2 -0
  85. package/js/position.js +1 -5
  86. package/js/push-menu.d.ts +2 -0
  87. package/js/push-menu.js +22 -35
  88. package/js/range-slider.d.ts +1 -0
  89. package/js/range-slider.js +5 -3
  90. package/js/scroll.d.ts +2 -0
  91. package/js/scroll.js +1 -0
  92. package/js/scrollbar.d.ts +2 -0
  93. package/js/scrollbar.js +24 -36
  94. package/js/select.d.ts +1 -0
  95. package/js/select.js +5 -10
  96. package/js/sidebar-nav.d.ts +2 -0
  97. package/js/sidebar-nav.js +8 -0
  98. package/js/stepper.d.ts +2 -0
  99. package/js/stepper.js +7 -1
  100. package/js/table.d.ts +4 -0
  101. package/js/table.js +15 -22
  102. package/js/tabs.d.ts +2 -0
  103. package/js/tabs.js +6 -14
  104. package/js/theme.d.ts +1 -0
  105. package/js/theme.js +5 -13
  106. package/js/timepicker.d.ts +3 -0
  107. package/js/timepicker.js +81 -67
  108. package/js/toast.d.ts +3 -0
  109. package/js/toast.js +24 -15
  110. package/js/tooltip.d.ts +2 -0
  111. package/js/tooltip.js +21 -19
  112. package/js/tree.d.ts +3 -0
  113. package/js/tree.js +13 -0
  114. package/js/utils.d.ts +1 -3
  115. package/js/utils.js +0 -3
  116. package/js/virtual-dropdown.d.ts +3 -0
  117. package/js/virtual-dropdown.js +25 -0
  118. package/package.json +2 -2
@@ -1,8 +1,7 @@
1
+ /** Enhances a native range input with a CSS fill-percentage custom property. */
1
2
  class RangeSlider {
3
+ input;
2
4
  constructor(input) {
3
- this.handleInput = () => {
4
- this.update();
5
- };
6
5
  this.input = input;
7
6
  this.update();
8
7
  this.input.addEventListener('input', this.handleInput);
@@ -18,6 +17,9 @@ class RangeSlider {
18
17
  const pct = ((+this.input.value - min) / (max - min)) * 100;
19
18
  this.input.style.setProperty('--range-fill', `${pct}%`);
20
19
  }
20
+ handleInput = () => {
21
+ this.update();
22
+ };
21
23
  destroy() {
22
24
  this.input.removeEventListener('input', this.handleInput);
23
25
  this.input.style.removeProperty('--range-fill');
package/js/scroll.d.ts CHANGED
@@ -1,8 +1,10 @@
1
+ /** Options for the Scroll.to() utility. */
1
2
  interface ScrollOptions {
2
3
  behavior?: ScrollBehavior;
3
4
  offset?: number;
4
5
  block?: ScrollLogicalPosition;
5
6
  }
7
+ /** Static utility for smooth-scrolling to a target element with header offset support. */
6
8
  declare class Scroll {
7
9
  static to(target: string | Element, options?: ScrollOptions): void;
8
10
  }
package/js/scroll.js CHANGED
@@ -1,3 +1,4 @@
1
+ /** Static utility for smooth-scrolling to a target element with header offset support. */
1
2
  class Scroll {
2
3
  static to(target, options = {}) {
3
4
  const fixed_header = document.querySelector('.main-header');
package/js/scrollbar.d.ts CHANGED
@@ -1,9 +1,11 @@
1
+ /** DOM element references for a Scrollbar instance. */
1
2
  interface ScrollbarElements {
2
3
  viewport: HTMLElement;
3
4
  content: HTMLElement;
4
5
  track: HTMLElement;
5
6
  thumb: HTMLElement;
6
7
  }
8
+ /** Custom scrollbar overlay that replaces the native scrollbar with a draggable thumb. */
7
9
  declare class Scrollbar {
8
10
  private static readonly instances;
9
11
  private static activeInstance;
package/js/scrollbar.js CHANGED
@@ -1,19 +1,36 @@
1
+ /** Custom scrollbar overlay that replaces the native scrollbar with a draggable thumb. */
1
2
  class Scrollbar {
3
+ static instances = new WeakMap();
4
+ static activeInstance = null;
5
+ static globalListenersInstalled = false;
6
+ static instanceCount = 0;
7
+ static globalListenerAbortController = null;
8
+ container;
9
+ viewport;
10
+ content;
11
+ track;
12
+ thumb;
13
+ MIN_THUMB_HEIGHT;
14
+ ro;
15
+ dragging = false;
16
+ activePointerId = null;
17
+ startPointerY = 0;
18
+ startThumbTop = 0;
19
+ boundPointerMove;
20
+ boundPointerUp;
21
+ boundThumbPointerDown;
22
+ boundTrackClick;
23
+ boundViewportScroll;
24
+ boundUpdateThumb;
25
+ boundContainerWheel;
2
26
  constructor(container) {
3
- this.dragging = false;
4
- this.activePointerId = null;
5
- this.startPointerY = 0;
6
- this.startThumbTop = 0;
7
27
  this.container = container;
8
- // Query and validate required elements
9
28
  const elements = this.getRequiredElements(container);
10
29
  this.viewport = elements.viewport;
11
30
  this.content = elements.content;
12
31
  this.track = elements.track;
13
32
  this.thumb = elements.thumb;
14
- // Get minimum thumb height from CSS variable or use default
15
33
  this.MIN_THUMB_HEIGHT = this.getMinThumbHeight();
16
- // Bind all event handlers once
17
34
  this.boundPointerMove = this.handlePointerMove.bind(this);
18
35
  this.boundPointerUp = this.handlePointerUp.bind(this);
19
36
  this.boundThumbPointerDown = this.handleThumbPointerDown.bind(this);
@@ -21,17 +38,13 @@ class Scrollbar {
21
38
  this.boundViewportScroll = this.updateThumb.bind(this);
22
39
  this.boundUpdateThumb = this.updateThumb.bind(this);
23
40
  this.boundContainerWheel = this.handleContainerWheel.bind(this);
24
- // Setup ResizeObserver
25
41
  this.ro = new ResizeObserver(this.boundUpdateThumb);
26
- // Initialize
27
42
  this.attachEventListeners();
28
43
  Scrollbar.instances.set(container, this);
29
- // Track instances and install global listeners once for all
30
44
  Scrollbar.instanceCount++;
31
45
  if (!Scrollbar.globalListenersInstalled) {
32
46
  Scrollbar.installGlobalListeners();
33
47
  }
34
- // Initial thumb update
35
48
  requestAnimationFrame(this.boundUpdateThumb);
36
49
  }
37
50
  getRequiredElements(container) {
@@ -68,12 +81,10 @@ class Scrollbar {
68
81
  Scrollbar.globalListenersInstalled = true;
69
82
  }
70
83
  attachEventListeners() {
71
- // Instance-specific events
72
84
  this.viewport.addEventListener('scroll', this.boundViewportScroll, { passive: true });
73
85
  this.thumb.addEventListener('pointerdown', this.boundThumbPointerDown);
74
86
  this.track.addEventListener('click', this.boundTrackClick);
75
87
  this.container.addEventListener('wheel', this.boundContainerWheel, { passive: false });
76
- // Observe size changes
77
88
  this.ro.observe(this.viewport);
78
89
  this.ro.observe(this.content);
79
90
  window.addEventListener('resize', this.boundUpdateThumb);
@@ -82,17 +93,14 @@ class Scrollbar {
82
93
  const viewportHeight = this.viewport.clientHeight;
83
94
  const contentHeight = this.content.scrollHeight;
84
95
  const trackHeight = this.track.clientHeight;
85
- // Hide thumb if content fits in viewport
86
96
  if (contentHeight <= viewportHeight + 1) {
87
97
  this.thumb.style.display = 'none';
88
98
  return;
89
99
  }
90
100
  this.thumb.style.display = '';
91
- // Calculate thumb size
92
101
  const ratio = viewportHeight / contentHeight;
93
102
  const thumbHeight = Math.max(Math.floor(ratio * trackHeight), this.MIN_THUMB_HEIGHT);
94
103
  this.thumb.style.height = `${thumbHeight}px`;
95
- // Calculate thumb position
96
104
  const maxScroll = contentHeight - viewportHeight;
97
105
  const maxThumbTop = trackHeight - thumbHeight;
98
106
  const scrollRatio = this.viewport.scrollTop / (maxScroll || 1);
@@ -104,7 +112,6 @@ class Scrollbar {
104
112
  this.dragging = true;
105
113
  this.activePointerId = e.pointerId;
106
114
  Scrollbar.activeInstance = this;
107
- // Capture pointer for reliable tracking
108
115
  try {
109
116
  this.thumb.setPointerCapture(e.pointerId);
110
117
  }
@@ -115,11 +122,9 @@ class Scrollbar {
115
122
  const thumbRect = this.thumb.getBoundingClientRect();
116
123
  const trackRect = this.track.getBoundingClientRect();
117
124
  this.startThumbTop = thumbRect.top - trackRect.top;
118
- // Prevent text selection during drag
119
125
  document.body.style.userSelect = 'none';
120
126
  }
121
127
  handlePointerMove(e) {
122
- // Only handle events for the active pointer
123
128
  if (!this.dragging || this.activePointerId !== e.pointerId) {
124
129
  return;
125
130
  }
@@ -128,10 +133,8 @@ class Scrollbar {
128
133
  const trackHeight = this.track.clientHeight;
129
134
  const thumbHeight = this.thumb.clientHeight;
130
135
  const maxThumbTop = trackHeight - thumbHeight;
131
- // Calculate new thumb position
132
136
  const newThumbTop = Math.max(0, Math.min(maxThumbTop, this.startThumbTop + pointerDelta));
133
137
  this.thumb.style.top = `${newThumbTop}px`;
134
- // Update viewport scroll position
135
138
  const contentHeight = this.content.scrollHeight;
136
139
  const viewportHeight = this.viewport.clientHeight;
137
140
  const maxScroll = contentHeight - viewportHeight;
@@ -143,7 +146,6 @@ class Scrollbar {
143
146
  return;
144
147
  }
145
148
  this.dragging = false;
146
- // Release pointer capture
147
149
  try {
148
150
  this.thumb.releasePointerCapture(e.pointerId);
149
151
  }
@@ -155,7 +157,6 @@ class Scrollbar {
155
157
  document.body.style.userSelect = '';
156
158
  }
157
159
  handleTrackClick(e) {
158
- // Ignore clicks directly on the thumb
159
160
  if (e.target === this.thumb) {
160
161
  return;
161
162
  }
@@ -163,11 +164,9 @@ class Scrollbar {
163
164
  const clickY = e.clientY - trackRect.top;
164
165
  const thumbHeight = this.thumb.clientHeight;
165
166
  const trackHeight = this.track.clientHeight;
166
- // Center thumb on click position
167
167
  const targetThumbTop = clickY - thumbHeight / 2;
168
168
  const maxThumbTop = trackHeight - thumbHeight;
169
169
  const clampedThumbTop = Math.max(0, Math.min(maxThumbTop, targetThumbTop));
170
- // Calculate corresponding scroll position
171
170
  const contentHeight = this.content.scrollHeight;
172
171
  const viewportHeight = this.viewport.clientHeight;
173
172
  const maxScroll = contentHeight - viewportHeight;
@@ -186,21 +185,16 @@ class Scrollbar {
186
185
  this.viewport.scrollTop += e.deltaY;
187
186
  }
188
187
  destroy() {
189
- // Remove event listeners
190
188
  this.viewport.removeEventListener('scroll', this.boundViewportScroll);
191
189
  this.thumb.removeEventListener('pointerdown', this.boundThumbPointerDown);
192
190
  this.track.removeEventListener('click', this.boundTrackClick);
193
191
  this.container.removeEventListener('wheel', this.boundContainerWheel);
194
192
  window.removeEventListener('resize', this.boundUpdateThumb);
195
- // Disconnect observer
196
193
  this.ro.disconnect();
197
- // Clear from instances map
198
194
  Scrollbar.instances.delete(this.container);
199
- // Clear active instance if this was it
200
195
  if (Scrollbar.activeInstance === this) {
201
196
  Scrollbar.activeInstance = null;
202
197
  }
203
- // Uninstall global listeners when last instance is destroyed
204
198
  Scrollbar.instanceCount--;
205
199
  if (Scrollbar.instanceCount === 0) {
206
200
  Scrollbar.globalListenerAbortController?.abort();
@@ -208,7 +202,6 @@ class Scrollbar {
208
202
  Scrollbar.globalListenersInstalled = false;
209
203
  }
210
204
  }
211
- // Static factory methods
212
205
  static create(elementOrSelector) {
213
206
  const container = typeof elementOrSelector === 'string'
214
207
  ? document.querySelector(elementOrSelector)
@@ -232,9 +225,4 @@ class Scrollbar {
232
225
  return Scrollbar.instances.get(container);
233
226
  }
234
227
  }
235
- Scrollbar.instances = new WeakMap();
236
- Scrollbar.activeInstance = null;
237
- Scrollbar.globalListenersInstalled = false;
238
- Scrollbar.instanceCount = 0;
239
- Scrollbar.globalListenerAbortController = null;
240
228
  export { Scrollbar };
package/js/select.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ /** Enhances a native `<select>` element with a custom styled dropdown. */
1
2
  declare class Select {
2
3
  private readonly element;
3
4
  private readonly isMultiselect;
package/js/select.js CHANGED
@@ -1,4 +1,9 @@
1
+ /** Enhances a native `<select>` element with a custom styled dropdown. */
1
2
  class Select {
3
+ element;
4
+ isMultiselect;
5
+ dropdown;
6
+ documentClickHandler;
2
7
  constructor(elementOrSelector) {
3
8
  const element = typeof elementOrSelector === 'string'
4
9
  ? document.querySelector(elementOrSelector)
@@ -43,7 +48,6 @@ class Select {
43
48
  const result = Select.initElement(element);
44
49
  if (!result)
45
50
  return null;
46
- // Static init path: add document listener without lifecycle management
47
51
  document.addEventListener('click', (e) => {
48
52
  if (!result.dropdown.contains(e.target)) {
49
53
  result.dropdown.classList.remove('open');
@@ -69,12 +73,10 @@ class Select {
69
73
  throw new Error(`Select: Required dropdown elements not found for "${element}"`);
70
74
  }
71
75
  const isMulti = dropdown.dataset.multi === 'true';
72
- // Toggle dropdown on selected element click
73
76
  selected.addEventListener('click', () => {
74
77
  Select.closeAllDropdowns(dropdown);
75
78
  dropdown.classList.toggle('open');
76
79
  });
77
- // Handle option selection
78
80
  options.addEventListener('click', (e) => {
79
81
  const target = e.target;
80
82
  if (!target.classList.contains('dropdown-option')) {
@@ -87,7 +89,6 @@ class Select {
87
89
  Select.handleSingleSelect(target, options, selected, dropdown, element);
88
90
  }
89
91
  });
90
- // Close dropdown when clicking the close icon
91
92
  const closeIcon = options.querySelector('.dropdown-options-icon');
92
93
  if (closeIcon) {
93
94
  closeIcon.addEventListener('click', () => {
@@ -130,14 +131,12 @@ class Select {
130
131
  const label = parent.querySelector('label');
131
132
  const isMulti = select.hasAttribute('multiple');
132
133
  const labelText = label?.textContent?.trim() || 'Select';
133
- // Create hidden wrapper for original select
134
134
  const hiddenWrapper = document.createElement('div');
135
135
  hiddenWrapper.classList.add('hidden');
136
136
  if (label) {
137
137
  hiddenWrapper.appendChild(label);
138
138
  }
139
139
  hiddenWrapper.appendChild(select);
140
- // Create dropdown structure
141
140
  const dropdown = document.createElement('div');
142
141
  dropdown.className = 'dropdown';
143
142
  dropdown.dataset.multi = String(isMulti);
@@ -146,12 +145,10 @@ class Select {
146
145
  dropdownSelected.textContent = labelText;
147
146
  const dropdownOptions = document.createElement('div');
148
147
  dropdownOptions.className = 'dropdown-options';
149
- // Add mobile menu
150
148
  const optionsMenu = document.createElement('div');
151
149
  optionsMenu.className = 'dropdown-options-menu hidden';
152
150
  optionsMenu.innerHTML = 'Select options<span class="dropdown-options-icon icon icon-close"></span>';
153
151
  dropdownOptions.appendChild(optionsMenu);
154
- // Create option elements
155
152
  Array.from(select.options).forEach(opt => {
156
153
  const optDiv = document.createElement('div');
157
154
  optDiv.className = 'dropdown-option';
@@ -159,10 +156,8 @@ class Select {
159
156
  optDiv.textContent = opt.textContent;
160
157
  dropdownOptions.appendChild(optDiv);
161
158
  });
162
- // Assemble dropdown
163
159
  dropdown.appendChild(dropdownSelected);
164
160
  dropdown.appendChild(dropdownOptions);
165
- // Replace original content
166
161
  parent.innerHTML = '';
167
162
  parent.appendChild(hiddenWrapper);
168
163
  parent.appendChild(dropdown);
@@ -1,9 +1,11 @@
1
+ /** Configuration options for a SidebarNav instance. */
1
2
  interface SidebarNavOptions {
2
3
  /** Selector for the toggle button. Default: '.sidebar-toggle' */
3
4
  toggleSelector?: string;
4
5
  /** Breakpoint (px) above which the sidebar is always visible. Default: 768 */
5
6
  breakpoint?: number;
6
7
  }
8
+ /** Collapsible sidebar navigation with backdrop and responsive breakpoint support. */
7
9
  declare class SidebarNav {
8
10
  private nav;
9
11
  private backdrop;
package/js/sidebar-nav.js CHANGED
@@ -1,4 +1,12 @@
1
+ /** Collapsible sidebar navigation with backdrop and responsive breakpoint support. */
1
2
  class SidebarNav {
3
+ nav;
4
+ backdrop;
5
+ toggleBtn;
6
+ opts;
7
+ _onToggle;
8
+ _onBackdrop;
9
+ _onResize;
2
10
  constructor(containerOrSelector, options = {}) {
3
11
  const container = typeof containerOrSelector === 'string'
4
12
  ? document.querySelector(containerOrSelector)
package/js/stepper.d.ts CHANGED
@@ -1,8 +1,10 @@
1
+ /** Configuration options for a Stepper instance. */
1
2
  interface StepperOptions {
2
3
  defaultStep?: number;
3
4
  clickable?: boolean;
4
5
  onChange?: (current: number, previous: number) => void;
5
6
  }
7
+ /** Multi-step progress indicator with clickable steps and connector state. */
6
8
  declare class Stepper {
7
9
  private container;
8
10
  private steps;
package/js/stepper.js CHANGED
@@ -1,6 +1,12 @@
1
+ /** Multi-step progress indicator with clickable steps and connector state. */
1
2
  class Stepper {
3
+ container;
4
+ steps;
5
+ connectors;
6
+ current;
7
+ onChange;
8
+ abortController = new AbortController();
2
9
  constructor(elementOrSelector, options = {}) {
3
- this.abortController = new AbortController();
4
10
  const element = typeof elementOrSelector === 'string'
5
11
  ? document.querySelector(elementOrSelector)
6
12
  : elementOrSelector;
package/js/table.d.ts CHANGED
@@ -1,16 +1,20 @@
1
+ /** Descriptor for a single table column. */
1
2
  interface TableColumn {
2
3
  key: string;
3
4
  label: string;
4
5
  sortable?: boolean;
5
6
  }
7
+ /** A single data row, keyed by column key. */
6
8
  interface TableRow {
7
9
  [key: string]: string | number | boolean;
8
10
  }
11
+ /** Configuration options for a Table instance. */
9
12
  interface TableOptions {
10
13
  data?: TableRow[];
11
14
  columns?: TableColumn[];
12
15
  pageSize?: number;
13
16
  }
17
+ /** Dynamic data table with sorting, filtering, and pagination. */
14
18
  declare class Table {
15
19
  private container;
16
20
  private data;
package/js/table.js CHANGED
@@ -1,7 +1,19 @@
1
1
  import { Select } from "./select.js";
2
+ /** Dynamic data table with sorting, filtering, and pagination. */
2
3
  class Table {
4
+ container;
5
+ data;
6
+ columns;
7
+ pageSize;
8
+ currentPage;
9
+ sortColumn;
10
+ sortDirection;
11
+ filterText;
12
+ tableBody;
13
+ tableHeader;
14
+ paginationContainer;
15
+ abortController = new AbortController();
3
16
  constructor(elementOrSelector, options = {}) {
4
- this.abortController = new AbortController();
5
17
  const element = typeof elementOrSelector === 'string'
6
18
  ? document.querySelector(elementOrSelector)
7
19
  : elementOrSelector;
@@ -32,14 +44,12 @@ class Table {
32
44
  const tbody = table.querySelector('tbody');
33
45
  if (!thead || !tbody)
34
46
  return;
35
- // Parse columns from header
36
47
  const ths = thead.querySelectorAll('th');
37
48
  this.columns = Array.from(ths).map((th, index) => ({
38
49
  key: `col${index}`,
39
50
  label: th.textContent?.trim() || '',
40
51
  sortable: true
41
52
  }));
42
- // Parse data from body rows
43
53
  const trs = tbody.querySelectorAll('tr');
44
54
  this.data = Array.from(trs).map(tr => {
45
55
  const row = {};
@@ -51,7 +61,6 @@ class Table {
51
61
  });
52
62
  return row;
53
63
  });
54
- // Clear the existing static table
55
64
  this.container.innerHTML = '';
56
65
  }
57
66
  /**
@@ -68,7 +77,6 @@ class Table {
68
77
  renderControls() {
69
78
  const controlsDiv = document.createElement('div');
70
79
  controlsDiv.className = 'table-controls';
71
- // Search input
72
80
  const searchInput = document.createElement('input');
73
81
  searchInput.type = 'text';
74
82
  searchInput.placeholder = 'Search...';
@@ -77,7 +85,6 @@ class Table {
77
85
  this.handleSearch(e.target.value);
78
86
  }, { signal: this.abortController.signal });
79
87
  controlsDiv.appendChild(searchInput);
80
- // Page size selector
81
88
  const selectGroup = document.createElement('div');
82
89
  selectGroup.className = 'select-group';
83
90
  const label = document.createElement('label');
@@ -110,7 +117,6 @@ class Table {
110
117
  const table = document.createElement('table');
111
118
  const thead = document.createElement('thead');
112
119
  const tbody = document.createElement('tbody');
113
- // Create header row
114
120
  const tr = document.createElement('tr');
115
121
  this.columns.forEach(col => {
116
122
  const th = document.createElement('th');
@@ -127,7 +133,6 @@ class Table {
127
133
  table.appendChild(tbody);
128
134
  wrapper.appendChild(table);
129
135
  this.container.appendChild(wrapper);
130
- // Create pagination container
131
136
  const paginationDiv = document.createElement('div');
132
137
  paginationDiv.className = 'pagination';
133
138
  this.container.appendChild(paginationDiv);
@@ -140,7 +145,6 @@ class Table {
140
145
  */
141
146
  getFilteredAndSortedData() {
142
147
  let processedData = [...this.data];
143
- // Apply filter
144
148
  if (this.filterText) {
145
149
  const lowerFilter = this.filterText.toLowerCase();
146
150
  processedData = processedData.filter(row => {
@@ -150,12 +154,10 @@ class Table {
150
154
  });
151
155
  });
152
156
  }
153
- // Apply sort
154
157
  if (this.sortColumn) {
155
158
  processedData.sort((a, b) => {
156
159
  const valA = a[this.sortColumn];
157
160
  const valB = b[this.sortColumn];
158
- // Handle null/undefined values
159
161
  if (valA == null && valB == null)
160
162
  return 0;
161
163
  if (valA == null)
@@ -178,7 +180,6 @@ class Table {
178
180
  const processedData = this.getFilteredAndSortedData();
179
181
  const totalItems = processedData.length;
180
182
  const totalPages = Math.ceil(totalItems / this.pageSize);
181
- // Ensure current page is valid
182
183
  if (this.currentPage > totalPages && totalPages > 0) {
183
184
  this.currentPage = totalPages;
184
185
  }
@@ -212,7 +213,7 @@ class Table {
212
213
  this.columns.forEach(col => {
213
214
  const td = document.createElement('td');
214
215
  td.textContent = String(row[col.key] ?? '');
215
- td.setAttribute('data-label', col.label); // For mobile view
216
+ td.setAttribute('data-label', col.label);
216
217
  tr.appendChild(td);
217
218
  });
218
219
  this.tableBody.appendChild(tr);
@@ -237,28 +238,23 @@ class Table {
237
238
  this.paginationContainer.innerHTML = '';
238
239
  if (totalItems === 0)
239
240
  return;
240
- // Info text
241
241
  const info = document.createElement('div');
242
242
  info.className = 'pagination-info';
243
243
  info.textContent = `Showing ${startIndex + 1} to ${endIndex} of ${totalItems} entries`;
244
244
  this.paginationContainer.appendChild(info);
245
- // Pagination buttons
246
245
  const buttonsDiv = document.createElement('div');
247
246
  buttonsDiv.className = 'pagination-buttons';
248
- // Previous button
249
247
  const prevBtn = document.createElement('button');
250
248
  prevBtn.className = 'page-btn';
251
249
  prevBtn.textContent = 'Previous';
252
250
  prevBtn.disabled = this.currentPage === 1;
253
251
  prevBtn.addEventListener('click', () => this.setPage(this.currentPage - 1));
254
252
  buttonsDiv.appendChild(prevBtn);
255
- // Calculate page range to display (max 5 pages)
256
253
  let startPage = Math.max(1, this.currentPage - 2);
257
254
  let endPage = Math.min(totalPages, startPage + 4);
258
255
  if (endPage - startPage < 4) {
259
256
  startPage = Math.max(1, endPage - 4);
260
257
  }
261
- // Page number buttons
262
258
  for (let i = startPage; i <= endPage; i++) {
263
259
  const btn = document.createElement('button');
264
260
  btn.className = `page-btn ${i === this.currentPage ? 'active' : ''}`;
@@ -266,7 +262,6 @@ class Table {
266
262
  btn.addEventListener('click', () => this.setPage(i));
267
263
  buttonsDiv.appendChild(btn);
268
264
  }
269
- // Next button
270
265
  const nextBtn = document.createElement('button');
271
266
  nextBtn.className = 'page-btn';
272
267
  nextBtn.textContent = 'Next';
@@ -280,7 +275,7 @@ class Table {
280
275
  */
281
276
  handleSearch(text) {
282
277
  this.filterText = text;
283
- this.currentPage = 1; // Reset to first page on search
278
+ this.currentPage = 1;
284
279
  this.render();
285
280
  }
286
281
  /**
@@ -288,7 +283,6 @@ class Table {
288
283
  */
289
284
  handleSort(key) {
290
285
  if (this.sortColumn === key) {
291
- // Toggle sort direction
292
286
  this.sortDirection = this.sortDirection === 'asc' ? 'desc' : 'asc';
293
287
  }
294
288
  else {
@@ -320,7 +314,6 @@ class Table {
320
314
  return null;
321
315
  let id = baseId;
322
316
  let counter = 1;
323
- // If baseId already ends with a number, extract it
324
317
  const match = baseId.match(/^(.*?)(\d+)$/);
325
318
  if (match) {
326
319
  id = match[1];
package/js/tabs.d.ts CHANGED
@@ -1,11 +1,13 @@
1
1
  type TabLayout = 'horizontal' | 'vertical';
2
2
  type MenuPosition = 'top' | 'bottom' | 'left' | 'right';
3
+ /** Configuration options for a Tabs instance. */
3
4
  interface TabsOptions {
4
5
  layout?: TabLayout;
5
6
  defaultTab?: number;
6
7
  menuPos?: MenuPosition;
7
8
  onChange?: (index: number) => void;
8
9
  }
10
+ /** Tabbed content component with horizontal/vertical layouts and keyboard navigation. */
9
11
  declare class Tabs {
10
12
  private container;
11
13
  private options;