@visns-studio/visns-components 6.17.2 → 6.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +10 -7
- package/src/components/AssociationManager.jsx +344 -177
- package/src/components/AsyncSelect.jsx +2 -2
- package/src/components/Autocomplete.jsx +57 -12
- package/src/components/Breadcrumb.jsx +23 -4
- package/src/components/ClientAssociationManager.jsx +321 -145
- package/src/components/DataGrid.jsx +625 -20
- package/src/components/DropZone.jsx +4 -1
- package/src/components/Form.jsx +233 -6
- package/src/components/MultiSelect.jsx +2 -2
- package/src/components/Navigation.jsx +39 -23
- package/src/components/TableFilter.jsx +172 -12
- package/src/components/UniversalSearch.jsx +390 -0
- package/src/components/auth/Login.jsx +164 -8
- package/src/components/auth/Profile.jsx +209 -22
- package/src/components/auth/authEndpoints.js +4 -0
- package/src/components/auth/webauthn.js +194 -0
- package/src/components/columns/ColumnRenderers.jsx +6 -1
- package/src/components/controls/DataGridSearch.jsx +11 -5
- package/src/components/generic/GenericAuth.jsx +6 -0
- package/src/components/generic/GenericDashboard.jsx +93 -36
- package/src/components/generic/GenericDetail.jsx +146 -61
- package/src/components/generic/GenericIndex.jsx +134 -38
- package/src/components/generic/GenericSettings.jsx +220 -0
- package/src/components/generic/StandardModal.jsx +165 -8
- package/src/components/generic/dashboardChartDefaults.js +230 -0
- package/src/components/generic/shared/indexLayout.js +38 -0
- package/src/components/settings/IntegrationsManager.jsx +474 -0
- package/src/components/sms/SmsLineSettings.jsx +16 -12
- package/src/components/styles/AssociationManager.module.scss +4 -363
- package/src/components/styles/AuditLog.module.scss +6 -6
- package/src/components/styles/AuditLogs.module.scss +3 -3
- package/src/components/styles/Autocomplete.module.scss +7 -7
- package/src/components/styles/BusinessCardOcr.module.scss +6 -1
- package/src/components/styles/CallQueueSettings.module.scss +4 -1
- package/src/components/styles/CameraPlacement.module.scss +19 -19
- package/src/components/styles/CategorizedDropZone.module.scss +6 -1
- package/src/components/styles/ClientAssociationManager.module.scss +5 -289
- package/src/components/styles/ClientAuth.module.scss +1 -1
- package/src/components/styles/DataGrid.module.scss +455 -8
- package/src/components/styles/Field.module.scss +32 -24
- package/src/components/styles/Form.module.scss +123 -3
- package/src/components/styles/GenericDashboard.module.scss +612 -825
- package/src/components/styles/GenericDetail.module.scss +406 -61
- package/src/components/styles/GenericDynamic.module.scss +25 -25
- package/src/components/styles/GenericEditableTable.module.scss +33 -33
- package/src/components/styles/GenericFormBuilder.module.scss +119 -119
- package/src/components/styles/GenericIndex.module.scss +483 -38
- package/src/components/styles/GenericMain.module.scss +6 -3
- package/src/components/styles/GenericQuote.module.scss +399 -81
- package/src/components/styles/GenericReport.module.scss +8 -8
- package/src/components/styles/GenericSettings.module.scss +209 -0
- package/src/components/styles/GenericSort.module.scss +9 -9
- package/src/components/styles/Integrations.module.scss +321 -0
- package/src/components/styles/List.module.scss +4 -4
- package/src/components/styles/Login.module.scss +57 -0
- package/src/components/styles/MultiSelect.module.scss +4 -4
- package/src/components/styles/Navigation.module.scss +12 -12
- package/src/components/styles/Notification.module.scss +12 -8
- package/src/components/styles/NotificationList.module.scss +5 -5
- package/src/components/styles/Profile.module.scss +5 -5
- package/src/components/styles/QrCode.module.scss +4 -4
- package/src/components/styles/QuickAction.module.scss +20 -20
- package/src/components/styles/SortableQuoteItems.module.scss +4 -4
- package/src/components/styles/TableFilter.module.scss +128 -17
- package/src/components/styles/TicketConversation.module.scss +497 -0
- package/src/components/styles/UniversalSearch.module.scss +229 -0
- package/src/components/styles/Vault.module.scss +413 -0
- package/src/components/styles/_associationManager.scss +467 -0
- package/src/components/styles/_authBrandPanel.scss +15 -9
- package/src/components/styles/_controls.scss +43 -39
- package/src/components/styles/global-datagrid.css +196 -0
- package/src/components/styles/global.css +168 -17
- package/src/components/tickets/TicketConversation.jsx +455 -0
- package/src/components/utils/rowActionSettings.js +117 -0
- package/src/components/vault/VaultClientPicker.jsx +183 -0
- package/src/components/vault/VaultEntryForm.jsx +23 -0
- package/src/components/vault/VaultManager.jsx +382 -34
- package/src/components/vault/VaultShareModal.jsx +454 -0
- package/src/components/vault/vaultEndpoints.js +16 -2
- package/src/components/vault/vaultShares.js +247 -0
- package/src/index.js +35 -0
- package/src/utils/fetchUtil.js +38 -14
|
@@ -34,56 +34,52 @@
|
|
|
34
34
|
gap: 1rem;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
/* ----------------------------------------------------------------------------
|
|
38
|
+
The card set. Same four cards, same spec, as `GenericIndex.module.scss` —
|
|
39
|
+
see the block comment there for why they were unified. The two files carry
|
|
40
|
+
the same declarations on purpose so a detail page and an index page sit on
|
|
41
|
+
the same baseline; change one, change the other.
|
|
42
|
+
-------------------------------------------------------------------------- */
|
|
43
|
+
|
|
44
|
+
@mixin card-surface {
|
|
45
|
+
background: var(--item-color, #fff);
|
|
46
|
+
border: 1px solid var(--border-color, #e1e1e1);
|
|
47
|
+
border-radius: var(--card-radius, 10px);
|
|
48
|
+
box-shadow: var(
|
|
49
|
+
--shadow-sm,
|
|
50
|
+
0 1px 2px rgba(var(--primary-rgb, 27, 57, 51), 0.08),
|
|
51
|
+
0 2px 8px rgba(var(--primary-rgb, 27, 57, 51), 0.06)
|
|
52
|
+
);
|
|
42
53
|
box-sizing: border-box;
|
|
54
|
+
/* Load-bearing: selects, popovers and tooltips open out of these. */
|
|
43
55
|
overflow: visible;
|
|
44
56
|
position: relative;
|
|
45
|
-
padding: 20px;
|
|
46
57
|
margin: 8px 0;
|
|
47
|
-
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.grid__three {
|
|
61
|
+
@include card-surface;
|
|
62
|
+
width: 33%;
|
|
63
|
+
padding: 20px;
|
|
48
64
|
}
|
|
49
65
|
|
|
50
66
|
.grid__half {
|
|
67
|
+
@include card-surface;
|
|
51
68
|
width: 50%;
|
|
52
|
-
background: var(--item-color);
|
|
53
|
-
border-radius: 6px;
|
|
54
|
-
border: 1px solid #dadce0;
|
|
55
|
-
box-sizing: border-box;
|
|
56
|
-
overflow: visible;
|
|
57
|
-
position: relative;
|
|
58
69
|
padding: 20px;
|
|
59
|
-
margin: 8px 0;
|
|
60
|
-
box-shadow: 0 10px 50px rgba(var(--primary-rgb), 0.05);
|
|
61
70
|
}
|
|
62
71
|
|
|
63
72
|
.grid__full {
|
|
73
|
+
@include card-surface;
|
|
64
74
|
width: 100%;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
border: 1px solid rgba(var(--item-color-rgb), 1.15);
|
|
68
|
-
box-sizing: border-box;
|
|
69
|
-
overflow: visible;
|
|
70
|
-
position: relative;
|
|
71
|
-
padding: 2px;
|
|
72
|
-
margin: 8px 0;
|
|
73
|
-
box-shadow: 0 10px 50px rgba(var(--primary-rgb), 0.05);
|
|
75
|
+
/* Was 2px — see GenericIndex. */
|
|
76
|
+
padding: 0;
|
|
74
77
|
}
|
|
75
78
|
|
|
76
79
|
.grid__dashfull {
|
|
80
|
+
@include card-surface;
|
|
77
81
|
width: 100%;
|
|
78
|
-
background: var(--item-color);
|
|
79
|
-
border-radius: 6px;
|
|
80
|
-
border: 1px solid #dadce0;
|
|
81
|
-
box-sizing: border-box;
|
|
82
|
-
overflow: visible;
|
|
83
|
-
position: relative;
|
|
84
82
|
padding: 20px;
|
|
85
|
-
margin: 8px 0;
|
|
86
|
-
box-shadow: 0 10px 50px rgba(var(--primary-rgb), 0.05);
|
|
87
83
|
}
|
|
88
84
|
|
|
89
85
|
.grid__subrow {
|
|
@@ -94,10 +90,10 @@
|
|
|
94
90
|
gap: 0.5rem;
|
|
95
91
|
}
|
|
96
92
|
|
|
97
|
-
/*
|
|
98
|
-
See the note on `tabsUnderlined` in GenericDetail.jsx
|
|
99
|
-
|
|
100
|
-
|
|
93
|
+
/* The default detail-page layout: tabs above the panel rather than beside it.
|
|
94
|
+
See the note on `tabsUnderlined` in GenericDetail.jsx. The row becomes a
|
|
95
|
+
column and both children take the full width; the rail gives up its card,
|
|
96
|
+
because an underline strip is not a panel. */
|
|
101
97
|
.grid__subrow--stacked {
|
|
102
98
|
flex-direction: column;
|
|
103
99
|
flex-wrap: nowrap;
|
|
@@ -107,8 +103,13 @@
|
|
|
107
103
|
.grid__subnav--underline {
|
|
108
104
|
flex: 0 0 auto;
|
|
109
105
|
width: 100%;
|
|
106
|
+
/* `min-width: 0` is what lets the strip inside actually scroll: a flex item
|
|
107
|
+
floors at its content's min-content width by default, so a strip of ten
|
|
108
|
+
tabs would push this container — and the page — wider instead of
|
|
109
|
+
overflowing within it. */
|
|
110
|
+
min-width: 0;
|
|
110
111
|
padding: 0;
|
|
111
|
-
margin:
|
|
112
|
+
margin: 0;
|
|
112
113
|
background: none;
|
|
113
114
|
border: none;
|
|
114
115
|
border-radius: 0;
|
|
@@ -375,7 +376,7 @@
|
|
|
375
376
|
|
|
376
377
|
span {
|
|
377
378
|
font-size: 0.875em;
|
|
378
|
-
color: rgba(var(--background-color-rgb), 0.65);
|
|
379
|
+
color: rgba(var(--background-color-rgb, 255, 255, 255), 0.65);
|
|
379
380
|
}
|
|
380
381
|
}
|
|
381
382
|
|
|
@@ -533,7 +534,7 @@
|
|
|
533
534
|
display: flex;
|
|
534
535
|
align-items: center;
|
|
535
536
|
justify-content: space-between;
|
|
536
|
-
background: rgba(var(--primary-rgb), 0.05);
|
|
537
|
+
background: rgba(var(--primary-rgb, 27, 57, 51), 0.05);
|
|
537
538
|
color: var(--primary-color);
|
|
538
539
|
border-radius: 6px;
|
|
539
540
|
transition: all 0.2s ease;
|
|
@@ -541,7 +542,7 @@
|
|
|
541
542
|
padding: 12px 16px;
|
|
542
543
|
box-sizing: border-box;
|
|
543
544
|
position: relative;
|
|
544
|
-
border: 1px solid rgba(var(--primary-rgb), 0.15);
|
|
545
|
+
border: 1px solid rgba(var(--primary-rgb, 27, 57, 51), 0.15);
|
|
545
546
|
line-height: 1.4;
|
|
546
547
|
font-size: 0.9rem;
|
|
547
548
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
|
@@ -549,7 +550,7 @@
|
|
|
549
550
|
&:hover {
|
|
550
551
|
transform: translateY(-2px);
|
|
551
552
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
|
552
|
-
background: rgba(var(--primary-rgb), 0.08);
|
|
553
|
+
background: rgba(var(--primary-rgb, 27, 57, 51), 0.08);
|
|
553
554
|
}
|
|
554
555
|
|
|
555
556
|
.file-info {
|
|
@@ -580,7 +581,7 @@
|
|
|
580
581
|
|
|
581
582
|
.file-size {
|
|
582
583
|
font-size: 0.75rem;
|
|
583
|
-
color: rgba(var(--primary-rgb), 0.7);
|
|
584
|
+
color: rgba(var(--primary-rgb, 27, 57, 51), 0.7);
|
|
584
585
|
margin-top: 2px;
|
|
585
586
|
font-weight: 400;
|
|
586
587
|
}
|
|
@@ -601,7 +602,7 @@
|
|
|
601
602
|
transition: background-color 0.2s ease;
|
|
602
603
|
|
|
603
604
|
&:hover {
|
|
604
|
-
background-color: rgba(var(--primary-rgb), 0.1);
|
|
605
|
+
background-color: rgba(var(--primary-rgb, 27, 57, 51), 0.1);
|
|
605
606
|
}
|
|
606
607
|
|
|
607
608
|
svg {
|
|
@@ -729,7 +730,7 @@
|
|
|
729
730
|
width: auto;
|
|
730
731
|
margin: 0;
|
|
731
732
|
padding: 0 2em;
|
|
732
|
-
border-right: 1px solid rgba(var(--primary-rgb), 0.35);
|
|
733
|
+
border-right: 1px solid rgba(var(--primary-rgb, 27, 57, 51), 0.35);
|
|
733
734
|
|
|
734
735
|
&:first-child {
|
|
735
736
|
padding-left: 0;
|
|
@@ -741,7 +742,7 @@
|
|
|
741
742
|
|
|
742
743
|
span {
|
|
743
744
|
display: block;
|
|
744
|
-
color: rgba(var(--primary-rgb), 0.7);
|
|
745
|
+
color: rgba(var(--primary-rgb, 27, 57, 51), 0.7);
|
|
745
746
|
}
|
|
746
747
|
}
|
|
747
748
|
}
|
|
@@ -944,7 +945,7 @@
|
|
|
944
945
|
.schedulingTable td {
|
|
945
946
|
padding: 0.75rem;
|
|
946
947
|
text-align: left;
|
|
947
|
-
border: 1px solid rgba(var(--primary-rgb), 0.1);
|
|
948
|
+
border: 1px solid rgba(var(--primary-rgb, 27, 57, 51), 0.1);
|
|
948
949
|
}
|
|
949
950
|
|
|
950
951
|
.schedulingTable th {
|
|
@@ -954,11 +955,11 @@
|
|
|
954
955
|
}
|
|
955
956
|
|
|
956
957
|
.schedulingTable td {
|
|
957
|
-
background-color: rgba(var(--primary-rgb), 0.05);
|
|
958
|
+
background-color: rgba(var(--primary-rgb, 27, 57, 51), 0.05);
|
|
958
959
|
}
|
|
959
960
|
|
|
960
961
|
.categoryRow {
|
|
961
|
-
background-color: rgba(var(--primary-rgb), 0.1);
|
|
962
|
+
background-color: rgba(var(--primary-rgb, 27, 57, 51), 0.1);
|
|
962
963
|
text-align: left;
|
|
963
964
|
font-weight: bold;
|
|
964
965
|
font-size: 1.2rem;
|
|
@@ -966,7 +967,7 @@
|
|
|
966
967
|
}
|
|
967
968
|
|
|
968
969
|
.totalRow {
|
|
969
|
-
background-color: rgba(var(--primary-rgb), 0.05);
|
|
970
|
+
background-color: rgba(var(--primary-rgb, 27, 57, 51), 0.05);
|
|
970
971
|
font-weight: bold;
|
|
971
972
|
text-align: right;
|
|
972
973
|
}
|
|
@@ -976,7 +977,7 @@
|
|
|
976
977
|
height: 14px !important;
|
|
977
978
|
border-radius: 4px;
|
|
978
979
|
background-color: var(--item-color);
|
|
979
|
-
border: 2px solid rgba(var(--primary-rgb), 0.15);
|
|
980
|
+
border: 2px solid rgba(var(--primary-rgb, 27, 57, 51), 0.15);
|
|
980
981
|
position: relative;
|
|
981
982
|
cursor: pointer;
|
|
982
983
|
transition: background-color 0.3s, border-color 0.3s;
|
|
@@ -989,13 +990,13 @@
|
|
|
989
990
|
|
|
990
991
|
.schedulingTable td input[type='checkbox']:focus {
|
|
991
992
|
outline: none;
|
|
992
|
-
box-shadow: 0 0 0 2px rgba(var(--primary-rgb), 0.2);
|
|
993
|
+
box-shadow: 0 0 0 2px rgba(var(--primary-rgb, 27, 57, 51), 0.2);
|
|
993
994
|
}
|
|
994
995
|
|
|
995
996
|
/* Custom hover effect for better user experience */
|
|
996
997
|
.schedulingTable td input[type='checkbox']:hover {
|
|
997
|
-
background-color: rgba(var(--primary-rgb), 0.1);
|
|
998
|
-
border-color: rgba(var(--primary-rgb), 0.25);
|
|
998
|
+
background-color: rgba(var(--primary-rgb, 27, 57, 51), 0.1);
|
|
999
|
+
border-color: rgba(var(--primary-rgb, 27, 57, 51), 0.25);
|
|
999
1000
|
}
|
|
1000
1001
|
|
|
1001
1002
|
.noDataMessage {
|
|
@@ -1015,15 +1016,15 @@
|
|
|
1015
1016
|
/* Enhanced JSON Rendering Styles */
|
|
1016
1017
|
.jsonQuestionAnswer {
|
|
1017
1018
|
padding: 0.75rem;
|
|
1018
|
-
background: rgba(var(--primary-rgb), 0.02);
|
|
1019
|
+
background: rgba(var(--primary-rgb, 27, 57, 51), 0.02);
|
|
1019
1020
|
border-radius: 4px;
|
|
1020
|
-
border: 1px solid rgba(var(--primary-rgb), 0.08);
|
|
1021
|
+
border: 1px solid rgba(var(--primary-rgb, 27, 57, 51), 0.08);
|
|
1021
1022
|
}
|
|
1022
1023
|
|
|
1023
1024
|
.questionAnswerPair {
|
|
1024
1025
|
margin-bottom: 1rem;
|
|
1025
1026
|
padding: 0.75rem;
|
|
1026
|
-
background: rgba(var(--primary-rgb), 0.01);
|
|
1027
|
+
background: rgba(var(--primary-rgb, 27, 57, 51), 0.01);
|
|
1027
1028
|
border-radius: 4px;
|
|
1028
1029
|
border-left: 3px solid var(--secondary-color);
|
|
1029
1030
|
|
|
@@ -1051,15 +1052,15 @@
|
|
|
1051
1052
|
|
|
1052
1053
|
.jsonKeyValue {
|
|
1053
1054
|
padding: 0.75rem;
|
|
1054
|
-
background: rgba(var(--primary-rgb), 0.02);
|
|
1055
|
+
background: rgba(var(--primary-rgb, 27, 57, 51), 0.02);
|
|
1055
1056
|
border-radius: 4px;
|
|
1056
|
-
border: 1px solid rgba(var(--primary-rgb), 0.08);
|
|
1057
|
+
border: 1px solid rgba(var(--primary-rgb, 27, 57, 51), 0.08);
|
|
1057
1058
|
}
|
|
1058
1059
|
|
|
1059
1060
|
.keyValuePair {
|
|
1060
1061
|
margin-bottom: 0.6rem;
|
|
1061
1062
|
padding: 0.5rem;
|
|
1062
|
-
background: rgba(var(--primary-rgb), 0.01);
|
|
1063
|
+
background: rgba(var(--primary-rgb, 27, 57, 51), 0.01);
|
|
1063
1064
|
border-radius: 3px;
|
|
1064
1065
|
display: flex;
|
|
1065
1066
|
gap: 0.5rem;
|
|
@@ -1077,8 +1078,8 @@
|
|
|
1077
1078
|
}
|
|
1078
1079
|
|
|
1079
1080
|
.jsonRaw {
|
|
1080
|
-
background: rgba(var(--primary-rgb), 0.03);
|
|
1081
|
-
border: 1px solid rgba(var(--primary-rgb), 0.1);
|
|
1081
|
+
background: rgba(var(--primary-rgb, 27, 57, 51), 0.03);
|
|
1082
|
+
border: 1px solid rgba(var(--primary-rgb, 27, 57, 51), 0.1);
|
|
1082
1083
|
border-radius: 4px;
|
|
1083
1084
|
padding: 0.75rem;
|
|
1084
1085
|
font-family: monospace;
|
|
@@ -1217,3 +1218,347 @@
|
|
|
1217
1218
|
position: relative;
|
|
1218
1219
|
}
|
|
1219
1220
|
|
|
1221
|
+
|
|
1222
|
+
/* ==========================================================================
|
|
1223
|
+
2026 pass — the detail page
|
|
1224
|
+
--------------------------------------------------------------------------
|
|
1225
|
+
Appended, so these are targeted overrides of the rules above and the cascade
|
|
1226
|
+
order is doing real work.
|
|
1227
|
+
|
|
1228
|
+
The 6.15 overview rework (label-above-value pairs on a real two-column grid,
|
|
1229
|
+
a muted dash for an empty field) stands and is not touched. What is dated is
|
|
1230
|
+
everything around it: the title in its own white slab, `--br` corners at 5px
|
|
1231
|
+
when every other surface in the app is now 12-14px, no elevation at all, and
|
|
1232
|
+
a floating action bar that hangs over the page with no ground of its own.
|
|
1233
|
+
========================================================================== */
|
|
1234
|
+
|
|
1235
|
+
.grid__subrow,
|
|
1236
|
+
.grid__subrow--stacked {
|
|
1237
|
+
--gd-surface: var(--background-color, #fff);
|
|
1238
|
+
--gd-ink: var(--paragraph-color, #2b2b2b);
|
|
1239
|
+
/* The three below defer to the app's own tokens first so a detail panel,
|
|
1240
|
+
an index card and the data grid all draw the SAME hairline, the same
|
|
1241
|
+
corner and the same lift. The local expressions stay as fallbacks for a
|
|
1242
|
+
host that declares none of them. */
|
|
1243
|
+
--gd-line: var(
|
|
1244
|
+
--border-color,
|
|
1245
|
+
color-mix(in srgb, var(--gd-ink) 12%, transparent)
|
|
1246
|
+
);
|
|
1247
|
+
--gd-muted: color-mix(in srgb, var(--gd-ink) 62%, transparent);
|
|
1248
|
+
--gd-quiet: color-mix(in srgb, var(--gd-ink) 3%, var(--gd-surface));
|
|
1249
|
+
--gd-radius: var(--detail-card-radius, var(--card-radius, 14px));
|
|
1250
|
+
--gd-motion: var(--speed, 160ms) var(--ease, cubic-bezier(0.4, 0, 0.2, 1));
|
|
1251
|
+
/* One contact shadow plus one ambient — a single large blur reads as a
|
|
1252
|
+
smudge rather than as a raised surface. */
|
|
1253
|
+
--gd-shadow: var(
|
|
1254
|
+
--shadow-sm,
|
|
1255
|
+
0 1px 2px color-mix(in srgb, var(--primary-color, #1b3933) 8%, transparent),
|
|
1256
|
+
0 8px 24px -12px color-mix(in srgb, var(--primary-color, #1b3933) 18%, transparent)
|
|
1257
|
+
);
|
|
1258
|
+
|
|
1259
|
+
align-items: flex-start;
|
|
1260
|
+
gap: var(--spacing-md, 1rem);
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
/* -- the title ------------------------------------------------------------ */
|
|
1264
|
+
|
|
1265
|
+
/* Was a full-width white slab with a hard edge, so the page arrived as two
|
|
1266
|
+
stacked boxes before any content. The breadcrumb is type on the page ground
|
|
1267
|
+
now, and the panels below are the only containers. */
|
|
1268
|
+
.crmtitle,
|
|
1269
|
+
.crmtitle--alternate {
|
|
1270
|
+
padding: 0 0.25rem 0.85rem;
|
|
1271
|
+
background: none;
|
|
1272
|
+
border: 0;
|
|
1273
|
+
box-shadow: none;
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
.titleInfo {
|
|
1277
|
+
color: var(--muted-color, #6b7688);
|
|
1278
|
+
font-size: 0.75rem;
|
|
1279
|
+
font-variant-numeric: tabular-nums;
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
/* -- the two panels ------------------------------------------------------- */
|
|
1283
|
+
|
|
1284
|
+
.grid__subnav,
|
|
1285
|
+
.grid__subcontent {
|
|
1286
|
+
border: 1px solid var(--gd-line);
|
|
1287
|
+
border-radius: var(--gd-radius);
|
|
1288
|
+
background: var(--gd-surface);
|
|
1289
|
+
box-shadow: var(--gd-shadow);
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
/* The rail is a list of destinations, not a panel of content: it gets the
|
|
1293
|
+
same surface but tighter padding so the tabs sit closer to their edge. */
|
|
1294
|
+
.grid__subnav {
|
|
1295
|
+
padding: 0.4rem;
|
|
1296
|
+
align-self: flex-start;
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
.grid__subcontent {
|
|
1300
|
+
padding: var(--spacing-md, 1rem);
|
|
1301
|
+
min-width: 0;
|
|
1302
|
+
overflow: hidden;
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
/* The underline tab strip is a strip, not a panel — giving it a card as well
|
|
1306
|
+
would box a row of text. */
|
|
1307
|
+
.grid__subnav--underline {
|
|
1308
|
+
padding: 0;
|
|
1309
|
+
border: 0;
|
|
1310
|
+
border-bottom: 1px solid var(--gd-line);
|
|
1311
|
+
border-radius: 0;
|
|
1312
|
+
background: none;
|
|
1313
|
+
box-shadow: none;
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
/* -- section headings ----------------------------------------------------- */
|
|
1317
|
+
|
|
1318
|
+
.gridtxt__header {
|
|
1319
|
+
display: flex;
|
|
1320
|
+
align-items: baseline;
|
|
1321
|
+
justify-content: space-between;
|
|
1322
|
+
gap: 0.75rem;
|
|
1323
|
+
padding-bottom: 0.6rem;
|
|
1324
|
+
margin-bottom: 0.9rem;
|
|
1325
|
+
border-bottom: 1px solid var(--gd-line);
|
|
1326
|
+
color: var(--heading-color, var(--primary-color, #1b3933));
|
|
1327
|
+
font-size: 0.9rem;
|
|
1328
|
+
font-weight: 600;
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
.gridtxt__meta {
|
|
1332
|
+
color: var(--gd-muted);
|
|
1333
|
+
font-size: 0.75rem;
|
|
1334
|
+
font-weight: 400;
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
/* -- overview fields ------------------------------------------------------ */
|
|
1338
|
+
|
|
1339
|
+
.overviewLabel {
|
|
1340
|
+
color: var(--gd-muted);
|
|
1341
|
+
font-size: 0.6875rem;
|
|
1342
|
+
font-weight: 600;
|
|
1343
|
+
letter-spacing: 0.05em;
|
|
1344
|
+
text-transform: uppercase;
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
.overviewValue {
|
|
1348
|
+
color: var(--gd-ink);
|
|
1349
|
+
font-size: 0.875rem;
|
|
1350
|
+
line-height: 1.5;
|
|
1351
|
+
/* A value can be an address or a long note; it must wrap rather than push
|
|
1352
|
+
the column wider than its track. */
|
|
1353
|
+
overflow-wrap: anywhere;
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
.overviewEmpty {
|
|
1357
|
+
color: var(--gd-muted);
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
/* -- the floating action bar ---------------------------------------------- */
|
|
1361
|
+
|
|
1362
|
+
/* It stays pinned bottom-right — every detail page in every project is laid
|
|
1363
|
+
out around that — but it had no ground of its own, so on a short page the
|
|
1364
|
+
buttons floated over the page background with nothing behind them. A pill
|
|
1365
|
+
with the same elevation as the panels gives them somewhere to sit. */
|
|
1366
|
+
.polActions {
|
|
1367
|
+
padding: 0.4rem;
|
|
1368
|
+
border: 1px solid var(--gd-line);
|
|
1369
|
+
border-radius: var(--radius-pill, 999px);
|
|
1370
|
+
background: color-mix(in srgb, var(--gd-surface) 92%, transparent);
|
|
1371
|
+
backdrop-filter: blur(8px);
|
|
1372
|
+
box-shadow:
|
|
1373
|
+
0 2px 4px color-mix(in srgb, var(--primary-color, #1b3933) 10%, transparent),
|
|
1374
|
+
0 16px 32px -14px color-mix(in srgb, var(--primary-color, #1b3933) 30%, transparent);
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
/* -- states --------------------------------------------------------------- */
|
|
1378
|
+
|
|
1379
|
+
.noDataMessage {
|
|
1380
|
+
display: flex;
|
|
1381
|
+
align-items: center;
|
|
1382
|
+
justify-content: center;
|
|
1383
|
+
min-height: 6rem;
|
|
1384
|
+
color: var(--gd-muted);
|
|
1385
|
+
font-size: 0.875rem;
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
/* A nested grid already carries its own card from DataGrid's 2026 pass;
|
|
1389
|
+
double-carding it puts a panel inside a panel. */
|
|
1390
|
+
.grid__subcontent [class*='dataGridContainer'] {
|
|
1391
|
+
border: 0;
|
|
1392
|
+
border-radius: 0;
|
|
1393
|
+
box-shadow: none;
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
@media (max-width: 900px) {
|
|
1397
|
+
.grid__subrow,
|
|
1398
|
+
.grid__subrow--stacked {
|
|
1399
|
+
flex-direction: column;
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
.grid__subnav {
|
|
1403
|
+
width: 100%;
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
/* ============================================================================
|
|
1408
|
+
* 2026 pass — the rail column
|
|
1409
|
+
* ----------------------------------------------------------------------------
|
|
1410
|
+
* The same two structural faults GenericIndex had, and they are worse on a
|
|
1411
|
+
* detail page than on an index:
|
|
1412
|
+
*
|
|
1413
|
+
* 1. The row was flex, with the rail on `flex: 1` and the panel on
|
|
1414
|
+
* `flex: 0 1 80%`. Those two fight over the leftover space, so the rail's
|
|
1415
|
+
* width moved with the content beside it — a tab list that changes width
|
|
1416
|
+
* when you switch tabs.
|
|
1417
|
+
* 2. The rail did not stick. A detail page is the LONGEST page in the app —
|
|
1418
|
+
* a form, its tables, its notes — so scrolling to the bottom of one tab
|
|
1419
|
+
* left no way to reach another without scrolling all the way back.
|
|
1420
|
+
*
|
|
1421
|
+
* The card stays, unlike on the index. There the grid drew its own card and the
|
|
1422
|
+
* rail's was a second one nested around it; here the content panel is a real
|
|
1423
|
+
* panel holding a form, so a card rail beside a card panel is consistent
|
|
1424
|
+
* rather than doubled.
|
|
1425
|
+
*
|
|
1426
|
+
* Tokens shared with GenericIndex (`--index-rail-*`) on purpose: the two pages
|
|
1427
|
+
* share one rail, and a project retuning it should not have to find two names.
|
|
1428
|
+
* ==========================================================================*/
|
|
1429
|
+
|
|
1430
|
+
.grid__subrow {
|
|
1431
|
+
display: grid;
|
|
1432
|
+
grid-template-columns:
|
|
1433
|
+
minmax(var(--index-rail-min, 190px), var(--index-rail-width, 224px))
|
|
1434
|
+
minmax(0, 1fr);
|
|
1435
|
+
align-items: start;
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
.grid__subnav {
|
|
1439
|
+
position: sticky;
|
|
1440
|
+
top: var(--index-rail-top, 88px);
|
|
1441
|
+
max-height: calc(100vh - var(--index-rail-offset, 120px));
|
|
1442
|
+
overflow-y: auto;
|
|
1443
|
+
overscroll-behavior: contain;
|
|
1444
|
+
scrollbar-width: thin;
|
|
1445
|
+
|
|
1446
|
+
/* No card, matching GenericIndex.
|
|
1447
|
+
|
|
1448
|
+
This kept its card at first, on the reasoning that a card rail beside a
|
|
1449
|
+
card content panel is consistent. In use it is not: the rail is 250px of
|
|
1450
|
+
content next to a panel ten times its height, so the card ENDS and
|
|
1451
|
+
leaves a bordered box floating above a large empty column — the same
|
|
1452
|
+
fault the index had. And the two pages sit next to each other in one
|
|
1453
|
+
app, so a bordered rail on one and a borderless rail on the other reads
|
|
1454
|
+
as a bug rather than as a distinction. */
|
|
1455
|
+
background: none;
|
|
1456
|
+
border: none;
|
|
1457
|
+
box-shadow: none;
|
|
1458
|
+
padding: 0;
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
/* The rail items need the same accent-edge gutter the index gives them, or the
|
|
1462
|
+
3px edge on the selected item pushes its label sideways. */
|
|
1463
|
+
.grid__subnav > ul li a {
|
|
1464
|
+
position: relative;
|
|
1465
|
+
padding-left: calc(var(--spacing-md, 1rem) - 3px);
|
|
1466
|
+
border-left: 3px solid transparent;
|
|
1467
|
+
border-radius: var(--radius-sm, 6px);
|
|
1468
|
+
color: var(--paragraph-color, #52606d);
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
.grid__subnav > ul li:hover a {
|
|
1472
|
+
background: color-mix(
|
|
1473
|
+
in srgb,
|
|
1474
|
+
var(--primary-color, #1b3933) 6%,
|
|
1475
|
+
transparent
|
|
1476
|
+
);
|
|
1477
|
+
color: var(--heading-color, #111827);
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
/* The stacked layout puts the tabs ABOVE the panel, so the row is one column
|
|
1481
|
+
and nothing sticks — a strip pinned over the content it labels would cover
|
|
1482
|
+
the first field of every form.
|
|
1483
|
+
|
|
1484
|
+
`grid-template-columns: none` undoes the two-column track the rail layout
|
|
1485
|
+
sets above; without it the strip and the panel would each be handed a
|
|
1486
|
+
column and the panel would keep the rail's 224px hole beside it. */
|
|
1487
|
+
.grid__subrow--stacked {
|
|
1488
|
+
display: flex;
|
|
1489
|
+
grid-template-columns: none;
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
.grid__subrow--stacked .grid__subnav {
|
|
1493
|
+
position: static;
|
|
1494
|
+
max-height: none;
|
|
1495
|
+
overflow: visible;
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
/* Both children run the full width. The panel's own `flex: 0 1 80%` was
|
|
1499
|
+
written for a ROW — in a column it is a height basis, which is nonsense
|
|
1500
|
+
here — and its 80% was the rail's column tax. That column is reclaimed:
|
|
1501
|
+
this is the whole point of the layout. */
|
|
1502
|
+
.grid__subrow--stacked > .grid__subnav,
|
|
1503
|
+
.grid__subrow--stacked > .grid__subcontent {
|
|
1504
|
+
flex: 0 0 auto;
|
|
1505
|
+
width: 100%;
|
|
1506
|
+
min-width: 0;
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
/* The strip is separated from the panel by the panel's own margin, so the
|
|
1510
|
+
strip's is zeroed above and the gap is stated once, here. A tab row butted
|
|
1511
|
+
straight onto the card below it reads as a header of that card rather than
|
|
1512
|
+
as a control above it. */
|
|
1513
|
+
.grid__subrow--stacked > .grid__subcontent {
|
|
1514
|
+
margin: var(--spacing-md, 1rem) 0 0;
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
@media (max-width: 759px) {
|
|
1518
|
+
.grid__subrow {
|
|
1519
|
+
grid-template-columns: minmax(0, 1fr);
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
.grid__subnav {
|
|
1523
|
+
position: static;
|
|
1524
|
+
max-height: none;
|
|
1525
|
+
overflow: visible;
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
/* ============================================================================
|
|
1530
|
+
* The grid card — one card, not two
|
|
1531
|
+
* ----------------------------------------------------------------------------
|
|
1532
|
+
* The same repair as the block at the end of GenericIndex.module.scss, for the
|
|
1533
|
+
* grids a detail page renders in a `.grid__full`. See that file for the full
|
|
1534
|
+
* reasoning; in short, `.grid__full` is the only element wrapping both the
|
|
1535
|
+
* toolbar and the table, so it is the card, and the grid's own container gives
|
|
1536
|
+
* up its border, radius and shadow to sit flush inside it.
|
|
1537
|
+
*
|
|
1538
|
+
* `[class*='dataGridContainer']` matches DataGrid.module.scss's hashed local
|
|
1539
|
+
* name, which this file cannot spell directly. It does NOT match
|
|
1540
|
+
* `dataGridTopContainer` or `dataGridBottomContainer` — neither contains that
|
|
1541
|
+
* substring.
|
|
1542
|
+
* ==========================================================================*/
|
|
1543
|
+
|
|
1544
|
+
.grid__full:has([class*='dataGridContainer']) {
|
|
1545
|
+
/* Selects, row-action popovers and the pager dropdown open out of the card. */
|
|
1546
|
+
overflow: visible;
|
|
1547
|
+
|
|
1548
|
+
/* Descendant, not `>`: the toolbar and the grid share an unclassed wrapper
|
|
1549
|
+
div, so the card's only direct child is that wrapper. And the radius is
|
|
1550
|
+
spelled out rather than `inherit`, because inheriting would take the
|
|
1551
|
+
wrapper's 0. See the matching block in GenericIndex.module.scss. */
|
|
1552
|
+
[class*='dataGridContainer'] {
|
|
1553
|
+
border: 0;
|
|
1554
|
+
box-shadow: none;
|
|
1555
|
+
border-radius: calc(var(--card-radius, 10px) - 1px);
|
|
1556
|
+
overflow: hidden;
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1559
|
+
[class*='dataGridTopContainer'] {
|
|
1560
|
+
border-top-left-radius: calc(var(--card-radius, 10px) - 1px);
|
|
1561
|
+
border-top-right-radius: calc(var(--card-radius, 10px) - 1px);
|
|
1562
|
+
border-bottom-color: var(--border-color, #e1e1e1);
|
|
1563
|
+
}
|
|
1564
|
+
}
|