nexus-shared 3.2.0 → 4.0.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/CHANGELOG.md +1564 -0
- package/README.md +1705 -1123
- package/dist/Client.Index.d.ts +14 -0
- package/dist/Client.Index.js +14 -0
- package/dist/Components/Documents/DocumentFrame.d.ts +50 -0
- package/dist/Components/Documents/DocumentFrame.js +83 -0
- package/dist/Components/Documents/Menu.d.ts +4 -0
- package/dist/Components/Documents/Menu.js +40 -24
- package/dist/Components/Documents/PrintDocument.d.ts +95 -0
- package/dist/Components/Documents/PrintDocument.js +62 -0
- package/dist/Components/Documents/Tabs.d.ts +59 -0
- package/dist/Components/Documents/Tabs.js +70 -0
- package/dist/Components/Forms/ApiForm.js +19 -2
- package/dist/Components/Forms/Crud.d.ts +2 -2
- package/dist/Components/Forms/Crud.js +576 -243
- package/dist/Components/Forms/CrudActions.d.ts +136 -0
- package/dist/Components/Forms/CrudActions.js +184 -0
- package/dist/Components/Forms/CrudNarrowPicker.d.ts +31 -0
- package/dist/Components/Forms/CrudNarrowPicker.js +180 -0
- package/dist/Components/Forms/CrudParts.d.ts +30 -2
- package/dist/Components/Forms/CrudParts.js +55 -5
- package/dist/Components/Forms/CrudRowForms.d.ts +26 -0
- package/dist/Components/Forms/CrudRowForms.js +114 -0
- package/dist/Components/Forms/CrudScopes.d.ts +28 -0
- package/dist/Components/Forms/CrudScopes.js +76 -0
- package/dist/Components/Forms/CrudTree.d.ts +90 -0
- package/dist/Components/Forms/CrudTree.js +363 -0
- package/dist/Components/Forms/CrudWorkspace.d.ts +63 -0
- package/dist/Components/Forms/CrudWorkspace.js +169 -0
- package/dist/Components/Forms/ExcelImport.js +3 -3
- package/dist/Components/Forms/Form.d.ts +4 -4
- package/dist/Components/Forms/Form.js +123 -17
- package/dist/Components/Forms/FormLeaveGuard.d.ts +44 -0
- package/dist/Components/Forms/FormLeaveGuard.js +65 -0
- package/dist/Components/Forms/RecordFlows.d.ts +50 -0
- package/dist/Components/Forms/RecordFlows.js +282 -0
- package/dist/Components/Forms/SubmitForm.d.ts +37 -2
- package/dist/Components/Forms/SubmitForm.js +195 -10
- package/dist/Components/Inputs/CheckBox.js +1 -1
- package/dist/Components/Inputs/ChoiceField.d.ts +21 -1
- package/dist/Components/Inputs/ChoiceField.js +28 -2
- package/dist/Components/Inputs/Dropdown.d.ts +13 -0
- package/dist/Components/Inputs/Dropdown.js +5 -5
- package/dist/Components/Inputs/DropdownParts.d.ts +3 -1
- package/dist/Components/Inputs/DropdownParts.js +16 -4
- package/dist/Components/Inputs/Field.d.ts +7 -1
- package/dist/Components/Inputs/Field.js +2 -2
- package/dist/Components/Inputs/GroupForm.d.ts +6 -6
- package/dist/Components/Inputs/GroupForm.js +10 -11
- package/dist/Components/Inputs/InputRenderer.d.ts +9 -6
- package/dist/Components/Inputs/InputRenderer.js +37 -32
- package/dist/Components/Inputs/PictureInput.d.ts +41 -0
- package/dist/Components/Inputs/PictureInput.js +70 -0
- package/dist/Components/Inputs/RadioGroup.d.ts +16 -3
- package/dist/Components/Inputs/RadioGroup.js +8 -3
- package/dist/Components/Inputs/RowsInput.d.ts +1 -1
- package/dist/Components/Inputs/RowsInput.js +18 -3
- package/dist/Components/Inputs/TabularForm.d.ts +5 -5
- package/dist/Components/Inputs/TabularForm.js +29 -29
- package/dist/Components/Inputs/TextArea.d.ts +6 -0
- package/dist/Components/Inputs/TextArea.js +11 -2
- package/dist/Components/Inputs/TextBoxTypes.d.ts +6 -0
- package/dist/Components/Inputs/TextBoxTypes.js +17 -0
- package/dist/Components/Inputs/TreeView.d.ts +53 -2
- package/dist/Components/Inputs/TreeView.js +147 -13
- package/dist/Components/Layouts/MessageBox.d.ts +15 -2
- package/dist/Components/Layouts/MessageBox.js +56 -7
- package/dist/Components/Layouts/Popup.d.ts +13 -6
- package/dist/Components/Layouts/Popup.js +37 -9
- package/dist/Components/Layouts/PopupDock.d.ts +3 -1
- package/dist/Components/Layouts/PopupDock.js +2 -1
- package/dist/Components/Layouts/PopupHost.js +5 -4
- package/dist/Components/Viewers/DataTable.js +150 -48
- package/dist/Components/Viewers/DataTableFilters.d.ts +1 -1
- package/dist/Components/Viewers/DataTableFilters.js +17 -2
- package/dist/Components/Viewers/DataTableParts.d.ts +21 -5
- package/dist/Components/Viewers/DataTableParts.js +26 -14
- package/dist/Components/Viewers/OwnerFiles.d.ts +175 -0
- package/dist/Components/Viewers/OwnerFiles.js +589 -0
- package/dist/Components/Viewers/QrCodeImage.d.ts +22 -0
- package/dist/Components/Viewers/QrCodeImage.js +15 -0
- package/dist/Components/Viewers/RecordCards.d.ts +16 -0
- package/dist/Components/Viewers/RecordCards.js +509 -0
- package/dist/Helpers/BusyHooks.d.ts +6 -0
- package/dist/Helpers/BusyHooks.js +39 -0
- package/dist/Helpers/CrudBackend.d.ts +20 -2
- package/dist/Helpers/CrudBackend.js +46 -2
- package/dist/Helpers/CrudColumns.d.ts +53 -6
- package/dist/Helpers/CrudColumns.js +98 -7
- package/dist/Helpers/CrudDetailsTabs.d.ts +58 -0
- package/dist/Helpers/CrudDetailsTabs.js +126 -0
- package/dist/Helpers/CrudHelpers.d.ts +81 -2
- package/dist/Helpers/CrudHelpers.js +195 -0
- package/dist/Helpers/CrudNarrowPick.d.ts +83 -0
- package/dist/Helpers/CrudNarrowPick.js +157 -0
- package/dist/Helpers/CrudRowForms.d.ts +15 -0
- package/dist/Helpers/CrudRowForms.js +43 -0
- package/dist/Helpers/CrudScopes.d.ts +32 -0
- package/dist/Helpers/CrudScopes.js +79 -0
- package/dist/Helpers/DropdownHelpers.d.ts +3 -1
- package/dist/Helpers/DropdownHelpers.js +6 -2
- package/dist/Helpers/ExcelHelpers.d.ts +1 -1
- package/dist/Helpers/ExcelHelpers.js +12 -11
- package/dist/Helpers/FileAdapter.d.ts +78 -0
- package/dist/Helpers/FileAdapter.js +102 -0
- package/dist/Helpers/FilePrimaries.d.ts +48 -0
- package/dist/Helpers/FilePrimaries.js +138 -0
- package/dist/Helpers/FormConfirm.d.ts +32 -0
- package/dist/Helpers/FormConfirm.js +40 -0
- package/dist/Helpers/FormStore.d.ts +90 -5
- package/dist/Helpers/FormStore.js +318 -22
- package/dist/Helpers/InputConditions.d.ts +50 -0
- package/dist/Helpers/InputConditions.js +168 -0
- package/dist/Helpers/InputMemory.d.ts +106 -0
- package/dist/Helpers/InputMemory.js +385 -0
- package/dist/Helpers/InputNarrowing.d.ts +18 -0
- package/dist/Helpers/InputNarrowing.js +67 -0
- package/dist/Helpers/InputParamsHelpers.d.ts +44 -1
- package/dist/Helpers/InputParamsHelpers.js +157 -74
- package/dist/Helpers/NexusDriveAdapter.d.ts +55 -0
- package/dist/Helpers/NexusDriveAdapter.js +207 -0
- package/dist/Helpers/NumberHelpers.d.ts +95 -0
- package/dist/Helpers/NumberHelpers.js +126 -0
- package/dist/Helpers/Permissions.js +2 -1
- package/dist/Helpers/QrCode.d.ts +26 -0
- package/dist/Helpers/QrCode.js +463 -0
- package/dist/Helpers/RecordCards.d.ts +205 -0
- package/dist/Helpers/RecordCards.js +378 -0
- package/dist/Helpers/RequestCache.d.ts +14 -2
- package/dist/Helpers/RequestCache.js +22 -3
- package/dist/Helpers/RowsStore.d.ts +37 -2
- package/dist/Helpers/RowsStore.js +128 -10
- package/dist/Helpers/ServerPreview.d.ts +69 -0
- package/dist/Helpers/ServerPreview.js +99 -0
- package/dist/Helpers/TableColumns.js +4 -3
- package/dist/Helpers/TableExport.d.ts +7 -1
- package/dist/Helpers/TableExport.js +9 -3
- package/dist/Helpers/TableFilters.d.ts +1 -1
- package/dist/Helpers/TableFilters.js +24 -23
- package/dist/Helpers/TableHelpers.d.ts +23 -2
- package/dist/Helpers/TableHelpers.js +51 -10
- package/dist/Helpers/TableJoins.d.ts +13 -0
- package/dist/Helpers/TableJoins.js +34 -0
- package/dist/Helpers/TableStore.d.ts +21 -1
- package/dist/Helpers/TableStore.js +64 -7
- package/dist/Helpers/TreeStore.d.ts +81 -0
- package/dist/Helpers/TreeStore.js +365 -0
- package/dist/Interfaces/CrudInterfaces.d.ts +465 -5
- package/dist/Interfaces/FileInterfaces.d.ts +162 -0
- package/dist/Interfaces/FileInterfaces.js +4 -0
- package/dist/Interfaces/FormInterfaces.d.ts +391 -30
- package/dist/Interfaces/FormInterfaces.js +79 -1
- package/dist/Interfaces/InputInterfaces.d.ts +15 -3
- package/dist/Interfaces/RecordInterfaces.d.ts +367 -0
- package/dist/Interfaces/RecordInterfaces.js +1 -0
- package/dist/Interfaces/TableInterfaces.d.ts +74 -1
- package/dist/Services/ExcelApi.js +5 -0
- package/dist/Services/FileApi.d.ts +13 -0
- package/dist/Services/FileApi.js +29 -0
- package/dist/Services/ImageEditorLoader.d.ts +14 -0
- package/dist/Services/ImageEditorLoader.js +51 -0
- package/dist/Services/JoinSources.d.ts +37 -5
- package/dist/Services/JoinSources.js +90 -14
- package/dist/Services/ModuleImport.d.ts +7 -0
- package/dist/Services/ModuleImport.js +22 -0
- package/dist/Shared.Index.d.ts +16 -0
- package/dist/Shared.Index.js +16 -0
- package/package.json +7 -2
- package/src/Styles/Nexus.Avatar.css +6 -5
- package/src/Styles/Nexus.Button.css +10 -4
- package/src/Styles/Nexus.Choice.css +16 -0
- package/src/Styles/Nexus.Crud.css +383 -9
- package/src/Styles/Nexus.Dropdown.css +8 -0
- package/src/Styles/Nexus.Files.css +410 -0
- package/src/Styles/Nexus.Form.css +5 -2
- package/src/Styles/Nexus.Index.css +4 -0
- package/src/Styles/Nexus.Input.css +42 -0
- package/src/Styles/Nexus.Menu.css +10 -1
- package/src/Styles/Nexus.Popup.css +77 -1
- package/src/Styles/Nexus.Print.css +288 -0
- package/src/Styles/Nexus.QrCode.css +12 -0
- package/src/Styles/Nexus.Record.css +430 -0
- package/src/Styles/Nexus.Tab.Buttons.css +87 -22
- package/src/Styles/Nexus.Table.css +67 -5
- package/src/Styles/Nexus.Themes.css +12 -6
- package/src/Styles/Nexus.Tokens.css +8 -3
- package/src/Styles/Nexus.Tree.css +31 -1
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* A printable document (PrintDocument.tsx): a receipt, a bill, a statement. On screen it reads in the theme's colours
|
|
3
|
+
* at the width of its paper; printed, it is the only thing on the paper, black on white - A5 (128 mm of text) or an
|
|
4
|
+
* 80 mm thermal roll (72 mm printed). The browser's own print, no PDF library. The paper itself is the component's
|
|
5
|
+
* own @page rule, written while it is on the page.
|
|
6
|
+
*
|
|
7
|
+
* And a whole page a server wrote, in a frame of its own (DocumentFrame.tsx): its sheet, desk and @page are its own.
|
|
8
|
+
*/
|
|
9
|
+
@layer nexus.components {
|
|
10
|
+
/* As wide as its paper, in any container (a flex column that would shrink it to its text included). */
|
|
11
|
+
.nx-print {
|
|
12
|
+
container: nx-print / inline-size;
|
|
13
|
+
width: 100%;
|
|
14
|
+
max-width: 128mm;
|
|
15
|
+
margin-inline: auto;
|
|
16
|
+
color: var(--nx-text);
|
|
17
|
+
font-size: 0.875rem;
|
|
18
|
+
line-height: 1.45;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.nx-print--thermal {
|
|
22
|
+
max-width: 72mm;
|
|
23
|
+
font-size: 0.75rem;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.nx-print p {
|
|
27
|
+
margin: 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.nx-print__head {
|
|
31
|
+
padding-block-end: var(--nx-space-2);
|
|
32
|
+
border-block-end: 1px dashed var(--nx-border);
|
|
33
|
+
text-align: center;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.nx-print__title {
|
|
37
|
+
font-size: 1.25em;
|
|
38
|
+
font-weight: 700;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/*
|
|
42
|
+
* A logo (`logo`). On A5 it sits beside the title lines in a 24 mm column, with one as wide after them so the lines
|
|
43
|
+
* stay centred on the paper; at most 16 mm tall, so the head is never taller than its lines and a one-page receipt
|
|
44
|
+
* stays one page. On an 80 mm roll it sits above them, small and centred.
|
|
45
|
+
*/
|
|
46
|
+
.nx-print__head--logo {
|
|
47
|
+
display: grid;
|
|
48
|
+
grid-template-columns: 24mm minmax(0, 1fr) 24mm;
|
|
49
|
+
align-items: center;
|
|
50
|
+
column-gap: var(--nx-space-2);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.nx-print__logo,
|
|
54
|
+
.nx-print__heading {
|
|
55
|
+
min-width: 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.nx-print__logo {
|
|
59
|
+
display: flex;
|
|
60
|
+
align-items: center;
|
|
61
|
+
justify-content: center;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.nx-print__logo > :is(img, svg) {
|
|
65
|
+
display: block;
|
|
66
|
+
max-width: 100%;
|
|
67
|
+
max-height: 16mm;
|
|
68
|
+
object-fit: contain;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.nx-print--thermal .nx-print__head--logo {
|
|
72
|
+
display: block;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.nx-print--thermal .nx-print__logo {
|
|
76
|
+
margin-block-end: var(--nx-space-1);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* An A5 document shown narrower than its paper (a phone): the logo above the lines, as on a roll. Printed, it is A5. */
|
|
80
|
+
@container nx-print (max-width: 100mm) {
|
|
81
|
+
.nx-print__head--logo {
|
|
82
|
+
display: block;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.nx-print__logo {
|
|
86
|
+
margin-block-end: var(--nx-space-1);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.nx-print--thermal .nx-print__logo > :is(img, svg) {
|
|
91
|
+
max-width: 36mm;
|
|
92
|
+
max-height: 10mm;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.nx-print__kind {
|
|
96
|
+
margin-block-start: var(--nx-space-1);
|
|
97
|
+
font-weight: 600;
|
|
98
|
+
letter-spacing: 0.04em;
|
|
99
|
+
text-transform: uppercase;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* A stamp across the document: Voided, Cancelled, Copy. */
|
|
103
|
+
.nx-print__stamp {
|
|
104
|
+
margin-block: var(--nx-space-2);
|
|
105
|
+
padding: var(--nx-space-1);
|
|
106
|
+
border: 1px solid currentColor;
|
|
107
|
+
font-weight: 700;
|
|
108
|
+
text-align: center;
|
|
109
|
+
text-transform: uppercase;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* Facts: a label and its value on each line, the labels in one column. */
|
|
113
|
+
.nx-print__facts {
|
|
114
|
+
display: grid;
|
|
115
|
+
gap: 2px;
|
|
116
|
+
margin: var(--nx-space-2) 0;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.nx-print__facts > div {
|
|
120
|
+
display: grid;
|
|
121
|
+
grid-template-columns: minmax(6.5em, 35%) 1fr;
|
|
122
|
+
gap: var(--nx-space-2);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.nx-print__facts dt {
|
|
126
|
+
color: var(--nx-text-muted);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.nx-print__facts dd {
|
|
130
|
+
margin: 0;
|
|
131
|
+
overflow-wrap: anywhere;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* Lines: what was charged, the figures lined up at the end, the totals under a rule. */
|
|
135
|
+
.nx-print__lines {
|
|
136
|
+
width: 100%;
|
|
137
|
+
margin-block: var(--nx-space-2);
|
|
138
|
+
border-collapse: collapse;
|
|
139
|
+
font-variant-numeric: tabular-nums;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.nx-print__lines th,
|
|
143
|
+
.nx-print__lines td {
|
|
144
|
+
padding: 3px 0;
|
|
145
|
+
text-align: start;
|
|
146
|
+
vertical-align: top;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.nx-print__lines :is(th, td) + :is(th, td) {
|
|
150
|
+
padding-inline-start: var(--nx-space-2);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.nx-print__lines .nx-print__end {
|
|
154
|
+
text-align: end;
|
|
155
|
+
white-space: nowrap;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.nx-print__lines thead th {
|
|
159
|
+
border-block-end: 1px solid var(--nx-border);
|
|
160
|
+
font-weight: 600;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.nx-print__lines tfoot :is(th, td) {
|
|
164
|
+
border-block-start: 1px solid var(--nx-border);
|
|
165
|
+
font-size: 1.1em;
|
|
166
|
+
font-weight: 700;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.nx-print__lines tfoot tr + tr :is(th, td) {
|
|
170
|
+
border-block-start: 0;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.nx-print__note {
|
|
174
|
+
display: block;
|
|
175
|
+
color: var(--nx-text-muted);
|
|
176
|
+
font-size: 0.9em;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.nx-print__foot {
|
|
180
|
+
padding-block-start: var(--nx-space-2);
|
|
181
|
+
border-block-start: 1px dashed var(--nx-border);
|
|
182
|
+
text-align: center;
|
|
183
|
+
white-space: pre-line;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/*
|
|
187
|
+
* Printed: only the document, lifted out of the page around it, black on white. Only while a document is on the
|
|
188
|
+
* page (`:has`), so printing any other page prints that page as it is.
|
|
189
|
+
*/
|
|
190
|
+
@media print {
|
|
191
|
+
body:has(.nx-print) * {
|
|
192
|
+
visibility: hidden;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
body:has(.nx-print) .nx-print,
|
|
196
|
+
body:has(.nx-print) .nx-print * {
|
|
197
|
+
visibility: visible;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
body:has(.nx-print) .nx-print {
|
|
201
|
+
position: absolute;
|
|
202
|
+
inset: 0 auto auto 0;
|
|
203
|
+
width: 100%;
|
|
204
|
+
max-width: none;
|
|
205
|
+
color: #000;
|
|
206
|
+
background: #fff;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
body:has(.nx-print) .nx-print--thermal {
|
|
210
|
+
width: 72mm;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.nx-print__facts dt,
|
|
214
|
+
.nx-print__note {
|
|
215
|
+
color: #000;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/* A logo prints in black and white, as the rest does: a thermal roll has no other colour. */
|
|
219
|
+
.nx-print__logo {
|
|
220
|
+
filter: grayscale(1);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.nx-print__head,
|
|
224
|
+
.nx-print__foot,
|
|
225
|
+
.nx-print__lines thead th,
|
|
226
|
+
.nx-print__lines tfoot :is(th, td) {
|
|
227
|
+
border-color: #000;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/*
|
|
232
|
+
* A server's page in a frame: a form's bar (its status line and the page's buttons) over the page, which fills the
|
|
233
|
+
* height the container gives and never less than 22rem, so a frame stacked under an editor is never a sliver. The
|
|
234
|
+
* frame scrolls inside itself; a sheet wider than the box scrolls sideways there, never the page.
|
|
235
|
+
*/
|
|
236
|
+
.nx-document-frame {
|
|
237
|
+
display: flex;
|
|
238
|
+
flex: 1 1 auto;
|
|
239
|
+
flex-direction: column;
|
|
240
|
+
gap: var(--nx-space-2);
|
|
241
|
+
min-width: 0;
|
|
242
|
+
min-height: 22rem;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/* Its line says a few words ("Loading the preview…"), so two buttons stay beside it in a half-width frame. */
|
|
246
|
+
.nx-document-frame__bar {
|
|
247
|
+
--nx-form-status-basis: 10rem;
|
|
248
|
+
|
|
249
|
+
flex: none;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/* Lower than the panel, as a read-only box: the page's own desk covers it once a page is there. */
|
|
253
|
+
.nx-document-frame__view {
|
|
254
|
+
position: relative;
|
|
255
|
+
display: grid;
|
|
256
|
+
flex: 1 1 auto;
|
|
257
|
+
place-items: center;
|
|
258
|
+
min-height: 0;
|
|
259
|
+
overflow: hidden;
|
|
260
|
+
border: 1px solid var(--nx-border);
|
|
261
|
+
border-radius: var(--nx-radius);
|
|
262
|
+
background: light-dark(var(--nx-surface-2), var(--nx-bg));
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.nx-document-frame__page {
|
|
266
|
+
position: absolute;
|
|
267
|
+
inset: 0;
|
|
268
|
+
display: block;
|
|
269
|
+
width: 100%;
|
|
270
|
+
height: 100%;
|
|
271
|
+
border: 0;
|
|
272
|
+
transition: opacity var(--nx-duration);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/* A read that lasts: the page shown stays, dimmed, under the bar's "Loading…". */
|
|
276
|
+
.nx-document-frame__view--busy .nx-document-frame__page {
|
|
277
|
+
opacity: 0.5;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
[data-nx-motion="reduce"] .nx-document-frame__page {
|
|
281
|
+
transition: none;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.nx-document-frame__empty {
|
|
285
|
+
max-width: 32rem;
|
|
286
|
+
padding: var(--nx-space-4);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
@layer nexus.components {
|
|
2
|
+
/*
|
|
3
|
+
* A QR code (`QrCodeImage`): the white square of its quiet zone with a control's rounded corners, 9rem wide unless the
|
|
4
|
+
* page's own class says otherwise. Its colours are the SVG's own fills, black on white in every theme, as a camera
|
|
5
|
+
* reads it; forced colours leave SVG fills alone (Chromium, measured by the template's qr-code.cjs).
|
|
6
|
+
*/
|
|
7
|
+
.nx-qr {
|
|
8
|
+
display: block;
|
|
9
|
+
width: 9rem;
|
|
10
|
+
border-radius: var(--nx-radius);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
@layer nexus.components {
|
|
2
|
+
/*
|
|
3
|
+
* A record's page of cards (`RecordCards`): the hero across the top, then the cards, as many to a row as have 26rem
|
|
4
|
+
* each (one on a phone), each as tall as what it holds. A card is a panel - the admin panel's edge, corner and surface -
|
|
5
|
+
* with its heading (an icon, the title and its count, a sentence, its buttons) over its body. Nothing inside a card is
|
|
6
|
+
* boxed: fields are label over value, items are rows between hairlines that reach the card's edges.
|
|
7
|
+
*/
|
|
8
|
+
.nx-record {
|
|
9
|
+
display: grid;
|
|
10
|
+
gap: var(--nx-space-4);
|
|
11
|
+
min-width: 0;
|
|
12
|
+
container-type: inline-size;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.nx-record__cards {
|
|
16
|
+
display: grid;
|
|
17
|
+
grid-template-columns: repeat(auto-fill, minmax(min(100%, 26rem), 1fr));
|
|
18
|
+
gap: var(--nx-space-4);
|
|
19
|
+
align-items: start;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.nx-record-card,
|
|
23
|
+
.nx-record-hero {
|
|
24
|
+
min-width: 0;
|
|
25
|
+
border: 1px solid var(--nx-border);
|
|
26
|
+
border-radius: var(--nx-radius-lg);
|
|
27
|
+
background: var(--nx-surface);
|
|
28
|
+
/* A link to a card (`#emails`) leaves a little room above it. */
|
|
29
|
+
scroll-margin-block: var(--nx-space-4);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.nx-record-card--wide {
|
|
33
|
+
grid-column: 1 / -1;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.nx-record-card__head {
|
|
37
|
+
display: flex;
|
|
38
|
+
align-items: flex-start;
|
|
39
|
+
gap: var(--nx-space-3);
|
|
40
|
+
padding: var(--nx-space-4) var(--nx-space-4) 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* The card's icon on a soft tint of the theme's colour: an icon, so 3:1 is its floor. */
|
|
44
|
+
.nx-record-card__icon {
|
|
45
|
+
display: grid;
|
|
46
|
+
flex: none;
|
|
47
|
+
place-items: center;
|
|
48
|
+
width: var(--nx-control-sm);
|
|
49
|
+
height: var(--nx-control-sm);
|
|
50
|
+
border-radius: var(--nx-radius);
|
|
51
|
+
background: color-mix(in oklab, var(--nx-primary) 12%, var(--nx-surface));
|
|
52
|
+
color: var(--nx-primary);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.nx-record-card__text {
|
|
56
|
+
display: grid;
|
|
57
|
+
flex: 1 1 auto;
|
|
58
|
+
align-content: center;
|
|
59
|
+
min-width: 0;
|
|
60
|
+
/* The title's line is a button's height, so a heading with buttons and one without line up. */
|
|
61
|
+
min-height: var(--nx-control-sm);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/*
|
|
65
|
+
* The title and its sentence, then the buttons. The text keeps at least 12rem beside them; a narrow card (a phone, two
|
|
66
|
+
* buttons, a long label) puts the buttons on a line of their own under the text, at its start, never squeezing the
|
|
67
|
+
* title to a few words a line.
|
|
68
|
+
*/
|
|
69
|
+
.nx-record-card__main {
|
|
70
|
+
display: flex;
|
|
71
|
+
flex: 1 1 auto;
|
|
72
|
+
flex-wrap: wrap;
|
|
73
|
+
align-items: flex-start;
|
|
74
|
+
gap: var(--nx-space-2) var(--nx-space-3);
|
|
75
|
+
min-width: 0;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.nx-record-card__main > .nx-record-card__text {
|
|
79
|
+
flex: 1 1 12rem;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* A title alone needs less: its buttons stay beside it down to 8rem. */
|
|
83
|
+
.nx-record-card__main > .nx-record-card__text:not(:has(> .nx-record-card__lead)) {
|
|
84
|
+
flex-basis: 8rem;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.nx-record-card__main > .nx-record-card__actions {
|
|
88
|
+
justify-content: flex-start;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.nx-record-card__title {
|
|
92
|
+
display: flex;
|
|
93
|
+
flex-wrap: wrap;
|
|
94
|
+
align-items: baseline;
|
|
95
|
+
gap: 0 var(--nx-space-2);
|
|
96
|
+
margin: 0;
|
|
97
|
+
font-size: var(--nx-text-lg);
|
|
98
|
+
font-weight: 600;
|
|
99
|
+
line-height: var(--nx-control-sm);
|
|
100
|
+
overflow-wrap: anywhere;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/* Focused from code only (the focus coming home after a popup), never by Tab: no ring of its own. */
|
|
104
|
+
.nx-record-card__title:focus {
|
|
105
|
+
outline: none;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* Its own line height, so the title's line is the same with a count and without one (while the list is read). */
|
|
109
|
+
.nx-record-card__count {
|
|
110
|
+
color: var(--nx-text-muted);
|
|
111
|
+
line-height: 1;
|
|
112
|
+
font-size: var(--nx-text-sm);
|
|
113
|
+
font-weight: 500;
|
|
114
|
+
font-variant-numeric: tabular-nums;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.nx-record-card__lead {
|
|
118
|
+
margin: 0 0 var(--nx-space-1);
|
|
119
|
+
color: var(--nx-text-muted);
|
|
120
|
+
font-size: var(--nx-text-sm);
|
|
121
|
+
line-height: 1.45;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.nx-record-card__actions {
|
|
125
|
+
display: flex;
|
|
126
|
+
flex: none;
|
|
127
|
+
flex-wrap: wrap;
|
|
128
|
+
justify-content: flex-end;
|
|
129
|
+
gap: var(--nx-space-2);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.nx-record-card__body {
|
|
133
|
+
min-width: 0;
|
|
134
|
+
padding: var(--nx-space-3) var(--nx-space-4) var(--nx-space-4);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.nx-record-card__empty {
|
|
138
|
+
margin: 0;
|
|
139
|
+
color: var(--nx-text-muted);
|
|
140
|
+
font-size: var(--nx-text-sm);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.nx-record-card__message {
|
|
144
|
+
margin: 0 0 var(--nx-space-3);
|
|
145
|
+
font-size: var(--nx-text-md);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/* A list reaches the card's edges, its last row as close to the foot as the heading is to the first. */
|
|
149
|
+
.nx-record-card--items > .nx-record-card__body {
|
|
150
|
+
padding: var(--nx-space-2) 0 var(--nx-space-1);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.nx-record-card--items > .nx-record-card__body > :is(.nx-record-card__empty, .nx-record__failed) {
|
|
154
|
+
margin: var(--nx-space-1) var(--nx-space-4) var(--nx-space-3);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/* A card of the page's own stacks what it is given at the cards' own gap, a paragraph's margins dropped. */
|
|
158
|
+
.nx-record-card--content > .nx-record-card__body {
|
|
159
|
+
display: grid;
|
|
160
|
+
gap: var(--nx-space-3);
|
|
161
|
+
align-content: start;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.nx-record-card--content > .nx-record-card__body > * {
|
|
165
|
+
margin-block: 0;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/* While a source loads: the table's bone, on the line it holds (the table draws it as a block, so two classes). */
|
|
169
|
+
.nx-table__bone.nx-record__bone {
|
|
170
|
+
display: inline-block;
|
|
171
|
+
max-width: 100%;
|
|
172
|
+
vertical-align: baseline;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/* A mark held while it is read: a tag's size, the bone's tint. */
|
|
176
|
+
.nx-record__bone-tag {
|
|
177
|
+
width: 7rem;
|
|
178
|
+
background: color-mix(in oklab, var(--nx-text) 9%, transparent);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.nx-record__held {
|
|
182
|
+
display: grid;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/* A held line is a line box of the text it stands for (its font and line height), its bone on the baseline. */
|
|
186
|
+
.nx-record__held-line,
|
|
187
|
+
.nx-record-item__text > .nx-record__held-line {
|
|
188
|
+
display: block;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/* The hero */
|
|
192
|
+
|
|
193
|
+
.nx-record-hero {
|
|
194
|
+
--nx-record-hero-picture: 5.5rem;
|
|
195
|
+
|
|
196
|
+
display: flex;
|
|
197
|
+
align-items: center;
|
|
198
|
+
gap: var(--nx-space-4);
|
|
199
|
+
padding: var(--nx-space-4) var(--nx-space-5);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.nx-record-hero__picture {
|
|
203
|
+
display: flex;
|
|
204
|
+
flex: none;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.nx-record-hero__text {
|
|
208
|
+
display: grid;
|
|
209
|
+
flex: 1 1 auto;
|
|
210
|
+
gap: 2px;
|
|
211
|
+
min-width: 0;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.nx-record-hero__title {
|
|
215
|
+
margin: 0;
|
|
216
|
+
font-size: var(--nx-text-xl);
|
|
217
|
+
font-weight: 650;
|
|
218
|
+
letter-spacing: -0.01em;
|
|
219
|
+
line-height: 1.3;
|
|
220
|
+
overflow-wrap: anywhere;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.nx-record-hero__line {
|
|
224
|
+
margin: 0;
|
|
225
|
+
color: var(--nx-text-muted);
|
|
226
|
+
font-size: var(--nx-text-sm);
|
|
227
|
+
line-height: 1.45;
|
|
228
|
+
overflow-wrap: anywhere;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.nx-record-hero__marks {
|
|
232
|
+
display: flex;
|
|
233
|
+
flex-wrap: wrap;
|
|
234
|
+
gap: 4px;
|
|
235
|
+
margin-top: var(--nx-space-1);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.nx-record-hero > .nx-record-card__actions {
|
|
239
|
+
align-self: flex-start;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/* Fields: label over value, as many to a row as have 11rem; long text and chips across. */
|
|
243
|
+
|
|
244
|
+
.nx-record-fields {
|
|
245
|
+
display: grid;
|
|
246
|
+
grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr));
|
|
247
|
+
gap: var(--nx-space-3) var(--nx-space-4);
|
|
248
|
+
margin: 0;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.nx-record-field {
|
|
252
|
+
min-width: 0;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.nx-record-field--wide {
|
|
256
|
+
grid-column: 1 / -1;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.nx-record-field__label {
|
|
260
|
+
color: var(--nx-text-muted);
|
|
261
|
+
font-size: var(--nx-text-xs);
|
|
262
|
+
font-weight: 500;
|
|
263
|
+
line-height: 1.5;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/* One line's height while it loads too, so nothing moves when the values come. */
|
|
267
|
+
.nx-record-field__value {
|
|
268
|
+
min-height: 1.45em;
|
|
269
|
+
margin: 0;
|
|
270
|
+
font-size: var(--nx-text-md);
|
|
271
|
+
line-height: 1.45;
|
|
272
|
+
overflow-wrap: anywhere;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.nx-record-field__empty {
|
|
276
|
+
color: var(--nx-text-muted);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.nx-record-field__lines {
|
|
280
|
+
white-space: pre-line;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.nx-record-chips {
|
|
284
|
+
display: flex;
|
|
285
|
+
flex-wrap: wrap;
|
|
286
|
+
gap: 4px;
|
|
287
|
+
margin: 2px 0 0;
|
|
288
|
+
padding: 0;
|
|
289
|
+
list-style: none;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/* Items: rows between hairlines, a picture or an icon, the name and its marks, lines, and icon buttons on the right. */
|
|
293
|
+
|
|
294
|
+
.nx-record-items {
|
|
295
|
+
display: grid;
|
|
296
|
+
margin: 0;
|
|
297
|
+
padding: 0;
|
|
298
|
+
list-style: none;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
.nx-record-item {
|
|
302
|
+
display: flex;
|
|
303
|
+
align-items: center;
|
|
304
|
+
gap: var(--nx-space-3);
|
|
305
|
+
min-width: 0;
|
|
306
|
+
padding: var(--nx-space-2) var(--nx-space-4);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.nx-record-item + .nx-record-item {
|
|
310
|
+
border-top: 1px solid var(--nx-border);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
.nx-record-item__media {
|
|
314
|
+
display: grid;
|
|
315
|
+
flex: none;
|
|
316
|
+
place-items: center;
|
|
317
|
+
width: var(--nx-control-md);
|
|
318
|
+
height: var(--nx-control-md);
|
|
319
|
+
overflow: hidden;
|
|
320
|
+
border-radius: 50%;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
.nx-record-item__media--icon {
|
|
324
|
+
border-radius: var(--nx-radius);
|
|
325
|
+
background: color-mix(in oklab, var(--nx-text) 6%, var(--nx-surface));
|
|
326
|
+
color: var(--nx-text-muted);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.nx-record-item__media--held {
|
|
330
|
+
background: color-mix(in oklab, var(--nx-text) 9%, transparent);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
.nx-record-item__text {
|
|
334
|
+
display: grid;
|
|
335
|
+
flex: 1 1 auto;
|
|
336
|
+
gap: 2px;
|
|
337
|
+
min-width: 0;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/* At least a mark's height, so a row is as tall with marks as without, and as its held row. */
|
|
341
|
+
.nx-record-item__title {
|
|
342
|
+
display: flex;
|
|
343
|
+
flex-wrap: wrap;
|
|
344
|
+
align-items: center;
|
|
345
|
+
gap: 2px var(--nx-space-2);
|
|
346
|
+
min-height: calc(var(--nx-text-xs) * 1.6 + 2px);
|
|
347
|
+
margin: 0;
|
|
348
|
+
font-size: var(--nx-text-md);
|
|
349
|
+
font-weight: 500;
|
|
350
|
+
line-height: 1.45;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
.nx-record-item__name {
|
|
354
|
+
min-width: 0;
|
|
355
|
+
overflow-wrap: anywhere;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.nx-record-item__marks {
|
|
359
|
+
display: inline-flex;
|
|
360
|
+
flex-wrap: wrap;
|
|
361
|
+
gap: 4px;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
.nx-record-item__line {
|
|
365
|
+
margin: 0;
|
|
366
|
+
color: var(--nx-text-muted);
|
|
367
|
+
font-size: var(--nx-text-sm);
|
|
368
|
+
line-height: 1.45;
|
|
369
|
+
overflow-wrap: anywhere;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
.nx-record-item__actions {
|
|
373
|
+
display: flex;
|
|
374
|
+
flex: none;
|
|
375
|
+
align-items: center;
|
|
376
|
+
gap: 2px;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/* A popup's step: its sentence over the form, and the button that stays on it under. */
|
|
380
|
+
|
|
381
|
+
.nx-record-step {
|
|
382
|
+
display: grid;
|
|
383
|
+
gap: var(--nx-space-3);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
.nx-record-step__lead {
|
|
387
|
+
font-size: var(--nx-text-md);
|
|
388
|
+
line-height: 1.5;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
.nx-record-step__lead > p {
|
|
392
|
+
margin: 0;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
.nx-record-step__also {
|
|
396
|
+
margin: 0;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/* A narrow page (a phone, a popup): the hero's picture smaller, its padding the cards'. */
|
|
400
|
+
@container (max-width: 34rem) {
|
|
401
|
+
.nx-record-hero {
|
|
402
|
+
--nx-record-hero-picture: 4rem;
|
|
403
|
+
|
|
404
|
+
gap: var(--nx-space-3);
|
|
405
|
+
padding: var(--nx-space-4);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
.nx-record-hero__title {
|
|
409
|
+
font-size: var(--nx-text-lg);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
.nx-record-card__head {
|
|
413
|
+
padding: var(--nx-space-3) var(--nx-space-3) 0;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
.nx-record-card__body {
|
|
417
|
+
padding: var(--nx-space-3);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
.nx-record-item {
|
|
421
|
+
gap: var(--nx-space-2);
|
|
422
|
+
padding-inline: var(--nx-space-3);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
.nx-record-item__media {
|
|
426
|
+
width: var(--nx-control-sm);
|
|
427
|
+
height: var(--nx-control-sm);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|