mtrl 0.2.9 → 0.3.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 (44) hide show
  1. package/index.ts +2 -0
  2. package/package.json +1 -1
  3. package/src/components/button/button.ts +34 -5
  4. package/src/components/navigation/system/core.ts +302 -0
  5. package/src/components/navigation/system/events.ts +240 -0
  6. package/src/components/navigation/system/index.ts +184 -0
  7. package/src/components/navigation/system/mobile.ts +278 -0
  8. package/src/components/navigation/system/state.ts +77 -0
  9. package/src/components/navigation/system/types.ts +364 -0
  10. package/src/components/slider/config.ts +2 -2
  11. package/src/components/slider/features/controller.ts +1 -25
  12. package/src/components/slider/features/handlers.ts +0 -1
  13. package/src/components/slider/features/range.ts +7 -7
  14. package/src/components/slider/{structure.ts → schema.ts} +2 -13
  15. package/src/components/slider/slider.ts +3 -2
  16. package/src/components/switch/api.ts +16 -0
  17. package/src/components/switch/config.ts +1 -18
  18. package/src/components/switch/features.ts +198 -0
  19. package/src/components/switch/index.ts +1 -0
  20. package/src/components/switch/switch.ts +3 -3
  21. package/src/components/switch/types.ts +14 -2
  22. package/src/core/composition/features/dom.ts +26 -14
  23. package/src/core/composition/features/icon.ts +18 -18
  24. package/src/core/composition/features/index.ts +3 -2
  25. package/src/core/composition/features/label.ts +16 -17
  26. package/src/core/composition/features/layout.ts +47 -0
  27. package/src/core/composition/index.ts +4 -4
  28. package/src/core/layout/README.md +350 -0
  29. package/src/core/layout/array.ts +181 -0
  30. package/src/core/layout/create.ts +55 -0
  31. package/src/core/layout/index.ts +26 -0
  32. package/src/core/layout/object.ts +124 -0
  33. package/src/core/layout/processor.ts +58 -0
  34. package/src/core/layout/result.ts +85 -0
  35. package/src/core/layout/types.ts +125 -0
  36. package/src/core/layout/utils.ts +136 -0
  37. package/src/styles/abstract/_variables.scss +28 -0
  38. package/src/styles/components/_switch.scss +133 -69
  39. package/src/styles/components/_textfield.scss +9 -16
  40. package/src/components/navigation/system-types.ts +0 -124
  41. package/src/components/navigation/system.ts +0 -776
  42. package/src/core/composition/features/structure.ts +0 -22
  43. package/src/core/layout/index.js +0 -95
  44. package/src/core/structure.ts +0 -288
@@ -1,22 +0,0 @@
1
- // src/core/composition/features/structure.ts
2
-
3
- /**
4
- * Adds structure definition to component without creating DOM
5
- * Now uses the structure from the baseConfig
6
- *
7
- * @param configuration
8
- * @returns Component enhancer with structure definition
9
- */
10
- export const withStructure = (config: SliderConfig) => component => {
11
- // Use the structure definition from the config
12
- if (!config.structureDefinition) {
13
- console.warn('No structure definition found in slider config');
14
- return component;
15
- }
16
-
17
- // Return enhanced component with structure definition
18
- return {
19
- ...component,
20
- structureDefinition: config.structureDefinition
21
- };
22
- };
@@ -1,95 +0,0 @@
1
- import { isObject } from '../utils'
2
-
3
- const createComponent = (Component, options = {}) => {
4
- // Check if Component is a class (has prototype) or function
5
- const isClass = Component.prototype && Component.prototype.constructor === Component
6
-
7
- if (isClass) {
8
- return new Component(options)
9
- }
10
-
11
- return Component(options)
12
- }
13
-
14
- /**
15
- * Recursively creates components based on a provided schema.
16
- *
17
- * @param {Array} schema - An array of components or sub-schemas.
18
- * @param {HTMLElement} container - The container for the current level of components.
19
- * @param {Object} [structure={}] - An accumulator object for components, keyed by name.
20
- * @param {number} [level=0] - The current level of recursion.
21
- * @returns {Object} The structure containing all created components.
22
- */
23
- const createLayout = (schema, container, structure = {}, level = 0, components = []) => {
24
- level++
25
- let component
26
- const object = {}
27
- const fragment = document.createDocumentFragment()
28
-
29
- if (!Array.isArray(schema)) {
30
- console.error('Schema is not an array!', container, level, schema)
31
- }
32
-
33
- for (let i = 0; i < schema.length; i++) {
34
- let name
35
- let options = {}
36
-
37
- if (schema[i] instanceof Object && typeof schema[i] === 'function') {
38
- if (isObject(schema[i + 1])) {
39
- options = schema[i + 1]
40
- } else if (isObject(schema[i + 2])) {
41
- options = schema[i + 2]
42
- }
43
-
44
- if (options.id) {
45
- name = options.id
46
- } else if (typeof schema[i + 1] === 'string') {
47
- name = schema[i + 1]
48
- if (!schema[i].isElement && !schema[i].isComponent) {
49
- options.name = name
50
- }
51
- }
52
-
53
- component = createComponent(schema[i], options)
54
-
55
- const element = component.element || component
56
- if (level === 1) structure.element = element
57
-
58
- if (name) {
59
- structure[name] = component
60
- components.push([name, component])
61
- }
62
-
63
- if (component) {
64
- if (component.insert) component.insert(fragment)
65
- else fragment.appendChild(element)
66
-
67
- if (container) {
68
- // console.log('container', container)
69
- component._container = container
70
- if (component.onInserted) component.onInserted(container)
71
- }
72
- }
73
- } else if (Array.isArray(schema[i])) {
74
- if (!component) component = container
75
- createLayout(schema[i], component, structure, level, components)
76
- }
77
- }
78
-
79
- if (container && fragment.hasChildNodes()) {
80
- const wrapper = container.element || container
81
- wrapper.appendChild(fragment)
82
- }
83
-
84
- function get (name) {
85
- return structure[name] || null
86
- }
87
-
88
- object.component = structure
89
- object.components = components
90
- object.get = get
91
-
92
- return object
93
- }
94
-
95
- export default createLayout
@@ -1,288 +0,0 @@
1
- // src/core/structure.ts
2
- import { createElement } from './dom/create';
3
-
4
- /**
5
- * Type definitions for structure creation
6
- */
7
- export interface ComponentLike {
8
- element: HTMLElement;
9
- destroy?: () => void;
10
- [key: string]: any;
11
- }
12
-
13
- export interface ElementDefinition {
14
- name?: string;
15
- creator?: Function;
16
- options?: Record<string, any>;
17
- children?: Record<string, ElementDefinition>;
18
- }
19
-
20
- export interface StructureDefinition {
21
- element?: ElementDefinition;
22
- [key: string]: ElementDefinition | any;
23
- }
24
-
25
- /**
26
- * Structure result interface with separated structure and utility functions
27
- */
28
- export interface StructureResult {
29
- // The raw structure object with all components
30
- structure: Record<string, any>;
31
-
32
- // Reference to the root element for convenience
33
- element: HTMLElement | ComponentLike;
34
-
35
- // Utility functions
36
- get: (name: string) => any;
37
- getAll: () => Record<string, any>;
38
- destroy: () => void;
39
- }
40
-
41
- /**
42
- * Checks if a value is a component object (has an element property)
43
- * Uses a faster property check before the instanceof check
44
- * @param value Value to check
45
- * @returns True if the value is a component-like object
46
- */
47
- function isComponentLike(value: any): value is ComponentLike {
48
- return value &&
49
- typeof value === 'object' &&
50
- 'element' in value &&
51
- value.element instanceof HTMLElement;
52
- }
53
-
54
- /**
55
- * Creates a document fragment for faster DOM operations when appending multiple children
56
- * @returns DocumentFragment
57
- */
58
- function createFragment(): DocumentFragment {
59
- return document.createDocumentFragment();
60
- }
61
-
62
- /**
63
- * Creates a DOM or component structure based on a structure definition
64
- * @param definition Structure definition object
65
- * @param parentElement Optional parent element to attach structure to
66
- * @returns Object containing the structure and utility functions
67
- */
68
- export function createStructure(
69
- definition: StructureDefinition,
70
- parentElement: HTMLElement | null = null
71
- ): StructureResult {
72
- // Use object literal instead of empty object for faster property access
73
- const structure: Record<string, any> = Object.create(null);
74
-
75
- // Special case for root component creation
76
- if (definition.element && !parentElement) {
77
- const elementDef = definition.element;
78
- const createElementFn = elementDef.creator || createElement;
79
- const rootComponent = createElementFn(elementDef.options);
80
- const rootElement = isComponentLike(rootComponent) ? rootComponent.element : rootComponent;
81
-
82
- structure.element = rootComponent;
83
-
84
- if (elementDef.name) {
85
- structure[elementDef.name] = rootComponent;
86
- }
87
-
88
- if (elementDef.children) {
89
- // Use fragment for better performance when appending multiple children
90
- const fragment = createFragment();
91
- let childKeys = Object.keys(elementDef.children);
92
-
93
- // Process all children first and collect their structures
94
- const childStructures = new Array(childKeys.length);
95
-
96
- for (let i = 0; i < childKeys.length; i++) {
97
- const key = childKeys[i];
98
- const childDef = elementDef.children[key];
99
-
100
- // Create child structure and attach to fragment temporarily
101
- const childResult = createStructure({ [key]: childDef }, fragment);
102
- childStructures[i] = childResult.structure;
103
- }
104
-
105
- // Append fragment to root element (single DOM operation)
106
- rootElement.appendChild(fragment);
107
-
108
- // Now merge all child structures into the main structure
109
- for (let i = 0; i < childStructures.length; i++) {
110
- Object.assign(structure, childStructures[i]);
111
- }
112
- }
113
-
114
- // Create and return the result object with utility functions
115
- return createStructureResult(structure);
116
- }
117
-
118
- // Use fragment if we have multiple elements to append to the parent
119
- const fragment = parentElement ? createFragment() : null;
120
- const keys = Object.keys(definition);
121
- const keyLength = keys.length;
122
-
123
- // Pre-allocate arrays for better performance
124
- const elements = new Array(keyLength);
125
- const childStructuresToMerge = [];
126
-
127
- // First pass: create all elements
128
- for (let i = 0; i < keyLength; i++) {
129
- const key = keys[i];
130
- const def = definition[key];
131
-
132
- // Skip if no definition
133
- if (!def) {
134
- elements[i] = null;
135
- continue;
136
- }
137
-
138
- // Create the element
139
- const createElementFn = def.creator || createElement;
140
- const created = createElementFn(def.options);
141
- elements[i] = created;
142
-
143
- // Add to structure
144
- structure[key] = created;
145
-
146
- // Add element to structure with its name if different from key
147
- if (def.name && def.name !== key) {
148
- structure[def.name] = created;
149
- }
150
- }
151
-
152
- // Second pass: handle children and append to parent
153
- for (let i = 0; i < keyLength; i++) {
154
- const key = keys[i];
155
- const def = definition[key];
156
- const created = elements[i];
157
-
158
- if (!created || !def) continue;
159
-
160
- // Get the actual DOM element
161
- const element = isComponentLike(created) ? created.element : created;
162
-
163
- // Append to fragment
164
- if (fragment) {
165
- fragment.appendChild(element);
166
- }
167
-
168
- // Process children recursively
169
- if (def.children) {
170
- const childResult = createStructure(def.children, element);
171
- childStructuresToMerge.push(childResult.structure);
172
- }
173
- }
174
-
175
- // Append fragment to parent (single DOM operation)
176
- if (parentElement && fragment) {
177
- parentElement.appendChild(fragment);
178
- }
179
-
180
- // Merge all child structures at once
181
- for (let i = 0; i < childStructuresToMerge.length; i++) {
182
- Object.assign(structure, childStructuresToMerge[i]);
183
- }
184
-
185
- // Create and return the result object with utility functions
186
- return createStructureResult(structure);
187
- }
188
-
189
- /**
190
- * Creates a result object with the structure and utility functions
191
- * @param structure The raw structure object
192
- * @returns Result object with structure and utility functions
193
- */
194
- function createStructureResult(structure: Record<string, any>): StructureResult {
195
- return {
196
- // Raw structure object
197
- structure,
198
-
199
- // Root element reference for convenience
200
- element: structure.element,
201
-
202
- /**
203
- * Gets a component by name
204
- * @param name Component name
205
- * @returns Component if found, null otherwise
206
- */
207
- get: (name: string): any => {
208
- return structure[name] || null;
209
- },
210
-
211
- /**
212
- * Gets all components in a flattened map
213
- * @returns Object with all components
214
- */
215
- getAll: (): Record<string, any> => {
216
- return flattenStructure(structure);
217
- },
218
-
219
- /**
220
- * Destroys the structure, cleaning up all components
221
- */
222
- destroy: (): void => {
223
- // Clean up the root element if it exists
224
- if (structure.element) {
225
- // If element is a component with a destroy method, call it
226
- if (isComponentLike(structure.element) && typeof structure.element.destroy === 'function') {
227
- structure.element.destroy();
228
- }
229
- // Otherwise, if it's a DOM element or component, remove it from the DOM
230
- else if (isComponentLike(structure.element) && structure.element.element.parentNode) {
231
- structure.element.element.parentNode.removeChild(structure.element.element);
232
- }
233
- else if (structure.element instanceof HTMLElement && structure.element.parentNode) {
234
- structure.element.parentNode.removeChild(structure.element);
235
- }
236
- }
237
-
238
- // Clean up all other components in the structure
239
- Object.keys(structure).forEach(key => {
240
- if (key === 'element') {
241
- return; // Already handled element
242
- }
243
-
244
- const item = structure[key];
245
-
246
- // Handle component objects
247
- if (isComponentLike(item) && typeof item.destroy === 'function') {
248
- item.destroy();
249
- }
250
- // Handle DOM elements
251
- else if (item instanceof HTMLElement && item.parentNode) {
252
- item.parentNode.removeChild(item);
253
- }
254
- });
255
- }
256
- };
257
- }
258
-
259
- /**
260
- * Flattens a nested structure into a simple object with element and component references
261
- * Optimized version that avoids unnecessary type checks where possible
262
- * @param structure Structure object
263
- * @returns Flattened structure with all elements and components
264
- */
265
- export function flattenStructure(structure: Record<string, any>): Record<string, any> {
266
- const flattened: Record<string, any> = Object.create(null);
267
- const keys = Object.keys(structure);
268
-
269
- for (let i = 0; i < keys.length; i++) {
270
- const key = keys[i];
271
- const value = structure[key];
272
-
273
- // Fast path for common cases
274
- if (value instanceof HTMLElement ||
275
- (value && typeof value === 'object' && 'element' in value)) {
276
- flattened[key] = value;
277
- continue;
278
- }
279
-
280
- // Skip functions and other non-element/component objects
281
- if (typeof value !== 'function' &&
282
- (value instanceof Element || isComponentLike(value))) {
283
- flattened[key] = value;
284
- }
285
- }
286
-
287
- return flattened;
288
- }