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,232 +1,286 @@
1
- @layer nexus.components {
2
- /* Popover panel: a native [popover] element, placed by the component that opens it. In dark mode it is a step
3
- lighter than the surface it floats over, so it reads as raised.
4
- (The shared panel lives in the theme picker's file because that is where it was first needed; it belongs to
5
- every popover, not to the picker. Moving it would have to move its place in Nexus.Index.css with it.) */
6
- .nx-popover {
7
- /* The arrow's base and depth. Keep in step with ARROW_BASE and ARROW_DEPTH in Helpers/PopoverHelpers.ts, which
8
- work out the room the arrow needs, and with the two paths below, which are drawn for exactly these. */
9
- --nx-popover-arrow: 26px;
10
- --nx-popover-arrow-depth: 11px;
11
- /* The panel's edge, shared with the arrow's own: a panel that changes it changes both. */
12
- --nx-popover-edge: var(--nx-border);
13
-
14
- margin: 0;
15
- /* The browser's own [popover] rule says `overflow: auto`, which would cut the arrow off at the panel's edge and
16
- put a pair of scroll bars on a panel that fits. A panel that has to scroll scrolls a block inside itself. */
17
- overflow: visible;
18
- padding: var(--nx-space-4);
19
- border: 1px solid var(--nx-popover-edge);
20
- border-radius: var(--nx-radius-lg);
21
- background: light-dark(var(--nx-surface), var(--nx-surface-2));
22
- color: var(--nx-text);
23
- box-shadow: var(--nx-shadow);
24
- }
25
-
26
- /*
27
- * The arrow that ties a panel to the button or the place it opened from: an isosceles tail, 26px across and 11px
28
- * deep, with a slightly rounded tip. It is drawn in two layers, because a shape with a line along two of its sides
29
- * and nothing along the third cannot be one: `::before` is the whole tail in the panel's edge colour, `::after`
30
- * the same tail a pixel smaller on both slopes and a pixel longer at the base, in the panel's own background. What
31
- * is left of the first between them is the 1px line along the slopes; the second covers the panel's border across
32
- * the base, so the tail opens into the panel with no seam and no line across its mouth. Both paths are drawn for
33
- * the sizes above: change one and the other two have to be worked out again.
34
- *
35
- * `placeUnderAnchor` and `placeAtPoint` (Helpers/PopoverHelpers.ts) say which edge carries the tail and where
36
- * along that edge its tip sits, and leave both out when it would point at nothing. Nothing here animates: the tail
37
- * is drawn with the panel, so it is there in the first frame whether the opening animation runs or not.
38
- */
39
- .nx-popover[data-nx-arrow]::before,
40
- .nx-popover[data-nx-arrow]::after {
41
- content: "";
42
- position: absolute;
43
- /* The middle is only a fallback: the two are always written together, and taken away together. */
44
- left: var(--nx-popover-arrow-x, 50%);
45
- width: var(--nx-popover-arrow);
46
- /* A pixel past the tail's depth: the panel's own border, which the fill covers. */
47
- height: calc(var(--nx-popover-arrow-depth) + 1px);
48
- margin-left: calc(var(--nx-popover-arrow) / -2);
49
- }
50
-
51
- /* The tail's outline: tip rounded by 2px, feet on the panel's border line. */
52
- .nx-popover[data-nx-arrow]::before {
53
- background: var(--nx-popover-edge);
54
- clip-path: path("M 0 11 L 11.708 1.093 A 2 2 0 0 1 14.292 1.093 L 26 11 Z");
55
- }
56
-
57
- /* The fill: the same tail, 1px in from each slope (so the outline is left as a line) and 1px further down. */
58
- .nx-popover[data-nx-arrow]::after {
59
- background: inherit;
60
- clip-path: path("M 0.367 12 L 12.354 1.857 A 1 1 0 0 1 13.646 1.857 L 25.633 12 Z");
61
- }
62
-
63
- /* Below its anchor: the tail stands on the panel's top edge, pointing up. */
64
- .nx-popover[data-nx-arrow="below"]::before,
65
- .nx-popover[data-nx-arrow="below"]::after {
66
- top: calc(-1px - var(--nx-popover-arrow-depth));
67
- }
68
-
69
- /* Above its anchor: the same tail turned over, on the bottom edge. */
70
- .nx-popover[data-nx-arrow="above"]::before,
71
- .nx-popover[data-nx-arrow="above"]::after {
72
- bottom: calc(-1px - var(--nx-popover-arrow-depth));
73
- transform: scaleY(-1);
74
- }
75
-
76
- .nx-theme-switcher__panel {
77
- position: fixed;
78
- inset: auto;
79
- width: min(340px, calc(100vw - 16px));
80
- max-height: calc(100vh - 80px);
81
- }
82
-
83
- /* A shut popover is hidden by the browser, so the panel takes its layout only while it is open. */
84
- .nx-theme-switcher__panel:popover-open {
85
- display: flex;
86
- }
87
-
88
- /* The picker scrolls, not the panel: a panel that scrolls its own box would cut its arrow off. */
89
- .nx-theme-switcher__panel > .nx-theme-picker {
90
- flex: 1 1 auto;
91
- min-height: 0;
92
- overflow-y: auto;
93
- overscroll-behavior: contain;
94
- }
95
-
96
- .nx-theme-picker {
97
- display: grid;
98
- gap: var(--nx-space-4);
99
- }
100
-
101
- .nx-theme-picker__group {
102
- min-width: 0;
103
- margin: 0;
104
- padding: 0;
105
- border: 0;
106
- }
107
-
108
- .nx-theme-picker__legend {
109
- margin: 0 0 var(--nx-space-2);
110
- padding: 0;
111
- color: var(--nx-text-muted);
112
- font-size: var(--nx-text-xs);
113
- font-weight: 600;
114
- letter-spacing: 0.06em;
115
- text-transform: uppercase;
116
- }
117
-
118
- /* Theme cards */
119
- .nx-theme-picker__grid {
120
- display: grid;
121
- grid-template-columns: repeat(auto-fill, minmax(128px, 1fr));
122
- gap: var(--nx-space-2);
123
- }
124
-
125
- .nx-theme-option {
126
- display: grid;
127
- gap: 6px;
128
- padding: 5px;
129
- border: 1px solid var(--nx-border);
130
- border-radius: var(--nx-radius);
131
- background: var(--nx-surface);
132
- color: var(--nx-text);
133
- cursor: pointer;
134
- transition:
135
- border-color var(--nx-duration),
136
- box-shadow var(--nx-duration);
137
- }
138
-
139
- .nx-theme-option:hover {
140
- border-color: var(--nx-border-strong);
141
- }
142
-
143
- .nx-theme-option:has(:checked) {
144
- border-color: var(--nx-primary);
145
- box-shadow: 0 0 0 1px var(--nx-primary);
146
- }
147
-
148
- .nx-theme-option:has(:focus-visible) {
149
- box-shadow: 0 0 0 1px var(--nx-primary), var(--nx-focus-ring);
150
- }
151
-
152
- /* Drawn with the previewed theme's tokens, because the element carries its data-nx-theme. */
153
- .nx-theme-option__preview {
154
- display: block;
155
- padding: 7px;
156
- border-radius: var(--nx-radius-sm);
157
- background: var(--nx-bg);
158
- }
159
-
160
- .nx-theme-option__window {
161
- display: grid;
162
- gap: 5px;
163
- padding: 7px;
164
- border: 1px solid var(--nx-border);
165
- border-radius: var(--nx-radius-sm);
166
- background: var(--nx-surface);
167
- }
168
-
169
- .nx-theme-option__line {
170
- width: 78%;
171
- height: 5px;
172
- border-radius: 3px;
173
- background: var(--nx-text);
174
- }
175
-
176
- .nx-theme-option__line--muted {
177
- width: 52%;
178
- background: var(--nx-text-muted);
179
- }
180
-
181
- .nx-theme-option__swatches {
182
- display: flex;
183
- align-items: center;
184
- gap: 4px;
185
- margin-top: 2px;
186
- }
187
-
188
- .nx-theme-option__pill {
189
- width: 26px;
190
- height: 10px;
191
- margin-right: auto;
192
- border-radius: var(--nx-radius-full);
193
- background: var(--nx-primary);
194
- }
195
-
196
- .nx-theme-option__dot {
197
- width: 9px;
198
- height: 9px;
199
- border-radius: 50%;
200
- }
201
-
202
- .nx-theme-option__dot--success {
203
- background: var(--nx-success);
204
- }
205
-
206
- .nx-theme-option__dot--warning {
207
- background: var(--nx-warning);
208
- }
209
-
210
- .nx-theme-option__dot--danger {
211
- background: var(--nx-danger);
212
- }
213
-
214
- .nx-theme-option__name {
215
- display: flex;
216
- align-items: center;
217
- justify-content: space-between;
218
- gap: 4px;
219
- padding: 0 3px 1px;
220
- font-size: var(--nx-text-sm);
221
- font-weight: 500;
222
- }
223
-
224
- .nx-theme-option__check {
225
- color: var(--nx-primary);
226
- visibility: hidden;
227
- }
228
-
229
- .nx-theme-option:has(:checked) .nx-theme-option__check {
230
- visibility: visible;
231
- }
232
- }
1
+ @layer nexus.components {
2
+ /* Popover panel: a native [popover] element, placed by the component that opens it. In dark mode it is a step
3
+ lighter than the surface it floats over, so it reads as raised.
4
+ (The shared panel lives in the theme picker's file because that is where it was first needed; it belongs to
5
+ every popover, not to the picker. Moving it would have to move its place in Nexus.Index.css with it.) */
6
+ .nx-popover {
7
+ /* The arrow's base and depth. Keep in step with ARROW_BASE and ARROW_DEPTH in Helpers/PopoverHelpers.ts, which
8
+ work out the room the arrow needs, and with the two paths below, which are drawn for exactly these. */
9
+ --nx-popover-arrow: 26px;
10
+ --nx-popover-arrow-depth: 11px;
11
+ /* The panel's edge, shared with the arrow's own: a panel that changes it changes both. */
12
+ --nx-popover-edge: var(--nx-border);
13
+ margin: 0;
14
+ /* The browser's own [popover] rule says `overflow: auto`, which would cut the arrow off at the panel's edge and
15
+ put a pair of scroll bars on a panel that fits. A panel that has to scroll scrolls a block inside itself. */
16
+ overflow: visible;
17
+ /* The room inside the edge: a panel sets `--nx-popover-pad` (a menu 4px, the table's panels 8px), never `padding`,
18
+ which this rule, loaded after theirs, would win over; its scroller (below) carries the right-hand part. */
19
+ padding: var(--nx-popover-pad, var(--nx-space-4));
20
+ border: 1px solid var(--nx-popover-edge);
21
+ border-radius: var(--nx-radius-lg);
22
+ background: light-dark(var(--nx-surface), var(--nx-surface-2));
23
+ color: var(--nx-text);
24
+ box-shadow: var(--nx-shadow);
25
+ /*
26
+ * Every panel fades in as it opens and out as it closes, briefly, and nothing waits for it: a closing panel keeps
27
+ * its layout (`display`) and its place on top (`overlay`) only while it fades, and takes no clicks meanwhile.
28
+ * With animations off it simply comes and goes.
29
+ */
30
+ transition:
31
+ opacity 120ms ease-out,
32
+ display 120ms allow-discrete,
33
+ overlay 120ms allow-discrete;
34
+ }
35
+
36
+ .nx-popover:not(:popover-open) {
37
+ opacity: 0;
38
+ pointer-events: none;
39
+ }
40
+
41
+ @starting-style {
42
+ .nx-popover:popover-open {
43
+ opacity: 0;
44
+ }
45
+ }
46
+
47
+ [data-nx-motion="reduce"] .nx-popover {
48
+ transition: none;
49
+ }
50
+
51
+ /*
52
+ * A panel whose content can be longer than the window marks the part that scrolls with `.nx-popover__scroll`, a
53
+ * child of the panel. The panel is then never taller than the room it was placed in (`--nx-popover-room`, written
54
+ * by the placing helpers: the room on the side of its button it opened on), and the scroller takes what is left.
55
+ * The scroller runs to the panel's right wall, so its scroll bar is the wall's and not a padding's width inside it,
56
+ * and it carries the panel's right padding inside itself; the panel's other children keep the same inset with a
57
+ * margin. Its right corners take the panel's rounding, so the bar is cut by the curve instead of drawn over it.
58
+ */
59
+ .nx-popover:has(> .nx-popover__scroll) {
60
+ max-height: var(--nx-popover-room, calc(100vh - 16px));
61
+ padding-right: 0;
62
+ }
63
+
64
+ /* A shut popover is hidden by the browser, so the panel takes its layout only while it is open. */
65
+ .nx-popover:has(> .nx-popover__scroll):popover-open {
66
+ display: flex;
67
+ flex-direction: column;
68
+ }
69
+
70
+ .nx-popover:has(> .nx-popover__scroll) > :not(.nx-popover__scroll) {
71
+ margin-right: var(--nx-popover-pad, var(--nx-space-4));
72
+ }
73
+
74
+ .nx-popover__scroll {
75
+ flex: 1 1 auto;
76
+ min-height: 0;
77
+ padding-right: var(--nx-popover-pad, var(--nx-space-4));
78
+ overflow: hidden auto;
79
+ overscroll-behavior: contain;
80
+ border-radius: 0 calc(var(--nx-radius-lg) - 1px) calc(var(--nx-radius-lg) - 1px) 0;
81
+ }
82
+
83
+ /*
84
+ * The arrow that ties a panel to the button or the place it opened from: an isosceles tail, 26px across and 11px
85
+ * deep, with a slightly rounded tip. It is drawn in two layers, because a shape with a line along two of its sides
86
+ * and nothing along the third cannot be one: `::before` is the whole tail in the panel's edge colour, `::after`
87
+ * the same tail a pixel smaller on both slopes and a pixel longer at the base, in the panel's own background. What
88
+ * is left of the first between them is the 1px line along the slopes; the second covers the panel's border across
89
+ * the base, so the tail opens into the panel with no seam and no line across its mouth. Both paths are drawn for
90
+ * the sizes above: change one and the other two have to be worked out again.
91
+ *
92
+ * `placeUnderAnchor` and `placeAtPoint` (Helpers/PopoverHelpers.ts) say which edge carries the tail and where
93
+ * along that edge its tip sits, and leave both out when it would point at nothing. Nothing here animates: the tail
94
+ * is drawn with the panel, so it is there in the first frame whether the opening animation runs or not.
95
+ */
96
+ .nx-popover[data-nx-arrow]::before,
97
+ .nx-popover[data-nx-arrow]::after {
98
+ content: "";
99
+ position: absolute;
100
+ /* The middle is only a fallback: the two are always written together, and taken away together. */
101
+ left: var(--nx-popover-arrow-x, 50%);
102
+ width: var(--nx-popover-arrow);
103
+ /* A pixel past the tail's depth: the panel's own border, which the fill covers. */
104
+ height: calc(var(--nx-popover-arrow-depth) + 1px);
105
+ margin-left: calc(var(--nx-popover-arrow) / -2);
106
+ }
107
+
108
+ /* The tail's outline: tip rounded by 2px, feet on the panel's border line. */
109
+ .nx-popover[data-nx-arrow]::before {
110
+ background: var(--nx-popover-edge);
111
+ clip-path: path("M 0 11 L 11.708 1.093 A 2 2 0 0 1 14.292 1.093 L 26 11 Z");
112
+ }
113
+
114
+ /* The fill: the same tail, 1px in from each slope (so the outline is left as a line) and 1px further down. */
115
+ .nx-popover[data-nx-arrow]::after {
116
+ background: inherit;
117
+ clip-path: path("M 0.367 12 L 12.354 1.857 A 1 1 0 0 1 13.646 1.857 L 25.633 12 Z");
118
+ }
119
+
120
+ /* Below its anchor: the tail stands on the panel's top edge, pointing up. */
121
+ .nx-popover[data-nx-arrow="below"]::before,
122
+ .nx-popover[data-nx-arrow="below"]::after {
123
+ top: calc(-1px - var(--nx-popover-arrow-depth));
124
+ }
125
+
126
+ /* Above its anchor: the same tail turned over, on the bottom edge. */
127
+ .nx-popover[data-nx-arrow="above"]::before,
128
+ .nx-popover[data-nx-arrow="above"]::after {
129
+ bottom: calc(-1px - var(--nx-popover-arrow-depth));
130
+ transform: scaleY(-1);
131
+ }
132
+
133
+ .nx-theme-switcher__panel {
134
+ position: fixed;
135
+ inset: auto;
136
+ width: min(340px, calc(100vw - 16px));
137
+ }
138
+
139
+ .nx-theme-picker,
140
+ .nx-theme-switcher__body {
141
+ display: grid;
142
+ gap: var(--nx-space-4);
143
+ }
144
+
145
+ /* A section of the preferences: a line above it and its name, a step stronger than the small headings under it. */
146
+ .nx-theme-picker__section {
147
+ margin: 0;
148
+ padding-top: var(--nx-space-4);
149
+ border-top: 1px solid var(--nx-border);
150
+ color: var(--nx-text);
151
+ font-size: var(--nx-text-sm);
152
+ font-weight: 600;
153
+ }
154
+
155
+ .nx-theme-picker__group {
156
+ min-width: 0;
157
+ margin: 0;
158
+ padding: 0;
159
+ border: 0;
160
+ }
161
+
162
+ .nx-theme-picker__legend {
163
+ margin: 0 0 var(--nx-space-2);
164
+ padding: 0;
165
+ color: var(--nx-text-muted);
166
+ font-size: var(--nx-text-xs);
167
+ font-weight: 600;
168
+ letter-spacing: 0.06em;
169
+ text-transform: uppercase;
170
+ }
171
+
172
+ /* Theme cards */
173
+ .nx-theme-picker__grid {
174
+ display: grid;
175
+ grid-template-columns: repeat(auto-fill, minmax(128px, 1fr));
176
+ gap: var(--nx-space-2);
177
+ }
178
+
179
+ .nx-theme-option {
180
+ display: grid;
181
+ gap: 6px;
182
+ padding: 5px;
183
+ border: 1px solid var(--nx-border);
184
+ border-radius: var(--nx-radius);
185
+ background: var(--nx-surface);
186
+ color: var(--nx-text);
187
+ cursor: pointer;
188
+ transition:
189
+ border-color var(--nx-duration),
190
+ box-shadow var(--nx-duration);
191
+ }
192
+
193
+ .nx-theme-option:hover {
194
+ border-color: var(--nx-border-strong);
195
+ }
196
+
197
+ .nx-theme-option:has(:checked) {
198
+ border-color: var(--nx-primary);
199
+ box-shadow: 0 0 0 1px var(--nx-primary);
200
+ }
201
+
202
+ .nx-theme-option:has(:focus-visible) {
203
+ box-shadow: 0 0 0 1px var(--nx-primary), var(--nx-focus-ring);
204
+ }
205
+
206
+ /* Drawn with the previewed theme's tokens, because the element carries its data-nx-theme. */
207
+ .nx-theme-option__preview {
208
+ display: block;
209
+ padding: 7px;
210
+ border-radius: var(--nx-radius-sm);
211
+ background: var(--nx-bg);
212
+ }
213
+
214
+ .nx-theme-option__window {
215
+ display: grid;
216
+ gap: 5px;
217
+ padding: 7px;
218
+ border: 1px solid var(--nx-border);
219
+ border-radius: var(--nx-radius-sm);
220
+ background: var(--nx-surface);
221
+ }
222
+
223
+ .nx-theme-option__line {
224
+ width: 78%;
225
+ height: 5px;
226
+ border-radius: 3px;
227
+ background: var(--nx-text);
228
+ }
229
+
230
+ .nx-theme-option__line--muted {
231
+ width: 52%;
232
+ background: var(--nx-text-muted);
233
+ }
234
+
235
+ .nx-theme-option__swatches {
236
+ display: flex;
237
+ align-items: center;
238
+ gap: 4px;
239
+ margin-top: 2px;
240
+ }
241
+
242
+ .nx-theme-option__pill {
243
+ width: 26px;
244
+ height: 10px;
245
+ margin-right: auto;
246
+ border-radius: var(--nx-radius-full);
247
+ background: var(--nx-primary);
248
+ }
249
+
250
+ .nx-theme-option__dot {
251
+ width: 9px;
252
+ height: 9px;
253
+ border-radius: 50%;
254
+ }
255
+
256
+ .nx-theme-option__dot--success {
257
+ background: var(--nx-success);
258
+ }
259
+
260
+ .nx-theme-option__dot--warning {
261
+ background: var(--nx-warning);
262
+ }
263
+
264
+ .nx-theme-option__dot--danger {
265
+ background: var(--nx-danger);
266
+ }
267
+
268
+ .nx-theme-option__name {
269
+ display: flex;
270
+ align-items: center;
271
+ justify-content: space-between;
272
+ gap: 4px;
273
+ padding: 0 3px 1px;
274
+ font-size: var(--nx-text-sm);
275
+ font-weight: 500;
276
+ }
277
+
278
+ .nx-theme-option__check {
279
+ color: var(--nx-primary);
280
+ visibility: hidden;
281
+ }
282
+
283
+ .nx-theme-option:has(:checked) .nx-theme-option__check {
284
+ visibility: visible;
285
+ }
286
+ }