@morscherlab/mint-sdk 1.0.0-alpha.2

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 (491) hide show
  1. package/README.md +326 -0
  2. package/dist/__stories__/experiment-helpers.d.ts +25 -0
  3. package/dist/__tests__/components/AppLayout.test.d.ts +1 -0
  4. package/dist/__tests__/components/AppSidebar.test.d.ts +1 -0
  5. package/dist/__tests__/components/AppTopBar.test.d.ts +1 -0
  6. package/dist/__tests__/components/BaseInput.test.d.ts +1 -0
  7. package/dist/__tests__/components/BasePill.test.d.ts +1 -0
  8. package/dist/__tests__/components/Calendar.test.d.ts +1 -0
  9. package/dist/__tests__/components/CollapsibleCard.test.d.ts +1 -0
  10. package/dist/__tests__/components/DataFrame.test.d.ts +1 -0
  11. package/dist/__tests__/components/DropdownButton.test.d.ts +1 -0
  12. package/dist/__tests__/composables/formBuilderRegistry.test.d.ts +1 -0
  13. package/dist/__tests__/composables/useAppExperiment.test.d.ts +1 -0
  14. package/dist/__tests__/composables/useAuth.test.d.ts +1 -0
  15. package/dist/__tests__/composables/useAutoGroup.test.d.ts +1 -0
  16. package/dist/__tests__/composables/useExperimentData.test.d.ts +13 -0
  17. package/dist/__tests__/composables/useExperimentSave.test.d.ts +1 -0
  18. package/dist/__tests__/composables/useForm.test.d.ts +1 -0
  19. package/dist/__tests__/composables/useFormBuilder.test.d.ts +1 -0
  20. package/dist/__tests__/composables/usePlatformContext.test.d.ts +1 -0
  21. package/dist/__tests__/composables/usePluginApi.test.d.ts +13 -0
  22. package/dist/__tests__/composables/usePluginConfig.test.d.ts +14 -0
  23. package/dist/__tests__/utils/color.test.d.ts +1 -0
  24. package/dist/auth-BYmxZdJl.js +297 -0
  25. package/dist/auth-BYmxZdJl.js.map +1 -0
  26. package/dist/components/AlertBox.vue.d.ts +34 -0
  27. package/dist/components/AppAvatarMenu.vue.d.ts +58 -0
  28. package/dist/components/AppContainer.vue.d.ts +28 -0
  29. package/dist/components/AppLayout.vue.d.ts +31 -0
  30. package/dist/components/AppPageSelector.vue.d.ts +43 -0
  31. package/dist/components/AppPillNav.vue.d.ts +11 -0
  32. package/dist/components/AppPluginSwitcher.vue.d.ts +38 -0
  33. package/dist/components/AppSidebar.vue.d.ts +47 -0
  34. package/dist/components/AppTopBar.vue.d.ts +111 -0
  35. package/dist/components/AuditTrail.vue.d.ts +38 -0
  36. package/dist/components/AutoGroupModal.vue.d.ts +124 -0
  37. package/dist/components/Avatar.vue.d.ts +14 -0
  38. package/dist/components/BaseButton.vue.d.ts +37 -0
  39. package/dist/components/BaseCheckbox.vue.d.ts +17 -0
  40. package/dist/components/BaseInput.vue.d.ts +34 -0
  41. package/dist/components/BaseModal.vue.d.ts +46 -0
  42. package/dist/components/BasePill.vue.d.ts +57 -0
  43. package/dist/components/BaseRadioGroup.vue.d.ts +21 -0
  44. package/dist/components/BaseSelect.vue.d.ts +20 -0
  45. package/dist/components/BaseSlider.vue.d.ts +22 -0
  46. package/dist/components/BaseTabs.vue.d.ts +14 -0
  47. package/dist/components/BaseTextarea.vue.d.ts +30 -0
  48. package/dist/components/BaseToggle.vue.d.ts +19 -0
  49. package/dist/components/BatchProgressList.vue.d.ts +43 -0
  50. package/dist/components/Breadcrumb.vue.d.ts +33 -0
  51. package/dist/components/Calendar.vue.d.ts +107 -0
  52. package/dist/components/ChartContainer.vue.d.ts +31 -0
  53. package/dist/components/ChemicalFormula.vue.d.ts +8 -0
  54. package/dist/components/CollapsibleCard.vue.d.ts +41 -0
  55. package/dist/components/ColorSlider.vue.d.ts +34 -0
  56. package/dist/components/ConcentrationInput.vue.d.ts +25 -0
  57. package/dist/components/ConfirmDialog.vue.d.ts +42 -0
  58. package/dist/components/DataFrame.vue.d.ts +107 -0
  59. package/dist/components/DatePicker.vue.d.ts +25 -0
  60. package/dist/components/DateTimePicker.vue.d.ts +30 -0
  61. package/dist/components/Divider.vue.d.ts +14 -0
  62. package/dist/components/DoseCalculator.vue.d.ts +19 -0
  63. package/dist/components/DropdownButton.vue.d.ts +47 -0
  64. package/dist/components/EmptyState.vue.d.ts +36 -0
  65. package/dist/components/ExperimentCodeBadge.vue.d.ts +14 -0
  66. package/dist/components/ExperimentDataViewer.vue.d.ts +29 -0
  67. package/dist/components/ExperimentPopover.vue.d.ts +32 -0
  68. package/dist/components/ExperimentSelectorModal.vue.d.ts +28 -0
  69. package/dist/components/ExperimentTimeline.vue.d.ts +44 -0
  70. package/dist/components/FileUploader.vue.d.ts +40 -0
  71. package/dist/components/FitPanel.vue.d.ts +46 -0
  72. package/dist/components/FormActions.vue.d.ts +33 -0
  73. package/dist/components/FormBuilder.vue.d.ts +287 -0
  74. package/dist/components/FormField.vue.d.ts +28 -0
  75. package/dist/components/FormFieldRenderer.vue.d.ts +31 -0
  76. package/dist/components/FormSection.vue.d.ts +43 -0
  77. package/dist/components/FormulaInput.vue.d.ts +25 -0
  78. package/dist/components/GroupAssigner.vue.d.ts +25 -0
  79. package/dist/components/GroupingModal.vue.d.ts +12 -0
  80. package/dist/components/IconButton.vue.d.ts +34 -0
  81. package/dist/components/LoadingSpinner.vue.d.ts +12 -0
  82. package/dist/components/MoleculeInput.vue.d.ts +27 -0
  83. package/dist/components/MultiSelect.vue.d.ts +19 -0
  84. package/dist/components/NumberInput.vue.d.ts +22 -0
  85. package/dist/components/PlateMapEditor.vue.d.ts +50 -0
  86. package/dist/components/ProgressBar.vue.d.ts +23 -0
  87. package/dist/components/ProtocolStepEditor.vue.d.ts +24 -0
  88. package/dist/components/RackEditor.vue.d.ts +40 -0
  89. package/dist/components/ReagentEditor.vue.d.ts +30 -0
  90. package/dist/components/ReagentList.vue.d.ts +32 -0
  91. package/dist/components/ResourceCard.vue.d.ts +50 -0
  92. package/dist/components/SampleHierarchyTree.vue.d.ts +26 -0
  93. package/dist/components/SampleLegend.vue.d.ts +32 -0
  94. package/dist/components/SampleSelector.vue.d.ts +29 -0
  95. package/dist/components/ScheduleCalendar.vue.d.ts +110 -0
  96. package/dist/components/ScientificNumber.vue.d.ts +14 -0
  97. package/dist/components/SegmentedControl.vue.d.ts +20 -0
  98. package/dist/components/SequenceInput.vue.d.ts +54 -0
  99. package/dist/components/SettingsButton.vue.d.ts +30 -0
  100. package/dist/components/SettingsModal.vue.d.ts +36 -0
  101. package/dist/components/Skeleton.vue.d.ts +11 -0
  102. package/dist/components/StatusIndicator.vue.d.ts +13 -0
  103. package/dist/components/StepWizard.vue.d.ts +65 -0
  104. package/dist/components/TagsInput.vue.d.ts +39 -0
  105. package/dist/components/ThemeToggle.vue.d.ts +7 -0
  106. package/dist/components/TimePicker.vue.d.ts +29 -0
  107. package/dist/components/TimeRangeInput.vue.d.ts +27 -0
  108. package/dist/components/ToastNotification.vue.d.ts +2 -0
  109. package/dist/components/Tooltip.vue.d.ts +35 -0
  110. package/dist/components/UnitInput.vue.d.ts +39 -0
  111. package/dist/components/WellEditPopup.vue.d.ts +25 -0
  112. package/dist/components/WellPlate.vue.d.ts +73 -0
  113. package/dist/components/index.d.ts +87 -0
  114. package/dist/components/index.js +3 -0
  115. package/dist/components-CKf-UpGi.js +15089 -0
  116. package/dist/components-CKf-UpGi.js.map +1 -0
  117. package/dist/composables/experiment-utils.d.ts +8 -0
  118. package/dist/composables/formBuilderRegistry.d.ts +13 -0
  119. package/dist/composables/index.d.ts +28 -0
  120. package/dist/composables/index.js +3 -0
  121. package/dist/composables/useApi.d.ts +20 -0
  122. package/dist/composables/useAppExperiment.d.ts +37 -0
  123. package/dist/composables/useAsync.d.ts +128 -0
  124. package/dist/composables/useAuth.d.ts +47 -0
  125. package/dist/composables/useAutoGroup.d.ts +106 -0
  126. package/dist/composables/useChemicalFormula.d.ts +21 -0
  127. package/dist/composables/useConcentrationUnits.d.ts +29 -0
  128. package/dist/composables/useDoseCalculator.d.ts +58 -0
  129. package/dist/composables/useExperimentData.d.ts +18 -0
  130. package/dist/composables/useExperimentSave.d.ts +36 -0
  131. package/dist/composables/useExperimentSelector.d.ts +30 -0
  132. package/dist/composables/useForm.d.ts +92 -0
  133. package/dist/composables/useFormBuilder.d.ts +24 -0
  134. package/dist/composables/usePasskey.d.ts +10 -0
  135. package/dist/composables/usePlatformContext.d.ts +131 -0
  136. package/dist/composables/usePluginApi.d.ts +29 -0
  137. package/dist/composables/usePluginConfig.d.ts +13 -0
  138. package/dist/composables/useProtocolTemplates.d.ts +44 -0
  139. package/dist/composables/useRackEditor.d.ts +31 -0
  140. package/dist/composables/useReagentSeries.d.ts +23 -0
  141. package/dist/composables/useScheduleDrag.d.ts +78 -0
  142. package/dist/composables/useSequenceUtils.d.ts +14 -0
  143. package/dist/composables/useTheme.d.ts +8 -0
  144. package/dist/composables/useTimeUtils.d.ts +29 -0
  145. package/dist/composables/useToast.d.ts +22 -0
  146. package/dist/composables/useWellPlateEditor.d.ts +33 -0
  147. package/dist/composables-D0QfFzq1.js +805 -0
  148. package/dist/composables-D0QfFzq1.js.map +1 -0
  149. package/dist/histoire.setup.d.ts +1 -0
  150. package/dist/index.d.ts +6 -0
  151. package/dist/index.js +7 -0
  152. package/dist/install.d.ts +16 -0
  153. package/dist/install.js +23 -0
  154. package/dist/install.js.map +1 -0
  155. package/dist/stores/auth.d.ts +146 -0
  156. package/dist/stores/index.d.ts +2 -0
  157. package/dist/stores/index.js +2 -0
  158. package/dist/stores/settings.d.ts +75 -0
  159. package/dist/styles.css +29728 -0
  160. package/dist/tailwind.preset.d.ts +58 -0
  161. package/dist/tailwind.preset.js +66 -0
  162. package/dist/tailwind.preset.js.map +1 -0
  163. package/dist/types/auth.d.ts +42 -0
  164. package/dist/types/auto-group.d.ts +34 -0
  165. package/dist/types/components.d.ts +528 -0
  166. package/dist/types/form-builder.d.ts +167 -0
  167. package/dist/types/index.d.ts +5 -0
  168. package/dist/types/index.js +0 -0
  169. package/dist/types/platform.d.ts +75 -0
  170. package/dist/useScheduleDrag-DAJueTbK.js +7181 -0
  171. package/dist/useScheduleDrag-DAJueTbK.js.map +1 -0
  172. package/dist/utils/color.d.ts +24 -0
  173. package/package.json +114 -0
  174. package/src/__stories__/experiment-helpers.ts +83 -0
  175. package/src/__tests__/components/AppLayout.test.ts +163 -0
  176. package/src/__tests__/components/AppSidebar.test.ts +292 -0
  177. package/src/__tests__/components/AppTopBar.test.ts +683 -0
  178. package/src/__tests__/components/BaseInput.test.ts +99 -0
  179. package/src/__tests__/components/BasePill.test.ts +291 -0
  180. package/src/__tests__/components/Calendar.test.ts +566 -0
  181. package/src/__tests__/components/CollapsibleCard.test.ts +524 -0
  182. package/src/__tests__/components/DataFrame.test.ts +767 -0
  183. package/src/__tests__/components/DropdownButton.test.ts +471 -0
  184. package/src/__tests__/composables/formBuilderRegistry.test.ts +187 -0
  185. package/src/__tests__/composables/useAppExperiment.test.ts +560 -0
  186. package/src/__tests__/composables/useAuth.test.ts +188 -0
  187. package/src/__tests__/composables/useAutoGroup.test.ts +860 -0
  188. package/src/__tests__/composables/useExperimentData.test.ts +127 -0
  189. package/src/__tests__/composables/useExperimentSave.test.ts +347 -0
  190. package/src/__tests__/composables/useForm.test.ts +205 -0
  191. package/src/__tests__/composables/useFormBuilder.test.ts +917 -0
  192. package/src/__tests__/composables/usePlatformContext.test.ts +116 -0
  193. package/src/__tests__/composables/usePluginApi.test.ts +81 -0
  194. package/src/__tests__/composables/usePluginConfig.test.ts +176 -0
  195. package/src/__tests__/utils/color.test.ts +96 -0
  196. package/src/components/AlertBox.story.vue +204 -0
  197. package/src/components/AlertBox.vue +88 -0
  198. package/src/components/AppAvatarMenu.story.vue +155 -0
  199. package/src/components/AppAvatarMenu.vue +184 -0
  200. package/src/components/AppContainer.story.vue +104 -0
  201. package/src/components/AppContainer.vue +34 -0
  202. package/src/components/AppLayout.story.vue +292 -0
  203. package/src/components/AppLayout.vue +75 -0
  204. package/src/components/AppPageSelector.vue +159 -0
  205. package/src/components/AppPillNav.vue +66 -0
  206. package/src/components/AppPluginSwitcher.vue +241 -0
  207. package/src/components/AppSidebar.story.vue +309 -0
  208. package/src/components/AppSidebar.vue +119 -0
  209. package/src/components/AppTopBar.story.vue +304 -0
  210. package/src/components/AppTopBar.vue +661 -0
  211. package/src/components/AuditTrail.story.vue +163 -0
  212. package/src/components/AuditTrail.vue +151 -0
  213. package/src/components/AutoGroupModal.story.vue +273 -0
  214. package/src/components/AutoGroupModal.vue +566 -0
  215. package/src/components/Avatar.story.vue +115 -0
  216. package/src/components/Avatar.vue +79 -0
  217. package/src/components/BaseButton.story.vue +96 -0
  218. package/src/components/BaseButton.vue +73 -0
  219. package/src/components/BaseCheckbox.story.vue +73 -0
  220. package/src/components/BaseCheckbox.vue +69 -0
  221. package/src/components/BaseInput.story.vue +98 -0
  222. package/src/components/BaseInput.vue +74 -0
  223. package/src/components/BaseModal.story.vue +237 -0
  224. package/src/components/BaseModal.vue +182 -0
  225. package/src/components/BasePill.story.vue +142 -0
  226. package/src/components/BasePill.vue +89 -0
  227. package/src/components/BaseRadioGroup.story.vue +145 -0
  228. package/src/components/BaseRadioGroup.vue +124 -0
  229. package/src/components/BaseSelect.story.vue +120 -0
  230. package/src/components/BaseSelect.vue +71 -0
  231. package/src/components/BaseSlider.story.vue +122 -0
  232. package/src/components/BaseSlider.vue +126 -0
  233. package/src/components/BaseTabs.story.vue +127 -0
  234. package/src/components/BaseTabs.vue +59 -0
  235. package/src/components/BaseTextarea.story.vue +91 -0
  236. package/src/components/BaseTextarea.vue +62 -0
  237. package/src/components/BaseToggle.story.vue +81 -0
  238. package/src/components/BaseToggle.vue +76 -0
  239. package/src/components/BatchProgressList.story.vue +92 -0
  240. package/src/components/BatchProgressList.vue +184 -0
  241. package/src/components/Breadcrumb.story.vue +106 -0
  242. package/src/components/Breadcrumb.vue +75 -0
  243. package/src/components/Calendar.story.vue +106 -0
  244. package/src/components/Calendar.vue +363 -0
  245. package/src/components/ChartContainer.story.vue +113 -0
  246. package/src/components/ChartContainer.vue +64 -0
  247. package/src/components/ChemicalFormula.story.vue +102 -0
  248. package/src/components/ChemicalFormula.vue +39 -0
  249. package/src/components/CollapsibleCard.story.vue +135 -0
  250. package/src/components/CollapsibleCard.vue +167 -0
  251. package/src/components/ColorSlider.story.vue +120 -0
  252. package/src/components/ColorSlider.vue +164 -0
  253. package/src/components/ConcentrationInput.story.vue +77 -0
  254. package/src/components/ConcentrationInput.vue +185 -0
  255. package/src/components/ConfirmDialog.story.vue +248 -0
  256. package/src/components/ConfirmDialog.vue +93 -0
  257. package/src/components/DataFrame.story.vue +148 -0
  258. package/src/components/DataFrame.vue +419 -0
  259. package/src/components/DatePicker.story.vue +119 -0
  260. package/src/components/DatePicker.vue +330 -0
  261. package/src/components/DateTimePicker.story.vue +112 -0
  262. package/src/components/DateTimePicker.vue +392 -0
  263. package/src/components/Divider.story.vue +80 -0
  264. package/src/components/Divider.vue +49 -0
  265. package/src/components/DoseCalculator.story.vue +68 -0
  266. package/src/components/DoseCalculator.vue +476 -0
  267. package/src/components/DropdownButton.story.vue +102 -0
  268. package/src/components/DropdownButton.vue +181 -0
  269. package/src/components/EmptyState.story.vue +135 -0
  270. package/src/components/EmptyState.vue +69 -0
  271. package/src/components/ExperimentCodeBadge.story.vue +77 -0
  272. package/src/components/ExperimentCodeBadge.vue +64 -0
  273. package/src/components/ExperimentDataViewer.story.vue +174 -0
  274. package/src/components/ExperimentDataViewer.vue +288 -0
  275. package/src/components/ExperimentPopover.story.vue +384 -0
  276. package/src/components/ExperimentPopover.vue +241 -0
  277. package/src/components/ExperimentSelectorModal.story.vue +391 -0
  278. package/src/components/ExperimentSelectorModal.vue +387 -0
  279. package/src/components/ExperimentTimeline.story.vue +161 -0
  280. package/src/components/ExperimentTimeline.vue +382 -0
  281. package/src/components/FileUploader.story.vue +107 -0
  282. package/src/components/FileUploader.vue +386 -0
  283. package/src/components/FitPanel.story.vue +125 -0
  284. package/src/components/FitPanel.vue +120 -0
  285. package/src/components/FormActions.vue +92 -0
  286. package/src/components/FormBuilder.vue +214 -0
  287. package/src/components/FormField.story.vue +132 -0
  288. package/src/components/FormField.vue +59 -0
  289. package/src/components/FormFieldRenderer.vue +58 -0
  290. package/src/components/FormSection.vue +90 -0
  291. package/src/components/FormulaInput.story.vue +96 -0
  292. package/src/components/FormulaInput.vue +125 -0
  293. package/src/components/GroupAssigner.story.vue +83 -0
  294. package/src/components/GroupAssigner.vue +284 -0
  295. package/src/components/GroupingModal.story.vue +52 -0
  296. package/src/components/GroupingModal.vue +422 -0
  297. package/src/components/IconButton.story.vue +135 -0
  298. package/src/components/IconButton.vue +73 -0
  299. package/src/components/LoadingSpinner.story.vue +70 -0
  300. package/src/components/LoadingSpinner.vue +50 -0
  301. package/src/components/MoleculeInput.story.vue +66 -0
  302. package/src/components/MoleculeInput.vue +426 -0
  303. package/src/components/MultiSelect.story.vue +132 -0
  304. package/src/components/MultiSelect.vue +118 -0
  305. package/src/components/NumberInput.story.vue +122 -0
  306. package/src/components/NumberInput.vue +160 -0
  307. package/src/components/PlateMapEditor.story.vue +92 -0
  308. package/src/components/PlateMapEditor.vue +513 -0
  309. package/src/components/ProgressBar.story.vue +148 -0
  310. package/src/components/ProgressBar.vue +114 -0
  311. package/src/components/ProtocolStepEditor.story.vue +69 -0
  312. package/src/components/ProtocolStepEditor.vue +522 -0
  313. package/src/components/RackEditor.story.vue +100 -0
  314. package/src/components/RackEditor.vue +371 -0
  315. package/src/components/ReagentEditor.story.vue +153 -0
  316. package/src/components/ReagentEditor.vue +418 -0
  317. package/src/components/ReagentList.story.vue +137 -0
  318. package/src/components/ReagentList.vue +463 -0
  319. package/src/components/ResourceCard.story.vue +150 -0
  320. package/src/components/ResourceCard.vue +161 -0
  321. package/src/components/SampleHierarchyTree.story.vue +161 -0
  322. package/src/components/SampleHierarchyTree.vue +256 -0
  323. package/src/components/SampleLegend.story.vue +91 -0
  324. package/src/components/SampleLegend.vue +119 -0
  325. package/src/components/SampleSelector.story.vue +111 -0
  326. package/src/components/SampleSelector.vue +1033 -0
  327. package/src/components/ScheduleCalendar.story.vue +195 -0
  328. package/src/components/ScheduleCalendar.vue +569 -0
  329. package/src/components/ScientificNumber.story.vue +127 -0
  330. package/src/components/ScientificNumber.vue +197 -0
  331. package/src/components/SegmentedControl.story.vue +132 -0
  332. package/src/components/SegmentedControl.vue +79 -0
  333. package/src/components/SequenceInput.story.vue +119 -0
  334. package/src/components/SequenceInput.vue +209 -0
  335. package/src/components/SettingsButton.story.vue +58 -0
  336. package/src/components/SettingsButton.vue +76 -0
  337. package/src/components/SettingsModal.story.vue +145 -0
  338. package/src/components/SettingsModal.vue +146 -0
  339. package/src/components/Skeleton.story.vue +141 -0
  340. package/src/components/Skeleton.vue +74 -0
  341. package/src/components/StatusIndicator.story.vue +99 -0
  342. package/src/components/StatusIndicator.vue +40 -0
  343. package/src/components/StepWizard.story.vue +155 -0
  344. package/src/components/StepWizard.vue +223 -0
  345. package/src/components/TagsInput.story.vue +155 -0
  346. package/src/components/TagsInput.vue +265 -0
  347. package/src/components/ThemeToggle.story.vue +36 -0
  348. package/src/components/ThemeToggle.vue +54 -0
  349. package/src/components/TimePicker.story.vue +96 -0
  350. package/src/components/TimePicker.vue +273 -0
  351. package/src/components/TimeRangeInput.story.vue +104 -0
  352. package/src/components/TimeRangeInput.vue +122 -0
  353. package/src/components/ToastNotification.story.vue +157 -0
  354. package/src/components/ToastNotification.vue +62 -0
  355. package/src/components/Tooltip.story.vue +138 -0
  356. package/src/components/Tooltip.vue +119 -0
  357. package/src/components/UnitInput.story.vue +194 -0
  358. package/src/components/UnitInput.vue +213 -0
  359. package/src/components/WellEditPopup.vue +234 -0
  360. package/src/components/WellPlate.story.vue +282 -0
  361. package/src/components/WellPlate.vue +830 -0
  362. package/src/components/index.ts +118 -0
  363. package/src/composables/experiment-utils.ts +57 -0
  364. package/src/composables/formBuilderRegistry.ts +79 -0
  365. package/src/composables/index.ts +140 -0
  366. package/src/composables/useApi.ts +167 -0
  367. package/src/composables/useAppExperiment.ts +159 -0
  368. package/src/composables/useAsync.ts +323 -0
  369. package/src/composables/useAuth.ts +445 -0
  370. package/src/composables/useAutoGroup.ts +641 -0
  371. package/src/composables/useChemicalFormula.ts +275 -0
  372. package/src/composables/useConcentrationUnits.ts +246 -0
  373. package/src/composables/useDoseCalculator.ts +370 -0
  374. package/src/composables/useExperimentData.ts +86 -0
  375. package/src/composables/useExperimentSave.ts +192 -0
  376. package/src/composables/useExperimentSelector.ts +292 -0
  377. package/src/composables/useForm.ts +416 -0
  378. package/src/composables/useFormBuilder.ts +383 -0
  379. package/src/composables/usePasskey.ts +216 -0
  380. package/src/composables/usePlatformContext.ts +299 -0
  381. package/src/composables/usePluginApi.ts +39 -0
  382. package/src/composables/usePluginConfig.ts +93 -0
  383. package/src/composables/useProtocolTemplates.ts +518 -0
  384. package/src/composables/useRackEditor.ts +222 -0
  385. package/src/composables/useReagentSeries.ts +91 -0
  386. package/src/composables/useScheduleDrag.ts +245 -0
  387. package/src/composables/useSequenceUtils.ts +105 -0
  388. package/src/composables/useTheme.ts +58 -0
  389. package/src/composables/useTimeUtils.ts +131 -0
  390. package/src/composables/useToast.ts +40 -0
  391. package/src/composables/useWellPlateEditor.ts +421 -0
  392. package/src/histoire.setup.ts +17 -0
  393. package/src/index.ts +367 -0
  394. package/src/install.ts +32 -0
  395. package/src/stores/auth.ts +152 -0
  396. package/src/stores/index.ts +2 -0
  397. package/src/stores/settings.ts +218 -0
  398. package/src/styles/components/alert-box.css +150 -0
  399. package/src/styles/components/app-avatar-menu.css +155 -0
  400. package/src/styles/components/app-container.css +33 -0
  401. package/src/styles/components/app-layout.css +98 -0
  402. package/src/styles/components/app-page-selector.css +191 -0
  403. package/src/styles/components/app-pill-nav.css +57 -0
  404. package/src/styles/components/app-plugin-switcher.css +209 -0
  405. package/src/styles/components/app-sidebar.css +145 -0
  406. package/src/styles/components/app-top-bar.css +492 -0
  407. package/src/styles/components/audit-trail.css +143 -0
  408. package/src/styles/components/auto-group-modal.css +644 -0
  409. package/src/styles/components/avatar.css +73 -0
  410. package/src/styles/components/batch-progress-list.css +196 -0
  411. package/src/styles/components/breadcrumb.css +64 -0
  412. package/src/styles/components/button.css +188 -0
  413. package/src/styles/components/calendar.css +192 -0
  414. package/src/styles/components/chart-container.css +69 -0
  415. package/src/styles/components/checkbox.css +123 -0
  416. package/src/styles/components/chemical-formula.css +46 -0
  417. package/src/styles/components/collapsible-card.css +253 -0
  418. package/src/styles/components/color-slider.css +110 -0
  419. package/src/styles/components/concentration-input.css +156 -0
  420. package/src/styles/components/confirm-dialog.css +183 -0
  421. package/src/styles/components/dataframe.css +382 -0
  422. package/src/styles/components/date-picker.css +243 -0
  423. package/src/styles/components/datetime-picker.css +229 -0
  424. package/src/styles/components/divider.css +63 -0
  425. package/src/styles/components/dose-calculator.css +301 -0
  426. package/src/styles/components/dropdown-button.css +280 -0
  427. package/src/styles/components/empty-state.css +151 -0
  428. package/src/styles/components/experiment-code-badge.css +33 -0
  429. package/src/styles/components/experiment-data-viewer.css +138 -0
  430. package/src/styles/components/experiment-popover.css +562 -0
  431. package/src/styles/components/experiment-selector-modal.css +285 -0
  432. package/src/styles/components/experiment-timeline.css +529 -0
  433. package/src/styles/components/file-uploader.css +310 -0
  434. package/src/styles/components/fit-panel.css +67 -0
  435. package/src/styles/components/form-builder.css +69 -0
  436. package/src/styles/components/form-field.css +48 -0
  437. package/src/styles/components/formula-input.css +103 -0
  438. package/src/styles/components/group-assigner.css +200 -0
  439. package/src/styles/components/grouping-modal.css +323 -0
  440. package/src/styles/components/icon-button.css +192 -0
  441. package/src/styles/components/input.css +66 -0
  442. package/src/styles/components/loading-spinner.css +67 -0
  443. package/src/styles/components/modal.css +350 -0
  444. package/src/styles/components/molecule-input.css +186 -0
  445. package/src/styles/components/multi-select.css +131 -0
  446. package/src/styles/components/number-input.css +199 -0
  447. package/src/styles/components/pill.css +188 -0
  448. package/src/styles/components/plate-map-editor.css +464 -0
  449. package/src/styles/components/progress-bar.css +133 -0
  450. package/src/styles/components/protocol-step-editor.css +449 -0
  451. package/src/styles/components/rack-editor.css +265 -0
  452. package/src/styles/components/radio-group.css +240 -0
  453. package/src/styles/components/reagent-editor.css +510 -0
  454. package/src/styles/components/reagent-list.css +407 -0
  455. package/src/styles/components/resource-card.css +360 -0
  456. package/src/styles/components/sample-hierarchy-tree.css +314 -0
  457. package/src/styles/components/sample-legend.css +201 -0
  458. package/src/styles/components/sample-selector.css +751 -0
  459. package/src/styles/components/schedule-calendar.css +478 -0
  460. package/src/styles/components/scientific-number.css +63 -0
  461. package/src/styles/components/segmented-control.css +197 -0
  462. package/src/styles/components/select.css +77 -0
  463. package/src/styles/components/sequence-input.css +184 -0
  464. package/src/styles/components/settings-button.css +94 -0
  465. package/src/styles/components/settings-modal.css +95 -0
  466. package/src/styles/components/skeleton.css +49 -0
  467. package/src/styles/components/slider.css +74 -0
  468. package/src/styles/components/status-indicator.css +66 -0
  469. package/src/styles/components/step-wizard.css +192 -0
  470. package/src/styles/components/tabs.css +95 -0
  471. package/src/styles/components/tags-input.css +195 -0
  472. package/src/styles/components/textarea.css +82 -0
  473. package/src/styles/components/theme-toggle.css +69 -0
  474. package/src/styles/components/time-picker.css +171 -0
  475. package/src/styles/components/time-range-input.css +42 -0
  476. package/src/styles/components/toast.css +91 -0
  477. package/src/styles/components/toggle.css +146 -0
  478. package/src/styles/components/tooltip.css +91 -0
  479. package/src/styles/components/unit-input.css +123 -0
  480. package/src/styles/components/well-edit-popup.css +252 -0
  481. package/src/styles/components/well-plate.css +307 -0
  482. package/src/styles/index.css +87 -0
  483. package/src/styles/variables.css +1117 -0
  484. package/src/tailwind.preset.ts +61 -0
  485. package/src/types/auth.ts +55 -0
  486. package/src/types/auto-group.ts +40 -0
  487. package/src/types/components.ts +710 -0
  488. package/src/types/form-builder.ts +197 -0
  489. package/src/types/index.ts +207 -0
  490. package/src/types/platform.ts +116 -0
  491. package/src/utils/color.ts +96 -0
@@ -0,0 +1,118 @@
1
+ // Base components
2
+ export { default as BaseButton } from './BaseButton.vue'
3
+ export { default as BaseInput } from './BaseInput.vue'
4
+ export { default as BaseTextarea } from './BaseTextarea.vue'
5
+ export { default as BaseSelect } from './BaseSelect.vue'
6
+ export { default as BaseCheckbox } from './BaseCheckbox.vue'
7
+ export { default as BaseToggle } from './BaseToggle.vue'
8
+ export { default as BaseRadioGroup } from './BaseRadioGroup.vue'
9
+ export { default as BaseSlider } from './BaseSlider.vue'
10
+ export { default as ColorSlider } from './ColorSlider.vue'
11
+ export { default as BaseTabs } from './BaseTabs.vue'
12
+ export { default as BaseModal } from './BaseModal.vue'
13
+ export { default as SegmentedControl } from './SegmentedControl.vue'
14
+ export { default as MultiSelect } from './MultiSelect.vue'
15
+ export { default as BasePill } from './BasePill.vue'
16
+ export { default as DropdownButton } from './DropdownButton.vue'
17
+ export { default as Calendar } from './Calendar.vue'
18
+ export { default as DataFrame } from './DataFrame.vue'
19
+
20
+ // Form components
21
+ export { default as FormField } from './FormField.vue'
22
+ export { default as DatePicker } from './DatePicker.vue'
23
+ export { default as TimePicker } from './TimePicker.vue'
24
+ export { default as TagsInput } from './TagsInput.vue'
25
+ export { default as NumberInput } from './NumberInput.vue'
26
+ export { default as FileUploader } from './FileUploader.vue'
27
+
28
+ // Feedback components
29
+ export { default as AlertBox } from './AlertBox.vue'
30
+ export { default as ToastNotification } from './ToastNotification.vue'
31
+ export { default as AppToastContainer } from './ToastNotification.vue'
32
+
33
+ // Action components
34
+ export { default as IconButton } from './IconButton.vue'
35
+ export { default as ThemeToggle } from './ThemeToggle.vue'
36
+ export { default as SettingsButton } from './SettingsButton.vue'
37
+
38
+ // Layout components
39
+ export { default as CollapsibleCard } from './CollapsibleCard.vue'
40
+ export { default as AppTopBar } from './AppTopBar.vue'
41
+ export { default as AppPageSelector } from './AppPageSelector.vue'
42
+ export { default as AppPillNav } from './AppPillNav.vue'
43
+ export { default as AppAvatarMenu } from './AppAvatarMenu.vue'
44
+ export { default as AppPluginSwitcher } from './AppPluginSwitcher.vue'
45
+ export { default as AppSidebar } from './AppSidebar.vue'
46
+ export { default as AppLayout } from './AppLayout.vue'
47
+ export { default as AppContainer } from './AppContainer.vue'
48
+
49
+ // Utility components
50
+ export { default as Skeleton } from './Skeleton.vue'
51
+ export { default as LoadingSpinner } from './LoadingSpinner.vue'
52
+ export { default as Divider } from './Divider.vue'
53
+ export { default as StatusIndicator } from './StatusIndicator.vue'
54
+ export { default as ProgressBar } from './ProgressBar.vue'
55
+ export { default as Avatar } from './Avatar.vue'
56
+ export { default as EmptyState } from './EmptyState.vue'
57
+ export { default as Breadcrumb } from './Breadcrumb.vue'
58
+ export { default as Tooltip } from './Tooltip.vue'
59
+ export { default as ConfirmDialog } from './ConfirmDialog.vue'
60
+ export { default as ChartContainer } from './ChartContainer.vue'
61
+ export { default as SettingsModal } from './SettingsModal.vue'
62
+
63
+ // Biological experiment components
64
+ export { default as WellPlate } from './WellPlate.vue'
65
+ export { default as RackEditor } from './RackEditor.vue'
66
+ export { default as SampleLegend } from './SampleLegend.vue'
67
+ export { default as PlateMapEditor } from './PlateMapEditor.vue'
68
+ export { default as ExperimentTimeline } from './ExperimentTimeline.vue'
69
+
70
+ // Sample management components
71
+ export { default as SampleSelector } from './SampleSelector.vue'
72
+ export { default as GroupingModal } from './GroupingModal.vue'
73
+ export { default as AutoGroupModal } from './AutoGroupModal.vue'
74
+ export { default as GroupAssigner } from './GroupAssigner.vue'
75
+
76
+ // Lab/Experiment components
77
+ export { default as MoleculeInput } from './MoleculeInput.vue'
78
+ export { default as ConcentrationInput } from './ConcentrationInput.vue'
79
+ export { default as DoseCalculator } from './DoseCalculator.vue'
80
+ export { default as ReagentEditor, type ReagentDefinition } from './ReagentEditor.vue'
81
+ export { default as ReagentList } from './ReagentList.vue'
82
+ export { default as SampleHierarchyTree } from './SampleHierarchyTree.vue'
83
+ export { default as ProtocolStepEditor } from './ProtocolStepEditor.vue'
84
+
85
+ // Scientific display components
86
+ export { default as ScientificNumber } from './ScientificNumber.vue'
87
+ export { default as ChemicalFormula } from './ChemicalFormula.vue'
88
+
89
+ // Scientific input components
90
+ export { default as FormulaInput } from './FormulaInput.vue'
91
+ export { default as SequenceInput } from './SequenceInput.vue'
92
+ export { default as UnitInput } from './UnitInput.vue'
93
+
94
+ // Workflow components
95
+ export { default as StepWizard } from './StepWizard.vue'
96
+ export { default as AuditTrail } from './AuditTrail.vue'
97
+ export { default as BatchProgressList } from './BatchProgressList.vue'
98
+
99
+ // Form builder components
100
+ export { default as FormBuilder } from './FormBuilder.vue'
101
+ export { default as FormSection } from './FormSection.vue'
102
+ export { default as FormActions } from './FormActions.vue'
103
+ export { default as FormFieldRenderer } from './FormFieldRenderer.vue'
104
+
105
+ // Experiment data display components
106
+ export { default as ExperimentDataViewer } from './ExperimentDataViewer.vue'
107
+ export { default as ExperimentCodeBadge } from './ExperimentCodeBadge.vue'
108
+
109
+ // Scheduling / booking components
110
+ export { default as DateTimePicker } from './DateTimePicker.vue'
111
+ export { default as TimeRangeInput } from './TimeRangeInput.vue'
112
+ export { default as ScheduleCalendar } from './ScheduleCalendar.vue'
113
+ export { default as ResourceCard } from './ResourceCard.vue'
114
+
115
+ // Experiment / analysis components
116
+ export { default as ExperimentSelectorModal } from './ExperimentSelectorModal.vue'
117
+ export { default as ExperimentPopover } from './ExperimentPopover.vue'
118
+ export { default as FitPanel } from './FitPanel.vue'
@@ -0,0 +1,57 @@
1
+ import type { DatePreset, ExperimentStatus, SelectOption, PillVariant } from '../types'
2
+
3
+ export function formatExperimentDate(dateStr: string): string {
4
+ try {
5
+ return new Date(dateStr).toLocaleDateString(undefined, {
6
+ year: 'numeric',
7
+ month: 'short',
8
+ day: 'numeric',
9
+ })
10
+ } catch {
11
+ return dateStr
12
+ }
13
+ }
14
+
15
+ export function datePresetToISO(preset: DatePreset): string {
16
+ const now = new Date()
17
+ const days = preset === 'last_7_days' ? 7 : preset === 'last_30_days' ? 30 : 90
18
+ const d = new Date(now.getTime() - days * 86_400_000)
19
+ return d.toISOString()
20
+ }
21
+
22
+ export const EXPERIMENT_STATUS_OPTIONS: SelectOption<string>[] = [
23
+ { value: '', label: 'All statuses' },
24
+ { value: 'planned', label: 'Planned' },
25
+ { value: 'ongoing', label: 'Ongoing' },
26
+ { value: 'completed', label: 'Completed' },
27
+ { value: 'cancelled', label: 'Cancelled' },
28
+ ]
29
+
30
+ export const EXPERIMENT_STATUS_VARIANT_MAP: Record<ExperimentStatus, PillVariant> = {
31
+ planned: 'default',
32
+ ongoing: 'primary',
33
+ completed: 'success',
34
+ cancelled: 'error',
35
+ }
36
+
37
+ export const EXPERIMENT_STATUS_LABELS: Record<ExperimentStatus, string> = {
38
+ planned: 'Planned',
39
+ ongoing: 'Ongoing',
40
+ completed: 'Completed',
41
+ cancelled: 'Cancelled',
42
+ }
43
+
44
+ export const DATE_PRESET_OPTIONS: SelectOption<string>[] = [
45
+ { value: '', label: 'Any time' },
46
+ { value: 'last_7_days', label: 'Last 7 days' },
47
+ { value: 'last_30_days', label: 'Last 30 days' },
48
+ { value: 'last_90_days', label: 'Last 90 days' },
49
+ ]
50
+
51
+ export const SORT_OPTIONS: SelectOption<string>[] = [
52
+ { value: 'created_at:desc', label: 'Newest first' },
53
+ { value: 'created_at:asc', label: 'Oldest first' },
54
+ { value: 'updated_at:desc', label: 'Recently updated' },
55
+ { value: 'name:asc', label: 'Name A\u2013Z' },
56
+ { value: 'name:desc', label: 'Name Z\u2013A' },
57
+ ]
@@ -0,0 +1,79 @@
1
+ import type { Component } from 'vue'
2
+ import type { FormFieldType } from '../types/form-builder'
3
+
4
+ import BaseInput from '../components/BaseInput.vue'
5
+ import BaseTextarea from '../components/BaseTextarea.vue'
6
+ import BaseSelect from '../components/BaseSelect.vue'
7
+ import MultiSelect from '../components/MultiSelect.vue'
8
+ import BaseCheckbox from '../components/BaseCheckbox.vue'
9
+ import BaseToggle from '../components/BaseToggle.vue'
10
+ import BaseRadioGroup from '../components/BaseRadioGroup.vue'
11
+ import BaseSlider from '../components/BaseSlider.vue'
12
+ import TagsInput from '../components/TagsInput.vue'
13
+ import NumberInput from '../components/NumberInput.vue'
14
+ import DatePicker from '../components/DatePicker.vue'
15
+ import TimePicker from '../components/TimePicker.vue'
16
+ import DateTimePicker from '../components/DateTimePicker.vue'
17
+ import FileUploader from '../components/FileUploader.vue'
18
+ import FormulaInput from '../components/FormulaInput.vue'
19
+ import SequenceInput from '../components/SequenceInput.vue'
20
+ import MoleculeInput from '../components/MoleculeInput.vue'
21
+ import ConcentrationInput from '../components/ConcentrationInput.vue'
22
+ import UnitInput from '../components/UnitInput.vue'
23
+
24
+ export interface RegistryEntry {
25
+ component: Component
26
+ /** Default props applied to the component. */
27
+ defaults: Record<string, unknown>
28
+ /** Whether the component uses v-model (false for event-only components like FileUploader). */
29
+ vModel: boolean
30
+ }
31
+
32
+ const registry: Record<FormFieldType, RegistryEntry> = {
33
+ text: { component: BaseInput, defaults: { type: 'text' }, vModel: true },
34
+ email: { component: BaseInput, defaults: { type: 'email' }, vModel: true },
35
+ password: { component: BaseInput, defaults: { type: 'password' }, vModel: true },
36
+ tel: { component: BaseInput, defaults: { type: 'tel' }, vModel: true },
37
+ url: { component: BaseInput, defaults: { type: 'url' }, vModel: true },
38
+ search: { component: BaseInput, defaults: { type: 'search' }, vModel: true },
39
+ number: { component: NumberInput, defaults: {}, vModel: true },
40
+ textarea: { component: BaseTextarea, defaults: {}, vModel: true },
41
+ select: { component: BaseSelect, defaults: {}, vModel: true },
42
+ multiselect: { component: MultiSelect, defaults: {}, vModel: true },
43
+ checkbox: { component: BaseCheckbox, defaults: {}, vModel: true },
44
+ toggle: { component: BaseToggle, defaults: {}, vModel: true },
45
+ radio: { component: BaseRadioGroup, defaults: {}, vModel: true },
46
+ slider: { component: BaseSlider, defaults: {}, vModel: true },
47
+ tags: { component: TagsInput, defaults: {}, vModel: true },
48
+ date: { component: DatePicker, defaults: {}, vModel: true },
49
+ time: { component: TimePicker, defaults: {}, vModel: true },
50
+ datetime: { component: DateTimePicker, defaults: {}, vModel: true },
51
+ file: { component: FileUploader, defaults: {}, vModel: false },
52
+ formula: { component: FormulaInput, defaults: {}, vModel: true },
53
+ sequence: { component: SequenceInput, defaults: {}, vModel: true },
54
+ molecule: { component: MoleculeInput, defaults: {}, vModel: true },
55
+ concentration: { component: ConcentrationInput, defaults: {}, vModel: true },
56
+ unit: { component: UnitInput, defaults: {}, vModel: true },
57
+ }
58
+
59
+ /** Return the registry entry for a given field type. Throws if the type is unregistered. */
60
+ export function getFieldRegistryEntry(type: FormFieldType): RegistryEntry {
61
+ return registry[type]
62
+ }
63
+
64
+ /** Get the default empty value for a given field type. */
65
+ export function getTypeDefault(type: FormFieldType): unknown {
66
+ switch (type) {
67
+ case 'checkbox':
68
+ case 'toggle':
69
+ return false
70
+ case 'number':
71
+ case 'slider':
72
+ return undefined
73
+ case 'multiselect':
74
+ case 'tags':
75
+ return []
76
+ default:
77
+ return ''
78
+ }
79
+ }
@@ -0,0 +1,140 @@
1
+ export { useApi, type ApiClientOptions } from './useApi'
2
+ export { useAuth } from './useAuth'
3
+ export { usePasskey } from './usePasskey'
4
+ export { useTheme } from './useTheme'
5
+ export { useToast } from './useToast'
6
+ export { usePlatformContext } from './usePlatformContext'
7
+ export {
8
+ useForm,
9
+ type ValidationRule,
10
+ type FieldRules,
11
+ type FieldState,
12
+ type UseFormReturn,
13
+ } from './useForm'
14
+ export {
15
+ useAsync,
16
+ useAsyncBatch,
17
+ type AsyncError,
18
+ type AsyncState,
19
+ type UseAsyncReturn,
20
+ type UseAsyncOptions,
21
+ } from './useAsync'
22
+ export {
23
+ useWellPlateEditor,
24
+ type UseWellPlateEditorOptions,
25
+ type UseWellPlateEditorReturn,
26
+ } from './useWellPlateEditor'
27
+ export {
28
+ useConcentrationUnits,
29
+ type ConcentrationValue,
30
+ type ConcentrationUnit,
31
+ type MolarityUnit,
32
+ type MassVolumeUnit,
33
+ type PercentageUnit,
34
+ type UnitCategory,
35
+ type UseConcentrationUnitsReturn,
36
+ } from './useConcentrationUnits'
37
+ export {
38
+ useDoseCalculator,
39
+ type VolumeUnit,
40
+ type VolumeValue,
41
+ type DilutionParams,
42
+ type DilutionResult,
43
+ type SerialDilutionParams,
44
+ type SerialDilutionStep,
45
+ type SerialDilutionResult,
46
+ type WellConcentration,
47
+ type UseDoseCalculatorReturn,
48
+ } from './useDoseCalculator'
49
+ export {
50
+ useProtocolTemplates,
51
+ type ParameterDefinition,
52
+ type StepTemplate,
53
+ type ValidationResult,
54
+ type UseProtocolTemplatesReturn,
55
+ } from './useProtocolTemplates'
56
+ export {
57
+ useRackEditor,
58
+ type UseRackEditorOptions,
59
+ type UseRackEditorReturn,
60
+ } from './useRackEditor'
61
+ export {
62
+ useChemicalFormula,
63
+ ATOMIC_WEIGHTS,
64
+ type ParsedElement,
65
+ type FormulaParseResult,
66
+ type FormulaPart,
67
+ type FormulaPartType,
68
+ } from './useChemicalFormula'
69
+ export {
70
+ useSequenceUtils,
71
+ type SequenceType,
72
+ type SequenceStats,
73
+ } from './useSequenceUtils'
74
+ export {
75
+ useTimeUtils,
76
+ parseTime,
77
+ formatTime,
78
+ generateTimeSlots,
79
+ rangesOverlap,
80
+ durationMinutes,
81
+ formatDuration,
82
+ isTimeInRange,
83
+ findAvailableSlots,
84
+ snapToSlot,
85
+ addMinutes,
86
+ compareTime,
87
+ } from './useTimeUtils'
88
+ export { useScheduleDrag } from './useScheduleDrag'
89
+ export { useFormBuilder, evaluateCondition } from './useFormBuilder'
90
+ export { useAutoGroup, DEFAULT_COLORS, extractSamplesFromDesignData } from './useAutoGroup'
91
+ export {
92
+ useReagentSeries,
93
+ generateDilutionSeries,
94
+ DEFAULT_PRESETS,
95
+ DEFAULT_UNITS,
96
+ type LevelEntry,
97
+ type DilutionPreset,
98
+ type UseReagentSeriesReturn,
99
+ } from './useReagentSeries'
100
+ export { usePluginConfig, type UsePluginConfigReturn } from './usePluginConfig'
101
+ export {
102
+ useExperimentSelector,
103
+ type UseExperimentSelectorOptions,
104
+ type UseExperimentSelectorReturn,
105
+ } from './useExperimentSelector'
106
+ export {
107
+ formatExperimentDate,
108
+ datePresetToISO,
109
+ EXPERIMENT_STATUS_OPTIONS,
110
+ EXPERIMENT_STATUS_VARIANT_MAP,
111
+ EXPERIMENT_STATUS_LABELS,
112
+ DATE_PRESET_OPTIONS,
113
+ SORT_OPTIONS,
114
+ } from './experiment-utils'
115
+ export {
116
+ useExperimentData,
117
+ type UseExperimentDataOptions,
118
+ type UseExperimentDataReturn,
119
+ } from './useExperimentData'
120
+ export {
121
+ getFieldRegistryEntry,
122
+ getTypeDefault,
123
+ type RegistryEntry,
124
+ } from './formBuilderRegistry'
125
+ export {
126
+ useAppExperiment,
127
+ APP_EXPERIMENT_KEY,
128
+ type UseAppExperimentOptions,
129
+ type UseAppExperimentReturn,
130
+ type AppExperimentState,
131
+ } from './useAppExperiment'
132
+ export {
133
+ useExperimentSave,
134
+ type UseExperimentSaveOptions,
135
+ type UseExperimentSaveReturn,
136
+ } from './useExperimentSave'
137
+ export {
138
+ usePluginApi,
139
+ type UsePluginApiOptions,
140
+ } from './usePluginApi'
@@ -0,0 +1,167 @@
1
+ import axios, { type AxiosInstance, type AxiosRequestConfig } from 'axios'
2
+ import { useSettingsStore } from '../stores/settings'
3
+ import { useAuthStore } from '../stores/auth'
4
+
5
+ let apiClientInstance: AxiosInstance | null = null
6
+ let interceptorAttached = false
7
+
8
+ function getApiClient(): AxiosInstance {
9
+ if (!apiClientInstance) {
10
+ apiClientInstance = axios.create({
11
+ headers: {
12
+ 'Content-Type': 'application/json',
13
+ },
14
+ })
15
+ }
16
+ return apiClientInstance
17
+ }
18
+
19
+ export interface ApiClientOptions {
20
+ baseUrl?: string
21
+ timeout?: number
22
+ withAuth?: boolean
23
+ }
24
+
25
+ export interface UseApiReturn {
26
+ client: AxiosInstance
27
+ get: <T>(url: string, config?: AxiosRequestConfig) => Promise<T>
28
+ post: <T>(url: string, data?: unknown, config?: AxiosRequestConfig) => Promise<T>
29
+ put: <T>(url: string, data?: unknown, config?: AxiosRequestConfig) => Promise<T>
30
+ patch: <T>(url: string, data?: unknown, config?: AxiosRequestConfig) => Promise<T>
31
+ delete: <T>(url: string, config?: AxiosRequestConfig) => Promise<T>
32
+ upload: <T>(url: string, file: File, fieldName?: string, additionalData?: Record<string, unknown>) => Promise<T>
33
+ download: (url: string, filename?: string) => Promise<string>
34
+ buildUrl: (path: string) => string
35
+ buildWsUrl: (path: string) => string
36
+ }
37
+
38
+ /** Axios-based API client that injects the plugin base URL and JWT auth header on every request. */
39
+ export function useApi(options: ApiClientOptions = {}): UseApiReturn {
40
+ const settingsStore = useSettingsStore()
41
+ const authStore = useAuthStore()
42
+ const apiClient = getApiClient()
43
+
44
+ // Ensure auth store is initialized (reads token from localStorage)
45
+ if (!authStore.isInitialized) {
46
+ authStore.initialize()
47
+ }
48
+
49
+ // Attach auth interceptor only once (reads token dynamically, not from closure)
50
+ if (!interceptorAttached) {
51
+ apiClient.interceptors.request.use((config) => {
52
+ if (authStore.token && config.headers && !config.headers.Authorization) {
53
+ config.headers.Authorization = `Bearer ${authStore.token}`
54
+ }
55
+ return config
56
+ })
57
+ interceptorAttached = true
58
+ }
59
+
60
+ // Build per-request config that applies this caller's options
61
+ function requestConfig(config?: AxiosRequestConfig): AxiosRequestConfig {
62
+ const base: AxiosRequestConfig = {
63
+ baseURL: options.baseUrl ?? settingsStore.getApiBaseUrl(),
64
+ timeout: options.timeout ?? settingsStore.requestTimeout,
65
+ ...config,
66
+ }
67
+ // Strip auth header if explicitly disabled
68
+ if (options.withAuth === false) {
69
+ base.headers = { ...base.headers, Authorization: undefined }
70
+ }
71
+ return base
72
+ }
73
+
74
+ // Generic request methods
75
+ async function get<T>(url: string, config?: AxiosRequestConfig): Promise<T> {
76
+ const response = await apiClient.get<T>(url, requestConfig(config))
77
+ return response.data
78
+ }
79
+
80
+ async function post<T>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T> {
81
+ const response = await apiClient.post<T>(url, data, requestConfig(config))
82
+ return response.data
83
+ }
84
+
85
+ async function put<T>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T> {
86
+ const response = await apiClient.put<T>(url, data, requestConfig(config))
87
+ return response.data
88
+ }
89
+
90
+ async function patch<T>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T> {
91
+ const response = await apiClient.patch<T>(url, data, requestConfig(config))
92
+ return response.data
93
+ }
94
+
95
+ async function del<T>(url: string, config?: AxiosRequestConfig): Promise<T> {
96
+ const response = await apiClient.delete<T>(url, requestConfig(config))
97
+ return response.data
98
+ }
99
+
100
+ // File upload helper
101
+ async function upload<T>(url: string, file: File, fieldName = 'file', additionalData?: Record<string, unknown>): Promise<T> {
102
+ const formData = new FormData()
103
+ formData.append(fieldName, file)
104
+
105
+ if (additionalData) {
106
+ Object.entries(additionalData).forEach(([key, value]) => {
107
+ if (value !== undefined && value !== null) {
108
+ formData.append(key, typeof value === 'object' ? JSON.stringify(value) : String(value))
109
+ }
110
+ })
111
+ }
112
+
113
+ const response = await apiClient.post<T>(url, formData, requestConfig({
114
+ // Let Axios set Content-Type with the correct multipart boundary
115
+ headers: { 'Content-Type': undefined },
116
+ }))
117
+ return response.data
118
+ }
119
+
120
+ // Download helper - returns blob URL
121
+ async function download(url: string, filename?: string): Promise<string> {
122
+ const response = await apiClient.get(url, requestConfig({ responseType: 'blob' }))
123
+ const blob = new Blob([response.data])
124
+ const blobUrl = URL.createObjectURL(blob)
125
+
126
+ // Optionally trigger download
127
+ if (filename) {
128
+ const link = document.createElement('a')
129
+ link.href = blobUrl
130
+ link.download = filename
131
+ document.body.appendChild(link)
132
+ link.click()
133
+ document.body.removeChild(link)
134
+ // Revoke after a short delay to allow download to start;
135
+ // return empty string since the URL will be invalidated
136
+ setTimeout(() => URL.revokeObjectURL(blobUrl), 100)
137
+ return ''
138
+ }
139
+
140
+ // Caller is responsible for revoking when no filename is provided
141
+ return blobUrl
142
+ }
143
+
144
+ // Build full URL for external use (e.g., <a href="...">)
145
+ function buildUrl(path: string): string {
146
+ const baseUrl = options.baseUrl ?? settingsStore.getApiBaseUrl()
147
+ return `${baseUrl}${path}`
148
+ }
149
+
150
+ // WebSocket URL builder
151
+ function buildWsUrl(path: string): string {
152
+ return `${settingsStore.getWsBaseUrl()}${path}`
153
+ }
154
+
155
+ return {
156
+ client: apiClient,
157
+ get,
158
+ post,
159
+ put,
160
+ patch,
161
+ delete: del,
162
+ upload,
163
+ download,
164
+ buildUrl,
165
+ buildWsUrl,
166
+ }
167
+ }