@morscherlab/mint-sdk 1.0.0-beta.1 → 1.0.0-beta.3

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 (421) hide show
  1. package/README.md +218 -6
  2. package/dist/__tests__/components/ActionItem.test.d.ts +1 -0
  3. package/dist/__tests__/components/AppAvatarMenu.test.d.ts +1 -0
  4. package/dist/__tests__/components/AppPageSelector.test.d.ts +1 -0
  5. package/dist/__tests__/components/AppPillNav.test.d.ts +1 -0
  6. package/dist/__tests__/components/AppPluginSwitcher.test.d.ts +1 -0
  7. package/dist/__tests__/components/AppToastContainer.test.d.ts +1 -0
  8. package/dist/__tests__/components/BaseRadioGroup.test.d.ts +1 -0
  9. package/dist/__tests__/components/BaseSelect.test.d.ts +1 -0
  10. package/dist/__tests__/components/BaseTabs.test.d.ts +1 -0
  11. package/dist/__tests__/components/BatchProgressList.test.d.ts +1 -0
  12. package/dist/__tests__/components/BioTemplateExperimentWorkspaceView.test.d.ts +1 -0
  13. package/dist/__tests__/components/BioTemplatePackWorkspaceView.test.d.ts +1 -0
  14. package/dist/__tests__/components/BioTemplatePresetWorkspaceView.test.d.ts +1 -0
  15. package/dist/__tests__/components/BioTemplateRenderer.test.d.ts +1 -0
  16. package/dist/__tests__/components/Breadcrumb.test.d.ts +1 -0
  17. package/dist/__tests__/components/CalendarGridPanel.test.d.ts +1 -0
  18. package/dist/__tests__/components/ConcentrationInput.test.d.ts +1 -0
  19. package/dist/__tests__/components/ControlWorkspaceView.test.d.ts +1 -0
  20. package/dist/__tests__/components/DatePicker.test.d.ts +1 -0
  21. package/dist/__tests__/components/DateTimePicker.test.d.ts +1 -0
  22. package/dist/__tests__/components/EmptyState.test.d.ts +1 -0
  23. package/dist/__tests__/components/ExperimentPopover.test.d.ts +1 -0
  24. package/dist/__tests__/components/FormBuilder.test.d.ts +1 -0
  25. package/dist/__tests__/components/FormCompatibility.test.d.ts +1 -0
  26. package/dist/__tests__/components/GroupAssigner.test.d.ts +1 -0
  27. package/dist/__tests__/components/GroupingModal.test.d.ts +1 -0
  28. package/dist/__tests__/components/MultiSelect.test.d.ts +1 -0
  29. package/dist/__tests__/components/PluginIcon.test.d.ts +1 -0
  30. package/dist/__tests__/components/ProtocolStepEditor.test.d.ts +1 -0
  31. package/dist/__tests__/components/ReagentList.test.d.ts +1 -0
  32. package/dist/__tests__/components/SampleHierarchyTree.test.d.ts +1 -0
  33. package/dist/__tests__/components/SampleSelector.test.d.ts +1 -0
  34. package/dist/__tests__/components/SegmentedControl.test.d.ts +1 -0
  35. package/dist/__tests__/components/SettingsButton.test.d.ts +1 -0
  36. package/dist/__tests__/components/SettingsModal.test.d.ts +1 -0
  37. package/dist/__tests__/components/TagsInput.test.d.ts +1 -0
  38. package/dist/__tests__/components/ThemeToggle.test.d.ts +1 -0
  39. package/dist/__tests__/components/TimePicker.test.d.ts +1 -0
  40. package/dist/__tests__/composables/useBioTemplatePackWorkspace.test.d.ts +1 -0
  41. package/dist/__tests__/composables/useBioTemplatePresetWorkspace.test.d.ts +1 -0
  42. package/dist/__tests__/composables/useBioTemplateWorkspace.test.d.ts +1 -0
  43. package/dist/__tests__/composables/useCalendarGrid.test.d.ts +1 -0
  44. package/dist/__tests__/composables/useControlSchema.test.d.ts +1 -0
  45. package/dist/__tests__/composables/useDebouncedWatch.test.d.ts +1 -0
  46. package/dist/__tests__/composables/useDropdownState.test.d.ts +1 -0
  47. package/dist/__tests__/composables/useEventListener.test.d.ts +1 -0
  48. package/dist/__tests__/composables/useExpansionSet.test.d.ts +1 -0
  49. package/dist/__tests__/composables/useExperimentData.test.d.ts +1 -0
  50. package/dist/__tests__/composables/useExperimentSelector.test.d.ts +1 -0
  51. package/dist/__tests__/composables/useGroupAssignment.test.d.ts +1 -0
  52. package/dist/__tests__/composables/useListSelection.test.d.ts +1 -0
  53. package/dist/__tests__/composables/usePluginClient.test.d.ts +1 -0
  54. package/dist/__tests__/composables/usePluginConfig.test.d.ts +1 -0
  55. package/dist/__tests__/composables/useRequestSyncState.test.d.ts +1 -0
  56. package/dist/__tests__/composables/useSampleGroups.test.d.ts +1 -0
  57. package/dist/__tests__/composables/useSelectionLimit.test.d.ts +1 -0
  58. package/dist/__tests__/composables/useSortedItems.test.d.ts +1 -0
  59. package/dist/__tests__/composables/useTemplateCollection.test.d.ts +1 -0
  60. package/dist/__tests__/composables/useTextSearch.test.d.ts +1 -0
  61. package/dist/__tests__/composables/useTheme.test.d.ts +1 -0
  62. package/dist/__tests__/composables/useTimeUtils.test.d.ts +1 -0
  63. package/dist/__tests__/docs/frontendDocsCatalog.test.d.ts +1 -0
  64. package/dist/__tests__/templates/templates.test.d.ts +1 -0
  65. package/dist/{auth-DsI0rQ7_.js → auth-QQj2kkze.js} +12 -5
  66. package/dist/auth-QQj2kkze.js.map +1 -0
  67. package/dist/components/ActionItem.vue.d.ts +32 -0
  68. package/dist/components/AppAvatarMenu.vue.d.ts +2 -7
  69. package/dist/components/AppPageSelector.vue.d.ts +3 -6
  70. package/dist/components/AppPillNav.vue.d.ts +2 -2
  71. package/dist/components/AppSidebar.vue.d.ts +56 -3
  72. package/dist/components/AppToastContainer.vue.d.ts +2 -0
  73. package/dist/components/AppTopBar.vue.d.ts +43 -10
  74. package/dist/components/BaseButton.vue.d.ts +2 -2
  75. package/dist/components/BaseCheckbox.vue.d.ts +1 -1
  76. package/dist/components/BaseInput.vue.d.ts +2 -2
  77. package/dist/components/BasePill.vue.d.ts +3 -3
  78. package/dist/components/BaseRadioGroup.vue.d.ts +4 -4
  79. package/dist/components/BaseSelect.vue.d.ts +4 -4
  80. package/dist/components/BaseSlider.vue.d.ts +1 -1
  81. package/dist/components/BaseTabs.vue.d.ts +2 -2
  82. package/dist/components/BaseTextarea.vue.d.ts +2 -2
  83. package/dist/components/BaseToggle.vue.d.ts +1 -1
  84. package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +117 -0
  85. package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +92 -0
  86. package/dist/components/BioTemplatePresetWorkspaceView.vue.d.ts +82 -0
  87. package/dist/components/BioTemplateRenderer.vue.d.ts +29 -0
  88. package/dist/components/Breadcrumb.vue.d.ts +2 -2
  89. package/dist/components/Calendar.vue.d.ts +1 -1
  90. package/dist/components/CalendarGridPanel.vue.d.ts +25 -0
  91. package/dist/components/CollapsibleCard.vue.d.ts +1 -1
  92. package/dist/components/ColorSlider.vue.d.ts +1 -1
  93. package/dist/components/ConcentrationInput.vue.d.ts +2 -2
  94. package/dist/components/ConfirmDialog.vue.d.ts +2 -2
  95. package/dist/components/ControlWorkspaceView.vue.d.ts +130 -0
  96. package/dist/components/DatePicker.vue.d.ts +2 -2
  97. package/dist/components/DateTimePicker.vue.d.ts +3 -3
  98. package/dist/components/DropdownButton.vue.d.ts +4 -4
  99. package/dist/components/EmptyState.vue.d.ts +1 -2
  100. package/dist/components/ExperimentDataViewer.vue.d.ts +1 -1
  101. package/dist/components/ExperimentTimeline.vue.d.ts +2 -2
  102. package/dist/components/FileUploader.vue.d.ts +2 -2
  103. package/dist/components/FitPanel.vue.d.ts +1 -1
  104. package/dist/components/FormActions.vue.d.ts +4 -4
  105. package/dist/components/FormBuilder.vue.d.ts +22 -8
  106. package/dist/components/FormFieldRenderer.vue.d.ts +7 -10
  107. package/dist/components/FormSection.vue.d.ts +11 -24
  108. package/dist/components/FormulaInput.vue.d.ts +2 -2
  109. package/dist/components/IconButton.vue.d.ts +1 -1
  110. package/dist/components/LoadingSpinner.vue.d.ts +1 -1
  111. package/dist/components/MoleculeInput.vue.d.ts +2 -2
  112. package/dist/components/MultiSelect.vue.d.ts +3 -3
  113. package/dist/components/NumberInput.vue.d.ts +2 -2
  114. package/dist/components/PluginIcon.vue.d.ts +11 -0
  115. package/dist/components/ProgressBar.vue.d.ts +2 -2
  116. package/dist/components/ProtocolStepEditor.vue.d.ts +3 -1
  117. package/dist/components/RackEditor.vue.d.ts +2 -2
  118. package/dist/components/ReagentEditor.vue.d.ts +1 -1
  119. package/dist/components/ResourceCard.vue.d.ts +1 -1
  120. package/dist/components/SampleLegend.vue.d.ts +2 -2
  121. package/dist/components/SampleSelector.vue.d.ts +1 -1
  122. package/dist/components/ScheduleCalendar.vue.d.ts +2 -2
  123. package/dist/components/ScientificNumber.vue.d.ts +1 -1
  124. package/dist/components/SegmentedControl.vue.d.ts +3 -3
  125. package/dist/components/SequenceInput.vue.d.ts +3 -3
  126. package/dist/components/SettingsButton.vue.d.ts +2 -2
  127. package/dist/components/SettingsModal.vue.d.ts +32 -4
  128. package/dist/components/StatusIndicator.vue.d.ts +1 -1
  129. package/dist/components/TagsInput.vue.d.ts +3 -2
  130. package/dist/components/TimePicker.vue.d.ts +3 -3
  131. package/dist/components/TimeRangeInput.vue.d.ts +2 -2
  132. package/dist/components/UnitInput.vue.d.ts +2 -2
  133. package/dist/components/WellPlate.vue.d.ts +8 -8
  134. package/dist/components/index.d.ts +12 -1
  135. package/dist/components/index.js +3 -3
  136. package/dist/components/internal/FormFieldRendererInternal.vue.d.ts +31 -0
  137. package/dist/components/internal/FormSectionRenderer.vue.d.ts +43 -0
  138. package/dist/{components-CzbQQPCb.js → components-D_Sr0adg.js} +9629 -8647
  139. package/dist/components-D_Sr0adg.js.map +1 -0
  140. package/dist/composables/index.d.ts +21 -2
  141. package/dist/composables/index.js +4 -3
  142. package/dist/composables/platformContextHelpers.d.ts +14 -0
  143. package/dist/composables/useBioTemplateComponents.d.ts +20 -0
  144. package/dist/composables/useBioTemplateControls.d.ts +6 -0
  145. package/dist/composables/useBioTemplatePackWorkspace.d.ts +45 -0
  146. package/dist/composables/useBioTemplatePresetWorkspace.d.ts +74 -0
  147. package/dist/composables/useBioTemplateWorkspace.d.ts +50 -0
  148. package/dist/composables/useCalendarGrid.d.ts +26 -0
  149. package/dist/composables/useControlSchema.d.ts +321 -0
  150. package/dist/composables/useDebouncedWatch.d.ts +20 -0
  151. package/dist/composables/useDropdownState.d.ts +19 -0
  152. package/dist/composables/useEventListener.d.ts +13 -0
  153. package/dist/composables/useExpansionSet.d.ts +21 -0
  154. package/dist/composables/useExperimentData.d.ts +10 -0
  155. package/dist/composables/useExperimentSave.d.ts +31 -2
  156. package/dist/composables/useExperimentSelector.d.ts +20 -0
  157. package/dist/composables/useForm.d.ts +2 -0
  158. package/dist/composables/useGroupAssignment.d.ts +31 -0
  159. package/dist/composables/useListSelection.d.ts +35 -0
  160. package/dist/composables/usePlatformContext.d.ts +24 -3
  161. package/dist/composables/usePluginApi.d.ts +7 -14
  162. package/dist/composables/usePluginClient.d.ts +109 -0
  163. package/dist/composables/usePluginConfig.d.ts +12 -0
  164. package/dist/composables/useRequestSyncState.d.ts +34 -0
  165. package/dist/composables/useSampleGroups.d.ts +32 -0
  166. package/dist/composables/useSelectionLimit.d.ts +17 -0
  167. package/dist/composables/useSortedItems.d.ts +32 -0
  168. package/dist/composables/useTemplateCollection.d.ts +58 -0
  169. package/dist/composables/useTextSearch.d.ts +18 -0
  170. package/dist/composables/useTimeUtils.d.ts +8 -0
  171. package/dist/{composables-BXklV5ii.js → composables-C3dpXQN5.js} +228 -146
  172. package/dist/composables-C3dpXQN5.js.map +1 -0
  173. package/dist/index.d.ts +12 -3
  174. package/dist/index.js +6 -5
  175. package/dist/install.d.ts +7 -2
  176. package/dist/install.js +2 -2
  177. package/dist/install.js.map +1 -1
  178. package/dist/stores/auth.d.ts +1 -1
  179. package/dist/stores/index.js +1 -1
  180. package/dist/stores/settings.d.ts +4 -1
  181. package/dist/styles.css +5255 -5654
  182. package/dist/templates/adapters.d.ts +43 -0
  183. package/dist/templates/builders.d.ts +63 -0
  184. package/dist/templates/catalog.d.ts +188 -0
  185. package/dist/templates/componentBindings.d.ts +58 -0
  186. package/dist/templates/controlSchemas.d.ts +25 -0
  187. package/dist/templates/index.d.ts +15 -0
  188. package/dist/templates/index.js +2 -0
  189. package/dist/templates/lookup.d.ts +4 -0
  190. package/dist/templates/packs.d.ts +18 -0
  191. package/dist/templates/presets.d.ts +90 -0
  192. package/dist/templates/types.d.ts +531 -0
  193. package/dist/templates-50NPjaxL.js +9333 -0
  194. package/dist/templates-50NPjaxL.js.map +1 -0
  195. package/dist/types/components.d.ts +62 -1
  196. package/dist/types/form-builder.d.ts +6 -8
  197. package/dist/types/index.d.ts +2 -2
  198. package/dist/types/platform.d.ts +8 -1
  199. package/dist/useScheduleDrag-D4oWdh41.js +4371 -0
  200. package/dist/useScheduleDrag-D4oWdh41.js.map +1 -0
  201. package/dist/utils/formModelSync.d.ts +5 -0
  202. package/dist/utils/items.d.ts +8 -0
  203. package/dist/utils/options.d.ts +6 -0
  204. package/dist/utils/pluginIcon.d.ts +9 -0
  205. package/package.json +7 -2
  206. package/src/__tests__/components/ActionItem.test.ts +99 -0
  207. package/src/__tests__/components/AppAvatarMenu.test.ts +27 -0
  208. package/src/__tests__/components/AppPageSelector.test.ts +134 -0
  209. package/src/__tests__/components/AppPillNav.test.ts +78 -0
  210. package/src/__tests__/components/AppPluginSwitcher.test.ts +44 -0
  211. package/src/__tests__/components/AppSidebar.test.ts +370 -0
  212. package/src/__tests__/components/AppToastContainer.test.ts +48 -0
  213. package/src/__tests__/components/AppTopBar.test.ts +414 -13
  214. package/src/__tests__/components/BaseRadioGroup.test.ts +25 -0
  215. package/src/__tests__/components/BaseSelect.test.ts +21 -0
  216. package/src/__tests__/components/BaseTabs.test.ts +25 -0
  217. package/src/__tests__/components/BatchProgressList.test.ts +52 -0
  218. package/src/__tests__/components/BioTemplateExperimentWorkspaceView.test.ts +153 -0
  219. package/src/__tests__/components/BioTemplatePackWorkspaceView.test.ts +161 -0
  220. package/src/__tests__/components/BioTemplatePresetWorkspaceView.test.ts +281 -0
  221. package/src/__tests__/components/BioTemplateRenderer.test.ts +71 -0
  222. package/src/__tests__/components/Breadcrumb.test.ts +23 -0
  223. package/src/__tests__/components/CalendarGridPanel.test.ts +36 -0
  224. package/src/__tests__/components/ConcentrationInput.test.ts +45 -0
  225. package/src/__tests__/components/ControlWorkspaceView.test.ts +1031 -0
  226. package/src/__tests__/components/DataFrame.test.ts +11 -0
  227. package/src/__tests__/components/DatePicker.test.ts +45 -0
  228. package/src/__tests__/components/DateTimePicker.test.ts +48 -0
  229. package/src/__tests__/components/DropdownButton.test.ts +23 -0
  230. package/src/__tests__/components/EmptyState.test.ts +23 -0
  231. package/src/__tests__/components/ExperimentPopover.test.ts +56 -0
  232. package/src/__tests__/components/FormBuilder.test.ts +296 -0
  233. package/src/__tests__/components/FormCompatibility.test.ts +94 -0
  234. package/src/__tests__/components/GroupAssigner.test.ts +30 -0
  235. package/src/__tests__/components/GroupingModal.test.ts +73 -0
  236. package/src/__tests__/components/MultiSelect.test.ts +48 -0
  237. package/src/__tests__/components/PluginIcon.test.ts +119 -0
  238. package/src/__tests__/components/ProtocolStepEditor.test.ts +33 -0
  239. package/src/__tests__/components/ReagentList.test.ts +82 -0
  240. package/src/__tests__/components/SampleHierarchyTree.test.ts +53 -0
  241. package/src/__tests__/components/SampleSelector.test.ts +60 -0
  242. package/src/__tests__/components/SegmentedControl.test.ts +24 -0
  243. package/src/__tests__/components/SettingsButton.test.ts +44 -0
  244. package/src/__tests__/components/SettingsModal.test.ts +296 -0
  245. package/src/__tests__/components/TagsInput.test.ts +75 -0
  246. package/src/__tests__/components/ThemeToggle.test.ts +47 -0
  247. package/src/__tests__/components/TimePicker.test.ts +38 -0
  248. package/src/__tests__/composables/useBioTemplatePackWorkspace.test.ts +122 -0
  249. package/src/__tests__/composables/useBioTemplatePresetWorkspace.test.ts +199 -0
  250. package/src/__tests__/composables/useBioTemplateWorkspace.test.ts +99 -0
  251. package/src/__tests__/composables/useCalendarGrid.test.ts +38 -0
  252. package/src/__tests__/composables/useControlSchema.test.ts +919 -0
  253. package/src/__tests__/composables/useDebouncedWatch.test.ts +93 -0
  254. package/src/__tests__/composables/useDropdownState.test.ts +95 -0
  255. package/src/__tests__/composables/useEventListener.test.ts +116 -0
  256. package/src/__tests__/composables/useExpansionSet.test.ts +62 -0
  257. package/src/__tests__/composables/useExperimentData.test.ts +4 -0
  258. package/src/__tests__/composables/useExperimentSave.test.ts +203 -8
  259. package/src/__tests__/composables/useExperimentSelector.test.ts +164 -0
  260. package/src/__tests__/composables/useForm.test.ts +58 -0
  261. package/src/__tests__/composables/useFormBuilder.test.ts +77 -0
  262. package/src/__tests__/composables/useGroupAssignment.test.ts +73 -0
  263. package/src/__tests__/composables/useListSelection.test.ts +66 -0
  264. package/src/__tests__/composables/usePluginClient.test.ts +444 -0
  265. package/src/__tests__/composables/usePluginConfig.test.ts +5 -0
  266. package/src/__tests__/composables/useRequestSyncState.test.ts +92 -0
  267. package/src/__tests__/composables/useSampleGroups.test.ts +66 -0
  268. package/src/__tests__/composables/useSelectionLimit.test.ts +41 -0
  269. package/src/__tests__/composables/useSortedItems.test.ts +87 -0
  270. package/src/__tests__/composables/useTemplateCollection.test.ts +147 -0
  271. package/src/__tests__/composables/useTextSearch.test.ts +55 -0
  272. package/src/__tests__/composables/useTheme.test.ts +91 -0
  273. package/src/__tests__/composables/useTimeUtils.test.ts +35 -0
  274. package/src/__tests__/docs/frontendDocsCatalog.test.ts +229 -0
  275. package/src/__tests__/fixtures/templates/dose-response.json +81 -0
  276. package/src/__tests__/fixtures/templates/plate-map.json +54 -0
  277. package/src/__tests__/fixtures/templates/qpcr-plate.json +96 -0
  278. package/src/__tests__/fixtures/templates/sample-sheet.json +71 -0
  279. package/src/__tests__/templates/templates.test.ts +1043 -0
  280. package/src/components/ActionItem.vue +82 -0
  281. package/src/components/AppAvatarMenu.vue +15 -69
  282. package/src/components/AppLayout.story.vue +25 -25
  283. package/src/components/AppPageSelector.vue +63 -94
  284. package/src/components/AppPillNav.vue +44 -39
  285. package/src/components/AppPluginSwitcher.vue +41 -145
  286. package/src/components/AppSidebar.story.vue +94 -0
  287. package/src/components/AppSidebar.vue +187 -12
  288. package/src/components/{ToastNotification.story.vue → AppToastContainer.story.vue} +6 -6
  289. package/src/components/AppToastContainer.vue +62 -0
  290. package/src/components/AppTopBar.story.vue +7 -30
  291. package/src/components/AppTopBar.vue +283 -84
  292. package/src/components/BaseModal.vue +3 -5
  293. package/src/components/BaseRadioGroup.vue +7 -3
  294. package/src/components/BaseSelect.vue +11 -7
  295. package/src/components/BaseTabs.vue +6 -4
  296. package/src/components/BatchProgressList.vue +5 -8
  297. package/src/components/BioTemplateExperimentWorkspaceView.story.vue +123 -0
  298. package/src/components/BioTemplateExperimentWorkspaceView.vue +337 -0
  299. package/src/components/BioTemplatePackWorkspaceView.story.vue +107 -0
  300. package/src/components/BioTemplatePackWorkspaceView.vue +176 -0
  301. package/src/components/BioTemplatePresetWorkspaceView.story.vue +151 -0
  302. package/src/components/BioTemplatePresetWorkspaceView.vue +392 -0
  303. package/src/components/BioTemplateRenderer.story.vue +57 -0
  304. package/src/components/BioTemplateRenderer.vue +269 -0
  305. package/src/components/Breadcrumb.vue +14 -8
  306. package/src/components/CalendarGridPanel.vue +120 -0
  307. package/src/components/ConcentrationInput.vue +27 -64
  308. package/src/components/ControlWorkspaceView.story.vue +336 -0
  309. package/src/components/ControlWorkspaceView.vue +347 -0
  310. package/src/components/DataFrame.vue +34 -50
  311. package/src/components/DatePicker.vue +59 -192
  312. package/src/components/DateTimePicker.vue +50 -171
  313. package/src/components/DropdownButton.vue +14 -32
  314. package/src/components/EmptyState.vue +4 -2
  315. package/src/components/ExperimentPopover.vue +5 -22
  316. package/src/components/FormBuilder.vue +124 -27
  317. package/src/components/FormFieldRenderer.vue +15 -38
  318. package/src/components/FormSection.vue +20 -73
  319. package/src/components/GroupAssigner.vue +24 -56
  320. package/src/components/GroupingModal.story.vue +3 -3
  321. package/src/components/GroupingModal.vue +30 -391
  322. package/src/components/MultiSelect.vue +17 -12
  323. package/src/components/PlateMapEditor.vue +3 -8
  324. package/src/components/PluginIcon.story.vue +71 -0
  325. package/src/components/PluginIcon.vue +68 -0
  326. package/src/components/ProtocolStepEditor.vue +13 -22
  327. package/src/components/ReagentList.vue +25 -33
  328. package/src/components/SampleHierarchyTree.vue +12 -23
  329. package/src/components/SampleSelector.vue +42 -122
  330. package/src/components/SegmentedControl.vue +7 -3
  331. package/src/components/SettingsButton.story.vue +1 -1
  332. package/src/components/SettingsButton.vue +15 -27
  333. package/src/components/SettingsModal.story.vue +337 -45
  334. package/src/components/SettingsModal.vue +344 -66
  335. package/src/components/TagsInput.vue +29 -14
  336. package/src/components/ThemeToggle.vue +9 -7
  337. package/src/components/TimePicker.vue +19 -41
  338. package/src/components/ToastNotification.vue +4 -57
  339. package/src/components/Tooltip.vue +7 -12
  340. package/src/components/WellEditPopup.vue +3 -8
  341. package/src/components/WellPlate.vue +4 -10
  342. package/src/components/index.ts +12 -1
  343. package/src/components/internal/FormFieldRendererInternal.vue +50 -0
  344. package/src/components/internal/FormSectionRenderer.vue +78 -0
  345. package/src/composables/index.ts +212 -0
  346. package/src/composables/platformContextHelpers.ts +74 -0
  347. package/src/composables/useBioTemplateComponents.ts +93 -0
  348. package/src/composables/useBioTemplateControls.ts +41 -0
  349. package/src/composables/useBioTemplatePackWorkspace.ts +181 -0
  350. package/src/composables/useBioTemplatePresetWorkspace.ts +337 -0
  351. package/src/composables/useBioTemplateWorkspace.ts +139 -0
  352. package/src/composables/useCalendarGrid.ts +140 -0
  353. package/src/composables/useControlSchema.ts +1274 -0
  354. package/src/composables/useDebouncedWatch.ts +119 -0
  355. package/src/composables/useDropdownState.ts +83 -0
  356. package/src/composables/useEventListener.ts +111 -0
  357. package/src/composables/useExpansionSet.ts +117 -0
  358. package/src/composables/useExperimentData.ts +20 -11
  359. package/src/composables/useExperimentSave.ts +202 -50
  360. package/src/composables/useExperimentSelector.ts +86 -72
  361. package/src/composables/useForm.ts +49 -4
  362. package/src/composables/useFormBuilder.ts +93 -42
  363. package/src/composables/useGroupAssignment.ts +148 -0
  364. package/src/composables/useListSelection.ts +158 -0
  365. package/src/composables/usePluginApi.ts +7 -14
  366. package/src/composables/usePluginClient.ts +425 -0
  367. package/src/composables/usePluginConfig.ts +34 -13
  368. package/src/composables/useRequestSyncState.ts +126 -0
  369. package/src/composables/useSampleGroups.ts +126 -0
  370. package/src/composables/useSelectionLimit.ts +57 -0
  371. package/src/composables/useSortedItems.ts +118 -0
  372. package/src/composables/useTemplateCollection.ts +229 -0
  373. package/src/composables/useTextSearch.ts +60 -0
  374. package/src/composables/useTheme.ts +2 -28
  375. package/src/composables/useTimeUtils.ts +26 -2
  376. package/src/composables/useWellPlateEditor.ts +13 -9
  377. package/src/index.ts +228 -4
  378. package/src/install.ts +11 -4
  379. package/src/stores/settings.ts +13 -9
  380. package/src/styles/components/app-page-selector.css +23 -0
  381. package/src/styles/components/app-pill-nav.css +8 -2
  382. package/src/styles/components/app-top-bar.css +35 -2
  383. package/src/styles/components/button.css +3 -7
  384. package/src/styles/components/concentration-input.css +3 -142
  385. package/src/styles/components/dropdown-button.css +4 -4
  386. package/src/styles/components/empty-state.css +0 -16
  387. package/src/styles/components/input.css +4 -5
  388. package/src/styles/components/number-input.css +3 -3
  389. package/src/styles/components/plugin-icon.css +38 -0
  390. package/src/styles/components/segmented-control.css +4 -7
  391. package/src/styles/components/settings-button.css +3 -66
  392. package/src/styles/components/settings-modal.css +184 -0
  393. package/src/styles/components/tabs.css +1 -2
  394. package/src/styles/components/textarea.css +4 -5
  395. package/src/styles/components/theme-toggle.css +3 -66
  396. package/src/styles/components/unit-input.css +3 -3
  397. package/src/styles/index.css +0 -1
  398. package/src/templates/adapters.ts +785 -0
  399. package/src/templates/builders.ts +2149 -0
  400. package/src/templates/catalog.ts +245 -0
  401. package/src/templates/componentBindings.ts +615 -0
  402. package/src/templates/controlSchemas.ts +718 -0
  403. package/src/templates/index.ts +314 -0
  404. package/src/templates/lookup.ts +18 -0
  405. package/src/templates/packs.ts +156 -0
  406. package/src/templates/presets.ts +146 -0
  407. package/src/templates/types.ts +668 -0
  408. package/src/types/components.ts +80 -1
  409. package/src/types/form-builder.ts +7 -2
  410. package/src/types/index.ts +17 -0
  411. package/src/types/platform.ts +8 -1
  412. package/src/utils/formModelSync.ts +52 -0
  413. package/src/utils/items.ts +28 -0
  414. package/src/utils/options.ts +23 -0
  415. package/src/utils/pluginIcon.ts +30 -0
  416. package/dist/auth-DsI0rQ7_.js.map +0 -1
  417. package/dist/components-CzbQQPCb.js.map +0 -1
  418. package/dist/composables-BXklV5ii.js.map +0 -1
  419. package/dist/useScheduleDrag-CxBeqYcu.js +0 -7181
  420. package/dist/useScheduleDrag-CxBeqYcu.js.map +0 -1
  421. package/src/styles/components/grouping-modal.css +0 -323
@@ -0,0 +1,269 @@
1
+ <script setup lang="ts">
2
+ /** Render biology template envelopes with matching SDK components such as WellPlate, DoseCalculator, and DataFrame. */
3
+ import { computed, type Component } from 'vue'
4
+ import {
5
+ toBioTemplateComponentProps,
6
+ type BioTemplateComponentPropsBinding,
7
+ } from '../templates/componentBindings'
8
+ import type {
9
+ BioTemplateEnvelope,
10
+ TemplateCollectionEnvelope,
11
+ } from '../templates/types'
12
+ import DataFrame from './DataFrame.vue'
13
+ import DoseCalculator from './DoseCalculator.vue'
14
+ import ExperimentTimeline from './ExperimentTimeline.vue'
15
+ import PlateMapEditor from './PlateMapEditor.vue'
16
+ import ReagentList from './ReagentList.vue'
17
+ import SampleSelector from './SampleSelector.vue'
18
+ import WellPlate from './WellPlate.vue'
19
+
20
+ interface Props {
21
+ /** Template envelope or template collection to render. */
22
+ target: BioTemplateEnvelope<unknown> | TemplateCollectionEnvelope
23
+ /** Optional allow-list of component names, for example ['WellPlate', 'DataFrame']. */
24
+ include?: string[]
25
+ /** Optional deny-list of component names. */
26
+ exclude?: string[]
27
+ /** Compact child component sizing. */
28
+ dense?: boolean
29
+ /** Prefer preview-safe props for editable components. */
30
+ readonly?: boolean
31
+ /** Show component/template labels above each rendered component. */
32
+ showHeaders?: boolean
33
+ /** Show binding descriptions in each header. */
34
+ showDescriptions?: boolean
35
+ /** Message shown when the target has no renderable bindings. */
36
+ emptyText?: string
37
+ }
38
+
39
+ type RenderableBinding = BioTemplateComponentPropsBinding & {
40
+ componentImpl: Component
41
+ normalizedProps: Record<string, unknown>
42
+ }
43
+
44
+ const props = withDefaults(defineProps<Props>(), {
45
+ include: () => [],
46
+ exclude: () => [],
47
+ dense: false,
48
+ readonly: true,
49
+ showHeaders: true,
50
+ showDescriptions: true,
51
+ emptyText: 'No renderable biology template components.',
52
+ })
53
+
54
+ const componentRegistry: Record<string, Component> = {
55
+ DataFrame,
56
+ DoseCalculator,
57
+ ExperimentTimeline,
58
+ PlateMapEditor,
59
+ ReagentList,
60
+ SampleSelector,
61
+ WellPlate,
62
+ }
63
+
64
+ const renderableBindings = computed<RenderableBinding[]>(() =>
65
+ toBioTemplateComponentProps(props.target)
66
+ .filter(binding => isIncluded(binding.component))
67
+ .map((binding) => {
68
+ const componentImpl = componentRegistry[binding.component]
69
+ if (!componentImpl) return null
70
+ return {
71
+ ...binding,
72
+ componentImpl,
73
+ normalizedProps: normalizeProps(binding),
74
+ }
75
+ })
76
+ .filter((binding): binding is RenderableBinding => binding !== null)
77
+ )
78
+
79
+ const rendererClasses = computed(() => [
80
+ 'mint-bio-template-renderer',
81
+ props.dense ? 'mint-bio-template-renderer--dense' : '',
82
+ ])
83
+
84
+ function isIncluded(componentName: string): boolean {
85
+ if (props.include.length > 0 && !props.include.includes(componentName)) return false
86
+ return !props.exclude.includes(componentName)
87
+ }
88
+
89
+ function normalizeProps(binding: BioTemplateComponentPropsBinding): Record<string, unknown> {
90
+ const base = { ...binding.propsObject }
91
+
92
+ switch (binding.component) {
93
+ case 'WellPlate':
94
+ return {
95
+ ...base,
96
+ readonly: props.readonly || Boolean(base.readonly),
97
+ size: props.dense ? 'md' : (base.size ?? 'fill'),
98
+ }
99
+ case 'PlateMapEditor':
100
+ return {
101
+ ...base,
102
+ size: props.dense ? 'md' : (base.size ?? 'fill'),
103
+ showToolbar: props.readonly ? false : (base.showToolbar ?? true),
104
+ showSidebar: props.readonly ? false : (base.showSidebar ?? true),
105
+ allowAddPlates: props.readonly ? false : (base.allowAddPlates ?? true),
106
+ allowAddSamples: props.readonly ? false : (base.allowAddSamples ?? true),
107
+ }
108
+ case 'DataFrame':
109
+ return {
110
+ ...base,
111
+ size: props.dense ? 'sm' : (base.size ?? 'md'),
112
+ maxHeight: base.maxHeight ?? (props.dense ? '280px' : undefined),
113
+ }
114
+ case 'ExperimentTimeline':
115
+ return {
116
+ ...base,
117
+ editable: props.readonly ? false : base.editable,
118
+ size: props.dense ? 'sm' : (base.size ?? 'md'),
119
+ }
120
+ case 'ReagentList':
121
+ return {
122
+ ...base,
123
+ readonly: props.readonly || Boolean(base.readonly),
124
+ }
125
+ case 'SampleSelector':
126
+ return {
127
+ ...base,
128
+ enableGrouping: props.readonly ? false : (base.enableGrouping ?? true),
129
+ enableSmartGroup: props.readonly ? false : (base.enableSmartGroup ?? true),
130
+ }
131
+ default:
132
+ return base
133
+ }
134
+ }
135
+ </script>
136
+
137
+ <template>
138
+ <div :class="rendererClasses">
139
+ <section
140
+ v-for="binding in renderableBindings"
141
+ :key="binding.id"
142
+ class="mint-bio-template-renderer__item"
143
+ :data-template-id="binding.template_id"
144
+ :data-template-component="binding.component"
145
+ >
146
+ <header
147
+ v-if="showHeaders"
148
+ class="mint-bio-template-renderer__header"
149
+ >
150
+ <div class="mint-bio-template-renderer__title-group">
151
+ <p class="mint-bio-template-renderer__component">
152
+ {{ binding.component }}
153
+ </p>
154
+ <p class="mint-bio-template-renderer__template">
155
+ {{ binding.template_id }}
156
+ </p>
157
+ </div>
158
+ <p
159
+ v-if="showDescriptions"
160
+ class="mint-bio-template-renderer__description"
161
+ >
162
+ {{ binding.description }}
163
+ </p>
164
+ </header>
165
+
166
+ <div class="mint-bio-template-renderer__body">
167
+ <component
168
+ :is="binding.componentImpl"
169
+ v-bind="binding.normalizedProps"
170
+ />
171
+ </div>
172
+ </section>
173
+
174
+ <p
175
+ v-if="renderableBindings.length === 0"
176
+ class="mint-bio-template-renderer__empty"
177
+ >
178
+ {{ emptyText }}
179
+ </p>
180
+ </div>
181
+ </template>
182
+
183
+ <style scoped>
184
+ .mint-bio-template-renderer {
185
+ display: grid;
186
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, 28rem), 1fr));
187
+ gap: 1rem;
188
+ min-width: 0;
189
+ }
190
+
191
+ .mint-bio-template-renderer--dense {
192
+ gap: 0.75rem;
193
+ }
194
+
195
+ .mint-bio-template-renderer__item {
196
+ min-width: 0;
197
+ overflow: hidden;
198
+ border: 1px solid var(--border-color, #e5e7eb);
199
+ border-radius: 0.5rem;
200
+ background: var(--bg-card, #ffffff);
201
+ box-shadow: var(--shadow-sm, 0 1px 2px rgb(15 23 42 / 0.06));
202
+ }
203
+
204
+ .mint-bio-template-renderer__header {
205
+ display: flex;
206
+ align-items: flex-start;
207
+ justify-content: space-between;
208
+ gap: 1rem;
209
+ padding: 0.75rem 1rem;
210
+ border-bottom: 1px solid var(--border-color, #e5e7eb);
211
+ background: var(--bg-secondary, #f8fafc);
212
+ }
213
+
214
+ .mint-bio-template-renderer__title-group {
215
+ min-width: 0;
216
+ }
217
+
218
+ .mint-bio-template-renderer__component {
219
+ margin: 0;
220
+ color: var(--text-primary, #0f172a);
221
+ font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace);
222
+ font-size: 0.8125rem;
223
+ font-weight: 600;
224
+ }
225
+
226
+ .mint-bio-template-renderer__template,
227
+ .mint-bio-template-renderer__description,
228
+ .mint-bio-template-renderer__empty {
229
+ margin: 0;
230
+ color: var(--text-secondary, #475569);
231
+ font-size: 0.75rem;
232
+ line-height: 1.4;
233
+ }
234
+
235
+ .mint-bio-template-renderer__description {
236
+ max-width: 24rem;
237
+ text-align: right;
238
+ }
239
+
240
+ .mint-bio-template-renderer__body {
241
+ min-width: 0;
242
+ padding: 1rem;
243
+ }
244
+
245
+ .mint-bio-template-renderer--dense .mint-bio-template-renderer__header,
246
+ .mint-bio-template-renderer--dense .mint-bio-template-renderer__body {
247
+ padding: 0.75rem;
248
+ }
249
+
250
+ .mint-bio-template-renderer__empty {
251
+ padding: 1rem;
252
+ border: 1px dashed var(--border-color, #e5e7eb);
253
+ border-radius: 0.5rem;
254
+ background: var(--bg-secondary, #f8fafc);
255
+ text-align: center;
256
+ }
257
+
258
+ @media (max-width: 720px) {
259
+ .mint-bio-template-renderer__header {
260
+ display: block;
261
+ }
262
+
263
+ .mint-bio-template-renderer__description {
264
+ max-width: none;
265
+ margin-top: 0.25rem;
266
+ text-align: left;
267
+ }
268
+ }
269
+ </style>
@@ -1,13 +1,15 @@
1
1
  <script setup lang="ts">
2
2
  /** Renders a breadcrumb trail where ancestors are links or emit-based buttons and the last item is the current page. */
3
- import type { BreadcrumbItem } from '../types'
3
+ import { computed } from 'vue'
4
+ import type { BreadcrumbItem, BreadcrumbItemInput } from '../types'
5
+ import { normalizeLabelItemInput } from '../utils/items'
4
6
 
5
7
  interface Props {
6
- items: BreadcrumbItem[]
8
+ items: BreadcrumbItemInput[]
7
9
  separator?: string
8
10
  }
9
11
 
10
- withDefaults(defineProps<Props>(), {
12
+ const props = withDefaults(defineProps<Props>(), {
11
13
  separator: '/',
12
14
  })
13
15
 
@@ -15,6 +17,10 @@ const emit = defineEmits<{
15
17
  navigate: [item: BreadcrumbItem]
16
18
  }>()
17
19
 
20
+ const normalizedItems = computed<BreadcrumbItem[]>(() =>
21
+ props.items.map(normalizeLabelItemInput)
22
+ )
23
+
18
24
  function handleClick(item: BreadcrumbItem) {
19
25
  if (!item.href) {
20
26
  emit('navigate', item)
@@ -26,20 +32,20 @@ function handleClick(item: BreadcrumbItem) {
26
32
  <nav class="mint-breadcrumb" aria-label="Breadcrumb">
27
33
  <ol class="mint-breadcrumb__list">
28
34
  <li
29
- v-for="(item, index) in items"
35
+ v-for="(item, index) in normalizedItems"
30
36
  :key="index"
31
37
  class="mint-breadcrumb__item"
32
38
  >
33
- <slot name="item" :item="item" :index="index" :is-last="index === items.length - 1">
39
+ <slot name="item" :item="item" :index="index" :is-last="index === normalizedItems.length - 1">
34
40
  <a
35
- v-if="item.href && index !== items.length - 1"
41
+ v-if="item.href && index !== normalizedItems.length - 1"
36
42
  :href="item.href"
37
43
  class="mint-breadcrumb__link"
38
44
  >
39
45
  {{ item.label }}
40
46
  </a>
41
47
  <button
42
- v-else-if="index !== items.length - 1"
48
+ v-else-if="index !== normalizedItems.length - 1"
43
49
  class="mint-breadcrumb__link"
44
50
  @click="handleClick(item)"
45
51
  >
@@ -54,7 +60,7 @@ function handleClick(item: BreadcrumbItem) {
54
60
  </span>
55
61
  </slot>
56
62
  <span
57
- v-if="index !== items.length - 1"
63
+ v-if="index !== normalizedItems.length - 1"
58
64
  class="mint-breadcrumb__separator"
59
65
  aria-hidden="true"
60
66
  >
@@ -0,0 +1,120 @@
1
+ <script setup lang="ts">
2
+ /** Shared calendar grid panel used by date-oriented picker components. */
3
+ import type { CalendarGridDay } from '../composables/useCalendarGrid'
4
+
5
+ interface Props {
6
+ weekDays: readonly string[]
7
+ monthYear: string
8
+ days: CalendarGridDay[]
9
+ selectedDate?: Date | null
10
+ locale?: string
11
+ previousLabel?: string
12
+ nextLabel?: string
13
+ }
14
+
15
+ const props = withDefaults(defineProps<Props>(), {
16
+ selectedDate: null,
17
+ locale: 'en-US',
18
+ previousLabel: 'Previous month',
19
+ nextLabel: 'Next month',
20
+ })
21
+
22
+ const emit = defineEmits<{
23
+ 'previous-month': []
24
+ 'next-month': []
25
+ select: [day: CalendarGridDay]
26
+ }>()
27
+
28
+ function isSameDay(date: Date, other: Date | null | undefined): boolean {
29
+ if (!other) return false
30
+ return date.toDateString() === other.toDateString()
31
+ }
32
+
33
+ function isToday(date: Date): boolean {
34
+ return isSameDay(date, new Date())
35
+ }
36
+
37
+ function dayAriaLabel(date: Date): string {
38
+ return date.toLocaleDateString(props.locale, {
39
+ weekday: 'long',
40
+ year: 'numeric',
41
+ month: 'long',
42
+ day: 'numeric',
43
+ })
44
+ }
45
+ </script>
46
+
47
+ <template>
48
+ <div class="mint-calendar-grid-panel">
49
+ <div class="mint-date-picker__header">
50
+ <button
51
+ type="button"
52
+ class="mint-date-picker__nav-btn"
53
+ :aria-label="previousLabel"
54
+ @click="emit('previous-month')"
55
+ >
56
+ <svg
57
+ viewBox="0 0 24 24"
58
+ fill="none"
59
+ stroke="currentColor"
60
+ stroke-width="2"
61
+ stroke-linecap="round"
62
+ stroke-linejoin="round"
63
+ aria-hidden="true"
64
+ >
65
+ <path d="m15 18-6-6 6-6" />
66
+ </svg>
67
+ </button>
68
+ <span class="mint-date-picker__month-year">{{ monthYear }}</span>
69
+ <button
70
+ type="button"
71
+ class="mint-date-picker__nav-btn"
72
+ :aria-label="nextLabel"
73
+ @click="emit('next-month')"
74
+ >
75
+ <svg
76
+ viewBox="0 0 24 24"
77
+ fill="none"
78
+ stroke="currentColor"
79
+ stroke-width="2"
80
+ stroke-linecap="round"
81
+ stroke-linejoin="round"
82
+ aria-hidden="true"
83
+ >
84
+ <path d="m9 18 6-6-6-6" />
85
+ </svg>
86
+ </button>
87
+ </div>
88
+
89
+ <div class="mint-date-picker__weekdays">
90
+ <div
91
+ v-for="day in weekDays"
92
+ :key="day"
93
+ class="mint-date-picker__weekday"
94
+ >
95
+ {{ day }}
96
+ </div>
97
+ </div>
98
+
99
+ <div class="mint-date-picker__grid">
100
+ <button
101
+ v-for="(day, index) in days"
102
+ :key="index"
103
+ type="button"
104
+ :disabled="day.isDisabled"
105
+ :aria-label="dayAriaLabel(day.date)"
106
+ :aria-selected="isSameDay(day.date, selectedDate)"
107
+ :class="[
108
+ 'mint-date-picker__day',
109
+ !day.isCurrentMonth ? 'mint-date-picker__day--other-month' : '',
110
+ day.isDisabled ? 'mint-date-picker__day--disabled' : '',
111
+ isSameDay(day.date, selectedDate) ? 'mint-date-picker__day--selected' : '',
112
+ isToday(day.date) && !isSameDay(day.date, selectedDate) ? 'mint-date-picker__day--today' : '',
113
+ ]"
114
+ @click="emit('select', day)"
115
+ >
116
+ {{ day.date.getDate() }}
117
+ </button>
118
+ </div>
119
+ </div>
120
+ </template>
@@ -6,6 +6,7 @@ import {
6
6
  type ConcentrationValue,
7
7
  type ConcentrationUnit,
8
8
  } from '../composables/useConcentrationUnits'
9
+ import UnitInput from './UnitInput.vue'
9
10
 
10
11
  interface Props {
11
12
  modelValue?: ConcentrationValue
@@ -52,6 +53,16 @@ const availableUnits = computed(() => {
52
53
  return filteredCategories.value.flatMap(cat => cat.units)
53
54
  })
54
55
 
56
+ const unitOptions = computed(() =>
57
+ filteredCategories.value.flatMap(category =>
58
+ category.units.map(unit => ({
59
+ value: unit,
60
+ label: unit,
61
+ group: filteredCategories.value.length > 1 ? category.label : undefined,
62
+ }))
63
+ )
64
+ )
65
+
55
66
  // Current value and unit
56
67
  const currentValue = computed(() => props.modelValue?.value)
57
68
  const currentUnit = computed(() => props.modelValue?.unit || availableUnits.value[0] || 'µM')
@@ -62,10 +73,7 @@ const conversionHint = computed(() => {
62
73
  return getConversionHint(props.modelValue)
63
74
  })
64
75
 
65
- function handleValueInput(event: Event) {
66
- const target = event.target as HTMLInputElement
67
- const value = target.value === '' ? undefined : Number(target.value)
68
-
76
+ function handleValueUpdate(value: number | undefined) {
69
77
  if (value === undefined || isNaN(value)) {
70
78
  emit('update:modelValue', undefined)
71
79
  return
@@ -86,13 +94,10 @@ function handleValueInput(event: Event) {
86
94
  })
87
95
  }
88
96
 
89
- function handleUnitChange(event: Event) {
90
- const target = event.target as HTMLSelectElement
91
- const unit = target.value as ConcentrationUnit
92
-
97
+ function handleUnitUpdate(unit: string) {
93
98
  emit('update:modelValue', {
94
99
  value: currentValue.value ?? 0,
95
- unit,
100
+ unit: unit as ConcentrationUnit,
96
101
  })
97
102
  }
98
103
 
@@ -115,61 +120,19 @@ watch(availableUnits, (units) => {
115
120
  disabled ? 'mint-concentration-input--disabled' : '',
116
121
  ]"
117
122
  >
118
- <div :class="['mint-concentration-input__controls', `mint-concentration-input__controls--${size}`]">
119
- <input
120
- type="number"
121
- :value="currentValue"
122
- :min="min"
123
- :max="max"
124
- :disabled="disabled"
125
- :placeholder="placeholder"
126
- :class="[
127
- 'mint-concentration-input__value',
128
- `mint-concentration-input__value--${size}`,
129
- disabled ? 'mint-concentration-input__value--disabled' : '',
130
- ]"
131
- aria-label="Concentration value"
132
- @input="handleValueInput"
133
- />
134
-
135
- <div class="mint-concentration-input__unit">
136
- <select
137
- :value="currentUnit"
138
- :disabled="disabled"
139
- :class="[
140
- 'mint-concentration-input__unit-select',
141
- `mint-concentration-input__unit-select--${size}`,
142
- ]"
143
- aria-label="Concentration unit"
144
- @change="handleUnitChange"
145
- >
146
- <template v-for="category in filteredCategories" :key="category.label">
147
- <optgroup
148
- v-if="filteredCategories.length > 1"
149
- :label="category.label"
150
- class="mint-concentration-input__unit-group"
151
- >
152
- <option
153
- v-for="unit in category.units"
154
- :key="unit"
155
- :value="unit"
156
- >
157
- {{ unit }}
158
- </option>
159
- </optgroup>
160
- <template v-else>
161
- <option
162
- v-for="unit in category.units"
163
- :key="unit"
164
- :value="unit"
165
- >
166
- {{ unit }}
167
- </option>
168
- </template>
169
- </template>
170
- </select>
171
- </div>
172
- </div>
123
+ <UnitInput
124
+ :model-value="currentValue"
125
+ :unit="currentUnit"
126
+ :units="unitOptions"
127
+ :min="min"
128
+ :max="max"
129
+ :disabled="disabled"
130
+ :error="error"
131
+ :size="size"
132
+ :placeholder="placeholder"
133
+ @update:model-value="handleValueUpdate"
134
+ @update:unit="handleUnitUpdate"
135
+ />
173
136
 
174
137
  <div
175
138
  v-if="showConversion && conversionHint"