mtrl 0.2.7 → 0.2.9
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.
- package/index.ts +2 -0
- package/package.json +14 -3
- package/src/components/badge/api.ts +23 -14
- package/src/components/badge/badge.ts +2 -2
- package/src/components/badge/config.ts +10 -11
- package/src/components/badge/features.ts +15 -10
- package/src/components/badge/index.ts +27 -2
- package/src/components/badge/types.ts +28 -8
- package/src/components/bottom-app-bar/bottom-app-bar.ts +2 -44
- package/src/components/bottom-app-bar/config.ts +1 -45
- package/src/components/bottom-app-bar/index.ts +7 -1
- package/src/components/bottom-app-bar/types.ts +7 -1
- package/src/components/button/button.ts +0 -1
- package/src/components/button/config.ts +1 -2
- package/src/components/button/index.ts +10 -2
- package/src/components/button/types.ts +14 -2
- package/src/components/card/config.ts +17 -9
- package/src/components/card/content.ts +8 -10
- package/src/components/card/features.ts +4 -6
- package/src/components/card/index.ts +29 -2
- package/src/components/card/types.ts +6 -23
- package/src/components/checkbox/config.ts +3 -4
- package/src/components/checkbox/index.ts +1 -2
- package/src/components/checkbox/types.ts +12 -3
- package/src/components/chip/api.ts +170 -221
- package/src/components/chip/chip.ts +34 -302
- package/src/components/chip/config.ts +1 -2
- package/src/components/chip/index.ts +10 -2
- package/src/components/chip/types.ts +224 -35
- package/src/components/datepicker/api.ts +18 -25
- package/src/components/datepicker/config.ts +9 -12
- package/src/components/datepicker/datepicker.ts +7 -12
- package/src/components/datepicker/index.ts +10 -7
- package/src/components/datepicker/render.ts +16 -18
- package/src/components/datepicker/types.ts +164 -35
- package/src/components/datepicker/utils.ts +1 -2
- package/src/components/dialog/api.ts +7 -8
- package/src/components/dialog/config.ts +3 -4
- package/src/components/dialog/features.ts +56 -22
- package/src/components/dialog/index.ts +38 -8
- package/src/components/dialog/types.ts +33 -10
- package/src/components/divider/index.ts +5 -1
- package/src/components/extended-fab/config.ts +6 -2
- package/src/components/extended-fab/index.ts +7 -2
- package/src/components/extended-fab/types.ts +21 -4
- package/src/components/fab/config.ts +3 -4
- package/src/components/fab/fab.ts +1 -1
- package/src/components/fab/index.ts +7 -2
- package/src/components/fab/types.ts +21 -4
- package/src/components/list/config.ts +4 -5
- package/src/components/list/features.ts +6 -7
- package/src/components/list/index.ts +7 -9
- package/src/components/list/list-item.ts +12 -13
- package/src/components/list/types.ts +50 -5
- package/src/components/list/utils.ts +30 -3
- package/src/components/menu/features/items-manager.ts +9 -9
- package/src/components/menu/features/positioning.ts +7 -7
- package/src/components/menu/features/visibility.ts +7 -7
- package/src/components/menu/index.ts +7 -9
- package/src/components/menu/menu-item.ts +6 -6
- package/src/components/menu/menu.ts +22 -0
- package/src/components/menu/types.ts +29 -10
- package/src/components/menu/utils.ts +67 -0
- package/src/components/navigation/api.ts +131 -96
- package/src/components/navigation/config.ts +22 -10
- package/src/components/navigation/features/controller.ts +273 -0
- package/src/components/navigation/features/items.ts +160 -87
- package/src/components/navigation/index.ts +0 -6
- package/src/components/navigation/nav-item.ts +12 -24
- package/src/components/navigation/navigation.ts +21 -8
- package/src/components/navigation/system-types.ts +124 -0
- package/src/components/navigation/system.ts +776 -0
- package/src/components/navigation/types.ts +228 -203
- package/src/components/progress/api.ts +2 -3
- package/src/components/progress/config.ts +2 -3
- package/src/components/progress/index.ts +0 -1
- package/src/components/progress/progress.ts +1 -2
- package/src/components/progress/types.ts +186 -33
- package/src/components/radios/config.ts +1 -1
- package/src/components/radios/index.ts +0 -1
- package/src/components/radios/types.ts +0 -7
- package/src/components/search/config.ts +1 -2
- package/src/components/search/features/search.ts +14 -15
- package/src/components/search/features/states.ts +5 -1
- package/src/components/search/features/structure.ts +3 -4
- package/src/components/search/index.ts +0 -3
- package/src/components/search/types.ts +18 -6
- package/src/components/segmented-button/config.ts +20 -7
- package/src/components/segmented-button/segment.ts +6 -7
- package/src/components/segmented-button/segmented-button.ts +4 -5
- package/src/components/segmented-button/types.ts +37 -2
- package/src/components/slider/config.ts +20 -2
- package/src/components/slider/features/controller.ts +761 -0
- package/src/components/slider/features/handlers.ts +18 -15
- package/src/components/slider/features/index.ts +3 -2
- package/src/components/slider/features/range.ts +104 -0
- package/src/components/slider/slider.ts +34 -14
- package/src/components/slider/structure.ts +152 -0
- package/src/components/slider/types.ts +34 -8
- package/src/components/snackbar/config.ts +2 -3
- package/src/components/snackbar/constants.ts +0 -32
- package/src/components/snackbar/index.ts +0 -1
- package/src/components/snackbar/position.ts +9 -1
- package/src/components/snackbar/types.ts +122 -46
- package/src/components/switch/config.ts +2 -3
- package/src/components/switch/index.ts +0 -1
- package/src/components/switch/types.ts +3 -2
- package/src/components/tabs/config.ts +3 -4
- package/src/components/tabs/index.ts +0 -15
- package/src/components/tabs/tab-api.ts +12 -4
- package/src/components/tabs/tab.ts +18 -6
- package/src/components/tabs/types.ts +13 -3
- package/src/components/textfield/api.ts +53 -0
- package/src/components/textfield/config.ts +2 -3
- package/src/components/textfield/features.ts +322 -0
- package/src/components/textfield/index.ts +0 -1
- package/src/components/textfield/textfield.ts +8 -0
- package/src/components/textfield/types.ts +29 -6
- package/src/components/timepicker/api.ts +1 -1
- package/src/components/timepicker/clockdial.ts +2 -5
- package/src/components/timepicker/config.ts +102 -4
- package/src/components/timepicker/index.ts +1 -6
- package/src/components/timepicker/render.ts +1 -1
- package/src/components/timepicker/timepicker.ts +1 -1
- package/src/components/tooltip/api.ts +1 -1
- package/src/components/tooltip/config.ts +27 -6
- package/src/components/tooltip/index.ts +0 -1
- package/src/components/tooltip/types.ts +13 -3
- package/src/core/compose/features/textinput.ts +15 -2
- package/src/core/compose/features/textlabel.ts +0 -3
- package/src/core/composition/features/dom.ts +33 -0
- package/src/core/composition/features/icon.ts +131 -0
- package/src/core/composition/features/index.ts +11 -0
- package/src/core/composition/features/label.ts +156 -0
- package/src/core/composition/features/structure.ts +22 -0
- package/src/core/composition/index.ts +26 -0
- package/src/core/index.ts +1 -1
- package/src/core/structure.ts +288 -0
- package/src/index.ts +1 -0
- package/src/styles/components/_navigation-mobile.scss +244 -0
- package/src/styles/components/_navigation-system.scss +151 -0
- package/src/{components/tabs/_styles.scss → styles/components/_tabs.scss} +1 -1
- package/src/{components/textfield/_styles.scss → styles/components/_textfield.scss} +314 -72
- package/src/styles/main.scss +98 -49
- package/src/components/badge/constants.ts +0 -40
- package/src/components/button/constants.ts +0 -11
- package/src/components/card/constants.ts +0 -84
- package/src/components/datepicker/constants.ts +0 -98
- package/src/components/dialog/constants.ts +0 -32
- package/src/components/extended-fab/constants.ts +0 -36
- package/src/components/fab/constants.ts +0 -41
- package/src/components/menu/constants.ts +0 -154
- package/src/components/navigation/constants.ts +0 -200
- package/src/components/progress/constants.ts +0 -29
- package/src/components/search/constants.ts +0 -21
- package/src/components/segmented-button/constants.ts +0 -42
- package/src/components/slider/features/slider.ts +0 -318
- package/src/components/slider/features/structure.ts +0 -181
- package/src/components/slider/features/ui.ts +0 -388
- package/src/components/switch/constants.ts +0 -80
- package/src/components/tabs/constants.ts +0 -89
- package/src/components/textfield/constants.ts +0 -100
- package/src/components/timepicker/constants.ts +0 -138
- /package/src/{components/badge/_styles.scss → styles/components/_badge.scss} +0 -0
- /package/src/{components/bottom-app-bar/_styles.scss → styles/components/_bottom-app-bar.scss} +0 -0
- /package/src/{components/button/_styles.scss → styles/components/_button.scss} +0 -0
- /package/src/{components/card/_styles.scss → styles/components/_card.scss} +0 -0
- /package/src/{components/carousel/_styles.scss → styles/components/_carousel.scss} +0 -0
- /package/src/{components/checkbox/_styles.scss → styles/components/_checkbox.scss} +0 -0
- /package/src/{components/chip/_styles.scss → styles/components/_chip.scss} +0 -0
- /package/src/{components/datepicker/_styles.scss → styles/components/_datepicker.scss} +0 -0
- /package/src/{components/dialog/_styles.scss → styles/components/_dialog.scss} +0 -0
- /package/src/{components/divider/_styles.scss → styles/components/_divider.scss} +0 -0
- /package/src/{components/extended-fab/_styles.scss → styles/components/_extended-fab.scss} +0 -0
- /package/src/{components/fab/_styles.scss → styles/components/_fab.scss} +0 -0
- /package/src/{components/list/_styles.scss → styles/components/_list.scss} +0 -0
- /package/src/{components/menu/_styles.scss → styles/components/_menu.scss} +0 -0
- /package/src/{components/navigation/_styles.scss → styles/components/_navigation.scss} +0 -0
- /package/src/{components/progress/_styles.scss → styles/components/_progress.scss} +0 -0
- /package/src/{components/radios/_styles.scss → styles/components/_radios.scss} +0 -0
- /package/src/{components/search/_styles.scss → styles/components/_search.scss} +0 -0
- /package/src/{components/segmented-button/_styles.scss → styles/components/_segmented-button.scss} +0 -0
- /package/src/{components/sheet/_styles.scss → styles/components/_sheet.scss} +0 -0
- /package/src/{components/slider/_styles.scss → styles/components/_slider.scss} +0 -0
- /package/src/{components/snackbar/_styles.scss → styles/components/_snackbar.scss} +0 -0
- /package/src/{components/switch/_styles.scss → styles/components/_switch.scss} +0 -0
- /package/src/{components/timepicker/_styles.scss → styles/components/_timepicker.scss} +0 -0
- /package/src/{components/tooltip/_styles.scss → styles/components/_tooltip.scss} +0 -0
- /package/src/{components/top-app-bar/_styles.scss → styles/components/_top-app-bar.scss} +0 -0
- /package/src/styles/utilities/{_color.scss → _colors.scss} +0 -0
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
// src/components/textfield/features.ts
|
|
2
|
+
import { BaseComponent, ElementComponent } from '../../core/compose/component';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Configuration for leading icon feature
|
|
6
|
+
*/
|
|
7
|
+
export interface LeadingIconConfig {
|
|
8
|
+
/**
|
|
9
|
+
* Leading icon HTML content
|
|
10
|
+
*/
|
|
11
|
+
leadingIcon?: string;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* CSS class prefix
|
|
15
|
+
*/
|
|
16
|
+
prefix?: string;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Component name
|
|
20
|
+
*/
|
|
21
|
+
componentName?: string;
|
|
22
|
+
|
|
23
|
+
[key: string]: any;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Configuration for trailing icon feature
|
|
28
|
+
*/
|
|
29
|
+
export interface TrailingIconConfig {
|
|
30
|
+
/**
|
|
31
|
+
* Trailing icon HTML content
|
|
32
|
+
*/
|
|
33
|
+
trailingIcon?: string;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* CSS class prefix
|
|
37
|
+
*/
|
|
38
|
+
prefix?: string;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Component name
|
|
42
|
+
*/
|
|
43
|
+
componentName?: string;
|
|
44
|
+
|
|
45
|
+
[key: string]: any;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Configuration for supporting text feature
|
|
50
|
+
*/
|
|
51
|
+
export interface SupportingTextConfig {
|
|
52
|
+
/**
|
|
53
|
+
* Supporting text content
|
|
54
|
+
*/
|
|
55
|
+
supportingText?: string;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Whether supporting text indicates an error
|
|
59
|
+
*/
|
|
60
|
+
error?: boolean;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* CSS class prefix
|
|
64
|
+
*/
|
|
65
|
+
prefix?: string;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Component name
|
|
69
|
+
*/
|
|
70
|
+
componentName?: string;
|
|
71
|
+
|
|
72
|
+
[key: string]: any;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Component with leading icon capabilities
|
|
77
|
+
*/
|
|
78
|
+
export interface LeadingIconComponent extends BaseComponent {
|
|
79
|
+
/**
|
|
80
|
+
* Leading icon element
|
|
81
|
+
*/
|
|
82
|
+
leadingIcon: HTMLElement | null;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Sets leading icon content
|
|
86
|
+
* @param html - HTML content for the icon
|
|
87
|
+
* @returns Component instance for chaining
|
|
88
|
+
*/
|
|
89
|
+
setLeadingIcon: (html: string) => LeadingIconComponent;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Removes leading icon
|
|
93
|
+
* @returns Component instance for chaining
|
|
94
|
+
*/
|
|
95
|
+
removeLeadingIcon: () => LeadingIconComponent;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Component with trailing icon capabilities
|
|
100
|
+
*/
|
|
101
|
+
export interface TrailingIconComponent extends BaseComponent {
|
|
102
|
+
/**
|
|
103
|
+
* Trailing icon element
|
|
104
|
+
*/
|
|
105
|
+
trailingIcon: HTMLElement | null;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Sets trailing icon content
|
|
109
|
+
* @param html - HTML content for the icon
|
|
110
|
+
* @returns Component instance for chaining
|
|
111
|
+
*/
|
|
112
|
+
setTrailingIcon: (html: string) => TrailingIconComponent;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Removes trailing icon
|
|
116
|
+
* @returns Component instance for chaining
|
|
117
|
+
*/
|
|
118
|
+
removeTrailingIcon: () => TrailingIconComponent;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Component with supporting text capabilities
|
|
123
|
+
*/
|
|
124
|
+
export interface SupportingTextComponent extends BaseComponent {
|
|
125
|
+
/**
|
|
126
|
+
* Supporting text element
|
|
127
|
+
*/
|
|
128
|
+
supportingTextElement: HTMLElement | null;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Sets supporting text content
|
|
132
|
+
* @param text - Text content
|
|
133
|
+
* @param isError - Whether text represents an error
|
|
134
|
+
* @returns Component instance for chaining
|
|
135
|
+
*/
|
|
136
|
+
setSupportingText: (text: string, isError?: boolean) => SupportingTextComponent;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Removes supporting text
|
|
140
|
+
* @returns Component instance for chaining
|
|
141
|
+
*/
|
|
142
|
+
removeSupportingText: () => SupportingTextComponent;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Creates and manages a leading icon for a component
|
|
147
|
+
* @param config - Configuration object with leading icon settings
|
|
148
|
+
* @returns Function that enhances a component with leading icon functionality
|
|
149
|
+
*/
|
|
150
|
+
export const withLeadingIcon = <T extends LeadingIconConfig>(config: T) =>
|
|
151
|
+
<C extends ElementComponent>(component: C): C & LeadingIconComponent => {
|
|
152
|
+
if (!config.leadingIcon) {
|
|
153
|
+
return component as C & LeadingIconComponent;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Create icon element
|
|
157
|
+
const PREFIX = config.prefix || 'mtrl';
|
|
158
|
+
const iconElement = document.createElement('span');
|
|
159
|
+
iconElement.className = `${PREFIX}-${config.componentName || 'textfield'}-leading-icon`;
|
|
160
|
+
iconElement.innerHTML = config.leadingIcon;
|
|
161
|
+
|
|
162
|
+
// Add leading icon to the component
|
|
163
|
+
component.element.appendChild(iconElement);
|
|
164
|
+
|
|
165
|
+
// Add leading-icon class to the component
|
|
166
|
+
component.element.classList.add(`${PREFIX}-${config.componentName || 'textfield'}--with-leading-icon`);
|
|
167
|
+
|
|
168
|
+
// When there's a leading icon, adjust input padding
|
|
169
|
+
if (component.input) {
|
|
170
|
+
component.input.classList.add(`${PREFIX}-${config.componentName || 'textfield'}-input--with-leading-icon`);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Add lifecycle integration if available
|
|
174
|
+
if ('lifecycle' in component && component.lifecycle?.destroy) {
|
|
175
|
+
const originalDestroy = component.lifecycle.destroy;
|
|
176
|
+
component.lifecycle.destroy = () => {
|
|
177
|
+
iconElement.remove();
|
|
178
|
+
originalDestroy.call(component.lifecycle);
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return {
|
|
183
|
+
...component,
|
|
184
|
+
leadingIcon: iconElement,
|
|
185
|
+
|
|
186
|
+
setLeadingIcon(html: string) {
|
|
187
|
+
iconElement.innerHTML = html;
|
|
188
|
+
return this;
|
|
189
|
+
},
|
|
190
|
+
|
|
191
|
+
removeLeadingIcon() {
|
|
192
|
+
if (iconElement.parentNode) {
|
|
193
|
+
iconElement.remove();
|
|
194
|
+
component.element.classList.remove(`${PREFIX}-${config.componentName || 'textfield'}--with-leading-icon`);
|
|
195
|
+
if (component.input) {
|
|
196
|
+
component.input.classList.remove(`${PREFIX}-${config.componentName || 'textfield'}-input--with-leading-icon`);
|
|
197
|
+
}
|
|
198
|
+
this.leadingIcon = null;
|
|
199
|
+
}
|
|
200
|
+
return this;
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Creates and manages a trailing icon for a component
|
|
207
|
+
* @param config - Configuration object with trailing icon settings
|
|
208
|
+
* @returns Function that enhances a component with trailing icon functionality
|
|
209
|
+
*/
|
|
210
|
+
export const withTrailingIcon = <T extends TrailingIconConfig>(config: T) =>
|
|
211
|
+
<C extends ElementComponent>(component: C): C & TrailingIconComponent => {
|
|
212
|
+
if (!config.trailingIcon) {
|
|
213
|
+
return component as C & TrailingIconComponent;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Create icon element
|
|
217
|
+
const PREFIX = config.prefix || 'mtrl';
|
|
218
|
+
const iconElement = document.createElement('span');
|
|
219
|
+
iconElement.className = `${PREFIX}-${config.componentName || 'textfield'}-trailing-icon`;
|
|
220
|
+
iconElement.innerHTML = config.trailingIcon;
|
|
221
|
+
|
|
222
|
+
// Add trailing icon to the component
|
|
223
|
+
component.element.appendChild(iconElement);
|
|
224
|
+
|
|
225
|
+
// Add trailing-icon class to the component
|
|
226
|
+
component.element.classList.add(`${PREFIX}-${config.componentName || 'textfield'}--with-trailing-icon`);
|
|
227
|
+
|
|
228
|
+
// When there's a trailing icon, adjust input padding
|
|
229
|
+
if (component.input) {
|
|
230
|
+
component.input.classList.add(`${PREFIX}-${config.componentName || 'textfield'}-input--with-trailing-icon`);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Add lifecycle integration if available
|
|
234
|
+
if ('lifecycle' in component && component.lifecycle?.destroy) {
|
|
235
|
+
const originalDestroy = component.lifecycle.destroy;
|
|
236
|
+
component.lifecycle.destroy = () => {
|
|
237
|
+
iconElement.remove();
|
|
238
|
+
originalDestroy.call(component.lifecycle);
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return {
|
|
243
|
+
...component,
|
|
244
|
+
trailingIcon: iconElement,
|
|
245
|
+
|
|
246
|
+
setTrailingIcon(html: string) {
|
|
247
|
+
iconElement.innerHTML = html;
|
|
248
|
+
return this;
|
|
249
|
+
},
|
|
250
|
+
|
|
251
|
+
removeTrailingIcon() {
|
|
252
|
+
if (iconElement.parentNode) {
|
|
253
|
+
iconElement.remove();
|
|
254
|
+
component.element.classList.remove(`${PREFIX}-${config.componentName || 'textfield'}--with-trailing-icon`);
|
|
255
|
+
if (component.input) {
|
|
256
|
+
component.input.classList.remove(`${PREFIX}-${config.componentName || 'textfield'}-input--with-trailing-icon`);
|
|
257
|
+
}
|
|
258
|
+
this.trailingIcon = null;
|
|
259
|
+
}
|
|
260
|
+
return this;
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Creates and manages supporting text for a component
|
|
267
|
+
* @param config - Configuration object with supporting text settings
|
|
268
|
+
* @returns Function that enhances a component with supporting text functionality
|
|
269
|
+
*/
|
|
270
|
+
export const withSupportingText = <T extends SupportingTextConfig>(config: T) =>
|
|
271
|
+
<C extends ElementComponent>(component: C): C & SupportingTextComponent => {
|
|
272
|
+
if (!config.supportingText) {
|
|
273
|
+
return component as C & SupportingTextComponent;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Create supporting text element
|
|
277
|
+
const PREFIX = config.prefix || 'mtrl';
|
|
278
|
+
const supportingElement = document.createElement('div');
|
|
279
|
+
supportingElement.className = `${PREFIX}-${config.componentName || 'textfield'}-helper`;
|
|
280
|
+
supportingElement.textContent = config.supportingText;
|
|
281
|
+
|
|
282
|
+
if (config.error) {
|
|
283
|
+
supportingElement.classList.add(`${PREFIX}-${config.componentName || 'textfield'}-helper--error`);
|
|
284
|
+
component.element.classList.add(`${PREFIX}-${config.componentName || 'textfield'}--error`);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Add supporting text to the component
|
|
288
|
+
component.element.appendChild(supportingElement);
|
|
289
|
+
|
|
290
|
+
// Add lifecycle integration if available
|
|
291
|
+
if ('lifecycle' in component && component.lifecycle?.destroy) {
|
|
292
|
+
const originalDestroy = component.lifecycle.destroy;
|
|
293
|
+
component.lifecycle.destroy = () => {
|
|
294
|
+
supportingElement.remove();
|
|
295
|
+
originalDestroy.call(component.lifecycle);
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return {
|
|
300
|
+
...component,
|
|
301
|
+
supportingTextElement: supportingElement,
|
|
302
|
+
|
|
303
|
+
setSupportingText(text: string, isError = false) {
|
|
304
|
+
supportingElement.textContent = text;
|
|
305
|
+
|
|
306
|
+
// Handle error state
|
|
307
|
+
supportingElement.classList.toggle(`${PREFIX}-${config.componentName || 'textfield'}-helper--error`, isError);
|
|
308
|
+
component.element.classList.toggle(`${PREFIX}-${config.componentName || 'textfield'}--error`, isError);
|
|
309
|
+
|
|
310
|
+
return this;
|
|
311
|
+
},
|
|
312
|
+
|
|
313
|
+
removeSupportingText() {
|
|
314
|
+
if (supportingElement.parentNode) {
|
|
315
|
+
supportingElement.remove();
|
|
316
|
+
this.supportingTextElement = null;
|
|
317
|
+
component.element.classList.remove(`${PREFIX}-${config.componentName || 'textfield'}--error`);
|
|
318
|
+
}
|
|
319
|
+
return this;
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
};
|
|
@@ -10,6 +10,11 @@ import {
|
|
|
10
10
|
withTextLabel
|
|
11
11
|
} from '../../core/compose/features';
|
|
12
12
|
import { withAPI } from './api';
|
|
13
|
+
import {
|
|
14
|
+
withLeadingIcon,
|
|
15
|
+
withTrailingIcon,
|
|
16
|
+
withSupportingText
|
|
17
|
+
} from './features';
|
|
13
18
|
import { TextfieldConfig, TextfieldComponent } from './types';
|
|
14
19
|
import {
|
|
15
20
|
createBaseConfig,
|
|
@@ -33,6 +38,9 @@ const createTextfield = (config: TextfieldConfig = {}): TextfieldComponent => {
|
|
|
33
38
|
withVariant(baseConfig),
|
|
34
39
|
withTextInput(baseConfig),
|
|
35
40
|
withTextLabel(baseConfig),
|
|
41
|
+
withLeadingIcon(baseConfig),
|
|
42
|
+
withTrailingIcon(baseConfig),
|
|
43
|
+
withSupportingText(baseConfig),
|
|
36
44
|
withDisabled(baseConfig),
|
|
37
45
|
withLifecycle(),
|
|
38
46
|
comp => withAPI(getApiConfig(comp))(comp)
|
|
@@ -1,15 +1,29 @@
|
|
|
1
1
|
// src/components/textfield/types.ts
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Available Textfield variants
|
|
5
|
+
*/
|
|
6
|
+
export type TextfieldVariant = 'filled' | 'outlined';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Available Textfield states
|
|
10
|
+
*/
|
|
11
|
+
export type TextfieldStates = 'active' | 'inactive' | 'disabled';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Available Textfield types
|
|
15
|
+
*/
|
|
16
|
+
export type TextfieldTypes = 'text' | 'password' | 'email' | 'number' | 'tel' | 'url' | 'search' | 'multiline';
|
|
3
17
|
|
|
4
18
|
/**
|
|
5
19
|
* Configuration interface for the Textfield component
|
|
6
20
|
*/
|
|
7
21
|
export interface TextfieldConfig {
|
|
8
22
|
/** Input type (text, password, email, etc.) */
|
|
9
|
-
type?:
|
|
23
|
+
type?: TextfieldTypes | string;
|
|
10
24
|
|
|
11
25
|
/** Visual variant (filled, outlined) */
|
|
12
|
-
variant?:
|
|
26
|
+
variant?: TextfieldVariant | string;
|
|
13
27
|
|
|
14
28
|
/** Input name attribute */
|
|
15
29
|
name?: string;
|
|
@@ -17,9 +31,6 @@ export interface TextfieldConfig {
|
|
|
17
31
|
/** Label text */
|
|
18
32
|
label?: string;
|
|
19
33
|
|
|
20
|
-
/** Placeholder text */
|
|
21
|
-
placeholder?: string;
|
|
22
|
-
|
|
23
34
|
/** Initial value */
|
|
24
35
|
value?: string;
|
|
25
36
|
|
|
@@ -38,6 +49,18 @@ export interface TextfieldConfig {
|
|
|
38
49
|
/** Autocomplete attribute */
|
|
39
50
|
autocomplete?: string;
|
|
40
51
|
|
|
52
|
+
/** Leading icon HTML content */
|
|
53
|
+
leadingIcon?: string;
|
|
54
|
+
|
|
55
|
+
/** Trailing icon HTML content */
|
|
56
|
+
trailingIcon?: string;
|
|
57
|
+
|
|
58
|
+
/** Supporting text content */
|
|
59
|
+
supportingText?: string;
|
|
60
|
+
|
|
61
|
+
/** Whether supporting text indicates an error */
|
|
62
|
+
error?: boolean;
|
|
63
|
+
|
|
41
64
|
/** Additional CSS classes */
|
|
42
65
|
class?: string;
|
|
43
66
|
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
TIME_FORMAT,
|
|
10
10
|
TIME_PERIOD
|
|
11
11
|
} from './types';
|
|
12
|
-
import { EVENTS, SELECTORS } from './
|
|
12
|
+
import { EVENTS, SELECTORS } from './config';
|
|
13
13
|
import { formatTime, padZero } from './utils';
|
|
14
14
|
import { renderTimePicker } from './render';
|
|
15
15
|
import { renderClockDial, getTimeValueFromClick } from './clockdial';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/components/timepicker/clockdial.ts
|
|
2
2
|
|
|
3
3
|
import { TimeValue, TIME_FORMAT, TIME_PICKER_TYPE, TIME_PERIOD } from './types';
|
|
4
|
-
import { DIAL_CONSTANTS, TIME_CONSTANTS } from './
|
|
4
|
+
import { DIAL_CONSTANTS, TIME_CONSTANTS } from './config';
|
|
5
5
|
import { padZero } from './utils';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -48,12 +48,9 @@ const CLOCK_CONSTANTS = {
|
|
|
48
48
|
function getThemeColors(prefix: string): ThemeColors {
|
|
49
49
|
const root = document.documentElement;
|
|
50
50
|
const styles = getComputedStyle(root);
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
// Extract primary color
|
|
53
53
|
const primaryColor = styles.getPropertyValue(`--${prefix}-sys-color-primary`).trim() || '#6750A4';
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
console.log('primaryColor', primaryColor)
|
|
57
54
|
|
|
58
55
|
// Extract on-primary color
|
|
59
56
|
const onPrimaryColor = styles.getPropertyValue(`--${prefix}-sys-color-on-primary`).trim() || '#FFFFFF';
|
|
@@ -9,10 +9,108 @@ import { TimePickerConfig } from './types';
|
|
|
9
9
|
import {
|
|
10
10
|
TIME_PICKER_TYPE,
|
|
11
11
|
TIME_PICKER_ORIENTATION,
|
|
12
|
-
TIME_FORMAT
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
TIME_FORMAT
|
|
13
|
+
} from './types';
|
|
14
|
+
|
|
15
|
+
export const DIAL_CONSTANTS = {
|
|
16
|
+
DIAMETER: 256,
|
|
17
|
+
INNER_RADIUS: 65,
|
|
18
|
+
OUTER_RADIUS: 110,
|
|
19
|
+
NUMBER_SIZE: 40,
|
|
20
|
+
CENTER_SIZE: 8,
|
|
21
|
+
HAND_SIZE: 36,
|
|
22
|
+
TRACK_WIDTH: 2,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Time constants used in the time picker.
|
|
27
|
+
*/
|
|
28
|
+
export const TIME_CONSTANTS = {
|
|
29
|
+
HOURS_12: Array.from({ length: 12 }, (_, i) => (i === 0 ? 12 : i)),
|
|
30
|
+
HOURS_24: Array.from({ length: 24 }, (_, i) => i),
|
|
31
|
+
MINUTES: Array.from({ length: 60 }, (_, i) => i),
|
|
32
|
+
SECONDS: Array.from({ length: 60 }, (_, i) => i),
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Custom events fired by the time picker.
|
|
37
|
+
*/
|
|
38
|
+
export const EVENTS = {
|
|
39
|
+
CHANGE: 'change',
|
|
40
|
+
OPEN: 'open',
|
|
41
|
+
CLOSE: 'close',
|
|
42
|
+
CONFIRM: 'confirm',
|
|
43
|
+
CANCEL: 'cancel',
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Element selectors for time picker components.
|
|
48
|
+
* Used for DOM manipulation and event delegation.
|
|
49
|
+
*/
|
|
50
|
+
export const SELECTORS = {
|
|
51
|
+
CONTAINER: '.mtrl-time-picker',
|
|
52
|
+
MODAL: '.mtrl-time-picker-modal',
|
|
53
|
+
DIALOG: '.mtrl-time-picker-dialog',
|
|
54
|
+
TITLE: '.mtrl-time-picker-title',
|
|
55
|
+
CONTENT: '.mtrl-time-picker-content',
|
|
56
|
+
DIAL: '.mtrl-time-picker-dial',
|
|
57
|
+
DIAL_CANVAS: '.mtrl-time-picker-dial-canvas',
|
|
58
|
+
DIAL_FACE: '.mtrl-time-picker-dial-face',
|
|
59
|
+
DIAL_HAND: '.mtrl-time-picker-dial-hand',
|
|
60
|
+
DIAL_CENTER: '.mtrl-time-picker-dial-center',
|
|
61
|
+
DIAL_NUMBERS: '.mtrl-time-picker-dial-numbers',
|
|
62
|
+
DIAL_NUMBER: '.mtrl-time-picker-dial-number',
|
|
63
|
+
INPUT_CONTAINER: '.mtrl-time-picker-input-container',
|
|
64
|
+
HOURS_INPUT: '.mtrl-time-picker-hours',
|
|
65
|
+
MINUTES_INPUT: '.mtrl-time-picker-minutes',
|
|
66
|
+
SECONDS_INPUT: '.mtrl-time-picker-seconds',
|
|
67
|
+
SEPARATOR: '.mtrl-time-picker-separator',
|
|
68
|
+
PERIOD_CONTAINER: '.mtrl-time-picker-period',
|
|
69
|
+
PERIOD_AM: '.mtrl-time-picker-period-am',
|
|
70
|
+
PERIOD_PM: '.mtrl-time-picker-period-pm',
|
|
71
|
+
ACTIONS: '.mtrl-time-picker-actions',
|
|
72
|
+
TOGGLE_TYPE_BUTTON: '.mtrl-time-picker-toggle-type',
|
|
73
|
+
CANCEL_BUTTON: '.mtrl-time-picker-cancel',
|
|
74
|
+
CONFIRM_BUTTON: '.mtrl-time-picker-confirm',
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Z-index values for different parts of the time picker.
|
|
79
|
+
*/
|
|
80
|
+
export const Z_INDEX = {
|
|
81
|
+
MODAL: 1050,
|
|
82
|
+
DIALOG: 1051,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Default clock icon for time picker.
|
|
87
|
+
* Simple clock SVG.
|
|
88
|
+
*/
|
|
89
|
+
export const DEFAULT_CLOCK_ICON = `
|
|
90
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
91
|
+
<circle cx="12" cy="12" r="10"></circle>
|
|
92
|
+
<polyline points="12 6 12 12 16 14"></polyline>
|
|
93
|
+
</svg>
|
|
94
|
+
`
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Default keyboard icon for time picker.
|
|
98
|
+
* Simple keyboard SVG.
|
|
99
|
+
*/
|
|
100
|
+
export const DEFAULT_KEYBOARD_ICON = `
|
|
101
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
102
|
+
<rect x="2" y="4" width="20" height="16" rx="2" ry="2"></rect>
|
|
103
|
+
<line x1="6" y1="8" x2="6" y2="8"></line>
|
|
104
|
+
<line x1="10" y1="8" x2="10" y2="8"></line>
|
|
105
|
+
<line x1="14" y1="8" x2="14" y2="8"></line>
|
|
106
|
+
<line x1="18" y1="8" x2="18" y2="8"></line>
|
|
107
|
+
<line x1="6" y1="12" x2="6" y2="12"></line>
|
|
108
|
+
<line x1="10" y1="12" x2="10" y2="12"></line>
|
|
109
|
+
<line x1="14" y1="12" x2="14" y2="12"></line>
|
|
110
|
+
<line x1="18" y1="12" x2="18" y2="12"></line>
|
|
111
|
+
<line x1="6" y1="16" x2="18" y2="16"></line>
|
|
112
|
+
</svg>
|
|
113
|
+
`;
|
|
16
114
|
|
|
17
115
|
/**
|
|
18
116
|
* Default configuration for the TimePicker component
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
+
// src/components/timepicker/index.ts
|
|
1
2
|
export { default } from './timepicker';
|
|
2
|
-
export {
|
|
3
|
-
TIME_PICKER_TYPE,
|
|
4
|
-
TIME_PICKER_ORIENTATION,
|
|
5
|
-
TIME_FORMAT,
|
|
6
|
-
TIME_PERIOD
|
|
7
|
-
} from './constants';
|
|
8
3
|
export type { TimePickerConfig, TimePickerComponent, TimeValue } from './types';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/components/tooltip/api.ts
|
|
2
2
|
import { TooltipComponent } from './types';
|
|
3
|
-
import { TOOLTIP_POSITIONS, DEFAULT_OFFSET, DEFAULT_ARROW_SIZE } from './
|
|
3
|
+
import { TOOLTIP_POSITIONS, DEFAULT_OFFSET, DEFAULT_ARROW_SIZE } from './config';
|
|
4
4
|
|
|
5
5
|
interface ApiOptions {
|
|
6
6
|
lifecycle: {
|
|
@@ -4,12 +4,33 @@ import {
|
|
|
4
4
|
createElementConfig
|
|
5
5
|
} from '../../core/config/component-config';
|
|
6
6
|
import { TooltipConfig } from './types';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
export const TOOLTIP_POSITIONS = {
|
|
10
|
+
TOP: 'top',
|
|
11
|
+
RIGHT: 'right',
|
|
12
|
+
BOTTOM: 'bottom',
|
|
13
|
+
LEFT: 'left',
|
|
14
|
+
TOP_START: 'top-start',
|
|
15
|
+
TOP_END: 'top-end',
|
|
16
|
+
RIGHT_START: 'right-start',
|
|
17
|
+
RIGHT_END: 'right-end',
|
|
18
|
+
BOTTOM_START: 'bottom-start',
|
|
19
|
+
BOTTOM_END: 'bottom-end',
|
|
20
|
+
LEFT_START: 'left-start',
|
|
21
|
+
LEFT_END: 'left-end'
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const TOOLTIP_VARIANTS = {
|
|
25
|
+
DEFAULT: 'default',
|
|
26
|
+
RICH: 'rich',
|
|
27
|
+
PLAIN: 'plain'
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const DEFAULT_SHOW_DELAY = 300
|
|
31
|
+
export const DEFAULT_HIDE_DELAY = 100
|
|
32
|
+
export const DEFAULT_OFFSET = 8
|
|
33
|
+
export const DEFAULT_ARROW_SIZE = 8
|
|
13
34
|
|
|
14
35
|
/**
|
|
15
36
|
* Default configuration for the Tooltip component
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
// src/components/tooltip/types.ts
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Available Textfield variants
|
|
5
|
+
*/
|
|
6
|
+
export type TooltipVariant = 'default' | 'rich' | 'plain';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Available Textfield states
|
|
10
|
+
*/
|
|
11
|
+
export type TooltipPosition = 'top' | 'right' | 'bottom' | 'left' | 'top-start' | 'top-end' | 'right-start' | 'right-end' | 'bottom-start' | 'bottom-end' | 'left-start' | 'left-end';
|
|
12
|
+
|
|
3
13
|
|
|
4
14
|
/**
|
|
5
15
|
* Configuration interface for the Tooltip component
|
|
@@ -22,13 +32,13 @@ export interface TooltipConfig {
|
|
|
22
32
|
* Tooltip position relative to the target
|
|
23
33
|
* @default 'bottom'
|
|
24
34
|
*/
|
|
25
|
-
position?:
|
|
35
|
+
position?: TooltipPosition | string;
|
|
26
36
|
|
|
27
37
|
/**
|
|
28
38
|
* Tooltip variant that determines visual styling
|
|
29
39
|
* @default 'default'
|
|
30
40
|
*/
|
|
31
|
-
variant?:
|
|
41
|
+
variant?: TooltipVariants | string;
|
|
32
42
|
|
|
33
43
|
/**
|
|
34
44
|
* Whether the tooltip is initially visible
|