mtrl 0.1.3 → 0.2.1
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 → _styles.scss} +79 -7
- package/src/components/card/{actions.js → actions.ts} +15 -18
- package/src/components/card/{api.js → api.ts} +33 -33
- package/src/components/card/card.ts +41 -0
- package/src/components/card/config.ts +99 -0
- package/src/components/card/{constants.js → constants.ts} +11 -10
- package/src/components/card/{content.js → content.ts} +15 -18
- package/src/components/card/{features.js → features.ts} +104 -94
- package/src/components/card/{header.js → header.ts} +21 -25
- 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/constants.ts +37 -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/{constants.js → constants.ts} +5 -5
- 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 +255 -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 +251 -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} +3 -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/card/card.js +0 -102
- package/src/components/card/config.js +0 -16
- package/src/components/card/index.js +0 -7
- package/src/components/card/media.js +0 -56
- package/src/components/checkbox/api.js +0 -45
- package/src/components/checkbox/checkbox.js +0 -96
- package/src/components/checkbox/constants.js +0 -88
- 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/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/textfield/{styles.scss → _styles.scss} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// src/components/card/
|
|
1
|
+
// src/components/card/_card.scss
|
|
2
2
|
@use '../../styles/abstract/base' as base;
|
|
3
3
|
@use '../../styles/abstract/variables' as v;
|
|
4
4
|
@use '../../styles/abstract/functions' as f;
|
|
@@ -17,9 +17,8 @@ $component: '#{base.$prefix}-card';
|
|
|
17
17
|
background-color: t.color('surface');
|
|
18
18
|
color: t.color('on-surface');
|
|
19
19
|
overflow: hidden;
|
|
20
|
-
// width
|
|
21
|
-
|
|
22
|
-
--card-elevation: m.elevation(2);
|
|
20
|
+
width: 320px; // Fixed width since v.card() isn't available
|
|
21
|
+
--card-elevation: 1;
|
|
23
22
|
|
|
24
23
|
// Typography
|
|
25
24
|
@include m.typography('body-medium');
|
|
@@ -50,10 +49,10 @@ $component: '#{base.$prefix}-card';
|
|
|
50
49
|
|
|
51
50
|
// Elevated variant
|
|
52
51
|
&--elevated {
|
|
53
|
-
|
|
52
|
+
@include m.elevation(1);
|
|
54
53
|
|
|
55
|
-
&:hover {
|
|
56
|
-
|
|
54
|
+
&:hover.#{$component}--interactive {
|
|
55
|
+
@include m.elevation(2);
|
|
57
56
|
}
|
|
58
57
|
}
|
|
59
58
|
|
|
@@ -284,4 +283,77 @@ $component: '#{base.$prefix}-card';
|
|
|
284
283
|
&--state-loading {
|
|
285
284
|
pointer-events: none;
|
|
286
285
|
}
|
|
286
|
+
|
|
287
|
+
&--dragging {
|
|
288
|
+
@include m.elevation(4);
|
|
289
|
+
opacity: 0.9;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Loading overlay
|
|
293
|
+
&-loading-overlay {
|
|
294
|
+
position: absolute;
|
|
295
|
+
top: 0;
|
|
296
|
+
left: 0;
|
|
297
|
+
width: 100%;
|
|
298
|
+
height: 100%;
|
|
299
|
+
display: flex;
|
|
300
|
+
align-items: center;
|
|
301
|
+
justify-content: center;
|
|
302
|
+
background-color: rgba(t.color('surface'), 0.7);
|
|
303
|
+
z-index: 1;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
&-loading-spinner {
|
|
307
|
+
width: 40px;
|
|
308
|
+
height: 40px;
|
|
309
|
+
border-radius: 50%;
|
|
310
|
+
border: 3px solid rgba(t.color('primary'), 0.2);
|
|
311
|
+
border-top-color: t.color('primary');
|
|
312
|
+
animation: card-spinner 1s infinite linear;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Expandable content
|
|
316
|
+
&-expandable-content {
|
|
317
|
+
overflow: hidden;
|
|
318
|
+
transition: max-height 0.3s ease;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
&-expand-button {
|
|
322
|
+
background: none;
|
|
323
|
+
border: none;
|
|
324
|
+
padding: 8px;
|
|
325
|
+
cursor: pointer;
|
|
326
|
+
color: t.color('primary');
|
|
327
|
+
|
|
328
|
+
&::before {
|
|
329
|
+
content: '';
|
|
330
|
+
display: inline-block;
|
|
331
|
+
width: 10px;
|
|
332
|
+
height: 10px;
|
|
333
|
+
border-right: 2px solid currentColor;
|
|
334
|
+
border-bottom: 2px solid currentColor;
|
|
335
|
+
transform: rotate(45deg);
|
|
336
|
+
transition: transform 0.3s ease;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
&[aria-expanded="true"]::before {
|
|
340
|
+
transform: rotate(-135deg);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Swipeable card
|
|
345
|
+
&--swipeable {
|
|
346
|
+
touch-action: pan-y;
|
|
347
|
+
transition: transform 0.3s ease;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Spinner animation
|
|
352
|
+
@keyframes card-spinner {
|
|
353
|
+
0% {
|
|
354
|
+
transform: rotate(0deg);
|
|
355
|
+
}
|
|
356
|
+
100% {
|
|
357
|
+
transform: rotate(360deg);
|
|
358
|
+
}
|
|
287
359
|
}
|
|
@@ -1,23 +1,20 @@
|
|
|
1
|
-
// src/components/card/actions.
|
|
2
|
-
import { PREFIX } from '../../core/config'
|
|
3
|
-
import { pipe } from '../../core/compose'
|
|
4
|
-
import { createBase, withElement } from '../../core/compose/component'
|
|
1
|
+
// src/components/card/actions.ts
|
|
2
|
+
import { PREFIX } from '../../core/config';
|
|
3
|
+
import { pipe } from '../../core/compose';
|
|
4
|
+
import { createBase, withElement } from '../../core/compose/component';
|
|
5
|
+
import { CardActionsConfig } from './types';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Creates a card actions component
|
|
8
|
-
* @param {
|
|
9
|
-
* @param {Array<HTMLElement>} [config.actions] - Action elements to include
|
|
10
|
-
* @param {boolean} [config.fullBleed=false] - Whether actions extend full width
|
|
11
|
-
* @param {boolean} [config.vertical=false] - Whether to stack actions vertically
|
|
12
|
-
* @param {string} [config.align='start'] - Horizontal alignment ('start', 'center', 'end', 'space-between')
|
|
9
|
+
* @param {CardActionsConfig} config - Actions configuration
|
|
13
10
|
* @returns {HTMLElement} Card actions element
|
|
14
11
|
*/
|
|
15
|
-
export const createCardActions = (config = {}) => {
|
|
12
|
+
export const createCardActions = (config: CardActionsConfig = {}): HTMLElement => {
|
|
16
13
|
const baseConfig = {
|
|
17
14
|
...config,
|
|
18
15
|
componentName: 'card-actions',
|
|
19
16
|
prefix: PREFIX
|
|
20
|
-
}
|
|
17
|
+
};
|
|
21
18
|
|
|
22
19
|
try {
|
|
23
20
|
const actions = pipe(
|
|
@@ -32,20 +29,20 @@ export const createCardActions = (config = {}) => {
|
|
|
32
29
|
config.align ? `${PREFIX}-card-actions--${config.align}` : null
|
|
33
30
|
]
|
|
34
31
|
})
|
|
35
|
-
)(baseConfig)
|
|
32
|
+
)(baseConfig);
|
|
36
33
|
|
|
37
34
|
// Add action elements if provided
|
|
38
35
|
if (Array.isArray(config.actions)) {
|
|
39
36
|
config.actions.forEach(action => {
|
|
40
37
|
if (action instanceof HTMLElement) {
|
|
41
|
-
actions.element.appendChild(action)
|
|
38
|
+
actions.element.appendChild(action);
|
|
42
39
|
}
|
|
43
|
-
})
|
|
40
|
+
});
|
|
44
41
|
}
|
|
45
42
|
|
|
46
|
-
return actions.element
|
|
43
|
+
return actions.element;
|
|
47
44
|
} catch (error) {
|
|
48
|
-
console.error('Card actions creation error:', error)
|
|
49
|
-
throw new Error(`Failed to create card actions: ${error.message}`)
|
|
45
|
+
console.error('Card actions creation error:', error instanceof Error ? error.message : String(error));
|
|
46
|
+
throw new Error(`Failed to create card actions: ${error instanceof Error ? error.message : String(error)}`);
|
|
50
47
|
}
|
|
51
|
-
}
|
|
48
|
+
};
|
|
@@ -1,102 +1,102 @@
|
|
|
1
|
-
// src/components/card/api.
|
|
1
|
+
// src/components/card/api.ts
|
|
2
|
+
import { BaseComponent, CardComponent, ApiOptions } from './types';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Enhances a card component with API methods
|
|
5
|
-
* @param {
|
|
6
|
-
* @param {Object} options.lifecycle - Object containing lifecycle methods
|
|
6
|
+
* @param {ApiOptions} options - API configuration options
|
|
7
7
|
* @returns {Function} Higher-order function that adds API methods to component
|
|
8
8
|
* @internal This is an internal utility for the Card component
|
|
9
9
|
*/
|
|
10
|
-
export const withAPI = ({ lifecycle }) => (component) => ({
|
|
10
|
+
export const withAPI = ({ lifecycle }: ApiOptions) => (component: BaseComponent): CardComponent => ({
|
|
11
11
|
...component,
|
|
12
12
|
element: component.element,
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Adds content to the card
|
|
16
16
|
* @param {HTMLElement} contentElement - The content element to add
|
|
17
|
-
* @returns {
|
|
17
|
+
* @returns {CardComponent} The card instance for chaining
|
|
18
18
|
*/
|
|
19
|
-
addContent
|
|
19
|
+
addContent(contentElement: HTMLElement): CardComponent {
|
|
20
20
|
if (contentElement && contentElement.classList.contains(`${component.getClass('card')}-content`)) {
|
|
21
|
-
component.element.appendChild(contentElement)
|
|
21
|
+
component.element.appendChild(contentElement);
|
|
22
22
|
}
|
|
23
|
-
return this
|
|
23
|
+
return this;
|
|
24
24
|
},
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* Sets the card header
|
|
28
28
|
* @param {HTMLElement} headerElement - The header element to add
|
|
29
|
-
* @returns {
|
|
29
|
+
* @returns {CardComponent} The card instance for chaining
|
|
30
30
|
*/
|
|
31
|
-
setHeader
|
|
31
|
+
setHeader(headerElement: HTMLElement): CardComponent {
|
|
32
32
|
if (headerElement && headerElement.classList.contains(`${component.getClass('card')}-header`)) {
|
|
33
33
|
// Remove existing header if present
|
|
34
|
-
const existingHeader = component.element.querySelector(`.${component.getClass('card')}-header`)
|
|
34
|
+
const existingHeader = component.element.querySelector(`.${component.getClass('card')}-header`);
|
|
35
35
|
if (existingHeader) {
|
|
36
|
-
existingHeader.remove()
|
|
36
|
+
existingHeader.remove();
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
// Insert at the beginning of the card
|
|
40
|
-
component.element.insertBefore(headerElement, component.element.firstChild)
|
|
40
|
+
component.element.insertBefore(headerElement, component.element.firstChild);
|
|
41
41
|
}
|
|
42
|
-
return this
|
|
42
|
+
return this;
|
|
43
43
|
},
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
46
|
* Adds media to the card
|
|
47
47
|
* @param {HTMLElement} mediaElement - The media element to add
|
|
48
48
|
* @param {string} [position='top'] - Position to place media ('top', 'bottom')
|
|
49
|
-
* @returns {
|
|
49
|
+
* @returns {CardComponent} The card instance for chaining
|
|
50
50
|
*/
|
|
51
|
-
addMedia
|
|
51
|
+
addMedia(mediaElement: HTMLElement, position: 'top' | 'bottom' = 'top'): CardComponent {
|
|
52
52
|
if (mediaElement && mediaElement.classList.contains(`${component.getClass('card')}-media`)) {
|
|
53
53
|
if (position === 'top') {
|
|
54
|
-
component.element.insertBefore(mediaElement, component.element.firstChild)
|
|
54
|
+
component.element.insertBefore(mediaElement, component.element.firstChild);
|
|
55
55
|
} else {
|
|
56
|
-
component.element.appendChild(mediaElement)
|
|
56
|
+
component.element.appendChild(mediaElement);
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
|
-
return this
|
|
59
|
+
return this;
|
|
60
60
|
},
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
63
|
* Sets the card actions section
|
|
64
64
|
* @param {HTMLElement} actionsElement - The actions element to add
|
|
65
|
-
* @returns {
|
|
65
|
+
* @returns {CardComponent} The card instance for chaining
|
|
66
66
|
*/
|
|
67
|
-
setActions
|
|
67
|
+
setActions(actionsElement: HTMLElement): CardComponent {
|
|
68
68
|
if (actionsElement && actionsElement.classList.contains(`${component.getClass('card')}-actions`)) {
|
|
69
69
|
// Remove existing actions if present
|
|
70
|
-
const existingActions = component.element.querySelector(`.${component.getClass('card')}-actions`)
|
|
70
|
+
const existingActions = component.element.querySelector(`.${component.getClass('card')}-actions`);
|
|
71
71
|
if (existingActions) {
|
|
72
|
-
existingActions.remove()
|
|
72
|
+
existingActions.remove();
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
// Add actions at the end
|
|
76
|
-
component.element.appendChild(actionsElement)
|
|
76
|
+
component.element.appendChild(actionsElement);
|
|
77
77
|
}
|
|
78
|
-
return this
|
|
78
|
+
return this;
|
|
79
79
|
},
|
|
80
80
|
|
|
81
81
|
/**
|
|
82
82
|
* Makes the card draggable
|
|
83
83
|
* @param {Function} [dragStartCallback] - Callback for drag start event
|
|
84
|
-
* @returns {
|
|
84
|
+
* @returns {CardComponent} The card instance for chaining
|
|
85
85
|
*/
|
|
86
|
-
makeDraggable (
|
|
87
|
-
component.element.setAttribute('draggable', 'true')
|
|
86
|
+
makeDraggable(dragStartCallback?: (event: DragEvent) => void): CardComponent {
|
|
87
|
+
component.element.setAttribute('draggable', 'true');
|
|
88
88
|
|
|
89
89
|
if (typeof dragStartCallback === 'function') {
|
|
90
|
-
component.element.addEventListener('dragstart', dragStartCallback)
|
|
90
|
+
component.element.addEventListener('dragstart', dragStartCallback as EventListener);
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
return this
|
|
93
|
+
return this;
|
|
94
94
|
},
|
|
95
95
|
|
|
96
96
|
/**
|
|
97
97
|
* Destroys the card component and removes event listeners
|
|
98
98
|
*/
|
|
99
|
-
destroy
|
|
100
|
-
lifecycle.destroy()
|
|
99
|
+
destroy(): void {
|
|
100
|
+
lifecycle.destroy();
|
|
101
101
|
}
|
|
102
|
-
})
|
|
102
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// src/components/card/card.ts
|
|
2
|
+
import { pipe } from '../../core/compose';
|
|
3
|
+
import { createBase, withElement } from '../../core/compose/component';
|
|
4
|
+
import {
|
|
5
|
+
withEvents,
|
|
6
|
+
withVariant,
|
|
7
|
+
withRipple,
|
|
8
|
+
withLifecycle
|
|
9
|
+
} from '../../core/compose/features';
|
|
10
|
+
import { withAPI } from './api';
|
|
11
|
+
import { CardComponent, BaseComponent, CardSchema } from './types';
|
|
12
|
+
import { createBaseConfig, getElementConfig, getApiConfig, withInteractiveBehavior } from './config';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Creates a new Card component following Material Design 3 principles
|
|
16
|
+
* @param {CardSchema} config - Card configuration object
|
|
17
|
+
* @returns {CardComponent} Card component instance
|
|
18
|
+
*/
|
|
19
|
+
const createCard = (config: CardSchema = {}): CardComponent => {
|
|
20
|
+
const baseConfig = createBaseConfig(config);
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const card = pipe(
|
|
24
|
+
createBase,
|
|
25
|
+
withEvents(),
|
|
26
|
+
withElement(getElementConfig(baseConfig)),
|
|
27
|
+
withVariant(baseConfig),
|
|
28
|
+
config.clickable ? withRipple(baseConfig) : (c: BaseComponent) => c,
|
|
29
|
+
withLifecycle(),
|
|
30
|
+
withInteractiveBehavior,
|
|
31
|
+
comp => withAPI(getApiConfig(comp))(comp)
|
|
32
|
+
)(baseConfig);
|
|
33
|
+
|
|
34
|
+
return card as CardComponent;
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.error('Card creation error:', error instanceof Error ? error.message : String(error));
|
|
37
|
+
throw new Error(`Failed to create card: ${error instanceof Error ? error.message : String(error)}`);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export default createCard;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// src/components/card/config.ts
|
|
2
|
+
import {
|
|
3
|
+
createComponentConfig,
|
|
4
|
+
createElementConfig,
|
|
5
|
+
BaseComponentConfig
|
|
6
|
+
} from '../../core/config/component-config';
|
|
7
|
+
import { BaseComponent, CardSchema } from './types';
|
|
8
|
+
import { CARD_VARIANTS, CARD_ELEVATIONS } from './constants';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Default configuration for the Card component
|
|
12
|
+
*/
|
|
13
|
+
export const defaultConfig: CardSchema = {
|
|
14
|
+
variant: CARD_VARIANTS.ELEVATED,
|
|
15
|
+
interactive: false,
|
|
16
|
+
fullWidth: false,
|
|
17
|
+
clickable: false,
|
|
18
|
+
draggable: false
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Creates the base configuration for Card component
|
|
23
|
+
* @param {CardSchema} config - User provided configuration
|
|
24
|
+
* @returns {CardSchema} Complete configuration with defaults applied
|
|
25
|
+
*/
|
|
26
|
+
export const createBaseConfig = (config: CardSchema = {}): CardSchema =>
|
|
27
|
+
createComponentConfig(defaultConfig, config, 'card') as CardSchema;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Generates element configuration for the Card component
|
|
31
|
+
* @param {CardSchema} config - Card configuration
|
|
32
|
+
* @returns {Object} Element configuration object for withElement
|
|
33
|
+
*/
|
|
34
|
+
export const getElementConfig = (config: CardSchema) =>
|
|
35
|
+
createElementConfig(config, {
|
|
36
|
+
tag: 'div',
|
|
37
|
+
className: [
|
|
38
|
+
config.class,
|
|
39
|
+
config.fullWidth ? `${config.prefix}-card--full-width` : null,
|
|
40
|
+
config.interactive ? `${config.prefix}-card--interactive` : null
|
|
41
|
+
],
|
|
42
|
+
forwardEvents: {
|
|
43
|
+
click: (component: BaseComponent) => !!config.clickable,
|
|
44
|
+
mouseenter: (component: BaseComponent) => !!config.interactive,
|
|
45
|
+
mouseleave: (component: BaseComponent) => !!config.interactive
|
|
46
|
+
},
|
|
47
|
+
interactive: config.interactive || config.clickable
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Creates API configuration for the Card component
|
|
52
|
+
* @param {Object} comp - Component with lifecycle feature
|
|
53
|
+
* @returns {Object} API configuration object
|
|
54
|
+
*/
|
|
55
|
+
export const getApiConfig = (comp) => ({
|
|
56
|
+
lifecycle: {
|
|
57
|
+
destroy: () => comp.lifecycle?.destroy?.()
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Adds interactive behavior to card component
|
|
63
|
+
* @param {BaseComponent} comp - Card component
|
|
64
|
+
* @returns {BaseComponent} Enhanced card component
|
|
65
|
+
*/
|
|
66
|
+
export const withInteractiveBehavior = (comp: BaseComponent): BaseComponent => {
|
|
67
|
+
// Implement hover state elevation changes for interactive cards
|
|
68
|
+
if (comp.config.interactive) {
|
|
69
|
+
comp.element.addEventListener('mouseenter', () => {
|
|
70
|
+
if (comp.config.variant === CARD_VARIANTS.ELEVATED) {
|
|
71
|
+
comp.element.style.setProperty('--card-elevation', String(CARD_ELEVATIONS.HOVERED));
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
comp.element.addEventListener('mouseleave', () => {
|
|
76
|
+
if (comp.config.variant === CARD_VARIANTS.ELEVATED) {
|
|
77
|
+
comp.element.style.setProperty('--card-elevation', String(CARD_ELEVATIONS.RESTING));
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Set up draggable
|
|
83
|
+
if (comp.config.draggable) {
|
|
84
|
+
comp.element.setAttribute('draggable', 'true');
|
|
85
|
+
comp.element.addEventListener('dragstart', (e) => {
|
|
86
|
+
comp.element.style.setProperty('--card-elevation', String(CARD_ELEVATIONS.DRAGGED));
|
|
87
|
+
comp.emit?.('dragstart', { event: e });
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
comp.element.addEventListener('dragend', (e) => {
|
|
91
|
+
comp.element.style.setProperty('--card-elevation', String(CARD_ELEVATIONS.RESTING));
|
|
92
|
+
comp.emit?.('dragend', { event: e });
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return comp;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export default defaultConfig;
|
|
@@ -1,24 +1,25 @@
|
|
|
1
|
-
// src/components/card/constants.
|
|
1
|
+
// src/components/card/constants.ts
|
|
2
|
+
import { CardVariant, CardElevation } from './types';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Card variant types following Material Design 3
|
|
5
6
|
* @enum {string}
|
|
6
7
|
*/
|
|
7
8
|
export const CARD_VARIANTS = {
|
|
8
|
-
ELEVATED:
|
|
9
|
-
FILLED:
|
|
10
|
-
OUTLINED:
|
|
11
|
-
}
|
|
9
|
+
ELEVATED: CardVariant.ELEVATED,
|
|
10
|
+
FILLED: CardVariant.FILLED,
|
|
11
|
+
OUTLINED: CardVariant.OUTLINED
|
|
12
|
+
};
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Card elevation levels
|
|
15
16
|
* @enum {number}
|
|
16
17
|
*/
|
|
17
18
|
export const CARD_ELEVATIONS = {
|
|
18
|
-
RESTING:
|
|
19
|
-
HOVERED:
|
|
20
|
-
DRAGGED:
|
|
21
|
-
}
|
|
19
|
+
RESTING: CardElevation.RESTING,
|
|
20
|
+
HOVERED: CardElevation.HOVERED,
|
|
21
|
+
DRAGGED: CardElevation.DRAGGED
|
|
22
|
+
};
|
|
22
23
|
|
|
23
24
|
/**
|
|
24
25
|
* Validation schema for card configuration
|
|
@@ -65,4 +66,4 @@ export const CARD_SCHEMA = {
|
|
|
65
66
|
type: 'object',
|
|
66
67
|
required: false
|
|
67
68
|
}
|
|
68
|
-
}
|
|
69
|
+
};
|
|
@@ -1,23 +1,20 @@
|
|
|
1
|
-
// src/components/card/content.
|
|
2
|
-
import { PREFIX } from '../../core/config'
|
|
3
|
-
import { pipe } from '../../core/compose'
|
|
4
|
-
import { createBase, withElement } from '../../core/compose/component'
|
|
1
|
+
// src/components/card/content.ts
|
|
2
|
+
import { PREFIX } from '../../core/config';
|
|
3
|
+
import { pipe } from '../../core/compose';
|
|
4
|
+
import { createBase, withElement } from '../../core/compose/component';
|
|
5
|
+
import { CardContentConfig } from './types';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Creates a card content component
|
|
8
|
-
* @param {
|
|
9
|
-
* @param {string} [config.text] - Text content
|
|
10
|
-
* @param {string} [config.html] - HTML content
|
|
11
|
-
* @param {Array<HTMLElement>} [config.children] - Child elements to append
|
|
12
|
-
* @param {boolean} [config.padding=true] - Whether to apply default padding
|
|
9
|
+
* @param {CardContentConfig} config - Content configuration
|
|
13
10
|
* @returns {HTMLElement} Card content element
|
|
14
11
|
*/
|
|
15
|
-
export const createCardContent = (config = {}) => {
|
|
12
|
+
export const createCardContent = (config: CardContentConfig = {}): HTMLElement => {
|
|
16
13
|
const baseConfig = {
|
|
17
14
|
...config,
|
|
18
15
|
componentName: 'card-content',
|
|
19
16
|
prefix: PREFIX
|
|
20
|
-
}
|
|
17
|
+
};
|
|
21
18
|
|
|
22
19
|
try {
|
|
23
20
|
const content = pipe(
|
|
@@ -32,20 +29,20 @@ export const createCardContent = (config = {}) => {
|
|
|
32
29
|
html: config.html,
|
|
33
30
|
text: config.text
|
|
34
31
|
})
|
|
35
|
-
)(baseConfig)
|
|
32
|
+
)(baseConfig);
|
|
36
33
|
|
|
37
34
|
// Add children if provided
|
|
38
35
|
if (Array.isArray(config.children)) {
|
|
39
36
|
config.children.forEach(child => {
|
|
40
37
|
if (child instanceof HTMLElement) {
|
|
41
|
-
content.element.appendChild(child)
|
|
38
|
+
content.element.appendChild(child);
|
|
42
39
|
}
|
|
43
|
-
})
|
|
40
|
+
});
|
|
44
41
|
}
|
|
45
42
|
|
|
46
|
-
return content.element
|
|
43
|
+
return content.element;
|
|
47
44
|
} catch (error) {
|
|
48
|
-
console.error('Card content creation error:', error)
|
|
49
|
-
throw new Error(`Failed to create card content: ${error.message}`)
|
|
45
|
+
console.error('Card content creation error:', error instanceof Error ? error.message : String(error));
|
|
46
|
+
throw new Error(`Failed to create card content: ${error instanceof Error ? error.message : String(error)}`);
|
|
50
47
|
}
|
|
51
|
-
}
|
|
48
|
+
};
|