mtrl 0.2.1 → 0.2.3
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/.typedocignore +11 -0
- package/DOCS.md +153 -0
- package/index.ts +18 -3
- package/package.json +7 -2
- package/src/components/badge/_styles.scss +174 -0
- package/src/components/badge/api.ts +292 -0
- package/src/components/badge/badge.ts +52 -0
- package/src/components/badge/config.ts +68 -0
- package/src/components/badge/constants.ts +30 -0
- package/src/components/badge/features.ts +185 -0
- package/src/components/badge/index.ts +4 -0
- package/src/components/badge/types.ts +105 -0
- package/src/components/button/types.ts +174 -29
- package/src/components/card/constants.ts +14 -0
- package/src/components/carousel/_styles.scss +645 -0
- package/src/components/carousel/api.ts +147 -0
- package/src/components/carousel/carousel.ts +178 -0
- package/src/components/carousel/config.ts +91 -0
- package/src/components/carousel/constants.ts +95 -0
- package/src/components/carousel/features/drag.ts +388 -0
- package/src/components/carousel/features/index.ts +8 -0
- package/src/components/carousel/features/slides.ts +682 -0
- package/src/components/carousel/index.ts +38 -0
- package/src/components/carousel/types.ts +327 -0
- package/src/components/chip/_styles.scss +83 -140
- package/src/components/chip/api.ts +231 -102
- package/src/components/chip/chip.ts +356 -44
- package/src/components/chip/constants.ts +3 -3
- package/src/components/chip/index.ts +3 -3
- package/src/components/dialog/_styles.scss +213 -0
- package/src/components/dialog/api.ts +283 -0
- package/src/components/dialog/config.ts +113 -0
- package/src/components/dialog/constants.ts +32 -0
- package/src/components/dialog/dialog.ts +56 -0
- package/src/components/dialog/features.ts +713 -0
- package/src/components/dialog/index.ts +15 -0
- package/src/components/dialog/types.ts +221 -0
- package/src/components/progress/_styles.scss +13 -1
- package/src/components/progress/api.ts +2 -2
- package/src/components/progress/progress.ts +2 -2
- package/src/components/progress/types.ts +3 -0
- package/src/components/radios/_styles.scss +232 -0
- package/src/components/radios/api.ts +100 -0
- package/src/components/radios/config.ts +60 -0
- package/src/components/radios/constants.ts +28 -0
- package/src/components/radios/index.ts +4 -0
- package/src/components/radios/radio.ts +269 -0
- package/src/components/radios/radios.ts +42 -0
- package/src/components/radios/types.ts +232 -0
- package/src/components/sheet/_styles.scss +236 -0
- package/src/components/sheet/api.ts +96 -0
- package/src/components/sheet/config.ts +66 -0
- package/src/components/sheet/constants.ts +20 -0
- package/src/components/sheet/features/content.ts +51 -0
- package/src/components/sheet/features/gestures.ts +177 -0
- package/src/components/sheet/features/index.ts +6 -0
- package/src/components/sheet/features/position.ts +42 -0
- package/src/components/sheet/features/state.ts +116 -0
- package/src/components/sheet/features/title.ts +86 -0
- package/src/components/sheet/index.ts +4 -0
- package/src/components/sheet/sheet.ts +57 -0
- package/src/components/sheet/types.ts +266 -0
- package/src/components/slider/_styles.scss +518 -0
- package/src/components/slider/api.ts +336 -0
- package/src/components/slider/config.ts +145 -0
- package/src/components/slider/constants.ts +28 -0
- package/src/components/slider/features/appearance.ts +140 -0
- package/src/components/slider/features/disabled.ts +43 -0
- package/src/components/slider/features/events.ts +164 -0
- package/src/components/slider/features/index.ts +5 -0
- package/src/components/slider/features/interactions.ts +256 -0
- package/src/components/slider/features/keyboard.ts +114 -0
- package/src/components/slider/features/slider.ts +336 -0
- package/src/components/slider/features/structure.ts +264 -0
- package/src/components/slider/features/ui.ts +518 -0
- package/src/components/slider/index.ts +9 -0
- package/src/components/slider/slider.ts +58 -0
- package/src/components/slider/types.ts +166 -0
- package/src/components/tabs/_styles.scss +224 -0
- package/src/components/tabs/api.ts +443 -0
- package/src/components/tabs/config.ts +80 -0
- package/src/components/tabs/constants.ts +12 -0
- package/src/components/tabs/index.ts +4 -0
- package/src/components/tabs/tabs.ts +52 -0
- package/src/components/tabs/types.ts +247 -0
- package/src/components/textfield/_styles.scss +97 -4
- package/src/components/tooltip/_styles.scss +241 -0
- package/src/components/tooltip/api.ts +411 -0
- package/src/components/tooltip/config.ts +78 -0
- package/src/components/tooltip/constants.ts +27 -0
- package/src/components/tooltip/index.ts +4 -0
- package/src/components/tooltip/tooltip.ts +60 -0
- package/src/components/tooltip/types.ts +178 -0
- package/src/index.ts +9 -1
- package/src/styles/abstract/_variables.scss +24 -0
- package/tsconfig.json +22 -0
- package/typedoc.json +28 -0
- package/typedoc.simple.json +14 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
// src/components/chip/chip.
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
// src/components/chip/chip.js
|
|
2
|
+
import { PREFIX } from '../../core/config'
|
|
3
|
+
import { pipe } from '../../core/compose'
|
|
4
|
+
import { createBase, withElement } from '../../core/compose/component'
|
|
4
5
|
import {
|
|
5
6
|
withEvents,
|
|
6
7
|
withText,
|
|
@@ -10,72 +11,383 @@ import {
|
|
|
10
11
|
withRipple,
|
|
11
12
|
withDisabled,
|
|
12
13
|
withLifecycle
|
|
13
|
-
} from '../../core/compose/features'
|
|
14
|
-
import { withAPI } from './api'
|
|
15
|
-
import {
|
|
16
|
-
import { createBaseConfig, getElementConfig, getApiConfig } from './config';
|
|
14
|
+
} from '../../core/compose/features'
|
|
15
|
+
import { withAPI } from './api'
|
|
16
|
+
import { CHIP_VARIANTS, CHIP_SIZES } from './constants'
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Creates a new Chip component
|
|
20
|
-
* @param {
|
|
21
|
-
* @
|
|
20
|
+
* @param {Object} config - Chip configuration
|
|
21
|
+
* @param {string} [config.variant='filled'] - Chip variant
|
|
22
|
+
* @param {string} [config.size='medium'] - Chip size
|
|
23
|
+
* @param {boolean} [config.selected=false] - Whether the chip is initially selected
|
|
24
|
+
* @param {boolean} [config.disabled=false] - Whether the chip is initially disabled
|
|
25
|
+
* @param {string} [config.text] - Chip text content
|
|
26
|
+
* @param {string} [config.leadingIcon] - Leading icon HTML content
|
|
27
|
+
* @param {string} [config.trailingIcon] - Trailing icon HTML content
|
|
28
|
+
* @param {string} [config.class] - Additional CSS classes
|
|
29
|
+
* @param {string} [config.value] - Chip value
|
|
30
|
+
* @param {boolean} [config.ripple=true] - Whether to enable ripple effect
|
|
31
|
+
* @param {Function} [config.onTrailingIconClick] - Callback when trailing icon is clicked
|
|
32
|
+
* @param {Function} [config.onSelect] - Callback when chip is selected
|
|
33
|
+
* @param {Function} [config.onChange] - Callback when chip selection changes
|
|
34
|
+
* @returns {Object} Chip component instance
|
|
22
35
|
*/
|
|
23
|
-
const createChip = (config
|
|
24
|
-
const baseConfig =
|
|
36
|
+
const createChip = (config = {}) => {
|
|
37
|
+
const baseConfig = {
|
|
38
|
+
...config,
|
|
39
|
+
variant: config.variant || CHIP_VARIANTS.FILLED,
|
|
40
|
+
size: config.size || CHIP_SIZES.MEDIUM,
|
|
41
|
+
componentName: 'chip',
|
|
42
|
+
prefix: PREFIX,
|
|
43
|
+
ripple: config.ripple !== false
|
|
44
|
+
}
|
|
25
45
|
|
|
26
46
|
try {
|
|
47
|
+
// Create base component with core features
|
|
27
48
|
const chip = pipe(
|
|
28
49
|
createBase,
|
|
29
50
|
withEvents(),
|
|
30
|
-
withElement(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
51
|
+
withElement({
|
|
52
|
+
tag: 'div',
|
|
53
|
+
componentName: 'chip',
|
|
54
|
+
attrs: {
|
|
55
|
+
role: 'button',
|
|
56
|
+
tabindex: '0',
|
|
57
|
+
'aria-disabled': config.disabled ? 'true' : 'false',
|
|
58
|
+
'aria-selected': config.selected ? 'true' : 'false',
|
|
59
|
+
'data-value': config.value || ''
|
|
60
|
+
},
|
|
61
|
+
className: config.class,
|
|
62
|
+
forwardEvents: {
|
|
63
|
+
click: (component) => component.element.getAttribute('aria-disabled') !== 'true',
|
|
64
|
+
focus: true,
|
|
65
|
+
blur: true
|
|
66
|
+
}
|
|
38
67
|
}),
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
68
|
+
withLifecycle()
|
|
69
|
+
)(baseConfig)
|
|
70
|
+
|
|
71
|
+
// Track selected state
|
|
72
|
+
let isSelectedState = !!config.selected;
|
|
73
|
+
|
|
74
|
+
// Manually add the variant class
|
|
75
|
+
if (config.variant) {
|
|
76
|
+
chip.element.classList.add(`${chip.getClass('chip')}--${config.variant}`)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Manually add the size class
|
|
80
|
+
if (config.size) {
|
|
81
|
+
chip.element.classList.add(`${chip.getClass('chip')}--${config.size}`)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Add ripple if enabled
|
|
85
|
+
if (config.ripple) {
|
|
86
|
+
withRipple(baseConfig)(chip)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Add disabled state if needed
|
|
90
|
+
if (config.disabled) {
|
|
91
|
+
withDisabled(baseConfig)(chip)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Add selected class if needed
|
|
95
|
+
if (config.selected) {
|
|
96
|
+
chip.element.classList.add(`${chip.getClass('chip')}--selected`)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Create a container for the chip content to ensure proper ordering
|
|
100
|
+
const contentContainer = document.createElement('div')
|
|
101
|
+
contentContainer.className = `${chip.getClass('chip')}-content`
|
|
102
|
+
contentContainer.style.display = 'flex'
|
|
103
|
+
contentContainer.style.alignItems = 'center'
|
|
104
|
+
contentContainer.style.justifyContent = 'center'
|
|
105
|
+
contentContainer.style.width = '100%'
|
|
106
|
+
chip.element.appendChild(contentContainer)
|
|
107
|
+
|
|
108
|
+
// Add leading icon if provided
|
|
109
|
+
if (config.leadingIcon) {
|
|
110
|
+
const leadingIconElement = document.createElement('span')
|
|
111
|
+
leadingIconElement.className = `${chip.getClass('chip')}-leading-icon`
|
|
112
|
+
leadingIconElement.innerHTML = config.leadingIcon
|
|
113
|
+
contentContainer.appendChild(leadingIconElement)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Add text element if provided
|
|
117
|
+
if (config.text) {
|
|
118
|
+
const textElement = document.createElement('span')
|
|
119
|
+
textElement.className = `${chip.getClass('chip')}-text`
|
|
120
|
+
textElement.textContent = config.text
|
|
121
|
+
contentContainer.appendChild(textElement)
|
|
122
|
+
}
|
|
44
123
|
|
|
45
124
|
// Add trailing icon if provided
|
|
46
125
|
if (config.trailingIcon) {
|
|
47
|
-
const trailingIconElement = document.createElement('span')
|
|
48
|
-
trailingIconElement.className = `${
|
|
49
|
-
trailingIconElement.innerHTML = config.trailingIcon
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// Add event listener for remove/close action if needed
|
|
126
|
+
const trailingIconElement = document.createElement('span')
|
|
127
|
+
trailingIconElement.className = `${chip.getClass('chip')}-trailing-icon`
|
|
128
|
+
trailingIconElement.innerHTML = config.trailingIcon
|
|
129
|
+
|
|
130
|
+
// Add click handler for trailing icon
|
|
53
131
|
if (config.onTrailingIconClick) {
|
|
54
132
|
trailingIconElement.addEventListener('click', (e) => {
|
|
55
|
-
e.stopPropagation()
|
|
56
|
-
config.onTrailingIconClick
|
|
57
|
-
})
|
|
133
|
+
e.stopPropagation() // Prevent chip click event
|
|
134
|
+
config.onTrailingIconClick(enhancedChip)
|
|
135
|
+
})
|
|
58
136
|
}
|
|
137
|
+
|
|
138
|
+
contentContainer.appendChild(trailingIconElement)
|
|
59
139
|
}
|
|
60
140
|
|
|
61
|
-
//
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
141
|
+
// Create enhanced component with API
|
|
142
|
+
const enhancedChip = {
|
|
143
|
+
...chip,
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Checks if the chip is disabled
|
|
147
|
+
* @returns {boolean} True if the chip is disabled
|
|
148
|
+
*/
|
|
149
|
+
isDisabled() {
|
|
150
|
+
return chip.element.getAttribute('aria-disabled') === 'true';
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Checks if the chip is selected
|
|
155
|
+
* @returns {boolean} True if the chip is selected
|
|
156
|
+
*/
|
|
157
|
+
isSelected() {
|
|
158
|
+
return isSelectedState;
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Sets the chip's selected state
|
|
163
|
+
* @param {boolean} selected - Whether the chip should be selected
|
|
164
|
+
* @returns {Object} The chip instance for chaining
|
|
165
|
+
*/
|
|
166
|
+
setSelected(selected) {
|
|
167
|
+
isSelectedState = !!selected;
|
|
168
|
+
|
|
169
|
+
if (selected) {
|
|
170
|
+
chip.element.classList.add(`${chip.getClass('chip')}--selected`);
|
|
171
|
+
chip.element.setAttribute('aria-selected', 'true');
|
|
172
|
+
} else {
|
|
173
|
+
chip.element.classList.remove(`${chip.getClass('chip')}--selected`);
|
|
174
|
+
chip.element.setAttribute('aria-selected', 'false');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return this;
|
|
178
|
+
},
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Toggles the chip's selected state
|
|
182
|
+
* @returns {Object} The chip instance for chaining
|
|
183
|
+
*/
|
|
184
|
+
toggleSelected() {
|
|
185
|
+
return this.setSelected(!isSelectedState);
|
|
186
|
+
},
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Gets the chip's value
|
|
190
|
+
* @returns {string} The chip's value
|
|
191
|
+
*/
|
|
192
|
+
getValue() {
|
|
193
|
+
return chip.element.getAttribute('data-value');
|
|
194
|
+
},
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Sets the chip's value
|
|
198
|
+
* @param {string} value - Value to set
|
|
199
|
+
* @returns {Object} The chip instance for chaining
|
|
200
|
+
*/
|
|
201
|
+
setValue(value) {
|
|
202
|
+
chip.element.setAttribute('data-value', value);
|
|
203
|
+
return this;
|
|
204
|
+
},
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Enables the chip
|
|
208
|
+
* @returns {Object} The chip instance for chaining
|
|
209
|
+
*/
|
|
210
|
+
enable() {
|
|
211
|
+
chip.element.classList.remove(`${chip.getClass('chip')}--disabled`);
|
|
212
|
+
chip.element.setAttribute('aria-disabled', 'false');
|
|
213
|
+
chip.element.setAttribute('tabindex', '0');
|
|
214
|
+
return this;
|
|
215
|
+
},
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Disables the chip
|
|
219
|
+
* @returns {Object} The chip instance for chaining
|
|
220
|
+
*/
|
|
221
|
+
disable() {
|
|
222
|
+
chip.element.classList.add(`${chip.getClass('chip')}--disabled`);
|
|
223
|
+
chip.element.setAttribute('aria-disabled', 'true');
|
|
224
|
+
chip.element.setAttribute('tabindex', '-1');
|
|
225
|
+
return this;
|
|
226
|
+
},
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Sets the chip's text content
|
|
230
|
+
* @param {string} content - Text content
|
|
231
|
+
* @returns {Object} The chip instance for chaining
|
|
232
|
+
*/
|
|
233
|
+
setText(content) {
|
|
234
|
+
const textElement = chip.element.querySelector(`.${chip.getClass('chip')}-text`);
|
|
235
|
+
|
|
236
|
+
if (textElement) {
|
|
237
|
+
textElement.textContent = content;
|
|
238
|
+
} else if (content) {
|
|
239
|
+
const newTextElement = document.createElement('span');
|
|
240
|
+
newTextElement.className = `${chip.getClass('chip')}-text`;
|
|
241
|
+
newTextElement.textContent = content;
|
|
242
|
+
contentContainer.appendChild(newTextElement);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return this;
|
|
246
|
+
},
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Gets the chip's text content
|
|
250
|
+
* @returns {string} The chip's text content
|
|
251
|
+
*/
|
|
252
|
+
getText() {
|
|
253
|
+
const textElement = chip.element.querySelector(`.${chip.getClass('chip')}-text`);
|
|
254
|
+
return textElement ? textElement.textContent : '';
|
|
255
|
+
},
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Sets the chip's icon
|
|
259
|
+
* @param {string} icon - Icon HTML content
|
|
260
|
+
* @returns {Object} The chip instance for chaining
|
|
261
|
+
*/
|
|
262
|
+
setIcon(icon) {
|
|
263
|
+
return this.setLeadingIcon(icon);
|
|
264
|
+
},
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Gets the chip's icon
|
|
268
|
+
* @returns {string} The chip's icon HTML
|
|
269
|
+
*/
|
|
270
|
+
getIcon() {
|
|
271
|
+
const iconElement = chip.element.querySelector(`.${chip.getClass('chip')}-leading-icon`);
|
|
272
|
+
return iconElement ? iconElement.innerHTML : '';
|
|
273
|
+
},
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Sets the chip's leading icon
|
|
277
|
+
* @param {string} icon - Icon HTML content
|
|
278
|
+
* @returns {Object} The chip instance for chaining
|
|
279
|
+
*/
|
|
280
|
+
setLeadingIcon(icon) {
|
|
281
|
+
const leadingIconSelector = `.${chip.getClass('chip')}-leading-icon`;
|
|
282
|
+
let leadingIconElement = chip.element.querySelector(leadingIconSelector);
|
|
283
|
+
|
|
284
|
+
if (!leadingIconElement && icon) {
|
|
285
|
+
leadingIconElement = document.createElement('span');
|
|
286
|
+
leadingIconElement.className = `${chip.getClass('chip')}-leading-icon`;
|
|
287
|
+
|
|
288
|
+
// Insert at the beginning of the content container
|
|
289
|
+
contentContainer.insertBefore(leadingIconElement, contentContainer.firstChild);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (leadingIconElement) {
|
|
293
|
+
leadingIconElement.innerHTML = icon || '';
|
|
294
|
+
|
|
295
|
+
// Remove the element if icon is empty
|
|
296
|
+
if (!icon && leadingIconElement.parentNode) {
|
|
297
|
+
leadingIconElement.parentNode.removeChild(leadingIconElement);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return this;
|
|
302
|
+
},
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Sets the chip's trailing icon
|
|
306
|
+
* @param {string} icon - Icon HTML content
|
|
307
|
+
* @param {Function} [onClick] - Click handler for the trailing icon
|
|
308
|
+
* @returns {Object} The chip instance for chaining
|
|
309
|
+
*/
|
|
310
|
+
setTrailingIcon(icon, onClick) {
|
|
311
|
+
const trailingIconSelector = `.${chip.getClass('chip')}-trailing-icon`;
|
|
312
|
+
let trailingIconElement = chip.element.querySelector(trailingIconSelector);
|
|
313
|
+
|
|
314
|
+
if (!trailingIconElement && icon) {
|
|
315
|
+
trailingIconElement = document.createElement('span');
|
|
316
|
+
trailingIconElement.className = `${chip.getClass('chip')}-trailing-icon`;
|
|
317
|
+
|
|
318
|
+
// Add at the end of the content container
|
|
319
|
+
contentContainer.appendChild(trailingIconElement);
|
|
320
|
+
|
|
321
|
+
// Add click handler if provided
|
|
322
|
+
if (onClick) {
|
|
323
|
+
trailingIconElement.addEventListener('click', (e) => {
|
|
324
|
+
e.stopPropagation(); // Prevent chip click event
|
|
325
|
+
onClick(this);
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (trailingIconElement) {
|
|
331
|
+
trailingIconElement.innerHTML = icon || '';
|
|
332
|
+
|
|
333
|
+
// Remove the element if icon is empty
|
|
334
|
+
if (!icon && trailingIconElement.parentNode) {
|
|
335
|
+
trailingIconElement.parentNode.removeChild(trailingIconElement);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return this;
|
|
340
|
+
},
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Destroys the chip component and cleans up resources
|
|
344
|
+
*/
|
|
345
|
+
destroy() {
|
|
346
|
+
chip.lifecycle && chip.lifecycle.destroy && chip.lifecycle.destroy();
|
|
347
|
+
chip.element.remove();
|
|
348
|
+
},
|
|
349
|
+
|
|
350
|
+
// Forward event methods from the original chip
|
|
351
|
+
on: chip.on,
|
|
352
|
+
off: chip.off,
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Add CSS classes to the chip element
|
|
356
|
+
* @param {...string} classes - CSS classes to add
|
|
357
|
+
* @returns {Object} The chip instance for chaining
|
|
358
|
+
*/
|
|
359
|
+
addClass(...classes) {
|
|
360
|
+
chip.element.classList.add(...classes);
|
|
361
|
+
return this;
|
|
362
|
+
}
|
|
363
|
+
};
|
|
65
364
|
|
|
66
|
-
//
|
|
67
|
-
if (config.
|
|
365
|
+
// Add click handler for selection toggle
|
|
366
|
+
if (config.variant === CHIP_VARIANTS.FILTER ||
|
|
367
|
+
config.variant === CHIP_VARIANTS.ASSIST ||
|
|
368
|
+
config.selectable) {
|
|
369
|
+
|
|
68
370
|
chip.element.addEventListener('click', () => {
|
|
69
|
-
if (
|
|
70
|
-
|
|
371
|
+
if (enhancedChip.isDisabled()) return;
|
|
372
|
+
|
|
373
|
+
enhancedChip.toggleSelected();
|
|
374
|
+
|
|
375
|
+
// Call onChange callback if provided
|
|
376
|
+
if (config.onChange) {
|
|
377
|
+
config.onChange(enhancedChip);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// Call onSelect callback if provided
|
|
381
|
+
if (config.onSelect) {
|
|
382
|
+
config.onSelect(enhancedChip);
|
|
71
383
|
}
|
|
72
384
|
});
|
|
73
385
|
}
|
|
74
386
|
|
|
75
|
-
return
|
|
387
|
+
return enhancedChip;
|
|
76
388
|
} catch (error) {
|
|
77
|
-
console.error('Chip creation error:', error
|
|
78
|
-
throw new Error(`Failed to create chip: ${error
|
|
389
|
+
console.error('Chip creation error:', error);
|
|
390
|
+
throw new Error(`Failed to create chip: ${error.message}`);
|
|
79
391
|
}
|
|
80
392
|
};
|
|
81
393
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// src/components/chip/constants.
|
|
1
|
+
// src/components/chip/constants.js
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Available variants for the Chip component
|
|
@@ -25,7 +25,7 @@ export const CHIP_VARIANTS = {
|
|
|
25
25
|
|
|
26
26
|
/** Suggestion chip for presenting options */
|
|
27
27
|
SUGGESTION: 'suggestion'
|
|
28
|
-
}
|
|
28
|
+
};
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Available sizes for the Chip component
|
|
@@ -35,4 +35,4 @@ export const CHIP_SIZES = {
|
|
|
35
35
|
SMALL: 'small',
|
|
36
36
|
MEDIUM: 'medium',
|
|
37
37
|
LARGE: 'large'
|
|
38
|
-
}
|
|
38
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// src/components/chip/index.
|
|
1
|
+
// src/components/chip/index.js
|
|
2
2
|
export { default } from './chip'
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
3
|
+
export { default as createChipSet } from './chip-set'
|
|
4
|
+
export { CHIP_VARIANTS, CHIP_SIZES } from './constants'
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
// src/components/dialog/_styles.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}-dialog';
|
|
9
|
+
|
|
10
|
+
// Dialog overlay - covers the entire screen
|
|
11
|
+
.#{$component}-overlay {
|
|
12
|
+
position: fixed;
|
|
13
|
+
top: 0;
|
|
14
|
+
left: 0;
|
|
15
|
+
right: 0;
|
|
16
|
+
bottom: 0;
|
|
17
|
+
background-color: t.alpha('scrim', 0.32);
|
|
18
|
+
display: flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
justify-content: center;
|
|
21
|
+
z-index: 1000;
|
|
22
|
+
padding: 24px;
|
|
23
|
+
opacity: 0;
|
|
24
|
+
visibility: hidden;
|
|
25
|
+
transition: opacity 0.15s ease, visibility 0s linear 0.15s;
|
|
26
|
+
overflow-y: auto;
|
|
27
|
+
|
|
28
|
+
&--visible {
|
|
29
|
+
opacity: 1;
|
|
30
|
+
visibility: visible;
|
|
31
|
+
transition: opacity 0.15s ease, visibility 0s linear;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Dialog container
|
|
36
|
+
.#{$component} {
|
|
37
|
+
position: relative;
|
|
38
|
+
display: flex;
|
|
39
|
+
flex-direction: column;
|
|
40
|
+
min-width: 280px;
|
|
41
|
+
max-width: 90vw;
|
|
42
|
+
width: fit-content;
|
|
43
|
+
max-height: calc(100vh - 48px);
|
|
44
|
+
border-radius: 28px;
|
|
45
|
+
background-color: t.color('surface-container-high');
|
|
46
|
+
color: t.color('on-surface');
|
|
47
|
+
overflow: hidden;
|
|
48
|
+
box-sizing: border-box;
|
|
49
|
+
@include m.elevation(3);
|
|
50
|
+
transform: scale(0.8);
|
|
51
|
+
opacity: 0;
|
|
52
|
+
transition: transform 0.15s ease, opacity 0.15s ease;
|
|
53
|
+
|
|
54
|
+
&--visible {
|
|
55
|
+
transform: scale(1);
|
|
56
|
+
opacity: 1;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Fullscreen variant
|
|
60
|
+
&--fullscreen {
|
|
61
|
+
width: 100vw;
|
|
62
|
+
height: 100vh;
|
|
63
|
+
max-width: 100vw;
|
|
64
|
+
max-height: 100vh;
|
|
65
|
+
border-radius: 0;
|
|
66
|
+
margin: 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Fullwidth variant
|
|
70
|
+
&--fullwidth {
|
|
71
|
+
width: 100%;
|
|
72
|
+
max-width: 560px;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Dialog header
|
|
76
|
+
&-header {
|
|
77
|
+
display: flex;
|
|
78
|
+
align-items: flex-start;
|
|
79
|
+
padding: 24px 24px 16px;
|
|
80
|
+
|
|
81
|
+
&-content {
|
|
82
|
+
flex: 1;
|
|
83
|
+
min-width: 0;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
&-title {
|
|
87
|
+
@include m.typography('headline-small');
|
|
88
|
+
color: t.color('on-surface');
|
|
89
|
+
margin: 0;
|
|
90
|
+
overflow: hidden;
|
|
91
|
+
text-overflow: ellipsis;
|
|
92
|
+
white-space: nowrap;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
&-subtitle {
|
|
96
|
+
@include m.typography('body-medium');
|
|
97
|
+
color: t.color('on-surface-variant');
|
|
98
|
+
margin: 4px 0 0;
|
|
99
|
+
overflow: hidden;
|
|
100
|
+
text-overflow: ellipsis;
|
|
101
|
+
white-space: nowrap;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
&-close {
|
|
105
|
+
margin: -8px -8px -8px 8px;
|
|
106
|
+
padding: 8px;
|
|
107
|
+
border: none;
|
|
108
|
+
background: transparent;
|
|
109
|
+
cursor: pointer;
|
|
110
|
+
display: flex;
|
|
111
|
+
align-items: center;
|
|
112
|
+
justify-content: center;
|
|
113
|
+
border-radius: 50%;
|
|
114
|
+
color: t.color('on-surface-variant');
|
|
115
|
+
|
|
116
|
+
&:hover {
|
|
117
|
+
background-color: t.alpha('on-surface', 0.08);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
&:active {
|
|
121
|
+
background-color: t.alpha('on-surface', 0.12);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
svg {
|
|
125
|
+
width: 24px;
|
|
126
|
+
height: 24px;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Dialog content
|
|
132
|
+
&-content {
|
|
133
|
+
flex: 1 1 auto;
|
|
134
|
+
padding: 0 24px;
|
|
135
|
+
overflow-y: auto;
|
|
136
|
+
-webkit-overflow-scrolling: touch;
|
|
137
|
+
@include m.typography('body-medium');
|
|
138
|
+
color: t.color('on-surface-variant');
|
|
139
|
+
|
|
140
|
+
&:first-child {
|
|
141
|
+
padding-top: 24px;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
&:last-child {
|
|
145
|
+
padding-bottom: 24px;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Dialog footer
|
|
150
|
+
&-footer {
|
|
151
|
+
display: flex;
|
|
152
|
+
flex-wrap: wrap;
|
|
153
|
+
align-items: center;
|
|
154
|
+
justify-content: flex-end;
|
|
155
|
+
padding: 16px 24px 24px;
|
|
156
|
+
gap: 8px;
|
|
157
|
+
|
|
158
|
+
&--left {
|
|
159
|
+
justify-content: flex-start;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
&--center {
|
|
163
|
+
justify-content: center;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
&--space-between {
|
|
167
|
+
justify-content: space-between;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
button {
|
|
171
|
+
margin: 0;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Size variants
|
|
176
|
+
&--small {
|
|
177
|
+
max-width: 400px;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
&--medium {
|
|
181
|
+
max-width: 560px;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
&--large {
|
|
185
|
+
max-width: 90vw;
|
|
186
|
+
width: 800px;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Animation variants
|
|
190
|
+
&--slide-up {
|
|
191
|
+
transform: translateY(20px) scale(1);
|
|
192
|
+
|
|
193
|
+
&.#{$component}--visible {
|
|
194
|
+
transform: translateY(0) scale(1);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
&--slide-down {
|
|
199
|
+
transform: translateY(-20px) scale(1);
|
|
200
|
+
|
|
201
|
+
&.#{$component}--visible {
|
|
202
|
+
transform: translateY(0) scale(1);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
&--fade {
|
|
207
|
+
transform: scale(1);
|
|
208
|
+
|
|
209
|
+
&.#{$component}--visible {
|
|
210
|
+
transform: scale(1);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|