mtrl 0.1.2 → 0.2.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/README.md +70 -22
- package/index.ts +33 -0
- package/package.json +14 -5
- package/src/components/button/{styles.scss → _styles.scss} +2 -2
- package/src/components/button/api.ts +89 -0
- package/src/components/button/button.ts +50 -0
- package/src/components/button/config.ts +75 -0
- package/src/components/button/constants.ts +17 -0
- package/src/components/button/index.ts +4 -0
- package/src/components/button/types.ts +118 -0
- package/src/components/card/_styles.scss +359 -0
- package/src/components/card/actions.ts +48 -0
- package/src/components/card/api.ts +102 -0
- package/src/components/card/card.ts +41 -0
- package/src/components/card/config.ts +99 -0
- package/src/components/card/constants.ts +69 -0
- package/src/components/card/content.ts +48 -0
- package/src/components/card/features.ts +228 -0
- package/src/components/card/header.ts +88 -0
- package/src/components/card/index.ts +19 -0
- package/src/components/card/media.ts +52 -0
- package/src/components/card/types.ts +174 -0
- package/src/components/checkbox/api.ts +82 -0
- package/src/components/checkbox/checkbox.ts +75 -0
- package/src/components/checkbox/config.ts +90 -0
- package/src/components/checkbox/index.ts +4 -0
- package/src/components/checkbox/types.ts +146 -0
- package/src/components/chip/_styles.scss +372 -0
- package/src/components/chip/api.ts +115 -0
- package/src/components/chip/chip-set.ts +225 -0
- package/src/components/chip/chip.ts +82 -0
- package/src/components/chip/config.ts +92 -0
- package/src/components/chip/constants.ts +38 -0
- package/src/components/chip/index.ts +4 -0
- package/src/components/chip/types.ts +172 -0
- package/src/components/list/api.ts +72 -0
- package/src/components/list/config.ts +43 -0
- package/src/components/list/{constants.js → constants.ts} +34 -7
- package/src/components/list/features.ts +224 -0
- package/src/components/list/index.ts +14 -0
- package/src/components/list/list-item.ts +120 -0
- package/src/components/list/list.ts +37 -0
- package/src/components/list/types.ts +179 -0
- package/src/components/list/utils.ts +47 -0
- package/src/components/menu/api.ts +119 -0
- package/src/components/menu/config.ts +54 -0
- package/src/components/menu/constants.ts +154 -0
- package/src/components/menu/features/items-manager.ts +457 -0
- package/src/components/menu/features/keyboard-navigation.ts +133 -0
- package/src/components/menu/features/positioning.ts +127 -0
- package/src/components/menu/features/{visibility.js → visibility.ts} +66 -64
- package/src/components/menu/index.ts +14 -0
- package/src/components/menu/menu-item.ts +43 -0
- package/src/components/menu/menu.ts +53 -0
- package/src/components/menu/types.ts +178 -0
- package/src/components/navigation/api.ts +79 -0
- package/src/components/navigation/config.ts +61 -0
- package/src/components/navigation/{constants.js → constants.ts} +10 -10
- package/src/components/navigation/index.ts +14 -0
- package/src/components/navigation/nav-item.ts +148 -0
- package/src/components/navigation/navigation.ts +50 -0
- package/src/components/navigation/types.ts +212 -0
- package/src/components/progress/_styles.scss +204 -0
- package/src/components/progress/api.ts +179 -0
- package/src/components/progress/config.ts +124 -0
- package/src/components/progress/constants.ts +43 -0
- package/src/components/progress/index.ts +5 -0
- package/src/components/progress/progress.ts +163 -0
- package/src/components/progress/types.ts +102 -0
- package/src/components/snackbar/api.ts +162 -0
- package/src/components/snackbar/config.ts +62 -0
- package/src/components/snackbar/{constants.js → constants.ts} +21 -4
- package/src/components/snackbar/features.ts +76 -0
- package/src/components/snackbar/index.ts +4 -0
- package/src/components/snackbar/position.ts +71 -0
- package/src/components/snackbar/queue.ts +76 -0
- package/src/components/snackbar/snackbar.ts +60 -0
- package/src/components/snackbar/types.ts +58 -0
- package/src/components/switch/api.ts +77 -0
- package/src/components/switch/config.ts +74 -0
- package/src/components/switch/index.ts +4 -0
- package/src/components/switch/switch.ts +52 -0
- package/src/components/switch/types.ts +142 -0
- package/src/components/textfield/api.ts +72 -0
- package/src/components/textfield/config.ts +54 -0
- package/src/components/textfield/{constants.js → constants.ts} +38 -5
- package/src/components/textfield/index.ts +4 -0
- package/src/components/textfield/textfield.ts +50 -0
- package/src/components/textfield/types.ts +139 -0
- package/src/core/compose/base.ts +43 -0
- package/src/core/compose/component.ts +247 -0
- package/src/core/compose/features/checkable.ts +155 -0
- package/src/core/compose/features/disabled.ts +116 -0
- package/src/core/compose/features/events.ts +65 -0
- package/src/core/compose/features/icon.ts +67 -0
- package/src/core/compose/features/index.ts +35 -0
- package/src/core/compose/features/input.ts +174 -0
- package/src/core/compose/features/lifecycle.ts +139 -0
- package/src/core/compose/features/position.ts +94 -0
- package/src/core/compose/features/ripple.ts +55 -0
- package/src/core/compose/features/size.ts +29 -0
- package/src/core/compose/features/style.ts +31 -0
- package/src/core/compose/features/text.ts +44 -0
- package/src/core/compose/features/textinput.ts +225 -0
- package/src/core/compose/features/textlabel.ts +92 -0
- package/src/core/compose/features/track.ts +84 -0
- package/src/core/compose/features/variant.ts +29 -0
- package/src/core/compose/features/withEvents.ts +137 -0
- package/src/core/compose/index.ts +54 -0
- package/src/core/compose/{pipe.js → pipe.ts} +16 -11
- package/src/core/config/component-config.ts +136 -0
- package/src/core/config.ts +211 -0
- package/src/core/dom/{attributes.js → attributes.ts} +11 -11
- package/src/core/dom/classes.ts +60 -0
- package/src/core/dom/create.ts +188 -0
- package/src/core/dom/events.ts +209 -0
- package/src/core/dom/index.ts +10 -0
- package/src/core/dom/utils.ts +97 -0
- package/src/core/index.ts +111 -0
- package/src/core/state/disabled.ts +81 -0
- package/src/core/state/emitter.ts +94 -0
- package/src/core/state/events.ts +88 -0
- package/src/core/state/index.ts +16 -0
- package/src/core/state/lifecycle.ts +131 -0
- package/src/core/state/store.ts +197 -0
- package/src/core/utils/index.ts +45 -0
- package/src/core/utils/{mobile.js → mobile.ts} +48 -24
- package/src/core/utils/object.ts +41 -0
- package/src/core/utils/validate.ts +234 -0
- package/src/{index.js → index.ts} +4 -2
- package/index.js +0 -11
- package/src/components/button/api.js +0 -54
- package/src/components/button/button.js +0 -81
- package/src/components/button/config.js +0 -10
- package/src/components/button/constants.js +0 -63
- package/src/components/button/index.js +0 -2
- package/src/components/checkbox/api.js +0 -45
- package/src/components/checkbox/checkbox.js +0 -96
- package/src/components/checkbox/index.js +0 -2
- package/src/components/container/api.js +0 -42
- package/src/components/container/container.js +0 -45
- package/src/components/container/index.js +0 -2
- package/src/components/container/styles.scss +0 -66
- package/src/components/list/index.js +0 -2
- package/src/components/list/list-item.js +0 -147
- package/src/components/list/list.js +0 -267
- package/src/components/menu/api.js +0 -117
- package/src/components/menu/constants.js +0 -42
- package/src/components/menu/features/items-manager.js +0 -375
- package/src/components/menu/features/keyboard-navigation.js +0 -129
- package/src/components/menu/features/positioning.js +0 -125
- package/src/components/menu/index.js +0 -2
- package/src/components/menu/menu-item.js +0 -41
- package/src/components/menu/menu.js +0 -54
- package/src/components/navigation/api.js +0 -43
- package/src/components/navigation/index.js +0 -2
- package/src/components/navigation/nav-item.js +0 -137
- package/src/components/navigation/navigation.js +0 -55
- package/src/components/snackbar/api.js +0 -125
- package/src/components/snackbar/features.js +0 -69
- package/src/components/snackbar/index.js +0 -2
- package/src/components/snackbar/position.js +0 -63
- package/src/components/snackbar/queue.js +0 -74
- package/src/components/snackbar/snackbar.js +0 -70
- package/src/components/switch/api.js +0 -44
- package/src/components/switch/index.js +0 -2
- package/src/components/switch/switch.js +0 -71
- package/src/components/textfield/api.js +0 -49
- package/src/components/textfield/index.js +0 -2
- package/src/components/textfield/textfield.js +0 -68
- package/src/core/build/_ripple.scss +0 -79
- package/src/core/build/constants.js +0 -51
- package/src/core/build/icon.js +0 -78
- package/src/core/build/ripple.js +0 -159
- package/src/core/build/text.js +0 -54
- package/src/core/compose/base.js +0 -8
- package/src/core/compose/component.js +0 -225
- package/src/core/compose/features/checkable.js +0 -114
- package/src/core/compose/features/disabled.js +0 -64
- package/src/core/compose/features/events.js +0 -48
- package/src/core/compose/features/icon.js +0 -33
- package/src/core/compose/features/index.js +0 -20
- package/src/core/compose/features/input.js +0 -100
- package/src/core/compose/features/lifecycle.js +0 -69
- package/src/core/compose/features/position.js +0 -60
- package/src/core/compose/features/ripple.js +0 -32
- package/src/core/compose/features/size.js +0 -9
- package/src/core/compose/features/style.js +0 -12
- package/src/core/compose/features/text.js +0 -17
- package/src/core/compose/features/textinput.js +0 -114
- package/src/core/compose/features/textlabel.js +0 -28
- package/src/core/compose/features/track.js +0 -49
- package/src/core/compose/features/variant.js +0 -9
- package/src/core/compose/features/withEvents.js +0 -67
- package/src/core/compose/index.js +0 -16
- package/src/core/config.js +0 -140
- package/src/core/dom/classes.js +0 -70
- package/src/core/dom/create.js +0 -132
- package/src/core/dom/events.js +0 -175
- package/src/core/dom/index.js +0 -5
- package/src/core/dom/utils.js +0 -22
- package/src/core/index.js +0 -23
- package/src/core/state/disabled.js +0 -51
- package/src/core/state/emitter.js +0 -63
- package/src/core/state/events.js +0 -29
- package/src/core/state/index.js +0 -6
- package/src/core/state/lifecycle.js +0 -64
- package/src/core/state/store.js +0 -112
- package/src/core/utils/index.js +0 -39
- package/src/core/utils/object.js +0 -22
- package/src/core/utils/validate.js +0 -37
- /package/src/components/checkbox/{styles.scss → _styles.scss} +0 -0
- /package/src/components/checkbox/{constants.js → constants.ts} +0 -0
- /package/src/components/list/{styles.scss → _styles.scss} +0 -0
- /package/src/components/menu/{styles.scss → _styles.scss} +0 -0
- /package/src/components/navigation/{styles.scss → _styles.scss} +0 -0
- /package/src/components/snackbar/{styles.scss → _styles.scss} +0 -0
- /package/src/components/switch/{styles.scss → _styles.scss} +0 -0
- /package/src/components/switch/{constants.js → constants.ts} +0 -0
- /package/src/components/textfield/{styles.scss → _styles.scss} +0 -0
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
// src/components/switch/api.js
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Enhances switch component with API methods
|
|
5
|
-
* @param {Object} options - API configuration
|
|
6
|
-
* @param {Object} options.disabled - Disabled state handlers
|
|
7
|
-
* @param {Object} options.lifecycle - Lifecycle handlers
|
|
8
|
-
* @param {Object} options.checkable - Checked state handlers
|
|
9
|
-
*/
|
|
10
|
-
export const withAPI = ({ disabled, lifecycle, checkable }) => (component) => ({
|
|
11
|
-
...component,
|
|
12
|
-
element: component.element,
|
|
13
|
-
|
|
14
|
-
// Value management
|
|
15
|
-
getValue: component.getValue,
|
|
16
|
-
setValue (value) {
|
|
17
|
-
component.setValue(value)
|
|
18
|
-
return this
|
|
19
|
-
},
|
|
20
|
-
|
|
21
|
-
// State management
|
|
22
|
-
check: checkable.check,
|
|
23
|
-
uncheck: checkable.uncheck,
|
|
24
|
-
toggle: checkable.toggle,
|
|
25
|
-
isChecked: checkable.isChecked,
|
|
26
|
-
|
|
27
|
-
// Label management
|
|
28
|
-
setLabel (text) {
|
|
29
|
-
component.text?.setText(text)
|
|
30
|
-
return this
|
|
31
|
-
},
|
|
32
|
-
getLabel () {
|
|
33
|
-
return component.text?.getText() || ''
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
// Event handling
|
|
37
|
-
on: component.on,
|
|
38
|
-
off: component.off,
|
|
39
|
-
|
|
40
|
-
// State management
|
|
41
|
-
enable: disabled.enable,
|
|
42
|
-
disable: disabled.disable,
|
|
43
|
-
destroy: lifecycle.destroy
|
|
44
|
-
})
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
// src/components/switch/switch.js
|
|
2
|
-
import { PREFIX } from '../../core/config'
|
|
3
|
-
import { pipe } from '../../core/compose'
|
|
4
|
-
import { createBase, withElement } from '../../core/compose/component'
|
|
5
|
-
import {
|
|
6
|
-
withEvents,
|
|
7
|
-
withTextLabel,
|
|
8
|
-
withDisabled,
|
|
9
|
-
withLifecycle,
|
|
10
|
-
withInput,
|
|
11
|
-
withTrack,
|
|
12
|
-
withCheckable
|
|
13
|
-
} from '../../core/compose/features'
|
|
14
|
-
import { withAPI } from './api'
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Adds label position handling to switch
|
|
18
|
-
*/
|
|
19
|
-
const withLabelPosition = (config) => (component) => {
|
|
20
|
-
if (!config.label) return component
|
|
21
|
-
|
|
22
|
-
const position = config.labelPosition || 'end'
|
|
23
|
-
component.element.classList.add(`${PREFIX}-switch--label-${position}`)
|
|
24
|
-
|
|
25
|
-
return component
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Creates a new Switch component
|
|
30
|
-
* @param {Object} config - Switch configuration
|
|
31
|
-
* @param {string} [config.name] - Input name
|
|
32
|
-
* @param {boolean} [config.checked] - Initial checked state
|
|
33
|
-
* @param {boolean} [config.required] - Is input required
|
|
34
|
-
* @param {boolean} [config.disabled] - Is switch disabled
|
|
35
|
-
* @param {string} [config.value] - Input value
|
|
36
|
-
* @param {string} [config.label] - Label text
|
|
37
|
-
* @param {string} [config.labelPosition='end'] - Label position (start/end)
|
|
38
|
-
* @param {string} [config.class] - Additional CSS classes
|
|
39
|
-
*/
|
|
40
|
-
const createSwitch = (config = {}) => {
|
|
41
|
-
const baseConfig = {
|
|
42
|
-
...config,
|
|
43
|
-
componentName: 'switch',
|
|
44
|
-
prefix: PREFIX
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return pipe(
|
|
48
|
-
createBase,
|
|
49
|
-
withEvents(), // Move events first to ensure system is available
|
|
50
|
-
withElement({
|
|
51
|
-
tag: 'div',
|
|
52
|
-
componentName: 'switch',
|
|
53
|
-
className: config.class,
|
|
54
|
-
interactive: true
|
|
55
|
-
}),
|
|
56
|
-
withInput(baseConfig),
|
|
57
|
-
withTrack(baseConfig),
|
|
58
|
-
withTextLabel(baseConfig),
|
|
59
|
-
withLabelPosition(baseConfig),
|
|
60
|
-
withCheckable(baseConfig),
|
|
61
|
-
withDisabled(baseConfig), // Pass the config to ensure disabled state is properly initialized
|
|
62
|
-
withLifecycle(),
|
|
63
|
-
comp => withAPI({
|
|
64
|
-
disabled: comp.disabled,
|
|
65
|
-
lifecycle: comp.lifecycle,
|
|
66
|
-
checkable: comp.checkable
|
|
67
|
-
})(comp)
|
|
68
|
-
)(baseConfig)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export default createSwitch
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
// src/components/textfield/api.js
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Enhances textfield component with API methods
|
|
5
|
-
* @param {Object} options - API configuration
|
|
6
|
-
* @param {Object} options.disabled - Disabled state handlers
|
|
7
|
-
* @param {Object} options.lifecycle - Lifecycle handlers
|
|
8
|
-
*/
|
|
9
|
-
export const withAPI = ({ disabled, lifecycle }) => (component) => ({
|
|
10
|
-
...component,
|
|
11
|
-
// Core element reference
|
|
12
|
-
element: component.element,
|
|
13
|
-
|
|
14
|
-
// Value management
|
|
15
|
-
getValue: () => component.getValue(),
|
|
16
|
-
setValue (value) {
|
|
17
|
-
component.setValue(value)
|
|
18
|
-
return this
|
|
19
|
-
},
|
|
20
|
-
|
|
21
|
-
// Attributes API
|
|
22
|
-
setAttribute (name, value) {
|
|
23
|
-
component.setAttribute(name, value)
|
|
24
|
-
return this
|
|
25
|
-
},
|
|
26
|
-
getAttribute: component.getAttribute,
|
|
27
|
-
removeAttribute (name) {
|
|
28
|
-
component.removeAttribute(name)
|
|
29
|
-
return this
|
|
30
|
-
},
|
|
31
|
-
|
|
32
|
-
// Label management
|
|
33
|
-
setLabel (text) {
|
|
34
|
-
component.label?.setText(text)
|
|
35
|
-
return this
|
|
36
|
-
},
|
|
37
|
-
getLabel () {
|
|
38
|
-
return component.label?.getText() || ''
|
|
39
|
-
},
|
|
40
|
-
|
|
41
|
-
// Event handling
|
|
42
|
-
on: component.on,
|
|
43
|
-
off: component.off,
|
|
44
|
-
|
|
45
|
-
// State management
|
|
46
|
-
enable: disabled.enable,
|
|
47
|
-
disable: disabled.disable,
|
|
48
|
-
destroy: lifecycle.destroy
|
|
49
|
-
})
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
// src/components/textfield/textfield.js
|
|
2
|
-
import { PREFIX } from '../../core/config'
|
|
3
|
-
import { pipe } from '../../core/compose'
|
|
4
|
-
import { createBase, withElement } from '../../core/compose/component'
|
|
5
|
-
import {
|
|
6
|
-
withEvents,
|
|
7
|
-
withDisabled,
|
|
8
|
-
withLifecycle,
|
|
9
|
-
withVariant,
|
|
10
|
-
withSize,
|
|
11
|
-
withTextInput,
|
|
12
|
-
withTextLabel
|
|
13
|
-
} from '../../core/compose/features'
|
|
14
|
-
import { withAPI } from './api'
|
|
15
|
-
import { TEXTFIELD_VARIANTS } from './constants'
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Creates a new Textfield component
|
|
19
|
-
* @param {Object} config - Textfield configuration
|
|
20
|
-
* @param {string} [config.type] - Input type (text, password, email, etc.)
|
|
21
|
-
* @param {string} [config.variant] - Visual variant (filled, outlined)
|
|
22
|
-
* @param {string} [config.size] - Size variant (small, medium, large)
|
|
23
|
-
* @param {string} [config.name] - Input name attribute
|
|
24
|
-
* @param {string} [config.label] - Label text
|
|
25
|
-
* @param {string} [config.placeholder] - Placeholder text
|
|
26
|
-
* @param {string} [config.value] - Initial value
|
|
27
|
-
* @param {boolean} [config.required] - Whether the input is required
|
|
28
|
-
* @param {boolean} [config.disabled] - Whether the input is disabled
|
|
29
|
-
* @param {number} [config.maxLength] - Maximum input length
|
|
30
|
-
* @param {string} [config.pattern] - Input pattern for validation
|
|
31
|
-
* @param {string} [config.autocomplete] - Autocomplete attribute
|
|
32
|
-
* @param {string} [config.class] - Additional CSS classes
|
|
33
|
-
* @returns {Object} Textfield component instance
|
|
34
|
-
*/
|
|
35
|
-
const createTextfield = (config = {}) => {
|
|
36
|
-
const baseConfig = {
|
|
37
|
-
...config,
|
|
38
|
-
componentName: 'textfield',
|
|
39
|
-
prefix: PREFIX,
|
|
40
|
-
variant: config.variant || TEXTFIELD_VARIANTS.FILLED
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
try {
|
|
44
|
-
return pipe(
|
|
45
|
-
createBase,
|
|
46
|
-
withEvents(),
|
|
47
|
-
withElement({
|
|
48
|
-
tag: 'div',
|
|
49
|
-
componentName: 'textfield',
|
|
50
|
-
className: config.class
|
|
51
|
-
}),
|
|
52
|
-
withVariant(baseConfig),
|
|
53
|
-
withSize(baseConfig),
|
|
54
|
-
withTextInput(baseConfig),
|
|
55
|
-
withTextLabel(baseConfig),
|
|
56
|
-
withDisabled(baseConfig),
|
|
57
|
-
withLifecycle(),
|
|
58
|
-
comp => withAPI({
|
|
59
|
-
disabled: comp.disabled,
|
|
60
|
-
lifecycle: comp.lifecycle
|
|
61
|
-
})(comp)
|
|
62
|
-
)(baseConfig)
|
|
63
|
-
} catch (error) {
|
|
64
|
-
throw new Error(`Failed to create textfield: ${error.message}`)
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export default createTextfield
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
// src/components/ripple/_ripple.scss
|
|
2
|
-
@use '../../styles/abstract/base' as base;
|
|
3
|
-
@use '../../styles/abstract/variables' as v;
|
|
4
|
-
@use '../../styles/abstract/functions' as f;
|
|
5
|
-
@use '../../styles/abstract/mixins' as m;
|
|
6
|
-
@use '../../styles/abstract/theme' as t;
|
|
7
|
-
|
|
8
|
-
$component: '#{base.$prefix}-ripple';
|
|
9
|
-
|
|
10
|
-
.#{$component} {
|
|
11
|
-
// Ripple container
|
|
12
|
-
position: absolute;
|
|
13
|
-
top: 0;
|
|
14
|
-
left: 0;
|
|
15
|
-
right: 0;
|
|
16
|
-
bottom: 0;
|
|
17
|
-
overflow: hidden;
|
|
18
|
-
border-radius: inherit;
|
|
19
|
-
pointer-events: none;
|
|
20
|
-
z-index: 0;
|
|
21
|
-
|
|
22
|
-
// Ripple element
|
|
23
|
-
&-wave {
|
|
24
|
-
position: absolute;
|
|
25
|
-
border-radius: 50%;
|
|
26
|
-
background-color: currentColor;
|
|
27
|
-
transform: scale(0);
|
|
28
|
-
opacity: 0;
|
|
29
|
-
pointer-events: none;
|
|
30
|
-
will-change: transform, opacity;
|
|
31
|
-
|
|
32
|
-
// Animation
|
|
33
|
-
transition-property: transform, opacity;
|
|
34
|
-
transition-duration: v.motion('duration-short4');
|
|
35
|
-
transition-timing-function: v.motion('easing-standard');
|
|
36
|
-
|
|
37
|
-
// Active ripple
|
|
38
|
-
&.active {
|
|
39
|
-
transform: scale(1);
|
|
40
|
-
opacity: v.state('hover-state-layer-opacity');
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
&.fade-out {
|
|
44
|
-
opacity: 0;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Standalone utility for adding ripple to any element
|
|
50
|
-
[data-ripple] {
|
|
51
|
-
position: relative;
|
|
52
|
-
overflow: hidden;
|
|
53
|
-
|
|
54
|
-
&::after {
|
|
55
|
-
content: '';
|
|
56
|
-
position: absolute;
|
|
57
|
-
top: 0;
|
|
58
|
-
left: 0;
|
|
59
|
-
right: 0;
|
|
60
|
-
bottom: 0;
|
|
61
|
-
z-index: 0;
|
|
62
|
-
pointer-events: none;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Handle ripple color based on data attribute
|
|
66
|
-
&[data-ripple="light"]::after {
|
|
67
|
-
background-color: rgba(255, 255, 255, 0.3);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
&[data-ripple="dark"]::after {
|
|
71
|
-
background-color: rgba(0, 0, 0, 0.1);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Make content appear above ripple
|
|
75
|
-
> * {
|
|
76
|
-
position: relative;
|
|
77
|
-
z-index: 1;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
// src/core/build/constants.js
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Animation timing functions for ripple effect
|
|
5
|
-
* @enum {string}
|
|
6
|
-
*/
|
|
7
|
-
export const RIPPLE_TIMING = {
|
|
8
|
-
LINEAR: 'linear',
|
|
9
|
-
EASE: 'ease',
|
|
10
|
-
EASE_IN: 'ease-in',
|
|
11
|
-
EASE_OUT: 'ease-out',
|
|
12
|
-
EASE_IN_OUT: 'ease-in-out',
|
|
13
|
-
MATERIAL: 'cubic-bezier(0.4, 0.0, 0.2, 1)'
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Default configuration for ripple effect
|
|
18
|
-
* @type {Object}
|
|
19
|
-
*/
|
|
20
|
-
export const RIPPLE_CONFIG = {
|
|
21
|
-
duration: 375,
|
|
22
|
-
timing: RIPPLE_TIMING.LINEAR,
|
|
23
|
-
opacity: ['1', '0.3']
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Validation schema for ripple configuration
|
|
28
|
-
* @type {Object}
|
|
29
|
-
*/
|
|
30
|
-
export const RIPPLE_SCHEMA = {
|
|
31
|
-
duration: {
|
|
32
|
-
type: 'number',
|
|
33
|
-
minimum: 0,
|
|
34
|
-
default: RIPPLE_CONFIG.duration
|
|
35
|
-
},
|
|
36
|
-
timing: {
|
|
37
|
-
type: 'string',
|
|
38
|
-
enum: Object.values(RIPPLE_TIMING),
|
|
39
|
-
default: RIPPLE_CONFIG.timing
|
|
40
|
-
},
|
|
41
|
-
opacity: {
|
|
42
|
-
type: 'array',
|
|
43
|
-
items: {
|
|
44
|
-
type: 'string',
|
|
45
|
-
pattern: '^[0-1](\\.\\d+)?$'
|
|
46
|
-
},
|
|
47
|
-
minItems: 2,
|
|
48
|
-
maxItems: 2,
|
|
49
|
-
default: RIPPLE_CONFIG.opacity
|
|
50
|
-
}
|
|
51
|
-
}
|
package/src/core/build/icon.js
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
// src/core/build/icon.js
|
|
2
|
-
/**
|
|
3
|
-
* @module core/build
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Creates an icon DOM element
|
|
8
|
-
* @memberof module:core/build
|
|
9
|
-
* @private
|
|
10
|
-
* @param {string} html - Icon HTML content
|
|
11
|
-
* @param {Object} [options] - Icon options
|
|
12
|
-
* @param {string} [options.prefix='mtrl'] - Class prefix
|
|
13
|
-
* @param {string} [options.class] - Additional CSS class
|
|
14
|
-
* @param {string} [options.size] - Icon size variant
|
|
15
|
-
* @returns {HTMLElement} Icon element
|
|
16
|
-
*/
|
|
17
|
-
const createIconElement = (html, options = {}) => {
|
|
18
|
-
const PREFIX = options.prefix || 'mtrl'
|
|
19
|
-
const element = document.createElement('span')
|
|
20
|
-
element.className = `${PREFIX}-icon`
|
|
21
|
-
|
|
22
|
-
if (options.class) {
|
|
23
|
-
element.classList.add(options.class)
|
|
24
|
-
}
|
|
25
|
-
if (options.size) {
|
|
26
|
-
element.classList.add(`${PREFIX}-icon--${options.size}`)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
element.innerHTML = html
|
|
30
|
-
return element
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Creates an icon manager for a component
|
|
35
|
-
* @memberof module:core/build
|
|
36
|
-
* @function createIcon
|
|
37
|
-
* @param {HTMLElement} element - Parent element
|
|
38
|
-
* @param {Object} [config] - Icon configuration
|
|
39
|
-
* @param {string} [config.prefix='mtrl'] - Class prefix
|
|
40
|
-
* @param {string} [config.type='component'] - Component type
|
|
41
|
-
* @param {string} [config.position] - Icon position ('start' or 'end')
|
|
42
|
-
* @returns {Object} Icon manager interface
|
|
43
|
-
* @property {Function} setIcon - Sets icon content
|
|
44
|
-
* @property {Function} getIcon - Gets current icon content
|
|
45
|
-
* @property {Function} getElement - Gets icon element
|
|
46
|
-
*/
|
|
47
|
-
export const createIcon = (element, config = {}) => {
|
|
48
|
-
let iconElement = null
|
|
49
|
-
const PREFIX = config.prefix || 'mtrl'
|
|
50
|
-
|
|
51
|
-
return {
|
|
52
|
-
setIcon (html) {
|
|
53
|
-
if (!iconElement && html) {
|
|
54
|
-
iconElement = createIconElement(html, {
|
|
55
|
-
prefix: PREFIX,
|
|
56
|
-
class: `${PREFIX}-${config.type || 'component'}-icon`,
|
|
57
|
-
size: config.iconSize
|
|
58
|
-
})
|
|
59
|
-
if (config.position === 'end') {
|
|
60
|
-
element.appendChild(iconElement)
|
|
61
|
-
} else {
|
|
62
|
-
element.insertBefore(iconElement, element.firstChild)
|
|
63
|
-
}
|
|
64
|
-
} else if (iconElement && html) {
|
|
65
|
-
iconElement.innerHTML = html
|
|
66
|
-
}
|
|
67
|
-
return this
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
getIcon () {
|
|
71
|
-
return iconElement ? iconElement.innerHTML : ''
|
|
72
|
-
},
|
|
73
|
-
|
|
74
|
-
getElement () {
|
|
75
|
-
return iconElement
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
package/src/core/build/ripple.js
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
// src/core/build/ripple.js
|
|
2
|
-
|
|
3
|
-
import { RIPPLE_CONFIG } from './constants'
|
|
4
|
-
|
|
5
|
-
const DEFAULT_CONFIG = RIPPLE_CONFIG
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Creates a ripple effect instance
|
|
9
|
-
* @param {Object} [config] - Ripple configuration
|
|
10
|
-
* @param {number} [config.duration] - Animation duration in ms
|
|
11
|
-
* @param {string} [config.timing] - Animation timing function
|
|
12
|
-
* @param {string[]} [config.opacity] - Start and end opacity values
|
|
13
|
-
* @returns {Object} Ripple controller instance
|
|
14
|
-
*/
|
|
15
|
-
export const createRipple = (config = {}) => {
|
|
16
|
-
// Make sure we fully merge the config options
|
|
17
|
-
const options = {
|
|
18
|
-
...DEFAULT_CONFIG,
|
|
19
|
-
...config,
|
|
20
|
-
// Handle nested objects like opacity array
|
|
21
|
-
opacity: config.opacity || DEFAULT_CONFIG.opacity
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const getEndCoordinates = (bounds) => {
|
|
25
|
-
const size = Math.max(bounds.width, bounds.height)
|
|
26
|
-
const top = bounds.height > bounds.width
|
|
27
|
-
? -bounds.height / 2
|
|
28
|
-
: -(bounds.width - bounds.height / 2)
|
|
29
|
-
|
|
30
|
-
return {
|
|
31
|
-
size: `${size * 2}px`,
|
|
32
|
-
top: `${top}px`,
|
|
33
|
-
left: `${size / -2}px`
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const createRippleElement = () => {
|
|
38
|
-
const ripple = document.createElement('div')
|
|
39
|
-
ripple.className = 'ripple'
|
|
40
|
-
// Initial styles already set in CSS
|
|
41
|
-
ripple.style.transition = `all ${options.duration}ms ${options.timing}`
|
|
42
|
-
return ripple
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Store document event listeners for cleanup
|
|
46
|
-
let documentListeners = []
|
|
47
|
-
|
|
48
|
-
// Safe document event handling
|
|
49
|
-
const addDocumentListener = (event, handler) => {
|
|
50
|
-
if (typeof document.addEventListener === 'function') {
|
|
51
|
-
document.addEventListener(event, handler)
|
|
52
|
-
documentListeners.push({ event, handler })
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const removeDocumentListener = (event, handler) => {
|
|
57
|
-
if (typeof document.removeEventListener === 'function') {
|
|
58
|
-
document.removeEventListener(event, handler)
|
|
59
|
-
documentListeners = documentListeners.filter(
|
|
60
|
-
listener => !(listener.event === event && listener.handler === handler)
|
|
61
|
-
)
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const animate = (event, container) => {
|
|
66
|
-
if (!container) return
|
|
67
|
-
|
|
68
|
-
const bounds = container.getBoundingClientRect()
|
|
69
|
-
const ripple = createRippleElement()
|
|
70
|
-
|
|
71
|
-
// Set initial position and state
|
|
72
|
-
Object.assign(ripple.style, {
|
|
73
|
-
left: `${event.offsetX || bounds.width / 2}px`,
|
|
74
|
-
top: `${event.offsetY || bounds.height / 2}px`,
|
|
75
|
-
transform: 'scale(0)',
|
|
76
|
-
opacity: options.opacity[0]
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
container.appendChild(ripple)
|
|
80
|
-
|
|
81
|
-
// Force reflow
|
|
82
|
-
// eslint-disable-next-line no-unused-expressions
|
|
83
|
-
ripple.offsetHeight
|
|
84
|
-
|
|
85
|
-
// Animate to end position
|
|
86
|
-
const end = getEndCoordinates(bounds)
|
|
87
|
-
Object.assign(ripple.style, {
|
|
88
|
-
...end,
|
|
89
|
-
transform: 'scale(1)',
|
|
90
|
-
opacity: options.opacity[1]
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
const cleanup = () => {
|
|
94
|
-
ripple.style.opacity = '0'
|
|
95
|
-
|
|
96
|
-
// Use setTimeout to remove element after animation
|
|
97
|
-
setTimeout(() => {
|
|
98
|
-
if (ripple.parentNode) {
|
|
99
|
-
ripple.parentNode.removeChild(ripple)
|
|
100
|
-
}
|
|
101
|
-
}, options.duration)
|
|
102
|
-
|
|
103
|
-
removeDocumentListener('mouseup', cleanup)
|
|
104
|
-
removeDocumentListener('mouseleave', cleanup)
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
addDocumentListener('mouseup', cleanup)
|
|
108
|
-
addDocumentListener('mouseleave', cleanup)
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return {
|
|
112
|
-
mount: (element) => {
|
|
113
|
-
if (!element) return
|
|
114
|
-
|
|
115
|
-
// Ensure proper positioning context
|
|
116
|
-
const currentPosition = window.getComputedStyle(element).position
|
|
117
|
-
if (currentPosition === 'static') {
|
|
118
|
-
element.style.position = 'relative'
|
|
119
|
-
}
|
|
120
|
-
element.style.overflow = 'hidden'
|
|
121
|
-
|
|
122
|
-
// Store the mousedown handler to be able to remove it later
|
|
123
|
-
const mousedownHandler = (e) => animate(e, element)
|
|
124
|
-
|
|
125
|
-
// Store handler reference on the element
|
|
126
|
-
if (!element.__rippleHandlers) {
|
|
127
|
-
element.__rippleHandlers = []
|
|
128
|
-
}
|
|
129
|
-
element.__rippleHandlers.push(mousedownHandler)
|
|
130
|
-
|
|
131
|
-
element.addEventListener('mousedown', mousedownHandler)
|
|
132
|
-
},
|
|
133
|
-
|
|
134
|
-
unmount: (element) => {
|
|
135
|
-
if (!element) return
|
|
136
|
-
|
|
137
|
-
// Clear document event listeners
|
|
138
|
-
documentListeners.forEach(({ event, handler }) => {
|
|
139
|
-
removeDocumentListener(event, handler)
|
|
140
|
-
})
|
|
141
|
-
documentListeners = []
|
|
142
|
-
|
|
143
|
-
// Remove event listeners
|
|
144
|
-
if (element.__rippleHandlers) {
|
|
145
|
-
element.__rippleHandlers.forEach(handler => {
|
|
146
|
-
element.removeEventListener('mousedown', handler)
|
|
147
|
-
})
|
|
148
|
-
element.__rippleHandlers = []
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Remove all ripple elements
|
|
152
|
-
const ripples = element.querySelectorAll('.ripple')
|
|
153
|
-
ripples.forEach(ripple => {
|
|
154
|
-
// Call remove directly to match the test expectation
|
|
155
|
-
ripple.remove()
|
|
156
|
-
})
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
package/src/core/build/text.js
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
// src/core/build/text.js
|
|
2
|
-
/**
|
|
3
|
-
* @module core/build
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Creates a text manager for a component
|
|
8
|
-
* @memberof module:core/build
|
|
9
|
-
* @function createText
|
|
10
|
-
* @param {HTMLElement} element - Parent element
|
|
11
|
-
* @param {Object} [config] - Text configuration
|
|
12
|
-
* @param {string} [config.prefix='mtrl'] - Class prefix
|
|
13
|
-
* @param {string} [config.type='component'] - Component type
|
|
14
|
-
* @param {HTMLElement} [config.beforeElement] - Element to insert before
|
|
15
|
-
* @returns {Object} Text manager interface
|
|
16
|
-
* @property {Function} setText - Sets text content
|
|
17
|
-
* @property {Function} getText - Gets current text
|
|
18
|
-
* @property {Function} getElement - Gets text element
|
|
19
|
-
*/
|
|
20
|
-
export const createText = (element, config = {}) => {
|
|
21
|
-
let textElement = null
|
|
22
|
-
const PREFIX = config.prefix || 'mtrl'
|
|
23
|
-
|
|
24
|
-
const createElement = (content) => {
|
|
25
|
-
const span = document.createElement('span')
|
|
26
|
-
span.className = `${PREFIX}-${config.type || 'component'}-text`
|
|
27
|
-
span.textContent = content
|
|
28
|
-
return span
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return {
|
|
32
|
-
setText (text) {
|
|
33
|
-
if (!textElement && text) {
|
|
34
|
-
textElement = createElement(text)
|
|
35
|
-
if (config.beforeElement) {
|
|
36
|
-
element.insertBefore(textElement, config.beforeElement)
|
|
37
|
-
} else {
|
|
38
|
-
element.appendChild(textElement)
|
|
39
|
-
}
|
|
40
|
-
} else if (textElement) {
|
|
41
|
-
textElement.textContent = text
|
|
42
|
-
}
|
|
43
|
-
return this
|
|
44
|
-
},
|
|
45
|
-
|
|
46
|
-
getText () {
|
|
47
|
-
return textElement ? textElement.textContent : ''
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
getElement () {
|
|
51
|
-
return textElement
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|