mtrl 0.2.8 → 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.
- package/index.ts +4 -0
- package/package.json +1 -1
- package/src/components/button/button.ts +34 -5
- package/src/components/navigation/api.ts +131 -96
- package/src/components/navigation/features/controller.ts +273 -0
- package/src/components/navigation/features/items.ts +133 -64
- package/src/components/navigation/navigation.ts +17 -2
- package/src/components/navigation/system/core.ts +302 -0
- package/src/components/navigation/system/events.ts +240 -0
- package/src/components/navigation/system/index.ts +184 -0
- package/src/components/navigation/system/mobile.ts +278 -0
- package/src/components/navigation/system/state.ts +77 -0
- package/src/components/navigation/system/types.ts +364 -0
- package/src/components/slider/config.ts +20 -2
- package/src/components/slider/features/controller.ts +737 -0
- package/src/components/slider/features/handlers.ts +18 -16
- package/src/components/slider/features/index.ts +3 -2
- package/src/components/slider/features/range.ts +104 -0
- package/src/components/slider/schema.ts +141 -0
- package/src/components/slider/slider.ts +34 -13
- package/src/components/switch/api.ts +16 -0
- package/src/components/switch/config.ts +1 -18
- package/src/components/switch/features.ts +198 -0
- package/src/components/switch/index.ts +1 -0
- package/src/components/switch/switch.ts +3 -3
- package/src/components/switch/types.ts +14 -2
- package/src/components/textfield/api.ts +53 -0
- package/src/components/textfield/features.ts +322 -0
- package/src/components/textfield/textfield.ts +8 -0
- package/src/components/textfield/types.ts +12 -3
- package/src/components/timepicker/clockdial.ts +1 -4
- package/src/core/compose/features/textinput.ts +15 -2
- package/src/core/composition/features/dom.ts +45 -0
- package/src/core/composition/features/icon.ts +131 -0
- package/src/core/composition/features/index.ts +12 -0
- package/src/core/composition/features/label.ts +155 -0
- package/src/core/composition/features/layout.ts +47 -0
- package/src/core/composition/index.ts +26 -0
- package/src/core/index.ts +1 -1
- package/src/core/layout/README.md +350 -0
- package/src/core/layout/array.ts +181 -0
- package/src/core/layout/create.ts +55 -0
- package/src/core/layout/index.ts +26 -0
- package/src/core/layout/object.ts +124 -0
- package/src/core/layout/processor.ts +58 -0
- package/src/core/layout/result.ts +85 -0
- package/src/core/layout/types.ts +125 -0
- package/src/core/layout/utils.ts +136 -0
- package/src/index.ts +1 -0
- package/src/styles/abstract/_variables.scss +28 -0
- package/src/styles/components/_navigation-mobile.scss +244 -0
- package/src/styles/components/_navigation-system.scss +151 -0
- package/src/styles/components/_switch.scss +133 -69
- package/src/styles/components/_textfield.scss +259 -27
- package/demo/build.ts +0 -349
- package/demo/index.html +0 -110
- package/demo/main.js +0 -448
- package/demo/styles.css +0 -239
- package/server.ts +0 -86
- 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/textfield/constants.ts +0 -100
- package/src/core/layout/index.js +0 -95
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// src/core/layout/object.ts
|
|
2
|
+
/**
|
|
3
|
+
* @module core/layout
|
|
4
|
+
* @description Processor for object-based layout schemas
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createElement } from '../dom/create';
|
|
8
|
+
import { Schema, LayoutResult, LayoutOptions } from './types';
|
|
9
|
+
import { isComponent, createFragment, processClassNames } from './utils';
|
|
10
|
+
import { createLayoutResult } from './result';
|
|
11
|
+
import { createComponentInstance } from './processor';
|
|
12
|
+
import { processArraySchema } from './array';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Processes an object-based layout definition
|
|
16
|
+
*
|
|
17
|
+
* @param schema - Object-based layout definition
|
|
18
|
+
* @param parentElement - Optional parent element to attach layout to
|
|
19
|
+
* @param options - Layout creation options
|
|
20
|
+
* @returns Layout result object
|
|
21
|
+
*/
|
|
22
|
+
export function processObjectSchema(
|
|
23
|
+
schema: Schema,
|
|
24
|
+
parentElement: HTMLElement | null = null,
|
|
25
|
+
options: LayoutOptions = {}
|
|
26
|
+
): LayoutResult {
|
|
27
|
+
const layout = {};
|
|
28
|
+
|
|
29
|
+
// Get default creator function from options or use createElement
|
|
30
|
+
const defaultCreator = options.creator || createElement;
|
|
31
|
+
|
|
32
|
+
// Handle root element creation
|
|
33
|
+
if (schema.element && !parentElement) {
|
|
34
|
+
const elementDef = schema.element;
|
|
35
|
+
const createElementFn = elementDef.creator || defaultCreator;
|
|
36
|
+
|
|
37
|
+
// Process class names based on prefix option
|
|
38
|
+
const elementOptions = elementDef.options || {};
|
|
39
|
+
const processedOptions = options.prefix !== false ?
|
|
40
|
+
processClassNames(elementOptions) :
|
|
41
|
+
{ ...elementOptions };
|
|
42
|
+
|
|
43
|
+
const rootComponent = createComponentInstance(createElementFn, processedOptions, options);
|
|
44
|
+
const rootElement = isComponent(rootComponent) ? rootComponent.element : rootComponent;
|
|
45
|
+
|
|
46
|
+
layout.element = rootComponent;
|
|
47
|
+
if (elementDef.name) layout[elementDef.name] = rootComponent;
|
|
48
|
+
|
|
49
|
+
// Process children
|
|
50
|
+
if (elementDef.children) {
|
|
51
|
+
const fragment = createFragment();
|
|
52
|
+
const childLayouts = [];
|
|
53
|
+
|
|
54
|
+
for (const key in elementDef.children) {
|
|
55
|
+
const childResult = processObjectSchema(
|
|
56
|
+
{ [key]: elementDef.children[key] },
|
|
57
|
+
fragment,
|
|
58
|
+
options
|
|
59
|
+
);
|
|
60
|
+
childLayouts.push(childResult.layout);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
rootElement.appendChild(fragment);
|
|
64
|
+
|
|
65
|
+
// Merge child layouts
|
|
66
|
+
for (const childLayout of childLayouts) {
|
|
67
|
+
Object.assign(layout, childLayout);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return createLayoutResult(layout);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Process normal schema elements
|
|
75
|
+
const fragment = parentElement ? createFragment() : null;
|
|
76
|
+
const childLayouts = [];
|
|
77
|
+
|
|
78
|
+
for (const key in schema) {
|
|
79
|
+
const def = schema[key];
|
|
80
|
+
if (!def) continue;
|
|
81
|
+
|
|
82
|
+
// Use appropriate creator
|
|
83
|
+
const elementCreator = def.creator || defaultCreator;
|
|
84
|
+
|
|
85
|
+
// Process class names based on prefix option
|
|
86
|
+
const elementOptions = def.options || {};
|
|
87
|
+
const shouldApplyPrefix =
|
|
88
|
+
'prefix' in elementOptions ? elementOptions.prefix : options.prefix !== false;
|
|
89
|
+
|
|
90
|
+
const processedOptions = shouldApplyPrefix ?
|
|
91
|
+
processClassNames(elementOptions) :
|
|
92
|
+
{ ...elementOptions };
|
|
93
|
+
|
|
94
|
+
// Create element
|
|
95
|
+
const created = createComponentInstance(elementCreator, processedOptions, options);
|
|
96
|
+
|
|
97
|
+
// Store in layout
|
|
98
|
+
layout[key] = created;
|
|
99
|
+
if (def.name && def.name !== key) layout[def.name] = created;
|
|
100
|
+
|
|
101
|
+
// Handle DOM operations
|
|
102
|
+
const element = isComponent(created) ? created.element : created;
|
|
103
|
+
if (fragment) fragment.appendChild(element);
|
|
104
|
+
|
|
105
|
+
// Process children
|
|
106
|
+
if (def.children) {
|
|
107
|
+
const childResult = processObjectSchema(def.children, element, options);
|
|
108
|
+
childLayouts.push(childResult.layout);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Append to parent
|
|
113
|
+
if (parentElement && fragment) {
|
|
114
|
+
const parentDom = isComponent(parentElement) ? parentElement.element : parentElement;
|
|
115
|
+
parentDom.appendChild(fragment);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Merge child layouts
|
|
119
|
+
for (const childLayout of childLayouts) {
|
|
120
|
+
Object.assign(layout, childLayout);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return createLayoutResult(layout);
|
|
124
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// src/core/layout/processor.ts
|
|
2
|
+
/**
|
|
3
|
+
* @module core/layout
|
|
4
|
+
* @description Lightweight processor for layout creation, optimized for bundle size
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Schema, LayoutResult, LayoutOptions } from './types';
|
|
8
|
+
import { isComponent } from './utils';
|
|
9
|
+
import { processArraySchema } from './array';
|
|
10
|
+
import { processObjectSchema } from './object';
|
|
11
|
+
import { isObject } from '../utils';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Creates a component from a constructor or factory function
|
|
15
|
+
*
|
|
16
|
+
* @param Component - Component constructor or factory function
|
|
17
|
+
* @param options - Component creation options
|
|
18
|
+
* @param layoutOptions - Global layout options
|
|
19
|
+
* @returns Created component instance
|
|
20
|
+
*/
|
|
21
|
+
export function createComponentInstance(
|
|
22
|
+
Component: any,
|
|
23
|
+
options: Record<string, any> = {},
|
|
24
|
+
layoutOptions: LayoutOptions = {}
|
|
25
|
+
): any {
|
|
26
|
+
// Check if Component is a class constructor
|
|
27
|
+
const isClass = typeof Component === 'function' &&
|
|
28
|
+
Component.prototype &&
|
|
29
|
+
Component.prototype.constructor === Component &&
|
|
30
|
+
// Exclude native constructors like Object, Array, etc.
|
|
31
|
+
Object.getPrototypeOf(Component) !== Function.prototype;
|
|
32
|
+
|
|
33
|
+
// Use 'new' for class constructors, call directly for function factories
|
|
34
|
+
return isClass
|
|
35
|
+
? new Component(options)
|
|
36
|
+
: Component(options);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Processes any type of layout definition (array or object)
|
|
41
|
+
* This is the main entry point for schema processing
|
|
42
|
+
*
|
|
43
|
+
* @param schema - Layout schema to process
|
|
44
|
+
* @param parentElement - Parent element to attach to
|
|
45
|
+
* @param level - Current nesting level
|
|
46
|
+
* @param options - Layout creation options
|
|
47
|
+
* @returns Layout result object
|
|
48
|
+
*/
|
|
49
|
+
export function processSchema(
|
|
50
|
+
schema: any,
|
|
51
|
+
parentElement: HTMLElement | null = null,
|
|
52
|
+
level: number = 0,
|
|
53
|
+
options: LayoutOptions = {}
|
|
54
|
+
): LayoutResult {
|
|
55
|
+
return Array.isArray(schema)
|
|
56
|
+
? processArraySchema(schema, parentElement, level, options)
|
|
57
|
+
: processObjectSchema(schema, parentElement, options);
|
|
58
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// src/core/layout/result.ts
|
|
2
|
+
/**
|
|
3
|
+
* @module core/layout
|
|
4
|
+
* @description Simplified layout result creation and management
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { LayoutResult } from './types';
|
|
8
|
+
import { isComponent, flattenLayout } from './utils';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Creates a result object with the layout and utility functions
|
|
12
|
+
* Simplified API for better usability and reduced overhead
|
|
13
|
+
*
|
|
14
|
+
* @param layout - The raw layout object
|
|
15
|
+
* @returns Result object with layout and utility functions
|
|
16
|
+
*/
|
|
17
|
+
export function createLayoutResult(layout: Record<string, any>): LayoutResult {
|
|
18
|
+
// Pre-compute flattened layout for better performance
|
|
19
|
+
const flattenedComponents = flattenLayout(layout);
|
|
20
|
+
|
|
21
|
+
// Create the result object with layout correctly exposed
|
|
22
|
+
const result: LayoutResult = {
|
|
23
|
+
// Raw layout object
|
|
24
|
+
layout,
|
|
25
|
+
|
|
26
|
+
// Root element reference for convenience
|
|
27
|
+
element: layout.element,
|
|
28
|
+
|
|
29
|
+
// Flattened component map
|
|
30
|
+
component: flattenedComponents,
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Gets a component by name
|
|
34
|
+
*
|
|
35
|
+
* @param name - Component name
|
|
36
|
+
* @returns Component if found, null otherwise
|
|
37
|
+
*/
|
|
38
|
+
get(name: string): any {
|
|
39
|
+
return layout[name] ?? null;
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Gets all components in a flattened map
|
|
44
|
+
*
|
|
45
|
+
* @returns Object with all components
|
|
46
|
+
*/
|
|
47
|
+
getAll(): Record<string, any> {
|
|
48
|
+
return flattenedComponents;
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Destroys the layout, cleaning up all components
|
|
53
|
+
*/
|
|
54
|
+
destroy(): void {
|
|
55
|
+
// Handle root element
|
|
56
|
+
const root = layout.element;
|
|
57
|
+
if (root) {
|
|
58
|
+
// Component with destroy method
|
|
59
|
+
if (isComponent(root) && typeof root.destroy === 'function') {
|
|
60
|
+
root.destroy();
|
|
61
|
+
}
|
|
62
|
+
// Component without destroy method
|
|
63
|
+
else if (isComponent(root) && root.element?.parentNode) {
|
|
64
|
+
root.element.parentNode.removeChild(root.element);
|
|
65
|
+
}
|
|
66
|
+
// Direct DOM element
|
|
67
|
+
else if (root instanceof HTMLElement && root.parentNode) {
|
|
68
|
+
root.parentNode.removeChild(root);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Clean up other components that have a destroy method
|
|
73
|
+
for (const key in layout) {
|
|
74
|
+
if (key === 'element') continue;
|
|
75
|
+
|
|
76
|
+
const item = layout[key];
|
|
77
|
+
if (isComponent(item) && typeof item.destroy === 'function') {
|
|
78
|
+
item.destroy();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// src/core/layout/types.ts
|
|
2
|
+
/**
|
|
3
|
+
* @module core/layout
|
|
4
|
+
* @description Optimized type definitions for layout creation system
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Interface for component-like objects
|
|
9
|
+
*/
|
|
10
|
+
export interface ComponentLike {
|
|
11
|
+
/**
|
|
12
|
+
* DOM element reference
|
|
13
|
+
*/
|
|
14
|
+
element: HTMLElement;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Optional method to clean up resources
|
|
18
|
+
*/
|
|
19
|
+
destroy?: () => void;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Allow additional properties
|
|
23
|
+
*/
|
|
24
|
+
[key: string]: any;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Definition for a single element in the layout
|
|
29
|
+
*/
|
|
30
|
+
export interface ElementDefinition {
|
|
31
|
+
/**
|
|
32
|
+
* Optional name to reference the element
|
|
33
|
+
*/
|
|
34
|
+
name?: string;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Creator function that produces an HTMLElement or ComponentLike
|
|
38
|
+
*/
|
|
39
|
+
creator?: (options?: Record<string, any>) => HTMLElement | ComponentLike;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Options to pass to the creator function
|
|
43
|
+
*/
|
|
44
|
+
options?: Record<string, any>;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Child elements to create and attach
|
|
48
|
+
*/
|
|
49
|
+
children?: Record<string, ElementDefinition>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Schema for layout creation
|
|
54
|
+
*/
|
|
55
|
+
export interface Schema {
|
|
56
|
+
/**
|
|
57
|
+
* Root element definition
|
|
58
|
+
*/
|
|
59
|
+
element?: ElementDefinition;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Additional elements
|
|
63
|
+
*/
|
|
64
|
+
[key: string]: ElementDefinition | undefined;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Options for layout creation
|
|
69
|
+
*/
|
|
70
|
+
export interface LayoutOptions {
|
|
71
|
+
/**
|
|
72
|
+
* Default creator function to use if not specified in schema
|
|
73
|
+
*/
|
|
74
|
+
creator?: (options?: Record<string, any>) => HTMLElement | ComponentLike;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Whether to apply CSS class prefix
|
|
78
|
+
* @default true
|
|
79
|
+
*/
|
|
80
|
+
prefix?: boolean;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Additional options
|
|
84
|
+
*/
|
|
85
|
+
[key: string]: any;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Result object returned after creating a layout
|
|
90
|
+
* Simplified API with essential methods
|
|
91
|
+
*/
|
|
92
|
+
export interface LayoutResult {
|
|
93
|
+
/**
|
|
94
|
+
* The raw layout object with all components
|
|
95
|
+
*/
|
|
96
|
+
layout: Record<string, any>;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Reference to the root element for convenience
|
|
100
|
+
*/
|
|
101
|
+
element: HTMLElement | ComponentLike;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Flattened component map
|
|
105
|
+
*/
|
|
106
|
+
component: Record<string, any>;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Gets a component by name
|
|
110
|
+
* @param name - Component name
|
|
111
|
+
* @returns Component if found, null otherwise
|
|
112
|
+
*/
|
|
113
|
+
get(name: string): any;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Gets all components in a flattened map
|
|
117
|
+
* @returns Object with all components
|
|
118
|
+
*/
|
|
119
|
+
getAll(): Record<string, any>;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Destroys the layout, cleaning up all components
|
|
123
|
+
*/
|
|
124
|
+
destroy(): void;
|
|
125
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// src/core/layout/utils.ts
|
|
2
|
+
/**
|
|
3
|
+
* @module core/layout
|
|
4
|
+
* @description Optimized utility functions for layout creation
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { PREFIX } from '../config';
|
|
8
|
+
import { ComponentLike } from './types';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Checks if a value is a component object (has an element property)
|
|
12
|
+
* Optimized fast path check by only validating that element property exists
|
|
13
|
+
*
|
|
14
|
+
* @param value - Value to check
|
|
15
|
+
* @returns True if the value is a component-like object
|
|
16
|
+
*/
|
|
17
|
+
export function isComponent(value: any): value is ComponentLike {
|
|
18
|
+
return value &&
|
|
19
|
+
typeof value === 'object' &&
|
|
20
|
+
'element' in value;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Creates a document fragment for faster DOM operations
|
|
25
|
+
*
|
|
26
|
+
* @returns New DocumentFragment
|
|
27
|
+
*/
|
|
28
|
+
export function createFragment(): DocumentFragment {
|
|
29
|
+
return document.createDocumentFragment();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Processes className options to add prefix if needed
|
|
34
|
+
* Supports BEM naming conventions when enabled
|
|
35
|
+
*
|
|
36
|
+
* @param options - Element options
|
|
37
|
+
* @param skipPrefix - Whether to skip adding prefixes
|
|
38
|
+
* @param useBEM - Whether to respect BEM naming conventions
|
|
39
|
+
* @returns Updated options with prefixed classNames
|
|
40
|
+
*/
|
|
41
|
+
export function processClassNames(
|
|
42
|
+
options: Record<string, any>,
|
|
43
|
+
skipPrefix: boolean = false,
|
|
44
|
+
useBEM: boolean = false
|
|
45
|
+
): Record<string, any> {
|
|
46
|
+
// Fast path - if no options or skipping prefix, return as is
|
|
47
|
+
if (!options || skipPrefix) return { ...options };
|
|
48
|
+
|
|
49
|
+
// Clone options to avoid mutating the original
|
|
50
|
+
const processed = { ...options };
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Processes a single class name with optional BEM handling
|
|
54
|
+
*
|
|
55
|
+
* @param cls - Class name to process
|
|
56
|
+
* @returns Processed class name with prefix
|
|
57
|
+
*/
|
|
58
|
+
const processClass = (cls: string): string => {
|
|
59
|
+
// Already prefixed - leave it as is
|
|
60
|
+
if (cls.startsWith(`${PREFIX}-`)) {
|
|
61
|
+
return cls;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (useBEM) {
|
|
65
|
+
// For BEM classes (with __ or --), only prefix the block part
|
|
66
|
+
if (cls.includes('__')) {
|
|
67
|
+
// This is a BEM element, prefix only the block part
|
|
68
|
+
const [block, element] = cls.split('__');
|
|
69
|
+
return `${PREFIX}-${block}__${element}`;
|
|
70
|
+
} else if (cls.includes('--')) {
|
|
71
|
+
// This is a BEM modifier, prefix only the block part
|
|
72
|
+
const [block, modifier] = cls.split('--');
|
|
73
|
+
return `${PREFIX}-${block}--${modifier}`;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Standard case - prefix the entire class name
|
|
78
|
+
return `${PREFIX}-${cls}`;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Process a class property (either 'class' or 'className')
|
|
83
|
+
*
|
|
84
|
+
* @param prop - Property name to process
|
|
85
|
+
*/
|
|
86
|
+
const processProperty = (prop: string): void => {
|
|
87
|
+
if (!processed[prop]) return;
|
|
88
|
+
|
|
89
|
+
// Handle string class names
|
|
90
|
+
if (typeof processed[prop] === 'string') {
|
|
91
|
+
processed[prop] = processed[prop]
|
|
92
|
+
.split(' ')
|
|
93
|
+
.map(cls => cls ? processClass(cls) : '')
|
|
94
|
+
.filter(Boolean)
|
|
95
|
+
.join(' ');
|
|
96
|
+
}
|
|
97
|
+
// Handle array class names
|
|
98
|
+
else if (Array.isArray(processed[prop])) {
|
|
99
|
+
processed[prop] = processed[prop]
|
|
100
|
+
.map(cls => typeof cls === 'string' ? processClass(cls) : cls)
|
|
101
|
+
.filter(Boolean)
|
|
102
|
+
.join(' ');
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// Process both possible class properties for compatibility
|
|
107
|
+
processProperty('class');
|
|
108
|
+
processProperty('className');
|
|
109
|
+
|
|
110
|
+
return processed;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Flattens a nested layout into a simple object with element and component references
|
|
115
|
+
* Optimized by using a direct property access loop and early exits
|
|
116
|
+
*
|
|
117
|
+
* @param layout - Layout object
|
|
118
|
+
* @returns Flattened layout with all elements and components
|
|
119
|
+
*/
|
|
120
|
+
export function flattenLayout(layout: Record<string, any>): Record<string, any> {
|
|
121
|
+
const flattened: Record<string, any> = {};
|
|
122
|
+
|
|
123
|
+
for (const key in layout) {
|
|
124
|
+
const value = layout[key];
|
|
125
|
+
|
|
126
|
+
// Only include components, elements, and non-functions
|
|
127
|
+
// Fast path with fewer type checks
|
|
128
|
+
if (value &&
|
|
129
|
+
typeof value !== 'function' &&
|
|
130
|
+
(value instanceof HTMLElement || 'element' in value)) {
|
|
131
|
+
flattened[key] = value;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return flattened;
|
|
136
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -16,6 +16,7 @@ export { default as createDialog } from './components/dialog'
|
|
|
16
16
|
export { default as createDivider } from './components/divider'
|
|
17
17
|
export { default as createMenu } from './components/menu'
|
|
18
18
|
export { default as createNavigation } from './components/navigation'
|
|
19
|
+
export { default as createNavigationSystem } from './components/navigation'
|
|
19
20
|
export { default as createProgress } from './components/progress'
|
|
20
21
|
export { default as createRadios } from './components/radios'
|
|
21
22
|
export { default as createSearch } from './components/search'
|
|
@@ -207,6 +207,34 @@ $button: (
|
|
|
207
207
|
'transition-easing': map.get($motion, 'easing-standard')
|
|
208
208
|
) !default;
|
|
209
209
|
|
|
210
|
+
|
|
211
|
+
// Define spacing scale (this might already exist, if not, add it)
|
|
212
|
+
$spacing-scale: (
|
|
213
|
+
'0': 0,
|
|
214
|
+
'1': 4px,
|
|
215
|
+
'2': 8px,
|
|
216
|
+
'3': 12px,
|
|
217
|
+
'4': 16px,
|
|
218
|
+
'5': 20px,
|
|
219
|
+
'6': 24px,
|
|
220
|
+
'8': 32px,
|
|
221
|
+
'10': 40px,
|
|
222
|
+
'12': 48px,
|
|
223
|
+
'14': 56px,
|
|
224
|
+
'16': 64px,
|
|
225
|
+
'20': 80px,
|
|
226
|
+
'24': 96px,
|
|
227
|
+
'32': 128px
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
// Add spacing function
|
|
231
|
+
@function spacing($key) {
|
|
232
|
+
@if not map.has-key($spacing-scale, $key) {
|
|
233
|
+
@error 'Spacing key "#{$key}" not found in spacing scale.';
|
|
234
|
+
}
|
|
235
|
+
@return map.get($spacing-scale, $key);
|
|
236
|
+
}
|
|
237
|
+
|
|
210
238
|
// Helper functions for easier token access
|
|
211
239
|
@function state($key) {
|
|
212
240
|
@return map.get($state, $key);
|