mtrl 0.2.9 → 0.3.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.
Files changed (99) hide show
  1. package/CLAUDE.md +33 -0
  2. package/package.json +3 -1
  3. package/src/components/button/button.ts +34 -5
  4. package/src/components/navigation/index.ts +4 -1
  5. package/src/components/navigation/system/core.ts +302 -0
  6. package/src/components/navigation/system/events.ts +240 -0
  7. package/src/components/navigation/system/index.ts +184 -0
  8. package/src/components/navigation/system/mobile.ts +278 -0
  9. package/src/components/navigation/system/state.ts +77 -0
  10. package/src/components/navigation/system/types.ts +364 -0
  11. package/src/components/navigation/types.ts +33 -0
  12. package/src/components/slider/config.ts +2 -2
  13. package/src/components/slider/features/controller.ts +1 -25
  14. package/src/components/slider/features/handlers.ts +0 -1
  15. package/src/components/slider/features/range.ts +7 -7
  16. package/src/components/slider/{structure.ts → schema.ts} +2 -13
  17. package/src/components/slider/slider.ts +3 -2
  18. package/src/components/snackbar/index.ts +7 -1
  19. package/src/components/snackbar/types.ts +25 -0
  20. package/src/components/switch/api.ts +16 -0
  21. package/src/components/switch/config.ts +1 -18
  22. package/src/components/switch/features.ts +198 -0
  23. package/src/components/switch/index.ts +6 -1
  24. package/src/components/switch/switch.ts +3 -3
  25. package/src/components/switch/types.ts +27 -2
  26. package/src/components/textfield/index.ts +7 -1
  27. package/src/components/textfield/types.ts +36 -0
  28. package/src/core/composition/features/dom.ts +26 -14
  29. package/src/core/composition/features/icon.ts +18 -18
  30. package/src/core/composition/features/index.ts +3 -2
  31. package/src/core/composition/features/label.ts +16 -17
  32. package/src/core/composition/features/layout.ts +47 -0
  33. package/src/core/composition/index.ts +4 -4
  34. package/src/core/layout/README.md +350 -0
  35. package/src/core/layout/array.ts +181 -0
  36. package/src/core/layout/create.ts +55 -0
  37. package/src/core/layout/index.ts +26 -0
  38. package/src/core/layout/object.ts +124 -0
  39. package/src/core/layout/processor.ts +58 -0
  40. package/src/core/layout/result.ts +85 -0
  41. package/src/core/layout/types.ts +125 -0
  42. package/src/core/layout/utils.ts +136 -0
  43. package/src/styles/abstract/_variables.scss +28 -0
  44. package/src/styles/components/_switch.scss +133 -69
  45. package/src/styles/components/_textfield.scss +9 -16
  46. package/test/components/badge.test.ts +545 -0
  47. package/test/components/bottom-app-bar.test.ts +303 -0
  48. package/test/components/button.test.ts +233 -0
  49. package/test/components/card.test.ts +560 -0
  50. package/test/components/carousel.test.ts +951 -0
  51. package/test/components/checkbox.test.ts +462 -0
  52. package/test/components/chip.test.ts +692 -0
  53. package/test/components/datepicker.test.ts +1124 -0
  54. package/test/components/dialog.test.ts +990 -0
  55. package/test/components/divider.test.ts +412 -0
  56. package/test/components/extended-fab.test.ts +672 -0
  57. package/test/components/fab.test.ts +561 -0
  58. package/test/components/list.test.ts +365 -0
  59. package/test/components/menu.test.ts +718 -0
  60. package/test/components/navigation.test.ts +186 -0
  61. package/test/components/progress.test.ts +567 -0
  62. package/test/components/radios.test.ts +699 -0
  63. package/test/components/search.test.ts +1135 -0
  64. package/test/components/segmented-button.test.ts +732 -0
  65. package/test/components/sheet.test.ts +641 -0
  66. package/test/components/slider.test.ts +1220 -0
  67. package/test/components/snackbar.test.ts +461 -0
  68. package/test/components/switch.test.ts +452 -0
  69. package/test/components/tabs.test.ts +1369 -0
  70. package/test/components/textfield.test.ts +400 -0
  71. package/test/components/timepicker.test.ts +592 -0
  72. package/test/components/tooltip.test.ts +630 -0
  73. package/test/components/top-app-bar.test.ts +566 -0
  74. package/test/core/dom.attributes.test.ts +148 -0
  75. package/test/core/dom.classes.test.ts +152 -0
  76. package/test/core/dom.events.test.ts +243 -0
  77. package/test/core/emitter.test.ts +141 -0
  78. package/test/core/ripple.test.ts +99 -0
  79. package/test/core/state.store.test.ts +189 -0
  80. package/test/core/utils.normalize.test.ts +61 -0
  81. package/test/core/utils.object.test.ts +120 -0
  82. package/test/setup.ts +451 -0
  83. package/tsconfig.json +2 -2
  84. package/src/components/navigation/system-types.ts +0 -124
  85. package/src/components/navigation/system.ts +0 -776
  86. package/src/components/snackbar/constants.ts +0 -26
  87. package/src/core/composition/features/structure.ts +0 -22
  88. package/src/core/layout/index.js +0 -95
  89. package/src/core/structure.ts +0 -288
  90. package/test/components/button.test.js +0 -170
  91. package/test/components/checkbox.test.js +0 -238
  92. package/test/components/list.test.js +0 -105
  93. package/test/components/menu.test.js +0 -385
  94. package/test/components/navigation.test.js +0 -227
  95. package/test/components/snackbar.test.js +0 -234
  96. package/test/components/switch.test.js +0 -186
  97. package/test/components/textfield.test.js +0 -314
  98. package/test/core/emitter.test.js +0 -141
  99. package/test/core/ripple.test.js +0 -66
@@ -0,0 +1,364 @@
1
+ // src/components/navigation/system/types.ts
2
+
3
+ /**
4
+ * Configuration options for the navigation system
5
+ */
6
+ export interface NavigationSystemConfig {
7
+ /**
8
+ * Screen width breakpoint for mobile mode (in pixels)
9
+ * @default 960
10
+ */
11
+ breakpoint?: number;
12
+
13
+ /**
14
+ * Prevent body scrolling when mobile drawer is open
15
+ * @default true
16
+ */
17
+ lockBodyScroll?: boolean;
18
+
19
+ /**
20
+ * Close drawer when clicking outside of it in mobile mode
21
+ * @default true
22
+ */
23
+ hideOnClickOutside?: boolean;
24
+
25
+ /**
26
+ * Enable swipe gestures for mobile navigation
27
+ * @default true
28
+ */
29
+ enableSwipeGestures?: boolean;
30
+
31
+ /**
32
+ * Optimize touch targets for mobile devices
33
+ * @default true
34
+ */
35
+ optimizeForTouch?: boolean;
36
+
37
+ /**
38
+ * CSS class for the overlay element
39
+ * @default 'mtrl-nav-overlay'
40
+ */
41
+ overlayClass?: string;
42
+
43
+ /**
44
+ * CSS class for the close button
45
+ * @default 'mtrl-nav-close-btn'
46
+ */
47
+ closeButtonClass?: string;
48
+
49
+ /**
50
+ * CSS class applied to body when drawer is open (to prevent scrolling)
51
+ * @default 'mtrl-body-drawer-open'
52
+ */
53
+ bodyLockClass?: string;
54
+
55
+ /**
56
+ * Display labels on rail navigation items
57
+ * @default true
58
+ */
59
+ showLabelsOnRail?: boolean;
60
+
61
+ /**
62
+ * Hide drawer when an item is clicked
63
+ * @default false
64
+ */
65
+ hideDrawerOnClick?: boolean;
66
+
67
+ /**
68
+ * Start with drawer expanded
69
+ * @default false
70
+ */
71
+ expanded?: boolean;
72
+
73
+ /**
74
+ * Delay before opening drawer on hover (in ms)
75
+ * @default 200
76
+ */
77
+ hoverDelay?: number;
78
+
79
+ /**
80
+ * Delay before closing drawer after mouseleave (in ms)
81
+ * @default 100
82
+ */
83
+ closeDelay?: number;
84
+
85
+ /**
86
+ * ID of the initially active section
87
+ */
88
+ activeSection?: string;
89
+
90
+ /**
91
+ * ID of the initially active subsection
92
+ */
93
+ activeSubsection?: string;
94
+
95
+ /**
96
+ * Navigation items configuration
97
+ */
98
+ items?: Record<string, NavigationSection>;
99
+
100
+ /**
101
+ * Additional options for the rail component
102
+ */
103
+ railOptions?: Record<string, any>;
104
+
105
+ /**
106
+ * Additional options for the drawer component
107
+ */
108
+ drawerOptions?: Record<string, any>;
109
+ }
110
+
111
+ /**
112
+ * Navigation section configuration
113
+ */
114
+ export interface NavigationSection {
115
+ /**
116
+ * Display label for the section
117
+ */
118
+ label: string;
119
+
120
+ /**
121
+ * Icon for the section
122
+ */
123
+ icon?: string;
124
+
125
+ /**
126
+ * Subsection items
127
+ */
128
+ items?: NavigationItem[];
129
+ }
130
+
131
+ /**
132
+ * Navigation item configuration
133
+ */
134
+ export interface NavigationItem {
135
+ /**
136
+ * Unique identifier for the item
137
+ */
138
+ id: string;
139
+
140
+ /**
141
+ * Display label for the item
142
+ */
143
+ label: string;
144
+
145
+ /**
146
+ * Icon for the item
147
+ */
148
+ icon?: string;
149
+
150
+ /**
151
+ * Whether the item is currently active
152
+ */
153
+ active?: boolean;
154
+
155
+ /**
156
+ * Additional properties
157
+ */
158
+ [key: string]: any;
159
+ }
160
+
161
+ /**
162
+ * Navigation system state interface
163
+ */
164
+ export interface NavigationSystemState {
165
+ /**
166
+ * Rail navigation component instance
167
+ */
168
+ rail: any;
169
+
170
+ /**
171
+ * Drawer navigation component instance
172
+ */
173
+ drawer: any;
174
+
175
+ /**
176
+ * ID of the active section
177
+ */
178
+ activeSection: string | null;
179
+
180
+ /**
181
+ * ID of the active subsection
182
+ */
183
+ activeSubsection: string | null;
184
+
185
+ /**
186
+ * Navigation items configuration
187
+ */
188
+ items: Record<string, NavigationSection>;
189
+
190
+ /**
191
+ * Whether the mouse is currently inside the drawer
192
+ */
193
+ mouseInDrawer: boolean;
194
+
195
+ /**
196
+ * Whether the mouse is currently inside the rail
197
+ */
198
+ mouseInRail: boolean;
199
+
200
+ /**
201
+ * Timer ID for hover delay
202
+ */
203
+ hoverTimer: number | null;
204
+
205
+ /**
206
+ * Timer ID for close delay
207
+ */
208
+ closeTimer: number | null;
209
+
210
+ /**
211
+ * Whether the system is currently processing a change
212
+ */
213
+ processingChange: boolean;
214
+
215
+ /**
216
+ * Whether the system is in mobile mode
217
+ */
218
+ isMobile: boolean;
219
+
220
+ /**
221
+ * Overlay element for mobile mode
222
+ */
223
+ overlayElement: HTMLElement | null;
224
+
225
+ /**
226
+ * Close button element for mobile mode
227
+ */
228
+ closeButtonElement: HTMLElement | null;
229
+
230
+ /**
231
+ * ResizeObserver instance for responsive behavior
232
+ */
233
+ resizeObserver: ResizeObserver | null;
234
+
235
+ /**
236
+ * Handler function for outside clicks
237
+ */
238
+ outsideClickHandler: ((event: Event) => void) | null;
239
+
240
+ /**
241
+ * Whether outside click handling is set up
242
+ */
243
+ outsideClickHandlerSet: boolean;
244
+ }
245
+
246
+ /**
247
+ * View change event data
248
+ */
249
+ export interface ViewChangeEvent {
250
+ /**
251
+ * Whether the system is now in mobile mode
252
+ */
253
+ mobile: boolean;
254
+
255
+ /**
256
+ * Whether the system was previously in mobile mode
257
+ */
258
+ previousMobile: boolean;
259
+
260
+ /**
261
+ * Current window width
262
+ */
263
+ width: number;
264
+ }
265
+
266
+ /**
267
+ * Navigation system API interface
268
+ */
269
+ export interface NavigationSystem {
270
+ /**
271
+ * Initialize the navigation system
272
+ */
273
+ initialize(): NavigationSystem;
274
+
275
+ /**
276
+ * Clean up resources
277
+ */
278
+ cleanup(): void;
279
+
280
+ /**
281
+ * Navigate to a specific section and subsection
282
+ * @param section - Section ID
283
+ * @param subsection - Subsection ID (optional)
284
+ * @param silent - Whether to suppress change events
285
+ */
286
+ navigateTo(section: string, subsection?: string, silent?: boolean): void;
287
+
288
+ /**
289
+ * Get the rail navigation component
290
+ */
291
+ getRail(): any;
292
+
293
+ /**
294
+ * Get the drawer navigation component
295
+ */
296
+ getDrawer(): any;
297
+
298
+ /**
299
+ * Get the active section ID
300
+ */
301
+ getActiveSection(): string | null;
302
+
303
+ /**
304
+ * Get the active subsection ID
305
+ */
306
+ getActiveSubsection(): string | null;
307
+
308
+ /**
309
+ * Show the drawer
310
+ */
311
+ showDrawer(): void;
312
+
313
+ /**
314
+ * Hide the drawer
315
+ */
316
+ hideDrawer(): void;
317
+
318
+ /**
319
+ * Check if the drawer is visible
320
+ */
321
+ isDrawerVisible(): boolean;
322
+
323
+ /**
324
+ * Update configuration
325
+ * @param newConfig - New configuration options
326
+ */
327
+ configure(newConfig: Partial<NavigationSystemConfig>): NavigationSystem;
328
+
329
+ /**
330
+ * Set processing change state
331
+ * @param isProcessing - Whether a change is being processed
332
+ */
333
+ setProcessingChange(isProcessing: boolean): void;
334
+
335
+ /**
336
+ * Check if a change is being processed
337
+ */
338
+ isProcessingChange(): boolean;
339
+
340
+ /**
341
+ * Check if the system is in mobile mode
342
+ */
343
+ isMobile(): boolean;
344
+
345
+ /**
346
+ * Check and update mobile state
347
+ */
348
+ checkMobileState(): void;
349
+
350
+ /**
351
+ * Handler for section changes
352
+ */
353
+ onSectionChange?: (sectionId: string, eventData: any) => void;
354
+
355
+ /**
356
+ * Handler for item selection
357
+ */
358
+ onItemSelect?: (event: any) => void;
359
+
360
+ /**
361
+ * Handler for view changes (mobile/desktop)
362
+ */
363
+ onViewChange?: (event: ViewChangeEvent) => void;
364
+ }
@@ -6,18 +6,51 @@
6
6
  */
7
7
  export type NavVariant = 'rail' | 'drawer' | 'bar' | 'modal' | 'standard';
8
8
 
9
+ /**
10
+ * Navigation variants enum
11
+ * @category Components
12
+ */
13
+ export const NAV_VARIANTS: Record<string, NavVariant> = {
14
+ RAIL: 'rail',
15
+ DRAWER: 'drawer',
16
+ BAR: 'bar',
17
+ MODAL: 'modal',
18
+ STANDARD: 'standard'
19
+ } as const;
20
+
9
21
  /**
10
22
  * Navigation positions
11
23
  * @category Components
12
24
  */
13
25
  export type NavPosition = 'left' | 'right' | 'top' | 'bottom';
14
26
 
27
+ /**
28
+ * Navigation positions enum
29
+ * @category Components
30
+ */
31
+ export const NAV_POSITIONS: Record<string, NavPosition> = {
32
+ LEFT: 'left',
33
+ RIGHT: 'right',
34
+ TOP: 'top',
35
+ BOTTOM: 'bottom'
36
+ } as const;
37
+
15
38
  /**
16
39
  * Navigation behaviors
17
40
  * @category Components
18
41
  */
19
42
  export type NavBehavior = 'fixed' | 'dismissible' | 'modal';
20
43
 
44
+ /**
45
+ * Navigation behaviors enum
46
+ * @category Components
47
+ */
48
+ export const NAV_BEHAVIORS: Record<string, NavBehavior> = {
49
+ FIXED: 'fixed',
50
+ DISMISSIBLE: 'dismissible',
51
+ MODAL: 'modal'
52
+ } as const;
53
+
21
54
  /**
22
55
  * Navigation item state
23
56
  * @category Components
@@ -5,7 +5,7 @@ import {
5
5
  } from '../../core/config/component-config';
6
6
  import { SliderConfig } from './types';
7
7
  import { SLIDER_COLORS, SLIDER_SIZES } from './constants';
8
- import { createSliderDefinition } from './structure';
8
+ import { createSliderSchema } from './schema';
9
9
 
10
10
  /**
11
11
  * Default configuration for the Slider component
@@ -47,7 +47,7 @@ export const createBaseConfig = (config: SliderConfig = {}): SliderConfig => {
47
47
  };
48
48
 
49
49
  // Add the structure definition to the config
50
- baseConfig.structureDefinition = createSliderDefinition(baseComponent, baseConfig);
50
+ baseConfig.schema = createSliderSchema(baseComponent, baseConfig);
51
51
 
52
52
  return baseConfig;
53
53
  };
@@ -16,30 +16,6 @@ export const withController = (config: SliderConfig) => component => {
16
16
  console.warn('Cannot initialize slider controller: missing element or components');
17
17
  return component;
18
18
  }
19
-
20
- // Ensure component has events
21
- if (!component.events) {
22
- component.events = {
23
- listeners: {},
24
- on(event, handler) {
25
- if (!this.listeners[event]) this.listeners[event] = [];
26
- this.listeners[event].push(handler);
27
- return this;
28
- },
29
- off(event, handler) {
30
- if (this.listeners[event]) {
31
- this.listeners[event] = this.listeners[event].filter(h => h !== handler);
32
- }
33
- return this;
34
- },
35
- trigger(event, data) {
36
- if (this.listeners[event]) {
37
- this.listeners[event].forEach(handler => handler(data));
38
- }
39
- return this;
40
- }
41
- };
42
- }
43
19
 
44
20
  // Initialize state
45
21
  const state = {
@@ -68,7 +44,7 @@ export const withController = (config: SliderConfig) => component => {
68
44
  defaultPrevented: false
69
45
  };
70
46
 
71
- state.component.events.trigger(eventName, eventData);
47
+ state.component.emit(eventName, eventData);
72
48
  return eventData;
73
49
  }
74
50
  };
@@ -174,7 +174,6 @@ export const createHandlers = (config: SliderConfig, state, uiRenderer, eventHel
174
174
  // Update UI and trigger events
175
175
  render();
176
176
  triggerEvent(SLIDER_EVENTS.INPUT, e);
177
- triggerEvent(SLIDER_EVENTS.CHANGE, e);
178
177
  } catch (error) {
179
178
  console.warn('Error handling track click:', error);
180
179
  }
@@ -10,7 +10,7 @@ import { createElement } from '../../../core/dom/create';
10
10
  */
11
11
  export const withRange = (config: SliderConfig) => component => {
12
12
  // If not a range slider or missing structure definition, return unmodified
13
- if (!config.range || !config.secondValue || !component.structureDefinition) {
13
+ if (!config.range || !config.secondValue || !component.schema) {
14
14
  return component;
15
15
  }
16
16
 
@@ -25,18 +25,18 @@ export const withRange = (config: SliderConfig) => component => {
25
25
  const getClass = component.getClass;
26
26
 
27
27
  // Clone the structure definition (deep copy)
28
- const structureDefinition = JSON.parse(JSON.stringify(component.structureDefinition));
28
+ const schema = JSON.parse(JSON.stringify(component.schema));
29
29
 
30
30
  // Add range class to root element
31
- const rootClasses = structureDefinition.element.options.className || [];
31
+ const rootClasses = schema.element.options.className || [];
32
32
  if (Array.isArray(rootClasses)) {
33
33
  rootClasses.push(getClass('slider--range'));
34
34
  } else {
35
- structureDefinition.element.options.className = `${rootClasses} ${getClass('slider--range')}`.trim();
35
+ schema.element.options.className = `${rootClasses} ${getClass('slider--range')}`.trim();
36
36
  }
37
37
 
38
38
  // Add start track segment to track children
39
- const trackChildren = structureDefinition.element.children.container.children.track.children;
39
+ const trackChildren = schema.element.children.container.children.track.children;
40
40
  trackChildren.startTrack = {
41
41
  name: 'startTrack',
42
42
  creator: createElement,
@@ -50,7 +50,7 @@ export const withRange = (config: SliderConfig) => component => {
50
50
  };
51
51
 
52
52
  // Add second handle to container children
53
- const containerChildren = structureDefinition.element.children.container.children;
53
+ const containerChildren = schema.element.children.container.children;
54
54
  containerChildren.secondHandle = {
55
55
  name: 'secondHandle',
56
56
  creator: createElement,
@@ -95,7 +95,7 @@ export const withRange = (config: SliderConfig) => component => {
95
95
  // Return component with updated structure definition
96
96
  return {
97
97
  ...component,
98
- structureDefinition
98
+ schema
99
99
  };
100
100
  } catch (error) {
101
101
  console.warn('Error enhancing structure with range functionality:', error);
@@ -6,9 +6,9 @@ import { SliderConfig } from './types';
6
6
  *
7
7
  * @param component Component for class name generation
8
8
  * @param config Slider configuration
9
- * @returns Structure definition object
9
+ * @returns Structure schema object
10
10
  */
11
- export function createSliderDefinition(component, config: SliderConfig) {
11
+ export function createSliderSchema(component, config: SliderConfig) {
12
12
  // Get prefixed class names
13
13
  const getClass = (className) => component.getClass(className);
14
14
 
@@ -26,7 +26,6 @@ export function createSliderDefinition(component, config: SliderConfig) {
26
26
  return {
27
27
  element: {
28
28
  options: {
29
- tag: 'div',
30
29
  className: [getClass('slider'), config.class].filter(Boolean),
31
30
  attrs: {
32
31
  tabindex: '-1',
@@ -38,20 +37,17 @@ export function createSliderDefinition(component, config: SliderConfig) {
38
37
  // Container with all slider elements
39
38
  container: {
40
39
  options: {
41
- tag: 'div',
42
40
  className: getClass('slider-container')
43
41
  },
44
42
  children: {
45
43
  // Track with segments
46
44
  track: {
47
45
  options: {
48
- tag: 'div',
49
46
  className: getClass('slider-track')
50
47
  },
51
48
  children: {
52
49
  activeTrack: {
53
50
  options: {
54
- tag: 'div',
55
51
  className: getClass('slider-active-track'),
56
52
  style: {
57
53
  width: `${valuePercent}%`
@@ -60,7 +56,6 @@ export function createSliderDefinition(component, config: SliderConfig) {
60
56
  },
61
57
  startTrack: {
62
58
  options: {
63
- tag: 'div',
64
59
  className: getClass('slider-start-track'),
65
60
  style: {
66
61
  display: 'none', // Initially hidden for single slider
@@ -70,7 +65,6 @@ export function createSliderDefinition(component, config: SliderConfig) {
70
65
  },
71
66
  remainingTrack: {
72
67
  options: {
73
- tag: 'div',
74
68
  className: getClass('slider-remaining-track'),
75
69
  style: {
76
70
  width: `${100 - valuePercent}%`
@@ -83,7 +77,6 @@ export function createSliderDefinition(component, config: SliderConfig) {
83
77
  // Ticks container
84
78
  ticksContainer: {
85
79
  options: {
86
- tag: 'div',
87
80
  className: getClass('slider-ticks-container')
88
81
  }
89
82
  },
@@ -91,7 +84,6 @@ export function createSliderDefinition(component, config: SliderConfig) {
91
84
  // Dots for ends
92
85
  startDot: {
93
86
  options: {
94
- tag: 'div',
95
87
  className: [
96
88
  getClass('slider-dot'),
97
89
  getClass('slider-dot--start')
@@ -100,7 +92,6 @@ export function createSliderDefinition(component, config: SliderConfig) {
100
92
  },
101
93
  endDot: {
102
94
  options: {
103
- tag: 'div',
104
95
  className: [
105
96
  getClass('slider-dot'),
106
97
  getClass('slider-dot--end')
@@ -111,7 +102,6 @@ export function createSliderDefinition(component, config: SliderConfig) {
111
102
  // Main handle
112
103
  handle: {
113
104
  options: {
114
- tag: 'div',
115
105
  className: getClass('slider-handle'),
116
106
  attrs: {
117
107
  role: 'slider',
@@ -132,7 +122,6 @@ export function createSliderDefinition(component, config: SliderConfig) {
132
122
  // Main value bubble
133
123
  valueBubble: {
134
124
  options: {
135
- tag: 'div',
136
125
  className: getClass('slider-value'),
137
126
  attrs: {
138
127
  'aria-hidden': 'true',
@@ -2,7 +2,7 @@
2
2
  import { pipe } from '../../core/compose/pipe';
3
3
  import { createBase } from '../../core/compose/component';
4
4
  import { withEvents, withLifecycle } from '../../core/compose/features';
5
- import { withStructure, withIcon, withLabel, withDom } from '../../core/composition/features';
5
+ import { withLayout, withIcon, withLabel, withDom } from '../../core/composition/features';
6
6
  import {
7
7
  withRange,
8
8
  withStates,
@@ -11,6 +11,7 @@ import {
11
11
  import { withAPI } from './api';
12
12
  import { SliderConfig, SliderComponent } from './types';
13
13
  import { createBaseConfig, getApiConfig } from './config';
14
+
14
15
  /**
15
16
  * Creates a new Slider component
16
17
  *
@@ -36,7 +37,7 @@ const createSlider = (config: SliderConfig = {}): SliderComponent => {
36
37
  // Base component with event system
37
38
  createBase,
38
39
  withEvents(),
39
- withStructure(baseConfig),
40
+ withLayout(baseConfig),
40
41
  withIcon(baseConfig),
41
42
  withLabel(baseConfig),
42
43
  withRange(baseConfig),
@@ -1,3 +1,9 @@
1
1
  // src/components/snackbar/index.ts
2
2
  export { default } from './snackbar'
3
- export { SnackbarConfig, SnackbarComponent } from './types'
3
+ export {
4
+ SnackbarConfig,
5
+ SnackbarComponent,
6
+ SNACKBAR_VARIANTS,
7
+ SNACKBAR_POSITIONS,
8
+ SNACKBAR_STATES
9
+ } from './types'
@@ -5,16 +5,41 @@
5
5
  */
6
6
  export type SnackbarVariant = 'basic' | 'action';
7
7
 
8
+ /**
9
+ * Snackbar visual variants
10
+ */
11
+ export const SNACKBAR_VARIANTS = {
12
+ BASIC: 'basic',
13
+ ACTION: 'action' // With action button
14
+ } as const;
15
+
8
16
  /**
9
17
  * Available snackbar positions
10
18
  */
11
19
  export type SnackbarPosition = 'center' | 'start' | 'end';
12
20
 
21
+ /**
22
+ * Snackbar display positions
23
+ */
24
+ export const SNACKBAR_POSITIONS = {
25
+ CENTER: 'center',
26
+ START: 'start',
27
+ END: 'end'
28
+ } as const;
29
+
13
30
  /**
14
31
  * Snackbar visibility states
15
32
  */
16
33
  export type SnackbarState = 'visible' | 'hidden';
17
34
 
35
+ /**
36
+ * Snackbar state classes
37
+ */
38
+ export const SNACKBAR_STATES = {
39
+ VISIBLE: 'visible',
40
+ HIDDEN: 'hidden'
41
+ } as const;
42
+
18
43
  /**
19
44
  * Available snackbar event types
20
45
  */