@morscherlab/mint-sdk 1.2.0-beta.7 → 1.2.0-beta.9

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 (307) hide show
  1. package/README.md +30 -0
  2. package/dist/{ExperimentPopover-CfOdh5Rm.js → ExperimentPopover-oL0fg_A0.js} +5 -3
  3. package/dist/ExperimentPopover-oL0fg_A0.js.map +1 -0
  4. package/dist/{ExperimentSelectorModal-DvIagrxY.js → ExperimentSelectorModal-BeEOomw_.js} +4 -4
  5. package/dist/ExperimentSelectorModal-BeEOomw_.js.map +1 -0
  6. package/dist/{SettingsModal-W3TYfnP9.js → SettingsModal-Dphh3RrI.js} +4 -4
  7. package/dist/SettingsModal-Dphh3RrI.js.map +1 -0
  8. package/dist/{EmptyState-NBqf2_8z.js → Skeleton-DxtwJ5gt.js} +110 -92
  9. package/dist/Skeleton-DxtwJ5gt.js.map +1 -0
  10. package/dist/__tests__/components/ExperimentTimeline.test.d.ts +1 -0
  11. package/dist/__tests__/composables/useListReorder.test.d.ts +1 -0
  12. package/dist/__tests__/styles/cssTokens.test.d.ts +1 -0
  13. package/dist/components/ActionMenu.vue.d.ts +1 -1
  14. package/dist/components/AppPluginSwitcher.vue.d.ts +2 -0
  15. package/dist/components/AuditTrail.vue.d.ts +13 -0
  16. package/dist/components/BatchProgressList.vue.d.ts +17 -0
  17. package/dist/components/DataFrame.vue.d.ts +14 -2
  18. package/dist/components/DatePicker.vue.d.ts +1 -1
  19. package/dist/components/DateTimePicker.vue.d.ts +2 -0
  20. package/dist/components/ExperimentDataViewer.vue.d.ts +26 -1
  21. package/dist/components/ExperimentPopover.vue.d.ts +1 -0
  22. package/dist/components/ExperimentTimeline.vue.d.ts +29 -1
  23. package/dist/components/LcmsSequenceTable.vue.d.ts +29 -1
  24. package/dist/components/ProgressBar.vue.d.ts +1 -1
  25. package/dist/components/ProtocolStepEditor.vue.d.ts +1 -0
  26. package/dist/components/ReagentList.vue.d.ts +29 -1
  27. package/dist/components/SampleHierarchyTree.vue.d.ts +29 -1
  28. package/dist/components/SampleSelector.drag.d.ts +13 -0
  29. package/dist/components/SampleSelector.tree.d.ts +2 -0
  30. package/dist/components/SampleSelector.vue.d.ts +34 -1
  31. package/dist/components/ScheduleCalendar.vue.d.ts +20 -0
  32. package/dist/components/SmartGroupFieldRecipe.vue.d.ts +1 -0
  33. package/dist/components/TimePicker.vue.d.ts +1 -0
  34. package/dist/components/WellPlate.geometry.d.ts +15 -0
  35. package/dist/components/WellPlate.interaction.d.ts +13 -0
  36. package/dist/components/WellPlate.vue.d.ts +29 -0
  37. package/dist/components/index.js +6 -6
  38. package/dist/components/internal/AppTopBarPageSelectorInternal.vue.d.ts +2 -0
  39. package/dist/components/internal/DataStateInternal.vue.d.ts +43 -0
  40. package/dist/{components-B80gV0P6.js → components-CgAUzF8F.js} +1930 -1688
  41. package/dist/components-CgAUzF8F.js.map +1 -0
  42. package/dist/composables/controlSchemaTypes.d.ts +34 -0
  43. package/dist/composables/index.d.ts +1 -0
  44. package/dist/composables/index.js +9 -9
  45. package/dist/composables/useDropdownState.d.ts +18 -2
  46. package/dist/composables/useEventStream.d.ts +9 -0
  47. package/dist/composables/useListReorder.d.ts +90 -0
  48. package/dist/composables/useMenuKeyboard.d.ts +2 -2
  49. package/dist/composables/usePluginConfig.d.ts +3 -1
  50. package/dist/composables/useRequestSyncState.d.ts +42 -2
  51. package/dist/composables/useScheduleDrag.d.ts +1 -0
  52. package/dist/{composables-C8mmD5ta.js → composables-B_pia3hO.js} +13 -69
  53. package/dist/composables-B_pia3hO.js.map +1 -0
  54. package/dist/{useApi-CDBq6z23.js → errors-_W0-LbA6.js} +102 -3
  55. package/dist/errors-_W0-LbA6.js.map +1 -0
  56. package/dist/{experiment-Y9Iz7KYi.js → experiment-Cwl9AYxw.js} +3 -8
  57. package/dist/experiment-Cwl9AYxw.js.map +1 -0
  58. package/dist/experiment-utils-DV3DrvE_.js.map +1 -1
  59. package/dist/index.js +14 -14
  60. package/dist/install.js +2 -7
  61. package/dist/install.js.map +1 -1
  62. package/dist/permissions.d.ts +42 -1
  63. package/dist/permissions.js +20 -10
  64. package/dist/permissions.js.map +1 -1
  65. package/dist/stores/index.d.ts +1 -1
  66. package/dist/stores/index.js +3 -3
  67. package/dist/stores/settings.d.ts +31 -1
  68. package/dist/styles.css +9572 -27877
  69. package/dist/templates/index.js +2 -4
  70. package/dist/{templates-CK72aKO1.js → templates-Qq113pyZ.js} +291 -85
  71. package/dist/templates-Qq113pyZ.js.map +1 -0
  72. package/dist/{useControlSchema-_OVhavKq.js → useControlSchema-aMZlb4Sc.js} +197 -1089
  73. package/dist/useControlSchema-aMZlb4Sc.js.map +1 -0
  74. package/dist/{useDropdownState-D5G4UvWd.js → useDropdownState-DitCtrTT.js} +21 -5
  75. package/dist/useDropdownState-DitCtrTT.js.map +1 -0
  76. package/dist/{useExperimentSelector-DSEckf_g.js → useExperimentSelector-I8HC8hUu.js} +3 -3
  77. package/dist/{useExperimentSelector-DSEckf_g.js.map → useExperimentSelector-I8HC8hUu.js.map} +1 -1
  78. package/dist/{useFormBuilder-Bd714C7y.js → useFormBuilder-TCxNnqeb.js} +2 -2
  79. package/dist/{useFormBuilder-Bd714C7y.js.map → useFormBuilder-TCxNnqeb.js.map} +1 -1
  80. package/dist/{useProtocolTemplates-Dq5Pzwyd.js → useProtocolTemplates-BmX_iVBR.js} +185 -157
  81. package/dist/useProtocolTemplates-BmX_iVBR.js.map +1 -0
  82. package/dist/utils/color.d.ts +13 -0
  83. package/dist/utils/errors.d.ts +9 -0
  84. package/package.json +1 -1
  85. package/src/__tests__/components/ActionMenu.test.ts +94 -0
  86. package/src/__tests__/components/DataFrame.test.ts +183 -11
  87. package/src/__tests__/components/DataStates.test.ts +176 -0
  88. package/src/__tests__/components/DatePicker.test.ts +76 -0
  89. package/src/__tests__/components/DateTimePicker.test.ts +36 -0
  90. package/src/__tests__/components/ExperimentTimeline.test.ts +63 -0
  91. package/src/__tests__/components/GroupAssigner.test.ts +53 -0
  92. package/src/__tests__/components/LcmsSequenceTable.test.ts +22 -0
  93. package/src/__tests__/components/RackEditor.test.ts +35 -0
  94. package/src/__tests__/components/ReagentList.test.ts +64 -2
  95. package/src/__tests__/components/RetiredStyles.test.ts +31 -0
  96. package/src/__tests__/components/SampleSelector.drag.test.ts +51 -1
  97. package/src/__tests__/components/ScheduleCalendar.test.ts +63 -0
  98. package/src/__tests__/components/SegmentedControl.test.ts +88 -0
  99. package/src/__tests__/components/TimePicker.test.ts +61 -0
  100. package/src/__tests__/components/WellPlate.interaction.test.ts +59 -0
  101. package/src/__tests__/composables/useDropdownState.test.ts +58 -1
  102. package/src/__tests__/composables/useListReorder.test.ts +145 -0
  103. package/src/__tests__/composables/useRequestSyncState.test.ts +140 -0
  104. package/src/__tests__/stores/settings.test.ts +71 -1
  105. package/src/__tests__/styles/cssTokens.test.ts +131 -0
  106. package/src/__tests__/utils/permissions.test.ts +68 -0
  107. package/src/components/ActionMenu.vue +45 -88
  108. package/src/components/AlertBox.vue +0 -4
  109. package/src/components/AppAvatarMenu.vue +2 -14
  110. package/src/components/AppLayout.vue +0 -4
  111. package/src/components/AppPluginSwitcher.story.vue +87 -0
  112. package/src/components/AppPluginSwitcher.vue +2 -5
  113. package/src/components/AppSidebar.vue +0 -4
  114. package/src/components/AppToastContainer.vue +6 -8
  115. package/src/components/AppTopBar.vue +0 -4
  116. package/src/components/ArtifactSaveDialog.vue +0 -4
  117. package/src/components/ArtifactSelectorModal.vue +0 -4
  118. package/src/components/AuditTrail.story.vue +18 -0
  119. package/src/components/AuditTrail.vue +27 -7
  120. package/src/components/AutoGroupModal.vue +0 -4
  121. package/src/components/Avatar.vue +0 -4
  122. package/src/components/BaseButton.vue +0 -4
  123. package/src/components/BaseCheckbox.vue +0 -4
  124. package/src/components/BaseInput.vue +0 -4
  125. package/src/components/BaseModal.vue +0 -4
  126. package/src/components/BasePill.vue +0 -4
  127. package/src/components/BaseRadioGroup.vue +0 -4
  128. package/src/components/BaseSelect.vue +0 -4
  129. package/src/components/BaseSlider.vue +0 -4
  130. package/src/components/BaseTabs.vue +0 -4
  131. package/src/components/BaseTextarea.vue +0 -4
  132. package/src/components/BaseToggle.vue +0 -4
  133. package/src/components/BatchProgressList.story.vue +18 -0
  134. package/src/components/BatchProgressList.vue +32 -4
  135. package/src/components/Breadcrumb.vue +0 -4
  136. package/src/components/Calendar.vue +0 -4
  137. package/src/components/ChartContainer.story.vue +1 -1
  138. package/src/components/ChartContainer.vue +0 -4
  139. package/src/components/ChemicalFormula.vue +0 -4
  140. package/src/components/CollapsibleCard.vue +0 -4
  141. package/src/components/ColorSlider.vue +0 -4
  142. package/src/components/ConcentrationInput.vue +0 -4
  143. package/src/components/ConfirmDialog.vue +0 -4
  144. package/src/components/DataFrame.story.vue +14 -0
  145. package/src/components/DataFrame.vue +97 -23
  146. package/src/components/DatePicker.vue +73 -27
  147. package/src/components/DateTimePicker.vue +45 -17
  148. package/src/components/Divider.vue +0 -4
  149. package/src/components/DoseCalculator.vue +0 -4
  150. package/src/components/DropdownButton.vue +2 -14
  151. package/src/components/EmptyState.vue +0 -4
  152. package/src/components/ExperimentCodeBadge.vue +0 -4
  153. package/src/components/ExperimentDataViewer.story.vue +3 -0
  154. package/src/components/ExperimentDataViewer.vue +33 -13
  155. package/src/components/ExperimentPopover.vue +2 -5
  156. package/src/components/ExperimentSelectorModal.vue +0 -4
  157. package/src/components/ExperimentTimeline.story.vue +18 -0
  158. package/src/components/ExperimentTimeline.vue +81 -75
  159. package/src/components/FileUploader.vue +0 -4
  160. package/src/components/FitPanel.vue +0 -4
  161. package/src/components/FormActions.story.vue +96 -0
  162. package/src/components/FormActions.vue +0 -4
  163. package/src/components/FormBuilder.vue +0 -4
  164. package/src/components/FormField.vue +0 -4
  165. package/src/components/FormulaInput.vue +0 -4
  166. package/src/components/GeneratedPathInput.story.vue +68 -0
  167. package/src/components/GeneratedPlotlyResult.story.vue +96 -0
  168. package/src/components/GeneratedPlotlyResult.vue +3 -3
  169. package/src/components/GeneratedPluginView.story.vue +145 -0
  170. package/src/components/GeneratedPluginView.vue +10 -10
  171. package/src/components/GeneratedResultRenderer.story.vue +117 -0
  172. package/src/components/GeneratedResultRenderer.vue +4 -4
  173. package/src/components/GroupAssigner.vue +67 -5
  174. package/src/components/IconButton.vue +0 -4
  175. package/src/components/InstrumentAlertLog.vue +0 -4
  176. package/src/components/InstrumentStateBadge.vue +0 -4
  177. package/src/components/InstrumentStatusCard.vue +0 -4
  178. package/src/components/JobsStatusTray.vue +0 -4
  179. package/src/components/LcmsSequenceTable.vue +81 -50
  180. package/src/components/LoadingSpinner.vue +0 -4
  181. package/src/components/MobileSupportGate.vue +0 -4
  182. package/src/components/MoleculeInput.vue +0 -4
  183. package/src/components/MultiSelect.vue +0 -4
  184. package/src/components/NumberInput.vue +0 -4
  185. package/src/components/PlateMapEditor.vue +3 -14
  186. package/src/components/PluginIcon.vue +0 -4
  187. package/src/components/ProgressBar.vue +0 -4
  188. package/src/components/ProtocolStepEditor.vue +2 -4
  189. package/src/components/RackEditor.vue +51 -70
  190. package/src/components/ReagentEditor.vue +0 -4
  191. package/src/components/ReagentList.story.vue +18 -0
  192. package/src/components/ReagentList.vue +127 -82
  193. package/src/components/ResourceCard.vue +0 -4
  194. package/src/components/RuntimeUpdateNotice.story.vue +49 -0
  195. package/src/components/RuntimeUpdateNotice.vue +4 -4
  196. package/src/components/SampleHierarchyTree.story.vue +18 -0
  197. package/src/components/SampleHierarchyTree.vue +32 -9
  198. package/src/components/SampleLegend.vue +2 -8
  199. package/src/components/SampleSelector.drag.ts +51 -0
  200. package/src/components/SampleSelector.story.vue +6 -0
  201. package/src/components/SampleSelector.tree.ts +2 -0
  202. package/src/components/SampleSelector.vue +49 -10
  203. package/src/components/SampleSelectorGroupNode.vue +19 -0
  204. package/src/components/ScheduleCalendar.story.vue +6 -0
  205. package/src/components/ScheduleCalendar.vue +82 -7
  206. package/src/components/ScientificNumber.vue +0 -4
  207. package/src/components/SectionCard.vue +0 -4
  208. package/src/components/SegmentedControl.vue +48 -5
  209. package/src/components/SequenceInput.vue +0 -4
  210. package/src/components/SequenceProgressBar.story.vue +110 -0
  211. package/src/components/SequenceProgressBar.vue +0 -4
  212. package/src/components/SettingsModal.vue +0 -4
  213. package/src/components/Skeleton.vue +0 -4
  214. package/src/components/SmartGroupFieldRecipe.vue +8 -6
  215. package/src/components/SmartGroupManual.vue +0 -4
  216. package/src/components/StatusIndicator.vue +0 -4
  217. package/src/components/StepWizard.vue +0 -4
  218. package/src/components/TagsInput.vue +4 -6
  219. package/src/components/ThemeToggle.vue +0 -4
  220. package/src/components/TimePicker.vue +36 -7
  221. package/src/components/TimeRangeInput.vue +0 -4
  222. package/src/components/Tooltip.story.vue +3 -3
  223. package/src/components/Tooltip.vue +0 -4
  224. package/src/components/UnitInput.vue +0 -4
  225. package/src/components/WellPlate.geometry.ts +60 -1
  226. package/src/components/WellPlate.interaction.ts +44 -0
  227. package/src/components/WellPlate.story.vue +8 -0
  228. package/src/components/WellPlate.vue +53 -7
  229. package/src/components/internal/AppTopBarPageSelectorInternal.vue +2 -5
  230. package/src/components/internal/AppTopBarPillNavInternal.vue +0 -4
  231. package/src/components/internal/DataStateInternal.vue +74 -0
  232. package/src/components/internal/FormSectionRenderer.vue +0 -4
  233. package/src/components/internal/WellEditPopupInternal.vue +0 -4
  234. package/src/composables/controlSchemaTypes.ts +34 -0
  235. package/src/composables/index.ts +10 -0
  236. package/src/composables/useDropdownState.ts +35 -5
  237. package/src/composables/useEventStream.ts +14 -2
  238. package/src/composables/useFileImport.ts +2 -7
  239. package/src/composables/useGeneratedAnalysis.ts +8 -9
  240. package/src/composables/useListReorder.story.vue +143 -0
  241. package/src/composables/useListReorder.ts +242 -0
  242. package/src/composables/useMenuKeyboard.ts +2 -2
  243. package/src/composables/useOptimisticMutation.ts +1 -15
  244. package/src/composables/usePluginConfig.ts +3 -1
  245. package/src/composables/useRackEditor.ts +2 -11
  246. package/src/composables/useRequestSyncState.ts +98 -28
  247. package/src/composables/useResourceCrud.ts +1 -15
  248. package/src/composables/useScheduleDrag.ts +37 -0
  249. package/src/composables/useWellPainting.ts +5 -29
  250. package/src/composables/useWellPlateEditor.ts +1 -11
  251. package/src/permissions.ts +48 -9
  252. package/src/stores/experiment.ts +2 -7
  253. package/src/stores/index.ts +9 -1
  254. package/src/stores/settings.ts +93 -1
  255. package/src/styles/components/audit-trail.css +5 -5
  256. package/src/styles/components/batch-progress-list.css +7 -0
  257. package/src/styles/components/color-slider.css +2 -2
  258. package/src/styles/components/data-state.css +30 -0
  259. package/src/styles/components/dataframe.css +29 -35
  260. package/src/styles/components/experiment-data-viewer.css +4 -4
  261. package/src/styles/components/experiment-timeline.css +3 -30
  262. package/src/styles/components/form-builder.css +5 -5
  263. package/src/styles/components/lcms-sequence-table.css +16 -1
  264. package/src/styles/components/multi-select.css +1 -1
  265. package/src/styles/components/reagent-list.css +38 -31
  266. package/src/styles/components/sample-hierarchy-tree.css +5 -19
  267. package/src/styles/components/sample-selector.css +9 -2
  268. package/src/styles/components/schedule-calendar.css +8 -0
  269. package/src/styles/components/scientific-number.css +1 -1
  270. package/src/styles/components/well-plate.css +8 -0
  271. package/src/styles/index.css +8 -0
  272. package/src/styles/variables.css +29 -0
  273. package/src/templates/builderPresetControls.ts +1 -1
  274. package/src/templates/componentPlateHelpers.ts +3 -1
  275. package/src/templates/doseResponseAdapters.ts +2 -13
  276. package/src/templates/elisaAssayCollectionBuilder.ts +2 -2
  277. package/src/templates/plateMapBuilder.ts +2 -2
  278. package/src/templates/qpcrPlateBuilder.ts +1 -1
  279. package/src/templates/templateValidators.ts +1 -1
  280. package/src/templates/timeCourseBuilder.ts +2 -2
  281. package/src/templates/wellPlateScreenCollectionBuilder.ts +2 -2
  282. package/src/utils/color.ts +51 -0
  283. package/src/utils/errors.ts +29 -0
  284. package/dist/EmptyState-NBqf2_8z.js.map +0 -1
  285. package/dist/ExperimentPopover-CfOdh5Rm.js.map +0 -1
  286. package/dist/ExperimentSelectorModal-DvIagrxY.js.map +0 -1
  287. package/dist/SettingsModal-W3TYfnP9.js.map +0 -1
  288. package/dist/components-B80gV0P6.js.map +0 -1
  289. package/dist/composables/autoGroupConstants.d.ts +0 -1
  290. package/dist/composables/autoGroupGrouping.d.ts +0 -3
  291. package/dist/composables/useAutoGroupInputSources.d.ts +0 -32
  292. package/dist/composables-C8mmD5ta.js.map +0 -1
  293. package/dist/experiment-Y9Iz7KYi.js.map +0 -1
  294. package/dist/templates/builderDefaults.d.ts +0 -1
  295. package/dist/templates/plateGeometry.d.ts +0 -4
  296. package/dist/templates-CK72aKO1.js.map +0 -1
  297. package/dist/useApi-CDBq6z23.js.map +0 -1
  298. package/dist/useControlSchema-_OVhavKq.js.map +0 -1
  299. package/dist/useDropdownState-D5G4UvWd.js.map +0 -1
  300. package/dist/useProtocolTemplates-Dq5Pzwyd.js.map +0 -1
  301. package/src/__tests__/composables/useAutoGroupInputSources.test.ts +0 -127
  302. package/src/composables/autoGroupConstants.ts +0 -4
  303. package/src/composables/autoGroupGrouping.ts +0 -148
  304. package/src/composables/useAutoGroupInputSources.ts +0 -147
  305. package/src/templates/builderDefaults.ts +0 -11
  306. package/src/templates/plateGeometry.ts +0 -62
  307. /package/dist/__tests__/{composables/useAutoGroupInputSources.test.d.ts → components/DataStates.test.d.ts} +0 -0
@@ -217,7 +217,3 @@ defineExpose({ setStepValid })
217
217
  </div>
218
218
  </div>
219
219
  </template>
220
-
221
- <style>
222
- @import '../styles/components/step-wizard.css';
223
- </style>
@@ -44,11 +44,13 @@ const emit = defineEmits<{
44
44
  }>()
45
45
 
46
46
  const inputValue = ref('')
47
- const inputRef = ref<HTMLInputElement>()
48
47
  const highlightedIndex = ref(-1)
48
+ // The text input doubles as the dropdown trigger, so focus restoration is the
49
+ // composable's `triggerRef` rather than a component-local refocus helper.
49
50
  const {
50
51
  isOpen: dropdownOpen,
51
52
  rootRef,
53
+ triggerRef: inputRef,
52
54
  open: openDropdown,
53
55
  close: closeDropdown,
54
56
  } = useDropdownState({
@@ -129,7 +131,7 @@ function handleKeydown(event: KeyboardEvent) {
129
131
  return
130
132
  }
131
133
  if (event.key === 'Escape') {
132
- closeDropdown()
134
+ closeDropdown(true)
133
135
  return
134
136
  }
135
137
  if (event.key === 'Backspace' && !inputValue.value && props.modelValue.length > 0) {
@@ -274,7 +276,3 @@ function onInputEvent() {
274
276
  </div>
275
277
  </div>
276
278
  </template>
277
-
278
- <style>
279
- @import '../styles/components/tags-input.css';
280
- </style>
@@ -50,7 +50,3 @@ const { isDark, toggleTheme } = useTheme()
50
50
  </svg>
51
51
  </IconButton>
52
52
  </template>
53
-
54
- <style>
55
- @import '../styles/components/theme-toggle.css';
56
- </style>
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  /** Input that opens a scrollable time-slot dropdown in 12h or 24h format, with min/max range. */
3
- import { ref, computed, watch, nextTick } from 'vue'
3
+ import { ref, computed, watch, nextTick, useId } from 'vue'
4
4
  import { useDropdownState } from '../composables/useDropdownState'
5
5
  import {
6
6
  compareTime,
@@ -38,7 +38,15 @@ const emit = defineEmits<{
38
38
 
39
39
  const listRef = ref<HTMLUListElement | null>(null)
40
40
  const highlightedIndex = ref(-1)
41
- const { isOpen, rootRef, open, close, toggle } = useDropdownState()
41
+ const listboxId = `mint-time-picker-listbox-${useId().replace(/:/g, '')}`
42
+ const { isOpen, rootRef, triggerRef, open, close, toggle } = useDropdownState()
43
+
44
+ /** Id of the highlighted slot, published to the input as `aria-activedescendant`. */
45
+ const activeSlotId = computed(() =>
46
+ isOpen.value && highlightedIndex.value >= 0
47
+ ? `${listboxId}-option-${highlightedIndex.value}`
48
+ : undefined,
49
+ )
42
50
 
43
51
  const slots = computed(() => {
44
52
  const start = props.min ?? '00:00'
@@ -134,9 +142,29 @@ function handleKeydown(event: KeyboardEvent) {
134
142
  }
135
143
  break
136
144
  }
145
+ case 'Home': {
146
+ event.preventDefault()
147
+ const first = slots.value.findIndex(slot => !isSlotDisabled(slot))
148
+ if (first >= 0) {
149
+ highlightedIndex.value = first
150
+ scrollToHighlighted()
151
+ }
152
+ break
153
+ }
154
+ case 'End': {
155
+ event.preventDefault()
156
+ for (let index = slots.value.length - 1; index >= 0; index--) {
157
+ if (!isSlotDisabled(slots.value[index])) {
158
+ highlightedIndex.value = index
159
+ scrollToHighlighted()
160
+ break
161
+ }
162
+ }
163
+ break
164
+ }
137
165
  case 'Escape': {
138
166
  event.preventDefault()
139
- close()
167
+ close(true)
140
168
  break
141
169
  }
142
170
  }
@@ -172,6 +200,7 @@ watch(isOpen, (open) => {
172
200
  <div ref="rootRef" class="mint-time-picker" @keydown="handleKeydown">
173
201
  <div class="mint-time-picker__input-wrapper">
174
202
  <input
203
+ ref="triggerRef"
175
204
  type="text"
176
205
  readonly
177
206
  :value="displayValue"
@@ -186,6 +215,8 @@ watch(isOpen, (open) => {
186
215
  role="combobox"
187
216
  aria-haspopup="listbox"
188
217
  :aria-expanded="isOpen"
218
+ :aria-controls="isOpen ? listboxId : undefined"
219
+ :aria-activedescendant="activeSlotId"
189
220
  @click="toggleDropdown"
190
221
  />
191
222
  <button
@@ -219,6 +250,7 @@ watch(isOpen, (open) => {
219
250
  class="mint-time-picker__dropdown"
220
251
  >
221
252
  <ul
253
+ :id="listboxId"
222
254
  ref="listRef"
223
255
  class="mint-time-picker__list"
224
256
  role="listbox"
@@ -226,6 +258,7 @@ watch(isOpen, (open) => {
226
258
  >
227
259
  <li
228
260
  v-for="(slot, index) in slots"
261
+ :id="`${listboxId}-option-${index}`"
229
262
  :key="slot"
230
263
  role="option"
231
264
  :aria-selected="slot === modelValue"
@@ -245,7 +278,3 @@ watch(isOpen, (open) => {
245
278
  </Transition>
246
279
  </div>
247
280
  </template>
248
-
249
- <style>
250
- @import '../styles/components/time-picker.css';
251
- </style>
@@ -116,7 +116,3 @@ function onEndChange(value: string | undefined) {
116
116
  </div>
117
117
  </div>
118
118
  </template>
119
-
120
- <style>
121
- @import '../styles/components/time-range-input.css';
122
- </style>
@@ -55,15 +55,15 @@ const positions: ('top' | 'bottom' | 'left' | 'right')[] = ['top', 'bottom', 'le
55
55
  <p style="margin: 0;">
56
56
  The experiment used
57
57
  <Tooltip text="Dimethyl sulfoxide - a polar aprotic solvent" position="top" :delay="100">
58
- <span style="text-decoration: underline dotted; cursor: help; color: var(--mint-primary, #3B82F6);">DMSO</span>
58
+ <span style="text-decoration: underline dotted; cursor: help; color: var(--color-primary);">DMSO</span>
59
59
  </Tooltip>
60
60
  as the vehicle control. Samples were incubated at
61
61
  <Tooltip text="Standard mammalian cell culture temperature" position="top" :delay="100">
62
- <span style="text-decoration: underline dotted; cursor: help; color: var(--mint-primary, #3B82F6);">37 C</span>
62
+ <span style="text-decoration: underline dotted; cursor: help; color: var(--color-primary);">37 C</span>
63
63
  </Tooltip>
64
64
  for 24 hours before
65
65
  <Tooltip text="3-(4,5-dimethylthiazol-2-yl)-2,5-diphenyltetrazolium bromide" position="top" :delay="100">
66
- <span style="text-decoration: underline dotted; cursor: help; color: var(--mint-primary, #3B82F6);">MTT</span>
66
+ <span style="text-decoration: underline dotted; cursor: help; color: var(--color-primary);">MTT</span>
67
67
  </Tooltip>
68
68
  assay readout.
69
69
  </p>
@@ -108,7 +108,3 @@ function resolvedMaxWidth(value: string | number | undefined): string | undefine
108
108
  </Teleport>
109
109
  </span>
110
110
  </template>
111
-
112
- <style>
113
- @import '../styles/components/tooltip.css';
114
- </style>
@@ -211,7 +211,3 @@ watch(conversionHint, (hint) => {
211
211
  </div>
212
212
  </div>
213
213
  </template>
214
-
215
- <style>
216
- @import '../styles/components/unit-input.css';
217
- </style>
@@ -37,8 +37,67 @@ export const WELL_PLATE_SIZE_CONFIGS: Record<WellPlateSize, WellPlateSizeConfig>
37
37
  fill: { cellWidth: '100%', cellHeight: '32px', headerWidth: '32px', headerHeight: '24px', fontSize: '0.75rem', gap: '2px' },
38
38
  }
39
39
 
40
+ /**
41
+ * Spreadsheet-style row label for a zero-based row index: A…Z, then AA, AB, …
42
+ *
43
+ * This is the single row-label generator for the SDK — plate grids, rack
44
+ * grids, well-id parsing and the template builders all go through it.
45
+ */
46
+ export function rowLabel(index: number): string {
47
+ let label = ''
48
+ let current = index
49
+ for (;;) {
50
+ label = String.fromCharCode(65 + (current % 26)) + label
51
+ current = Math.floor(current / 26) - 1
52
+ if (current < 0) return label
53
+ }
54
+ }
55
+
56
+ /** Inverse of {@link rowLabel}: 'A' → 0, 'Z' → 25, 'AA' → 26. */
57
+ export function rowIndex(label: string): number {
58
+ return [...label].reduce((value, char) => value * 26 + char.charCodeAt(0) - 64, 0) - 1
59
+ }
60
+
40
61
  export function createPlateRowLabels(config: WellPlateConfig): string[] {
41
- return Array.from({ length: config.rows }, (_, index) => String.fromCharCode(65 + index))
62
+ return Array.from({ length: config.rows }, (_, index) => rowLabel(index))
63
+ }
64
+
65
+ function plateConfigOrThrow(format: number): WellPlateConfig {
66
+ const config = PLATE_CONFIGS[format as WellPlateFormat]
67
+ if (!config) throw new Error(`Unsupported plate format '${format}'.`)
68
+ return config
69
+ }
70
+
71
+ /** Every well id of a plate, row-major (A1, A2, … B1, …). */
72
+ export function wellIdsForFormat(format: number): string[] {
73
+ const { rows, cols } = plateConfigOrThrow(format)
74
+ return Array.from({ length: rows }, (_, row) =>
75
+ Array.from({ length: cols }, (_col, col) => `${rowLabel(row)}${col + 1}`)
76
+ ).flat()
77
+ }
78
+
79
+ /** Throw unless `wellId` names a well that exists on a `format`-well plate. */
80
+ export function assertWellInFormat(wellId: string, format: number): void {
81
+ const { rows, cols } = plateConfigOrThrow(format)
82
+ const match = /^([A-Z]+)([1-9][0-9]*)$/.exec(wellId.toUpperCase())
83
+ if (!match) {
84
+ throw new Error(`Invalid well id '${wellId}'.`)
85
+ }
86
+ const row = rowIndex(match[1])
87
+ const col = Number(match[2]) - 1
88
+ if (row < 0 || col < 0 || row >= rows || col >= cols) {
89
+ throw new Error(`Well '${wellId}' is outside a ${format}-well plate.`)
90
+ }
91
+ }
92
+
93
+ /** Coerce an unknown value to a supported plate format, else `fallback`. */
94
+ export function readPlateFormat(value: unknown, fallback: WellPlateFormat): WellPlateFormat {
95
+ const parsed = typeof value === 'number'
96
+ ? value
97
+ : typeof value === 'string'
98
+ ? Number(value)
99
+ : Number.NaN
100
+ return parsed in PLATE_CONFIGS ? (parsed as WellPlateFormat) : fallback
42
101
  }
43
102
 
44
103
  export function createPlateColumnLabels(config: WellPlateConfig): number[] {
@@ -11,6 +11,7 @@ import {
11
11
  type WellPlateCoordinate,
12
12
  } from './WellPlate.geometry'
13
13
  import { parseDroppedSampleTransfer } from './WellPlate.sampleDrop'
14
+ import { useReorderAnnouncer } from '../composables/useListReorder'
14
15
 
15
16
  export interface WellPlateInteractionOptions {
16
17
  modelValue: () => string[]
@@ -64,6 +65,7 @@ export function useWellPlateInteraction(options: WellPlateInteractionOptions) {
64
65
  const hoveredWell = ref<string | null>(null)
65
66
  const editingWellId = ref<string | null>(null)
66
67
  const editPopupPosition = ref({ x: 0, y: 0 })
68
+ const { announcement, announce, announcerStyle } = useReorderAnnouncer()
67
69
 
68
70
  const selectedWellSet = computed(() => new Set(options.modelValue()))
69
71
 
@@ -215,6 +217,45 @@ export function useWellPlateInteraction(options: WellPlateInteractionOptions) {
215
217
  dragTargetWell.value = null
216
218
  }
217
219
 
220
+ // Keyboard alternative to the well-to-well drag. The plate is a 2D grid, not a
221
+ // list, so it cannot use `useListReorder`'s index maths: instead Alt+Enter (or
222
+ // Alt+Space) picks a filled well up, the same chord on another well drops it
223
+ // there, and Escape cancels. Every step is announced politely.
224
+ function handleWellMoveKeydown(well: Well, event: KeyboardEvent) {
225
+ if (options.disabled() || options.readonly() || options.selectionMode() !== 'drag') return
226
+
227
+ if (event.key === 'Escape' && dragSourceWell.value) {
228
+ event.preventDefault()
229
+ announce(`Move cancelled. ${dragSourceWell.value} stays in place.`)
230
+ dragSourceWell.value = null
231
+ dragTargetWell.value = null
232
+ return
233
+ }
234
+
235
+ if (!event.altKey || (event.key !== 'Enter' && event.key !== ' ')) return
236
+ event.preventDefault()
237
+
238
+ const source = dragSourceWell.value
239
+ if (!source) {
240
+ if (!well.sampleType) {
241
+ announce(`Well ${well.id} is empty and cannot be moved.`)
242
+ return
243
+ }
244
+ dragSourceWell.value = well.id
245
+ announce(`Well ${well.id} picked up. Move to another well and press Alt and Enter to drop it.`)
246
+ return
247
+ }
248
+
249
+ if (source !== well.id) {
250
+ options.emitWellMove(source, well.id)
251
+ announce(`Well ${source} moved to ${well.id}.`)
252
+ } else {
253
+ announce(`Move cancelled. ${source} stays in place.`)
254
+ }
255
+ dragSourceWell.value = null
256
+ dragTargetWell.value = null
257
+ }
258
+
218
259
  function parseDroppedSample(event: DragEvent, wellId: string): WellSampleDropData | null {
219
260
  const customParser = options.sampleDropParser()
220
261
  if (customParser) return customParser(event, { wellId, event }) ?? null
@@ -267,6 +308,9 @@ export function useWellPlateInteraction(options: WellPlateInteractionOptions) {
267
308
  handleDragLeave,
268
309
  handleDrop,
269
310
  handleDragEnd,
311
+ handleWellMoveKeydown,
270
312
  handleKeyDown,
313
+ moveAnnouncement: announcement,
314
+ moveAnnouncerStyle: announcerStyle,
271
315
  }
272
316
  }
@@ -121,6 +121,8 @@ const doseWells = generateDoseWells()
121
121
 
122
122
  function initState() {
123
123
  return {
124
+ loading: false,
125
+ error: '',
124
126
  format: 96 as WellPlateFormat,
125
127
  selectionMode: 'multiple' as WellPlateSelectionMode,
126
128
  size: 'md' as WellPlateSize,
@@ -141,6 +143,8 @@ function initState() {
141
143
  <template #default="{ state }">
142
144
  <div style="padding: 2rem;">
143
145
  <WellPlate
146
+ :loading="state.loading"
147
+ :error="state.error || null"
144
148
  v-model="selectedWells"
145
149
  :format="state.format"
146
150
  :wells="generateMockWells(state.format)"
@@ -161,6 +165,10 @@ function initState() {
161
165
  </template>
162
166
 
163
167
  <template #controls="{ state }">
168
+
169
+ <HstCheckbox v-model="state.loading" title="Loading" />
170
+
171
+ <HstText v-model="state.error" title="Error Message" />
164
172
  <HstSelect
165
173
  v-model="state.format"
166
174
  title="Format"
@@ -32,6 +32,7 @@ import {
32
32
  wellStyle,
33
33
  } from './WellPlate.rendering'
34
34
  import { DEFAULT_WELL_LEGEND_ITEMS } from './WellPlate.legend'
35
+ import DataStateInternal from './internal/DataStateInternal.vue'
35
36
 
36
37
  interface Props {
37
38
  modelValue?: string[]
@@ -59,6 +60,19 @@ interface Props {
59
60
  rowConditions?: RowCondition[]
60
61
  allowSampleDrop?: boolean
61
62
  sampleDropParser?: WellSampleDropParser
63
+ /** Replace the plate grid with a loading placeholder. */
64
+ loading?: boolean
65
+ /**
66
+ * Error message. When set, the plate grid is replaced by an error state.
67
+ * `null`/`undefined` renders normally.
68
+ */
69
+ error?: string | null
70
+ /**
71
+ * Opt-in empty-state headline. A blank plate is meaningful, so the empty
72
+ * state only replaces the grid when this message is supplied and no wells
73
+ * carry data.
74
+ */
75
+ emptyMessage?: string
62
76
  }
63
77
 
64
78
  const props = withDefaults(defineProps<Props>(), {
@@ -114,6 +128,12 @@ interface WellEditorSlotProps {
114
128
 
115
129
  defineSlots<{
116
130
  'well-editor'?: (props: WellEditorSlotProps) => unknown
131
+ /** Replaces the default loading placeholder. */
132
+ loading?: () => unknown
133
+ /** Replaces the default error placeholder. */
134
+ error?: (props: { error: string }) => unknown
135
+ /** Replaces the default empty placeholder. */
136
+ empty?: () => unknown
117
137
  }>()
118
138
 
119
139
  const plateRef = ref<HTMLElement | null>(null)
@@ -166,7 +186,10 @@ const {
166
186
  handleDragLeave,
167
187
  handleDrop,
168
188
  handleDragEnd,
189
+ handleWellMoveKeydown,
169
190
  handleKeyDown,
191
+ moveAnnouncement,
192
+ moveAnnouncerStyle,
170
193
  } = useWellPlateInteraction({
171
194
  modelValue: () => props.modelValue,
172
195
  selectionMode: () => props.selectionMode,
@@ -233,6 +256,11 @@ const containerStyle = computed(() =>
233
256
  }
234
257
  )
235
258
 
259
+ /** Empty state is opt-in: it needs an `emptyMessage` and a plate with no well data. */
260
+ const showEmptyState = computed(() =>
261
+ Boolean(props.emptyMessage) && Object.keys(props.wells).length === 0,
262
+ )
263
+
236
264
  const tableStyle = computed(() => ({
237
265
  borderCollapse: 'separate' as const,
238
266
  borderSpacing: sizeConfig.value.gap,
@@ -246,7 +274,25 @@ const tableStyle = computed(() => ({
246
274
  :class="['mint-well-plate', isFillMode ? 'mint-well-plate--fill' : 'mint-well-plate--inline']"
247
275
  :style="containerStyle"
248
276
  >
249
- <div class="mint-well-plate__scroll">
277
+ <div v-if="error" class="mint-well-plate__state">
278
+ <slot name="error" :error="error">
279
+ <DataStateInternal state="error" :title="error" />
280
+ </slot>
281
+ </div>
282
+
283
+ <div v-else-if="loading" class="mint-well-plate__state">
284
+ <slot name="loading">
285
+ <DataStateInternal state="loading" loading-label="Loading plate" />
286
+ </slot>
287
+ </div>
288
+
289
+ <div v-else-if="showEmptyState" class="mint-well-plate__state">
290
+ <slot name="empty">
291
+ <DataStateInternal state="empty" :title="emptyMessage" />
292
+ </slot>
293
+ </div>
294
+
295
+ <div v-else class="mint-well-plate__scroll">
250
296
  <div class="mint-well-plate__content">
251
297
  <table
252
298
  ref="tableRef"
@@ -390,8 +436,9 @@ const tableStyle = computed(() => ({
390
436
  @dragleave="handleDragLeave"
391
437
  @drop="handleDrop(well, $event)"
392
438
  @dragend="handleDragEnd"
393
- @keydown.enter="handleWellClick(well, $event as unknown as MouseEvent)"
394
- @keydown.space.prevent="handleWellClick(well, $event as unknown as MouseEvent)"
439
+ @keydown="handleWellMoveKeydown(well, $event)"
440
+ @keydown.enter.exact="handleWellClick(well, $event as unknown as MouseEvent)"
441
+ @keydown.space.exact.prevent="handleWellClick(well, $event as unknown as MouseEvent)"
395
442
  >
396
443
  <!-- Well label text (from metadata.label) -->
397
444
  <span
@@ -489,9 +536,8 @@ const tableStyle = computed(() => ({
489
536
  />
490
537
  </slot>
491
538
  </template>
539
+
540
+ <!-- Keyboard well-move announcements for screen readers -->
541
+ <div role="status" aria-live="polite" :style="moveAnnouncerStyle">{{ moveAnnouncement }}</div>
492
542
  </div>
493
543
  </template>
494
-
495
- <style>
496
- @import '../styles/components/well-plate.css';
497
- </style>
@@ -24,7 +24,7 @@ const emit = defineEmits<{
24
24
  select: [page: PageSelectorItem]
25
25
  }>()
26
26
 
27
- const { isOpen, rootRef, close, toggle } = useDropdownState()
27
+ const { isOpen, rootRef, triggerRef, close, toggle } = useDropdownState()
28
28
  const normalizedPages = computed<PageSelectorItem[]>(() => props.pages.map(normalizeItemInput))
29
29
 
30
30
  const current = computed<PageSelectorItem | undefined>(() =>
@@ -45,6 +45,7 @@ function handleSelect(page: PageSelectorItem) {
45
45
  <template>
46
46
  <div ref="rootRef" class="mint-page-selector" :style="{ minWidth }">
47
47
  <button
48
+ ref="triggerRef"
48
49
  type="button"
49
50
  class="mint-page-selector__trigger"
50
51
  :class="{ 'mint-page-selector__trigger--open': isOpen }"
@@ -121,7 +122,3 @@ function handleSelect(page: PageSelectorItem) {
121
122
  </div>
122
123
  </div>
123
124
  </template>
124
-
125
- <style>
126
- @import '../../styles/components/app-page-selector.css';
127
- </style>
@@ -188,7 +188,3 @@ useEventListener(() => document, 'click', handleClickOutside)
188
188
  </div>
189
189
  </nav>
190
190
  </template>
191
-
192
- <style>
193
- @import '../../styles/components/app-pill-nav.css';
194
- </style>
@@ -0,0 +1,74 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * Shared loading / error / empty presentation for the SDK data components.
4
+ *
5
+ * Internal: not exported from the package entrypoints. Data components render
6
+ * this instead of hand-rolling their own placeholder markup so that the
7
+ * loading, error and empty states look the same everywhere.
8
+ */
9
+ import { computed } from 'vue'
10
+ import EmptyState from '../EmptyState.vue'
11
+ import LoadingSpinner from '../LoadingSpinner.vue'
12
+
13
+ /** Single-path warning triangle used for the error state. */
14
+ const ERROR_ICON_PATH
15
+ = 'M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z'
16
+ + 'M12 9v4M12 17h.01'
17
+
18
+ interface Props {
19
+ /** Which of the three placeholder states to render. */
20
+ state: 'loading' | 'error' | 'empty'
21
+ /** Headline for the empty/error state. */
22
+ title?: string
23
+ /** Supporting copy for the empty/error state. */
24
+ description?: string
25
+ /** Custom `<path d>` for the empty state icon (the error state has its own). */
26
+ iconPath?: string
27
+ /** Placeholder scale; also drives the loading spinner size. */
28
+ size?: 'sm' | 'md' | 'lg'
29
+ /** `EmptyState` layout variant. */
30
+ variant?: 'illustrated' | 'inline'
31
+ /** Accessible label (and visible caption) for the loading state. */
32
+ loadingLabel?: string
33
+ /** Optional call-to-action rendered under the empty/error copy. */
34
+ actionLabel?: string
35
+ }
36
+
37
+ const props = withDefaults(defineProps<Props>(), {
38
+ size: 'md',
39
+ variant: 'illustrated',
40
+ loadingLabel: 'Loading',
41
+ })
42
+
43
+ const emit = defineEmits<{
44
+ action: []
45
+ }>()
46
+
47
+ const spinnerSize = computed(() => (props.size === 'sm' ? 'sm' : props.size === 'lg' ? 'lg' : 'md'))
48
+ </script>
49
+
50
+ <template>
51
+ <div
52
+ :class="['mint-data-state', `mint-data-state--${state}`, `mint-data-state--${size}`]"
53
+ :data-state="state"
54
+ >
55
+ <template v-if="state === 'loading'">
56
+ <LoadingSpinner :size="spinnerSize" :label="loadingLabel" />
57
+ <p class="mint-data-state__loading-text" aria-hidden="true">{{ loadingLabel }}</p>
58
+ </template>
59
+ <EmptyState
60
+ v-else
61
+ :title="title"
62
+ :description="description"
63
+ :icon-path="state === 'error' ? ERROR_ICON_PATH : iconPath"
64
+ :color="state === 'error' ? 'error' : 'muted'"
65
+ :size="size"
66
+ :variant="variant"
67
+ :action-label="actionLabel"
68
+ @action="emit('action')"
69
+ >
70
+ <slot />
71
+ </EmptyState>
72
+ </div>
73
+ </template>
74
+
@@ -72,7 +72,3 @@ const gridStyle = computed(() => ({
72
72
  <slot :name="`section:${section.id}:after`" :form="builder.form" />
73
73
  </div>
74
74
  </template>
75
-
76
- <style>
77
- @import '../../styles/components/form-builder.css';
78
- </style>
@@ -243,7 +243,3 @@ const sampleTypeButtons = [
243
243
  </div>
244
244
  </Teleport>
245
245
  </template>
246
-
247
- <style>
248
- @import '../../styles/components/well-edit-popup.css';
249
- </style>
@@ -42,10 +42,27 @@ export interface ControlSectionConfig {
42
42
  actions?: SidebarToolSectionAction[]
43
43
  columns?: 1 | 2 | 3
44
44
  condition?: FieldCondition
45
+ /** The access policy. Preferred over the flat fields below. */
45
46
  access?: AccessPolicy
47
+ /**
48
+ * @deprecated Since MINT 1.2; use `access.visibleFor` instead. The flat
49
+ * duplicate is removed in 1.3.
50
+ */
46
51
  visibleFor?: AccessAudienceInput
52
+ /**
53
+ * @deprecated Since MINT 1.2; use `access.requiresAdmin` instead. The flat
54
+ * duplicate is removed in 1.3.
55
+ */
47
56
  requiresAdmin?: boolean
57
+ /**
58
+ * @deprecated Since MINT 1.2; use `access.permissions` instead. The flat
59
+ * duplicate is removed in 1.3.
60
+ */
48
61
  permissions?: readonly string[]
62
+ /**
63
+ * @deprecated Since MINT 1.2; use `access.anyPermissions` instead. The flat
64
+ * duplicate is removed in 1.3.
65
+ */
49
66
  anyPermissions?: readonly string[]
50
67
  defaultOpen?: boolean
51
68
  showToggle?: boolean
@@ -86,10 +103,27 @@ export interface ControlDefinition {
86
103
  pattern?: string | { value: string; message: string }
87
104
  validation?: FieldValidation
88
105
  condition?: FieldCondition
106
+ /** The access policy. Preferred over the flat fields below. */
89
107
  access?: AccessPolicy
108
+ /**
109
+ * @deprecated Since MINT 1.2; use `access.visibleFor` instead. The flat
110
+ * duplicate is removed in 1.3.
111
+ */
90
112
  visibleFor?: AccessAudienceInput
113
+ /**
114
+ * @deprecated Since MINT 1.2; use `access.requiresAdmin` instead. The flat
115
+ * duplicate is removed in 1.3.
116
+ */
91
117
  requiresAdmin?: boolean
118
+ /**
119
+ * @deprecated Since MINT 1.2; use `access.permissions` instead. The flat
120
+ * duplicate is removed in 1.3.
121
+ */
92
122
  permissions?: readonly string[]
123
+ /**
124
+ * @deprecated Since MINT 1.2; use `access.anyPermissions` instead. The flat
125
+ * duplicate is removed in 1.3.
126
+ */
93
127
  anyPermissions?: readonly string[]
94
128
  options?: readonly ControlOption[]
95
129
  section?: string
@@ -549,6 +549,16 @@ export {
549
549
  type UseRovingFocusOptions,
550
550
  type UseRovingFocusReturn,
551
551
  } from './useRovingFocus'
552
+ export {
553
+ reorderList,
554
+ useListReorder,
555
+ useReorderAnnouncer,
556
+ REORDER_ANNOUNCER_STYLE,
557
+ type ListReorderMove,
558
+ type UseListReorderOptions,
559
+ type UseListReorderReturn,
560
+ type UseReorderAnnouncerReturn,
561
+ } from './useListReorder'
552
562
  export {
553
563
  useMenuKeyboard,
554
564
  type UseMenuKeyboardOptions,