@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
@@ -1,6 +1,10 @@
1
1
  <script setup lang="ts">
2
2
  /** Input that opens a calendar dropdown for selecting a single date, with clearable support. */
3
- import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
3
+ import { ref, computed, watch } from 'vue'
4
+ import { useCalendarGrid, type CalendarGridDay } from '../composables/useCalendarGrid'
5
+ import { useDropdownState } from '../composables/useDropdownState'
6
+ import { useEventListener } from '../composables/useEventListener'
7
+ import CalendarGridPanelInternal from './internal/CalendarGridPanelInternal.vue'
4
8
 
5
9
  interface Props {
6
10
  modelValue?: string
@@ -24,12 +28,25 @@ const emit = defineEmits<{
24
28
  'update:modelValue': [value: string | undefined]
25
29
  }>()
26
30
 
27
- const isOpen = ref(false)
28
- const containerRef = ref<HTMLDivElement>()
29
- const inputRef = ref<HTMLDivElement>()
30
- const dropdownRef = ref<HTMLDivElement>()
31
+ const inputRef = ref<HTMLDivElement | null>(null)
32
+ const dropdownRef = ref<HTMLDivElement | null>(null)
31
33
  const dropdownStyle = ref<Record<string, string>>({})
32
- const currentMonth = ref(new Date())
34
+ const { isOpen, rootRef: containerRef, close, toggle } = useDropdownState({
35
+ insideRefs: [dropdownRef],
36
+ })
37
+ const {
38
+ weekDays,
39
+ monthYear,
40
+ calendarDays,
41
+ isDateDisabled,
42
+ formatDateValue,
43
+ setCurrentMonthFromDate,
44
+ prevMonth,
45
+ nextMonth,
46
+ } = useCalendarGrid({
47
+ min: () => props.min,
48
+ max: () => props.max,
49
+ })
33
50
 
34
51
  const selectedDate = computed(() => {
35
52
  if (!props.modelValue) return null
@@ -46,114 +63,29 @@ const displayValue = computed(() => {
46
63
  })
47
64
  })
48
65
 
49
- const monthYear = computed(() => {
50
- return currentMonth.value.toLocaleDateString('en-US', {
51
- year: 'numeric',
52
- month: 'long',
53
- })
54
- })
55
-
56
- const weekDays = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa']
57
-
58
- const calendarDays = computed(() => {
59
- const year = currentMonth.value.getFullYear()
60
- const month = currentMonth.value.getMonth()
61
-
62
- const firstDay = new Date(year, month, 1)
63
- const lastDay = new Date(year, month + 1, 0)
64
-
65
- const days: { date: Date; isCurrentMonth: boolean; isDisabled: boolean }[] = []
66
-
67
- // Previous month days
68
- const startPadding = firstDay.getDay()
69
- for (let i = startPadding - 1; i >= 0; i--) {
70
- const date = new Date(year, month, -i)
71
- days.push({ date, isCurrentMonth: false, isDisabled: isDateDisabled(date) })
72
- }
73
-
74
- // Current month days
75
- for (let i = 1; i <= lastDay.getDate(); i++) {
76
- const date = new Date(year, month, i)
77
- days.push({ date, isCurrentMonth: true, isDisabled: isDateDisabled(date) })
78
- }
79
-
80
- // Next month days
81
- const endPadding = 42 - days.length
82
- for (let i = 1; i <= endPadding; i++) {
83
- const date = new Date(year, month + 1, i)
84
- days.push({ date, isCurrentMonth: false, isDisabled: isDateDisabled(date) })
85
- }
86
-
87
- return days
88
- })
89
-
90
- function isDateDisabled(date: Date): boolean {
91
- if (props.min) {
92
- const minDate = new Date(props.min + 'T00:00:00')
93
- if (date < minDate) return true
94
- }
95
- if (props.max) {
96
- const maxDate = new Date(props.max + 'T00:00:00')
97
- if (date > maxDate) return true
98
- }
99
- return false
100
- }
101
-
102
- function isSameDay(date1: Date, date2: Date | null): boolean {
103
- if (!date2) return false
104
- return date1.toDateString() === date2.toDateString()
105
- }
106
-
107
- function isToday(date: Date): boolean {
108
- return date.toDateString() === new Date().toDateString()
109
- }
110
-
111
- function formatDateValue(date: Date): string {
112
- const year = date.getFullYear()
113
- const month = String(date.getMonth() + 1).padStart(2, '0')
114
- const day = String(date.getDate()).padStart(2, '0')
115
- return `${year}-${month}-${day}`
116
- }
117
-
118
- function selectDate(day: { date: Date; isDisabled: boolean }) {
66
+ function selectDate(day: CalendarGridDay) {
119
67
  if (day.isDisabled || props.disabled) return
120
68
  emit('update:modelValue', formatDateValue(day.date))
121
- isOpen.value = false
122
- }
123
-
124
- function prevMonth() {
125
- currentMonth.value = new Date(
126
- currentMonth.value.getFullYear(),
127
- currentMonth.value.getMonth() - 1,
128
- 1
129
- )
130
- }
131
-
132
- function nextMonth() {
133
- currentMonth.value = new Date(
134
- currentMonth.value.getFullYear(),
135
- currentMonth.value.getMonth() + 1,
136
- 1
137
- )
69
+ close()
138
70
  }
139
71
 
140
72
  function goToToday() {
141
73
  const today = new Date()
142
- currentMonth.value = new Date(today.getFullYear(), today.getMonth(), 1)
74
+ setCurrentMonthFromDate(today)
143
75
  if (!isDateDisabled(today)) {
144
76
  emit('update:modelValue', formatDateValue(today))
145
- isOpen.value = false
77
+ close()
146
78
  }
147
79
  }
148
80
 
149
81
  function clear() {
150
82
  emit('update:modelValue', undefined)
151
- isOpen.value = false
83
+ close()
152
84
  }
153
85
 
154
86
  function toggleCalendar() {
155
87
  if (props.disabled) return
156
- isOpen.value = !isOpen.value
88
+ toggle()
157
89
  }
158
90
 
159
91
  function updateDropdownPosition() {
@@ -168,41 +100,21 @@ function updateDropdownPosition() {
168
100
  }
169
101
  }
170
102
 
171
- function handleClickOutside(event: MouseEvent) {
172
- const target = event.target as Node
173
- if (containerRef.value?.contains(target)) return
174
- if (dropdownRef.value?.contains(target)) return
175
- isOpen.value = false
176
- }
177
-
178
103
  function handleScrollOrResize() {
179
- if (isOpen.value) isOpen.value = false
104
+ close()
180
105
  }
181
106
 
182
107
  watch(isOpen, (open) => {
183
108
  if (open) {
184
109
  updateDropdownPosition()
185
110
  if (selectedDate.value) {
186
- currentMonth.value = new Date(
187
- selectedDate.value.getFullYear(),
188
- selectedDate.value.getMonth(),
189
- 1
190
- )
111
+ setCurrentMonthFromDate(selectedDate.value)
191
112
  }
192
113
  }
193
114
  })
194
115
 
195
- onMounted(() => {
196
- document.addEventListener('click', handleClickOutside)
197
- window.addEventListener('scroll', handleScrollOrResize, true)
198
- window.addEventListener('resize', handleScrollOrResize)
199
- })
200
-
201
- onUnmounted(() => {
202
- document.removeEventListener('click', handleClickOutside)
203
- window.removeEventListener('scroll', handleScrollOrResize, true)
204
- window.removeEventListener('resize', handleScrollOrResize)
205
- })
116
+ useEventListener(() => window, 'scroll', handleScrollOrResize, true)
117
+ useEventListener(() => window, 'resize', handleScrollOrResize)
206
118
  </script>
207
119
 
208
120
  <template>
@@ -247,79 +159,34 @@ onUnmounted(() => {
247
159
  aria-modal="true"
248
160
  aria-label="Date picker"
249
161
  >
250
- <div class="mint-date-picker__header">
251
- <button
252
- type="button"
253
- aria-label="Previous month"
254
- class="mint-date-picker__nav-btn"
255
- @click="prevMonth"
256
- >
257
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
258
- <path d="m15 18-6-6 6-6" />
259
- </svg>
260
- </button>
261
- <span class="mint-date-picker__month-year">{{ monthYear }}</span>
262
- <button
263
- type="button"
264
- aria-label="Next month"
265
- class="mint-date-picker__nav-btn"
266
- @click="nextMonth"
267
- >
268
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
269
- <path d="m9 18 6-6-6-6" />
270
- </svg>
271
- </button>
272
- </div>
273
-
274
- <div class="mint-date-picker__weekdays">
275
- <div
276
- v-for="day in weekDays"
277
- :key="day"
278
- class="mint-date-picker__weekday"
279
- >
280
- {{ day }}
162
+ <CalendarGridPanelInternal
163
+ :week-days="weekDays"
164
+ :month-year="monthYear"
165
+ :days="calendarDays"
166
+ :selected-date="selectedDate"
167
+ @previous-month="prevMonth"
168
+ @next-month="nextMonth"
169
+ @select="selectDate"
170
+ />
171
+
172
+ <div class="mint-date-picker__footer">
173
+ <button
174
+ type="button"
175
+ class="mint-date-picker__footer-btn mint-date-picker__today-btn"
176
+ @click="goToToday"
177
+ >
178
+ Today
179
+ </button>
180
+ <button
181
+ v-if="clearable && modelValue"
182
+ type="button"
183
+ class="mint-date-picker__footer-btn mint-date-picker__clear-btn"
184
+ @click="clear"
185
+ >
186
+ Clear
187
+ </button>
281
188
  </div>
282
189
  </div>
283
-
284
- <div class="mint-date-picker__grid">
285
- <button
286
- v-for="(day, index) in calendarDays"
287
- :key="index"
288
- type="button"
289
- :disabled="day.isDisabled"
290
- :aria-label="day.date.toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })"
291
- :aria-selected="isSameDay(day.date, selectedDate)"
292
- :class="[
293
- 'mint-date-picker__day',
294
- !day.isCurrentMonth ? 'mint-date-picker__day--other-month' : '',
295
- day.isDisabled ? 'mint-date-picker__day--disabled' : '',
296
- isSameDay(day.date, selectedDate) ? 'mint-date-picker__day--selected' : '',
297
- isToday(day.date) && !isSameDay(day.date, selectedDate) ? 'mint-date-picker__day--today' : '',
298
- ]"
299
- @click="selectDate(day)"
300
- >
301
- {{ day.date.getDate() }}
302
- </button>
303
- </div>
304
-
305
- <div class="mint-date-picker__footer">
306
- <button
307
- type="button"
308
- class="mint-date-picker__footer-btn mint-date-picker__today-btn"
309
- @click="goToToday"
310
- >
311
- Today
312
- </button>
313
- <button
314
- v-if="clearable && modelValue"
315
- type="button"
316
- class="mint-date-picker__footer-btn mint-date-picker__clear-btn"
317
- @click="clear"
318
- >
319
- Clear
320
- </button>
321
- </div>
322
- </div>
323
190
  </Transition>
324
191
  </Teleport>
325
192
  </div>
@@ -1,7 +1,10 @@
1
1
  <script setup lang="ts">
2
2
  /** Combined date and time picker with a dropdown calendar, time slots, and 12/24 h format support. */
3
- import { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'
4
- import { generateTimeSlots, formatTime, parseTime } from '../composables/useTimeUtils'
3
+ import { computed, watch, nextTick } from 'vue'
4
+ import { useCalendarGrid, type CalendarGridDay } from '../composables/useCalendarGrid'
5
+ import { useDropdownState } from '../composables/useDropdownState'
6
+ import { formatTime, formatTimeSlot, generateTimeSlots, toMinutes } from '../composables/useTimeUtils'
7
+ import CalendarGridPanelInternal from './internal/CalendarGridPanelInternal.vue'
5
8
 
6
9
  interface Props {
7
10
  modelValue?: string
@@ -32,8 +35,20 @@ const emit = defineEmits<{
32
35
  'update:modelValue': [value: string | undefined]
33
36
  }>()
34
37
 
35
- const isOpen = ref(false)
36
- const containerRef = ref<HTMLDivElement>()
38
+ const { isOpen, rootRef, close, toggle } = useDropdownState()
39
+ const {
40
+ weekDays,
41
+ monthYear,
42
+ calendarDays,
43
+ formatDateValue,
44
+ setCurrentMonthFromDate,
45
+ prevMonth,
46
+ nextMonth,
47
+ } = useCalendarGrid({
48
+ min: () => props.min,
49
+ max: () => props.max,
50
+ locale: () => props.locale,
51
+ })
37
52
 
38
53
  // Parse model value into date and time parts
39
54
  const selectedDate = computed(() => {
@@ -44,10 +59,7 @@ const selectedDate = computed(() => {
44
59
 
45
60
  const selectedDateStr = computed(() => {
46
61
  if (!selectedDate.value) return null
47
- const y = selectedDate.value.getFullYear()
48
- const m = String(selectedDate.value.getMonth() + 1).padStart(2, '0')
49
- const d = String(selectedDate.value.getDate()).padStart(2, '0')
50
- return `${y}-${m}-${d}`
62
+ return formatDateValue(selectedDate.value)
51
63
  })
52
64
 
53
65
  const selectedTimeStr = computed(() => {
@@ -70,196 +82,89 @@ const displayValue = computed(() => {
70
82
  return `${dateStr} ${timeStr}`
71
83
  })
72
84
 
73
- // Calendar state
74
- const currentMonth = ref(new Date())
75
- const weekDays = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa']
76
-
77
- const calendarDays = computed(() => {
78
- const year = currentMonth.value.getFullYear()
79
- const month = currentMonth.value.getMonth()
80
- const firstDay = new Date(year, month, 1)
81
- const lastDay = new Date(year, month + 1, 0)
82
-
83
- const days: { date: Date; isCurrentMonth: boolean; isDisabled: boolean }[] = []
84
-
85
- const startPadding = firstDay.getDay()
86
- for (let i = startPadding - 1; i >= 0; i--) {
87
- const date = new Date(year, month, -i)
88
- days.push({ date, isCurrentMonth: false, isDisabled: isDateDisabled(date) })
89
- }
90
-
91
- for (let i = 1; i <= lastDay.getDate(); i++) {
92
- const date = new Date(year, month, i)
93
- days.push({ date, isCurrentMonth: true, isDisabled: isDateDisabled(date) })
94
- }
95
-
96
- const endPadding = 42 - days.length
97
- for (let i = 1; i <= endPadding; i++) {
98
- const date = new Date(year, month + 1, i)
99
- days.push({ date, isCurrentMonth: false, isDisabled: isDateDisabled(date) })
100
- }
101
-
102
- return days
103
- })
104
-
105
85
  // Time slots
106
86
  const timeSlots = computed(() => {
107
87
  return generateTimeSlots('00:00', '23:59', props.timeStep)
108
88
  })
109
89
 
110
- const monthYear = computed(() => {
111
- return currentMonth.value.toLocaleDateString(props.locale, {
112
- year: 'numeric',
113
- month: 'long',
114
- })
115
- })
116
-
117
- function isDateDisabled(date: Date): boolean {
118
- if (props.min) {
119
- const minDate = new Date(props.min)
120
- minDate.setHours(0, 0, 0, 0)
121
- const check = new Date(date)
122
- check.setHours(0, 0, 0, 0)
123
- if (check < minDate) return true
124
- }
125
- if (props.max) {
126
- const maxDate = new Date(props.max)
127
- maxDate.setHours(23, 59, 59, 999)
128
- const check = new Date(date)
129
- check.setHours(23, 59, 59, 999)
130
- if (check > maxDate) return true
131
- }
132
- return false
133
- }
134
-
135
90
  function isTimeDisabled(time: string): boolean {
136
91
  if (!selectedDateStr.value) return false
137
- const { hour, minute } = parseTime(time)
92
+ const timeMinutes = toMinutes(time)
138
93
 
139
94
  if (props.min) {
140
95
  const minDate = new Date(props.min)
141
- if (selectedDateStr.value === formatDateStr(minDate)) {
96
+ if (selectedDateStr.value === formatDateValue(minDate)) {
142
97
  const minMin = minDate.getHours() * 60 + minDate.getMinutes()
143
- if (hour * 60 + minute < minMin) return true
98
+ if (timeMinutes < minMin) return true
144
99
  }
145
100
  }
146
101
  if (props.max) {
147
102
  const maxDate = new Date(props.max)
148
- if (selectedDateStr.value === formatDateStr(maxDate)) {
103
+ if (selectedDateStr.value === formatDateValue(maxDate)) {
149
104
  const maxMin = maxDate.getHours() * 60 + maxDate.getMinutes()
150
- if (hour * 60 + minute > maxMin) return true
105
+ if (timeMinutes > maxMin) return true
151
106
  }
152
107
  }
153
108
  return false
154
109
  }
155
110
 
156
- function formatDateStr(d: Date): string {
157
- const y = d.getFullYear()
158
- const m = String(d.getMonth() + 1).padStart(2, '0')
159
- const day = String(d.getDate()).padStart(2, '0')
160
- return `${y}-${m}-${day}`
161
- }
162
-
163
- function isSameDay(a: Date, b: Date | null): boolean {
164
- if (!b) return false
165
- return a.toDateString() === b.toDateString()
166
- }
167
-
168
- function isToday(date: Date): boolean {
169
- return date.toDateString() === new Date().toDateString()
170
- }
171
-
172
- function selectDate(day: { date: Date; isDisabled: boolean }) {
111
+ function selectDate(day: CalendarGridDay) {
173
112
  if (day.isDisabled || props.disabled) return
174
- const dateStr = formatDateStr(day.date)
113
+ const dateStr = formatDateValue(day.date)
175
114
  const timeStr = selectedTimeStr.value || '09:00'
176
115
  emit('update:modelValue', `${dateStr}T${timeStr}`)
177
116
  }
178
117
 
179
118
  function selectTime(time: string) {
180
119
  if (isTimeDisabled(time)) return
181
- const dateStr = selectedDateStr.value || formatDateStr(new Date())
120
+ const dateStr = selectedDateStr.value || formatDateValue(new Date())
182
121
  emit('update:modelValue', `${dateStr}T${time}`)
183
122
  }
184
123
 
185
- function prevMonth() {
186
- currentMonth.value = new Date(
187
- currentMonth.value.getFullYear(),
188
- currentMonth.value.getMonth() - 1,
189
- 1,
190
- )
191
- }
192
-
193
- function nextMonth() {
194
- currentMonth.value = new Date(
195
- currentMonth.value.getFullYear(),
196
- currentMonth.value.getMonth() + 1,
197
- 1,
198
- )
199
- }
200
-
201
124
  function goToNow() {
202
125
  const now = new Date()
203
- currentMonth.value = new Date(now.getFullYear(), now.getMonth(), 1)
204
- const dateStr = formatDateStr(now)
126
+ setCurrentMonthFromDate(now)
127
+ const dateStr = formatDateValue(now)
205
128
  const timeStr = formatTime(now.getHours(), now.getMinutes())
206
129
  emit('update:modelValue', `${dateStr}T${timeStr}`)
207
- isOpen.value = false
130
+ close()
208
131
  }
209
132
 
210
133
  function goToToday() {
211
134
  const today = new Date()
212
- currentMonth.value = new Date(today.getFullYear(), today.getMonth(), 1)
213
- const dateStr = formatDateStr(today)
135
+ setCurrentMonthFromDate(today)
136
+ const dateStr = formatDateValue(today)
214
137
  const timeStr = selectedTimeStr.value || '09:00'
215
138
  emit('update:modelValue', `${dateStr}T${timeStr}`)
216
139
  }
217
140
 
218
141
  function clear() {
219
142
  emit('update:modelValue', undefined)
220
- isOpen.value = false
143
+ close()
221
144
  }
222
145
 
223
146
  function toggleDropdown() {
224
147
  if (props.disabled) return
225
- isOpen.value = !isOpen.value
226
- }
227
-
228
- function handleClickOutside(event: MouseEvent) {
229
- if (containerRef.value && !containerRef.value.contains(event.target as Node)) {
230
- isOpen.value = false
231
- }
148
+ toggle()
232
149
  }
233
150
 
234
151
  watch(isOpen, (open) => {
235
152
  if (open && selectedDate.value) {
236
- currentMonth.value = new Date(
237
- selectedDate.value.getFullYear(),
238
- selectedDate.value.getMonth(),
239
- 1,
240
- )
153
+ setCurrentMonthFromDate(selectedDate.value)
241
154
  nextTick(() => {
242
155
  // Scroll time grid to selected time
243
- const grid = containerRef.value?.querySelector('.mint-datetime-picker__time-grid')
244
- const active = containerRef.value?.querySelector('.mint-datetime-picker__time-chip--active')
156
+ const grid = rootRef.value?.querySelector('.mint-datetime-picker__time-grid')
157
+ const active = rootRef.value?.querySelector('.mint-datetime-picker__time-chip--active')
245
158
  if (grid && active) {
246
159
  active.scrollIntoView({ block: 'center' })
247
160
  }
248
161
  })
249
162
  }
250
163
  })
251
-
252
- onMounted(() => {
253
- document.addEventListener('click', handleClickOutside)
254
- })
255
-
256
- onUnmounted(() => {
257
- document.removeEventListener('click', handleClickOutside)
258
- })
259
164
  </script>
260
165
 
261
166
  <template>
262
- <div ref="containerRef" class="mint-datetime-picker">
167
+ <div ref="rootRef" class="mint-datetime-picker">
263
168
  <div class="mint-datetime-picker__input-wrapper">
264
169
  <div class="mint-datetime-picker__icon-calendar">
265
170
  <svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -305,42 +210,16 @@ onUnmounted(() => {
305
210
  >
306
211
  <!-- Calendar section -->
307
212
  <div class="mint-datetime-picker__calendar-section">
308
- <div class="mint-date-picker__header">
309
- <button type="button" class="mint-date-picker__nav-btn" aria-label="Previous month" @click="prevMonth">
310
- <svg fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
311
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
312
- </svg>
313
- </button>
314
- <span class="mint-date-picker__month-year">{{ monthYear }}</span>
315
- <button type="button" class="mint-date-picker__nav-btn" aria-label="Next month" @click="nextMonth">
316
- <svg fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
317
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
318
- </svg>
319
- </button>
320
- </div>
321
-
322
- <div class="mint-date-picker__weekdays">
323
- <div v-for="day in weekDays" :key="day" class="mint-date-picker__weekday">{{ day }}</div>
324
- </div>
325
-
326
- <div class="mint-date-picker__grid">
327
- <button
328
- v-for="(day, index) in calendarDays"
329
- :key="index"
330
- type="button"
331
- :disabled="day.isDisabled"
332
- :class="[
333
- 'mint-date-picker__day',
334
- !day.isCurrentMonth ? 'mint-date-picker__day--other-month' : '',
335
- day.isDisabled ? 'mint-date-picker__day--disabled' : '',
336
- isSameDay(day.date, selectedDate) ? 'mint-date-picker__day--selected' : '',
337
- isToday(day.date) && !isSameDay(day.date, selectedDate) ? 'mint-date-picker__day--today' : '',
338
- ]"
339
- @click="selectDate(day)"
340
- >
341
- {{ day.date.getDate() }}
342
- </button>
343
- </div>
213
+ <CalendarGridPanelInternal
214
+ :week-days="weekDays"
215
+ :month-year="monthYear"
216
+ :days="calendarDays"
217
+ :selected-date="selectedDate"
218
+ :locale="locale"
219
+ @previous-month="prevMonth"
220
+ @next-month="nextMonth"
221
+ @select="selectDate"
222
+ />
344
223
  </div>
345
224
 
346
225
  <!-- Divider -->
@@ -362,7 +241,7 @@ onUnmounted(() => {
362
241
  ]"
363
242
  @click="selectTime(time)"
364
243
  >
365
- {{ timeFormat === '12h' ? formatTime(parseTime(time).hour, parseTime(time).minute, '12h') : time }}
244
+ {{ formatTimeSlot(time, timeFormat) }}
366
245
  </button>
367
246
  </div>
368
247
  </div>