@svadmin/ui 0.42.1 → 0.42.3

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/dist/app.css CHANGED
@@ -679,15 +679,15 @@ main {
679
679
  }
680
680
 
681
681
  /* Base card flat background overrides */
682
- .layout-clean-flat .bg-card,
682
+ .layout-clean-flat [data-svadmin-content-page] .bg-card,
683
683
  .layout-clean-flat [data-slot="card"] {
684
684
  background: #ffffff !important;
685
685
  border: 1px solid #f1f3f7 !important;
686
686
  box-shadow: none !important;
687
687
  border-radius: 0.5rem !important;
688
688
  }
689
- .dark.layout-clean-flat .bg-card,
690
- .dark .layout-clean-flat .bg-card,
689
+ .dark.layout-clean-flat [data-svadmin-content-page] .bg-card,
690
+ .dark .layout-clean-flat [data-svadmin-content-page] .bg-card,
691
691
  .dark.layout-clean-flat [data-slot="card"],
692
692
  .dark .layout-clean-flat [data-slot="card"] {
693
693
  background: #1e1e2d !important;
@@ -696,7 +696,7 @@ main {
696
696
  }
697
697
 
698
698
  /* Crisp table header styles */
699
- .layout-clean-flat th {
699
+ .layout-clean-flat [data-slot="table-head"] {
700
700
  background-color: #f9f9f9 !important;
701
701
  border-bottom: 1px solid #f1f3f7 !important;
702
702
  color: #181c32 !important;
@@ -705,43 +705,43 @@ main {
705
705
  text-transform: uppercase !important;
706
706
  letter-spacing: 0.05em !important;
707
707
  }
708
- .dark.layout-clean-flat th,
709
- .dark .layout-clean-flat th {
708
+ .dark.layout-clean-flat [data-slot="table-head"],
709
+ .dark .layout-clean-flat [data-slot="table-head"] {
710
710
  background-color: #1a1a27 !important;
711
711
  border-bottom: 1px solid #2b2b40 !important;
712
712
  color: #a1a5b7 !important;
713
713
  }
714
714
 
715
715
  /* Crisp table cell styles */
716
- .layout-clean-flat td {
716
+ .layout-clean-flat [data-slot="table-cell"] {
717
717
  border-bottom: 1px solid #f1f3f7 !important;
718
718
  color: #5e6278 !important;
719
719
  font-size: 0.8125rem !important;
720
720
  }
721
- .dark.layout-clean-flat td,
722
- .dark .layout-clean-flat td {
721
+ .dark.layout-clean-flat [data-slot="table-cell"],
722
+ .dark .layout-clean-flat [data-slot="table-cell"] {
723
723
  border-bottom: 1px solid rgba(43, 43, 64, 0.6) !important;
724
724
  color: #a1a5b7 !important;
725
725
  }
726
726
 
727
727
  /* Table row hover state */
728
- .layout-clean-flat tr:hover td {
728
+ .layout-clean-flat [data-slot="table-row"]:hover [data-slot="table-cell"] {
729
729
  background-color: #f9f9f9 !important;
730
730
  }
731
- .dark.layout-clean-flat tr:hover td,
732
- .dark .layout-clean-flat tr:hover td {
731
+ .dark.layout-clean-flat [data-slot="table-row"]:hover [data-slot="table-cell"],
732
+ .dark .layout-clean-flat [data-slot="table-row"]:hover [data-slot="table-cell"] {
733
733
  background-color: rgba(43, 43, 64, 0.3) !important;
734
734
  }
735
735
 
736
736
  /* Sidebar layout adjustments for clean-flat theme */
737
- .layout-clean-flat aside {
737
+ .layout-clean-flat [data-svadmin-sidebar] {
738
738
  background: #fafbfc !important;
739
739
  color: #181c32 !important;
740
740
  border-right-color: #f1f3f7 !important;
741
741
  box-shadow: none !important;
742
742
  }
743
- .dark.layout-clean-flat aside,
744
- .dark .layout-clean-flat aside {
743
+ .dark.layout-clean-flat [data-svadmin-sidebar],
744
+ .dark .layout-clean-flat [data-svadmin-sidebar] {
745
745
  background: #1e1e2d !important;
746
746
  color: #a1a5b7 !important;
747
747
  border-right-color: #2b2b40 !important;
@@ -843,12 +843,12 @@ main {
843
843
  }
844
844
 
845
845
  /* svadmin flat list and edit surfaces */
846
- [data-svadmin-list-header],
847
- [data-svadmin-table-toolbar],
848
- [data-svadmin-table-card],
849
- [data-svadmin-form-header],
850
- [data-svadmin-form-card],
851
- [data-svadmin-form-actions] {
846
+ .layout-clean-flat [data-svadmin-list-header],
847
+ .layout-clean-flat [data-svadmin-table-toolbar],
848
+ .layout-clean-flat [data-svadmin-table-card],
849
+ .layout-clean-flat [data-svadmin-form-header],
850
+ .layout-clean-flat [data-svadmin-form-card],
851
+ .layout-clean-flat [data-svadmin-form-actions] {
852
852
  box-shadow: none !important;
853
853
  }
854
854
 
@@ -880,12 +880,12 @@ main {
880
880
  background: #f9f9f9 !important;
881
881
  }
882
882
 
883
- [data-svadmin-datatable] {
883
+ .layout-clean-flat [data-svadmin-datatable] {
884
884
  border-collapse: separate !important;
885
885
  border-spacing: 0 !important;
886
886
  }
887
887
 
888
- [data-svadmin-table-head] [data-slot="table-head"] {
888
+ .layout-clean-flat [data-svadmin-table-head] [data-slot="table-head"] {
889
889
  height: 3.25rem !important;
890
890
  border-bottom: 1px solid rgba(225, 227, 234, 0.78) !important;
891
891
  background: #f9f9f9 !important;
@@ -896,59 +896,59 @@ main {
896
896
  text-transform: uppercase !important;
897
897
  }
898
898
 
899
- [data-svadmin-table-row] {
899
+ .layout-clean-flat [data-svadmin-table-row] {
900
900
  border-bottom-color: rgba(241, 243, 247, 0.95) !important;
901
901
  }
902
902
 
903
- [data-svadmin-table-row] [data-slot="table-cell"] {
903
+ .layout-clean-flat [data-svadmin-table-row] [data-slot="table-cell"] {
904
904
  height: 3.625rem !important;
905
905
  color: #5e6278 !important;
906
906
  font-size: 0.8125rem !important;
907
907
  }
908
908
 
909
- [data-svadmin-table-row]:hover [data-slot="table-cell"] {
909
+ .layout-clean-flat [data-svadmin-table-row]:hover [data-slot="table-cell"] {
910
910
  background: #fbfcfd !important;
911
911
  }
912
912
 
913
- [data-svadmin-pagination] {
913
+ .layout-clean-flat [data-svadmin-pagination] {
914
914
  border-radius: 0.5rem;
915
915
  padding: 0.35rem 0.15rem;
916
916
  }
917
917
 
918
- [data-svadmin-form-content] {
918
+ .layout-clean-flat [data-svadmin-form-content] {
919
919
  padding-top: 0 !important;
920
920
  padding-bottom: 0 !important;
921
921
  }
922
922
 
923
- [data-svadmin-form-row] {
923
+ .layout-clean-flat [data-svadmin-form-row] {
924
924
  border-bottom: 1px solid rgba(241, 243, 247, 0.95);
925
925
  padding: 1.35rem 0;
926
926
  }
927
927
 
928
- [data-svadmin-form-row]:last-child {
928
+ .layout-clean-flat [data-svadmin-form-row]:last-child {
929
929
  border-bottom: 0;
930
930
  }
931
931
 
932
- [data-svadmin-field-label] {
932
+ .layout-clean-flat [data-svadmin-field-label] {
933
933
  color: #3f4254 !important;
934
934
  font-weight: 600 !important;
935
935
  }
936
936
 
937
- [data-svadmin-form-settings] [data-slot="input"],
938
- [data-svadmin-form-settings] textarea,
939
- [data-svadmin-form-settings] [data-slot="select-trigger"] {
937
+ .layout-clean-flat [data-svadmin-form-settings] [data-slot="input"],
938
+ .layout-clean-flat [data-svadmin-form-settings] textarea,
939
+ .layout-clean-flat [data-svadmin-form-settings] [data-slot="select-trigger"] {
940
940
  min-height: 2.75rem !important;
941
941
  border-radius: 0.5rem !important;
942
942
  background: #f9f9f9 !important;
943
943
  }
944
944
 
945
- [data-svadmin-form-actions] {
945
+ .layout-clean-flat [data-svadmin-form-actions] {
946
946
  width: fit-content;
947
947
  max-width: 100%;
948
948
  }
949
949
 
950
950
  @media (min-width: 768px) {
951
- [data-svadmin-form-settings] [data-svadmin-field] {
951
+ .layout-clean-flat [data-svadmin-form-settings] [data-svadmin-field] {
952
952
  display: grid !important;
953
953
  grid-template-columns: minmax(10rem, 14rem) minmax(0, 1fr) !important;
954
954
  align-items: start !important;
@@ -956,45 +956,50 @@ main {
956
956
  row-gap: 0.35rem !important;
957
957
  }
958
958
 
959
- [data-svadmin-form-settings] [data-svadmin-field] > [data-svadmin-field-label] {
959
+ .layout-clean-flat [data-svadmin-form-settings] [data-svadmin-field] > [data-svadmin-field-label] {
960
960
  padding-top: 0.8rem !important;
961
961
  }
962
962
 
963
- [data-svadmin-form-settings] [data-svadmin-field] > :not([data-svadmin-field-label]) {
963
+ .layout-clean-flat [data-svadmin-form-settings] [data-svadmin-field] > :not([data-svadmin-field-label]) {
964
964
  grid-column: 2 !important;
965
965
  }
966
966
  }
967
967
 
968
- .dark [data-svadmin-table-head] [data-slot="table-head"] {
968
+ .dark.layout-clean-flat [data-svadmin-table-head] [data-slot="table-head"],
969
+ .dark .layout-clean-flat [data-svadmin-table-head] [data-slot="table-head"] {
969
970
  background: #1a1a27 !important;
970
971
  border-bottom-color: #2b2b40 !important;
971
972
  color: #a1a5b7 !important;
972
973
  }
973
974
 
974
- .dark [data-svadmin-table-row] {
975
+ .dark.layout-clean-flat [data-svadmin-table-row],
976
+ .dark .layout-clean-flat [data-svadmin-table-row] {
975
977
  border-bottom-color: rgba(43, 43, 64, 0.82) !important;
976
978
  }
977
979
 
978
- .dark [data-svadmin-table-row] [data-slot="table-cell"] {
980
+ .dark.layout-clean-flat [data-svadmin-table-row] [data-slot="table-cell"],
981
+ .dark .layout-clean-flat [data-svadmin-table-row] [data-slot="table-cell"] {
979
982
  color: #a1a5b7 !important;
980
983
  }
981
984
 
982
- .dark [data-svadmin-table-row]:hover [data-slot="table-cell"] {
985
+ .dark.layout-clean-flat [data-svadmin-table-row]:hover [data-slot="table-cell"],
986
+ .dark .layout-clean-flat [data-svadmin-table-row]:hover [data-slot="table-cell"] {
983
987
  background: rgba(43, 43, 64, 0.32) !important;
984
988
  }
985
989
 
986
- .dark [data-svadmin-form-row] {
990
+ .dark.layout-clean-flat [data-svadmin-form-row],
991
+ .dark .layout-clean-flat [data-svadmin-form-row] {
987
992
  border-bottom-color: rgba(43, 43, 64, 0.82);
988
993
  }
989
994
 
990
995
  /* ─── Flat workspace redesign pass: non-sidebar pages ─── */
991
- .layout-clean-flat main {
996
+ .layout-clean-flat [data-svadmin-main] {
992
997
  background:
993
998
  linear-gradient(180deg, color-mix(in oklch, var(--background) 86%, white) 0%, var(--background) 34rem),
994
999
  var(--background) !important;
995
1000
  }
996
1001
 
997
- .layout-clean-flat main > div {
1002
+ .layout-clean-flat [data-svadmin-main] > div {
998
1003
  min-width: 0 !important;
999
1004
  }
1000
1005
 
@@ -1025,86 +1030,86 @@ main {
1025
1030
  min-width: 0 !important;
1026
1031
  }
1027
1032
 
1028
- .layout-clean-flat main section,
1029
- .layout-clean-flat main [class*="grid"],
1030
- .layout-clean-flat main [class*="flex"],
1031
- .layout-clean-flat main [data-slot="card-content"] {
1033
+ .layout-clean-flat [data-svadmin-main] section,
1034
+ .layout-clean-flat [data-svadmin-main] [class*="grid"],
1035
+ .layout-clean-flat [data-svadmin-main] [class*="flex"],
1036
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-content"] {
1032
1037
  min-width: 0;
1033
1038
  }
1034
1039
 
1035
- .layout-clean-flat main h1,
1036
- .layout-clean-flat main h2,
1037
- .layout-clean-flat main h3,
1038
- .layout-clean-flat main p,
1039
- .layout-clean-flat main [data-slot="badge"] {
1040
+ .layout-clean-flat [data-svadmin-main] h1,
1041
+ .layout-clean-flat [data-svadmin-main] h2,
1042
+ .layout-clean-flat [data-svadmin-main] h3,
1043
+ .layout-clean-flat [data-svadmin-main] p,
1044
+ .layout-clean-flat [data-svadmin-main] [data-slot="badge"] {
1040
1045
  max-width: 100%;
1041
1046
  }
1042
1047
 
1043
- .layout-clean-flat main h1,
1044
- .layout-clean-flat main h2,
1045
- .layout-clean-flat main h3,
1046
- .layout-clean-flat main [data-slot="card-title"] {
1048
+ .layout-clean-flat [data-svadmin-main] h1,
1049
+ .layout-clean-flat [data-svadmin-main] h2,
1050
+ .layout-clean-flat [data-svadmin-main] h3,
1051
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-title"] {
1047
1052
  overflow-wrap: anywhere;
1048
1053
  }
1049
1054
 
1050
- .layout-clean-flat main p,
1051
- .layout-clean-flat main [data-slot="card-description"] {
1055
+ .layout-clean-flat [data-svadmin-main] p,
1056
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-description"] {
1052
1057
  overflow-wrap: break-word;
1053
1058
  }
1054
1059
 
1055
- .layout-clean-flat main > div[class*="space-y"] > section:first-child {
1060
+ .layout-clean-flat [data-svadmin-main] > div[class*="space-y"] > section:first-child {
1056
1061
  border-radius: 0 !important;
1057
1062
  background: transparent !important;
1058
1063
  }
1059
1064
 
1060
- .layout-clean-flat main > div[class*="space-y"] > section:first-child [data-slot="card"],
1061
- .layout-clean-flat main > div[class*="space-y"] > section:first-child + [class*="grid"] [data-slot="card"],
1062
- .layout-clean-flat main [data-svadmin-ops-hero] [data-slot="card"] {
1065
+ .layout-clean-flat [data-svadmin-main] > div[class*="space-y"] > section:first-child [data-slot="card"],
1066
+ .layout-clean-flat [data-svadmin-main] > div[class*="space-y"] > section:first-child + [class*="grid"] [data-slot="card"],
1067
+ .layout-clean-flat [data-svadmin-main] [data-svadmin-ops-hero] [data-slot="card"] {
1063
1068
  background: transparent !important;
1064
1069
  border-color: color-mix(in oklch, var(--border) 72%, transparent) !important;
1065
1070
  box-shadow: none !important;
1066
1071
  }
1067
1072
 
1068
- .layout-clean-flat main > div[class*="space-y"] > section:first-child [data-slot="card"]:has([data-slot="card"]),
1069
- .layout-clean-flat main [data-slot="card"]:has(> [data-slot="card-content"] [data-svadmin-table-card]) {
1073
+ .layout-clean-flat [data-svadmin-main] > div[class*="space-y"] > section:first-child [data-slot="card"]:has([data-slot="card"]),
1074
+ .layout-clean-flat [data-svadmin-main] [data-slot="card"]:has(> [data-slot="card-content"] [data-svadmin-table-card]) {
1070
1075
  border: 0 !important;
1071
1076
  background: transparent !important;
1072
1077
  padding: 0 !important;
1073
1078
  }
1074
1079
 
1075
- .layout-clean-flat main [data-slot="card"] [data-slot="card"] {
1080
+ .layout-clean-flat [data-svadmin-main] [data-slot="card"] [data-slot="card"] {
1076
1081
  background: color-mix(in oklch, var(--card) 88%, var(--background)) !important;
1077
1082
  border-color: color-mix(in oklch, var(--border) 70%, transparent) !important;
1078
1083
  }
1079
1084
 
1080
- .layout-clean-flat main [data-slot="card-content"] > .flex,
1081
- .layout-clean-flat main [data-slot="card-content"] > .grid {
1085
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-content"] > .flex,
1086
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-content"] > .grid {
1082
1087
  min-width: 0;
1083
1088
  }
1084
1089
 
1085
- .layout-clean-flat main [data-slot="card-content"] span[class*="h-10"][class*="w-10"],
1086
- .layout-clean-flat main [data-slot="card-content"] span[class*="h-11"][class*="w-11"],
1087
- .layout-clean-flat main [data-slot="card-content"] span[class*="h-12"][class*="w-12"] {
1090
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-content"] span[class*="h-10"][class*="w-10"],
1091
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-content"] span[class*="h-11"][class*="w-11"],
1092
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-content"] span[class*="h-12"][class*="w-12"] {
1088
1093
  flex-shrink: 0;
1089
1094
  }
1090
1095
 
1091
- .layout-clean-flat main [data-slot="card-content"] [class*="text-2xl"],
1092
- .layout-clean-flat main [data-slot="card-content"] [class*="text-3xl"] {
1096
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-content"] [class*="text-2xl"],
1097
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-content"] [class*="text-3xl"] {
1093
1098
  line-height: 1.12;
1094
1099
  }
1095
1100
 
1096
- .layout-clean-flat main [data-slot="badge"] {
1101
+ .layout-clean-flat [data-svadmin-main] [data-slot="badge"] {
1097
1102
  overflow: hidden;
1098
1103
  text-overflow: ellipsis;
1099
1104
  white-space: nowrap;
1100
1105
  }
1101
1106
 
1102
- .layout-clean-flat main [data-slot="tabs-list"] {
1107
+ .layout-clean-flat [data-svadmin-main] [data-slot="tabs-list"] {
1103
1108
  min-width: 0;
1104
1109
  border-radius: 0.5rem !important;
1105
1110
  }
1106
1111
 
1107
- .layout-clean-flat main [data-slot="tabs-trigger"] {
1112
+ .layout-clean-flat [data-svadmin-main] [data-slot="tabs-trigger"] {
1108
1113
  min-width: 0;
1109
1114
  overflow: hidden;
1110
1115
  text-overflow: ellipsis;
@@ -1194,29 +1199,29 @@ main {
1194
1199
  }
1195
1200
 
1196
1201
  @media (max-width: 767px) {
1197
- .layout-clean-flat main {
1202
+ .layout-clean-flat [data-svadmin-main] {
1198
1203
  padding-left: 1rem !important;
1199
1204
  padding-right: 1rem !important;
1200
1205
  }
1201
1206
 
1202
- .layout-clean-flat main h1 {
1207
+ .layout-clean-flat [data-svadmin-main] h1 {
1203
1208
  font-size: clamp(1.75rem, 1.55rem + 1vw, 2.125rem) !important;
1204
1209
  }
1205
1210
 
1206
- .layout-clean-flat main [data-slot="card"] {
1211
+ .layout-clean-flat [data-svadmin-main] [data-slot="card"] {
1207
1212
  border-left: 1px solid color-mix(in oklch, var(--border) 72%, transparent) !important;
1208
1213
  border-right: 1px solid color-mix(in oklch, var(--border) 72%, transparent) !important;
1209
1214
  border-radius: 0.5rem !important;
1210
1215
  }
1211
1216
 
1212
- .layout-clean-flat main [data-slot="card-header"],
1213
- .layout-clean-flat main [data-slot="card-content"],
1214
- .layout-clean-flat main [data-slot="card-footer"] {
1217
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-header"],
1218
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-content"],
1219
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-footer"] {
1215
1220
  padding-left: 1rem !important;
1216
1221
  padding-right: 1rem !important;
1217
1222
  }
1218
1223
 
1219
- .layout-clean-flat main > div[class*="space-y"] > section:first-child {
1224
+ .layout-clean-flat [data-svadmin-main] > div[class*="space-y"] > section:first-child {
1220
1225
  padding-bottom: 1rem !important;
1221
1226
  }
1222
1227
 
@@ -1255,14 +1260,14 @@ main {
1255
1260
  }
1256
1261
 
1257
1262
  @media (min-width: 768px) and (max-width: 1023px) {
1258
- .layout-clean-flat main [class*="md:grid-cols"],
1259
- .layout-clean-flat main [class*="lg:grid-cols"],
1260
- .layout-clean-flat main [class*="xl:grid-cols"] {
1263
+ .layout-clean-flat [data-svadmin-main] [class*="md:grid-cols"],
1264
+ .layout-clean-flat [data-svadmin-main] [class*="lg:grid-cols"],
1265
+ .layout-clean-flat [data-svadmin-main] [class*="xl:grid-cols"] {
1261
1266
  grid-template-columns: minmax(0, 1fr) !important;
1262
1267
  }
1263
1268
 
1264
- .layout-clean-flat main [class*="lg:flex-row"],
1265
- .layout-clean-flat main [class*="xl:flex-row"] {
1269
+ .layout-clean-flat [data-svadmin-main] [class*="lg:flex-row"],
1270
+ .layout-clean-flat [data-svadmin-main] [class*="xl:flex-row"] {
1266
1271
  flex-direction: column !important;
1267
1272
  align-items: stretch !important;
1268
1273
  }
@@ -678,15 +678,15 @@ main {
678
678
  }
679
679
 
680
680
  /* Base card flat background overrides */
681
- .layout-clean-flat .bg-card,
681
+ .layout-clean-flat [data-svadmin-content-page] .bg-card,
682
682
  .layout-clean-flat [data-slot="card"] {
683
683
  background: #ffffff !important;
684
684
  border: 1px solid #f1f3f7 !important;
685
685
  box-shadow: none !important;
686
686
  border-radius: 0.5rem !important;
687
687
  }
688
- .dark.layout-clean-flat .bg-card,
689
- .dark .layout-clean-flat .bg-card,
688
+ .dark.layout-clean-flat [data-svadmin-content-page] .bg-card,
689
+ .dark .layout-clean-flat [data-svadmin-content-page] .bg-card,
690
690
  .dark.layout-clean-flat [data-slot="card"],
691
691
  .dark .layout-clean-flat [data-slot="card"] {
692
692
  background: #1e1e2d !important;
@@ -695,7 +695,7 @@ main {
695
695
  }
696
696
 
697
697
  /* Crisp table header styles */
698
- .layout-clean-flat th {
698
+ .layout-clean-flat [data-slot="table-head"] {
699
699
  background-color: #f9f9f9 !important;
700
700
  border-bottom: 1px solid #f1f3f7 !important;
701
701
  color: #181c32 !important;
@@ -704,43 +704,43 @@ main {
704
704
  text-transform: uppercase !important;
705
705
  letter-spacing: 0.05em !important;
706
706
  }
707
- .dark.layout-clean-flat th,
708
- .dark .layout-clean-flat th {
707
+ .dark.layout-clean-flat [data-slot="table-head"],
708
+ .dark .layout-clean-flat [data-slot="table-head"] {
709
709
  background-color: #1a1a27 !important;
710
710
  border-bottom: 1px solid #2b2b40 !important;
711
711
  color: #a1a5b7 !important;
712
712
  }
713
713
 
714
714
  /* Crisp table cell styles */
715
- .layout-clean-flat td {
715
+ .layout-clean-flat [data-slot="table-cell"] {
716
716
  border-bottom: 1px solid #f1f3f7 !important;
717
717
  color: #5e6278 !important;
718
718
  font-size: 0.8125rem !important;
719
719
  }
720
- .dark.layout-clean-flat td,
721
- .dark .layout-clean-flat td {
720
+ .dark.layout-clean-flat [data-slot="table-cell"],
721
+ .dark .layout-clean-flat [data-slot="table-cell"] {
722
722
  border-bottom: 1px solid rgba(43, 43, 64, 0.6) !important;
723
723
  color: #a1a5b7 !important;
724
724
  }
725
725
 
726
726
  /* Table row hover state */
727
- .layout-clean-flat tr:hover td {
727
+ .layout-clean-flat [data-slot="table-row"]:hover [data-slot="table-cell"] {
728
728
  background-color: #f9f9f9 !important;
729
729
  }
730
- .dark.layout-clean-flat tr:hover td,
731
- .dark .layout-clean-flat tr:hover td {
730
+ .dark.layout-clean-flat [data-slot="table-row"]:hover [data-slot="table-cell"],
731
+ .dark .layout-clean-flat [data-slot="table-row"]:hover [data-slot="table-cell"] {
732
732
  background-color: rgba(43, 43, 64, 0.3) !important;
733
733
  }
734
734
 
735
735
  /* Sidebar layout adjustments for clean-flat theme */
736
- .layout-clean-flat aside {
736
+ .layout-clean-flat [data-svadmin-sidebar] {
737
737
  background: #fafbfc !important;
738
738
  color: #181c32 !important;
739
739
  border-right-color: #f1f3f7 !important;
740
740
  box-shadow: none !important;
741
741
  }
742
- .dark.layout-clean-flat aside,
743
- .dark .layout-clean-flat aside {
742
+ .dark.layout-clean-flat [data-svadmin-sidebar],
743
+ .dark .layout-clean-flat [data-svadmin-sidebar] {
744
744
  background: #1e1e2d !important;
745
745
  color: #a1a5b7 !important;
746
746
  border-right-color: #2b2b40 !important;
@@ -842,12 +842,12 @@ main {
842
842
  }
843
843
 
844
844
  /* svadmin flat list and edit surfaces */
845
- [data-svadmin-list-header],
846
- [data-svadmin-table-toolbar],
847
- [data-svadmin-table-card],
848
- [data-svadmin-form-header],
849
- [data-svadmin-form-card],
850
- [data-svadmin-form-actions] {
845
+ .layout-clean-flat [data-svadmin-list-header],
846
+ .layout-clean-flat [data-svadmin-table-toolbar],
847
+ .layout-clean-flat [data-svadmin-table-card],
848
+ .layout-clean-flat [data-svadmin-form-header],
849
+ .layout-clean-flat [data-svadmin-form-card],
850
+ .layout-clean-flat [data-svadmin-form-actions] {
851
851
  box-shadow: none !important;
852
852
  }
853
853
 
@@ -879,12 +879,12 @@ main {
879
879
  background: #f9f9f9 !important;
880
880
  }
881
881
 
882
- [data-svadmin-datatable] {
882
+ .layout-clean-flat [data-svadmin-datatable] {
883
883
  border-collapse: separate !important;
884
884
  border-spacing: 0 !important;
885
885
  }
886
886
 
887
- [data-svadmin-table-head] [data-slot="table-head"] {
887
+ .layout-clean-flat [data-svadmin-table-head] [data-slot="table-head"] {
888
888
  height: 3.25rem !important;
889
889
  border-bottom: 1px solid rgba(225, 227, 234, 0.78) !important;
890
890
  background: #f9f9f9 !important;
@@ -895,59 +895,59 @@ main {
895
895
  text-transform: uppercase !important;
896
896
  }
897
897
 
898
- [data-svadmin-table-row] {
898
+ .layout-clean-flat [data-svadmin-table-row] {
899
899
  border-bottom-color: rgba(241, 243, 247, 0.95) !important;
900
900
  }
901
901
 
902
- [data-svadmin-table-row] [data-slot="table-cell"] {
902
+ .layout-clean-flat [data-svadmin-table-row] [data-slot="table-cell"] {
903
903
  height: 3.625rem !important;
904
904
  color: #5e6278 !important;
905
905
  font-size: 0.8125rem !important;
906
906
  }
907
907
 
908
- [data-svadmin-table-row]:hover [data-slot="table-cell"] {
908
+ .layout-clean-flat [data-svadmin-table-row]:hover [data-slot="table-cell"] {
909
909
  background: #fbfcfd !important;
910
910
  }
911
911
 
912
- [data-svadmin-pagination] {
912
+ .layout-clean-flat [data-svadmin-pagination] {
913
913
  border-radius: 0.5rem;
914
914
  padding: 0.35rem 0.15rem;
915
915
  }
916
916
 
917
- [data-svadmin-form-content] {
917
+ .layout-clean-flat [data-svadmin-form-content] {
918
918
  padding-top: 0 !important;
919
919
  padding-bottom: 0 !important;
920
920
  }
921
921
 
922
- [data-svadmin-form-row] {
922
+ .layout-clean-flat [data-svadmin-form-row] {
923
923
  border-bottom: 1px solid rgba(241, 243, 247, 0.95);
924
924
  padding: 1.35rem 0;
925
925
  }
926
926
 
927
- [data-svadmin-form-row]:last-child {
927
+ .layout-clean-flat [data-svadmin-form-row]:last-child {
928
928
  border-bottom: 0;
929
929
  }
930
930
 
931
- [data-svadmin-field-label] {
931
+ .layout-clean-flat [data-svadmin-field-label] {
932
932
  color: #3f4254 !important;
933
933
  font-weight: 600 !important;
934
934
  }
935
935
 
936
- [data-svadmin-form-settings] [data-slot="input"],
937
- [data-svadmin-form-settings] textarea,
938
- [data-svadmin-form-settings] [data-slot="select-trigger"] {
936
+ .layout-clean-flat [data-svadmin-form-settings] [data-slot="input"],
937
+ .layout-clean-flat [data-svadmin-form-settings] textarea,
938
+ .layout-clean-flat [data-svadmin-form-settings] [data-slot="select-trigger"] {
939
939
  min-height: 2.75rem !important;
940
940
  border-radius: 0.5rem !important;
941
941
  background: #f9f9f9 !important;
942
942
  }
943
943
 
944
- [data-svadmin-form-actions] {
944
+ .layout-clean-flat [data-svadmin-form-actions] {
945
945
  width: fit-content;
946
946
  max-width: 100%;
947
947
  }
948
948
 
949
949
  @media (min-width: 768px) {
950
- [data-svadmin-form-settings] [data-svadmin-field] {
950
+ .layout-clean-flat [data-svadmin-form-settings] [data-svadmin-field] {
951
951
  display: grid !important;
952
952
  grid-template-columns: minmax(10rem, 14rem) minmax(0, 1fr) !important;
953
953
  align-items: start !important;
@@ -955,45 +955,50 @@ main {
955
955
  row-gap: 0.35rem !important;
956
956
  }
957
957
 
958
- [data-svadmin-form-settings] [data-svadmin-field] > [data-svadmin-field-label] {
958
+ .layout-clean-flat [data-svadmin-form-settings] [data-svadmin-field] > [data-svadmin-field-label] {
959
959
  padding-top: 0.8rem !important;
960
960
  }
961
961
 
962
- [data-svadmin-form-settings] [data-svadmin-field] > :not([data-svadmin-field-label]) {
962
+ .layout-clean-flat [data-svadmin-form-settings] [data-svadmin-field] > :not([data-svadmin-field-label]) {
963
963
  grid-column: 2 !important;
964
964
  }
965
965
  }
966
966
 
967
- .dark [data-svadmin-table-head] [data-slot="table-head"] {
967
+ .dark.layout-clean-flat [data-svadmin-table-head] [data-slot="table-head"],
968
+ .dark .layout-clean-flat [data-svadmin-table-head] [data-slot="table-head"] {
968
969
  background: #1a1a27 !important;
969
970
  border-bottom-color: #2b2b40 !important;
970
971
  color: #a1a5b7 !important;
971
972
  }
972
973
 
973
- .dark [data-svadmin-table-row] {
974
+ .dark.layout-clean-flat [data-svadmin-table-row],
975
+ .dark .layout-clean-flat [data-svadmin-table-row] {
974
976
  border-bottom-color: rgba(43, 43, 64, 0.82) !important;
975
977
  }
976
978
 
977
- .dark [data-svadmin-table-row] [data-slot="table-cell"] {
979
+ .dark.layout-clean-flat [data-svadmin-table-row] [data-slot="table-cell"],
980
+ .dark .layout-clean-flat [data-svadmin-table-row] [data-slot="table-cell"] {
978
981
  color: #a1a5b7 !important;
979
982
  }
980
983
 
981
- .dark [data-svadmin-table-row]:hover [data-slot="table-cell"] {
984
+ .dark.layout-clean-flat [data-svadmin-table-row]:hover [data-slot="table-cell"],
985
+ .dark .layout-clean-flat [data-svadmin-table-row]:hover [data-slot="table-cell"] {
982
986
  background: rgba(43, 43, 64, 0.32) !important;
983
987
  }
984
988
 
985
- .dark [data-svadmin-form-row] {
989
+ .dark.layout-clean-flat [data-svadmin-form-row],
990
+ .dark .layout-clean-flat [data-svadmin-form-row] {
986
991
  border-bottom-color: rgba(43, 43, 64, 0.82);
987
992
  }
988
993
 
989
994
  /* ─── Flat workspace redesign pass: non-sidebar pages ─── */
990
- .layout-clean-flat main {
995
+ .layout-clean-flat [data-svadmin-main] {
991
996
  background:
992
997
  linear-gradient(180deg, color-mix(in oklch, var(--background) 86%, white) 0%, var(--background) 34rem),
993
998
  var(--background) !important;
994
999
  }
995
1000
 
996
- .layout-clean-flat main > div {
1001
+ .layout-clean-flat [data-svadmin-main] > div {
997
1002
  min-width: 0 !important;
998
1003
  }
999
1004
 
@@ -1024,86 +1029,86 @@ main {
1024
1029
  min-width: 0 !important;
1025
1030
  }
1026
1031
 
1027
- .layout-clean-flat main section,
1028
- .layout-clean-flat main [class*="grid"],
1029
- .layout-clean-flat main [class*="flex"],
1030
- .layout-clean-flat main [data-slot="card-content"] {
1032
+ .layout-clean-flat [data-svadmin-main] section,
1033
+ .layout-clean-flat [data-svadmin-main] [class*="grid"],
1034
+ .layout-clean-flat [data-svadmin-main] [class*="flex"],
1035
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-content"] {
1031
1036
  min-width: 0;
1032
1037
  }
1033
1038
 
1034
- .layout-clean-flat main h1,
1035
- .layout-clean-flat main h2,
1036
- .layout-clean-flat main h3,
1037
- .layout-clean-flat main p,
1038
- .layout-clean-flat main [data-slot="badge"] {
1039
+ .layout-clean-flat [data-svadmin-main] h1,
1040
+ .layout-clean-flat [data-svadmin-main] h2,
1041
+ .layout-clean-flat [data-svadmin-main] h3,
1042
+ .layout-clean-flat [data-svadmin-main] p,
1043
+ .layout-clean-flat [data-svadmin-main] [data-slot="badge"] {
1039
1044
  max-width: 100%;
1040
1045
  }
1041
1046
 
1042
- .layout-clean-flat main h1,
1043
- .layout-clean-flat main h2,
1044
- .layout-clean-flat main h3,
1045
- .layout-clean-flat main [data-slot="card-title"] {
1047
+ .layout-clean-flat [data-svadmin-main] h1,
1048
+ .layout-clean-flat [data-svadmin-main] h2,
1049
+ .layout-clean-flat [data-svadmin-main] h3,
1050
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-title"] {
1046
1051
  overflow-wrap: anywhere;
1047
1052
  }
1048
1053
 
1049
- .layout-clean-flat main p,
1050
- .layout-clean-flat main [data-slot="card-description"] {
1054
+ .layout-clean-flat [data-svadmin-main] p,
1055
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-description"] {
1051
1056
  overflow-wrap: break-word;
1052
1057
  }
1053
1058
 
1054
- .layout-clean-flat main > div[class*="space-y"] > section:first-child {
1059
+ .layout-clean-flat [data-svadmin-main] > div[class*="space-y"] > section:first-child {
1055
1060
  border-radius: 0 !important;
1056
1061
  background: transparent !important;
1057
1062
  }
1058
1063
 
1059
- .layout-clean-flat main > div[class*="space-y"] > section:first-child [data-slot="card"],
1060
- .layout-clean-flat main > div[class*="space-y"] > section:first-child + [class*="grid"] [data-slot="card"],
1061
- .layout-clean-flat main [data-svadmin-ops-hero] [data-slot="card"] {
1064
+ .layout-clean-flat [data-svadmin-main] > div[class*="space-y"] > section:first-child [data-slot="card"],
1065
+ .layout-clean-flat [data-svadmin-main] > div[class*="space-y"] > section:first-child + [class*="grid"] [data-slot="card"],
1066
+ .layout-clean-flat [data-svadmin-main] [data-svadmin-ops-hero] [data-slot="card"] {
1062
1067
  background: transparent !important;
1063
1068
  border-color: color-mix(in oklch, var(--border) 72%, transparent) !important;
1064
1069
  box-shadow: none !important;
1065
1070
  }
1066
1071
 
1067
- .layout-clean-flat main > div[class*="space-y"] > section:first-child [data-slot="card"]:has([data-slot="card"]),
1068
- .layout-clean-flat main [data-slot="card"]:has(> [data-slot="card-content"] [data-svadmin-table-card]) {
1072
+ .layout-clean-flat [data-svadmin-main] > div[class*="space-y"] > section:first-child [data-slot="card"]:has([data-slot="card"]),
1073
+ .layout-clean-flat [data-svadmin-main] [data-slot="card"]:has(> [data-slot="card-content"] [data-svadmin-table-card]) {
1069
1074
  border: 0 !important;
1070
1075
  background: transparent !important;
1071
1076
  padding: 0 !important;
1072
1077
  }
1073
1078
 
1074
- .layout-clean-flat main [data-slot="card"] [data-slot="card"] {
1079
+ .layout-clean-flat [data-svadmin-main] [data-slot="card"] [data-slot="card"] {
1075
1080
  background: color-mix(in oklch, var(--card) 88%, var(--background)) !important;
1076
1081
  border-color: color-mix(in oklch, var(--border) 70%, transparent) !important;
1077
1082
  }
1078
1083
 
1079
- .layout-clean-flat main [data-slot="card-content"] > .flex,
1080
- .layout-clean-flat main [data-slot="card-content"] > .grid {
1084
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-content"] > .flex,
1085
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-content"] > .grid {
1081
1086
  min-width: 0;
1082
1087
  }
1083
1088
 
1084
- .layout-clean-flat main [data-slot="card-content"] span[class*="h-10"][class*="w-10"],
1085
- .layout-clean-flat main [data-slot="card-content"] span[class*="h-11"][class*="w-11"],
1086
- .layout-clean-flat main [data-slot="card-content"] span[class*="h-12"][class*="w-12"] {
1089
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-content"] span[class*="h-10"][class*="w-10"],
1090
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-content"] span[class*="h-11"][class*="w-11"],
1091
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-content"] span[class*="h-12"][class*="w-12"] {
1087
1092
  flex-shrink: 0;
1088
1093
  }
1089
1094
 
1090
- .layout-clean-flat main [data-slot="card-content"] [class*="text-2xl"],
1091
- .layout-clean-flat main [data-slot="card-content"] [class*="text-3xl"] {
1095
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-content"] [class*="text-2xl"],
1096
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-content"] [class*="text-3xl"] {
1092
1097
  line-height: 1.12;
1093
1098
  }
1094
1099
 
1095
- .layout-clean-flat main [data-slot="badge"] {
1100
+ .layout-clean-flat [data-svadmin-main] [data-slot="badge"] {
1096
1101
  overflow: hidden;
1097
1102
  text-overflow: ellipsis;
1098
1103
  white-space: nowrap;
1099
1104
  }
1100
1105
 
1101
- .layout-clean-flat main [data-slot="tabs-list"] {
1106
+ .layout-clean-flat [data-svadmin-main] [data-slot="tabs-list"] {
1102
1107
  min-width: 0;
1103
1108
  border-radius: 0.5rem !important;
1104
1109
  }
1105
1110
 
1106
- .layout-clean-flat main [data-slot="tabs-trigger"] {
1111
+ .layout-clean-flat [data-svadmin-main] [data-slot="tabs-trigger"] {
1107
1112
  min-width: 0;
1108
1113
  overflow: hidden;
1109
1114
  text-overflow: ellipsis;
@@ -1193,29 +1198,29 @@ main {
1193
1198
  }
1194
1199
 
1195
1200
  @media (max-width: 767px) {
1196
- .layout-clean-flat main {
1201
+ .layout-clean-flat [data-svadmin-main] {
1197
1202
  padding-left: 1rem !important;
1198
1203
  padding-right: 1rem !important;
1199
1204
  }
1200
1205
 
1201
- .layout-clean-flat main h1 {
1206
+ .layout-clean-flat [data-svadmin-main] h1 {
1202
1207
  font-size: clamp(1.75rem, 1.55rem + 1vw, 2.125rem) !important;
1203
1208
  }
1204
1209
 
1205
- .layout-clean-flat main [data-slot="card"] {
1210
+ .layout-clean-flat [data-svadmin-main] [data-slot="card"] {
1206
1211
  border-left: 1px solid color-mix(in oklch, var(--border) 72%, transparent) !important;
1207
1212
  border-right: 1px solid color-mix(in oklch, var(--border) 72%, transparent) !important;
1208
1213
  border-radius: 0.5rem !important;
1209
1214
  }
1210
1215
 
1211
- .layout-clean-flat main [data-slot="card-header"],
1212
- .layout-clean-flat main [data-slot="card-content"],
1213
- .layout-clean-flat main [data-slot="card-footer"] {
1216
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-header"],
1217
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-content"],
1218
+ .layout-clean-flat [data-svadmin-main] [data-slot="card-footer"] {
1214
1219
  padding-left: 1rem !important;
1215
1220
  padding-right: 1rem !important;
1216
1221
  }
1217
1222
 
1218
- .layout-clean-flat main > div[class*="space-y"] > section:first-child {
1223
+ .layout-clean-flat [data-svadmin-main] > div[class*="space-y"] > section:first-child {
1219
1224
  padding-bottom: 1rem !important;
1220
1225
  }
1221
1226
 
@@ -1254,14 +1259,14 @@ main {
1254
1259
  }
1255
1260
 
1256
1261
  @media (min-width: 768px) and (max-width: 1023px) {
1257
- .layout-clean-flat main [class*="md:grid-cols"],
1258
- .layout-clean-flat main [class*="lg:grid-cols"],
1259
- .layout-clean-flat main [class*="xl:grid-cols"] {
1262
+ .layout-clean-flat [data-svadmin-main] [class*="md:grid-cols"],
1263
+ .layout-clean-flat [data-svadmin-main] [class*="lg:grid-cols"],
1264
+ .layout-clean-flat [data-svadmin-main] [class*="xl:grid-cols"] {
1260
1265
  grid-template-columns: minmax(0, 1fr) !important;
1261
1266
  }
1262
1267
 
1263
- .layout-clean-flat main [class*="lg:flex-row"],
1264
- .layout-clean-flat main [class*="xl:flex-row"] {
1268
+ .layout-clean-flat [data-svadmin-main] [class*="lg:flex-row"],
1269
+ .layout-clean-flat [data-svadmin-main] [class*="xl:flex-row"] {
1265
1270
  flex-direction: column !important;
1266
1271
  align-items: stretch !important;
1267
1272
  }
@@ -200,8 +200,7 @@
200
200
  const routerState = provideRouterState(untrack(() => resolvedRouter));
201
201
  const scopedRouterProvider: RouterProvider = {
202
202
  go(options) {
203
- resolvedRouter.go(options);
204
- routerState.sync();
203
+ return navigateAfterAuthCheck(options);
205
204
  },
206
205
  back() {
207
206
  resolvedRouter.back();
@@ -303,9 +302,8 @@
303
302
  // Reactive getters for route state
304
303
  const route = $derived(routerState.route);
305
304
  const params = $derived(routerState.params);
305
+ const path = $derived(routerState.path);
306
306
  const resourceNames = $derived(new Set(resources.map((resource) => resource.name)));
307
- const hasRouteResource = $derived(!params.resource || resourceNames.has(params.resource));
308
- const currentResourcePages = $derived(params.resource ? resourcePages?.[params.resource] : undefined);
309
307
  const isStandaloneTwoFactor = $derived(route === '/2fa' || route === '/authentication/branded/2fa');
310
308
  const standaloneErrorStatus = $derived.by((): '404' | '500' | undefined => {
311
309
  if (route === '/authentication/error-404' || route === '/404' || (route === '/:resource' && params.resource === '404')) return '404';
@@ -316,9 +314,82 @@
316
314
  // Auth check
317
315
  let isAuthenticated = $state(untrack(() => !resolvedAuthProvider));
318
316
  let authChecked = $state(untrack(() => !resolvedAuthProvider));
317
+ let checkedAuthProvider = $state.raw<AuthProvider | null>(null);
318
+ let checkedAuthPath = $state<string | null>(null);
319
+ let navigationAuthPending = $state(false);
320
+ let navigationCheckId = 0;
321
+ const authProviderPending = $derived(!!resolvedAuthProvider && checkedAuthProvider !== resolvedAuthProvider);
322
+ const authRechecking = $derived(
323
+ navigationAuthPending
324
+ || (!!resolvedAuthProvider
325
+ && !authProviderPending
326
+ && authChecked
327
+ && isAuthenticated
328
+ && checkedAuthPath !== path),
329
+ );
330
+ const renderedRoute = $derived(route);
331
+ const renderedParams = $derived(params);
332
+ const renderedHasRouteResource = $derived(!renderedParams.resource || resourceNames.has(renderedParams.resource));
333
+ const renderedResourcePages = $derived(renderedParams.resource ? resourcePages?.[renderedParams.resource] : undefined);
334
+
335
+ async function navigateWithinApp(path: string, options?: { replaceState?: boolean }) {
336
+ await adminContext.navigate(path, options);
337
+ }
338
+
339
+ async function commitNavigation(options: Parameters<RouterProvider['go']>[0]): Promise<Awaited<ReturnType<RouterProvider['go']>>> {
340
+ const navigated = await resolvedRouter.go(options);
341
+ if (navigated === false) return false;
342
+ routerState.sync();
343
+ return navigated;
344
+ }
345
+
346
+ function recordCheckedRoute(provider: AuthProvider) {
347
+ checkedAuthProvider = provider;
348
+ checkedAuthPath = routerState.path;
349
+ }
350
+
351
+ async function navigateAfterAuthCheck(options: Parameters<RouterProvider['go']>[0]): Promise<Awaited<ReturnType<RouterProvider['go']>>> {
352
+ const provider = resolvedAuthProvider;
353
+ if (!provider || checkedAuthProvider !== provider || !authChecked || !isAuthenticated) {
354
+ return commitNavigation(options);
355
+ }
356
+
357
+ const checkId = ++navigationCheckId;
358
+ navigationAuthPending = true;
359
+ let result: Awaited<ReturnType<AuthProvider['check']>>;
360
+ try {
361
+ result = await provider.check();
362
+ } catch (err) {
363
+ if (checkId !== navigationCheckId || provider !== resolvedAuthProvider) return false;
364
+ console.warn('Auth check failed:', err);
365
+ isAuthenticated = false;
366
+ authChecked = true;
367
+ try {
368
+ await navigateWithinApp('/login', { replaceState: true });
369
+ recordCheckedRoute(provider);
370
+ return false;
371
+ } finally {
372
+ if (checkId === navigationCheckId) navigationAuthPending = false;
373
+ }
374
+ }
319
375
 
320
- async function navigateWithinApp(path: string) {
321
- await adminContext.navigate(path);
376
+ if (checkId !== navigationCheckId || provider !== resolvedAuthProvider) return false;
377
+ try {
378
+ if (!result.authenticated) {
379
+ isAuthenticated = false;
380
+ authChecked = true;
381
+ await navigateWithinApp(result.redirectTo ?? '/login', { replaceState: true });
382
+ recordCheckedRoute(provider);
383
+ return false;
384
+ }
385
+ const navigated = await commitNavigation(options);
386
+ if (navigated === false) return false;
387
+ if (checkId !== navigationCheckId || provider !== resolvedAuthProvider) return false;
388
+ recordCheckedRoute(provider);
389
+ return navigated;
390
+ } finally {
391
+ if (checkId === navigationCheckId) navigationAuthPending = false;
392
+ }
322
393
  }
323
394
 
324
395
  function isPublicSystemRoute(currentRoute: string): boolean {
@@ -332,19 +403,35 @@
332
403
  let cancelled = false;
333
404
  // Explicitly track route so auth is re-checked on navigation
334
405
  const _route = route;
406
+ const _path = path;
407
+ const provider = resolvedAuthProvider;
408
+ navigationCheckId += 1;
409
+ navigationAuthPending = false;
335
410
 
336
- if (!resolvedAuthProvider) {
411
+ if (!provider) {
337
412
  if (!cancelled) {
338
413
  isAuthenticated = true;
339
414
  authChecked = true;
415
+ checkedAuthProvider = null;
416
+ checkedAuthPath = _path;
340
417
  }
341
418
  return;
342
419
  }
343
- authChecked = false;
344
- resolvedAuthProvider.check().then(result => {
420
+ if (
421
+ untrack(() => checkedAuthProvider) === provider
422
+ && untrack(() => checkedAuthPath) === _path
423
+ ) return;
424
+ const providerChanged = untrack(() => checkedAuthProvider) !== provider;
425
+ if (providerChanged) {
426
+ isAuthenticated = false;
427
+ authChecked = false;
428
+ }
429
+ provider.check().then(result => {
345
430
  if (cancelled) return;
346
431
  isAuthenticated = result.authenticated;
347
432
  authChecked = true;
433
+ checkedAuthProvider = provider;
434
+ checkedAuthPath = _path;
348
435
  if (!result.authenticated && _route !== '/login' && _route !== '/register' && _route !== '/forgot-password' && _route !== '/update-password' && !isPublicSystemRoute(_route)) {
349
436
  void navigateWithinApp(result.redirectTo ?? '/login');
350
437
  }
@@ -353,6 +440,8 @@
353
440
  console.warn('Auth check failed:', err);
354
441
  isAuthenticated = false;
355
442
  authChecked = true;
443
+ checkedAuthProvider = provider;
444
+ checkedAuthPath = _path;
356
445
  if (_route !== '/login' && _route !== '/register' && _route !== '/forgot-password' && _route !== '/update-password' && !isPublicSystemRoute(_route)) {
357
446
  void navigateWithinApp('/login');
358
447
  }
@@ -365,7 +454,7 @@
365
454
  <QueryClientProvider client={queryClient}>
366
455
  {#if !resolvedDataProvider}
367
456
  <ConfigErrorScreen title="{title} — DataProvider is required" />
368
- {:else if !authChecked}
457
+ {:else if !authChecked || authProviderPending}
369
458
  <div class="flex h-screen items-center justify-center">
370
459
  <div class="space-y-4 text-center">
371
460
  <div class="h-8 w-8 animate-spin rounded-full border-4 border-muted border-t-primary mx-auto"></div>
@@ -390,7 +479,7 @@
390
479
  <UpdatePasswordPage {title} />
391
480
  {:else if route === '/login' || route === '/register' || route === '/forgot-password' || route === '/update-password'}
392
481
  <ConfigErrorScreen title="{title} — {translation.t('common.configRequired')}" />
393
- {:else if (isAuthenticated || !resolvedAuthProvider) && isStandaloneTwoFactor}
482
+ {:else if (isAuthenticated || !resolvedAuthProvider) && isStandaloneTwoFactor && !authRechecking}
394
483
  <SystemPageShell {title}>
395
484
  <LazyPage loader={loadTwoFactorAuthPage} props={{}} />
396
485
  </SystemPageShell>
@@ -401,47 +490,56 @@
401
490
  </SystemPageShell>
402
491
  {:else if isAuthenticated || !resolvedAuthProvider}
403
492
  <Layout {title} {menu} {siteUrl} routeMode={resolvedRouteMode}>
404
- {#key route + (params.resource ?? '') + (params.id ?? '') + (params.variant ?? '') + (params.columns ?? '')}
493
+ <div class="relative min-h-40" aria-busy={authRechecking}>
494
+ {#if authRechecking}
495
+ <div class="absolute inset-0 z-10 flex min-h-40 items-center justify-center bg-background/80" role="status" aria-live="polite">
496
+ <div class="space-y-3 text-center">
497
+ <div class="h-6 w-6 animate-spin rounded-full border-4 border-muted border-t-primary mx-auto"></div>
498
+ <p class="text-sm text-muted-foreground">Loading...</p>
499
+ </div>
500
+ </div>
501
+ {:else}
502
+ {#key renderedRoute + (renderedParams.resource ?? '') + (renderedParams.id ?? '') + (renderedParams.variant ?? '') + (renderedParams.columns ?? '')}
405
503
  <div class="svadmin-page-enter">
406
- {#if route === '/public-profile'}
504
+ {#if renderedRoute === '/public-profile'}
407
505
  <LazyPage loader={loadPublicProfilePage} props={{ variant: 'default', initialTab: 'projects' }} />
408
- {:else if route === '/public-profile/projects/:columns'}
409
- <LazyPage loader={loadPublicProfilePage} props={{ variant: 'default', initialTab: 'projects', columns: params.columns?.includes('3') ? 3 : 2 }} />
410
- {:else if route === '/public-profile/activity'}
506
+ {:else if renderedRoute === '/public-profile/projects/:columns'}
507
+ <LazyPage loader={loadPublicProfilePage} props={{ variant: 'default', initialTab: 'projects', columns: renderedParams.columns?.includes('3') ? 3 : 2 }} />
508
+ {:else if renderedRoute === '/public-profile/activity'}
411
509
  <LazyPage loader={loadPublicProfilePage} props={{ variant: 'default', initialTab: 'activity' }} />
412
- {:else if route === '/public-profile/teams'}
510
+ {:else if renderedRoute === '/public-profile/teams'}
413
511
  <LazyPage loader={loadPublicProfilePage} props={{ variant: 'default', initialTab: 'teams' }} />
414
- {:else if route === '/public-profile/profiles/:variant'}
415
- <LazyPage loader={loadPublicProfilePage} props={{ variant: (params.variant === 'company' || params.variant === 'gamer' || params.variant === 'default' ? params.variant : 'default') as 'company' | 'gamer' | 'default', showSections: true }} />
416
- {:else if route === '/account/get-started' || route === '/account/home/get-started'}
512
+ {:else if renderedRoute === '/public-profile/profiles/:variant'}
513
+ <LazyPage loader={loadPublicProfilePage} props={{ variant: (renderedParams.variant === 'company' || renderedParams.variant === 'gamer' || renderedParams.variant === 'default' ? renderedParams.variant : 'default') as 'company' | 'gamer' | 'default', showSections: true }} />
514
+ {:else if renderedRoute === '/account/get-started' || renderedRoute === '/account/home/get-started'}
417
515
  <LazyPage loader={loadGetStartedPage} props={{}} />
418
- {:else if route === '/account/home/user-profile'}
516
+ {:else if renderedRoute === '/account/home/user-profile'}
419
517
  <LazyPage loader={loadUserProfilePage} props={{}} />
420
- {:else if route === '/account/company-profile' || route === '/account/home/company-profile'}
518
+ {:else if renderedRoute === '/account/company-profile' || renderedRoute === '/account/home/company-profile'}
421
519
  <LazyPage loader={loadCompanyProfilePage} props={{}} />
422
- {:else if route === '/account/settings-plain' || route === '/account/home/settings-plain'}
520
+ {:else if renderedRoute === '/account/settings-plain' || renderedRoute === '/account/home/settings-plain'}
423
521
  <LazyPage loader={loadSettingsPlainPage} props={{}} />
424
- {:else if route === '/account/settings-sidebar' || route === '/account/home/settings-sidebar'}
522
+ {:else if renderedRoute === '/account/settings-sidebar' || renderedRoute === '/account/home/settings-sidebar'}
425
523
  <LazyPage loader={loadSettingsSidebarPage} props={{}} />
426
- {:else if route === '/account/settings-enterprise' || route === '/account/home/settings-enterprise'}
524
+ {:else if renderedRoute === '/account/settings-enterprise' || renderedRoute === '/account/home/settings-enterprise'}
427
525
  <LazyPage loader={loadSettingsEnterprisePage} props={{}} />
428
- {:else if route === '/account/:tab'}
526
+ {:else if renderedRoute === '/account/:tab'}
429
527
  <SettingsPage />
430
- {:else if route === '/account/import-members' || route === '/account/members/import-members'}
528
+ {:else if renderedRoute === '/account/import-members' || renderedRoute === '/account/members/import-members'}
431
529
  <LazyPage loader={loadImportMembersPage} props={{}} />
432
- {:else if route === '/account/members-starter' || route === '/account/members/members-starter'}
530
+ {:else if renderedRoute === '/account/members-starter' || renderedRoute === '/account/members/members-starter'}
433
531
  <LazyPage loader={loadMembersStarterPage} props={{}} />
434
- {:else if route === '/account/team-members' || route === '/account/members/team-members'}
532
+ {:else if renderedRoute === '/account/team-members' || renderedRoute === '/account/members/team-members'}
435
533
  <LazyPage loader={loadTeamMembersPage} props={{}} />
436
- {:else if route === '/account/security-log' || route === '/account/security/security-log'}
534
+ {:else if renderedRoute === '/account/security-log' || renderedRoute === '/account/security/security-log'}
437
535
  <LazyPage loader={loadSecurityLogPage} props={{}} />
438
- {:else if route === '/network/user-cards' || route === '/network/user-cards/nft'}
536
+ {:else if renderedRoute === '/network/user-cards' || renderedRoute === '/network/user-cards/nft'}
439
537
  <LazyPage loader={loadUserCardsNFTPage} props={{}} />
440
- {:else if route === '/network/team-crew' || route === '/network/user-table/team-crew'}
538
+ {:else if renderedRoute === '/network/team-crew' || renderedRoute === '/network/user-table/team-crew'}
441
539
  <LazyPage loader={loadTeamCrewTablePage} props={{}} />
442
- {:else if route.startsWith('/settings')}
540
+ {:else if renderedRoute.startsWith('/settings')}
443
541
  <SettingsPage />
444
- {:else if route === '/' || route === '' || route === '/inventory-dashboard'}
542
+ {:else if renderedRoute === '/' || renderedRoute === '' || renderedRoute === '/inventory-dashboard'}
445
543
  {#if dashboard}
446
544
  {@render dashboard()}
447
545
  {:else}
@@ -450,30 +548,30 @@
450
548
  <p class="text-muted-foreground">{translation.t('common.dashboardHint')}</p>
451
549
  </div>
452
550
  {/if}
453
- {:else if (route === '/:resource' || route === '/:parent/:parentId/:resource') && hasRouteResource}
454
- {#key params.resource}
455
- {@const Comp = currentResourcePages?.list ?? mergedComponents.AutoTable}
456
- <Comp resourceName={params.resource} />
551
+ {:else if (renderedRoute === '/:resource' || renderedRoute === '/:parent/:parentId/:resource') && renderedHasRouteResource}
552
+ {#key renderedParams.resource}
553
+ {@const Comp = renderedResourcePages?.list ?? mergedComponents.AutoTable}
554
+ <Comp resourceName={renderedParams.resource} />
457
555
  {/key}
458
- {:else if (route === '/:resource/create' || route === '/:parent/:parentId/:resource/create') && hasRouteResource}
459
- {#key params.resource}
460
- {@const Comp = currentResourcePages?.create ?? mergedComponents.AutoForm}
461
- <Comp resourceName={params.resource} mode="create" />
556
+ {:else if (renderedRoute === '/:resource/create' || renderedRoute === '/:parent/:parentId/:resource/create') && renderedHasRouteResource}
557
+ {#key renderedParams.resource}
558
+ {@const Comp = renderedResourcePages?.create ?? mergedComponents.AutoForm}
559
+ <Comp resourceName={renderedParams.resource} mode="create" />
462
560
  {/key}
463
- {:else if (route === '/:resource/edit/:id' || route === '/:parent/:parentId/:resource/edit/:id') && hasRouteResource}
464
- {#key `${params.resource}-${params.id}`}
465
- {@const Comp = currentResourcePages?.edit ?? mergedComponents.AutoForm}
466
- <Comp resourceName={params.resource} mode="edit" id={params.id} />
561
+ {:else if (renderedRoute === '/:resource/edit/:id' || renderedRoute === '/:parent/:parentId/:resource/edit/:id') && renderedHasRouteResource}
562
+ {#key `${renderedParams.resource}-${renderedParams.id}`}
563
+ {@const Comp = renderedResourcePages?.edit ?? mergedComponents.AutoForm}
564
+ <Comp resourceName={renderedParams.resource} mode="edit" id={renderedParams.id} />
467
565
  {/key}
468
- {:else if (route === '/:resource/show/:id' || route === '/:parent/:parentId/:resource/show/:id') && hasRouteResource}
469
- {#key `${params.resource}-${params.id}`}
470
- {@const Comp = currentResourcePages?.show ?? mergedComponents.ShowPage}
471
- <Comp resourceName={params.resource} id={params.id} />
566
+ {:else if (renderedRoute === '/:resource/show/:id' || renderedRoute === '/:parent/:parentId/:resource/show/:id') && renderedHasRouteResource}
567
+ {#key `${renderedParams.resource}-${renderedParams.id}`}
568
+ {@const Comp = renderedResourcePages?.show ?? mergedComponents.ShowPage}
569
+ <Comp resourceName={renderedParams.resource} id={renderedParams.id} />
472
570
  {/key}
473
- {:else if (route === '/:resource/clone/:id' || route === '/:parent/:parentId/:resource/clone/:id') && hasRouteResource}
474
- {#key `${params.resource}-clone-${params.id}`}
475
- {@const Comp = currentResourcePages?.clone ?? mergedComponents.AutoForm}
476
- <Comp resourceName={params.resource} mode="clone" id={params.id} />
571
+ {:else if (renderedRoute === '/:resource/clone/:id' || renderedRoute === '/:parent/:parentId/:resource/clone/:id') && renderedHasRouteResource}
572
+ {#key `${renderedParams.resource}-clone-${renderedParams.id}`}
573
+ {@const Comp = renderedResourcePages?.clone ?? mergedComponents.AutoForm}
574
+ <Comp resourceName={renderedParams.resource} mode="clone" id={renderedParams.id} />
477
575
  {/key}
478
576
  {:else}
479
577
  {@const ErrorComp = mergedComponents.ErrorPage || ErrorPage}
@@ -481,6 +579,8 @@
481
579
  {/if}
482
580
  </div>
483
581
  {/key}
582
+ {/if}
583
+ </div>
484
584
  </Layout>
485
585
  {:else}
486
586
  <div class="flex h-screen items-center justify-center">
@@ -201,7 +201,7 @@
201
201
 
202
202
  <!-- Content area: responsive padding + centered max-width container
203
203
  so wide screens don't stretch content indefinitely (avoids sparse layouts) -->
204
- <main class="flex-1 overflow-y-auto bg-muted/30 px-4 py-5 sm:px-5 md:px-7.5 md:py-7">
204
+ <main data-svadmin-main class="flex-1 overflow-y-auto bg-muted/30 px-4 py-5 sm:px-5 md:px-7.5 md:py-7">
205
205
  <div class="mx-auto w-full max-w-[1600px]">
206
206
  {#key getPath()}
207
207
  <div in:fly={{ x: 20, duration: 150 }} out:fade={{ duration: 80 }}>
@@ -277,6 +277,7 @@
277
277
 
278
278
 
279
279
  <aside
280
+ data-svadmin-sidebar
280
281
  aria-label="Sidebar navigation"
281
282
  class="fixed inset-y-0 left-0 z-30 flex flex-col border-r border-border/40 transition-all duration-300"
282
283
  style="background-color: var(--sidebar);"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@svadmin/ui",
3
- "version": "0.42.1",
3
+ "version": "0.42.3",
4
4
  "description": "Pre-built admin UI components — AdminApp, AutoTable, AutoForm, Sidebar, Layout",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -39,7 +39,7 @@
39
39
  "./components/*": "./dist/components/*"
40
40
  },
41
41
  "peerDependencies": {
42
- "@svadmin/core": "^0.36.1",
42
+ "@svadmin/core": "^0.36.3",
43
43
  "@tanstack/svelte-query": "^6.1.38",
44
44
  "highlight.js": "^11.11.1",
45
45
  "isomorphic-dompurify": "^3.22.0",