mtrl 0.2.8 → 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 +1 -1
- 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-types.ts +124 -0
- package/src/components/navigation/system.ts +776 -0
- 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/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 +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/styles/components/_textfield.scss +250 -11
- 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
|
@@ -7,20 +7,23 @@ import { SliderConfig, SliderEvent } from '../types';
|
|
|
7
7
|
*
|
|
8
8
|
* @param config Slider configuration
|
|
9
9
|
* @param state Slider state object
|
|
10
|
-
* @param
|
|
10
|
+
* @param uiRenderer UI renderer interface from controller
|
|
11
11
|
* @param eventHelpers Event helper methods
|
|
12
12
|
* @returns Event handlers for all slider interactions
|
|
13
13
|
*/
|
|
14
|
-
export const createHandlers = (config: SliderConfig, state,
|
|
14
|
+
export const createHandlers = (config: SliderConfig, state, uiRenderer, eventHelpers) => {
|
|
15
15
|
// Get required elements from structure (with fallbacks)
|
|
16
|
+
const components = state.component?.components || {};
|
|
17
|
+
|
|
18
|
+
// Extract needed components
|
|
16
19
|
const {
|
|
17
20
|
container = null,
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
handle = null,
|
|
22
|
+
track = null,
|
|
20
23
|
valueBubble = null,
|
|
21
24
|
secondHandle = null,
|
|
22
25
|
secondValueBubble = null
|
|
23
|
-
} =
|
|
26
|
+
} = components;
|
|
24
27
|
|
|
25
28
|
// Get required helper methods (with fallbacks)
|
|
26
29
|
const {
|
|
@@ -28,8 +31,8 @@ export const createHandlers = (config: SliderConfig, state, uiHelpers, eventHelp
|
|
|
28
31
|
roundToStep = value => value,
|
|
29
32
|
clamp = (value, min, max) => value,
|
|
30
33
|
showValueBubble = () => {},
|
|
31
|
-
|
|
32
|
-
} =
|
|
34
|
+
render = () => {}
|
|
35
|
+
} = uiRenderer;
|
|
33
36
|
|
|
34
37
|
const { triggerEvent = () => ({ defaultPrevented: false }) } = eventHelpers;
|
|
35
38
|
|
|
@@ -127,7 +130,7 @@ export const createHandlers = (config: SliderConfig, state, uiHelpers, eventHelp
|
|
|
127
130
|
document.addEventListener('touchmove', handleMouseMove, { passive: false });
|
|
128
131
|
document.addEventListener('touchend', handleMouseUp);
|
|
129
132
|
|
|
130
|
-
|
|
133
|
+
render();
|
|
131
134
|
triggerEvent(SLIDER_EVENTS.START, e);
|
|
132
135
|
};
|
|
133
136
|
|
|
@@ -169,7 +172,7 @@ export const createHandlers = (config: SliderConfig, state, uiHelpers, eventHelp
|
|
|
169
172
|
}
|
|
170
173
|
|
|
171
174
|
// Update UI and trigger events
|
|
172
|
-
|
|
175
|
+
render();
|
|
173
176
|
triggerEvent(SLIDER_EVENTS.INPUT, e);
|
|
174
177
|
triggerEvent(SLIDER_EVENTS.CHANGE, e);
|
|
175
178
|
} catch (error) {
|
|
@@ -244,7 +247,7 @@ export const createHandlers = (config: SliderConfig, state, uiHelpers, eventHelp
|
|
|
244
247
|
state.value = newValue;
|
|
245
248
|
}
|
|
246
249
|
|
|
247
|
-
|
|
250
|
+
render();
|
|
248
251
|
triggerEvent(SLIDER_EVENTS.INPUT, e);
|
|
249
252
|
} catch (error) {
|
|
250
253
|
console.warn('Error during slider drag:', error);
|
|
@@ -274,7 +277,7 @@ export const createHandlers = (config: SliderConfig, state, uiHelpers, eventHelp
|
|
|
274
277
|
|
|
275
278
|
// Reset active handle and update UI
|
|
276
279
|
state.activeHandle = null;
|
|
277
|
-
|
|
280
|
+
render();
|
|
278
281
|
|
|
279
282
|
// Trigger events
|
|
280
283
|
triggerEvent(SLIDER_EVENTS.CHANGE, e);
|
|
@@ -355,7 +358,7 @@ export const createHandlers = (config: SliderConfig, state, uiHelpers, eventHelp
|
|
|
355
358
|
}
|
|
356
359
|
|
|
357
360
|
// Update UI and trigger events
|
|
358
|
-
|
|
361
|
+
render();
|
|
359
362
|
triggerEvent(SLIDER_EVENTS.INPUT, e);
|
|
360
363
|
triggerEvent(SLIDER_EVENTS.CHANGE, e);
|
|
361
364
|
};
|
|
@@ -406,7 +409,7 @@ export const createHandlers = (config: SliderConfig, state, uiHelpers, eventHelp
|
|
|
406
409
|
* Set up all event listeners
|
|
407
410
|
*/
|
|
408
411
|
const setupEventListeners = () => {
|
|
409
|
-
if (!state.component || !state.component.
|
|
412
|
+
if (!state.component || !state.component.components) {
|
|
410
413
|
console.warn('Cannot set up event listeners: missing component structure');
|
|
411
414
|
return;
|
|
412
415
|
}
|
|
@@ -436,7 +439,7 @@ export const createHandlers = (config: SliderConfig, state, uiHelpers, eventHelp
|
|
|
436
439
|
* Clean up all event listeners
|
|
437
440
|
*/
|
|
438
441
|
const cleanupEventListeners = () => {
|
|
439
|
-
if (!state.component || !state.component.
|
|
442
|
+
if (!state.component || !state.component.components) return;
|
|
440
443
|
|
|
441
444
|
// Clean up container listeners
|
|
442
445
|
if (container) {
|
|
@@ -492,4 +495,4 @@ export const createHandlers = (config: SliderConfig, state, uiHelpers, eventHelp
|
|
|
492
495
|
hideAllBubbles,
|
|
493
496
|
clearKeyboardFocus
|
|
494
497
|
};
|
|
495
|
-
}
|
|
498
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// src/components/slider/features/index.ts
|
|
2
|
-
|
|
2
|
+
// Export slider-specific features
|
|
3
|
+
export { withRange } from './range';
|
|
3
4
|
export { withStates } from './states';
|
|
4
|
-
export {
|
|
5
|
+
export { withController } from './controller';
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// src/components/slider/features/range.ts
|
|
2
|
+
import { SliderConfig } from '../types';
|
|
3
|
+
import { createElement } from '../../../core/dom/create';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Enhances structure definition with range slider elements
|
|
7
|
+
*
|
|
8
|
+
* @param config Slider configuration
|
|
9
|
+
* @returns Component enhancer that adds range slider to structure
|
|
10
|
+
*/
|
|
11
|
+
export const withRange = (config: SliderConfig) => component => {
|
|
12
|
+
// If not a range slider or missing structure definition, return unmodified
|
|
13
|
+
if (!config.range || !config.secondValue || !component.structureDefinition) {
|
|
14
|
+
return component;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
// Calculate values for second handle
|
|
19
|
+
const min = config.min || 0;
|
|
20
|
+
const max = config.max || 100;
|
|
21
|
+
const secondValue = config.secondValue;
|
|
22
|
+
const secondValuePercent = ((secondValue - min) / (max - min)) * 100;
|
|
23
|
+
const formatter = config.valueFormatter || (val => val.toString());
|
|
24
|
+
const isDisabled = config.disabled === true;
|
|
25
|
+
const getClass = component.getClass;
|
|
26
|
+
|
|
27
|
+
// Clone the structure definition (deep copy)
|
|
28
|
+
const structureDefinition = JSON.parse(JSON.stringify(component.structureDefinition));
|
|
29
|
+
|
|
30
|
+
// Add range class to root element
|
|
31
|
+
const rootClasses = structureDefinition.element.options.className || [];
|
|
32
|
+
if (Array.isArray(rootClasses)) {
|
|
33
|
+
rootClasses.push(getClass('slider--range'));
|
|
34
|
+
} else {
|
|
35
|
+
structureDefinition.element.options.className = `${rootClasses} ${getClass('slider--range')}`.trim();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Add start track segment to track children
|
|
39
|
+
const trackChildren = structureDefinition.element.children.container.children.track.children;
|
|
40
|
+
trackChildren.startTrack = {
|
|
41
|
+
name: 'startTrack',
|
|
42
|
+
creator: createElement,
|
|
43
|
+
options: {
|
|
44
|
+
tag: 'div',
|
|
45
|
+
className: getClass('slider-start-track'),
|
|
46
|
+
style: {
|
|
47
|
+
width: '0%'
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// Add second handle to container children
|
|
53
|
+
const containerChildren = structureDefinition.element.children.container.children;
|
|
54
|
+
containerChildren.secondHandle = {
|
|
55
|
+
name: 'secondHandle',
|
|
56
|
+
creator: createElement,
|
|
57
|
+
options: {
|
|
58
|
+
tag: 'div',
|
|
59
|
+
className: getClass('slider-handle'),
|
|
60
|
+
attrs: {
|
|
61
|
+
role: 'slider',
|
|
62
|
+
'aria-valuemin': String(min),
|
|
63
|
+
'aria-valuemax': String(max),
|
|
64
|
+
'aria-valuenow': String(secondValue),
|
|
65
|
+
'aria-orientation': 'horizontal',
|
|
66
|
+
tabindex: isDisabled ? '-1' : '0',
|
|
67
|
+
'aria-disabled': isDisabled ? 'true' : 'false',
|
|
68
|
+
'data-value': String(secondValue),
|
|
69
|
+
'data-handle-index': '1'
|
|
70
|
+
},
|
|
71
|
+
style: {
|
|
72
|
+
left: `${secondValuePercent}%`
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// Add second value bubble to container children
|
|
78
|
+
containerChildren.secondValueBubble = {
|
|
79
|
+
name: 'secondValueBubble',
|
|
80
|
+
creator: createElement,
|
|
81
|
+
options: {
|
|
82
|
+
tag: 'div',
|
|
83
|
+
className: getClass('slider-value'),
|
|
84
|
+
attrs: {
|
|
85
|
+
'aria-hidden': 'true',
|
|
86
|
+
'data-handle-index': '1'
|
|
87
|
+
},
|
|
88
|
+
text: formatter(secondValue),
|
|
89
|
+
style: {
|
|
90
|
+
left: `${secondValuePercent}%`
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// Return component with updated structure definition
|
|
96
|
+
return {
|
|
97
|
+
...component,
|
|
98
|
+
structureDefinition
|
|
99
|
+
};
|
|
100
|
+
} catch (error) {
|
|
101
|
+
console.warn('Error enhancing structure with range functionality:', error);
|
|
102
|
+
return component;
|
|
103
|
+
}
|
|
104
|
+
};
|
|
@@ -1,42 +1,62 @@
|
|
|
1
1
|
// src/components/slider/slider.ts
|
|
2
2
|
import { pipe } from '../../core/compose/pipe';
|
|
3
|
-
import { createBase
|
|
4
|
-
import { withEvents, withLifecycle
|
|
5
|
-
import { withStructure,
|
|
6
|
-
import {
|
|
3
|
+
import { createBase } from '../../core/compose/component';
|
|
4
|
+
import { withEvents, withLifecycle } from '../../core/compose/features';
|
|
5
|
+
import { withStructure, withIcon, withLabel, withDom } from '../../core/composition/features';
|
|
6
|
+
import {
|
|
7
|
+
withRange,
|
|
8
|
+
withStates,
|
|
9
|
+
withController
|
|
10
|
+
} from './features';
|
|
7
11
|
import { withAPI } from './api';
|
|
8
12
|
import { SliderConfig, SliderComponent } from './types';
|
|
9
|
-
import { createBaseConfig,
|
|
10
|
-
|
|
13
|
+
import { createBaseConfig, getApiConfig } from './config';
|
|
11
14
|
/**
|
|
12
15
|
* Creates a new Slider component
|
|
16
|
+
*
|
|
17
|
+
* Slider follows a clear architectural pattern:
|
|
18
|
+
* 1. Structure definition - Describes the DOM structure declaratively
|
|
19
|
+
* 2. Feature enhancement - Adds specific capabilities (range, icons, labels)
|
|
20
|
+
* 3. DOM creation - Turns the structure into actual DOM elements
|
|
21
|
+
* 4. State management - Handles visual states and appearance
|
|
22
|
+
* 5. Controller - Manages behavior, events, and UI rendering
|
|
23
|
+
* 6. Lifecycle - Handles component lifecycle events
|
|
24
|
+
* 7. Public API - Exposes a clean, consistent API
|
|
25
|
+
*
|
|
13
26
|
* @param {SliderConfig} config - Slider configuration object
|
|
14
27
|
* @returns {SliderComponent} Slider component instance
|
|
15
28
|
*/
|
|
16
29
|
const createSlider = (config: SliderConfig = {}): SliderComponent => {
|
|
30
|
+
// Process configuration with defaults
|
|
17
31
|
const baseConfig = createBaseConfig(config);
|
|
18
32
|
|
|
19
33
|
try {
|
|
20
|
-
// Create the component
|
|
34
|
+
// Create the component by composing features in a specific order
|
|
21
35
|
const component = pipe(
|
|
36
|
+
// Base component with event system
|
|
22
37
|
createBase,
|
|
23
38
|
withEvents(),
|
|
24
|
-
withElement(getElementConfig(baseConfig)),
|
|
25
|
-
withIcon(baseConfig),
|
|
26
|
-
withTextLabel(baseConfig),
|
|
27
39
|
withStructure(baseConfig),
|
|
40
|
+
withIcon(baseConfig),
|
|
41
|
+
withLabel(baseConfig),
|
|
42
|
+
withRange(baseConfig),
|
|
43
|
+
|
|
44
|
+
// Now create the actual DOM elements from the complete structure
|
|
45
|
+
withDom(),
|
|
46
|
+
|
|
47
|
+
// Add state management and behavior
|
|
28
48
|
withStates(baseConfig),
|
|
29
|
-
|
|
49
|
+
withController(baseConfig),
|
|
30
50
|
withLifecycle()
|
|
31
51
|
)(baseConfig);
|
|
32
52
|
|
|
33
|
-
// Generate the API configuration
|
|
53
|
+
// Generate the API configuration based on the enhanced component
|
|
34
54
|
const apiOptions = getApiConfig(component);
|
|
35
55
|
|
|
36
|
-
// Apply the API layer
|
|
56
|
+
// Apply the public API layer
|
|
37
57
|
const slider = withAPI(apiOptions)(component);
|
|
38
58
|
|
|
39
|
-
// Register event handlers from config
|
|
59
|
+
// Register event handlers from config for convenience
|
|
40
60
|
if (baseConfig.on && typeof slider.on === 'function') {
|
|
41
61
|
Object.entries(baseConfig.on).forEach(([event, handler]) => {
|
|
42
62
|
if (typeof handler === 'function') {
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
// src/components/slider/structure.ts
|
|
2
|
+
import { SliderConfig } from './types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Creates the base slider structure definition
|
|
6
|
+
*
|
|
7
|
+
* @param component Component for class name generation
|
|
8
|
+
* @param config Slider configuration
|
|
9
|
+
* @returns Structure definition object
|
|
10
|
+
*/
|
|
11
|
+
export function createSliderDefinition(component, config: SliderConfig) {
|
|
12
|
+
// Get prefixed class names
|
|
13
|
+
const getClass = (className) => component.getClass(className);
|
|
14
|
+
|
|
15
|
+
// Set default values
|
|
16
|
+
const min = config.min || 0;
|
|
17
|
+
const max = config.max || 100;
|
|
18
|
+
const value = config.value !== undefined ? config.value : min;
|
|
19
|
+
const isDisabled = config.disabled === true;
|
|
20
|
+
const formatter = config.valueFormatter || (val => val.toString());
|
|
21
|
+
|
|
22
|
+
// Calculate initial position
|
|
23
|
+
const valuePercent = ((value - min) / (max - min)) * 100;
|
|
24
|
+
|
|
25
|
+
// Return base structure definition formatted for createStructure
|
|
26
|
+
return {
|
|
27
|
+
element: {
|
|
28
|
+
options: {
|
|
29
|
+
tag: 'div',
|
|
30
|
+
className: [getClass('slider'), config.class].filter(Boolean),
|
|
31
|
+
attrs: {
|
|
32
|
+
tabindex: '-1',
|
|
33
|
+
role: 'none',
|
|
34
|
+
'aria-disabled': isDisabled ? 'true' : 'false'
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
children: {
|
|
38
|
+
// Container with all slider elements
|
|
39
|
+
container: {
|
|
40
|
+
options: {
|
|
41
|
+
tag: 'div',
|
|
42
|
+
className: getClass('slider-container')
|
|
43
|
+
},
|
|
44
|
+
children: {
|
|
45
|
+
// Track with segments
|
|
46
|
+
track: {
|
|
47
|
+
options: {
|
|
48
|
+
tag: 'div',
|
|
49
|
+
className: getClass('slider-track')
|
|
50
|
+
},
|
|
51
|
+
children: {
|
|
52
|
+
activeTrack: {
|
|
53
|
+
options: {
|
|
54
|
+
tag: 'div',
|
|
55
|
+
className: getClass('slider-active-track'),
|
|
56
|
+
style: {
|
|
57
|
+
width: `${valuePercent}%`
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
startTrack: {
|
|
62
|
+
options: {
|
|
63
|
+
tag: 'div',
|
|
64
|
+
className: getClass('slider-start-track'),
|
|
65
|
+
style: {
|
|
66
|
+
display: 'none', // Initially hidden for single slider
|
|
67
|
+
width: '0%'
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
remainingTrack: {
|
|
72
|
+
options: {
|
|
73
|
+
tag: 'div',
|
|
74
|
+
className: getClass('slider-remaining-track'),
|
|
75
|
+
style: {
|
|
76
|
+
width: `${100 - valuePercent}%`
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
// Ticks container
|
|
84
|
+
ticksContainer: {
|
|
85
|
+
options: {
|
|
86
|
+
tag: 'div',
|
|
87
|
+
className: getClass('slider-ticks-container')
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
// Dots for ends
|
|
92
|
+
startDot: {
|
|
93
|
+
options: {
|
|
94
|
+
tag: 'div',
|
|
95
|
+
className: [
|
|
96
|
+
getClass('slider-dot'),
|
|
97
|
+
getClass('slider-dot--start')
|
|
98
|
+
]
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
endDot: {
|
|
102
|
+
options: {
|
|
103
|
+
tag: 'div',
|
|
104
|
+
className: [
|
|
105
|
+
getClass('slider-dot'),
|
|
106
|
+
getClass('slider-dot--end')
|
|
107
|
+
]
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
// Main handle
|
|
112
|
+
handle: {
|
|
113
|
+
options: {
|
|
114
|
+
tag: 'div',
|
|
115
|
+
className: getClass('slider-handle'),
|
|
116
|
+
attrs: {
|
|
117
|
+
role: 'slider',
|
|
118
|
+
'aria-valuemin': String(min),
|
|
119
|
+
'aria-valuemax': String(max),
|
|
120
|
+
'aria-valuenow': String(value),
|
|
121
|
+
'aria-orientation': 'horizontal',
|
|
122
|
+
tabindex: isDisabled ? '-1' : '0',
|
|
123
|
+
'aria-disabled': isDisabled ? 'true' : 'false',
|
|
124
|
+
'data-value': String(value),
|
|
125
|
+
'data-handle-index': '0'
|
|
126
|
+
},
|
|
127
|
+
style: {
|
|
128
|
+
left: `${valuePercent}%`
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
// Main value bubble
|
|
133
|
+
valueBubble: {
|
|
134
|
+
options: {
|
|
135
|
+
tag: 'div',
|
|
136
|
+
className: getClass('slider-value'),
|
|
137
|
+
attrs: {
|
|
138
|
+
'aria-hidden': 'true',
|
|
139
|
+
'data-handle-index': '0'
|
|
140
|
+
},
|
|
141
|
+
text: formatter(value),
|
|
142
|
+
style: {
|
|
143
|
+
left: `${valuePercent}%`
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
// src/components/textfield/api.ts
|
|
2
2
|
import { BaseComponent, TextfieldComponent, ApiOptions } from './types';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Enhances textfield component with API methods
|
|
6
|
+
* @param {ApiOptions} options - API configuration
|
|
7
|
+
* @returns {Function} Higher-order function that adds API methods to component
|
|
8
|
+
*/
|
|
4
9
|
/**
|
|
5
10
|
* Enhances textfield component with API methods
|
|
6
11
|
* @param {ApiOptions} options - API configuration
|
|
@@ -43,6 +48,54 @@ export const withAPI = ({ disabled, lifecycle }: ApiOptions) =>
|
|
|
43
48
|
getLabel(): string {
|
|
44
49
|
return component.label?.getText() || '';
|
|
45
50
|
},
|
|
51
|
+
|
|
52
|
+
// Leading icon management (if present)
|
|
53
|
+
leadingIcon: component.leadingIcon || null,
|
|
54
|
+
setLeadingIcon(html: string): TextfieldComponent {
|
|
55
|
+
if (component.setLeadingIcon) {
|
|
56
|
+
component.setLeadingIcon(html);
|
|
57
|
+
}
|
|
58
|
+
return this;
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
removeLeadingIcon(): TextfieldComponent {
|
|
62
|
+
if (component.removeLeadingIcon) {
|
|
63
|
+
component.removeLeadingIcon();
|
|
64
|
+
}
|
|
65
|
+
return this;
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
// Trailing icon management (if present)
|
|
69
|
+
trailingIcon: component.trailingIcon || null,
|
|
70
|
+
setTrailingIcon(html: string): TextfieldComponent {
|
|
71
|
+
if (component.setTrailingIcon) {
|
|
72
|
+
component.setTrailingIcon(html);
|
|
73
|
+
}
|
|
74
|
+
return this;
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
removeTrailingIcon(): TextfieldComponent {
|
|
78
|
+
if (component.removeTrailingIcon) {
|
|
79
|
+
component.removeTrailingIcon();
|
|
80
|
+
}
|
|
81
|
+
return this;
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
// Supporting text management (if present)
|
|
85
|
+
supportingTextElement: component.supportingTextElement || null,
|
|
86
|
+
setSupportingText(text: string, isError?: boolean): TextfieldComponent {
|
|
87
|
+
if (component.setSupportingText) {
|
|
88
|
+
component.setSupportingText(text, isError);
|
|
89
|
+
}
|
|
90
|
+
return this;
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
removeSupportingText(): TextfieldComponent {
|
|
94
|
+
if (component.removeSupportingText) {
|
|
95
|
+
component.removeSupportingText();
|
|
96
|
+
}
|
|
97
|
+
return this;
|
|
98
|
+
},
|
|
46
99
|
|
|
47
100
|
// Event handling
|
|
48
101
|
on(event: string, handler: Function): TextfieldComponent {
|