mtrl 0.1.3 → 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 → _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/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} +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/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
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
// src/components/chip/_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}-chip';
|
|
9
|
+
|
|
10
|
+
.#{$component} {
|
|
11
|
+
// Base styles
|
|
12
|
+
position: relative;
|
|
13
|
+
display: inline-flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
justify-content: center;
|
|
16
|
+
height: 32px;
|
|
17
|
+
padding: 0 12px;
|
|
18
|
+
border: none;
|
|
19
|
+
border-radius: 8px;
|
|
20
|
+
background-color: transparent;
|
|
21
|
+
color: inherit;
|
|
22
|
+
font: inherit;
|
|
23
|
+
text-decoration: none;
|
|
24
|
+
cursor: pointer;
|
|
25
|
+
user-select: none;
|
|
26
|
+
vertical-align: middle;
|
|
27
|
+
appearance: none;
|
|
28
|
+
overflow: hidden;
|
|
29
|
+
transition: background-color 0.15s ease, box-shadow 0.15s ease, color 0.15s ease,
|
|
30
|
+
border-color 0.15s ease, opacity 0.15s ease;
|
|
31
|
+
|
|
32
|
+
// Typography
|
|
33
|
+
@include m.typography('label-large');
|
|
34
|
+
|
|
35
|
+
// Focus styles
|
|
36
|
+
&:focus {
|
|
37
|
+
outline: none;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
&:focus-visible {
|
|
41
|
+
outline: 2px solid t.color('outline');
|
|
42
|
+
outline-offset: 2px;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Disabled state
|
|
46
|
+
&[aria-disabled="true"] {
|
|
47
|
+
pointer-events: none;
|
|
48
|
+
opacity: 0.38;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Leading icon styles
|
|
52
|
+
&-icon {
|
|
53
|
+
display: inline-flex;
|
|
54
|
+
align-items: center;
|
|
55
|
+
justify-content: center;
|
|
56
|
+
width: 18px;
|
|
57
|
+
height: 18px;
|
|
58
|
+
margin-right: 8px;
|
|
59
|
+
|
|
60
|
+
svg {
|
|
61
|
+
width: 18px;
|
|
62
|
+
height: 18px;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Trailing icon styles
|
|
67
|
+
&-trailing-icon {
|
|
68
|
+
display: inline-flex;
|
|
69
|
+
align-items: center;
|
|
70
|
+
justify-content: center;
|
|
71
|
+
width: 18px;
|
|
72
|
+
height: 18px;
|
|
73
|
+
margin-left: 8px;
|
|
74
|
+
|
|
75
|
+
svg {
|
|
76
|
+
width: 18px;
|
|
77
|
+
height: 18px;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
&:hover {
|
|
81
|
+
opacity: 0.8;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Text content
|
|
86
|
+
&-text {
|
|
87
|
+
// Text truncation for long chip labels
|
|
88
|
+
@include m.truncate;
|
|
89
|
+
max-width: 150px;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Ripple container
|
|
93
|
+
.ripple {
|
|
94
|
+
position: absolute;
|
|
95
|
+
border-radius: 50%;
|
|
96
|
+
transform: scale(0);
|
|
97
|
+
pointer-events: none;
|
|
98
|
+
background-color: currentColor;
|
|
99
|
+
opacity: 0.12;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// === VARIANTS ===
|
|
103
|
+
|
|
104
|
+
// Filled chip (default)
|
|
105
|
+
&--filled {
|
|
106
|
+
background-color: t.color('surface-container-highest');
|
|
107
|
+
color: t.color('on-surface');
|
|
108
|
+
|
|
109
|
+
&:hover {
|
|
110
|
+
@include m.state-layer(t.color('on-surface'), 'hover');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
&:active {
|
|
114
|
+
@include m.state-layer(t.color('on-surface'), 'pressed');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
&.#{$component}--selected {
|
|
118
|
+
background-color: t.color('secondary-container');
|
|
119
|
+
color: t.color('on-secondary-container');
|
|
120
|
+
|
|
121
|
+
&:hover {
|
|
122
|
+
@include m.state-layer(t.color('on-secondary-container'), 'hover');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
&:active {
|
|
126
|
+
@include m.state-layer(t.color('on-secondary-container'), 'pressed');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Outlined chip
|
|
132
|
+
&--outlined {
|
|
133
|
+
border: 1px solid t.color('outline');
|
|
134
|
+
color: t.color('on-surface');
|
|
135
|
+
|
|
136
|
+
&:hover {
|
|
137
|
+
@include m.state-layer(t.color('on-surface'), 'hover');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
&:active {
|
|
141
|
+
@include m.state-layer(t.color('on-surface'), 'pressed');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
&.#{$component}--selected {
|
|
145
|
+
border-color: t.color('secondary');
|
|
146
|
+
background-color: t.color('secondary-container');
|
|
147
|
+
color: t.color('on-secondary-container');
|
|
148
|
+
|
|
149
|
+
&:hover {
|
|
150
|
+
@include m.state-layer(t.color('on-secondary-container'), 'hover');
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
&:active {
|
|
154
|
+
@include m.state-layer(t.color('on-secondary-container'), 'pressed');
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Elevated chip
|
|
160
|
+
&--elevated {
|
|
161
|
+
background-color: t.color('surface-container-low');
|
|
162
|
+
color: t.color('on-surface');
|
|
163
|
+
@include m.elevation(1);
|
|
164
|
+
|
|
165
|
+
&:hover {
|
|
166
|
+
@include m.state-layer(t.color('on-surface'), 'hover');
|
|
167
|
+
@include m.elevation(2);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
&:active {
|
|
171
|
+
@include m.state-layer(t.color('on-surface'), 'pressed');
|
|
172
|
+
@include m.elevation(1);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
&.#{$component}--selected {
|
|
176
|
+
background-color: t.color('secondary-container');
|
|
177
|
+
color: t.color('on-secondary-container');
|
|
178
|
+
|
|
179
|
+
&:hover {
|
|
180
|
+
@include m.state-layer(t.color('on-secondary-container'), 'hover');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
&:active {
|
|
184
|
+
@include m.state-layer(t.color('on-secondary-container'), 'pressed');
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
&[aria-disabled="true"] {
|
|
189
|
+
@include m.elevation(0);
|
|
190
|
+
box-shadow: none;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Assist chip
|
|
195
|
+
&--assist {
|
|
196
|
+
background-color: t.color('surface-container');
|
|
197
|
+
color: t.color('on-surface');
|
|
198
|
+
|
|
199
|
+
&:hover {
|
|
200
|
+
@include m.state-layer(t.color('on-surface'), 'hover');
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
&:active {
|
|
204
|
+
@include m.state-layer(t.color('on-surface'), 'pressed');
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.#{$component}-icon {
|
|
208
|
+
color: t.color('primary');
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Filter chip
|
|
213
|
+
&--filter {
|
|
214
|
+
background-color: t.color('surface-container-highest');
|
|
215
|
+
color: t.color('on-surface');
|
|
216
|
+
|
|
217
|
+
&:hover {
|
|
218
|
+
@include m.state-layer(t.color('on-surface'), 'hover');
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
&:active {
|
|
222
|
+
@include m.state-layer(t.color('on-surface'), 'pressed');
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
&.#{$component}--selected {
|
|
226
|
+
background-color: t.color('secondary-container');
|
|
227
|
+
color: t.color('on-secondary-container');
|
|
228
|
+
|
|
229
|
+
&:hover {
|
|
230
|
+
@include m.state-layer(t.color('on-secondary-container'), 'hover');
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
&:active {
|
|
234
|
+
@include m.state-layer(t.color('on-secondary-container'), 'pressed');
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Checkmark icon for selected filter chips
|
|
238
|
+
.#{$component}-icon {
|
|
239
|
+
color: t.color('on-secondary-container');
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Input chip
|
|
245
|
+
&--input {
|
|
246
|
+
background-color: t.color('surface-container-highest');
|
|
247
|
+
color: t.color('on-surface');
|
|
248
|
+
padding-right: 8px; // Less padding on the right to accommodate the trailing icon
|
|
249
|
+
|
|
250
|
+
&:hover {
|
|
251
|
+
@include m.state-layer(t.color('on-surface'), 'hover');
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.#{$component}-trailing-icon {
|
|
255
|
+
color: t.color('on-surface-variant');
|
|
256
|
+
|
|
257
|
+
&:hover {
|
|
258
|
+
color: t.color('on-surface');
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Suggestion chip
|
|
264
|
+
&--suggestion {
|
|
265
|
+
background-color: t.color('surface-container');
|
|
266
|
+
color: t.color('on-surface');
|
|
267
|
+
|
|
268
|
+
&:hover {
|
|
269
|
+
@include m.state-layer(t.color('on-surface'), 'hover');
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
&:active {
|
|
273
|
+
@include m.state-layer(t.color('on-surface'), 'pressed');
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// === SIZES ===
|
|
278
|
+
|
|
279
|
+
&--small {
|
|
280
|
+
height: 24px;
|
|
281
|
+
padding: 0 8px;
|
|
282
|
+
font-size: 12px;
|
|
283
|
+
|
|
284
|
+
.#{$component}-icon,
|
|
285
|
+
.#{$component}-trailing-icon {
|
|
286
|
+
width: 16px;
|
|
287
|
+
height: 16px;
|
|
288
|
+
|
|
289
|
+
svg {
|
|
290
|
+
width: 16px;
|
|
291
|
+
height: 16px;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.#{$component}-icon {
|
|
296
|
+
margin-right: 4px;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.#{$component}-trailing-icon {
|
|
300
|
+
margin-left: 4px;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
&--large {
|
|
305
|
+
height: 40px;
|
|
306
|
+
padding: 0 16px;
|
|
307
|
+
font-size: 15px;
|
|
308
|
+
border-radius: 12px;
|
|
309
|
+
|
|
310
|
+
.#{$component}-icon,
|
|
311
|
+
.#{$component}-trailing-icon {
|
|
312
|
+
width: 20px;
|
|
313
|
+
height: 20px;
|
|
314
|
+
|
|
315
|
+
svg {
|
|
316
|
+
width: 20px;
|
|
317
|
+
height: 20px;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.#{$component}-icon {
|
|
322
|
+
margin-right: 10px;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.#{$component}-trailing-icon {
|
|
326
|
+
margin-left: 10px;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// === SPECIAL CASES ===
|
|
331
|
+
|
|
332
|
+
// For chips with only icons (no text)
|
|
333
|
+
&--icon-only {
|
|
334
|
+
padding: 0;
|
|
335
|
+
width: 32px;
|
|
336
|
+
|
|
337
|
+
&.#{$component}--small {
|
|
338
|
+
width: 24px;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
&.#{$component}--large {
|
|
342
|
+
width: 40px;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
.#{$component}-icon {
|
|
346
|
+
margin-right: 0;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// === CHIP SET STYLES ===
|
|
352
|
+
|
|
353
|
+
.#{$component}-set {
|
|
354
|
+
display: flex;
|
|
355
|
+
flex-wrap: wrap;
|
|
356
|
+
gap: 8px;
|
|
357
|
+
|
|
358
|
+
&--scrollable {
|
|
359
|
+
flex-wrap: nowrap;
|
|
360
|
+
overflow-x: auto;
|
|
361
|
+
scrollbar-width: none; // Firefox
|
|
362
|
+
|
|
363
|
+
&::-webkit-scrollbar {
|
|
364
|
+
display: none; // Chrome, Safari, Edge
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
&--vertical {
|
|
369
|
+
flex-direction: column;
|
|
370
|
+
align-items: flex-start;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// src/components/chip/api.js
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Enhances a chip component with API methods
|
|
5
|
+
* @param {Object} options - API configuration options
|
|
6
|
+
* @param {Object} options.disabled - Object containing enable/disable methods
|
|
7
|
+
* @param {Object} options.lifecycle - Object containing lifecycle methods
|
|
8
|
+
* @returns {Function} Higher-order function that adds API methods to component
|
|
9
|
+
* @internal This is an internal utility for the Chip component
|
|
10
|
+
*/
|
|
11
|
+
export const withAPI = ({ disabled, lifecycle }) => (component) => ({
|
|
12
|
+
...component,
|
|
13
|
+
element: component.element,
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Gets the chip's value
|
|
17
|
+
* @returns {string} The chip's value attribute
|
|
18
|
+
*/
|
|
19
|
+
getValue: () => component.element.getAttribute('data-value'),
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Sets the chip's value
|
|
23
|
+
* @param {string} value - Value to set
|
|
24
|
+
* @returns {Object} The chip instance for chaining
|
|
25
|
+
*/
|
|
26
|
+
setValue (value) {
|
|
27
|
+
component.element.setAttribute('data-value', value)
|
|
28
|
+
return this
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Enables the chip
|
|
33
|
+
* @returns {Object} The chip instance for chaining
|
|
34
|
+
*/
|
|
35
|
+
enable () {
|
|
36
|
+
disabled.enable()
|
|
37
|
+
component.element.setAttribute('aria-disabled', 'false')
|
|
38
|
+
return this
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Disables the chip
|
|
43
|
+
* @returns {Object} The chip instance for chaining
|
|
44
|
+
*/
|
|
45
|
+
disable () {
|
|
46
|
+
disabled.disable()
|
|
47
|
+
component.element.setAttribute('aria-disabled', 'true')
|
|
48
|
+
return this
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Sets the chip's text content
|
|
53
|
+
* @param {string} content - Text content
|
|
54
|
+
* @returns {Object} The chip instance for chaining
|
|
55
|
+
*/
|
|
56
|
+
setText (content) {
|
|
57
|
+
component.text.setText(content)
|
|
58
|
+
return this
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Gets the chip's text content
|
|
63
|
+
* @returns {string} The chip's text content
|
|
64
|
+
*/
|
|
65
|
+
getText () {
|
|
66
|
+
return component.text.getText()
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Sets the chip's leading icon
|
|
71
|
+
* @param {string} icon - Icon HTML content
|
|
72
|
+
* @returns {Object} The chip instance for chaining
|
|
73
|
+
*/
|
|
74
|
+
setIcon (icon) {
|
|
75
|
+
component.icon.setIcon(icon)
|
|
76
|
+
return this
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Gets the chip's icon content
|
|
81
|
+
* @returns {string} The chip's icon HTML
|
|
82
|
+
*/
|
|
83
|
+
getIcon () {
|
|
84
|
+
return component.icon.getIcon()
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Sets the chip's trailing icon
|
|
89
|
+
* @param {string} icon - Icon HTML content
|
|
90
|
+
* @returns {Object} The chip instance for chaining
|
|
91
|
+
*/
|
|
92
|
+
setTrailingIcon (icon) {
|
|
93
|
+
const trailingIconSelector = `.${component.getClass('chip')}-trailing-icon`
|
|
94
|
+
let trailingIconElement = component.element.querySelector(trailingIconSelector)
|
|
95
|
+
|
|
96
|
+
if (!trailingIconElement && icon) {
|
|
97
|
+
trailingIconElement = document.createElement('span')
|
|
98
|
+
trailingIconElement.className = `${component.getClass('chip')}-trailing-icon`
|
|
99
|
+
component.element.appendChild(trailingIconElement)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (trailingIconElement) {
|
|
103
|
+
trailingIconElement.innerHTML = icon || ''
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return this
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Destroys the chip component and cleans up resources
|
|
111
|
+
*/
|
|
112
|
+
destroy () {
|
|
113
|
+
lifecycle.destroy()
|
|
114
|
+
}
|
|
115
|
+
})
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
// src/components/chip/chip-set.js
|
|
2
|
+
import { PREFIX } from '../../core/config'
|
|
3
|
+
import createChip from './chip'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Creates a chip set container for grouping related chips
|
|
7
|
+
* @param {Object} config - ChipSet configuration
|
|
8
|
+
* @param {Array} [config.chips=[]] - Array of chip configurations to initialize
|
|
9
|
+
* @param {boolean} [config.scrollable=false] - Whether the chip set is horizontally scrollable
|
|
10
|
+
* @param {boolean} [config.vertical=false] - Whether the chip set is vertically stacked
|
|
11
|
+
* @param {string} [config.class] - Additional CSS classes
|
|
12
|
+
* @param {string} [config.selector] - CSS selector for filtering behavior
|
|
13
|
+
* @param {boolean} [config.multiSelect=false] - Whether multiple chips can be selected simultaneously
|
|
14
|
+
* @param {Function} [config.onChange] - Callback function when chip selection changes
|
|
15
|
+
* @returns {Object} ChipSet component instance
|
|
16
|
+
*/
|
|
17
|
+
const createChipSet = (config = {}) => {
|
|
18
|
+
const {
|
|
19
|
+
chips = [],
|
|
20
|
+
scrollable = false,
|
|
21
|
+
vertical = false,
|
|
22
|
+
class: customClass,
|
|
23
|
+
selector = null,
|
|
24
|
+
multiSelect = false,
|
|
25
|
+
onChange = null
|
|
26
|
+
} = config
|
|
27
|
+
|
|
28
|
+
// Create container element
|
|
29
|
+
const element = document.createElement('div')
|
|
30
|
+
element.className = `${PREFIX}-chip-set`
|
|
31
|
+
|
|
32
|
+
if (customClass) {
|
|
33
|
+
element.classList.add(customClass)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (scrollable) {
|
|
37
|
+
element.classList.add(`${PREFIX}-chip-set--scrollable`)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (vertical) {
|
|
41
|
+
element.classList.add(`${PREFIX}-chip-set--vertical`)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Store chip instances
|
|
45
|
+
const chipInstances = []
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Updates chip selection states based on multiSelect configuration
|
|
49
|
+
* @param {Object} selectedChip - The chip that was clicked/selected
|
|
50
|
+
*/
|
|
51
|
+
const handleSelection = (selectedChip) => {
|
|
52
|
+
if (!multiSelect) {
|
|
53
|
+
// Single selection mode - deselect all other chips
|
|
54
|
+
chipInstances.forEach(chip => {
|
|
55
|
+
if (chip !== selectedChip && chip.isSelected()) {
|
|
56
|
+
chip.setSelected(false)
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Call onChange callback if provided
|
|
62
|
+
if (typeof onChange === 'function') {
|
|
63
|
+
const selectedChips = chipInstances.filter(chip => chip.isSelected())
|
|
64
|
+
onChange(selectedChips, selectedChip)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Adds a chip to the chip set
|
|
70
|
+
* @param {Object} chipConfig - Configuration for the chip
|
|
71
|
+
* @returns {Object} The created chip instance
|
|
72
|
+
*/
|
|
73
|
+
const addChip = (chipConfig) => {
|
|
74
|
+
const chipInstance = createChip({
|
|
75
|
+
...chipConfig,
|
|
76
|
+
onSelect: (chip) => {
|
|
77
|
+
handleSelection(chip)
|
|
78
|
+
if (chipConfig.onSelect) {
|
|
79
|
+
chipConfig.onSelect(chip)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
element.appendChild(chipInstance.element)
|
|
85
|
+
chipInstances.push(chipInstance)
|
|
86
|
+
|
|
87
|
+
// Add click handler to toggle selection
|
|
88
|
+
chipInstance.element.addEventListener('click', () => {
|
|
89
|
+
if (!chipInstance.element.getAttribute('aria-disabled') === 'true') {
|
|
90
|
+
chipInstance.toggleSelected()
|
|
91
|
+
handleSelection(chipInstance)
|
|
92
|
+
}
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
return chipInstance
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Initialize with provided chips
|
|
99
|
+
chips.forEach(chipConfig => addChip(chipConfig))
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
element,
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Adds a new chip to the chip set
|
|
106
|
+
* @param {Object} chipConfig - Configuration for the chip
|
|
107
|
+
* @returns {Object} The chip set instance for chaining
|
|
108
|
+
*/
|
|
109
|
+
addChip (chipConfig) {
|
|
110
|
+
addChip(chipConfig)
|
|
111
|
+
return this
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Removes a chip from the chip set
|
|
116
|
+
* @param {Object|number} chipOrIndex - Chip instance or index to remove
|
|
117
|
+
* @returns {Object} The chip set instance for chaining
|
|
118
|
+
*/
|
|
119
|
+
removeChip (chipOrIndex) {
|
|
120
|
+
const index = typeof chipOrIndex === 'number'
|
|
121
|
+
? chipOrIndex
|
|
122
|
+
: chipInstances.indexOf(chipOrIndex)
|
|
123
|
+
|
|
124
|
+
if (index >= 0 && index < chipInstances.length) {
|
|
125
|
+
const chip = chipInstances[index]
|
|
126
|
+
chip.destroy()
|
|
127
|
+
chipInstances.splice(index, 1)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return this
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Gets all chip instances in the set
|
|
135
|
+
* @returns {Array} Array of chip instances
|
|
136
|
+
*/
|
|
137
|
+
getChips () {
|
|
138
|
+
return [...chipInstances]
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Gets currently selected chips
|
|
143
|
+
* @returns {Array} Array of selected chip instances
|
|
144
|
+
*/
|
|
145
|
+
getSelectedChips () {
|
|
146
|
+
return chipInstances.filter(chip => chip.isSelected())
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Gets the values of selected chips
|
|
151
|
+
* @returns {Array} Array of selected chip values
|
|
152
|
+
*/
|
|
153
|
+
getSelectedValues () {
|
|
154
|
+
return this.getSelectedChips().map(chip => chip.getValue())
|
|
155
|
+
},
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Selects chips by their values
|
|
159
|
+
* @param {Array|string} values - Value or array of values to select
|
|
160
|
+
* @returns {Object} The chip set instance for chaining
|
|
161
|
+
*/
|
|
162
|
+
selectByValue (values) {
|
|
163
|
+
const valueArray = Array.isArray(values) ? values : [values]
|
|
164
|
+
|
|
165
|
+
chipInstances.forEach(chip => {
|
|
166
|
+
const shouldSelect = valueArray.includes(chip.getValue())
|
|
167
|
+
if (shouldSelect !== chip.isSelected()) {
|
|
168
|
+
chip.setSelected(shouldSelect)
|
|
169
|
+
}
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
return this
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Clears all selections
|
|
177
|
+
* @returns {Object} The chip set instance for chaining
|
|
178
|
+
*/
|
|
179
|
+
clearSelection () {
|
|
180
|
+
chipInstances.forEach(chip => {
|
|
181
|
+
chip.setSelected(false)
|
|
182
|
+
})
|
|
183
|
+
return this
|
|
184
|
+
},
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Sets the scrollable state of the chip set
|
|
188
|
+
* @param {boolean} isScrollable - Whether the chip set should be scrollable
|
|
189
|
+
* @returns {Object} The chip set instance for chaining
|
|
190
|
+
*/
|
|
191
|
+
setScrollable (isScrollable) {
|
|
192
|
+
if (isScrollable) {
|
|
193
|
+
element.classList.add(`${PREFIX}-chip-set--scrollable`)
|
|
194
|
+
} else {
|
|
195
|
+
element.classList.remove(`${PREFIX}-chip-set--scrollable`)
|
|
196
|
+
}
|
|
197
|
+
return this
|
|
198
|
+
},
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Sets the vertical layout state
|
|
202
|
+
* @param {boolean} isVertical - Whether the chip set should be vertically stacked
|
|
203
|
+
* @returns {Object} The chip set instance for chaining
|
|
204
|
+
*/
|
|
205
|
+
setVertical (isVertical) {
|
|
206
|
+
if (isVertical) {
|
|
207
|
+
element.classList.add(`${PREFIX}-chip-set--vertical`)
|
|
208
|
+
} else {
|
|
209
|
+
element.classList.remove(`${PREFIX}-chip-set--vertical`)
|
|
210
|
+
}
|
|
211
|
+
return this
|
|
212
|
+
},
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Destroys the chip set and all contained chips
|
|
216
|
+
*/
|
|
217
|
+
destroy () {
|
|
218
|
+
chipInstances.forEach(chip => chip.destroy())
|
|
219
|
+
chipInstances.length = 0
|
|
220
|
+
element.remove()
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export default createChipSet
|