nexus-shared 3.1.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.
Files changed (234) hide show
  1. package/CHANGELOG.md +2268 -446
  2. package/LICENSE +21 -21
  3. package/README.md +1705 -1084
  4. package/dist/Client.Index.d.ts +17 -0
  5. package/dist/Client.Index.js +17 -0
  6. package/dist/Components/Documents/DocumentFrame.d.ts +50 -0
  7. package/dist/Components/Documents/DocumentFrame.js +83 -0
  8. package/dist/Components/Documents/Menu.d.ts +4 -0
  9. package/dist/Components/Documents/Menu.js +40 -24
  10. package/dist/Components/Documents/PrintDocument.d.ts +95 -0
  11. package/dist/Components/Documents/PrintDocument.js +62 -0
  12. package/dist/Components/Documents/Tabs.d.ts +59 -0
  13. package/dist/Components/Documents/Tabs.js +70 -0
  14. package/dist/Components/Forms/ApiForm.js +19 -2
  15. package/dist/Components/Forms/Crud.d.ts +2 -2
  16. package/dist/Components/Forms/Crud.js +871 -377
  17. package/dist/Components/Forms/CrudActions.d.ts +136 -0
  18. package/dist/Components/Forms/CrudActions.js +184 -0
  19. package/dist/Components/Forms/CrudHistory.d.ts +66 -0
  20. package/dist/Components/Forms/CrudHistory.js +140 -0
  21. package/dist/Components/Forms/CrudNarrowPicker.d.ts +31 -0
  22. package/dist/Components/Forms/CrudNarrowPicker.js +180 -0
  23. package/dist/Components/Forms/CrudParts.d.ts +30 -2
  24. package/dist/Components/Forms/CrudParts.js +56 -5
  25. package/dist/Components/Forms/CrudRowForms.d.ts +26 -0
  26. package/dist/Components/Forms/CrudRowForms.js +114 -0
  27. package/dist/Components/Forms/CrudScopes.d.ts +28 -0
  28. package/dist/Components/Forms/CrudScopes.js +76 -0
  29. package/dist/Components/Forms/CrudTree.d.ts +90 -0
  30. package/dist/Components/Forms/CrudTree.js +363 -0
  31. package/dist/Components/Forms/CrudWorkspace.d.ts +63 -0
  32. package/dist/Components/Forms/CrudWorkspace.js +169 -0
  33. package/dist/Components/Forms/ExcelImport.js +3 -3
  34. package/dist/Components/Forms/Form.d.ts +4 -4
  35. package/dist/Components/Forms/Form.js +125 -16
  36. package/dist/Components/Forms/FormLeaveGuard.d.ts +44 -0
  37. package/dist/Components/Forms/FormLeaveGuard.js +65 -0
  38. package/dist/Components/Forms/RecordFlows.d.ts +50 -0
  39. package/dist/Components/Forms/RecordFlows.js +282 -0
  40. package/dist/Components/Forms/SubmitForm.d.ts +37 -2
  41. package/dist/Components/Forms/SubmitForm.js +195 -10
  42. package/dist/Components/Inputs/CheckBox.js +1 -1
  43. package/dist/Components/Inputs/ChoiceField.d.ts +21 -1
  44. package/dist/Components/Inputs/ChoiceField.js +28 -2
  45. package/dist/Components/Inputs/CodeBox.d.ts +69 -0
  46. package/dist/Components/Inputs/CodeBox.js +316 -0
  47. package/dist/Components/Inputs/DatePicker.js +4 -1
  48. package/dist/Components/Inputs/DateRangePicker.js +4 -1
  49. package/dist/Components/Inputs/DateTimePicker.js +4 -1
  50. package/dist/Components/Inputs/Dropdown.d.ts +13 -0
  51. package/dist/Components/Inputs/Dropdown.js +8 -5
  52. package/dist/Components/Inputs/DropdownParts.d.ts +3 -1
  53. package/dist/Components/Inputs/DropdownParts.js +16 -4
  54. package/dist/Components/Inputs/Field.d.ts +7 -1
  55. package/dist/Components/Inputs/Field.js +2 -2
  56. package/dist/Components/Inputs/GroupForm.d.ts +6 -6
  57. package/dist/Components/Inputs/GroupForm.js +10 -11
  58. package/dist/Components/Inputs/InputRenderer.d.ts +9 -6
  59. package/dist/Components/Inputs/InputRenderer.js +39 -31
  60. package/dist/Components/Inputs/NumberBox.js +4 -2
  61. package/dist/Components/Inputs/PictureInput.d.ts +41 -0
  62. package/dist/Components/Inputs/PictureInput.js +70 -0
  63. package/dist/Components/Inputs/RadioGroup.d.ts +16 -3
  64. package/dist/Components/Inputs/RadioGroup.js +8 -3
  65. package/dist/Components/Inputs/RowsInput.d.ts +1 -1
  66. package/dist/Components/Inputs/RowsInput.js +18 -3
  67. package/dist/Components/Inputs/TabularForm.d.ts +5 -5
  68. package/dist/Components/Inputs/TabularForm.js +29 -29
  69. package/dist/Components/Inputs/TextArea.d.ts +6 -0
  70. package/dist/Components/Inputs/TextArea.js +14 -2
  71. package/dist/Components/Inputs/TextBox.js +4 -1
  72. package/dist/Components/Inputs/TextBoxTypes.d.ts +6 -0
  73. package/dist/Components/Inputs/TextBoxTypes.js +17 -0
  74. package/dist/Components/Inputs/TimePicker.js +4 -1
  75. package/dist/Components/Inputs/TreeView.d.ts +107 -6
  76. package/dist/Components/Inputs/TreeView.js +513 -30
  77. package/dist/Components/Layouts/MessageBox.d.ts +15 -2
  78. package/dist/Components/Layouts/MessageBox.js +56 -7
  79. package/dist/Components/Layouts/Popup.d.ts +13 -6
  80. package/dist/Components/Layouts/Popup.js +37 -9
  81. package/dist/Components/Layouts/PopupDock.d.ts +3 -1
  82. package/dist/Components/Layouts/PopupDock.js +2 -1
  83. package/dist/Components/Layouts/PopupHost.js +5 -4
  84. package/dist/Components/Layouts/ThemePicker.d.ts +3 -2
  85. package/dist/Components/Layouts/ThemePicker.js +16 -4
  86. package/dist/Components/Viewers/DataTable.js +205 -61
  87. package/dist/Components/Viewers/DataTableFilters.d.ts +1 -1
  88. package/dist/Components/Viewers/DataTableFilters.js +17 -2
  89. package/dist/Components/Viewers/DataTableParts.d.ts +46 -12
  90. package/dist/Components/Viewers/DataTableParts.js +62 -21
  91. package/dist/Components/Viewers/OwnerFiles.d.ts +175 -0
  92. package/dist/Components/Viewers/OwnerFiles.js +589 -0
  93. package/dist/Components/Viewers/QrCodeImage.d.ts +22 -0
  94. package/dist/Components/Viewers/QrCodeImage.js +15 -0
  95. package/dist/Components/Viewers/RecordCards.d.ts +16 -0
  96. package/dist/Components/Viewers/RecordCards.js +509 -0
  97. package/dist/Helpers/ApiModules.d.ts +3 -34
  98. package/dist/Helpers/ApiModules.js +3 -3
  99. package/dist/Helpers/ApiRoutes.d.ts +68 -26
  100. package/dist/Helpers/ApiRoutes.js +31 -27
  101. package/dist/Helpers/ArrayHelpers.d.ts +0 -0
  102. package/dist/Helpers/ArrayHelpers.js +2 -0
  103. package/dist/Helpers/BusyHooks.d.ts +6 -0
  104. package/dist/Helpers/BusyHooks.js +39 -0
  105. package/dist/Helpers/CodeHelpers.d.ts +97 -0
  106. package/dist/Helpers/CodeHelpers.js +332 -0
  107. package/dist/Helpers/CrudBackend.d.ts +114 -6
  108. package/dist/Helpers/CrudBackend.js +214 -11
  109. package/dist/Helpers/CrudColumns.d.ts +98 -0
  110. package/dist/Helpers/CrudColumns.js +160 -0
  111. package/dist/Helpers/CrudDetailsTabs.d.ts +58 -0
  112. package/dist/Helpers/CrudDetailsTabs.js +126 -0
  113. package/dist/Helpers/CrudHelpers.d.ts +130 -6
  114. package/dist/Helpers/CrudHelpers.js +304 -12
  115. package/dist/Helpers/CrudNarrowPick.d.ts +83 -0
  116. package/dist/Helpers/CrudNarrowPick.js +157 -0
  117. package/dist/Helpers/CrudRowForms.d.ts +15 -0
  118. package/dist/Helpers/CrudRowForms.js +43 -0
  119. package/dist/Helpers/CrudScopes.d.ts +32 -0
  120. package/dist/Helpers/CrudScopes.js +79 -0
  121. package/dist/Helpers/DropdownHelpers.d.ts +3 -1
  122. package/dist/Helpers/DropdownHelpers.js +6 -2
  123. package/dist/Helpers/ExcelHelpers.d.ts +1 -1
  124. package/dist/Helpers/ExcelHelpers.js +12 -11
  125. package/dist/Helpers/FileAdapter.d.ts +78 -0
  126. package/dist/Helpers/FileAdapter.js +102 -0
  127. package/dist/Helpers/FilePrimaries.d.ts +48 -0
  128. package/dist/Helpers/FilePrimaries.js +138 -0
  129. package/dist/Helpers/FormConfirm.d.ts +32 -0
  130. package/dist/Helpers/FormConfirm.js +40 -0
  131. package/dist/Helpers/FormStore.d.ts +90 -5
  132. package/dist/Helpers/FormStore.js +318 -22
  133. package/dist/Helpers/InputConditions.d.ts +50 -0
  134. package/dist/Helpers/InputConditions.js +168 -0
  135. package/dist/Helpers/InputMemory.d.ts +106 -0
  136. package/dist/Helpers/InputMemory.js +385 -0
  137. package/dist/Helpers/InputNarrowing.d.ts +18 -0
  138. package/dist/Helpers/InputNarrowing.js +67 -0
  139. package/dist/Helpers/InputParamsHelpers.d.ts +44 -1
  140. package/dist/Helpers/InputParamsHelpers.js +162 -71
  141. package/dist/Helpers/MessageBuilder.js +2 -0
  142. package/dist/Helpers/NexusDriveAdapter.d.ts +55 -0
  143. package/dist/Helpers/NexusDriveAdapter.js +207 -0
  144. package/dist/Helpers/NexusHelpers.d.ts +0 -0
  145. package/dist/Helpers/NexusHelpers.js +1 -0
  146. package/dist/Helpers/NumberHelpers.d.ts +95 -0
  147. package/dist/Helpers/NumberHelpers.js +126 -0
  148. package/dist/Helpers/Permissions.js +2 -1
  149. package/dist/Helpers/QrCode.d.ts +26 -0
  150. package/dist/Helpers/QrCode.js +463 -0
  151. package/dist/Helpers/RecordCards.d.ts +205 -0
  152. package/dist/Helpers/RecordCards.js +378 -0
  153. package/dist/Helpers/RequestCache.d.ts +47 -0
  154. package/dist/Helpers/RequestCache.js +132 -0
  155. package/dist/Helpers/RowsStore.d.ts +37 -2
  156. package/dist/Helpers/RowsStore.js +128 -10
  157. package/dist/Helpers/ServerPreview.d.ts +69 -0
  158. package/dist/Helpers/ServerPreview.js +99 -0
  159. package/dist/Helpers/TableColumns.js +4 -3
  160. package/dist/Helpers/TableExport.d.ts +7 -1
  161. package/dist/Helpers/TableExport.js +21 -15
  162. package/dist/Helpers/TableFilters.d.ts +1 -1
  163. package/dist/Helpers/TableFilters.js +24 -23
  164. package/dist/Helpers/TableHelpers.d.ts +24 -3
  165. package/dist/Helpers/TableHelpers.js +58 -12
  166. package/dist/Helpers/TableJoins.d.ts +83 -0
  167. package/dist/Helpers/TableJoins.js +284 -0
  168. package/dist/Helpers/TableStore.d.ts +26 -1
  169. package/dist/Helpers/TableStore.js +73 -7
  170. package/dist/Helpers/TreeStore.d.ts +306 -11
  171. package/dist/Helpers/TreeStore.js +1048 -90
  172. package/dist/Helpers/UserPreferences.d.ts +8 -0
  173. package/dist/Helpers/UserPreferences.js +17 -0
  174. package/dist/Interfaces/CrudInterfaces.d.ts +512 -14
  175. package/dist/Interfaces/FileInterfaces.d.ts +162 -0
  176. package/dist/Interfaces/FileInterfaces.js +4 -0
  177. package/dist/Interfaces/FormInterfaces.d.ts +393 -29
  178. package/dist/Interfaces/FormInterfaces.js +79 -1
  179. package/dist/Interfaces/InputInterfaces.d.ts +39 -3
  180. package/dist/Interfaces/MessageInterfaces.d.ts +1 -1
  181. package/dist/Interfaces/PreferenceInterfaces.d.ts +8 -0
  182. package/dist/Interfaces/PreferenceInterfaces.js +2 -5
  183. package/dist/Interfaces/RecordInterfaces.d.ts +367 -0
  184. package/dist/Interfaces/RecordInterfaces.js +1 -0
  185. package/dist/Interfaces/TableInterfaces.d.ts +160 -5
  186. package/dist/Services/ApiProxy.d.ts +36 -1
  187. package/dist/Services/ApiProxy.js +182 -52
  188. package/dist/Services/ApiProxyRules.d.ts +203 -0
  189. package/dist/Services/ApiProxyRules.js +426 -0
  190. package/dist/Services/ExcelApi.js +5 -0
  191. package/dist/Services/FileApi.d.ts +13 -0
  192. package/dist/Services/FileApi.js +29 -0
  193. package/dist/Services/ImageEditorLoader.d.ts +14 -0
  194. package/dist/Services/ImageEditorLoader.js +51 -0
  195. package/dist/Services/JoinSources.d.ts +80 -0
  196. package/dist/Services/JoinSources.js +150 -0
  197. package/dist/Services/ModuleImport.d.ts +7 -0
  198. package/dist/Services/ModuleImport.js +22 -0
  199. package/dist/Services/ServerApi.d.ts +13 -2
  200. package/dist/Services/ServerApi.js +8 -3
  201. package/dist/Shared.Index.d.ts +20 -0
  202. package/dist/Shared.Index.js +20 -0
  203. package/package.json +92 -85
  204. package/src/Styles/Nexus.Avatar.css +80 -79
  205. package/src/Styles/Nexus.Base.css +117 -117
  206. package/src/Styles/Nexus.Button.css +186 -180
  207. package/src/Styles/Nexus.Calendar.css +273 -273
  208. package/src/Styles/Nexus.Chat.css +1443 -1443
  209. package/src/Styles/Nexus.Choice.css +359 -343
  210. package/src/Styles/Nexus.Crud.css +542 -168
  211. package/src/Styles/Nexus.DateTime.css +81 -81
  212. package/src/Styles/Nexus.Dropdown.css +733 -725
  213. package/src/Styles/Nexus.Editor.css +295 -295
  214. package/src/Styles/Nexus.Excel.css +389 -389
  215. package/src/Styles/Nexus.Files.css +410 -0
  216. package/src/Styles/Nexus.Form.css +282 -279
  217. package/src/Styles/Nexus.Index.css +41 -37
  218. package/src/Styles/Nexus.Input.css +238 -4
  219. package/src/Styles/Nexus.Markdown.css +237 -237
  220. package/src/Styles/Nexus.Menu.css +246 -237
  221. package/src/Styles/Nexus.Popup.css +800 -724
  222. package/src/Styles/Nexus.Print.css +288 -0
  223. package/src/Styles/Nexus.QrCode.css +12 -0
  224. package/src/Styles/Nexus.Record.css +430 -0
  225. package/src/Styles/Nexus.Rows.css +637 -637
  226. package/src/Styles/Nexus.Slider.css +276 -276
  227. package/src/Styles/Nexus.Tab.Buttons.css +497 -432
  228. package/src/Styles/Nexus.Table.css +98 -35
  229. package/src/Styles/Nexus.Theme.Picker.css +59 -3
  230. package/src/Styles/Nexus.Themes.css +200 -194
  231. package/src/Styles/Nexus.Time.css +144 -144
  232. package/src/Styles/Nexus.Toast.css +263 -263
  233. package/src/Styles/Nexus.Tokens.css +94 -89
  234. package/src/Styles/Nexus.Tree.css +530 -431
@@ -139,11 +139,36 @@
139
139
  font-variant-numeric: tabular-nums;
140
140
  }
141
141
 
142
+ /*
143
+ * A value worked out from other inputs (a form's `compute`): an <output> where an input would be, its text placed as an
144
+ * input's is (in the middle of the box, low in an inbox one) and in the text colour, a long one cut with an ellipsis.
145
+ * Never typed in, so no I-beam; the read-only tint around it comes from the field.
146
+ */
147
+ .nx-field__control--output {
148
+ display: flex;
149
+ align-items: center;
150
+ overflow: hidden;
151
+ white-space: nowrap;
152
+ cursor: default;
153
+ }
154
+
155
+ .nx-field__output-text {
156
+ min-width: 0;
157
+ overflow: hidden;
158
+ text-overflow: ellipsis;
159
+ }
160
+
142
161
  .nx-field__control::placeholder {
143
162
  color: var(--nx-text-subtle);
144
163
  opacity: 1;
145
164
  }
146
165
 
166
+ /* A read-only field's placeholder is all it shows ("None"), so it reads as text: --nx-text-subtle is under 3:1 on the
167
+ read-only box in light themes, muted text at least 4.5:1. */
168
+ .nx-field[data-readonly] .nx-field__control::placeholder {
169
+ color: var(--nx-text-muted);
170
+ }
171
+
147
172
  /* Browser extras that the field replaces with its own buttons. */
148
173
  .nx-field__control::-webkit-search-cancel-button,
149
174
  .nx-field__control::-webkit-search-decoration {
@@ -338,6 +363,12 @@
338
363
  animation: nx-field-nudge 320ms ease-in-out;
339
364
  }
340
365
 
366
+ /* A box pointed at with the same nudge: the one thing to set first, when the cursor is sent to it (a CRUD's Add pressed
367
+ while its narrowing box has nothing picked). */
368
+ .nx-field__box[data-nudge] {
369
+ animation: nx-field-nudge 320ms ease-in-out;
370
+ }
371
+
341
372
  @keyframes nx-field-nudge {
342
373
  20%,
343
374
  60% {
@@ -466,14 +497,51 @@
466
497
  top: calc(var(--nx-field-pad-y) + var(--nx-field-font) * 0.7);
467
498
  }
468
499
 
469
- /* Outlined: the raised label sits on the top border. Its backing covers only the lower half, so it blends with any panel. */
500
+ /*
501
+ * Outlined: the raised label sits on the top border, centred on its inner edge, and opens a gap in it: behind the
502
+ * label the field's colour runs from the box's top edge down, and never above it, where it shows on any panel whose
503
+ * colour is not the field's (a read-only box, a dark popover). No CSS length finds that edge at every scale: a 1px
504
+ * border is one device pixel thick at 125% and two at 200%. So the backing is placed by the same length the label is
505
+ * lifted by (half its 1.2 line height: the two cancel, and it starts on the border's inner edge), and its 1px outline
506
+ * covers the border, because the browser snaps an outline exactly as it snaps a border. The label's overflow keeps
507
+ * the outline's sides and foot inside it. A gradient on the label instead was half a pixel off at most scales from 67%
508
+ * to 300%: the field's colour a row above the box, or a hairline of border through the gap.
509
+ */
470
510
  .nx-field--outlined:is([data-raised], :focus-within, :has(.nx-field__control:not(:placeholder-shown))) .nx-field__label {
471
- top: 0;
511
+ top: -0.6em;
472
512
  left: calc(var(--nx-field-pad-x) - 4px);
473
513
  padding: 0 4px;
474
- background: linear-gradient(to bottom, transparent calc(50% - 1px), var(--nx-field-bg) calc(50% - 1px));
475
514
  font-size: var(--nx-text-xs);
476
515
  font-weight: 500;
516
+ transform: none;
517
+ }
518
+
519
+ .nx-field--outlined:is([data-raised], :focus-within, :has(.nx-field__control:not(:placeholder-shown))) .nx-field__label::before {
520
+ content: "";
521
+ position: absolute;
522
+ z-index: -1;
523
+ inset: 0.6em 0 0;
524
+ outline: 1px solid var(--nx-field-bg);
525
+ background: var(--nx-field-bg);
526
+ }
527
+
528
+ /* Forced colours would paint that outline in the text's colour; the browser's backplate behind the text opens the gap. */
529
+ @media (forced-colors: active) {
530
+ .nx-field--outlined .nx-field__label::before {
531
+ display: none;
532
+ }
533
+ }
534
+
535
+ /*
536
+ * Outlined, with focus: the border thickens to 2px instead of taking the ring. A ring lies outside the box, past the
537
+ * label's backing, so it ran on behind the label; this edge lies on the border and a pixel inside it, where the
538
+ * backing opens the same gap in it. One 2px outline over the border, not a second pixel beside it, which showed a
539
+ * seam at 150%; and an outline, so it is drawn over the control (an autofilled one is opaque) and under the label.
540
+ */
541
+ .nx-field--outlined:not([data-readonly], [data-disabled]) .nx-field__box:focus-within {
542
+ outline: 2px solid var(--nx-field-accent);
543
+ outline-offset: -2px;
544
+ box-shadow: var(--nx-shadow-sm);
477
545
  }
478
546
 
479
547
  /* Inbox: a taller box with the raised label inside its top edge. */
@@ -540,6 +608,16 @@
540
608
  resize: vertical;
541
609
  }
542
610
 
611
+ /* Code (`TextArea code`): the editor's monospace, lines kept as typed, a long one scrolled sideways in the box. */
612
+ .nx-field--multiline .nx-field__control--code {
613
+ overflow-x: auto;
614
+ font-family: var(--nx-font-mono);
615
+ font-size: calc(var(--nx-field-font) - 0.5px);
616
+ white-space: pre;
617
+ overflow-wrap: normal;
618
+ tab-size: 2;
619
+ }
620
+
543
621
  /* Buttons and the read-only lock sit at the top end, centered on the first line (line height 1.4). */
544
622
  .nx-field--multiline .nx-field__actions {
545
623
  align-items: flex-start;
@@ -590,12 +668,168 @@
590
668
  }
591
669
  }
592
670
 
671
+ /*
672
+ * Code box: a box per character, drawn from one input that lies over them unseen. The boxes wear the field's own
673
+ * variables, so sizes, states, densities, and themes come with them; the field's single frame steps aside.
674
+ */
675
+ .nx-field--code .nx-field__box,
676
+ .nx-field--code .nx-field__box:focus-within {
677
+ min-height: 0;
678
+ border: 0;
679
+ background: none;
680
+ box-shadow: none;
681
+ }
682
+
683
+ .nx-code {
684
+ position: relative;
685
+ display: flex;
686
+ min-width: 0;
687
+ }
688
+
689
+ .nx-code[data-block] {
690
+ flex: 1 1 auto;
691
+ }
692
+
693
+ /* On a phone the gaps and the characters scale with the screen, so an SSN's nine boxes fit a 390px screen. */
694
+ .nx-code__slots,
695
+ .nx-code__group {
696
+ display: flex;
697
+ align-items: center;
698
+ gap: min(var(--nx-space-2), 1.2vw);
699
+ min-width: 0;
700
+ }
701
+
702
+ .nx-code[data-block] :is(.nx-code__slots, .nx-code__group) {
703
+ flex: 1 1 auto;
704
+ }
705
+
706
+ .nx-code__separator {
707
+ flex: none;
708
+ color: var(--nx-text-muted);
709
+ font-size: var(--nx-field-font);
710
+ }
711
+
712
+ /*
713
+ * A box is a little taller than the field's line and about as wide; its character is larger than the field's text.
714
+ * Boxes shrink alike rather than spill out of their field: a code too long for its room is cramped, never cut off.
715
+ */
716
+ .nx-code__slot {
717
+ position: relative;
718
+ display: grid;
719
+ flex: 0 1 calc(var(--nx-field-height) + var(--nx-space-1));
720
+ place-items: center;
721
+ min-width: 0;
722
+ height: calc(var(--nx-field-height) + var(--nx-space-3));
723
+ border: 1px solid var(--nx-field-border);
724
+ border-radius: var(--nx-radius);
725
+ background: var(--nx-field-bg);
726
+ box-shadow: var(--nx-shadow-sm);
727
+ color: var(--nx-text);
728
+ font-size: min(calc(var(--nx-field-font) * 1.4), 5vw);
729
+ font-variant-numeric: tabular-nums;
730
+ font-weight: 600;
731
+ line-height: 1;
732
+ transition:
733
+ border-color var(--nx-duration),
734
+ box-shadow var(--nx-duration),
735
+ background-color var(--nx-duration);
736
+ }
737
+
738
+ /*
739
+ * Without `block` the rows around the boxes are as wide as their content, and Chromium counts each box's width there,
740
+ * not its flex-basis: with a basis alone an empty box was its 2px border and a filled one its character. A width
741
+ * gives each box its size; `min-width: 0` still lets them shrink alike on a narrow screen.
742
+ */
743
+ .nx-code:not([data-block]) .nx-code__slot {
744
+ width: calc(var(--nx-field-height) + var(--nx-space-1));
745
+ }
746
+
747
+ .nx-code[data-block] .nx-code__slot {
748
+ flex: 1 1 0;
749
+ }
750
+
751
+ .nx-code:hover .nx-code__slot {
752
+ border-color: var(--nx-field-border-hover);
753
+ }
754
+
755
+ .nx-code__slot[data-active] {
756
+ border-color: var(--nx-field-accent);
757
+ box-shadow: var(--nx-field-ring);
758
+ }
759
+
760
+ .nx-code__slot[data-selected] {
761
+ background: color-mix(in oklab, var(--nx-field-accent) 14%, var(--nx-field-bg));
762
+ }
763
+
764
+ .nx-code__slot:empty::before {
765
+ content: attr(data-placeholder);
766
+ color: var(--nx-text-subtle);
767
+ font-weight: 400;
768
+ }
769
+
770
+ /* The caret in an empty box, blinking as a text caret does. */
771
+ .nx-code__slot[data-caret]::after {
772
+ content: "";
773
+ position: absolute;
774
+ width: 2px;
775
+ height: 45%;
776
+ border-radius: 1px;
777
+ background: var(--nx-text);
778
+ animation: nx-code-caret 1s step-end infinite;
779
+ }
780
+
781
+ @keyframes nx-code-caret {
782
+ 50% {
783
+ opacity: 0;
784
+ }
785
+ }
786
+
787
+ .nx-field:is([data-readonly], [data-disabled]) .nx-code__slot {
788
+ box-shadow: none;
789
+ }
790
+
791
+ /* The input that holds the code lies over the boxes, never seen. At 16px a phone does not zoom in on focus. */
792
+ .nx-code__input {
793
+ position: absolute;
794
+ inset: 0;
795
+ width: 100%;
796
+ margin: 0;
797
+ padding: 0;
798
+ border: 0;
799
+ outline: none;
800
+ background: transparent;
801
+ color: transparent;
802
+ caret-color: transparent;
803
+ font-size: 16px;
804
+ cursor: text;
805
+ }
806
+
807
+ .nx-code__input::selection {
808
+ background: transparent;
809
+ }
810
+
811
+ /* An offered code fills the input without its yellow: the boxes show it. */
812
+ .nx-code__input:is(:autofill, :-webkit-autofill) {
813
+ -webkit-text-fill-color: transparent;
814
+ transition: background-color 600000s;
815
+ }
816
+
817
+ .nx-code__input:disabled {
818
+ cursor: not-allowed;
819
+ }
820
+
593
821
  [data-nx-motion="reduce"] .nx-field__label,
594
- [data-nx-motion="reduce"] .nx-field--inbox :is(.nx-field__icon, .nx-field__affix, .nx-field__actions) {
822
+ [data-nx-motion="reduce"] .nx-field--inbox :is(.nx-field__icon, .nx-field__affix, .nx-field__actions),
823
+ [data-nx-motion="reduce"] .nx-code__slot {
595
824
  transition: none;
596
825
  }
597
826
 
827
+ [data-nx-motion="reduce"] .nx-code__slot[data-caret]::after {
828
+ animation: none;
829
+ }
830
+
598
831
  [data-nx-motion="reduce"] .nx-field__lock[data-nudge],
832
+ [data-nx-motion="reduce"] .nx-field__box[data-nudge],
599
833
  [data-nx-motion="reduce"] .nx-field-notice:popover-open {
600
834
  animation: none;
601
835
  }