mtrl 0.5.2 → 0.5.4

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.
Files changed (80) hide show
  1. package/dist/components/checkbox/api.d.ts +1 -1
  2. package/dist/components/checkbox/types.d.ts +17 -6
  3. package/dist/components/chips/api.d.ts +5 -2
  4. package/dist/components/chips/chip/api.d.ts +1 -1
  5. package/dist/components/chips/config.d.ts +5 -1
  6. package/dist/components/chips/types.d.ts +14 -3
  7. package/dist/components/index.d.ts +1 -0
  8. package/dist/components/select/types.d.ts +21 -3
  9. package/dist/components/switch/types.d.ts +8 -4
  10. package/dist/index.cjs +14 -14
  11. package/dist/index.cjs.map +13 -13
  12. package/dist/index.js +14 -14
  13. package/dist/index.js.map +13 -13
  14. package/dist/package.json +1 -1
  15. package/dist/styles.css +2 -2
  16. package/package.json +4 -2
  17. package/src/styles/abstract/_base.scss +2 -0
  18. package/src/styles/abstract/_config.scss +28 -0
  19. package/src/styles/abstract/_functions.scss +124 -0
  20. package/src/styles/abstract/_mixins.scss +401 -0
  21. package/src/styles/abstract/_theme.scss +269 -0
  22. package/src/styles/abstract/_variables.scss +338 -0
  23. package/src/styles/base/_reset.scss +86 -0
  24. package/src/styles/base/_typography.scss +155 -0
  25. package/src/styles/components/_badge.scss +183 -0
  26. package/src/styles/components/_bottom-app-bar.scss +103 -0
  27. package/src/styles/components/_button.scss +756 -0
  28. package/src/styles/components/_card.scss +401 -0
  29. package/src/styles/components/_carousel.scss +645 -0
  30. package/src/styles/components/_checkbox.scss +231 -0
  31. package/src/styles/components/_chips.scss +643 -0
  32. package/src/styles/components/_datepicker.scss +358 -0
  33. package/src/styles/components/_dialog.scss +259 -0
  34. package/src/styles/components/_divider.scss +57 -0
  35. package/src/styles/components/_extended-fab.scss +309 -0
  36. package/src/styles/components/_fab.scss +244 -0
  37. package/src/styles/components/_list.scss +774 -0
  38. package/src/styles/components/_menu.scss +245 -0
  39. package/src/styles/components/_navigation-mobile.scss +244 -0
  40. package/src/styles/components/_navigation-system.scss +151 -0
  41. package/src/styles/components/_navigation.scss +407 -0
  42. package/src/styles/components/_progress.scss +101 -0
  43. package/src/styles/components/_radios.scss +187 -0
  44. package/src/styles/components/_search.scss +306 -0
  45. package/src/styles/components/_segmented-button.scss +227 -0
  46. package/src/styles/components/_select.scss +274 -0
  47. package/src/styles/components/_sheet.scss +236 -0
  48. package/src/styles/components/_slider.scss +264 -0
  49. package/src/styles/components/_snackbar.scss +211 -0
  50. package/src/styles/components/_switch.scss +305 -0
  51. package/src/styles/components/_tabs.scss +421 -0
  52. package/src/styles/components/_textfield.scss +1035 -0
  53. package/src/styles/components/_timepicker.scss +451 -0
  54. package/src/styles/components/_tooltip.scss +241 -0
  55. package/src/styles/components/_top-app-bar.scss +225 -0
  56. package/src/styles/main.scss +129 -0
  57. package/src/styles/themes/_autumn.scss +105 -0
  58. package/src/styles/themes/_base-theme.scss +85 -0
  59. package/src/styles/themes/_baseline.scss +173 -0
  60. package/src/styles/themes/_bluekhaki.scss +125 -0
  61. package/src/styles/themes/_brownbeige.scss +125 -0
  62. package/src/styles/themes/_browngreen.scss +125 -0
  63. package/src/styles/themes/_forest.scss +77 -0
  64. package/src/styles/themes/_greenbeige.scss +125 -0
  65. package/src/styles/themes/_index.scss +19 -0
  66. package/src/styles/themes/_material.scss +125 -0
  67. package/src/styles/themes/_ocean.scss +77 -0
  68. package/src/styles/themes/_sageivory.scss +125 -0
  69. package/src/styles/themes/_spring.scss +77 -0
  70. package/src/styles/themes/_summer.scss +87 -0
  71. package/src/styles/themes/_sunset.scss +60 -0
  72. package/src/styles/themes/_tealcaramel.scss +125 -0
  73. package/src/styles/themes/_winter.scss +77 -0
  74. package/src/styles/utilities/_colors.scss +154 -0
  75. package/src/styles/utilities/_flexbox.scss +194 -0
  76. package/src/styles/utilities/_layout.scss +665 -0
  77. package/src/styles/utilities/_ripple.scss +79 -0
  78. package/src/styles/utilities/_spacing.scss +139 -0
  79. package/src/styles/utilities/_typography.scss +178 -0
  80. package/src/styles/utilities/_visibility.scss +142 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mtrl",
3
- "version": "0.5.2",
3
+ "version": "0.5.4",
4
4
  "description": "A functional TypeScript/JavaScript component library with composable architecture based on Material Design 3",
5
5
  "author": "floor",
6
6
  "license": "MIT License",
@@ -25,6 +25,7 @@
25
25
  "types": "./dist/index.d.ts",
26
26
  "exports": {
27
27
  ".": {
28
+ "development": "./src/index.ts",
28
29
  "import": "./dist/index.js",
29
30
  "require": "./dist/index.cjs",
30
31
  "types": "./dist/index.d.ts"
@@ -32,7 +33,8 @@
32
33
  "./styles": "./dist/styles.css"
33
34
  },
34
35
  "files": [
35
- "dist"
36
+ "dist",
37
+ "src/styles"
36
38
  ],
37
39
  "scripts": {
38
40
  "start": "bun run server.js",
@@ -0,0 +1,2 @@
1
+ // src/styles/abstract/_base.scss
2
+ $prefix: 'mtrl';
@@ -0,0 +1,28 @@
1
+ // src/styles/abstract/_config.scss
2
+ @use 'variables' as *;
3
+ @forward 'variables';
4
+ @forward 'functions';
5
+ @forward 'mixins' show
6
+ typography,
7
+ state-layer,
8
+ elevation,
9
+ motion-transition,
10
+ motion-exit,
11
+ motion-enter,
12
+ focus-ring,
13
+ interactive-states,
14
+ flex-center,
15
+ center-content,
16
+ container,
17
+ truncate,
18
+ shape,
19
+ breakpoint-up,
20
+ breakpoint-down,
21
+ breakpoint-between,
22
+ visually-hidden,
23
+ reduced-motion,
24
+ high-contrast,
25
+ rtl,
26
+ touch-target,
27
+ custom-scrollbar,
28
+ print;
@@ -0,0 +1,124 @@
1
+ // src/styles/abstract/_functions.scss
2
+ @use 'sass:map';
3
+ @use 'sass:math';
4
+ @use 'sass:color';
5
+ @use 'variables' as v;
6
+
7
+ // Get nested map value
8
+ @function map-deep-get($map, $keys...) {
9
+ @each $key in $keys {
10
+ $map: map.get($map, $key);
11
+ }
12
+ @return $map;
13
+ }
14
+
15
+ // Get value from design tokens
16
+ @function get-token($category, $token) {
17
+ $token-map: null;
18
+
19
+ @if $category == 'state' {
20
+ $token-map: v.$state;
21
+ } @else if $category == 'motion' {
22
+ $token-map: v.$motion;
23
+ } @else if $category == 'elevation' {
24
+ $token-map: v.$elevation;
25
+ } @else if $category == 'typescale' {
26
+ $token-map: v.$typescale;
27
+ } @else if $category == 'shape' {
28
+ $token-map: v.$shape;
29
+ } @else if $category == 'z-index' {
30
+ $token-map: v.$z-index;
31
+ }
32
+
33
+ @if not $token-map {
34
+ @error 'Unknown token category: #{$category}';
35
+ }
36
+
37
+ $value: map.get($token-map, $token);
38
+
39
+ @if not $value {
40
+ @error 'Unknown token: #{$token} in category #{$category}';
41
+ }
42
+
43
+ @return $value;
44
+ }
45
+
46
+ // State Layer
47
+ @function get-state-opacity($state) {
48
+ @return get-token('state', '#{$state}-state-layer-opacity');
49
+ }
50
+
51
+ // Motion
52
+ @function get-motion-duration($duration) {
53
+ @return get-token('motion', 'duration-#{$duration}');
54
+ }
55
+
56
+ @function get-motion-easing($easing) {
57
+ @return get-token('motion', 'easing-#{$easing}');
58
+ }
59
+
60
+ // Elevation
61
+ @function get-elevation($level) {
62
+ @return get-token('elevation', 'level-#{$level}');
63
+ }
64
+
65
+ // Typography
66
+ @function get-typography($scale) {
67
+ @return get-token('typescale', $scale);
68
+ }
69
+
70
+ // Shape
71
+ @function get-shape($size) {
72
+ @return get-token('shape', $size);
73
+ }
74
+
75
+ // Z-index
76
+ @function get-z-index($layer) {
77
+ @return get-token('z-index', $layer);
78
+ }
79
+
80
+ // Breakpoints
81
+ @function get-breakpoint($size) {
82
+ @return map.get(v.$breakpoints, $size);
83
+ }
84
+
85
+ // Color utilities
86
+ @function get-luminance($color) {
87
+ $red: color.red($color);
88
+ $green: color.green($color);
89
+ $blue: color.blue($color);
90
+
91
+ $luminance: ($red * 0.299 + $green * 0.587 + $blue * 0.114) / 255;
92
+ @return $luminance;
93
+ }
94
+
95
+ @function is-light-color($color) {
96
+ @return get-luminance($color) > 0.6;
97
+ }
98
+
99
+ @function get-contrast-color($color, $light: #fff, $dark: #000) {
100
+ @return if(is-light-color($color), $dark, $light);
101
+ }
102
+
103
+ // Unit conversion utilities
104
+ @function strip-unit($number) {
105
+ @if type-of($number) == 'number' and not unitless($number) {
106
+ @return math.div($number, ($number * 0 + 1));
107
+ }
108
+ @return $number;
109
+ }
110
+
111
+ @function to-rem($size, $base-size: 16px) {
112
+ $rem-size: math.div(strip-unit($size), strip-unit($base-size));
113
+ @return #{$rem-size}rem;
114
+ }
115
+
116
+ @function to-em($size, $base-size: 16px) {
117
+ $em-size: math.div(strip-unit($size), strip-unit($base-size));
118
+ @return #{$em-size}em;
119
+ }
120
+
121
+ // Value constraint utility
122
+ @function constrain($min, $value, $max) {
123
+ @return max($min, min($value, $max));
124
+ }
@@ -0,0 +1,401 @@
1
+ // src/styles/abstract/_mixins.scss
2
+ @use 'sass:map';
3
+ @use 'sass:list';
4
+ @use 'sass:math';
5
+ @use 'variables' as v;
6
+ @use 'functions' as f;
7
+
8
+ // Common icons map
9
+ $icons: (
10
+ 'chevron_right': 'data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"%3E%3Cpolyline points="9 18 15 12 9 6"%3E%3C/polyline%3E%3C/svg%3E',
11
+ 'chevron_down': 'data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"%3E%3Cpolyline points="6 9 12 15 18 9"%3E%3C/polyline%3E%3C/svg%3E',
12
+ 'check': 'data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"%3E%3Cpolyline points="20 6 9 17 4 12"%3E%3C/polyline%3E%3C/svg%3E'
13
+ );
14
+
15
+ @mixin icon($name, $size: 24px) {
16
+ $icon-url: map.get($icons, $name);
17
+ @if $icon-url {
18
+ content: '';
19
+ display: inline-block;
20
+ width: $size;
21
+ height: $size;
22
+ background-image: url($icon-url);
23
+ background-size: contain;
24
+ background-position: center;
25
+ background-repeat: no-repeat;
26
+ }
27
+ }
28
+
29
+ // Typography
30
+ @mixin typography($scale) {
31
+ $styles: f.get-typography($scale);
32
+ font-family: map.get($styles, 'font-family');
33
+ font-size: map.get($styles, 'font-size');
34
+ line-height: map.get($styles, 'line-height');
35
+ letter-spacing: map.get($styles, 'letter-spacing');
36
+ font-weight: map.get($styles, 'font-weight');
37
+ }
38
+
39
+ // State Layers
40
+ @mixin state-layer($color, $state: 'hover', $selector: false) {
41
+ position: relative;
42
+
43
+ @if $selector == false {
44
+ // Default behavior - create a pseudo-element for the state layer
45
+ &::before {
46
+ content: '';
47
+ position: absolute;
48
+ inset: 0;
49
+ background-color: $color;
50
+ opacity: f.get-state-opacity($state);
51
+ pointer-events: none;
52
+ border-radius: inherit;
53
+ }
54
+ } @else {
55
+ // Use the provided selector
56
+ #{$selector} {
57
+ content: '';
58
+ position: absolute;
59
+ inset: 0;
60
+ background-color: $color;
61
+ opacity: f.get-state-opacity($state);
62
+ pointer-events: none;
63
+ border-radius: inherit;
64
+ }
65
+ }
66
+ }
67
+
68
+ // Elevation
69
+ @mixin elevation($level) {
70
+ box-shadow: f.get-elevation($level);
71
+ }
72
+
73
+ // Motion
74
+ @mixin motion-transition($properties...) {
75
+ $transitions: ();
76
+ @each $prop in $properties {
77
+ $transitions: list.append(
78
+ $transitions,
79
+ $prop f.get-motion-duration('short2') v.motion('easing-standard'),
80
+ comma
81
+ );
82
+ }
83
+ transition: $transitions;
84
+ }
85
+
86
+ @mixin motion-exit($properties...) {
87
+ $transitions: ();
88
+ @each $prop in $properties {
89
+ $transitions: list.append(
90
+ $transitions,
91
+ $prop f.get-motion-duration('short4') v.motion('easing-exit'),
92
+ comma
93
+ );
94
+ }
95
+ transition: $transitions;
96
+ }
97
+
98
+ @mixin motion-enter($properties...) {
99
+ $transitions: ();
100
+ @each $prop in $properties {
101
+ $transitions: list.append(
102
+ $transitions,
103
+ $prop f.get-motion-duration('short4') v.motion('easing-enter'),
104
+ comma
105
+ );
106
+ }
107
+ transition: $transitions;
108
+ }
109
+
110
+ // New mixins for specific animation behaviors
111
+ @mixin motion-appear($properties...) {
112
+ $transitions: ();
113
+ @each $prop in $properties {
114
+ $transitions: list.append(
115
+ $transitions,
116
+ $prop f.get-motion-duration('short3') v.motion('easing-appear'),
117
+ comma
118
+ );
119
+ }
120
+ transition: $transitions;
121
+ }
122
+
123
+ @mixin motion-disappear($properties...) {
124
+ $transitions: ();
125
+ @each $prop in $properties {
126
+ $transitions: list.append(
127
+ $transitions,
128
+ $prop f.get-motion-duration('short2') v.motion('easing-disappear'),
129
+ comma
130
+ );
131
+ }
132
+ transition: $transitions;
133
+ }
134
+
135
+ @mixin motion-expand($properties...) {
136
+ $transitions: ();
137
+ @each $prop in $properties {
138
+ $transitions: list.append(
139
+ $transitions,
140
+ $prop f.get-motion-duration('short4') v.motion('easing-expand'),
141
+ comma
142
+ );
143
+ }
144
+ transition: $transitions;
145
+ }
146
+
147
+ @mixin motion-collapse($properties...) {
148
+ $transitions: ();
149
+ @each $prop in $properties {
150
+ $transitions: list.append(
151
+ $transitions,
152
+ $prop f.get-motion-duration('short3') v.motion('easing-collapse'),
153
+ comma
154
+ );
155
+ }
156
+ transition: $transitions;
157
+ }
158
+
159
+ // Focus Ring
160
+ @mixin focus-ring($color: var(--#{v.$prefix}-sys-color-primary), $width: 2px, $offset: 2px) {
161
+ &:focus-visible {
162
+ outline: $width solid $color;
163
+ outline-offset: $offset;
164
+ @include elevation(1);
165
+ }
166
+ }
167
+
168
+ // Interactive States
169
+ @mixin interactive-states($config: ()) {
170
+ $default-config: (
171
+ base-color: var(--#{v.$prefix}-sys-color-primary),
172
+ hover-state: true,
173
+ focus-state: true,
174
+ active-state: true,
175
+ disabled-state: true,
176
+ disabled-opacity: 0.38
177
+ );
178
+
179
+ $config: map.merge($default-config, $config);
180
+
181
+ @if map.get($config, hover-state) {
182
+ &:hover {
183
+ @include state-layer(map.get($config, base-color), 'hover');
184
+ }
185
+ }
186
+
187
+ @if map.get($config, focus-state) {
188
+ &:focus {
189
+ @include state-layer(map.get($config, base-color), 'focus');
190
+ }
191
+ }
192
+
193
+ @if map.get($config, active-state) {
194
+ &:active {
195
+ @include state-layer(map.get($config, base-color), 'pressed');
196
+ }
197
+ }
198
+
199
+ @if map.get($config, disabled-state) {
200
+ &:disabled {
201
+ opacity: map.get($config, disabled-opacity);
202
+ pointer-events: none;
203
+ }
204
+ }
205
+ }
206
+
207
+ // Layout
208
+ @mixin flex-center {
209
+ display: flex;
210
+ align-items: center;
211
+ justify-content: center;
212
+ }
213
+
214
+ @mixin center-content {
215
+ position: absolute;
216
+ top: 50%;
217
+ left: 50%;
218
+ transform: translate(-50%, -50%);
219
+ }
220
+
221
+ @mixin container($max-width: 1200px, $padding: 24px) {
222
+ width: 100%;
223
+ max-width: $max-width;
224
+ margin-inline: auto;
225
+ padding-inline: $padding;
226
+ }
227
+
228
+ // Text
229
+ @mixin truncate($lines: 1) {
230
+ @if $lines == 1 {
231
+ overflow: hidden;
232
+ text-overflow: ellipsis;
233
+ white-space: nowrap;
234
+ } @else {
235
+ display: -webkit-box;
236
+ -webkit-line-clamp: $lines;
237
+ -webkit-box-orient: vertical;
238
+ overflow: hidden;
239
+ }
240
+ }
241
+
242
+ // Shape
243
+ @mixin shape($size) {
244
+ border-radius: f.get-shape($size);
245
+ }
246
+
247
+ // Media Queries
248
+ @mixin breakpoint-up($size) {
249
+ @media (min-width: f.get-breakpoint($size)) {
250
+ @content;
251
+ }
252
+ }
253
+
254
+ @mixin breakpoint-down($size) {
255
+ @media (max-width: f.get-breakpoint($size) - 1) {
256
+ @content;
257
+ }
258
+ }
259
+
260
+ @mixin breakpoint-between($min, $max) {
261
+ @media (min-width: f.get-breakpoint($min)) and (max-width: f.get-breakpoint($max) - 1) {
262
+ @content;
263
+ }
264
+ }
265
+
266
+ // A11y
267
+ @mixin visually-hidden {
268
+ position: absolute;
269
+ width: 1px;
270
+ height: 1px;
271
+ padding: 0;
272
+ margin: -1px;
273
+ overflow: hidden;
274
+ clip: rect(0, 0, 0, 0);
275
+ white-space: nowrap;
276
+ border: 0;
277
+ }
278
+
279
+ @mixin reduced-motion {
280
+ @media (prefers-reduced-motion: reduce) {
281
+ @content;
282
+ }
283
+ }
284
+
285
+ @mixin high-contrast {
286
+ @media (forced-colors: active) {
287
+ @content;
288
+ }
289
+ }
290
+
291
+ // RTL Support
292
+ @mixin rtl {
293
+ [dir='rtl'] & {
294
+ @content;
295
+ }
296
+ }
297
+
298
+ @mixin touch-target($size: 48px) {
299
+ // Position first to avoid the deprecation warning
300
+ position: relative;
301
+
302
+ &::after {
303
+ content: '';
304
+ position: absolute;
305
+ inset: 50%;
306
+ width: $size;
307
+ height: $size;
308
+ transform: translate(-50%, -50%);
309
+ }
310
+
311
+ @media (prefers-reduced-motion: reduce) {
312
+ @content;
313
+ }
314
+
315
+ @media (forced-colors: active) {
316
+ @content;
317
+ }
318
+ }
319
+
320
+ // Scrollbars
321
+ @mixin custom-scrollbar($config: ()) {
322
+ $default-config: (
323
+ width: 8px,
324
+ track-color: transparent,
325
+ thumb-color: rgba(0, 0, 0, 0.2),
326
+ thumb-hover-color: rgba(0, 0, 0, 0.3)
327
+ );
328
+
329
+ $config: map.merge($default-config, $config);
330
+
331
+ &::-webkit-scrollbar {
332
+ width: map.get($config, width);
333
+ }
334
+
335
+ &::-webkit-scrollbar-track {
336
+ background: map.get($config, track-color);
337
+ }
338
+
339
+ &::-webkit-scrollbar-thumb {
340
+ background: map.get($config, thumb-color);
341
+ border-radius: f.get-shape('full');
342
+
343
+ &:hover {
344
+ background: map.get($config, thumb-hover-color);
345
+ }
346
+ }
347
+ }
348
+
349
+
350
+ // Scrollbar mixin for consistent styling across components
351
+ @mixin scrollbar(
352
+ $width: 8px,
353
+ $track-color: rgba(0, 0, 0, 0.05),
354
+ $thumb-color: rgba(0, 0, 0, 0.2)
355
+ ) {
356
+ &::-webkit-scrollbar {
357
+ width: $width;
358
+ }
359
+
360
+ &::-webkit-scrollbar-track {
361
+ background: $track-color;
362
+ }
363
+
364
+ &::-webkit-scrollbar-thumb {
365
+ background: $thumb-color;
366
+ border-radius: math.div($width, 2);
367
+ }
368
+
369
+ // Firefox scrollbar (future compatibility)
370
+ scrollbar-width: thin;
371
+ scrollbar-color: $thumb-color $track-color;
372
+ }
373
+
374
+
375
+ // Flexbox layout mixins
376
+ @mixin flex-row($align: center, $justify: flex-start, $gap: 0) {
377
+ display: flex;
378
+ flex-direction: row;
379
+ align-items: $align;
380
+ justify-content: $justify;
381
+ @if $gap > 0 {
382
+ gap: $gap;
383
+ }
384
+ }
385
+
386
+ @mixin flex-column($align: flex-start, $justify: flex-start, $gap: 0) {
387
+ display: flex;
388
+ flex-direction: column;
389
+ align-items: $align;
390
+ justify-content: $justify;
391
+ @if $gap > 0 {
392
+ gap: $gap;
393
+ }
394
+ }
395
+
396
+ // Print
397
+ @mixin print {
398
+ @media print {
399
+ @content;
400
+ }
401
+ }