@propbinder/mobile-design 0.2.31 → 0.2.33

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/index.d.ts CHANGED
@@ -616,7 +616,7 @@ declare class DsMobileProfileActionsSheetComponent implements OnInit, OnChanges
616
616
  /**
617
617
  * Current view state
618
618
  */
619
- currentView: _angular_core.WritableSignal<"main" | "language">;
619
+ currentView: _angular_core.WritableSignal<"language" | "main">;
620
620
  /**
621
621
  * Reference to the view container for height calculations
622
622
  */
@@ -1158,7 +1158,7 @@ declare class DsMobileContentComponent {
1158
1158
  */
1159
1159
  declare class SectionHeaderComponent {
1160
1160
  /** Width of the header placeholder */
1161
- width: _angular_core.InputSignal<"half" | "third" | "full">;
1161
+ width: _angular_core.InputSignal<"full" | "half" | "third">;
1162
1162
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<SectionHeaderComponent, never>;
1163
1163
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<SectionHeaderComponent, "section-header", never, { "width": { "alias": "width"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
1164
1164
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@propbinder/mobile-design",
3
- "version": "0.2.31",
3
+ "version": "0.2.33",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^20.3.0 || ^21.0.0",
6
6
  "@angular/core": "^20.3.0 || ^21.0.0"
package/styles/ionic.css CHANGED
@@ -22,54 +22,46 @@
22
22
  :root {
23
23
  /* Mobile-specific brand color for headers/backgrounds */
24
24
  --color-brand-secondary: #221a4c;
25
-
25
+
26
26
  /* Ionic Keyboard Appearance - force light theme */
27
27
  --ion-keyboard-color: #ffffff;
28
28
  --ion-keyboard-background: #ffffff;
29
29
  --ion-keyboard-text-color: #000000;
30
30
  color-scheme: light;
31
-
31
+
32
32
  /* Layout - Mobile Navigation */
33
33
  --mobile-tab-bar-height: 64px;
34
34
  --mobile-content-spacing: 20px;
35
-
35
+
36
36
  /* Tab Bar Height - Used for FAB positioning and other layout calculations */
37
37
  /* This is set by ds-mobile-tab-bar and consumed by ds-mobile-fab */
38
38
  --ds-tab-bar-height: 64px;
39
-
39
+
40
40
  /* ============================================
41
41
  SPRING ANIMATIONS
42
42
  Physics-based easing curves with natural bounce
43
43
  ============================================ */
44
-
44
+
45
45
  /* Spring Curves */
46
- --spring-curve-bouncy: linear(
47
- 0, 0.0209, 0.0772, 0.1598, 0.2602, 0.3709, 0.4854, 0.5984, 0.7056, 0.8038, 0.8908, 0.9653, 1.0267, 1.075, 1.111, 1.1354, 1.1497, 1.1551, 1.1532, 1.1455, 1.1335, 1.1184, 1.1014, 1.0837, 1.066, 1.0492, 1.0336, 1.0197, 1.0077, 0.9977, 0.9898, 0.9838, 0.9796, 0.9771, 0.976, 0.9761, 0.9771, 0.9788, 0.9811, 0.9837, 0.9864, 0.9892, 0.9918, 0.9943, 0.9965, 0.9984, 1.0001, 1.0013, 1.0023, 1.003, 1.0035, 1
48
- );
49
-
50
- --spring-curve-gentle: linear(
51
- 0, 0.2, 0.5, 0.8, 1.02, 1.01, 1
52
- );
53
-
54
- --spring-curve-snappy: linear(
55
- 0, 0.3, 0.7, 1.05, 0.98, 1
56
- );
57
-
58
- --spring-curve-smooth: linear(
59
- 0, 0.215, 0.61, 0.855, 1
60
- );
61
-
46
+ --spring-curve-bouncy: linear(0, 0.0209, 0.0772, 0.1598, 0.2602, 0.3709, 0.4854, 0.5984, 0.7056, 0.8038, 0.8908, 0.9653, 1.0267, 1.075, 1.111, 1.1354, 1.1497, 1.1551, 1.1532, 1.1455, 1.1335, 1.1184, 1.1014, 1.0837, 1.066, 1.0492, 1.0336, 1.0197, 1.0077, 0.9977, 0.9898, 0.9838, 0.9796, 0.9771, 0.976, 0.9761, 0.9771, 0.9788, 0.9811, 0.9837, 0.9864, 0.9892, 0.9918, 0.9943, 0.9965, 0.9984, 1.0001, 1.0013, 1.0023, 1.003, 1.0035, 1);
47
+
48
+ --spring-curve-gentle: linear(0, 0.2, 0.5, 0.8, 1.02, 1.01, 1);
49
+
50
+ --spring-curve-snappy: linear(0, 0.3, 0.7, 1.05, 0.98, 1);
51
+
52
+ --spring-curve-smooth: linear(0, 0.215, 0.61, 0.855, 1);
53
+
62
54
  /* Spring Durations */
63
55
  --spring-duration-fast: 400ms;
64
56
  --spring-duration-medium: 700ms;
65
57
  --spring-duration-slow: 1000ms;
66
-
58
+
67
59
  /* Spring Presets (curve + duration) */
68
60
  --spring-bouncy: var(--spring-duration-medium) var(--spring-curve-bouncy);
69
61
  --spring-gentle: var(--spring-duration-fast) var(--spring-curve-gentle);
70
62
  --spring-snappy: var(--spring-duration-fast) var(--spring-curve-snappy);
71
63
  --spring-smooth: var(--spring-duration-medium) var(--spring-curve-smooth);
72
-
64
+
73
65
  /* ============================================
74
66
  SAFE AREA / STATUS BAR CONFIGURATION
75
67
 
@@ -83,12 +75,12 @@
83
75
  1. app.ts: StatusBar.setOverlaysWebView({ overlay: true/false })
84
76
  2. These CSS variables below
85
77
  ============================================ */
86
-
78
+
87
79
  /* Sheet/modal top offset - positions content below status bar area */
88
80
  /* Uses max() to ensure at least 32px offset even on devices without notch */
89
81
  /* +12px adds breathing room below the status bar */
90
82
  --app-sheet-top-offset: calc(max(32px, env(safe-area-inset-top, 32px)) + 12px);
91
-
83
+
92
84
  /* Header top offset - used to fine-tune header position on iOS with overlay: true */
93
85
  /* On web (no safe area), this should be 0px. On iOS, it compensates for status bar overlap */
94
86
  --app-header-top-offset: max(0px, calc(env(safe-area-inset-top, 0px) - 16px));
@@ -109,13 +101,13 @@ body {
109
101
  background-color: var(--color-header-surface);
110
102
  color: var(--text-color-default-primary);
111
103
  font-family: 'Brockmann', system-ui, -apple-system, sans-serif;
112
-
104
+
113
105
  /* Ensure full height for iOS PWA */
114
106
  height: 100%;
115
107
  width: 100%;
116
108
  margin: 0;
117
109
  padding: 0;
118
-
110
+
119
111
  /* Don't add padding to html/body - let Ionic components handle safe areas */
120
112
  }
121
113
 
@@ -127,6 +119,11 @@ body {
127
119
 
128
120
  .plt-ios ion-app {
129
121
  background-color: var(--color-header-surface) !important;
122
+ height: 100dvh;
123
+ }
124
+
125
+ ion-app {
126
+ height: 100dvh;
130
127
  }
131
128
 
132
129
  /* When modal opens, ensure purple background is maintained */
@@ -144,7 +141,7 @@ body.backdrop-no-scroll {
144
141
  --ion-color-primary-contrast: var(--color-on-accent);
145
142
  --ion-color-primary-shade: var(--color-accent-hover);
146
143
  --ion-color-primary-tint: var(--color-accent);
147
-
144
+
148
145
  /* Ionic component defaults */
149
146
  --ion-background-color: var(--color-header-surface);
150
147
  --ion-text-color: var(--text-color-default-primary);
@@ -183,8 +180,10 @@ ion-content::part(scroll) {
183
180
  overscroll-behavior-y: none;
184
181
  -webkit-overflow-scrolling: touch;
185
182
  /* Hide scrollbar while maintaining scroll functionality */
186
- scrollbar-width: none; /* Firefox */
187
- -ms-overflow-style: none; /* IE/Edge */
183
+ scrollbar-width: none;
184
+ /* Firefox */
185
+ -ms-overflow-style: none;
186
+ /* IE/Edge */
188
187
  }
189
188
 
190
189
  /* Hide scrollbar for WebKit browsers (Chrome, Safari, iOS) */
@@ -329,7 +328,7 @@ ion-toast {
329
328
  --box-shadow: 0px -2px 24px rgba(0, 0, 0, 0.12);
330
329
  --backdrop-opacity: 0.4;
331
330
  transition: --backdrop-opacity 0.3s ease;
332
-
331
+
333
332
  /* Position the modal container to fill screen */
334
333
  top: 0 !important;
335
334
  height: 100% !important;
@@ -416,7 +415,8 @@ ion-toast {
416
415
 
417
416
  /* Ensure action list scrolls if needed */
418
417
  .ds-bottom-sheet .actions-list {
419
- max-height: calc(85dvh - 80px); /* Account for handle, padding, and safe area */
418
+ max-height: calc(85dvh - 80px);
419
+ /* Account for handle, padding, and safe area */
420
420
  overflow-y: auto;
421
421
  -webkit-overflow-scrolling: touch;
422
422
  }
@@ -544,6 +544,7 @@ ion-toast {
544
544
  from {
545
545
  transform: translateY(100%);
546
546
  }
547
+
547
548
  to {
548
549
  transform: translateY(0);
549
550
  }
@@ -553,6 +554,7 @@ ion-toast {
553
554
  from {
554
555
  transform: translateY(0);
555
556
  }
557
+
556
558
  to {
557
559
  transform: translateY(100%);
558
560
  }
@@ -562,6 +564,7 @@ ion-toast {
562
564
  from {
563
565
  opacity: 0;
564
566
  }
567
+
565
568
  to {
566
569
  opacity: 1;
567
570
  }
@@ -571,6 +574,7 @@ ion-toast {
571
574
  from {
572
575
  opacity: 1;
573
576
  }
577
+
574
578
  to {
575
579
  opacity: 0;
576
580
  }
@@ -588,6 +592,7 @@ ion-toast {
588
592
 
589
593
  /* Accessibility: Reduced motion */
590
594
  @media (prefers-reduced-motion: reduce) {
595
+
591
596
  .ds-mobile-modal.modal-card-enter-active,
592
597
  .ds-mobile-modal.modal-card-leave-active,
593
598
  .ds-mobile-modal.modal-sheet-enter-active,
@@ -616,11 +621,11 @@ ion-modal.ds-modal-base {
616
621
  --width: 100%;
617
622
  --max-width: 640px;
618
623
  /* Subtract top offset from total height to avoid bottom clipping */
619
- --height: calc(100dvh - var(--app-sheet-top-offset, 24px)) !important;
620
- --max-height: calc(100dvh - var(--app-sheet-top-offset, 24px)) !important;
624
+ --height: calc(100dvh - var(--app-sheet-top-offset, 24px)) !important;
625
+ --max-height: calc(100dvh - var(--app-sheet-top-offset, 24px)) !important;
621
626
  --border-radius: 16px 16px 0 0;
622
627
  display: flex !important;
623
- align-items: flex-end !important;
628
+ align-items: flex-end !important;
624
629
  }
625
630
 
626
631
  ion-modal.ds-modal-base::part(content) {
@@ -630,10 +635,10 @@ ion-modal.ds-modal-base::part(content) {
630
635
  max-width: 640px;
631
636
  margin: 0 auto;
632
637
  /* Reset Ionic's default top offset and stick to bottom */
633
- top: auto !important;
634
- bottom: 0 !important;
635
- height: 100% !important;
636
- position: relative !important;
638
+ top: auto !important;
639
+ bottom: 0 !important;
640
+ height: 100% !important;
641
+ position: relative !important;
637
642
  }
638
643
 
639
644
  /* Auto-height support for base modals */
@@ -649,13 +654,14 @@ ion-modal.ds-modal-base::part(content) {
649
654
  position: relative !important;
650
655
  top: auto !important;
651
656
  max-height: calc(100dvh - var(--app-sheet-top-offset, 24px)) !important;
652
- bottom: 0 !important;
657
+ bottom: 0 !important;
653
658
  }
654
659
 
655
660
  .ds-modal-base.auto-height ion-content {
656
661
  height: auto !important;
657
662
  --height: auto;
658
663
  }
664
+
659
665
  .ds-modal-base::part(backdrop) {
660
666
  background: rgba(0, 0, 0, 0.4);
661
667
  backdrop-filter: blur(4px);
@@ -673,7 +679,8 @@ ion-modal.ds-modal-base::part(content) {
673
679
  --background: var(--color-background-neutral-primary, #ffffff);
674
680
  --width: 100%;
675
681
  --max-width: 640px;
676
- --height: 100dvh; /* Full viewport height - content top offset creates gap */
682
+ --height: 100dvh;
683
+ /* Full viewport height - content top offset creates gap */
677
684
  --border-radius: 16px 16px 0 0;
678
685
  }
679
686
 
@@ -766,7 +773,8 @@ ion-app ion-router-outlet.ion-page-hidden {
766
773
  --background: var(--color-background-neutral-primary, #ffffff);
767
774
  --width: 100%;
768
775
  --max-width: 640px;
769
- --height: 100dvh; /* Full viewport height - content top offset creates gap */
776
+ --height: 100dvh;
777
+ /* Full viewport height - content top offset creates gap */
770
778
  --border-radius: 16px 16px 0 0;
771
779
  }
772
780
 
@@ -801,7 +809,8 @@ ion-app ion-router-outlet.ion-page-hidden {
801
809
  --background: var(--color-background-neutral-primary, #ffffff);
802
810
  --width: 100%;
803
811
  --max-width: 640px;
804
- --height: 100dvh; /* Use dynamic viewport height instead of 100% */
812
+ --height: 100dvh;
813
+ /* Use dynamic viewport height instead of 100% */
805
814
  --border-radius: 16px 16px 0 0;
806
815
  margin-top: var(--app-sheet-top-offset);
807
816
  }
@@ -830,15 +839,15 @@ ion-app ion-router-outlet.ion-page-hidden {
830
839
  .ds-handbook-detail-modal {
831
840
  --background: var(--color-background-neutral-primary-dark, #1a1a1a);
832
841
  }
833
-
842
+
834
843
  .ds-handbook-detail-modal::part(content) {
835
844
  background: var(--color-background-neutral-primary-dark, #1a1a1a);
836
845
  }
837
-
846
+
838
847
  .ds-handbook-detail-modal::part(backdrop) {
839
848
  background: rgba(0, 0, 0, 0.6);
840
849
  }
841
-
850
+
842
851
  .ds-handbook-detail-modal ion-content {
843
852
  --background: var(--color-background-neutral-primary-dark, #1a1a1a);
844
853
  }
@@ -852,7 +861,8 @@ ion-app ion-router-outlet.ion-page-hidden {
852
861
  --background: var(--color-background-neutral-primary, #ffffff);
853
862
  --width: 100%;
854
863
  --max-width: 640px;
855
- --height: 100dvh; /* Full viewport height - content top offset creates gap */
864
+ --height: 100dvh;
865
+ /* Full viewport height - content top offset creates gap */
856
866
  --border-radius: 16px 16px 0 0;
857
867
  }
858
868
 
@@ -897,5 +907,4 @@ ds-button .btn:active:not(:disabled) {
897
907
  /* FORCE hover background color directly - only for primary variant */
898
908
  ds-button[variant="primary"]:hover .btn {
899
909
  background-color: var(--color-accent-hover) !important;
900
- }
901
-
910
+ }