mtrl 0.3.3 → 0.3.6
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/package.json +1 -1
- package/src/components/menu/api.ts +143 -268
- package/src/components/menu/config.ts +84 -40
- package/src/components/menu/features/anchor.ts +159 -0
- package/src/components/menu/features/controller.ts +970 -0
- package/src/components/menu/features/index.ts +4 -0
- package/src/components/menu/index.ts +31 -63
- package/src/components/menu/menu.ts +107 -97
- package/src/components/menu/types.ts +263 -447
- package/src/components/segmented-button/config.ts +59 -20
- package/src/components/segmented-button/index.ts +1 -1
- package/src/components/segmented-button/segment.ts +51 -97
- package/src/components/segmented-button/segmented-button.ts +114 -2
- package/src/components/segmented-button/types.ts +52 -0
- package/src/core/compose/features/icon.ts +15 -13
- package/src/core/dom/classes.ts +81 -9
- package/src/core/dom/create.ts +30 -19
- package/src/core/layout/README.md +531 -166
- package/src/core/layout/array.ts +3 -4
- package/src/core/layout/config.ts +193 -0
- package/src/core/layout/create.ts +1 -2
- package/src/core/layout/index.ts +12 -2
- package/src/core/layout/object.ts +2 -3
- package/src/core/layout/processor.ts +60 -12
- package/src/core/layout/result.ts +1 -2
- package/src/core/layout/types.ts +105 -50
- package/src/core/layout/utils.ts +69 -61
- package/src/index.ts +2 -1
- package/src/styles/components/_button.scss +6 -0
- package/src/styles/components/_chip.scss +4 -5
- package/src/styles/components/_menu.scss +20 -8
- package/src/styles/components/_segmented-button.scss +173 -63
- package/src/styles/main.scss +23 -23
- package/src/styles/utilities/_layout.scss +665 -0
- package/src/components/menu/features/items-manager.ts +0 -457
- package/src/components/menu/features/keyboard-navigation.ts +0 -133
- package/src/components/menu/features/positioning.ts +0 -127
- package/src/components/menu/features/visibility.ts +0 -230
- package/src/components/menu/menu-item.ts +0 -86
- package/src/components/menu/utils.ts +0 -67
- /package/src/{core/build → styles/utilities}/_ripple.scss +0 -0
package/src/core/dom/classes.ts
CHANGED
|
@@ -1,60 +1,132 @@
|
|
|
1
1
|
// src/core/dom/classes.ts
|
|
2
2
|
/**
|
|
3
3
|
* @module core/dom
|
|
4
|
-
* @description DOM manipulation utilities
|
|
4
|
+
* @description DOM manipulation utilities optimized for performance
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { normalizeClasses } from '../utils';
|
|
8
|
+
import { PREFIX } from '../config';
|
|
9
|
+
|
|
10
|
+
// Constant for prefix with dash for better performance
|
|
11
|
+
const PREFIX_WITH_DASH = `${PREFIX}-`;
|
|
8
12
|
|
|
9
13
|
/**
|
|
10
14
|
* Adds multiple classes to an element
|
|
15
|
+
* Automatically adds prefix to classes that don't already have it
|
|
16
|
+
* Optimized for minimal array operations and DOM interactions
|
|
17
|
+
*
|
|
11
18
|
* @param {HTMLElement} element - Target element
|
|
12
19
|
* @param {...(string | string[])} classes - Classes to add
|
|
13
20
|
* @returns {HTMLElement} Modified element
|
|
14
21
|
*/
|
|
15
22
|
export const addClass = (element: HTMLElement, ...classes: (string | string[])[]): HTMLElement => {
|
|
16
23
|
const normalizedClasses = normalizeClasses(...classes);
|
|
17
|
-
|
|
18
|
-
|
|
24
|
+
|
|
25
|
+
// Early return for empty classes
|
|
26
|
+
if (!normalizedClasses.length) return element;
|
|
27
|
+
|
|
28
|
+
// Using DOMTokenList's add() with multiple arguments is faster than multiple add() calls
|
|
29
|
+
// But we need to handle prefixing first
|
|
30
|
+
const prefixedClasses: string[] = [];
|
|
31
|
+
|
|
32
|
+
for (let i = 0; i < normalizedClasses.length; i++) {
|
|
33
|
+
const cls = normalizedClasses[i];
|
|
34
|
+
if (!cls) continue;
|
|
35
|
+
|
|
36
|
+
prefixedClasses.push(
|
|
37
|
+
cls.startsWith(PREFIX_WITH_DASH) ? cls : PREFIX_WITH_DASH + cls
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Add all classes in a single operation if possible
|
|
42
|
+
if (prefixedClasses.length) {
|
|
43
|
+
element.classList.add(...prefixedClasses);
|
|
19
44
|
}
|
|
45
|
+
|
|
20
46
|
return element;
|
|
21
47
|
};
|
|
22
48
|
|
|
23
49
|
/**
|
|
24
50
|
* Removes multiple classes from an element
|
|
51
|
+
* Handles only exact class names as specified (no automatic prefixing)
|
|
52
|
+
* For better performance, clients should know exactly which classes to remove
|
|
53
|
+
*
|
|
25
54
|
* @param {HTMLElement} element - Target element
|
|
26
55
|
* @param {...(string | string[])} classes - Classes to remove
|
|
27
56
|
* @returns {HTMLElement} Modified element
|
|
28
57
|
*/
|
|
29
58
|
export const removeClass = (element: HTMLElement, ...classes: (string | string[])[]): HTMLElement => {
|
|
30
59
|
const normalizedClasses = normalizeClasses(...classes);
|
|
31
|
-
|
|
32
|
-
|
|
60
|
+
|
|
61
|
+
// Early return for empty classes
|
|
62
|
+
if (!normalizedClasses.length) return element;
|
|
63
|
+
|
|
64
|
+
// Prepare prefixed class names
|
|
65
|
+
const prefixedClasses: string[] = [];
|
|
66
|
+
|
|
67
|
+
for (let i = 0; i < normalizedClasses.length; i++) {
|
|
68
|
+
const cls = normalizedClasses[i];
|
|
69
|
+
if (!cls) continue;
|
|
70
|
+
|
|
71
|
+
// Only add the prefixed version
|
|
72
|
+
prefixedClasses.push(
|
|
73
|
+
cls.startsWith(PREFIX_WITH_DASH) ? cls : PREFIX_WITH_DASH + cls
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Remove all classes in a single operation if possible
|
|
78
|
+
if (prefixedClasses.length) {
|
|
79
|
+
element.classList.remove(...prefixedClasses);
|
|
33
80
|
}
|
|
81
|
+
|
|
34
82
|
return element;
|
|
35
83
|
};
|
|
36
84
|
|
|
37
85
|
/**
|
|
38
86
|
* Toggles multiple classes on an element
|
|
87
|
+
* Automatically adds prefix to classes that don't already have it
|
|
88
|
+
*
|
|
39
89
|
* @param {HTMLElement} element - Target element
|
|
40
90
|
* @param {...(string | string[])} classes - Classes to toggle
|
|
41
91
|
* @returns {HTMLElement} Modified element
|
|
42
92
|
*/
|
|
43
93
|
export const toggleClass = (element: HTMLElement, ...classes: (string | string[])[]): HTMLElement => {
|
|
44
94
|
const normalizedClasses = normalizeClasses(...classes);
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
95
|
+
|
|
96
|
+
for (let i = 0; i < normalizedClasses.length; i++) {
|
|
97
|
+
const cls = normalizedClasses[i];
|
|
98
|
+
if (!cls) continue;
|
|
99
|
+
|
|
100
|
+
const prefixedClass = cls.startsWith(PREFIX_WITH_DASH) ? cls : PREFIX_WITH_DASH + cls;
|
|
101
|
+
element.classList.toggle(prefixedClass);
|
|
102
|
+
}
|
|
103
|
+
|
|
48
104
|
return element;
|
|
49
105
|
};
|
|
50
106
|
|
|
51
107
|
/**
|
|
52
108
|
* Checks if an element has all specified classes
|
|
109
|
+
* Automatically adds prefix to classes that don't already have it
|
|
110
|
+
*
|
|
53
111
|
* @param {HTMLElement} element - Target element
|
|
54
112
|
* @param {...(string | string[])} classes - Classes to check
|
|
55
113
|
* @returns {boolean} True if element has all specified classes
|
|
56
114
|
*/
|
|
57
115
|
export const hasClass = (element: HTMLElement, ...classes: (string | string[])[]): boolean => {
|
|
58
116
|
const normalizedClasses = normalizeClasses(...classes);
|
|
59
|
-
|
|
117
|
+
|
|
118
|
+
// Early return for empty classes (technically all are present)
|
|
119
|
+
if (!normalizedClasses.length) return true;
|
|
120
|
+
|
|
121
|
+
for (let i = 0; i < normalizedClasses.length; i++) {
|
|
122
|
+
const cls = normalizedClasses[i];
|
|
123
|
+
if (!cls) continue;
|
|
124
|
+
|
|
125
|
+
const prefixedClass = cls.startsWith(PREFIX_WITH_DASH) ? cls : PREFIX_WITH_DASH + cls;
|
|
126
|
+
if (!element.classList.contains(prefixedClass)) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return true;
|
|
60
132
|
};
|
package/src/core/dom/create.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import { setAttributes } from './attributes';
|
|
8
8
|
import { normalizeClasses } from '../utils';
|
|
9
9
|
import { PREFIX } from '../config';
|
|
10
|
+
import { addClass } from './classes'; // Import addClass
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Event handler function type
|
|
@@ -58,9 +59,22 @@ export interface CreateElementOptions {
|
|
|
58
59
|
data?: Record<string, string>;
|
|
59
60
|
|
|
60
61
|
/**
|
|
61
|
-
* CSS classes
|
|
62
|
+
* CSS classes (will be automatically prefixed with 'mtrl-')
|
|
63
|
+
* Alias for 'className'
|
|
62
64
|
*/
|
|
63
|
-
|
|
65
|
+
class?: string | string[];
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* CSS classes (will be automatically prefixed with 'mtrl-')
|
|
69
|
+
* Alias for 'class'
|
|
70
|
+
*/
|
|
71
|
+
className?: string | string[];
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* CSS classes that will NOT be prefixed
|
|
75
|
+
* Added as-is to the element
|
|
76
|
+
*/
|
|
77
|
+
rawClass?: string | string[];
|
|
64
78
|
|
|
65
79
|
/**
|
|
66
80
|
* HTML attributes
|
|
@@ -95,9 +109,6 @@ export interface EventHandlerStorage {
|
|
|
95
109
|
[eventName: string]: EventHandler;
|
|
96
110
|
}
|
|
97
111
|
|
|
98
|
-
// Constant for prefix with dash
|
|
99
|
-
const PREFIX_WITH_DASH = `${PREFIX}-`;
|
|
100
|
-
|
|
101
112
|
/**
|
|
102
113
|
* Creates a DOM element with the specified options
|
|
103
114
|
*
|
|
@@ -112,7 +123,9 @@ export const createElement = (options: CreateElementOptions = {}): HTMLElement =
|
|
|
112
123
|
text = '',
|
|
113
124
|
id = '',
|
|
114
125
|
data = {},
|
|
126
|
+
class: classOption,
|
|
115
127
|
className,
|
|
128
|
+
rawClass,
|
|
116
129
|
attrs = {},
|
|
117
130
|
forwardEvents = {},
|
|
118
131
|
onCreate,
|
|
@@ -127,14 +140,17 @@ export const createElement = (options: CreateElementOptions = {}): HTMLElement =
|
|
|
127
140
|
if (text) element.textContent = text;
|
|
128
141
|
if (id) element.id = id;
|
|
129
142
|
|
|
130
|
-
// Handle classes
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
143
|
+
// 1. Handle prefixed classes using addClass
|
|
144
|
+
const prefixedClassSource = classOption || className;
|
|
145
|
+
if (prefixedClassSource) {
|
|
146
|
+
addClass(element, prefixedClassSource);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// 2. Handle raw classes (no prefix)
|
|
150
|
+
if (rawClass) {
|
|
151
|
+
const rawClasses = normalizeClasses(rawClass);
|
|
152
|
+
if (rawClasses.length) {
|
|
153
|
+
element.classList.add(...rawClasses);
|
|
138
154
|
}
|
|
139
155
|
}
|
|
140
156
|
|
|
@@ -230,12 +246,7 @@ export const withAttributes = (attrs: Record<string, any>) =>
|
|
|
230
246
|
*/
|
|
231
247
|
export const withClasses = (...classes: (string | string[])[]) =>
|
|
232
248
|
(element: HTMLElement): HTMLElement => {
|
|
233
|
-
|
|
234
|
-
if (normalizedClasses.length) {
|
|
235
|
-
element.classList.add(...normalizedClasses.map(cls =>
|
|
236
|
-
cls && !cls.startsWith(PREFIX_WITH_DASH) ? PREFIX_WITH_DASH + cls : cls
|
|
237
|
-
).filter(Boolean));
|
|
238
|
-
}
|
|
249
|
+
addClass(element, ...classes);
|
|
239
250
|
return element;
|
|
240
251
|
};
|
|
241
252
|
|