mtrl 0.1.2 → 0.2.0

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 (220) hide show
  1. package/README.md +70 -22
  2. package/index.ts +33 -0
  3. package/package.json +14 -5
  4. package/src/components/button/{styles.scss → _styles.scss} +2 -2
  5. package/src/components/button/api.ts +89 -0
  6. package/src/components/button/button.ts +50 -0
  7. package/src/components/button/config.ts +75 -0
  8. package/src/components/button/constants.ts +17 -0
  9. package/src/components/button/index.ts +4 -0
  10. package/src/components/button/types.ts +118 -0
  11. package/src/components/card/_styles.scss +359 -0
  12. package/src/components/card/actions.ts +48 -0
  13. package/src/components/card/api.ts +102 -0
  14. package/src/components/card/card.ts +41 -0
  15. package/src/components/card/config.ts +99 -0
  16. package/src/components/card/constants.ts +69 -0
  17. package/src/components/card/content.ts +48 -0
  18. package/src/components/card/features.ts +228 -0
  19. package/src/components/card/header.ts +88 -0
  20. package/src/components/card/index.ts +19 -0
  21. package/src/components/card/media.ts +52 -0
  22. package/src/components/card/types.ts +174 -0
  23. package/src/components/checkbox/api.ts +82 -0
  24. package/src/components/checkbox/checkbox.ts +75 -0
  25. package/src/components/checkbox/config.ts +90 -0
  26. package/src/components/checkbox/index.ts +4 -0
  27. package/src/components/checkbox/types.ts +146 -0
  28. package/src/components/chip/_styles.scss +372 -0
  29. package/src/components/chip/api.ts +115 -0
  30. package/src/components/chip/chip-set.ts +225 -0
  31. package/src/components/chip/chip.ts +82 -0
  32. package/src/components/chip/config.ts +92 -0
  33. package/src/components/chip/constants.ts +38 -0
  34. package/src/components/chip/index.ts +4 -0
  35. package/src/components/chip/types.ts +172 -0
  36. package/src/components/list/api.ts +72 -0
  37. package/src/components/list/config.ts +43 -0
  38. package/src/components/list/{constants.js → constants.ts} +34 -7
  39. package/src/components/list/features.ts +224 -0
  40. package/src/components/list/index.ts +14 -0
  41. package/src/components/list/list-item.ts +120 -0
  42. package/src/components/list/list.ts +37 -0
  43. package/src/components/list/types.ts +179 -0
  44. package/src/components/list/utils.ts +47 -0
  45. package/src/components/menu/api.ts +119 -0
  46. package/src/components/menu/config.ts +54 -0
  47. package/src/components/menu/constants.ts +154 -0
  48. package/src/components/menu/features/items-manager.ts +457 -0
  49. package/src/components/menu/features/keyboard-navigation.ts +133 -0
  50. package/src/components/menu/features/positioning.ts +127 -0
  51. package/src/components/menu/features/{visibility.js → visibility.ts} +66 -64
  52. package/src/components/menu/index.ts +14 -0
  53. package/src/components/menu/menu-item.ts +43 -0
  54. package/src/components/menu/menu.ts +53 -0
  55. package/src/components/menu/types.ts +178 -0
  56. package/src/components/navigation/api.ts +79 -0
  57. package/src/components/navigation/config.ts +61 -0
  58. package/src/components/navigation/{constants.js → constants.ts} +10 -10
  59. package/src/components/navigation/index.ts +14 -0
  60. package/src/components/navigation/nav-item.ts +148 -0
  61. package/src/components/navigation/navigation.ts +50 -0
  62. package/src/components/navigation/types.ts +212 -0
  63. package/src/components/progress/_styles.scss +204 -0
  64. package/src/components/progress/api.ts +179 -0
  65. package/src/components/progress/config.ts +124 -0
  66. package/src/components/progress/constants.ts +43 -0
  67. package/src/components/progress/index.ts +5 -0
  68. package/src/components/progress/progress.ts +163 -0
  69. package/src/components/progress/types.ts +102 -0
  70. package/src/components/snackbar/api.ts +162 -0
  71. package/src/components/snackbar/config.ts +62 -0
  72. package/src/components/snackbar/{constants.js → constants.ts} +21 -4
  73. package/src/components/snackbar/features.ts +76 -0
  74. package/src/components/snackbar/index.ts +4 -0
  75. package/src/components/snackbar/position.ts +71 -0
  76. package/src/components/snackbar/queue.ts +76 -0
  77. package/src/components/snackbar/snackbar.ts +60 -0
  78. package/src/components/snackbar/types.ts +58 -0
  79. package/src/components/switch/api.ts +77 -0
  80. package/src/components/switch/config.ts +74 -0
  81. package/src/components/switch/index.ts +4 -0
  82. package/src/components/switch/switch.ts +52 -0
  83. package/src/components/switch/types.ts +142 -0
  84. package/src/components/textfield/api.ts +72 -0
  85. package/src/components/textfield/config.ts +54 -0
  86. package/src/components/textfield/{constants.js → constants.ts} +38 -5
  87. package/src/components/textfield/index.ts +4 -0
  88. package/src/components/textfield/textfield.ts +50 -0
  89. package/src/components/textfield/types.ts +139 -0
  90. package/src/core/compose/base.ts +43 -0
  91. package/src/core/compose/component.ts +247 -0
  92. package/src/core/compose/features/checkable.ts +155 -0
  93. package/src/core/compose/features/disabled.ts +116 -0
  94. package/src/core/compose/features/events.ts +65 -0
  95. package/src/core/compose/features/icon.ts +67 -0
  96. package/src/core/compose/features/index.ts +35 -0
  97. package/src/core/compose/features/input.ts +174 -0
  98. package/src/core/compose/features/lifecycle.ts +139 -0
  99. package/src/core/compose/features/position.ts +94 -0
  100. package/src/core/compose/features/ripple.ts +55 -0
  101. package/src/core/compose/features/size.ts +29 -0
  102. package/src/core/compose/features/style.ts +31 -0
  103. package/src/core/compose/features/text.ts +44 -0
  104. package/src/core/compose/features/textinput.ts +225 -0
  105. package/src/core/compose/features/textlabel.ts +92 -0
  106. package/src/core/compose/features/track.ts +84 -0
  107. package/src/core/compose/features/variant.ts +29 -0
  108. package/src/core/compose/features/withEvents.ts +137 -0
  109. package/src/core/compose/index.ts +54 -0
  110. package/src/core/compose/{pipe.js → pipe.ts} +16 -11
  111. package/src/core/config/component-config.ts +136 -0
  112. package/src/core/config.ts +211 -0
  113. package/src/core/dom/{attributes.js → attributes.ts} +11 -11
  114. package/src/core/dom/classes.ts +60 -0
  115. package/src/core/dom/create.ts +188 -0
  116. package/src/core/dom/events.ts +209 -0
  117. package/src/core/dom/index.ts +10 -0
  118. package/src/core/dom/utils.ts +97 -0
  119. package/src/core/index.ts +111 -0
  120. package/src/core/state/disabled.ts +81 -0
  121. package/src/core/state/emitter.ts +94 -0
  122. package/src/core/state/events.ts +88 -0
  123. package/src/core/state/index.ts +16 -0
  124. package/src/core/state/lifecycle.ts +131 -0
  125. package/src/core/state/store.ts +197 -0
  126. package/src/core/utils/index.ts +45 -0
  127. package/src/core/utils/{mobile.js → mobile.ts} +48 -24
  128. package/src/core/utils/object.ts +41 -0
  129. package/src/core/utils/validate.ts +234 -0
  130. package/src/{index.js → index.ts} +4 -2
  131. package/index.js +0 -11
  132. package/src/components/button/api.js +0 -54
  133. package/src/components/button/button.js +0 -81
  134. package/src/components/button/config.js +0 -10
  135. package/src/components/button/constants.js +0 -63
  136. package/src/components/button/index.js +0 -2
  137. package/src/components/checkbox/api.js +0 -45
  138. package/src/components/checkbox/checkbox.js +0 -96
  139. package/src/components/checkbox/index.js +0 -2
  140. package/src/components/container/api.js +0 -42
  141. package/src/components/container/container.js +0 -45
  142. package/src/components/container/index.js +0 -2
  143. package/src/components/container/styles.scss +0 -66
  144. package/src/components/list/index.js +0 -2
  145. package/src/components/list/list-item.js +0 -147
  146. package/src/components/list/list.js +0 -267
  147. package/src/components/menu/api.js +0 -117
  148. package/src/components/menu/constants.js +0 -42
  149. package/src/components/menu/features/items-manager.js +0 -375
  150. package/src/components/menu/features/keyboard-navigation.js +0 -129
  151. package/src/components/menu/features/positioning.js +0 -125
  152. package/src/components/menu/index.js +0 -2
  153. package/src/components/menu/menu-item.js +0 -41
  154. package/src/components/menu/menu.js +0 -54
  155. package/src/components/navigation/api.js +0 -43
  156. package/src/components/navigation/index.js +0 -2
  157. package/src/components/navigation/nav-item.js +0 -137
  158. package/src/components/navigation/navigation.js +0 -55
  159. package/src/components/snackbar/api.js +0 -125
  160. package/src/components/snackbar/features.js +0 -69
  161. package/src/components/snackbar/index.js +0 -2
  162. package/src/components/snackbar/position.js +0 -63
  163. package/src/components/snackbar/queue.js +0 -74
  164. package/src/components/snackbar/snackbar.js +0 -70
  165. package/src/components/switch/api.js +0 -44
  166. package/src/components/switch/index.js +0 -2
  167. package/src/components/switch/switch.js +0 -71
  168. package/src/components/textfield/api.js +0 -49
  169. package/src/components/textfield/index.js +0 -2
  170. package/src/components/textfield/textfield.js +0 -68
  171. package/src/core/build/_ripple.scss +0 -79
  172. package/src/core/build/constants.js +0 -51
  173. package/src/core/build/icon.js +0 -78
  174. package/src/core/build/ripple.js +0 -159
  175. package/src/core/build/text.js +0 -54
  176. package/src/core/compose/base.js +0 -8
  177. package/src/core/compose/component.js +0 -225
  178. package/src/core/compose/features/checkable.js +0 -114
  179. package/src/core/compose/features/disabled.js +0 -64
  180. package/src/core/compose/features/events.js +0 -48
  181. package/src/core/compose/features/icon.js +0 -33
  182. package/src/core/compose/features/index.js +0 -20
  183. package/src/core/compose/features/input.js +0 -100
  184. package/src/core/compose/features/lifecycle.js +0 -69
  185. package/src/core/compose/features/position.js +0 -60
  186. package/src/core/compose/features/ripple.js +0 -32
  187. package/src/core/compose/features/size.js +0 -9
  188. package/src/core/compose/features/style.js +0 -12
  189. package/src/core/compose/features/text.js +0 -17
  190. package/src/core/compose/features/textinput.js +0 -114
  191. package/src/core/compose/features/textlabel.js +0 -28
  192. package/src/core/compose/features/track.js +0 -49
  193. package/src/core/compose/features/variant.js +0 -9
  194. package/src/core/compose/features/withEvents.js +0 -67
  195. package/src/core/compose/index.js +0 -16
  196. package/src/core/config.js +0 -140
  197. package/src/core/dom/classes.js +0 -70
  198. package/src/core/dom/create.js +0 -132
  199. package/src/core/dom/events.js +0 -175
  200. package/src/core/dom/index.js +0 -5
  201. package/src/core/dom/utils.js +0 -22
  202. package/src/core/index.js +0 -23
  203. package/src/core/state/disabled.js +0 -51
  204. package/src/core/state/emitter.js +0 -63
  205. package/src/core/state/events.js +0 -29
  206. package/src/core/state/index.js +0 -6
  207. package/src/core/state/lifecycle.js +0 -64
  208. package/src/core/state/store.js +0 -112
  209. package/src/core/utils/index.js +0 -39
  210. package/src/core/utils/object.js +0 -22
  211. package/src/core/utils/validate.js +0 -37
  212. /package/src/components/checkbox/{styles.scss → _styles.scss} +0 -0
  213. /package/src/components/checkbox/{constants.js → constants.ts} +0 -0
  214. /package/src/components/list/{styles.scss → _styles.scss} +0 -0
  215. /package/src/components/menu/{styles.scss → _styles.scss} +0 -0
  216. /package/src/components/navigation/{styles.scss → _styles.scss} +0 -0
  217. /package/src/components/snackbar/{styles.scss → _styles.scss} +0 -0
  218. /package/src/components/switch/{styles.scss → _styles.scss} +0 -0
  219. /package/src/components/switch/{constants.js → constants.ts} +0 -0
  220. /package/src/components/textfield/{styles.scss → _styles.scss} +0 -0
@@ -1,4 +1,4 @@
1
- // src/components/navigation/constants.js
1
+ // src/components/navigation/constants.ts
2
2
 
3
3
  /**
4
4
  * Navigation variants following Material Design 3
@@ -9,7 +9,7 @@ export const NAV_VARIANTS = {
9
9
  BAR: 'bar', // Bottom or top navigation bar
10
10
  DRAWER_MODAL: 'modal', // Modal drawer overlay
11
11
  DRAWER_STANDARD: 'standard' // Standard permanent drawer
12
- }
12
+ } as const;
13
13
 
14
14
  /**
15
15
  * Navigation positions
@@ -19,7 +19,7 @@ export const NAV_POSITIONS = {
19
19
  RIGHT: 'right',
20
20
  TOP: 'top',
21
21
  BOTTOM: 'bottom'
22
- }
22
+ } as const;
23
23
 
24
24
  /**
25
25
  * Navigation behaviors
@@ -28,7 +28,7 @@ export const NAV_BEHAVIORS = {
28
28
  FIXED: 'fixed', // Always visible
29
29
  DISMISSIBLE: 'dismissible', // Can be dismissed/hidden
30
30
  MODAL: 'modal' // Overlays content with scrim
31
- }
31
+ } as const;
32
32
 
33
33
  /**
34
34
  * Navigation state classes
@@ -41,7 +41,7 @@ export const NAV_STATES = {
41
41
  HOVERED: 'hovered', // Hover state
42
42
  FOCUSED: 'focused', // Keyboard focus state
43
43
  PRESSED: 'pressed' // Press/click state
44
- }
44
+ } as const;
45
45
 
46
46
  /**
47
47
  * Navigation element classes
@@ -61,7 +61,7 @@ export const NAV_CLASSES = {
61
61
  NESTED_CONTAINER: 'nav-nested-container',
62
62
  NESTED_ITEM: 'nav-nested-item',
63
63
  EXPAND_ICON: 'nav-expand-icon'
64
- }
64
+ } as const;
65
65
 
66
66
  /**
67
67
  * Validation schema for navigation configuration
@@ -119,7 +119,7 @@ export const NAV_SCHEMA = {
119
119
  optional: true
120
120
  }
121
121
  }
122
- }
122
+ } as const;
123
123
 
124
124
  /**
125
125
  * Navigation item states
@@ -127,7 +127,7 @@ export const NAV_SCHEMA = {
127
127
  export const NAV_ITEM_STATES = {
128
128
  EXPANDED: 'expanded',
129
129
  COLLAPSED: 'collapsed'
130
- }
130
+ } as const;
131
131
 
132
132
  /**
133
133
  * Navigation item schema
@@ -175,7 +175,7 @@ export const NAV_ITEM_SCHEMA = {
175
175
  default: false
176
176
  }
177
177
  }
178
- }
178
+ } as const;
179
179
 
180
180
  /**
181
181
  * Navigation group schema
@@ -197,4 +197,4 @@ export const NAV_GROUP_SCHEMA = {
197
197
  default: true
198
198
  }
199
199
  }
200
- }
200
+ } as const;
@@ -0,0 +1,14 @@
1
+ // src/components/navigation/index.ts
2
+ export { default } from './navigation'
3
+ export {
4
+ NAV_VARIANTS,
5
+ NAV_POSITIONS,
6
+ NAV_BEHAVIORS,
7
+ NAV_STATES
8
+ } from './constants'
9
+ export {
10
+ NavigationConfig,
11
+ NavigationComponent,
12
+ NavItemConfig,
13
+ NavGroupConfig
14
+ } from './types'
@@ -0,0 +1,148 @@
1
+ // src/components/navigation/nav-item.ts
2
+ import { NavItemConfig } from './types';
3
+
4
+ /**
5
+ * Creates an expand/collapse icon element
6
+ * @param {string} prefix - CSS class prefix
7
+ * @returns {HTMLElement} Expand icon element
8
+ */
9
+ export const createExpandIcon = (prefix: string): HTMLElement => {
10
+ const icon = document.createElement('span');
11
+ icon.className = `${prefix}-nav-expand-icon`;
12
+ icon.innerHTML = `
13
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor">
14
+ <polyline points="9 18 15 12 9 6"></polyline>
15
+ </svg>
16
+ `;
17
+ return icon;
18
+ };
19
+
20
+ /**
21
+ * Creates a nested items container
22
+ * @param {NavItemConfig[]} items - Nested items configuration
23
+ * @param {string} prefix - CSS class prefix
24
+ * @param {Function} createItem - Item creation function
25
+ * @returns {HTMLElement} Nested items container
26
+ */
27
+ export const createNestedContainer = (
28
+ items: NavItemConfig[],
29
+ prefix: string,
30
+ createItem: (config: NavItemConfig, container: HTMLElement, prefix: string) => HTMLElement
31
+ ): HTMLElement => {
32
+ const container = document.createElement('div');
33
+ container.className = `${prefix}-nav-nested-container`;
34
+ container.setAttribute('role', 'group');
35
+ container.hidden = true;
36
+
37
+ items.forEach(itemConfig => {
38
+ createItem(itemConfig, container, prefix);
39
+ });
40
+
41
+ return container;
42
+ };
43
+
44
+ /**
45
+ * Creates a navigation item element
46
+ * @param {NavItemConfig} config - Item configuration
47
+ * @param {HTMLElement} container - Container element
48
+ * @param {string} prefix - CSS class prefix
49
+ * @returns {HTMLElement} Created navigation item
50
+ */
51
+ export const createNavItem = (
52
+ config: NavItemConfig,
53
+ container: HTMLElement,
54
+ prefix: string
55
+ ): HTMLElement => {
56
+ const itemContainer = document.createElement('div');
57
+ itemContainer.className = `${prefix}-nav-item-container`;
58
+
59
+ const item = document.createElement('button');
60
+ item.className = `${prefix}-nav-item`;
61
+ item.setAttribute('role', config.items?.length ? 'button' : 'menuitem');
62
+ item.setAttribute('aria-selected', 'false');
63
+
64
+ if (config.id) {
65
+ item.dataset.id = config.id;
66
+ }
67
+
68
+ if (config.disabled) {
69
+ item.disabled = true;
70
+ item.setAttribute('aria-disabled', 'true');
71
+ }
72
+
73
+ // Add icon if provided
74
+ if (config.icon) {
75
+ const icon = document.createElement('span');
76
+ icon.className = `${prefix}-nav-item-icon`;
77
+ icon.innerHTML = config.icon;
78
+ item.appendChild(icon);
79
+ }
80
+
81
+ // Add label if provided
82
+ if (config.label) {
83
+ const label = document.createElement('span');
84
+ label.className = `${prefix}-nav-item-label`;
85
+ label.textContent = config.label;
86
+ item.appendChild(label);
87
+ item.setAttribute('aria-label', config.label);
88
+ }
89
+
90
+ // Add badge if provided
91
+ if (config.badge) {
92
+ const badge = document.createElement('span');
93
+ badge.className = `${prefix}-nav-item-badge`;
94
+ badge.textContent = config.badge;
95
+ badge.setAttribute('aria-label', `${config.badge} notifications`);
96
+ item.appendChild(badge);
97
+ }
98
+
99
+ itemContainer.appendChild(item);
100
+
101
+ // Handle nested items - only for drawer variant
102
+ if (config.items?.length && container.closest('.mtrl-nav--drawer, .mtrl-nav--drawer-modal, .mtrl-nav--drawer-standard')) {
103
+ const expandIcon = createExpandIcon(prefix);
104
+ item.appendChild(expandIcon);
105
+
106
+ item.setAttribute('aria-expanded', config.expanded ? 'true' : 'false');
107
+ item.setAttribute('aria-haspopup', 'true');
108
+
109
+ const nestedContainer = createNestedContainer(config.items, prefix, createNavItem);
110
+ nestedContainer.hidden = !config.expanded;
111
+ itemContainer.appendChild(nestedContainer);
112
+
113
+ // Handle expand/collapse
114
+ item.addEventListener('click', (event) => {
115
+ event.stopPropagation();
116
+ const isExpanded = item.getAttribute('aria-expanded') === 'true';
117
+ item.setAttribute('aria-expanded', (!isExpanded).toString());
118
+ nestedContainer.hidden = isExpanded;
119
+
120
+ // Toggle expand icon rotation
121
+ if (expandIcon.style) {
122
+ expandIcon.style.transform = isExpanded ? '' : 'rotate(90deg)';
123
+ }
124
+ });
125
+ }
126
+
127
+ container.appendChild(itemContainer);
128
+ return item;
129
+ };
130
+
131
+ /**
132
+ * Recursively gets all nested items from a navigation item
133
+ * @param {HTMLElement} item - Navigation item element
134
+ * @param {string} prefix - CSS class prefix
135
+ * @returns {Array<HTMLElement>} Array of all nested items
136
+ */
137
+ export const getAllNestedItems = (item: HTMLElement, prefix: string): HTMLElement[] => {
138
+ const container = item.closest(`.${prefix}-nav-item-container`);
139
+ if (!container) return [];
140
+
141
+ const nestedContainer = container.querySelector(`.${prefix}-nav-nested-container`);
142
+ if (!nestedContainer) return [];
143
+
144
+ const items = Array.from(nestedContainer.querySelectorAll(`.${prefix}-nav-item`)) as HTMLElement[];
145
+ return items.reduce((acc: HTMLElement[], nestedItem: HTMLElement) => {
146
+ return [...acc, nestedItem, ...getAllNestedItems(nestedItem, prefix)];
147
+ }, []);
148
+ };
@@ -0,0 +1,50 @@
1
+ // src/components/navigation/navigation.ts
2
+ import { pipe } from '../../core/compose';
3
+ import { createBase, withElement } from '../../core/compose/component';
4
+ import {
5
+ withEvents,
6
+ withDisabled,
7
+ withLifecycle,
8
+ withVariant,
9
+ withPosition // Import core position feature
10
+ } from '../../core/compose/features';
11
+ import { withAPI } from './api';
12
+ import { withNavItems } from './features/items';
13
+ import { NavigationConfig, NavigationComponent } from './types';
14
+ import {
15
+ createBaseConfig,
16
+ getElementConfig,
17
+ getApiConfig
18
+ } from './config';
19
+
20
+ /**
21
+ * Creates a new Navigation component
22
+ * @param {NavigationConfig} config - Navigation configuration
23
+ * @returns {NavigationComponent} Navigation component instance
24
+ */
25
+ const createNavigation = (config: NavigationConfig = {}): NavigationComponent => {
26
+ const baseConfig = createBaseConfig(config);
27
+
28
+ try {
29
+ const navigation = pipe(
30
+ createBase,
31
+ // First add events system
32
+ withEvents(),
33
+ // Then add the element and other features
34
+ withElement(getElementConfig(baseConfig)),
35
+ withVariant(baseConfig),
36
+ withPosition(baseConfig),
37
+ withNavItems(baseConfig),
38
+ withDisabled(baseConfig),
39
+ withLifecycle(),
40
+ comp => withAPI(getApiConfig(comp))(comp)
41
+ )(baseConfig);
42
+
43
+ return navigation as NavigationComponent;
44
+ } catch (error) {
45
+ console.error('Navigation creation error:', error instanceof Error ? error.message : String(error));
46
+ throw new Error(`Failed to create navigation: ${error instanceof Error ? error.message : String(error)}`);
47
+ }
48
+ };
49
+
50
+ export default createNavigation;
@@ -0,0 +1,212 @@
1
+ // src/components/navigation/types.ts
2
+ import {
3
+ NAV_VARIANTS,
4
+ NAV_POSITIONS,
5
+ NAV_BEHAVIORS
6
+ } from './constants';
7
+
8
+ /**
9
+ * Navigation item configuration
10
+ */
11
+ export interface NavItemConfig {
12
+ /** Unique identifier for the item */
13
+ id: string;
14
+
15
+ /** HTML content for the icon */
16
+ icon: string;
17
+
18
+ /** Text label for the item */
19
+ label: string;
20
+
21
+ /** Optional badge text (notifications, etc.) */
22
+ badge?: string;
23
+
24
+ /** Whether the item is disabled */
25
+ disabled?: boolean;
26
+
27
+ /** Whether the item is active */
28
+ active?: boolean;
29
+
30
+ /** Optional subtitle (for drawer variant) */
31
+ subtitle?: string;
32
+
33
+ /** ID of the group this item belongs to */
34
+ groupId?: string;
35
+
36
+ /** Nested navigation items */
37
+ items?: NavItemConfig[];
38
+
39
+ /** Whether nested items are expanded */
40
+ expanded?: boolean;
41
+ }
42
+
43
+ /**
44
+ * Navigation group configuration
45
+ */
46
+ export interface NavGroupConfig {
47
+ /** Unique identifier for the group */
48
+ id: string;
49
+
50
+ /** Group title text */
51
+ title: string;
52
+
53
+ /** Whether the group is expanded */
54
+ expanded?: boolean;
55
+ }
56
+
57
+ /**
58
+ * Stored item data
59
+ */
60
+ export interface NavItemData {
61
+ /** DOM element for the item */
62
+ element: HTMLElement;
63
+
64
+ /** Item configuration */
65
+ config: NavItemConfig;
66
+ }
67
+
68
+ /**
69
+ * Navigation change event data
70
+ */
71
+ export interface NavChangeEvent {
72
+ /** ID of the active item */
73
+ id: string;
74
+
75
+ /** Item data */
76
+ item: NavItemData;
77
+
78
+ /** Previously active item */
79
+ previousItem: NavItemData | null;
80
+
81
+ /** Path of parent item IDs */
82
+ path: string[];
83
+ }
84
+
85
+ /**
86
+ * Configuration interface for the Navigation component
87
+ */
88
+ export interface NavigationConfig {
89
+ /** Navigation variant */
90
+ variant?: keyof typeof NAV_VARIANTS | string;
91
+
92
+ /** Navigation position */
93
+ position?: keyof typeof NAV_POSITIONS | string;
94
+
95
+ /** Navigation behavior */
96
+ behavior?: keyof typeof NAV_BEHAVIORS | string;
97
+
98
+ /** Initial navigation items */
99
+ items?: NavItemConfig[];
100
+
101
+ /** Navigation groups */
102
+ groups?: NavGroupConfig[];
103
+
104
+ /** Whether the navigation is disabled */
105
+ disabled?: boolean;
106
+
107
+ /** Whether drawer is initially expanded */
108
+ expanded?: boolean;
109
+
110
+ /** Whether to show labels */
111
+ showLabels?: boolean;
112
+
113
+ /** Whether backdrop scrim is enabled */
114
+ scrimEnabled?: boolean;
115
+
116
+ /** ARIA label for accessibility */
117
+ ariaLabel?: string;
118
+
119
+ /** Additional CSS classes */
120
+ class?: string;
121
+
122
+ /** Prefix for class names */
123
+ prefix?: string;
124
+
125
+ /** Component name */
126
+ componentName?: string;
127
+ }
128
+
129
+ /**
130
+ * Navigation component interface
131
+ */
132
+ export interface NavigationComponent {
133
+ /** The root element of the navigation */
134
+ element: HTMLElement;
135
+
136
+ /** Map of all navigation items */
137
+ items: Map<string, NavItemData>;
138
+
139
+ /** Adds a new navigation item */
140
+ addItem: (itemConfig: NavItemConfig) => NavigationComponent;
141
+
142
+ /** Removes a navigation item by ID */
143
+ removeItem: (id: string) => NavigationComponent;
144
+
145
+ /** Retrieves a navigation item by ID */
146
+ getItem: (id: string) => NavItemData | undefined;
147
+
148
+ /** Retrieves all navigation items */
149
+ getAllItems: () => NavItemData[];
150
+
151
+ /** Gets the currently active item */
152
+ getActive: () => NavItemData | null;
153
+
154
+ /** Gets the path to an item (parent IDs) */
155
+ getItemPath: (id: string) => string[];
156
+
157
+ /** Sets an item as active by ID */
158
+ setActive: (id: string) => NavigationComponent;
159
+
160
+ /** Adds event listener */
161
+ on: (event: string, handler: Function) => NavigationComponent;
162
+
163
+ /** Removes event listener */
164
+ off: (event: string, handler: Function) => NavigationComponent;
165
+
166
+ /** Enables the navigation */
167
+ enable: () => NavigationComponent;
168
+
169
+ /** Disables the navigation */
170
+ disable: () => NavigationComponent;
171
+
172
+ /** Destroys the navigation component and cleans up resources */
173
+ destroy: () => void;
174
+ }
175
+
176
+ /**
177
+ * API options interface
178
+ */
179
+ export interface ApiOptions {
180
+ disabled: {
181
+ enable: () => any;
182
+ disable: () => any;
183
+ };
184
+ lifecycle: {
185
+ destroy: () => void;
186
+ };
187
+ }
188
+
189
+ /**
190
+ * Base component interface
191
+ */
192
+ export interface BaseComponent {
193
+ element: HTMLElement;
194
+ emit?: (event: string, data: any) => void;
195
+ on?: (event: string, handler: Function) => any;
196
+ off?: (event: string, handler: Function) => any;
197
+ addItem?: (itemConfig: NavItemConfig) => any;
198
+ removeItem?: (id: string) => any;
199
+ getItem?: (id: string) => NavItemData | undefined;
200
+ getAllItems?: () => NavItemData[];
201
+ getActive?: () => NavItemData | null;
202
+ getItemPath?: (id: string) => string[];
203
+ setActive?: (id: string) => any;
204
+ disabled?: {
205
+ enable: () => any;
206
+ disable: () => any;
207
+ };
208
+ lifecycle?: {
209
+ destroy: () => void;
210
+ };
211
+ [key: string]: any;
212
+ }
@@ -0,0 +1,204 @@
1
+ // src/components/progress/_styles.scss
2
+ @use '../../styles/abstract/base' as base;
3
+ @use '../../styles/abstract/variables' as v;
4
+ @use '../../styles/abstract/functions' as f;
5
+ @use '../../styles/abstract/mixins' as m;
6
+ @use '../../styles/abstract/theme' as t;
7
+
8
+ $component: '#{base.$prefix}-progress';
9
+
10
+ .#{$component} {
11
+ // Base styles
12
+ position: relative;
13
+ display: block;
14
+ overflow: hidden;
15
+
16
+ // Common accessibility attributes
17
+ &[aria-disabled="true"] {
18
+ opacity: 0.38;
19
+ pointer-events: none;
20
+ }
21
+
22
+ // Linear progress variant
23
+ &--linear {
24
+ width: 100%;
25
+ height: 4px; // Default height
26
+
27
+ .#{$component}-track {
28
+ position: absolute;
29
+ top: 0;
30
+ left: 0;
31
+ width: 100%;
32
+ height: 100%;
33
+ background-color: t.color('surface-container-highest');
34
+ }
35
+
36
+ .#{$component}-buffer {
37
+ position: absolute;
38
+ top: 0;
39
+ left: 0;
40
+ height: 100%;
41
+ width: 0;
42
+ background-color: t.alpha('primary', 0.4);
43
+ transition: width 0.3s ease;
44
+ }
45
+
46
+ .#{$component}-indicator {
47
+ position: absolute;
48
+ top: 0;
49
+ left: 0;
50
+ height: 100%;
51
+ width: 0;
52
+ background-color: t.color('primary');
53
+ transition: width 0.3s ease;
54
+ }
55
+
56
+ // Indeterminate animation for linear progress
57
+ &.#{$component}--indeterminate {
58
+ .#{$component}-buffer {
59
+ display: none;
60
+ }
61
+
62
+ .#{$component}-indicator {
63
+ width: 30%;
64
+ animation: linear-indeterminate 2s infinite;
65
+ }
66
+ }
67
+
68
+ .#{$component}-label {
69
+ position: absolute;
70
+ right: 0;
71
+ top: 8px;
72
+ font-size: 12px;
73
+ color: t.color('on-surface-variant');
74
+ }
75
+ }
76
+
77
+ // Circular progress variant
78
+ &--circular {
79
+ display: inline-flex;
80
+ align-items: center;
81
+ justify-content: center;
82
+ width: 48px;
83
+ height: 48px;
84
+
85
+ svg {
86
+ width: 100%;
87
+ height: 100%;
88
+ transform: rotate(-90deg);
89
+ }
90
+
91
+ .#{$component}-track {
92
+ stroke: t.color('surface-container-highest');
93
+ fill: none;
94
+ }
95
+
96
+ .#{$component}-indicator {
97
+ stroke: t.color('primary');
98
+ fill: none;
99
+ stroke-dasharray: 283; // 2*PI*45
100
+ stroke-dashoffset: 283;
101
+ transition: stroke-dashoffset 0.3s ease;
102
+ }
103
+
104
+ // Indeterminate animation for circular progress
105
+ &.#{$component}--indeterminate {
106
+ .#{$component}-indicator {
107
+ animation: circular-indeterminate 1.5s linear infinite;
108
+ }
109
+ }
110
+
111
+ .#{$component}-label {
112
+ position: absolute;
113
+ font-size: 12px;
114
+ color: t.color('on-surface-variant');
115
+ }
116
+ }
117
+
118
+ // Size variants
119
+ &--small {
120
+ &.#{$component}--linear {
121
+ height: 2px;
122
+ }
123
+
124
+ &.#{$component}--circular {
125
+ width: 24px;
126
+ height: 24px;
127
+
128
+ .#{$component}-track,
129
+ .#{$component}-indicator {
130
+ stroke-width: 3;
131
+ }
132
+ }
133
+ }
134
+
135
+ &--medium {
136
+ &.#{$component}--linear {
137
+ height: 4px;
138
+ }
139
+
140
+ &.#{$component}--circular {
141
+ width: 48px;
142
+ height: 48px;
143
+
144
+ .#{$component}-track,
145
+ .#{$component}-indicator {
146
+ stroke-width: 4;
147
+ }
148
+ }
149
+ }
150
+
151
+ &--large {
152
+ &.#{$component}--linear {
153
+ height: 8px;
154
+
155
+ .#{$component}-label {
156
+ font-size: 14px;
157
+ top: 12px;
158
+ }
159
+ }
160
+
161
+ &.#{$component}--circular {
162
+ width: 64px;
163
+ height: 64px;
164
+
165
+ .#{$component}-track,
166
+ .#{$component}-indicator {
167
+ stroke-width: 6;
168
+ }
169
+
170
+ .#{$component}-label {
171
+ font-size: 14px;
172
+ }
173
+ }
174
+ }
175
+
176
+ // Disabled state
177
+ &--disabled {
178
+ opacity: 0.38;
179
+ pointer-events: none;
180
+ }
181
+ }
182
+
183
+ // Keyframes for indeterminate animations
184
+ @keyframes linear-indeterminate {
185
+ 0% {
186
+ left: -30%;
187
+ }
188
+ 100% {
189
+ left: 100%;
190
+ }
191
+ }
192
+
193
+ @keyframes circular-indeterminate {
194
+ 0% {
195
+ stroke-dashoffset: 283;
196
+ }
197
+ 50% {
198
+ stroke-dashoffset: 70;
199
+ }
200
+ 100% {
201
+ stroke-dashoffset: 283;
202
+ transform: rotate(360deg);
203
+ }
204
+ }