nexus-shared 3.0.0 → 3.1.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.
Files changed (121) hide show
  1. package/CHANGELOG.md +446 -262
  2. package/LICENSE +21 -21
  3. package/README.md +1084 -1000
  4. package/dist/Client.Index.d.ts +3 -0
  5. package/dist/Client.Index.js +3 -0
  6. package/dist/Components/Chats/ChatParts.d.ts +2 -2
  7. package/dist/Components/Chats/ChatParts.js +3 -7
  8. package/dist/Components/Chats/ChatThread.js +3 -3
  9. package/dist/Components/Documents/Button.d.ts +6 -1
  10. package/dist/Components/Documents/Button.js +2 -2
  11. package/dist/Components/Documents/Menu.js +21 -9
  12. package/dist/Components/Documents/SplitButton.d.ts +3 -1
  13. package/dist/Components/Documents/SplitButton.js +7 -5
  14. package/dist/Components/Documents/TabButtons.d.ts +5 -2
  15. package/dist/Components/Documents/TabButtons.js +2 -2
  16. package/dist/Components/Forms/ApiForm.d.ts +1 -1
  17. package/dist/Components/Forms/ApiForm.js +1 -1
  18. package/dist/Components/Forms/Crud.js +177 -58
  19. package/dist/Components/Forms/CrudParts.d.ts +5 -1
  20. package/dist/Components/Forms/CrudParts.js +37 -5
  21. package/dist/Components/Forms/ExcelImport.d.ts +23 -7
  22. package/dist/Components/Forms/ExcelImport.js +189 -60
  23. package/dist/Components/Forms/Form.js +5 -13
  24. package/dist/Components/Forms/SubmitForm.d.ts +11 -2
  25. package/dist/Components/Forms/SubmitForm.js +23 -12
  26. package/dist/Components/Inputs/DropdownParts.d.ts +1 -1
  27. package/dist/Components/Inputs/DropdownParts.js +4 -6
  28. package/dist/Components/Inputs/NumberBox.js +24 -2
  29. package/dist/Components/Inputs/RowsInput.js +2 -2
  30. package/dist/Components/Inputs/Slider.js +4 -1
  31. package/dist/Components/Inputs/TabularForm.js +42 -10
  32. package/dist/Components/Inputs/TimePanel.js +4 -3
  33. package/dist/Components/Layouts/Popup.js +1 -4
  34. package/dist/Components/Layouts/ThemePicker.d.ts +20 -3
  35. package/dist/Components/Layouts/ThemePicker.js +77 -6
  36. package/dist/Components/Layouts/ThemeScript.d.ts +4 -2
  37. package/dist/Components/Layouts/ThemeScript.js +4 -2
  38. package/dist/Components/Layouts/ThemeSwitcher.d.ts +6 -3
  39. package/dist/Components/Layouts/ThemeSwitcher.js +9 -8
  40. package/dist/Components/Viewers/Avatar.d.ts +21 -0
  41. package/dist/Components/Viewers/Avatar.js +21 -0
  42. package/dist/Components/Viewers/DataTable.js +192 -44
  43. package/dist/Components/Viewers/DataTableColumns.d.ts +7 -3
  44. package/dist/Components/Viewers/DataTableColumns.js +25 -68
  45. package/dist/Components/Viewers/DataTableFilters.d.ts +21 -0
  46. package/dist/Components/Viewers/DataTableFilters.js +68 -0
  47. package/dist/Components/Viewers/DataTableParts.d.ts +2 -2
  48. package/dist/Components/Viewers/DataTableParts.js +3 -3
  49. package/dist/Helpers/AnimationHelpers.d.ts +11 -0
  50. package/dist/Helpers/AnimationHelpers.js +20 -2
  51. package/dist/Helpers/CrudBackend.d.ts +7 -4
  52. package/dist/Helpers/CrudBackend.js +4 -2
  53. package/dist/Helpers/ExcelBackend.d.ts +3 -3
  54. package/dist/Helpers/ExcelBackend.js +8 -2
  55. package/dist/Helpers/ExcelHelpers.d.ts +36 -8
  56. package/dist/Helpers/ExcelHelpers.js +55 -13
  57. package/dist/Helpers/FormStore.d.ts +9 -5
  58. package/dist/Helpers/FormStore.js +25 -5
  59. package/dist/Helpers/MessageBuilder.js +1 -0
  60. package/dist/Helpers/NumberHelpers.d.ts +7 -1
  61. package/dist/Helpers/NumberHelpers.js +41 -3
  62. package/dist/Helpers/PopoverHelpers.d.ts +17 -5
  63. package/dist/Helpers/PopoverHelpers.js +52 -17
  64. package/dist/Helpers/PopoverHooks.d.ts +24 -0
  65. package/dist/Helpers/PopoverHooks.js +62 -0
  66. package/dist/Helpers/RowsStore.d.ts +7 -2
  67. package/dist/Helpers/RowsStore.js +15 -3
  68. package/dist/Helpers/TableExport.js +12 -12
  69. package/dist/Helpers/TableFilters.d.ts +25 -0
  70. package/dist/Helpers/TableFilters.js +162 -0
  71. package/dist/Helpers/TableHelpers.d.ts +6 -3
  72. package/dist/Helpers/TableHelpers.js +8 -4
  73. package/dist/Helpers/TableStore.d.ts +11 -3
  74. package/dist/Helpers/TableStore.js +16 -5
  75. package/dist/Helpers/ThemeHelpers.d.ts +21 -4
  76. package/dist/Helpers/ThemeHelpers.js +46 -9
  77. package/dist/Helpers/UserPreferences.d.ts +14 -0
  78. package/dist/Helpers/UserPreferences.js +99 -0
  79. package/dist/Interfaces/CrudInterfaces.d.ts +20 -1
  80. package/dist/Interfaces/ExcelInterfaces.d.ts +12 -0
  81. package/dist/Interfaces/FormInterfaces.d.ts +33 -5
  82. package/dist/Interfaces/PreferenceInterfaces.d.ts +43 -0
  83. package/dist/Interfaces/PreferenceInterfaces.js +28 -0
  84. package/dist/Interfaces/TableInterfaces.d.ts +59 -12
  85. package/dist/Interfaces/ThemeInterfaces.d.ts +25 -0
  86. package/dist/Interfaces/ThemeInterfaces.js +15 -0
  87. package/dist/Services/ExcelApi.d.ts +3 -1
  88. package/dist/Services/ExcelApi.js +1 -1
  89. package/dist/Services/ThemeService.d.ts +18 -2
  90. package/dist/Services/ThemeService.js +80 -16
  91. package/dist/Shared.Index.d.ts +2 -0
  92. package/dist/Shared.Index.js +2 -0
  93. package/package.json +85 -85
  94. package/src/Styles/Nexus.Avatar.css +79 -0
  95. package/src/Styles/Nexus.Base.css +117 -70
  96. package/src/Styles/Nexus.Button.css +180 -153
  97. package/src/Styles/Nexus.Calendar.css +273 -275
  98. package/src/Styles/Nexus.Chat.css +1443 -1489
  99. package/src/Styles/Nexus.Choice.css +343 -345
  100. package/src/Styles/Nexus.Crud.css +168 -161
  101. package/src/Styles/Nexus.DateTime.css +81 -81
  102. package/src/Styles/Nexus.Dropdown.css +725 -774
  103. package/src/Styles/Nexus.Editor.css +295 -297
  104. package/src/Styles/Nexus.Excel.css +389 -370
  105. package/src/Styles/Nexus.Form.css +279 -321
  106. package/src/Styles/Nexus.Index.css +37 -36
  107. package/src/Styles/Nexus.Input.css +602 -637
  108. package/src/Styles/Nexus.Markdown.css +237 -265
  109. package/src/Styles/Nexus.Menu.css +237 -259
  110. package/src/Styles/Nexus.Popup.css +724 -731
  111. package/src/Styles/Nexus.RichText.css +2 -32
  112. package/src/Styles/Nexus.Rows.css +637 -596
  113. package/src/Styles/Nexus.Slider.css +276 -278
  114. package/src/Styles/Nexus.Tab.Buttons.css +432 -419
  115. package/src/Styles/Nexus.Table.css +1386 -1296
  116. package/src/Styles/Nexus.Theme.Picker.css +286 -232
  117. package/src/Styles/Nexus.Themes.css +194 -194
  118. package/src/Styles/Nexus.Time.css +144 -147
  119. package/src/Styles/Nexus.Toast.css +263 -265
  120. package/src/Styles/Nexus.Tokens.css +89 -72
  121. package/src/Styles/Nexus.Tree.css +431 -435
@@ -1,321 +1,279 @@
1
- /*
2
- * Forms: inputs on a 12-column grid, the note of a restored draft, placeholders while the values load, and the bar with
3
- * the status line and the buttons.
4
- */
5
- @layer nexus.components {
6
- .nx-form {
7
- position: relative;
8
- display: flex;
9
- flex-direction: column;
10
- gap: var(--nx-space-4);
11
- min-width: 0;
12
- }
13
-
14
- .nx-form__grid {
15
- container-type: inline-size;
16
- display: grid;
17
- grid-template-columns: repeat(12, minmax(0, 1fr));
18
- align-items: start;
19
- gap: var(--nx-form-row-gap, var(--nx-space-5)) var(--nx-form-column-gap, var(--nx-space-4));
20
- }
21
-
22
- /* A heading that names the inputs under it. It takes a row of its own, across the whole grid. */
23
- .nx-form__section {
24
- grid-column: 1 / -1;
25
- margin: 0;
26
- color: var(--nx-text);
27
- font-size: var(--nx-text-sm);
28
- font-weight: 600;
29
- line-height: 1.3;
30
- }
31
-
32
- /* One that follows inputs stands away from them; the first one keeps the form's own top. */
33
- .nx-form__section:not(:first-child) {
34
- margin-top: var(--nx-space-2);
35
- }
36
-
37
- .nx-form--sm .nx-form__section {
38
- font-size: var(--nx-text-xs);
39
- }
40
-
41
- .nx-form--lg .nx-form__section {
42
- font-size: var(--nx-text-md);
43
- }
44
-
45
- .nx-form__cell {
46
- grid-column: span var(--nx-span, 12);
47
- min-width: 0;
48
- }
49
-
50
- /* A checkbox, switch, or radio lines up with the boxes beside it. */
51
- .nx-form__cell--choice {
52
- display: flex;
53
- align-self: end;
54
- align-items: center;
55
- min-height: var(--nx-control-md);
56
- }
57
-
58
- .nx-form--sm .nx-form__cell--choice {
59
- min-height: var(--nx-control-sm);
60
- }
61
-
62
- .nx-form--lg .nx-form__cell--choice {
63
- min-height: var(--nx-control-lg);
64
- }
65
-
66
- /*
67
- * Beside labeled boxes, a choice starts under the room of their labels and centers on their boxes, so a message under a
68
- * box beside it does not move it. The label's line is 1.3 times its font, and 6px separate it from the box.
69
- */
70
- .nx-form__cell--choice[data-beside] {
71
- --nx-form-label-room: calc(var(--nx-text-sm) * 1.3 + 6px);
72
- align-self: start;
73
- min-height: calc(var(--nx-form-label-room) + var(--nx-control-md));
74
- padding-top: var(--nx-form-label-room);
75
- }
76
-
77
- .nx-form--sm .nx-form__cell--choice[data-beside] {
78
- --nx-form-label-room: calc(var(--nx-text-xs) * 1.3 + 6px);
79
- min-height: calc(var(--nx-form-label-room) + var(--nx-control-sm));
80
- }
81
-
82
- .nx-form--lg .nx-form__cell--choice[data-beside] {
83
- --nx-form-label-room: calc(var(--nx-text-md) * 1.3 + 6px);
84
- min-height: calc(var(--nx-form-label-room) + var(--nx-control-lg));
85
- }
86
-
87
- /* Three or four inputs to a row become two on a medium form, and every input takes the whole width on a narrow one. */
88
- @container (max-width: 48rem) {
89
- .nx-form__cell:is([data-span="1"], [data-span="2"], [data-span="3"]) {
90
- grid-column: span 6;
91
- }
92
- }
93
-
94
- @container (max-width: 34rem) {
95
- .nx-form__cell,
96
- .nx-form__cell:is([data-span="1"], [data-span="2"], [data-span="3"]) {
97
- grid-column: span 12;
98
- }
99
-
100
- .nx-form__cell--choice,
101
- .nx-form__cell--choice[data-beside] {
102
- min-height: 0;
103
- padding-top: 0;
104
- }
105
- }
106
-
107
- .nx-form__message {
108
- margin: 0;
109
- font-size: var(--nx-text-sm);
110
- }
111
-
112
- /* A restored draft */
113
- .nx-form__notice {
114
- display: flex;
115
- flex-wrap: wrap;
116
- align-items: center;
117
- gap: var(--nx-space-1) var(--nx-space-2);
118
- padding: var(--nx-space-2) var(--nx-space-2) var(--nx-space-2) var(--nx-space-3);
119
- border-radius: var(--nx-radius);
120
- background: var(--nx-info-soft);
121
- color: var(--nx-text);
122
- font-size: var(--nx-text-sm);
123
- line-height: 1.4;
124
- }
125
-
126
- .nx-form__notice > .nx-icon {
127
- width: 1.3em;
128
- height: 1.3em;
129
- color: var(--nx-info);
130
- }
131
-
132
- .nx-form__notice-text {
133
- flex: 1 1 16rem;
134
- min-width: 0;
135
- margin: 0;
136
- }
137
-
138
- .nx-form__notice-text strong {
139
- font-weight: 600;
140
- }
141
-
142
- .nx-form__notice .nx-btn {
143
- margin-block: -4px;
144
- }
145
-
146
- /* Placeholders while the values load, in the shape of the inputs to come. */
147
- .nx-form__skeleton {
148
- display: flex;
149
- flex-direction: column;
150
- gap: 6px;
151
- }
152
-
153
- /* A checkbox's placeholder starts where its box would. */
154
- .nx-form__skeleton.nx-form__cell--choice {
155
- flex-direction: row;
156
- }
157
-
158
- .nx-form__skeleton-label,
159
- .nx-form__skeleton-box {
160
- display: block;
161
- border-radius: var(--nx-radius-sm);
162
- background: color-mix(in oklab, var(--nx-text) 9%, transparent);
163
- animation: nx-form-pulse 1.6s ease-in-out infinite;
164
- }
165
-
166
- /* The label's line: 1.3 × the label font, with the text's height as the bar. */
167
- .nx-form__skeleton-label {
168
- width: min(40%, 10rem);
169
- height: 0.85em;
170
- margin-block: 0.225em;
171
- font-size: var(--nx-text-sm);
172
- }
173
-
174
- .nx-form__skeleton-box {
175
- height: var(--nx-control-md);
176
- border-radius: var(--nx-radius);
177
- }
178
-
179
- .nx-form--sm .nx-form__skeleton-box {
180
- height: var(--nx-control-sm);
181
- }
182
-
183
- .nx-form--lg .nx-form__skeleton-box {
184
- height: var(--nx-control-lg);
185
- }
186
-
187
- .nx-form__skeleton-box--tall,
188
- .nx-form--sm .nx-form__skeleton-box--tall,
189
- .nx-form--lg .nx-form__skeleton-box--tall {
190
- height: calc(var(--nx-control-md) * 2.75);
191
- }
192
-
193
- .nx-form__skeleton-box--choice,
194
- .nx-form--sm .nx-form__skeleton-box--choice,
195
- .nx-form--lg .nx-form__skeleton-box--choice {
196
- width: min(60%, 12rem);
197
- height: 1.1em;
198
- }
199
-
200
- @keyframes nx-form-pulse {
201
- 50% {
202
- opacity: 0.45;
203
- }
204
- }
205
-
206
- @media (prefers-reduced-motion: reduce) {
207
- .nx-form__skeleton-label,
208
- .nx-form__skeleton-box {
209
- animation: none;
210
- }
211
- }
212
-
213
- /* SubmitForm */
214
- .nx-submit-form {
215
- display: flex;
216
- flex-direction: column;
217
- gap: var(--nx-space-6);
218
- min-width: 0;
219
- }
220
-
221
- /* The bar: the status line and the buttons, which wrap under it on a narrow form. */
222
- .nx-form-buttons {
223
- display: flex;
224
- flex-wrap: wrap;
225
- align-items: center;
226
- gap: var(--nx-space-3) var(--nx-space-4);
227
- }
228
-
229
- .nx-form-buttons__actions {
230
- display: flex;
231
- flex-wrap: wrap;
232
- align-items: center;
233
- gap: var(--nx-space-2);
234
- }
235
-
236
- .nx-form-buttons--end .nx-form-buttons__actions {
237
- margin-left: auto;
238
- }
239
-
240
- .nx-form-status {
241
- display: flex;
242
- flex: 1 1 14rem;
243
- align-items: flex-start;
244
- gap: 6px;
245
- min-width: 0;
246
- margin: 0;
247
- color: var(--nx-text-muted);
248
- font-size: var(--nx-text-sm);
249
- line-height: 1.45;
250
- }
251
-
252
- .nx-form-status .nx-icon {
253
- flex-shrink: 0;
254
- width: 1.3em;
255
- height: 1.3em;
256
- margin-top: 0.075em;
257
- }
258
-
259
- .nx-form-status--error {
260
- color: var(--nx-danger);
261
- font-weight: 500;
262
- }
263
-
264
- .nx-form-status--success {
265
- color: var(--nx-success);
266
- }
267
-
268
- /* An input's name in the status line: a link-like button that goes to it. */
269
- .nx-form-status__jump {
270
- padding: 0;
271
- border: 0;
272
- border-radius: 2px;
273
- background: none;
274
- color: inherit;
275
- font: inherit;
276
- text-decoration: underline;
277
- text-decoration-thickness: 1px;
278
- text-underline-offset: 2px;
279
- cursor: pointer;
280
- }
281
-
282
- .nx-form-status__jump:hover {
283
- text-decoration-thickness: 2px;
284
- }
285
-
286
- /* ApiForm: the values could not load */
287
- .nx-form-load-failed {
288
- display: flex;
289
- flex-wrap: wrap;
290
- align-items: center;
291
- gap: var(--nx-space-2) var(--nx-space-3);
292
- padding: var(--nx-space-3) var(--nx-space-3) var(--nx-space-3) var(--nx-space-4);
293
- border-radius: var(--nx-radius);
294
- background: var(--nx-danger-soft);
295
- color: var(--nx-text);
296
- font-size: var(--nx-text-sm);
297
- line-height: 1.45;
298
- }
299
-
300
- .nx-form-load-failed > .nx-icon {
301
- width: 1.35em;
302
- height: 1.35em;
303
- color: var(--nx-danger);
304
- }
305
-
306
- .nx-form-load-failed p {
307
- flex: 1 1 16rem;
308
- min-width: 0;
309
- margin: 0;
310
- }
311
-
312
- .nx-form-load-failed strong {
313
- font-weight: 600;
314
- }
315
-
316
- .nx-form-load-failed__actions {
317
- display: flex;
318
- gap: var(--nx-space-2);
319
- margin-left: auto;
320
- }
321
- }
1
+ /*
2
+ * Forms: inputs on a 12-column grid, the note of a restored draft, placeholders while the values load, and the bar with
3
+ * the status line and the buttons.
4
+ */
5
+ @layer nexus.components {
6
+ .nx-form {
7
+ position: relative;
8
+ display: flex;
9
+ flex-direction: column;
10
+ gap: var(--nx-space-4);
11
+ min-width: 0;
12
+ }
13
+
14
+ .nx-form__grid {
15
+ container-type: inline-size;
16
+ display: grid;
17
+ grid-template-columns: repeat(12, minmax(0, 1fr));
18
+ align-items: start;
19
+ gap: var(--nx-form-row-gap, var(--nx-space-5)) var(--nx-form-column-gap, var(--nx-space-4));
20
+ }
21
+
22
+ /* A heading that names the inputs under it. It takes a row of its own, across the whole grid. */
23
+ .nx-form__section {
24
+ grid-column: 1 / -1;
25
+ margin: 0;
26
+ color: var(--nx-text);
27
+ font-size: var(--nx-text-sm);
28
+ font-weight: 600;
29
+ line-height: 1.3;
30
+ }
31
+
32
+ /* One that follows inputs stands away from them; the first one keeps the form's own top. */
33
+ .nx-form__section:not(:first-child) {
34
+ margin-top: var(--nx-space-2);
35
+ }
36
+
37
+ .nx-form--sm .nx-form__section {
38
+ font-size: var(--nx-text-xs);
39
+ }
40
+
41
+ .nx-form--lg .nx-form__section {
42
+ font-size: var(--nx-text-md);
43
+ }
44
+
45
+ .nx-form__cell {
46
+ grid-column: span var(--nx-span, 12);
47
+ min-width: 0;
48
+ }
49
+
50
+ /* A checkbox, switch, or radio lines up with the boxes beside it. */
51
+ .nx-form__cell--choice {
52
+ display: flex;
53
+ align-self: end;
54
+ align-items: center;
55
+ min-height: var(--nx-control-md);
56
+ }
57
+
58
+ .nx-form--sm .nx-form__cell--choice {
59
+ min-height: var(--nx-control-sm);
60
+ }
61
+
62
+ .nx-form--lg .nx-form__cell--choice {
63
+ min-height: var(--nx-control-lg);
64
+ }
65
+
66
+ /*
67
+ * Beside labeled boxes, a choice starts under the room of their labels and centers on their boxes, so a message under a
68
+ * box beside it does not move it. The label's line is 1.3 times its font, and 6px separate it from the box.
69
+ */
70
+ .nx-form__cell--choice[data-beside] {
71
+ --nx-form-label-room: calc(var(--nx-text-sm) * 1.3 + 6px);
72
+ align-self: start;
73
+ min-height: calc(var(--nx-form-label-room) + var(--nx-control-md));
74
+ padding-top: var(--nx-form-label-room);
75
+ }
76
+
77
+ .nx-form--sm .nx-form__cell--choice[data-beside] {
78
+ --nx-form-label-room: calc(var(--nx-text-xs) * 1.3 + 6px);
79
+ min-height: calc(var(--nx-form-label-room) + var(--nx-control-sm));
80
+ }
81
+
82
+ .nx-form--lg .nx-form__cell--choice[data-beside] {
83
+ --nx-form-label-room: calc(var(--nx-text-md) * 1.3 + 6px);
84
+ min-height: calc(var(--nx-form-label-room) + var(--nx-control-lg));
85
+ }
86
+
87
+ /* Three or four inputs to a row become two on a medium form, and every input takes the whole width on a narrow one. */
88
+ @container (max-width: 48rem) {
89
+ .nx-form__cell:is([data-span="1"], [data-span="2"], [data-span="3"]) {
90
+ grid-column: span 6;
91
+ }
92
+ }
93
+
94
+ @container (max-width: 34rem) {
95
+ .nx-form__cell,
96
+ .nx-form__cell:is([data-span="1"], [data-span="2"], [data-span="3"]) {
97
+ grid-column: span 12;
98
+ }
99
+
100
+ .nx-form__cell--choice,
101
+ .nx-form__cell--choice[data-beside] {
102
+ min-height: 0;
103
+ padding-top: 0;
104
+ }
105
+ }
106
+
107
+ .nx-form__message {
108
+ margin: 0;
109
+ font-size: var(--nx-text-sm);
110
+ }
111
+
112
+ /* A restored draft */
113
+ .nx-form__notice {
114
+ display: flex;
115
+ flex-wrap: wrap;
116
+ align-items: center;
117
+ gap: var(--nx-space-1) var(--nx-space-2);
118
+ padding: var(--nx-space-2) var(--nx-space-2) var(--nx-space-2) var(--nx-space-3);
119
+ border-radius: var(--nx-radius);
120
+ background: var(--nx-info-soft);
121
+ color: var(--nx-text);
122
+ font-size: var(--nx-text-sm);
123
+ line-height: 1.4;
124
+ }
125
+
126
+ .nx-form__notice > .nx-icon {
127
+ width: 1.3em;
128
+ height: 1.3em;
129
+ color: var(--nx-info);
130
+ }
131
+
132
+ .nx-form__notice-text {
133
+ flex: 1 1 16rem;
134
+ min-width: 0;
135
+ margin: 0;
136
+ }
137
+
138
+ .nx-form__notice-text strong {
139
+ font-weight: 600;
140
+ }
141
+
142
+ .nx-form__notice .nx-btn {
143
+ margin-block: -4px;
144
+ }
145
+
146
+ /* SubmitForm */
147
+ .nx-submit-form {
148
+ display: flex;
149
+ flex-direction: column;
150
+ gap: var(--nx-space-6);
151
+ min-width: 0;
152
+ }
153
+
154
+ /* The bar: the status line and the buttons, which wrap under it on a narrow form. */
155
+ .nx-form-buttons {
156
+ display: flex;
157
+ flex-wrap: wrap;
158
+ align-items: center;
159
+ gap: var(--nx-space-3) var(--nx-space-4);
160
+ }
161
+
162
+ .nx-form-buttons__actions {
163
+ display: flex;
164
+ flex-wrap: wrap;
165
+ align-items: center;
166
+ gap: var(--nx-space-2);
167
+ }
168
+
169
+ .nx-form-buttons--end .nx-form-buttons__actions {
170
+ margin-left: auto;
171
+ }
172
+
173
+ /* `block`: the buttons share the bar's whole width, as a sign-in's one button fills its card. */
174
+ .nx-form-buttons--block .nx-form-buttons__actions {
175
+ width: 100%;
176
+ margin-left: 0;
177
+ }
178
+
179
+ .nx-form-buttons--block .nx-form-buttons__actions > .nx-btn {
180
+ flex: 1;
181
+ }
182
+
183
+ /* One line kept even when empty: "Loading…", "Saving…" and "Unsaved changes" come and go, and the bar never jumps. */
184
+ .nx-form-status {
185
+ display: flex;
186
+ flex: 1 1 14rem;
187
+ align-items: flex-start;
188
+ gap: 6px;
189
+ min-width: 0;
190
+ min-height: 1lh;
191
+ margin: 0;
192
+ color: var(--nx-text-muted);
193
+ font-size: var(--nx-text-sm);
194
+ line-height: 1.45;
195
+ }
196
+
197
+ .nx-form-status .nx-icon {
198
+ flex-shrink: 0;
199
+ width: 1.3em;
200
+ height: 1.3em;
201
+ margin-top: 0.075em;
202
+ }
203
+
204
+ .nx-form-status--error {
205
+ color: var(--nx-danger);
206
+ font-weight: 500;
207
+ }
208
+
209
+ .nx-form-status--success {
210
+ color: var(--nx-success);
211
+ }
212
+
213
+ /*
214
+ * An `errors` line has nothing to say until something goes wrong, so it keeps no room until then. It is clipped,
215
+ * not removed: a live region has to be there before its words arrive for a screen reader to read them.
216
+ */
217
+ .nx-form-status--errors:empty {
218
+ position: absolute;
219
+ width: 1px;
220
+ height: 1px;
221
+ min-height: 0;
222
+ overflow: hidden;
223
+ clip-path: inset(50%);
224
+ }
225
+
226
+ /* An input's name in the status line: a link-like button that goes to it. */
227
+ .nx-form-status__jump {
228
+ padding: 0;
229
+ border: 0;
230
+ border-radius: 2px;
231
+ background: none;
232
+ color: inherit;
233
+ font: inherit;
234
+ text-decoration: underline;
235
+ text-decoration-thickness: 1px;
236
+ text-underline-offset: 2px;
237
+ cursor: pointer;
238
+ }
239
+
240
+ .nx-form-status__jump:hover {
241
+ text-decoration-thickness: 2px;
242
+ }
243
+
244
+ /* ApiForm: the values could not load */
245
+ .nx-form-load-failed {
246
+ display: flex;
247
+ flex-wrap: wrap;
248
+ align-items: center;
249
+ gap: var(--nx-space-2) var(--nx-space-3);
250
+ padding: var(--nx-space-3) var(--nx-space-3) var(--nx-space-3) var(--nx-space-4);
251
+ border-radius: var(--nx-radius);
252
+ background: var(--nx-danger-soft);
253
+ color: var(--nx-text);
254
+ font-size: var(--nx-text-sm);
255
+ line-height: 1.45;
256
+ }
257
+
258
+ .nx-form-load-failed > .nx-icon {
259
+ width: 1.35em;
260
+ height: 1.35em;
261
+ color: var(--nx-danger);
262
+ }
263
+
264
+ .nx-form-load-failed p {
265
+ flex: 1 1 16rem;
266
+ min-width: 0;
267
+ margin: 0;
268
+ }
269
+
270
+ .nx-form-load-failed strong {
271
+ font-weight: 600;
272
+ }
273
+
274
+ .nx-form-load-failed__actions {
275
+ display: flex;
276
+ gap: var(--nx-space-2);
277
+ margin-left: auto;
278
+ }
279
+ }
@@ -1,36 +1,37 @@
1
- /*
2
- * nexus-shared styles: import once, at the root of the app.
3
- * import "nexus-shared/styles.css";
4
- *
5
- * Everything sits in cascade layers, so any style the app writes outside a layer wins without !important.
6
- * Themes: set data-nx-theme on <html> (nexus, github, nord, dracula, solarized, catppuccin, rose-pine),
7
- * and data-nx-mode="light" or "dark" to override the system setting. ThemeScript and ThemeSwitcher do both.
8
- */
9
- @layer nexus.tokens, nexus.themes, nexus.base, nexus.components;
10
-
11
- @import "./Nexus.Tokens.css";
12
- @import "./Nexus.Themes.css";
13
- @import "./Nexus.Base.css";
14
- @import "./Nexus.Button.css";
15
- @import "./Nexus.Calendar.css";
16
- @import "./Nexus.Chat.css";
17
- @import "./Nexus.DateTime.css";
18
- @import "./Nexus.Choice.css";
19
- @import "./Nexus.Crud.css";
20
- @import "./Nexus.Dropdown.css";
21
- @import "./Nexus.Input.css";
22
- @import "./Nexus.Editor.css";
23
- @import "./Nexus.Excel.css";
24
- @import "./Nexus.Form.css";
25
- @import "./Nexus.Markdown.css";
26
- @import "./Nexus.Menu.css";
27
- @import "./Nexus.Popup.css";
28
- @import "./Nexus.RichText.css";
29
- @import "./Nexus.Rows.css";
30
- @import "./Nexus.Slider.css";
31
- @import "./Nexus.Tab.Buttons.css";
32
- @import "./Nexus.Table.css";
33
- @import "./Nexus.Theme.Picker.css";
34
- @import "./Nexus.Time.css";
35
- @import "./Nexus.Toast.css";
36
- @import "./Nexus.Tree.css";
1
+ /*
2
+ * nexus-shared styles: import once, at the root of the app.
3
+ * import "nexus-shared/styles.css";
4
+ *
5
+ * Everything sits in cascade layers, so any style the app writes outside a layer wins without !important.
6
+ * Themes: set data-nx-theme on <html> (nexus, github, nord, dracula, solarized, catppuccin, rose-pine),
7
+ * and data-nx-mode="light" or "dark" to override the system setting. ThemeScript and ThemeSwitcher do both.
8
+ */
9
+ @layer nexus.tokens, nexus.themes, nexus.base, nexus.components;
10
+
11
+ @import "./Nexus.Tokens.css";
12
+ @import "./Nexus.Themes.css";
13
+ @import "./Nexus.Base.css";
14
+ @import "./Nexus.Avatar.css";
15
+ @import "./Nexus.Button.css";
16
+ @import "./Nexus.Calendar.css";
17
+ @import "./Nexus.Chat.css";
18
+ @import "./Nexus.DateTime.css";
19
+ @import "./Nexus.Choice.css";
20
+ @import "./Nexus.Crud.css";
21
+ @import "./Nexus.Dropdown.css";
22
+ @import "./Nexus.Input.css";
23
+ @import "./Nexus.Editor.css";
24
+ @import "./Nexus.Excel.css";
25
+ @import "./Nexus.Form.css";
26
+ @import "./Nexus.Markdown.css";
27
+ @import "./Nexus.Menu.css";
28
+ @import "./Nexus.Popup.css";
29
+ @import "./Nexus.RichText.css";
30
+ @import "./Nexus.Rows.css";
31
+ @import "./Nexus.Slider.css";
32
+ @import "./Nexus.Tab.Buttons.css";
33
+ @import "./Nexus.Table.css";
34
+ @import "./Nexus.Theme.Picker.css";
35
+ @import "./Nexus.Time.css";
36
+ @import "./Nexus.Toast.css";
37
+ @import "./Nexus.Tree.css";