mtrl-addons 0.2.3 → 0.2.5

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/package.json CHANGED
@@ -1,9 +1,20 @@
1
1
  {
2
2
  "name": "mtrl-addons",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "Additional components and utilities for the mtrl system, featuring forms, specialized elements, and extended functionality for modern applications",
5
5
  "type": "module",
6
- "main": "index.ts",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.mjs",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "development": "./src/index.ts",
12
+ "import": "./dist/index.mjs",
13
+ "require": "./dist/index.js",
14
+ "types": "./dist/index.d.ts"
15
+ },
16
+ "./styles": "./dist/styles.css"
17
+ },
7
18
  "files": [
8
19
  "dist",
9
20
  "src/styles"
@@ -38,7 +49,7 @@
38
49
  "author": "floor",
39
50
  "license": "MIT",
40
51
  "peerDependencies": {
41
- "mtrl": "^0.5.1"
52
+ "mtrl": "^0.5.4"
42
53
  },
43
54
  "devDependencies": {
44
55
  "@types/jsdom": "^21.1.7",
@@ -0,0 +1,694 @@
1
+ // src/styles/components/_vlist.scss
2
+ @use "../../../../mtrl/src/styles/abstract/base" as base;
3
+ @use "../../../../mtrl/src/styles/abstract/variables" as v;
4
+ @use "../../../../mtrl/src/styles/abstract/mixins" as m;
5
+
6
+ @use "sass:map";
7
+ @use "sass:list";
8
+ @use "sass:math";
9
+
10
+ $prefix: base.$prefix;
11
+ $layout: "#{$prefix}-layout";
12
+
13
+ // Common gap sizes for layout components
14
+ $gap-sizes: (
15
+ "0": 0,
16
+ "1": 4px,
17
+ "2": 8px,
18
+ "3": 12px,
19
+ "4": 16px,
20
+ "5": 20px,
21
+ "6": 24px,
22
+ "8": 32px,
23
+ "10": 40px,
24
+ "12": 48px,
25
+ );
26
+
27
+ // Default layout properties
28
+ $defaults: (
29
+ "gap": 16px,
30
+ "stack-gap": 16px,
31
+ "row-gap": 16px,
32
+ "grid-gap": 16px,
33
+ "grid-min": 200px,
34
+ "grid-columns": 12,
35
+ "breakpoints": (
36
+ "xs": 0,
37
+ "sm": 600px,
38
+ "md": 960px,
39
+ "lg": 1280px,
40
+ "xl": 1920px,
41
+ ),
42
+ );
43
+
44
+ // ----------------------------------------
45
+ // Base layout styles
46
+ // ----------------------------------------
47
+
48
+ // Container - centers content with max-width
49
+ .#{$layout} {
50
+ width: 100%;
51
+ margin-left: auto;
52
+ margin-right: auto;
53
+ padding-left: map.get($defaults, "gap");
54
+ padding-right: map.get($defaults, "gap");
55
+ box-sizing: border-box;
56
+
57
+ // Different container sizes
58
+ &--sm {
59
+ max-width: 600px;
60
+ }
61
+
62
+ &--md {
63
+ max-width: 960px;
64
+ }
65
+
66
+ &--lg {
67
+ max-width: 1280px;
68
+ }
69
+
70
+ &--xl {
71
+ max-width: 1920px;
72
+ }
73
+
74
+ &--fluid {
75
+ max-width: 100%;
76
+ }
77
+
78
+ // Mobile padding adjustments
79
+ @media (max-width: map.get(map.get($defaults, "breakpoints"), "sm") - 1px) {
80
+ padding-left: 12px;
81
+ padding-right: 12px;
82
+ }
83
+
84
+ // Mobile width options
85
+ &--mobile-narrow {
86
+ @media (max-width: map.get(map.get($defaults, "breakpoints"), "sm") - 1px) {
87
+ max-width: 90%;
88
+ }
89
+ }
90
+
91
+ &--mobile-full {
92
+ @media (max-width: map.get(map.get($defaults, "breakpoints"), "sm") - 1px) {
93
+ padding-left: 0;
94
+ padding-right: 0;
95
+ }
96
+ }
97
+ }
98
+
99
+ // ----------------------------------------
100
+ // Stack Layout (Vertical)
101
+ // ----------------------------------------
102
+
103
+ .#{$layout}--stack {
104
+ display: flex;
105
+ flex-direction: column;
106
+ width: 100%;
107
+ gap: map.get($defaults, "stack-gap");
108
+
109
+ // Stack alignment
110
+ &-start {
111
+ align-items: flex-start;
112
+ }
113
+
114
+ &-center {
115
+ align-items: center;
116
+ }
117
+
118
+ &-end {
119
+ align-items: flex-end;
120
+ }
121
+
122
+ &-stretch {
123
+ align-items: stretch;
124
+ }
125
+
126
+ // Stack distribution (for multi-item stacks)
127
+ &-justify-start {
128
+ justify-content: flex-start;
129
+ }
130
+
131
+ &-justify-center {
132
+ justify-content: center;
133
+ }
134
+
135
+ &-justify-end {
136
+ justify-content: flex-end;
137
+ }
138
+
139
+ &-justify-between {
140
+ justify-content: space-between;
141
+ }
142
+
143
+ &-justify-around {
144
+ justify-content: space-around;
145
+ }
146
+
147
+ // Stack spacing
148
+ @each $name, $size in $gap-sizes {
149
+ &-gap-#{$name} {
150
+ gap: $size;
151
+ }
152
+ }
153
+ }
154
+
155
+ // ----------------------------------------
156
+ // Row Layout (Horizontal)
157
+ // ----------------------------------------
158
+
159
+ .#{$layout}--row {
160
+ display: flex;
161
+ width: 100%;
162
+ gap: map.get($defaults, "row-gap");
163
+
164
+ // Auto-stack on mobile by default
165
+ flex-direction: column;
166
+
167
+ @media (min-width: map.get(map.get($defaults, "breakpoints"), "sm")) {
168
+ flex-direction: row;
169
+ flex-wrap: wrap;
170
+ }
171
+
172
+ // Row alignment
173
+ &-start {
174
+ align-items: flex-start;
175
+ }
176
+
177
+ &-center {
178
+ align-items: center;
179
+ }
180
+
181
+ &-end {
182
+ align-items: flex-end;
183
+ }
184
+
185
+ &-stretch {
186
+ align-items: stretch;
187
+ }
188
+
189
+ // Row distribution
190
+ &-justify-start {
191
+ justify-content: flex-start;
192
+ }
193
+
194
+ &-justify-center {
195
+ justify-content: center;
196
+ }
197
+
198
+ &-justify-end {
199
+ justify-content: flex-end;
200
+ }
201
+
202
+ &-justify-between {
203
+ justify-content: space-between;
204
+ }
205
+
206
+ &-justify-around {
207
+ justify-content: space-around;
208
+ }
209
+
210
+ &-justify-evenly {
211
+ justify-content: space-evenly;
212
+ }
213
+
214
+ // Row wrapping
215
+ &-nowrap {
216
+ @media (min-width: map.get(map.get($defaults, "breakpoints"), "sm")) {
217
+ flex-wrap: nowrap;
218
+ overflow-x: auto;
219
+ }
220
+ }
221
+
222
+ &-wrap-reverse {
223
+ @media (min-width: map.get(map.get($defaults, "breakpoints"), "sm")) {
224
+ flex-wrap: wrap-reverse;
225
+ }
226
+ }
227
+
228
+ // Add option to override auto-stacking for specific cases
229
+ &-no-stack {
230
+ flex-direction: row;
231
+ flex-wrap: wrap;
232
+ }
233
+
234
+ // Row spacing
235
+ @each $name, $size in $gap-sizes {
236
+ &-gap-#{$name} {
237
+ gap: $size;
238
+ }
239
+ }
240
+
241
+ // Row items - full width on mobile, equal width on larger screens
242
+ > * {
243
+ width: 100%; // Full width on mobile
244
+
245
+ @media (min-width: map.get(map.get($defaults, "breakpoints"), "sm")) {
246
+ flex: 1 1 0%; // Equal width on larger screens
247
+ }
248
+ }
249
+
250
+ // Auto width items
251
+ > .#{$layout}__item--auto {
252
+ @media (min-width: map.get(map.get($defaults, "breakpoints"), "sm")) {
253
+ flex: 0 0 auto;
254
+ width: auto;
255
+ }
256
+ }
257
+
258
+ // Fixed width items - full width on mobile
259
+ @for $i from 1 through 12 {
260
+ > .#{$layout}__item--#{$i} {
261
+ @media (min-width: map.get(map.get($defaults, "breakpoints"), "sm")) {
262
+ flex: 0 0 auto;
263
+ width: calc(
264
+ #{math.div($i, 12) * 100%} -
265
+ (
266
+ #{map.get($defaults, "row-gap")} *
267
+ #{math.div(12 - $i, 12)}
268
+ )
269
+ );
270
+ }
271
+ }
272
+ }
273
+
274
+ // Responsive width items
275
+ @each $bp, $width in map.get($defaults, "breakpoints") {
276
+ @if $bp != "xs" {
277
+ @for $i from 1 through 12 {
278
+ > .#{$layout}__item--#{$bp}-#{$i} {
279
+ @media (min-width: $width) {
280
+ flex: 0 0 auto;
281
+ width: calc(
282
+ #{math.div($i, 12) * 100%} -
283
+ (
284
+ #{map.get($defaults, "row-gap")} *
285
+ #{math.div(12 - $i, 12)}
286
+ )
287
+ );
288
+ }
289
+ }
290
+ }
291
+ }
292
+ }
293
+
294
+ // Row items in a no-stack row
295
+ &-no-stack {
296
+ > * {
297
+ flex: 1 1 0%;
298
+ }
299
+
300
+ @for $i from 1 through 12 {
301
+ > .#{$layout}__item--#{$i} {
302
+ flex: 0 0 auto;
303
+ width: calc(
304
+ #{math.div($i, 12) *
305
+ 100%} -
306
+ (
307
+ #{map.get($defaults, "row-gap")} *
308
+ #{math.div(12 - $i, 12)}
309
+ )
310
+ );
311
+ }
312
+ }
313
+ }
314
+ }
315
+
316
+ // ----------------------------------------
317
+ // Grid Layout
318
+ // ----------------------------------------
319
+
320
+ .#{$layout}--grid {
321
+ display: grid;
322
+ gap: map.get($defaults, "grid-gap");
323
+ width: 100%;
324
+
325
+ // Auto-stack on mobile by default
326
+ grid-template-columns: 1fr;
327
+
328
+ @media (min-width: map.get(map.get($defaults, "breakpoints"), "sm")) {
329
+ // Default to auto-fit for non-mobile screens
330
+ grid-template-columns: repeat(
331
+ auto-fit,
332
+ minmax(map.get($defaults, "grid-min"), 1fr)
333
+ );
334
+ }
335
+
336
+ // Grid modes: auto-fit (default), auto-fill
337
+ &-fill {
338
+ @media (min-width: map.get(map.get($defaults, "breakpoints"), "sm")) {
339
+ grid-template-columns: repeat(
340
+ auto-fill,
341
+ minmax(map.get($defaults, "grid-min"), 1fr)
342
+ );
343
+ }
344
+ }
345
+
346
+ // Fixed column counts - stack on mobile by default
347
+ @for $i from 1 through 12 {
348
+ &-cols-#{$i} {
349
+ @media (min-width: map.get(map.get($defaults, "breakpoints"), "sm")) {
350
+ grid-template-columns: repeat($i, 1fr);
351
+ }
352
+ }
353
+ }
354
+
355
+ // Responsive column counts
356
+ @each $bp, $width in map.get($defaults, "breakpoints") {
357
+ @if $bp != "xs" {
358
+ @for $i from 1 through 6 {
359
+ &-#{$bp}-cols-#{$i} {
360
+ @media (min-width: $width) {
361
+ grid-template-columns: repeat($i, 1fr);
362
+ }
363
+ }
364
+ }
365
+ }
366
+ }
367
+
368
+ // Add option to override auto-stacking for specific cases
369
+ &-no-stack {
370
+ grid-template-columns: repeat(
371
+ auto-fit,
372
+ minmax(map.get($defaults, "grid-min"), 1fr)
373
+ );
374
+
375
+ &-cols-2 {
376
+ grid-template-columns: repeat(2, 1fr);
377
+ }
378
+
379
+ &-cols-3 {
380
+ grid-template-columns: repeat(3, 1fr);
381
+ }
382
+ }
383
+
384
+ // Dense auto-placement
385
+ &-dense {
386
+ grid-auto-flow: dense;
387
+ }
388
+
389
+ // Grid alignment
390
+ &-align-start {
391
+ align-items: start;
392
+ }
393
+
394
+ &-align-center {
395
+ align-items: center;
396
+ }
397
+
398
+ &-align-end {
399
+ align-items: end;
400
+ }
401
+
402
+ &-justify-start {
403
+ justify-content: start;
404
+ }
405
+
406
+ &-justify-center {
407
+ justify-content: center;
408
+ }
409
+
410
+ &-justify-end {
411
+ justify-content: end;
412
+ }
413
+
414
+ &-auto-height {
415
+ align-items: start; // Prevent stretching items vertically
416
+
417
+ > * {
418
+ height: auto; // Ensure children only take the height they need
419
+ }
420
+ }
421
+
422
+ // Grid minimum sizes
423
+ @each $name,
424
+ $size
425
+ in ("xs": 120px, "sm": 180px, "md": 240px, "lg": 300px, "xl": 360px)
426
+ {
427
+ &-min-#{$name} {
428
+ grid-template-columns: repeat(auto-fit, minmax($size, 1fr));
429
+
430
+ &.#{$layout}--grid-fill {
431
+ grid-template-columns: repeat(auto-fill, minmax($size, 1fr));
432
+ }
433
+ }
434
+ }
435
+
436
+ // Grid gap sizes
437
+ @each $name, $size in $gap-sizes {
438
+ &-gap-#{$name} {
439
+ gap: $size;
440
+ }
441
+ }
442
+
443
+ // Grid item span
444
+ @for $i from 1 through 12 {
445
+ > .#{$layout}__item--span-#{$i} {
446
+ grid-column: span $i;
447
+ }
448
+
449
+ > .#{$layout}__item--row-span-#{$i} {
450
+ grid-row: span $i;
451
+ }
452
+ }
453
+
454
+ // Responsive item spans
455
+ @each $bp, $width in map.get($defaults, "breakpoints") {
456
+ @if $bp != "xs" {
457
+ @for $i from 1 through 12 {
458
+ > .#{$layout}__item--#{$bp}-span-#{$i} {
459
+ @media (min-width: $width) {
460
+ grid-column: span $i;
461
+ }
462
+ }
463
+ }
464
+ }
465
+ }
466
+ }
467
+
468
+ // ----------------------------------------
469
+ // Item placement and alignment
470
+ // ----------------------------------------
471
+
472
+ // Self alignment utilities for both flex and grid children
473
+ .#{$layout}__item--self-start {
474
+ align-self: flex-start;
475
+ }
476
+
477
+ .#{$layout}__item--self-center {
478
+ align-self: center;
479
+ }
480
+
481
+ .#{$layout}__item--self-end {
482
+ align-self: flex-end;
483
+ }
484
+
485
+ .#{$layout}__item--self-stretch {
486
+ align-self: stretch;
487
+ }
488
+
489
+ // Order utilities
490
+ .#{$layout}__item--order-first {
491
+ order: -9999;
492
+ }
493
+
494
+ .#{$layout}__item--order-last {
495
+ order: 9999;
496
+ }
497
+
498
+ @for $i from 1 through 12 {
499
+ .#{$layout}__item--order-#{$i} {
500
+ order: $i;
501
+ }
502
+ }
503
+
504
+ // ----------------------------------------
505
+ // Responsive display utilities
506
+ // ----------------------------------------
507
+
508
+ // Hide on specific breakpoints
509
+ @each $bp, $width in map.get($defaults, "breakpoints") {
510
+ @if $bp != "xs" {
511
+ .#{$layout}--hide-#{$bp}-up {
512
+ @media (min-width: $width) {
513
+ display: none !important;
514
+ }
515
+ }
516
+
517
+ .#{$layout}--hide-#{$bp}-down {
518
+ @media (max-width: $width - 1px) {
519
+ display: none !important;
520
+ }
521
+ }
522
+ }
523
+ }
524
+
525
+ // Mobile-specific layouts - now redundant as stacking is default behavior
526
+ // These are kept for backward compatibility
527
+ .#{$layout}--stack-mobile {
528
+ @media (max-width: map.get(map.get($defaults, "breakpoints"), "sm") - 1px) {
529
+ display: flex;
530
+ flex-direction: column;
531
+ width: 100%;
532
+ }
533
+ }
534
+
535
+ // Still useful for layouts that specifically need to override
536
+ .#{$layout}--force-stack {
537
+ flex-direction: column !important;
538
+
539
+ > * {
540
+ width: 100% !important;
541
+ }
542
+ }
543
+
544
+ .#{$layout}--row-mobile-scroll {
545
+ @media (max-width: map.get(map.get($defaults, "breakpoints"), "sm") - 1px) {
546
+ flex-wrap: nowrap;
547
+ overflow-x: auto;
548
+ -webkit-overflow-scrolling: touch;
549
+ scroll-snap-type: x mandatory;
550
+
551
+ > * {
552
+ scroll-snap-align: start;
553
+ flex: 0 0 auto;
554
+ width: 80%; // Default mobile scroll item width
555
+ max-width: 300px;
556
+ }
557
+
558
+ // Optionally override the width
559
+ &-small > * {
560
+ width: 60%;
561
+ max-width: 200px;
562
+ }
563
+
564
+ &-large > * {
565
+ width: 90%;
566
+ max-width: 400px;
567
+ }
568
+ }
569
+ }
570
+
571
+ // Mobile-first responsive grid with specified minimum sizes
572
+ .#{$layout}--grid-mobile-first {
573
+ grid-template-columns: 1fr;
574
+
575
+ @media (min-width: map.get(map.get($defaults, "breakpoints"), "sm")) {
576
+ grid-template-columns: repeat(2, 1fr);
577
+ }
578
+
579
+ @media (min-width: map.get(map.get($defaults, "breakpoints"), "md")) {
580
+ grid-template-columns: repeat(
581
+ auto-fit,
582
+ minmax(map.get($defaults, "grid-min"), 1fr)
583
+ );
584
+ }
585
+ }
586
+
587
+ // ----------------------------------------
588
+ // Mobile-specific utilities
589
+ // ----------------------------------------
590
+
591
+ // Mobile safe area insets (for notches and home indicators)
592
+ .#{$layout}--safe-area {
593
+ padding-top: env(safe-area-inset-top, 0);
594
+ padding-right: env(safe-area-inset-right, 0);
595
+ padding-bottom: env(safe-area-inset-bottom, 0);
596
+ padding-left: env(safe-area-inset-left, 0);
597
+ }
598
+
599
+ // Touch-friendly spacing
600
+ .#{$layout}--touch-friendly {
601
+ @media (max-width: map.get(map.get($defaults, "breakpoints"), "sm") - 1px) {
602
+ > * {
603
+ min-height: 44px; // Minimum recommended touch target size
604
+ margin-bottom: 12px; // Ensure adequate spacing between touch targets
605
+ }
606
+ }
607
+ }
608
+
609
+ // Prevent overscroll bounce on iOS
610
+ .#{$layout}--prevent-overscroll {
611
+ height: 100%;
612
+ overflow: hidden;
613
+
614
+ > div {
615
+ height: 100%;
616
+ overflow-y: auto;
617
+ -webkit-overflow-scrolling: touch;
618
+ }
619
+ }
620
+
621
+ // Mobile viewport height fix (for address bar issues)
622
+ .#{$layout}--full-height {
623
+ height: 100vh; /* Fallback */
624
+ height: -webkit-fill-available;
625
+ height: stretch; /* Future standard */
626
+
627
+ @supports (-webkit-touch-callout: none) {
628
+ /* iOS specific fix */
629
+ min-height: -webkit-fill-available;
630
+ }
631
+ }
632
+
633
+ // Mobile navigation bar spacing
634
+ .#{$layout}--nav-spacing {
635
+ padding-bottom: max(env(safe-area-inset-bottom, 16px), 16px);
636
+ }
637
+
638
+ // ----------------------------------------
639
+ // Spacing utilities
640
+ // ----------------------------------------
641
+
642
+ // Utility for consistent spacing in a section
643
+ .#{$layout}--section {
644
+ padding-top: 32px;
645
+ padding-bottom: 32px;
646
+
647
+ @media (min-width: map.get(map.get($defaults, "breakpoints"), "md")) {
648
+ padding-top: 48px;
649
+ padding-bottom: 48px;
650
+ }
651
+
652
+ @media (min-width: map.get(map.get($defaults, "breakpoints"), "lg")) {
653
+ padding-top: 64px;
654
+ padding-bottom: 64px;
655
+ }
656
+
657
+ &-sm {
658
+ padding-top: 16px;
659
+ padding-bottom: 16px;
660
+
661
+ @media (min-width: map.get(map.get($defaults, "breakpoints"), "md")) {
662
+ padding-top: 24px;
663
+ padding-bottom: 24px;
664
+ }
665
+ }
666
+
667
+ &-lg {
668
+ padding-top: 48px;
669
+ padding-bottom: 48px;
670
+
671
+ @media (min-width: map.get(map.get($defaults, "breakpoints"), "md")) {
672
+ padding-top: 64px;
673
+ padding-bottom: 64px;
674
+ }
675
+
676
+ @media (min-width: map.get(map.get($defaults, "breakpoints"), "lg")) {
677
+ padding-top: 96px;
678
+ padding-bottom: 96px;
679
+ }
680
+ }
681
+ }
682
+
683
+ // ----------------------------------------
684
+ // Hero layout
685
+ // ----------------------------------------
686
+
687
+ // Hero layout
688
+ .#{$layout}--hero {
689
+ display: grid;
690
+ grid-template-rows: auto 1fr auto;
691
+ min-height: 100vh;
692
+ min-height: -webkit-fill-available;
693
+ width: 100%;
694
+ }