@morscherlab/mint-sdk 1.0.0-beta.2 → 1.0.0-beta.4

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 (427) hide show
  1. package/README.md +225 -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/ComponentBindingRenderer.test.d.ts +1 -0
  19. package/dist/__tests__/components/ConcentrationInput.test.d.ts +1 -0
  20. package/dist/__tests__/components/ControlWorkspaceView.test.d.ts +1 -0
  21. package/dist/__tests__/components/DatePicker.test.d.ts +1 -0
  22. package/dist/__tests__/components/DateTimePicker.test.d.ts +1 -0
  23. package/dist/__tests__/components/DoseDesignWorkspaceView.test.d.ts +1 -0
  24. package/dist/__tests__/components/EmptyState.test.d.ts +1 -0
  25. package/dist/__tests__/components/ExperimentPopover.test.d.ts +1 -0
  26. package/dist/__tests__/components/FormBuilder.test.d.ts +1 -0
  27. package/dist/__tests__/components/GroupAssigner.test.d.ts +1 -0
  28. package/dist/__tests__/components/MultiSelect.test.d.ts +1 -0
  29. package/dist/__tests__/components/PluginWorkspaceView.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/SettingsModal.test.d.ts +1 -0
  36. package/dist/__tests__/components/TagsInput.test.d.ts +1 -0
  37. package/dist/__tests__/components/ThemeToggle.test.d.ts +1 -0
  38. package/dist/__tests__/components/TimePicker.test.d.ts +1 -0
  39. package/dist/__tests__/composables/experiment-utils.test.d.ts +1 -0
  40. package/dist/__tests__/composables/useApi.test.d.ts +1 -0
  41. package/dist/__tests__/composables/useBioTemplatePackWorkspace.test.d.ts +1 -0
  42. package/dist/__tests__/composables/useBioTemplatePresetWorkspace.test.d.ts +1 -0
  43. package/dist/__tests__/composables/useBioTemplateWorkspace.test.d.ts +1 -0
  44. package/dist/__tests__/composables/useCalendarGrid.test.d.ts +1 -0
  45. package/dist/__tests__/composables/useControlSchema.test.d.ts +1 -0
  46. package/dist/__tests__/composables/useDebouncedWatch.test.d.ts +1 -0
  47. package/dist/__tests__/composables/useDropdownState.test.d.ts +1 -0
  48. package/dist/__tests__/composables/useEventListener.test.d.ts +1 -0
  49. package/dist/__tests__/composables/useExpansionSet.test.d.ts +1 -0
  50. package/dist/__tests__/composables/useExperimentData.test.d.ts +1 -0
  51. package/dist/__tests__/composables/useExperimentSelector.test.d.ts +1 -0
  52. package/dist/__tests__/composables/useGroupAssignment.test.d.ts +1 -0
  53. package/dist/__tests__/composables/useListSelection.test.d.ts +1 -0
  54. package/dist/__tests__/composables/usePluginClient.test.d.ts +1 -0
  55. package/dist/__tests__/composables/usePluginConfig.test.d.ts +1 -0
  56. package/dist/__tests__/composables/useRequestSyncState.test.d.ts +1 -0
  57. package/dist/__tests__/composables/useSampleGroups.test.d.ts +1 -0
  58. package/dist/__tests__/composables/useSelectionLimit.test.d.ts +1 -0
  59. package/dist/__tests__/composables/useSortedItems.test.d.ts +1 -0
  60. package/dist/__tests__/composables/useTemplateCollection.test.d.ts +1 -0
  61. package/dist/__tests__/composables/useTextSearch.test.d.ts +1 -0
  62. package/dist/__tests__/composables/useTheme.test.d.ts +1 -0
  63. package/dist/__tests__/composables/useTimeUtils.test.d.ts +1 -0
  64. package/dist/__tests__/docs/frontendDocsCatalog.test.d.ts +1 -0
  65. package/dist/__tests__/templates/templates.test.d.ts +1 -0
  66. package/dist/{auth-DsI0rQ7_.js → auth-QQj2kkze.js} +12 -5
  67. package/dist/auth-QQj2kkze.js.map +1 -0
  68. package/dist/components/AppAvatarMenu.vue.d.ts +2 -7
  69. package/dist/components/AppContainer.vue.d.ts +1 -1
  70. package/dist/components/AppLayout.vue.d.ts +20 -1
  71. package/dist/components/AppSidebar.vue.d.ts +111 -6
  72. package/dist/components/AppTopBar.vue.d.ts +35 -22
  73. package/dist/components/BaseButton.vue.d.ts +1 -1
  74. package/dist/components/BaseCheckbox.vue.d.ts +1 -1
  75. package/dist/components/BaseInput.vue.d.ts +2 -2
  76. package/dist/components/BasePill.vue.d.ts +2 -2
  77. package/dist/components/BaseRadioGroup.vue.d.ts +3 -3
  78. package/dist/components/BaseSelect.vue.d.ts +3 -3
  79. package/dist/components/BaseTabs.vue.d.ts +2 -2
  80. package/dist/components/BaseTextarea.vue.d.ts +1 -1
  81. package/dist/components/BaseToggle.vue.d.ts +1 -1
  82. package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +119 -0
  83. package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +93 -0
  84. package/dist/components/BioTemplatePresetWorkspaceView.vue.d.ts +87 -0
  85. package/dist/components/BioTemplateRenderer.vue.d.ts +29 -0
  86. package/dist/components/Breadcrumb.vue.d.ts +2 -2
  87. package/dist/components/Calendar.vue.d.ts +1 -1
  88. package/dist/components/CollapsibleCard.vue.d.ts +1 -1
  89. package/dist/components/ComponentBindingRenderer.vue.d.ts +44 -0
  90. package/dist/components/ConcentrationInput.vue.d.ts +2 -2
  91. package/dist/components/ConfirmDialog.vue.d.ts +2 -2
  92. package/dist/components/ControlWorkspaceView.vue.d.ts +147 -0
  93. package/dist/components/DatePicker.vue.d.ts +1 -1
  94. package/dist/components/DateTimePicker.vue.d.ts +3 -3
  95. package/dist/components/Divider.vue.d.ts +1 -1
  96. package/dist/components/DoseDesignWorkspaceView.vue.d.ts +149 -0
  97. package/dist/components/DropdownButton.vue.d.ts +3 -3
  98. package/dist/components/EmptyState.vue.d.ts +1 -2
  99. package/dist/components/ExperimentDataViewer.vue.d.ts +1 -1
  100. package/dist/components/ExperimentTimeline.vue.d.ts +2 -2
  101. package/dist/components/FileUploader.vue.d.ts +1 -1
  102. package/dist/components/FitPanel.vue.d.ts +1 -1
  103. package/dist/components/FormActions.vue.d.ts +4 -4
  104. package/dist/components/FormBuilder.vue.d.ts +31 -17
  105. package/dist/components/FormulaInput.vue.d.ts +2 -2
  106. package/dist/components/MoleculeInput.vue.d.ts +2 -2
  107. package/dist/components/MultiSelect.vue.d.ts +3 -3
  108. package/dist/components/NumberInput.vue.d.ts +1 -1
  109. package/dist/components/PlateMapEditor.vue.d.ts +1 -1
  110. package/dist/components/PluginWorkspaceView.vue.d.ts +310 -0
  111. package/dist/components/ProgressBar.vue.d.ts +1 -1
  112. package/dist/components/ProtocolStepEditor.vue.d.ts +3 -1
  113. package/dist/components/RackEditor.vue.d.ts +2 -2
  114. package/dist/components/SampleLegend.vue.d.ts +2 -2
  115. package/dist/components/ScheduleCalendar.vue.d.ts +2 -2
  116. package/dist/components/SegmentedControl.vue.d.ts +2 -2
  117. package/dist/components/SequenceInput.vue.d.ts +3 -3
  118. package/dist/components/SettingsModal.vue.d.ts +14 -6
  119. package/dist/components/StatusIndicator.vue.d.ts +1 -1
  120. package/dist/components/TagsInput.vue.d.ts +3 -2
  121. package/dist/components/TimePicker.vue.d.ts +3 -3
  122. package/dist/components/TimeRangeInput.vue.d.ts +1 -1
  123. package/dist/components/UnitInput.vue.d.ts +2 -2
  124. package/dist/components/WellPlate.vue.d.ts +6 -6
  125. package/dist/components/index.d.ts +9 -8
  126. package/dist/components/index.js +3 -3
  127. package/dist/components/{SettingsButton.vue.d.ts → internal/ActionItemInternal.vue.d.ts} +11 -9
  128. package/dist/components/{AppPageSelector.vue.d.ts → internal/AppPageSelectorInternal.vue.d.ts} +3 -6
  129. package/dist/components/{AppPillNav.vue.d.ts → internal/AppPillNavInternal.vue.d.ts} +4 -2
  130. package/dist/components/internal/CalendarGridPanelInternal.vue.d.ts +25 -0
  131. package/dist/components/{FormFieldRenderer.vue.d.ts → internal/FormFieldRendererInternal.vue.d.ts} +2 -2
  132. package/dist/components/{FormSection.vue.d.ts → internal/FormSectionRenderer.vue.d.ts} +7 -7
  133. package/dist/components/{WellEditPopup.vue.d.ts → internal/WellEditPopupInternal.vue.d.ts} +1 -1
  134. package/dist/{components-_XqPEhP9.js → components-BkGF4B4y.js} +9760 -8471
  135. package/dist/components-BkGF4B4y.js.map +1 -0
  136. package/dist/composables/experiment-utils.d.ts +8 -0
  137. package/dist/composables/index.d.ts +22 -5
  138. package/dist/composables/index.js +4 -3
  139. package/dist/composables/platformContextHelpers.d.ts +14 -0
  140. package/dist/composables/useAppExperiment.d.ts +31 -2
  141. package/dist/composables/useBioTemplateComponents.d.ts +22 -0
  142. package/dist/composables/useBioTemplateControls.d.ts +6 -0
  143. package/dist/composables/useBioTemplatePackWorkspace.d.ts +46 -0
  144. package/dist/composables/useBioTemplatePresetWorkspace.d.ts +75 -0
  145. package/dist/composables/useBioTemplateWorkspace.d.ts +51 -0
  146. package/dist/composables/useCalendarGrid.d.ts +26 -0
  147. package/dist/composables/useControlSchema.d.ts +343 -0
  148. package/dist/composables/useDebouncedWatch.d.ts +20 -0
  149. package/dist/composables/useDropdownState.d.ts +19 -0
  150. package/dist/composables/useEventListener.d.ts +13 -0
  151. package/dist/composables/useExpansionSet.d.ts +21 -0
  152. package/dist/composables/useExperimentData.d.ts +10 -0
  153. package/dist/composables/useExperimentSave.d.ts +31 -2
  154. package/dist/composables/useExperimentSelector.d.ts +20 -0
  155. package/dist/composables/useForm.d.ts +2 -0
  156. package/dist/composables/useGroupAssignment.d.ts +31 -0
  157. package/dist/composables/useListSelection.d.ts +35 -0
  158. package/dist/composables/usePlatformContext.d.ts +21 -3
  159. package/dist/composables/usePluginClient.d.ts +112 -0
  160. package/dist/composables/usePluginConfig.d.ts +12 -0
  161. package/dist/composables/useRequestSyncState.d.ts +34 -0
  162. package/dist/composables/useSampleGroups.d.ts +32 -0
  163. package/dist/composables/useSelectionLimit.d.ts +17 -0
  164. package/dist/composables/useSortedItems.d.ts +32 -0
  165. package/dist/composables/useTemplateCollection.d.ts +58 -0
  166. package/dist/composables/useTextSearch.d.ts +18 -0
  167. package/dist/composables/useTimeUtils.d.ts +8 -0
  168. package/dist/{composables-tiZqLu1M.js → composables-CHsME9H1.js} +240 -146
  169. package/dist/composables-CHsME9H1.js.map +1 -0
  170. package/dist/index.d.ts +6 -4
  171. package/dist/index.js +6 -5
  172. package/dist/install.d.ts +7 -2
  173. package/dist/install.js +2 -2
  174. package/dist/install.js.map +1 -1
  175. package/dist/stores/index.js +1 -1
  176. package/dist/stores/settings.d.ts +4 -1
  177. package/dist/styles.css +4746 -5514
  178. package/dist/templates/adapters.d.ts +43 -0
  179. package/dist/templates/builders.d.ts +63 -0
  180. package/dist/templates/catalog.d.ts +188 -0
  181. package/dist/templates/componentBindings.d.ts +71 -0
  182. package/dist/templates/controlSchemas.d.ts +25 -0
  183. package/dist/templates/index.d.ts +15 -0
  184. package/dist/templates/index.js +2 -0
  185. package/dist/templates/lookup.d.ts +4 -0
  186. package/dist/templates/packs.d.ts +18 -0
  187. package/dist/templates/presets.d.ts +90 -0
  188. package/dist/templates/types.d.ts +531 -0
  189. package/dist/templates-B5jmTWuk.js +9388 -0
  190. package/dist/templates-B5jmTWuk.js.map +1 -0
  191. package/dist/types/components.d.ts +26 -23
  192. package/dist/types/form-builder.d.ts +6 -8
  193. package/dist/types/index.d.ts +2 -2
  194. package/dist/types/platform.d.ts +7 -1
  195. package/dist/useScheduleDrag-BgzpQT53.js +4414 -0
  196. package/dist/useScheduleDrag-BgzpQT53.js.map +1 -0
  197. package/dist/utils/formModelSync.d.ts +5 -0
  198. package/dist/utils/items.d.ts +8 -0
  199. package/dist/utils/options.d.ts +6 -0
  200. package/dist/utils/pluginIcon.d.ts +9 -0
  201. package/package.json +7 -2
  202. package/src/__tests__/components/ActionItem.test.ts +99 -0
  203. package/src/__tests__/components/AppAvatarMenu.test.ts +27 -0
  204. package/src/__tests__/components/AppLayout.test.ts +44 -0
  205. package/src/__tests__/components/AppPageSelector.test.ts +134 -0
  206. package/src/__tests__/components/AppPillNav.test.ts +125 -0
  207. package/src/__tests__/components/AppPluginSwitcher.test.ts +44 -0
  208. package/src/__tests__/components/AppSidebar.test.ts +496 -0
  209. package/src/__tests__/components/AppToastContainer.test.ts +37 -0
  210. package/src/__tests__/components/AppTopBar.test.ts +455 -9
  211. package/src/__tests__/components/BaseRadioGroup.test.ts +25 -0
  212. package/src/__tests__/components/BaseSelect.test.ts +21 -0
  213. package/src/__tests__/components/BaseTabs.test.ts +25 -0
  214. package/src/__tests__/components/BatchProgressList.test.ts +52 -0
  215. package/src/__tests__/components/BioTemplateExperimentWorkspaceView.test.ts +159 -0
  216. package/src/__tests__/components/BioTemplatePackWorkspaceView.test.ts +175 -0
  217. package/src/__tests__/components/BioTemplatePresetWorkspaceView.test.ts +306 -0
  218. package/src/__tests__/components/BioTemplateRenderer.test.ts +71 -0
  219. package/src/__tests__/components/Breadcrumb.test.ts +23 -0
  220. package/src/__tests__/components/CalendarGridPanel.test.ts +36 -0
  221. package/src/__tests__/components/ComponentBindingRenderer.test.ts +161 -0
  222. package/src/__tests__/components/ConcentrationInput.test.ts +45 -0
  223. package/src/__tests__/components/ControlWorkspaceView.test.ts +1102 -0
  224. package/src/__tests__/components/DataFrame.test.ts +11 -0
  225. package/src/__tests__/components/DatePicker.test.ts +45 -0
  226. package/src/__tests__/components/DateTimePicker.test.ts +48 -0
  227. package/src/__tests__/components/DoseDesignWorkspaceView.test.ts +185 -0
  228. package/src/__tests__/components/DropdownButton.test.ts +23 -0
  229. package/src/__tests__/components/EmptyState.test.ts +23 -0
  230. package/src/__tests__/components/ExperimentPopover.test.ts +56 -0
  231. package/src/__tests__/components/FormBuilder.test.ts +296 -0
  232. package/src/__tests__/components/GroupAssigner.test.ts +30 -0
  233. package/src/__tests__/components/MultiSelect.test.ts +48 -0
  234. package/src/__tests__/components/PluginWorkspaceView.test.ts +548 -0
  235. package/src/__tests__/components/ProtocolStepEditor.test.ts +33 -0
  236. package/src/__tests__/components/ReagentList.test.ts +82 -0
  237. package/src/__tests__/components/SampleHierarchyTree.test.ts +53 -0
  238. package/src/__tests__/components/SampleSelector.test.ts +60 -0
  239. package/src/__tests__/components/SegmentedControl.test.ts +24 -0
  240. package/src/__tests__/components/SettingsModal.test.ts +296 -0
  241. package/src/__tests__/components/TagsInput.test.ts +75 -0
  242. package/src/__tests__/components/ThemeToggle.test.ts +47 -0
  243. package/src/__tests__/components/TimePicker.test.ts +38 -0
  244. package/src/__tests__/composables/experiment-utils.test.ts +30 -0
  245. package/src/__tests__/composables/useApi.test.ts +30 -0
  246. package/src/__tests__/composables/useAppExperiment.test.ts +100 -1
  247. package/src/__tests__/composables/useBioTemplatePackWorkspace.test.ts +125 -0
  248. package/src/__tests__/composables/useBioTemplatePresetWorkspace.test.ts +199 -0
  249. package/src/__tests__/composables/useBioTemplateWorkspace.test.ts +104 -0
  250. package/src/__tests__/composables/useCalendarGrid.test.ts +38 -0
  251. package/src/__tests__/composables/useControlSchema.test.ts +1033 -0
  252. package/src/__tests__/composables/useDebouncedWatch.test.ts +93 -0
  253. package/src/__tests__/composables/useDropdownState.test.ts +95 -0
  254. package/src/__tests__/composables/useEventListener.test.ts +116 -0
  255. package/src/__tests__/composables/useExpansionSet.test.ts +62 -0
  256. package/src/__tests__/composables/useExperimentData.test.ts +4 -0
  257. package/src/__tests__/composables/useExperimentSave.test.ts +203 -8
  258. package/src/__tests__/composables/useExperimentSelector.test.ts +164 -0
  259. package/src/__tests__/composables/useForm.test.ts +58 -0
  260. package/src/__tests__/composables/useFormBuilder.test.ts +77 -0
  261. package/src/__tests__/composables/useGroupAssignment.test.ts +73 -0
  262. package/src/__tests__/composables/useListSelection.test.ts +66 -0
  263. package/src/__tests__/composables/usePluginClient.test.ts +541 -0
  264. package/src/__tests__/composables/usePluginConfig.test.ts +5 -0
  265. package/src/__tests__/composables/useRequestSyncState.test.ts +92 -0
  266. package/src/__tests__/composables/useSampleGroups.test.ts +66 -0
  267. package/src/__tests__/composables/useSelectionLimit.test.ts +41 -0
  268. package/src/__tests__/composables/useSortedItems.test.ts +87 -0
  269. package/src/__tests__/composables/useTemplateCollection.test.ts +147 -0
  270. package/src/__tests__/composables/useTextSearch.test.ts +55 -0
  271. package/src/__tests__/composables/useTheme.test.ts +91 -0
  272. package/src/__tests__/composables/useTimeUtils.test.ts +35 -0
  273. package/src/__tests__/docs/frontendDocsCatalog.test.ts +324 -0
  274. package/src/__tests__/fixtures/templates/dose-response.json +81 -0
  275. package/src/__tests__/fixtures/templates/plate-map.json +54 -0
  276. package/src/__tests__/fixtures/templates/qpcr-plate.json +96 -0
  277. package/src/__tests__/fixtures/templates/sample-sheet.json +71 -0
  278. package/src/__tests__/templates/templates.test.ts +1055 -0
  279. package/src/components/AppAvatarMenu.vue +15 -69
  280. package/src/components/AppLayout.story.vue +64 -25
  281. package/src/components/AppLayout.vue +83 -2
  282. package/src/components/AppPluginSwitcher.vue +41 -145
  283. package/src/components/AppSidebar.story.vue +203 -1
  284. package/src/components/AppSidebar.vue +320 -25
  285. package/src/components/{ToastNotification.story.vue → AppToastContainer.story.vue} +6 -6
  286. package/src/components/{ToastNotification.vue → AppToastContainer.vue} +1 -1
  287. package/src/components/AppTopBar.story.vue +7 -33
  288. package/src/components/AppTopBar.vue +104 -300
  289. package/src/components/BaseModal.vue +3 -5
  290. package/src/components/BaseRadioGroup.vue +7 -3
  291. package/src/components/BaseSelect.vue +11 -7
  292. package/src/components/BaseTabs.vue +6 -4
  293. package/src/components/BatchProgressList.vue +5 -8
  294. package/src/components/BioTemplateExperimentWorkspaceView.story.vue +123 -0
  295. package/src/components/BioTemplateExperimentWorkspaceView.vue +343 -0
  296. package/src/components/BioTemplatePackWorkspaceView.story.vue +107 -0
  297. package/src/components/BioTemplatePackWorkspaceView.vue +177 -0
  298. package/src/components/BioTemplatePresetWorkspaceView.story.vue +163 -0
  299. package/src/components/BioTemplatePresetWorkspaceView.vue +401 -0
  300. package/src/components/BioTemplateRenderer.story.vue +57 -0
  301. package/src/components/BioTemplateRenderer.vue +57 -0
  302. package/src/components/Breadcrumb.vue +14 -8
  303. package/src/components/ComponentBindingRenderer.story.vue +57 -0
  304. package/src/components/ComponentBindingRenderer.vue +308 -0
  305. package/src/components/ConcentrationInput.vue +27 -64
  306. package/src/components/ControlWorkspaceView.story.vue +347 -0
  307. package/src/components/ControlWorkspaceView.vue +378 -0
  308. package/src/components/DataFrame.vue +34 -50
  309. package/src/components/DatePicker.vue +59 -192
  310. package/src/components/DateTimePicker.vue +50 -171
  311. package/src/components/DoseDesignWorkspaceView.story.vue +77 -0
  312. package/src/components/DoseDesignWorkspaceView.vue +255 -0
  313. package/src/components/DropdownButton.vue +14 -32
  314. package/src/components/EmptyState.vue +4 -2
  315. package/src/components/ExperimentPopover.vue +7 -28
  316. package/src/components/ExperimentSelectorModal.vue +6 -5
  317. package/src/components/FormBuilder.story.vue +190 -0
  318. package/src/components/FormBuilder.vue +124 -27
  319. package/src/components/GroupAssigner.vue +24 -56
  320. package/src/components/MultiSelect.vue +17 -12
  321. package/src/components/PlateMapEditor.vue +3 -8
  322. package/src/components/PluginIcon.vue +2 -22
  323. package/src/components/PluginWorkspaceView.story.vue +334 -0
  324. package/src/components/PluginWorkspaceView.vue +708 -0
  325. package/src/components/ProtocolStepEditor.vue +13 -22
  326. package/src/components/ReagentList.vue +25 -33
  327. package/src/components/SampleHierarchyTree.vue +12 -23
  328. package/src/components/SampleSelector.vue +42 -122
  329. package/src/components/SegmentedControl.vue +7 -3
  330. package/src/components/SettingsModal.story.vue +88 -1
  331. package/src/components/SettingsModal.vue +120 -29
  332. package/src/components/TagsInput.vue +29 -14
  333. package/src/components/ThemeToggle.vue +9 -7
  334. package/src/components/TimePicker.vue +19 -41
  335. package/src/components/Tooltip.vue +7 -12
  336. package/src/components/WellPlate.vue +6 -12
  337. package/src/components/index.ts +9 -8
  338. package/src/components/internal/ActionItemInternal.vue +82 -0
  339. package/src/components/internal/AppPageSelectorInternal.vue +128 -0
  340. package/src/components/internal/AppPillNavInternal.vue +194 -0
  341. package/src/components/internal/CalendarGridPanelInternal.vue +120 -0
  342. package/src/components/{FormFieldRenderer.vue → internal/FormFieldRendererInternal.vue} +4 -12
  343. package/src/components/{FormSection.vue → internal/FormSectionRenderer.vue} +6 -18
  344. package/src/components/{WellEditPopup.vue → internal/WellEditPopupInternal.vue} +5 -10
  345. package/src/composables/experiment-utils.ts +26 -0
  346. package/src/composables/index.ts +229 -3
  347. package/src/composables/platformContextHelpers.ts +74 -0
  348. package/src/composables/useApi.ts +9 -2
  349. package/src/composables/useAppExperiment.ts +85 -13
  350. package/src/composables/useBioTemplateComponents.ts +105 -0
  351. package/src/composables/useBioTemplateControls.ts +41 -0
  352. package/src/composables/useBioTemplatePackWorkspace.ts +185 -0
  353. package/src/composables/useBioTemplatePresetWorkspace.ts +326 -0
  354. package/src/composables/useBioTemplateWorkspace.ts +141 -0
  355. package/src/composables/useCalendarGrid.ts +140 -0
  356. package/src/composables/useControlSchema.ts +1362 -0
  357. package/src/composables/useDebouncedWatch.ts +119 -0
  358. package/src/composables/useDropdownState.ts +83 -0
  359. package/src/composables/useEventListener.ts +111 -0
  360. package/src/composables/useExpansionSet.ts +117 -0
  361. package/src/composables/useExperimentData.ts +20 -11
  362. package/src/composables/useExperimentSave.ts +202 -50
  363. package/src/composables/useExperimentSelector.ts +86 -72
  364. package/src/composables/useForm.ts +49 -4
  365. package/src/composables/useFormBuilder.ts +93 -42
  366. package/src/composables/useGroupAssignment.ts +148 -0
  367. package/src/composables/useListSelection.ts +158 -0
  368. package/src/composables/usePluginClient.ts +466 -0
  369. package/src/composables/usePluginConfig.ts +34 -13
  370. package/src/composables/useRequestSyncState.ts +126 -0
  371. package/src/composables/useSampleGroups.ts +126 -0
  372. package/src/composables/useSelectionLimit.ts +57 -0
  373. package/src/composables/useSortedItems.ts +118 -0
  374. package/src/composables/useTemplateCollection.ts +229 -0
  375. package/src/composables/useTextSearch.ts +60 -0
  376. package/src/composables/useTheme.ts +2 -28
  377. package/src/composables/useTimeUtils.ts +26 -2
  378. package/src/composables/useWellPlateEditor.ts +13 -9
  379. package/src/index.ts +11 -348
  380. package/src/install.ts +11 -4
  381. package/src/stores/settings.ts +13 -9
  382. package/src/styles/components/app-layout.css +82 -0
  383. package/src/styles/components/app-page-selector.css +23 -0
  384. package/src/styles/components/app-pill-nav.css +77 -0
  385. package/src/styles/components/app-sidebar.css +119 -0
  386. package/src/styles/components/app-top-bar.css +0 -201
  387. package/src/styles/components/concentration-input.css +3 -142
  388. package/src/styles/components/empty-state.css +0 -16
  389. package/src/styles/components/theme-toggle.css +3 -66
  390. package/src/styles/index.css +0 -2
  391. package/src/templates/adapters.ts +785 -0
  392. package/src/templates/builders.ts +2149 -0
  393. package/src/templates/catalog.ts +245 -0
  394. package/src/templates/componentBindings.ts +653 -0
  395. package/src/templates/controlSchemas.ts +718 -0
  396. package/src/templates/index.ts +318 -0
  397. package/src/templates/lookup.ts +18 -0
  398. package/src/templates/packs.ts +156 -0
  399. package/src/templates/presets.ts +146 -0
  400. package/src/templates/types.ts +668 -0
  401. package/src/types/components.ts +39 -27
  402. package/src/types/form-builder.ts +7 -2
  403. package/src/types/index.ts +13 -3
  404. package/src/types/platform.ts +7 -1
  405. package/src/utils/formModelSync.ts +52 -0
  406. package/src/utils/items.ts +28 -0
  407. package/src/utils/options.ts +23 -0
  408. package/src/utils/pluginIcon.ts +30 -0
  409. package/dist/__tests__/composables/usePluginApi.test.d.ts +0 -13
  410. package/dist/auth-DsI0rQ7_.js.map +0 -1
  411. package/dist/components/GroupingModal.vue.d.ts +0 -12
  412. package/dist/components-_XqPEhP9.js.map +0 -1
  413. package/dist/composables/usePluginApi.d.ts +0 -29
  414. package/dist/composables-tiZqLu1M.js.map +0 -1
  415. package/dist/useScheduleDrag-CA9sGNJG.js +0 -7181
  416. package/dist/useScheduleDrag-CA9sGNJG.js.map +0 -1
  417. package/src/__tests__/composables/usePluginApi.test.ts +0 -81
  418. package/src/components/AppPageSelector.vue +0 -159
  419. package/src/components/AppPillNav.vue +0 -66
  420. package/src/components/GroupingModal.story.vue +0 -52
  421. package/src/components/GroupingModal.vue +0 -422
  422. package/src/components/SettingsButton.story.vue +0 -58
  423. package/src/components/SettingsButton.vue +0 -76
  424. package/src/composables/usePluginApi.ts +0 -39
  425. package/src/styles/components/grouping-modal.css +0 -323
  426. package/src/styles/components/settings-button.css +0 -94
  427. /package/dist/components/{ToastNotification.vue.d.ts → AppToastContainer.vue.d.ts} +0 -0
@@ -0,0 +1,378 @@
1
+ <script setup lang="ts">
2
+ /** Complete control workspace component that turns a simple controls data model into AppTopBar, AppSidebar, and FormBuilder forms. */
3
+ import { computed, effectScope, onScopeDispose, shallowRef, toRaw, watch, type EffectScope } from 'vue'
4
+ import type { TopBarVariant } from '../types'
5
+ import type { FormEnhancements } from '../types/form-builder'
6
+ import type {
7
+ ControlComponentBindingsConfig,
8
+ ControlComponentPropsByIdMap,
9
+ ControlComponentPropsMap,
10
+ ControlModel,
11
+ ControlModelBinding,
12
+ ControlSchema,
13
+ ControlWorkspaceOptions,
14
+ UseControlWorkspaceReturn,
15
+ } from '../composables/useControlSchema'
16
+ import { defineControlModel, mergeControlWorkspaceOptions, useControlWorkspace } from '../composables/useControlSchema'
17
+ import AppLayout from './AppLayout.vue'
18
+ import AppSidebar from './AppSidebar.vue'
19
+ import AppTopBar from './AppTopBar.vue'
20
+ import FormBuilder from './FormBuilder.vue'
21
+
22
+ type ControlWorkspaceSidebarVariant = 'default' | 'analysis'
23
+ type ResolvedControlWorkspace = UseControlWorkspaceReturn<ControlSchema>
24
+
25
+ interface ControlWorkspaceDefaultSlotProps {
26
+ workspace: ResolvedControlWorkspace
27
+ bindings: ResolvedControlWorkspace['bindings']
28
+ values: ResolvedControlWorkspace['values']
29
+ componentBindings: ReturnType<ResolvedControlWorkspace['getComponentBindings']>
30
+ componentBindingsById: ReturnType<ResolvedControlWorkspace['getComponentBindingsById']>
31
+ componentProps: ReturnType<ResolvedControlWorkspace['getComponentProps']>
32
+ componentPropsById: ReturnType<ResolvedControlWorkspace['getComponentPropsById']>
33
+ }
34
+
35
+ interface ControlWorkspaceTopbarSlotProps {
36
+ workspace: ResolvedControlWorkspace
37
+ bindings: ResolvedControlWorkspace['bindings']
38
+ topBar: ResolvedControlWorkspace['bindings']['topBar']['value']
39
+ }
40
+
41
+ interface ControlWorkspaceSidebarSlotProps {
42
+ workspace: ResolvedControlWorkspace
43
+ bindings: ResolvedControlWorkspace['bindings']
44
+ sidebar: ResolvedControlWorkspace['sidebar']
45
+ }
46
+
47
+ interface Props {
48
+ /** Model returned by defineControlModel()/defineDoseDesignControlModel(), or a raw nested ControlModel. */
49
+ model?: ControlModel | ControlModelBinding
50
+ /** Workspace returned by useControlWorkspace(). Use for full manual control. */
51
+ workspace?: UseControlWorkspaceReturn<ControlSchema>
52
+ /** Compact controls schema. When provided without workspace, the view creates the workspace internally. */
53
+ controls?: ControlSchema
54
+ /** Options passed to the internally generated useControlWorkspace() call. */
55
+ controlOptions?: ControlWorkspaceOptions
56
+ /** Initial values for the internally generated workspace. Merged over controlOptions.initialValues. */
57
+ initialValues?: Record<string, unknown>
58
+ /** External values for the internally generated workspace. Supports default v-model. */
59
+ modelValue?: Record<string, unknown>
60
+ /** External values for the internally generated workspace. Supports v-model:values. */
61
+ values?: Record<string, unknown>
62
+ /** AppTopBar title. */
63
+ title?: string
64
+ /** AppTopBar subtitle. */
65
+ subtitle?: string
66
+ /** AppTopBar visual variant. */
67
+ topBarVariant?: TopBarVariant
68
+ /** AppSidebar/AppLayout sidebar width. */
69
+ sidebarWidth?: string
70
+ /** AppSidebar visual preset. `analysis` matches the LEAF-style MINT analysis sidebar design language. */
71
+ sidebarVariant?: ControlWorkspaceSidebarVariant
72
+ /** Convert the sidebar into an SDK-owned mobile overlay below the AppLayout breakpoint. */
73
+ responsiveSidebar?: boolean
74
+ /** Sidebar position in AppLayout. */
75
+ sidebarPosition?: 'left' | 'right'
76
+ /** Optional AppSidebar chrome title for LEAF-style plugin workbenches. */
77
+ sidebarTitle?: string
78
+ /** Optional AppSidebar chrome subtitle for active experiment/run context. */
79
+ sidebarSubtitle?: string
80
+ /** Optional compact badge/count rendered in the AppSidebar chrome header. */
81
+ sidebarBadge?: string | number
82
+ /** Floating AppLayout style. */
83
+ floating?: boolean
84
+ /** Compact AppSidebar density. */
85
+ dense?: boolean
86
+ /** Whether AppTopBar should show generated settings. */
87
+ showSettings?: boolean
88
+ /** Render FormBuilder actions in the default content. */
89
+ showFormActions?: boolean
90
+ /** Runtime FormBuilder enhancements passed to generated forms. */
91
+ formEnhancements?: FormEnhancements<Record<string, unknown>>
92
+ /** Optional SDK component bindings exposed to the default slot with resolved props. */
93
+ componentBindings?: ControlComponentBindingsConfig
94
+ /** Optional mapping from workspace values to component props exposed to the default slot. */
95
+ componentProps?: ControlComponentPropsMap
96
+ /** Optional named mappings from workspace values to component props exposed to the default slot. */
97
+ componentPropsById?: ControlComponentPropsByIdMap
98
+ /** Loading/saving state passed to generated forms. */
99
+ formLoading?: boolean
100
+ /** Disabled state passed to generated forms. */
101
+ formDisabled?: boolean
102
+ /** Readonly state passed to generated forms. */
103
+ formReadonly?: boolean
104
+ /** FormBuilder size in the default content. */
105
+ formSize?: 'sm' | 'md' | 'lg'
106
+ }
107
+
108
+ const emit = defineEmits<{
109
+ /** Emitted when generated workspace values change through FormBuilder, AppSidebar, or AppTopBar settings. */
110
+ 'update:modelValue': [values: Record<string, unknown>]
111
+ /** Emitted when generated workspace values change through FormBuilder, AppSidebar, or AppTopBar settings. */
112
+ 'update:values': [values: Record<string, unknown>]
113
+ /** Forwarded from the default FormBuilder when showFormActions is enabled. */
114
+ submit: [values: Record<string, unknown>]
115
+ /** Forwarded from the default FormBuilder when showFormActions is enabled. */
116
+ cancel: []
117
+ }>()
118
+
119
+ defineSlots<{
120
+ default?: (props: ControlWorkspaceDefaultSlotProps) => unknown
121
+ topbar?: (props: ControlWorkspaceTopbarSlotProps) => unknown
122
+ sidebar?: (props: ControlWorkspaceSidebarSlotProps) => unknown
123
+ }>()
124
+
125
+ const props = withDefaults(defineProps<Props>(), {
126
+ model: undefined,
127
+ workspace: undefined,
128
+ controls: undefined,
129
+ controlOptions: () => ({}),
130
+ initialValues: undefined,
131
+ modelValue: undefined,
132
+ values: undefined,
133
+ title: 'Workspace',
134
+ subtitle: undefined,
135
+ topBarVariant: 'card',
136
+ sidebarWidth: '320px',
137
+ sidebarVariant: 'analysis',
138
+ responsiveSidebar: true,
139
+ sidebarPosition: 'left',
140
+ sidebarTitle: undefined,
141
+ sidebarSubtitle: undefined,
142
+ sidebarBadge: undefined,
143
+ floating: false,
144
+ dense: true,
145
+ showSettings: true,
146
+ showFormActions: false,
147
+ formEnhancements: undefined,
148
+ componentBindings: undefined,
149
+ componentProps: undefined,
150
+ componentPropsById: undefined,
151
+ formLoading: false,
152
+ formDisabled: false,
153
+ formReadonly: false,
154
+ formSize: 'md',
155
+ })
156
+
157
+ const externalValues = computed(() => props.modelValue ?? props.values)
158
+ const resolvedModel = computed<ControlModelBinding | undefined>(() => {
159
+ if (props.model === undefined) return undefined
160
+ return isControlModelBinding(props.model) ? props.model : defineControlModel(props.model)
161
+ })
162
+ const resolvedControls = computed<ControlSchema>(() => props.controls ?? resolvedModel.value?.controls ?? {})
163
+ const baseControlOptions = computed<ControlWorkspaceOptions>(() =>
164
+ mergeControlWorkspaceOptions(resolvedModel.value?.controlOptions ?? {}, props.controlOptions)
165
+ )
166
+
167
+ const resolvedControlOptions = computed<ControlWorkspaceOptions>(() => {
168
+ if (props.initialValues === undefined && externalValues.value === undefined) return baseControlOptions.value
169
+
170
+ return {
171
+ ...baseControlOptions.value,
172
+ initialValues: {
173
+ ...(baseControlOptions.value.initialValues ?? {}),
174
+ ...(props.initialValues ?? {}),
175
+ ...(externalValues.value ?? {}),
176
+ },
177
+ }
178
+ })
179
+
180
+ let generatedWorkspaceScope: EffectScope | undefined
181
+
182
+ function createGeneratedWorkspace(seedValues: Record<string, unknown> = {}) {
183
+ generatedWorkspaceScope?.stop()
184
+ generatedWorkspaceScope = effectScope()
185
+ return generatedWorkspaceScope.run(() =>
186
+ useControlWorkspace(resolvedControls.value, {
187
+ ...resolvedControlOptions.value,
188
+ initialValues: {
189
+ ...seedValues,
190
+ ...(resolvedControlOptions.value.initialValues ?? {}),
191
+ },
192
+ })
193
+ )!
194
+ }
195
+
196
+ const generatedWorkspace = shallowRef<UseControlWorkspaceReturn<ControlSchema>>(createGeneratedWorkspace())
197
+ const resolvedWorkspace = computed<UseControlWorkspaceReturn<ControlSchema>>(() => props.workspace ?? generatedWorkspace.value)
198
+ const resolvedComponentBindings = computed(() =>
199
+ resolvedWorkspace.value.getComponentBindings(props.componentBindings ?? resolvedModel.value?.componentBindings)
200
+ )
201
+ const resolvedComponentBindingsById = computed(() =>
202
+ resolvedWorkspace.value.getComponentBindingsById(props.componentBindings ?? resolvedModel.value?.componentBindings)
203
+ )
204
+ const resolvedComponentProps = computed(() =>
205
+ resolvedWorkspace.value.getComponentProps(props.componentProps ?? resolvedModel.value?.componentProps)
206
+ )
207
+ const resolvedComponentPropsById = computed(() =>
208
+ resolvedWorkspace.value.getComponentPropsById(props.componentPropsById ?? resolvedModel.value?.componentPropsById)
209
+ )
210
+ const resolvedBindings = computed<ResolvedControlWorkspace['bindings']>(() => ({
211
+ ...resolvedWorkspace.value.bindings,
212
+ componentBindings: resolvedComponentBindings,
213
+ componentBindingsById: resolvedComponentBindingsById,
214
+ componentProps: resolvedComponentProps,
215
+ componentPropsById: resolvedComponentPropsById,
216
+ }))
217
+ const resolvedTopBarSlot = computed(() => resolvedWorkspace.value.bindings.topBar.value)
218
+
219
+ watch(
220
+ [() => props.model, () => props.controls, () => props.controlOptions, () => props.initialValues],
221
+ () => {
222
+ const previousWorkspace = generatedWorkspace.value
223
+ const previousActiveView = previousWorkspace.activeView.value
224
+ generatedWorkspace.value = createGeneratedWorkspace({ ...previousWorkspace.values })
225
+ generatedWorkspace.value.setActiveView(previousActiveView)
226
+ },
227
+ { deep: true },
228
+ )
229
+
230
+ onScopeDispose(() => generatedWorkspaceScope?.stop())
231
+
232
+ watch(
233
+ externalValues,
234
+ (values) => {
235
+ if (values === undefined || props.workspace !== undefined) return
236
+ if (recordsEqual(generatedWorkspace.value.values, values)) return
237
+ generatedWorkspace.value.setValues(values)
238
+ },
239
+ { deep: true },
240
+ )
241
+
242
+ watch(
243
+ () => generatedWorkspace.value.values,
244
+ (values) => {
245
+ if (props.workspace !== undefined) return
246
+ const nextValues = { ...values }
247
+ if (externalValues.value !== undefined && recordsEqual(externalValues.value, nextValues)) return
248
+ emit('update:modelValue', nextValues)
249
+ emit('update:values', nextValues)
250
+ },
251
+ { deep: true },
252
+ )
253
+
254
+ function recordsEqual(left: Record<string, unknown>, right: Record<string, unknown>): boolean {
255
+ const leftKeys = Object.keys(left)
256
+ const rightKeys = Object.keys(right)
257
+ if (leftKeys.length !== rightKeys.length) return false
258
+ return leftKeys.every(key => valuesEqual(left[key], right[key]))
259
+ }
260
+
261
+ function valuesEqual(left: unknown, right: unknown): boolean {
262
+ const leftRaw = toRaw(left)
263
+ const rightRaw = toRaw(right)
264
+
265
+ if (Object.is(leftRaw, rightRaw)) return true
266
+
267
+ if (Array.isArray(leftRaw) || Array.isArray(rightRaw)) {
268
+ if (!Array.isArray(leftRaw) || !Array.isArray(rightRaw)) return false
269
+ if (leftRaw.length !== rightRaw.length) return false
270
+ return leftRaw.every((item, index) => valuesEqual(item, rightRaw[index]))
271
+ }
272
+
273
+ if (isPlainRecord(leftRaw) || isPlainRecord(rightRaw)) {
274
+ if (!isPlainRecord(leftRaw) || !isPlainRecord(rightRaw)) return false
275
+ return recordsEqual(leftRaw, rightRaw)
276
+ }
277
+
278
+ return false
279
+ }
280
+
281
+ function isPlainRecord(value: unknown): value is Record<string, unknown> {
282
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
283
+ }
284
+
285
+ function isControlModelBinding(model: ControlModel | ControlModelBinding): model is ControlModelBinding {
286
+ return 'controlOptions' in model
287
+ }
288
+ </script>
289
+
290
+ <template>
291
+ <AppLayout
292
+ class="mint-control-workspace-view"
293
+ :sidebar-position="sidebarPosition"
294
+ :sidebar-width="sidebarWidth"
295
+ :responsive-sidebar="responsiveSidebar"
296
+ :floating="floating"
297
+ >
298
+ <template #topbar>
299
+ <slot
300
+ name="topbar"
301
+ :workspace="resolvedWorkspace"
302
+ :bindings="resolvedBindings"
303
+ :top-bar="resolvedTopBarSlot"
304
+ >
305
+ <AppTopBar
306
+ :title="title"
307
+ :subtitle="subtitle"
308
+ :variant="topBarVariant"
309
+ :pill-nav="resolvedWorkspace.pillNav.items"
310
+ :current-pill-id="resolvedWorkspace.pillNav.currentItemId"
311
+ :show-settings="showSettings"
312
+ :settings-config="resolvedWorkspace.topBarSettings.settingsConfig"
313
+ @pill-select="resolvedWorkspace.pillNav.onSelect"
314
+ @settings-values-change="resolvedWorkspace.topBarSettings.onSettingsValuesChange"
315
+ />
316
+ </slot>
317
+ </template>
318
+
319
+ <template #sidebar>
320
+ <slot
321
+ name="sidebar"
322
+ :workspace="resolvedWorkspace"
323
+ :bindings="resolvedBindings"
324
+ :sidebar="resolvedWorkspace.sidebar"
325
+ >
326
+ <AppSidebar
327
+ v-bind="resolvedWorkspace.sidebar"
328
+ :title="sidebarTitle"
329
+ :subtitle="sidebarSubtitle"
330
+ :badge="sidebarBadge"
331
+ :variant="sidebarVariant"
332
+ :floating="false"
333
+ :dense="dense"
334
+ :width="sidebarWidth"
335
+ :form-enhancements="formEnhancements"
336
+ :form-loading="formLoading"
337
+ :form-disabled="formDisabled"
338
+ :form-readonly="formReadonly"
339
+ />
340
+ </slot>
341
+ </template>
342
+
343
+ <main class="mint-control-workspace-view__content">
344
+ <slot
345
+ :workspace="resolvedWorkspace"
346
+ :bindings="resolvedBindings"
347
+ :values="resolvedWorkspace.values"
348
+ :component-bindings="resolvedComponentBindings"
349
+ :component-bindings-by-id="resolvedComponentBindingsById"
350
+ :component-props="resolvedComponentProps"
351
+ :component-props-by-id="resolvedComponentPropsById"
352
+ >
353
+ <FormBuilder
354
+ v-bind="resolvedWorkspace.form"
355
+ :enhancements="formEnhancements"
356
+ :loading="formLoading"
357
+ :disabled="formDisabled"
358
+ :readonly="formReadonly"
359
+ :show-actions="showFormActions"
360
+ :size="formSize"
361
+ @submit="emit('submit', $event)"
362
+ @cancel="emit('cancel')"
363
+ />
364
+ </slot>
365
+ </main>
366
+ </AppLayout>
367
+ </template>
368
+
369
+ <style scoped>
370
+ .mint-control-workspace-view {
371
+ min-width: 0;
372
+ }
373
+
374
+ .mint-control-workspace-view__content {
375
+ min-width: 0;
376
+ padding: 1rem;
377
+ }
378
+ </style>
@@ -2,6 +2,9 @@
2
2
  /** Data table with sortable columns, search, pagination, and optional row selection. */
3
3
  import { ref, computed } from 'vue'
4
4
  import type { DataFrameColumn, SortState, PaginationState } from '../types'
5
+ import { useSortedItems } from '../composables/useSortedItems'
6
+ import { useTextSearch } from '../composables/useTextSearch'
7
+ import { useListSelection } from '../composables/useListSelection'
5
8
 
6
9
  /**
7
10
  * DataFrame - Data table with sorting, searching, pagination, and row selection.
@@ -114,43 +117,27 @@ function formatCell(col: DataFrameColumn, row: Record<string, unknown>, index: n
114
117
  return String(value)
115
118
  }
116
119
 
117
- // Filtering
118
- const filteredData = computed(() => {
119
- if (!props.searchable || !searchQuery.value.trim()) return props.data
120
- const query = searchQuery.value.toLowerCase()
121
- const keys = props.searchKeys ?? props.columns.map(c => c.key)
122
- return props.data.filter(row =>
123
- keys.some(key => {
124
- const val = getCellValue(row, key)
125
- return val !== null && val !== undefined && String(val).toLowerCase().includes(query)
126
- })
127
- )
120
+ const textSearch = useTextSearch({
121
+ items: () => props.data,
122
+ query: searchQuery,
123
+ enabled: () => props.searchable,
124
+ getText: (row) => {
125
+ const keys = props.searchKeys ?? props.columns.map(c => c.key)
126
+ return keys.map(key => getCellValue(row, key))
127
+ },
128
128
  })
129
-
130
- // Sorting
131
- const sortedData = computed(() => {
132
- const sort = activeSort.value
133
- if (!sort || !sort.direction) return filteredData.value
134
-
135
- const col = props.columns.find(c => c.key === sort.key)
136
- if (!col) return filteredData.value
137
-
138
- return [...filteredData.value].sort((a, b) => {
139
- const aVal = getCellValue(a, sort.key)
140
- const bVal = getCellValue(b, sort.key)
141
-
142
- if (aVal === null || aVal === undefined) return 1
143
- if (bVal === null || bVal === undefined) return -1
144
-
145
- let cmp = 0
146
- if (typeof aVal === 'number' && typeof bVal === 'number') {
147
- cmp = aVal - bVal
148
- } else {
149
- cmp = String(aVal).localeCompare(String(bVal))
150
- }
151
- return sort.direction === 'asc' ? cmp : -cmp
152
- })
129
+ const filteredData = textSearch.filteredItems
130
+
131
+ const tableSort = useSortedItems({
132
+ items: filteredData,
133
+ sort: activeSort,
134
+ enabled: () => {
135
+ const sort = activeSort.value
136
+ return Boolean(sort?.direction && props.columns.some(c => c.key === sort.key))
137
+ },
138
+ getValue: (row, key) => getCellValue(row, key),
153
139
  })
140
+ const sortedData = tableSort.sortedItems
154
141
 
155
142
  // Pagination
156
143
  const paginatedData = computed(() => {
@@ -199,11 +186,15 @@ function isColumnSortable(col: DataFrameColumn): boolean {
199
186
  }
200
187
 
201
188
  // Selection
189
+ const pageRowKeys = computed(() =>
190
+ paginatedData.value.map((row, i) => getRowKey(row, i))
191
+ )
192
+ const rowSelection = useListSelection({
193
+ selected: () => props.selectedKeys,
194
+ items: pageRowKeys,
195
+ })
202
196
  const allSelected = computed(() => {
203
- if (!props.selectable || paginatedData.value.length === 0) return false
204
- return paginatedData.value.every((row, i) =>
205
- props.selectedKeys.includes(getRowKey(row, i))
206
- )
197
+ return props.selectable && rowSelection.isAllSelected.value
207
198
  })
208
199
 
209
200
  const selectIndeterminate = computed(() => {
@@ -214,19 +205,12 @@ function toggleSelectAll() {
214
205
  if (allSelected.value) {
215
206
  emit('update:selectedKeys', [])
216
207
  } else {
217
- emit('update:selectedKeys', paginatedData.value.map((row, i) => getRowKey(row, i)))
208
+ emit('update:selectedKeys', rowSelection.itemValues.value)
218
209
  }
219
210
  }
220
211
 
221
212
  function toggleRowSelect(key: string | number) {
222
- const next = [...props.selectedKeys]
223
- const idx = next.indexOf(key)
224
- if (idx >= 0) {
225
- next.splice(idx, 1)
226
- } else {
227
- next.push(key)
228
- }
229
- emit('update:selectedKeys', next)
213
+ emit('update:selectedKeys', rowSelection.toggleValue(key))
230
214
  }
231
215
 
232
216
  const wrapperStyle = computed(() => {
@@ -325,7 +309,7 @@ const wrapperStyle = computed(() => {
325
309
  'mint-dataframe__row',
326
310
  {
327
311
  'mint-dataframe__row--striped': striped && rowIndex % 2 === 1,
328
- 'mint-dataframe__row--selected': selectedKeys.includes(getRowKey(row, rowIndex)),
312
+ 'mint-dataframe__row--selected': rowSelection.isSelected(getRowKey(row, rowIndex)),
329
313
  },
330
314
  ]"
331
315
  @click="emit('row-click', row, rowIndex)"
@@ -333,7 +317,7 @@ const wrapperStyle = computed(() => {
333
317
  <td v-if="selectable" class="mint-dataframe__td mint-dataframe__td--checkbox">
334
318
  <input
335
319
  type="checkbox"
336
- :checked="selectedKeys.includes(getRowKey(row, rowIndex))"
320
+ :checked="rowSelection.isSelected(getRowKey(row, rowIndex))"
337
321
  class="mint-dataframe__checkbox"
338
322
  @click.stop
339
323
  @change="toggleRowSelect(getRowKey(row, rowIndex))"