@morscherlab/mint-sdk 1.0.0-beta.3 → 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 (165) hide show
  1. package/README.md +9 -2
  2. package/dist/__tests__/composables/experiment-utils.test.d.ts +1 -0
  3. package/dist/__tests__/composables/useApi.test.d.ts +1 -0
  4. package/dist/components/AppContainer.vue.d.ts +1 -1
  5. package/dist/components/AppLayout.vue.d.ts +20 -1
  6. package/dist/components/AppSidebar.vue.d.ts +56 -4
  7. package/dist/components/AppTopBar.vue.d.ts +7 -25
  8. package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +3 -1
  9. package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +1 -0
  10. package/dist/components/BioTemplatePresetWorkspaceView.vue.d.ts +5 -0
  11. package/dist/components/ComponentBindingRenderer.vue.d.ts +44 -0
  12. package/dist/components/ControlWorkspaceView.vue.d.ts +24 -7
  13. package/dist/components/DoseDesignWorkspaceView.vue.d.ts +149 -0
  14. package/dist/components/ExperimentTimeline.vue.d.ts +1 -1
  15. package/dist/components/FormBuilder.vue.d.ts +9 -9
  16. package/dist/components/PlateMapEditor.vue.d.ts +1 -1
  17. package/dist/components/PluginWorkspaceView.vue.d.ts +310 -0
  18. package/dist/components/SettingsModal.vue.d.ts +1 -1
  19. package/dist/components/WellPlate.vue.d.ts +2 -2
  20. package/dist/components/index.d.ts +3 -12
  21. package/dist/components/index.js +3 -3
  22. package/dist/components/{AppPageSelector.vue.d.ts → internal/AppPageSelectorInternal.vue.d.ts} +1 -1
  23. package/dist/components/{AppPillNav.vue.d.ts → internal/AppPillNavInternal.vue.d.ts} +3 -1
  24. package/dist/components/{CalendarGridPanel.vue.d.ts → internal/CalendarGridPanelInternal.vue.d.ts} +1 -1
  25. package/dist/components/internal/FormSectionRenderer.vue.d.ts +4 -4
  26. package/dist/components/{WellEditPopup.vue.d.ts → internal/WellEditPopupInternal.vue.d.ts} +1 -1
  27. package/dist/{components-D_Sr0adg.js → components-BkGF4B4y.js} +4484 -3967
  28. package/dist/components-BkGF4B4y.js.map +1 -0
  29. package/dist/composables/experiment-utils.d.ts +8 -0
  30. package/dist/composables/index.d.ts +5 -7
  31. package/dist/composables/index.js +4 -4
  32. package/dist/composables/useAppExperiment.d.ts +31 -2
  33. package/dist/composables/useBioTemplateComponents.d.ts +5 -3
  34. package/dist/composables/useBioTemplatePackWorkspace.d.ts +3 -2
  35. package/dist/composables/useBioTemplatePresetWorkspace.d.ts +6 -5
  36. package/dist/composables/useBioTemplateWorkspace.d.ts +5 -4
  37. package/dist/composables/useControlSchema.d.ts +43 -21
  38. package/dist/composables/usePluginClient.d.ts +5 -2
  39. package/dist/{composables-C3dpXQN5.js → composables-CHsME9H1.js} +40 -28
  40. package/dist/composables-CHsME9H1.js.map +1 -0
  41. package/dist/index.d.ts +5 -12
  42. package/dist/index.js +5 -5
  43. package/dist/install.js +2 -2
  44. package/dist/styles.css +3625 -3651
  45. package/dist/templates/componentBindings.d.ts +13 -0
  46. package/dist/templates/index.d.ts +3 -3
  47. package/dist/templates/index.js +2 -2
  48. package/dist/{templates-50NPjaxL.js → templates-B5jmTWuk.js} +111 -56
  49. package/dist/templates-B5jmTWuk.js.map +1 -0
  50. package/dist/types/components.d.ts +6 -25
  51. package/dist/types/index.d.ts +1 -1
  52. package/dist/{useScheduleDrag-D4oWdh41.js → useScheduleDrag-BgzpQT53.js} +160 -117
  53. package/dist/useScheduleDrag-BgzpQT53.js.map +1 -0
  54. package/package.json +1 -1
  55. package/src/__tests__/components/ActionItem.test.ts +6 -6
  56. package/src/__tests__/components/AppLayout.test.ts +44 -0
  57. package/src/__tests__/components/AppPageSelector.test.ts +8 -8
  58. package/src/__tests__/components/AppPillNav.test.ts +53 -6
  59. package/src/__tests__/components/AppSidebar.test.ts +126 -0
  60. package/src/__tests__/components/AppToastContainer.test.ts +0 -11
  61. package/src/__tests__/components/AppTopBar.test.ts +182 -119
  62. package/src/__tests__/components/BioTemplateExperimentWorkspaceView.test.ts +7 -1
  63. package/src/__tests__/components/BioTemplatePackWorkspaceView.test.ts +15 -1
  64. package/src/__tests__/components/BioTemplatePresetWorkspaceView.test.ts +26 -1
  65. package/src/__tests__/components/CalendarGridPanel.test.ts +3 -3
  66. package/src/__tests__/components/ComponentBindingRenderer.test.ts +161 -0
  67. package/src/__tests__/components/ControlWorkspaceView.test.ts +134 -63
  68. package/src/__tests__/components/DateTimePicker.test.ts +2 -2
  69. package/src/__tests__/components/DoseDesignWorkspaceView.test.ts +185 -0
  70. package/src/__tests__/components/PluginWorkspaceView.test.ts +548 -0
  71. package/src/__tests__/composables/experiment-utils.test.ts +30 -0
  72. package/src/__tests__/composables/useApi.test.ts +30 -0
  73. package/src/__tests__/composables/useAppExperiment.test.ts +100 -1
  74. package/src/__tests__/composables/useBioTemplatePackWorkspace.test.ts +6 -3
  75. package/src/__tests__/composables/useBioTemplatePresetWorkspace.test.ts +6 -6
  76. package/src/__tests__/composables/useBioTemplateWorkspace.test.ts +6 -1
  77. package/src/__tests__/composables/useControlSchema.test.ts +150 -36
  78. package/src/__tests__/composables/usePluginClient.test.ts +99 -2
  79. package/src/__tests__/docs/frontendDocsCatalog.test.ts +120 -25
  80. package/src/__tests__/templates/templates.test.ts +12 -0
  81. package/src/components/AppAvatarMenu.vue +3 -3
  82. package/src/components/AppLayout.story.vue +39 -0
  83. package/src/components/AppLayout.vue +83 -2
  84. package/src/components/AppPluginSwitcher.vue +5 -5
  85. package/src/components/AppSidebar.story.vue +113 -5
  86. package/src/components/AppSidebar.vue +144 -24
  87. package/src/components/AppTopBar.story.vue +2 -5
  88. package/src/components/AppTopBar.vue +35 -425
  89. package/src/components/BioTemplateExperimentWorkspaceView.story.vue +2 -2
  90. package/src/components/BioTemplateExperimentWorkspaceView.vue +6 -0
  91. package/src/components/BioTemplatePackWorkspaceView.story.vue +4 -4
  92. package/src/components/BioTemplatePackWorkspaceView.vue +1 -0
  93. package/src/components/BioTemplatePresetWorkspaceView.story.vue +14 -2
  94. package/src/components/BioTemplatePresetWorkspaceView.vue +11 -2
  95. package/src/components/BioTemplateRenderer.vue +15 -227
  96. package/src/components/ComponentBindingRenderer.story.vue +57 -0
  97. package/src/components/ComponentBindingRenderer.vue +308 -0
  98. package/src/components/ControlWorkspaceView.story.vue +20 -9
  99. package/src/components/ControlWorkspaceView.vue +43 -12
  100. package/src/components/DatePicker.vue +2 -2
  101. package/src/components/DateTimePicker.vue +2 -2
  102. package/src/components/DoseDesignWorkspaceView.story.vue +77 -0
  103. package/src/components/DoseDesignWorkspaceView.vue +255 -0
  104. package/src/components/ExperimentPopover.vue +2 -6
  105. package/src/components/ExperimentSelectorModal.vue +6 -5
  106. package/src/components/FormBuilder.story.vue +190 -0
  107. package/src/components/PluginWorkspaceView.story.vue +334 -0
  108. package/src/components/PluginWorkspaceView.vue +708 -0
  109. package/src/components/SettingsModal.story.vue +87 -0
  110. package/src/components/WellPlate.vue +2 -2
  111. package/src/components/index.ts +3 -12
  112. package/src/components/{AppPageSelector.vue → internal/AppPageSelectorInternal.vue} +9 -9
  113. package/src/components/internal/AppPillNavInternal.vue +194 -0
  114. package/src/components/{CalendarGridPanel.vue → internal/CalendarGridPanelInternal.vue} +1 -1
  115. package/src/components/{WellEditPopup.vue → internal/WellEditPopupInternal.vue} +3 -3
  116. package/src/composables/experiment-utils.ts +26 -0
  117. package/src/composables/index.ts +21 -7
  118. package/src/composables/useApi.ts +9 -2
  119. package/src/composables/useAppExperiment.ts +85 -13
  120. package/src/composables/useBioTemplateComponents.ts +12 -0
  121. package/src/composables/useBioTemplatePackWorkspace.ts +6 -2
  122. package/src/composables/useBioTemplatePresetWorkspace.ts +10 -21
  123. package/src/composables/useBioTemplateWorkspace.ts +6 -4
  124. package/src/composables/useControlSchema.ts +157 -69
  125. package/src/composables/usePluginClient.ts +50 -9
  126. package/src/index.ts +6 -563
  127. package/src/styles/components/app-layout.css +82 -0
  128. package/src/styles/components/app-pill-nav.css +70 -0
  129. package/src/styles/components/app-sidebar.css +119 -0
  130. package/src/styles/components/app-top-bar.css +0 -235
  131. package/src/styles/index.css +0 -1
  132. package/src/templates/componentBindings.ts +38 -0
  133. package/src/templates/index.ts +4 -0
  134. package/src/types/components.ts +6 -31
  135. package/src/types/index.ts +2 -6
  136. package/dist/__tests__/composables/usePluginApi.test.d.ts +0 -13
  137. package/dist/components/FormFieldRenderer.vue.d.ts +0 -28
  138. package/dist/components/FormSection.vue.d.ts +0 -30
  139. package/dist/components/GroupingModal.vue.d.ts +0 -12
  140. package/dist/components/SettingsButton.vue.d.ts +0 -30
  141. package/dist/components/ToastNotification.vue.d.ts +0 -2
  142. package/dist/components-D_Sr0adg.js.map +0 -1
  143. package/dist/composables/usePluginApi.d.ts +0 -22
  144. package/dist/composables-C3dpXQN5.js.map +0 -1
  145. package/dist/templates-50NPjaxL.js.map +0 -1
  146. package/dist/useScheduleDrag-D4oWdh41.js.map +0 -1
  147. package/src/__tests__/components/FormCompatibility.test.ts +0 -94
  148. package/src/__tests__/components/GroupingModal.test.ts +0 -73
  149. package/src/__tests__/components/SettingsButton.test.ts +0 -44
  150. package/src/__tests__/composables/usePluginApi.test.ts +0 -81
  151. package/src/components/AppPillNav.vue +0 -71
  152. package/src/components/FormFieldRenderer.vue +0 -35
  153. package/src/components/FormSection.vue +0 -37
  154. package/src/components/GroupingModal.story.vue +0 -52
  155. package/src/components/GroupingModal.vue +0 -61
  156. package/src/components/SettingsButton.story.vue +0 -58
  157. package/src/components/SettingsButton.vue +0 -64
  158. package/src/components/ToastNotification.vue +0 -9
  159. package/src/composables/usePluginApi.ts +0 -32
  160. package/src/styles/components/settings-button.css +0 -31
  161. /package/dist/__tests__/components/{FormCompatibility.test.d.ts → ComponentBindingRenderer.test.d.ts} +0 -0
  162. /package/dist/__tests__/components/{GroupingModal.test.d.ts → DoseDesignWorkspaceView.test.d.ts} +0 -0
  163. /package/dist/__tests__/components/{SettingsButton.test.d.ts → PluginWorkspaceView.test.d.ts} +0 -0
  164. /package/dist/components/{ActionItem.vue.d.ts → internal/ActionItemInternal.vue.d.ts} +0 -0
  165. /package/src/components/{ActionItem.vue → internal/ActionItemInternal.vue} +0 -0
@@ -58,37 +58,15 @@ export interface CollapsibleState {
58
58
  close: () => void;
59
59
  }
60
60
  export type TopBarVariant = 'card' | 'default';
61
- export interface TopBarPage {
61
+ export interface PillNavOption {
62
62
  id: string;
63
63
  label: string;
64
64
  to?: string;
65
65
  href?: string;
66
- icon?: string;
67
66
  description?: string;
68
67
  disabled?: boolean;
69
68
  }
70
- export type TopBarPageInput = TopBarPage | string;
71
- export interface TopBarTab {
72
- id: string;
73
- label: string;
74
- to?: string;
75
- href?: string;
76
- icon?: string;
77
- disabled?: boolean;
78
- children?: TopBarTabOption[];
79
- }
80
- export interface TopBarTabOption {
81
- id: string;
82
- label: string;
83
- to?: string;
84
- href?: string;
85
- description?: string;
86
- disabled?: boolean;
87
- }
88
- export type TopBarTabOptionInput = TopBarTabOption | string;
89
- export type TopBarTabInput = (Omit<TopBarTab, 'children'> & {
90
- children?: TopBarTabOptionInput[];
91
- }) | string;
69
+ export type PillNavOptionInput = PillNavOption | string;
92
70
  export interface TopBarSettingsConfig {
93
71
  title?: string;
94
72
  tabs?: SettingsTabInput[];
@@ -115,8 +93,11 @@ export interface PillNavItem {
115
93
  to?: string;
116
94
  href?: string;
117
95
  disabled?: boolean;
96
+ children?: PillNavOption[];
118
97
  }
119
- export type PillNavItemInput = PillNavItem | string;
98
+ export type PillNavItemInput = (Omit<PillNavItem, 'children'> & {
99
+ children?: PillNavOptionInput[];
100
+ }) | string;
120
101
  export interface PageSelectorItem {
121
102
  id: string;
122
103
  label: string;
@@ -1,4 +1,4 @@
1
- export type { ContainerDirection, ButtonVariant, ButtonSize, InputType, ModalSize, ModalVariant, AlertType, Toast, TabItem, TabItemInput, OptionPrimitive, SelectOption, SelectOptionInput, RadioOption, RadioOptionInput, FormFieldProps, SidebarToolSection, CollapsibleState, TopBarVariant, TopBarPage, TopBarPageInput, TopBarTab, TopBarTabInput, TopBarTabOption, TopBarTabOptionInput, TopBarSettingsConfig, PillNavItem, PillNavItemInput, PageSelectorItem, PageSelectorItemInput, PluginSwitcherPlugin, PluginSwitcherInfo, AccountMenuItem, WellPlateFormat, WellState, WellPlateSelectionMode, WellPlateSize, WellShape, Well, HeatmapColorScale, HeatmapConfig, SlotPosition, WellExtendedData, WellEditData, WellEditField, WellLegendItem, PlateCondition, ColumnCondition, RowCondition, Rack, SampleType, PlateMap, PlateMapEditorState, ProtocolStepType, ProtocolStepStatus, ProtocolStep, SampleGroup, GroupItem, FileUploaderMode, SegmentedOption, SegmentedOptionInput, SegmentedControlVariant, SegmentedControlSize, MultiSelectOption, MultiSelectOptionInput, MultiSelectSize, PillVariant, PillColor, PillSize, CalendarSelectionMode, CalendarMarker, CalendarDayContext, SortDirection, SortState, DataFrameColumn, PaginationState, SpinnerSize, SpinnerVariant, DividerSpacing, StatusType, ProgressVariant, ProgressSize, AvatarSize, EmptyStateColor, EmptyStateSize, BreadcrumbItem, BreadcrumbItemInput, TooltipPosition, ConfirmVariant, SettingsTab, SettingsTabInput, SettingsModalLayout, SettingsGroup, SettingsModalSchema, NumberNotation, UnitOption, WizardStep, WizardStepState, AuditEntryType, AuditEntry, BatchItemStatus, BatchItem, BatchSummary, TimePickerFormat, TimeRange, ScheduleView, ScheduleEventStatus, ScheduleEvent, ScheduleBlockedSlot, ScheduleSlotContext, ScheduleEventCreateContext, ScheduleEventUpdateContext, SummarySectionItem, SummarySection, SummaryData, ResourceStatus, ResourceSpec, MoleculeData, ExperimentStatus, DatePreset, ExperimentSortField, ExperimentTypeOption, ExperimentSummary, ExperimentListResponse, ExperimentFilters, FitState, FitResultSummary, StorageCondition, ReagentColumn, Reagent, TreeNodeType, BadgeVariant, TreeNode, } from './components';
1
+ export type { ContainerDirection, ButtonVariant, ButtonSize, InputType, ModalSize, ModalVariant, AlertType, Toast, TabItem, TabItemInput, OptionPrimitive, SelectOption, SelectOptionInput, RadioOption, RadioOptionInput, FormFieldProps, SidebarToolSection, CollapsibleState, TopBarVariant, TopBarSettingsConfig, PillNavOption, PillNavOptionInput, PillNavItem, PillNavItemInput, PageSelectorItem, PageSelectorItemInput, PluginSwitcherPlugin, PluginSwitcherInfo, AccountMenuItem, WellPlateFormat, WellState, WellPlateSelectionMode, WellPlateSize, WellShape, Well, HeatmapColorScale, HeatmapConfig, SlotPosition, WellExtendedData, WellEditData, WellEditField, WellLegendItem, PlateCondition, ColumnCondition, RowCondition, Rack, SampleType, PlateMap, PlateMapEditorState, ProtocolStepType, ProtocolStepStatus, ProtocolStep, SampleGroup, GroupItem, FileUploaderMode, SegmentedOption, SegmentedOptionInput, SegmentedControlVariant, SegmentedControlSize, MultiSelectOption, MultiSelectOptionInput, MultiSelectSize, PillVariant, PillColor, PillSize, CalendarSelectionMode, CalendarMarker, CalendarDayContext, SortDirection, SortState, DataFrameColumn, PaginationState, SpinnerSize, SpinnerVariant, DividerSpacing, StatusType, ProgressVariant, ProgressSize, AvatarSize, EmptyStateColor, EmptyStateSize, BreadcrumbItem, BreadcrumbItemInput, TooltipPosition, ConfirmVariant, SettingsTab, SettingsTabInput, SettingsModalLayout, SettingsGroup, SettingsModalSchema, NumberNotation, UnitOption, WizardStep, WizardStepState, AuditEntryType, AuditEntry, BatchItemStatus, BatchItem, BatchSummary, TimePickerFormat, TimeRange, ScheduleView, ScheduleEventStatus, ScheduleEvent, ScheduleBlockedSlot, ScheduleSlotContext, ScheduleEventCreateContext, ScheduleEventUpdateContext, SummarySectionItem, SummarySection, SummaryData, ResourceStatus, ResourceSpec, MoleculeData, ExperimentStatus, DatePreset, ExperimentSortField, ExperimentTypeOption, ExperimentSummary, ExperimentListResponse, ExperimentFilters, FitState, FitResultSummary, StorageCondition, ReagentColumn, Reagent, TreeNodeType, BadgeVariant, TreeNode, } from './components';
2
2
  export type { FormFieldType, FieldCondition, FieldValidation, FormFieldSchema, FormOptionInput, FormSectionSchema, FormStepSchema, FormSchema, FieldEnhancement, FormEnhancements, UseFormBuilderReturn, } from './form-builder';
3
3
  export type { OutlierAction, InputMode, OutlierInfo, ColumnInfo, MetadataRow, AutoGroupResult, ParsedCsvData, } from './auto-group';
4
4
  export type { AuthConfig, UserInfo, LoginResponse, TokenVerifyResponse, RegisterRequest, UpdateProfileRequest, CredentialInfo, } from './auth';
@@ -1,4 +1,4 @@
1
- import { Dn as useControlWorkspace, Ft as extractTemplateCollection, Mn as useConcentrationUnits, On as getFieldRegistryEntry, Ot as createTemplateCollection, Pt as ensureTemplateFromCollection, Xt as getBioTemplatePresetInfo, _ as toBioTemplateComponentSnippets, d as getBioTemplateComponentProps$1, dt as createBioTemplatePresetCollection, en as getBioTemplatePackInfo, ft as createBioTemplatePresetCollectionFromControls, g as toBioTemplateComponentPropsById, h as toBioTemplateComponentPropsByComponent$1, i as createBioTemplateControlToolkit, kn as getTypeDefault, m as toBioTemplateComponentProps, p as toBioTemplateComponentImports, u as getBioTemplateComponentBindings, ut as createBioTemplatePackCollection, v as toBioTemplateComponentUsage } from "./templates-50NPjaxL.js";
1
+ import { At as createTemplateCollection, It as ensureTemplateFromCollection, Ln as useConcentrationUnits, Lt as extractTemplateCollection, Mn as useControlWorkspace, Nn as getFieldRegistryEntry, Pn as getTypeDefault, Qt as getBioTemplatePresetInfo, _ as toBioTemplateComponentPropsByComponent$1, b as toBioTemplateComponentUsage, d as getBioTemplateComponentProps$1, ft as createBioTemplatePackCollection, g as toBioTemplateComponentProps, h as toBioTemplateComponentImports, i as createBioTemplateControlToolkit, m as toBioTemplateComponentBindingsById, mt as createBioTemplatePresetCollectionFromControls, nn as getBioTemplatePackInfo, p as toBioTemplateComponentBindings, pt as createBioTemplatePresetCollection, u as getBioTemplateComponentBindings, v as toBioTemplateComponentPropsById, y as toBioTemplateComponentSnippets } from "./templates-B5jmTWuk.js";
2
2
  import { r as useSettingsStore, t as useAuthStore } from "./auth-QQj2kkze.js";
3
3
  import { computed, effectScope, getCurrentScope, onMounted, onScopeDispose, onUnmounted, provide, reactive, readonly, ref, shallowRef, toRaw, toValue, watch } from "vue";
4
4
  import axios from "axios";
@@ -673,9 +673,121 @@ function useFormBuilder(schema, initialData, enhancements) {
673
673
  };
674
674
  }
675
675
  //#endregion
676
+ //#region src/composables/experiment-utils.ts
677
+ function formatExperimentDate(dateStr) {
678
+ try {
679
+ return new Date(dateStr).toLocaleDateString(void 0, {
680
+ year: "numeric",
681
+ month: "short",
682
+ day: "numeric"
683
+ });
684
+ } catch {
685
+ return dateStr;
686
+ }
687
+ }
688
+ function datePresetToISO(preset) {
689
+ const now = /* @__PURE__ */ new Date();
690
+ const days = preset === "last_7_days" ? 7 : preset === "last_30_days" ? 30 : 90;
691
+ return (/* @__PURE__ */ new Date(now.getTime() - days * 864e5)).toISOString();
692
+ }
693
+ var EXPERIMENT_STATUS_OPTIONS = [
694
+ {
695
+ value: "",
696
+ label: "All statuses"
697
+ },
698
+ {
699
+ value: "planned",
700
+ label: "Planned"
701
+ },
702
+ {
703
+ value: "ongoing",
704
+ label: "Ongoing"
705
+ },
706
+ {
707
+ value: "completed",
708
+ label: "Completed"
709
+ },
710
+ {
711
+ value: "cancelled",
712
+ label: "Cancelled"
713
+ }
714
+ ];
715
+ var EXPERIMENT_STATUS_VARIANT_MAP = {
716
+ planned: "default",
717
+ ongoing: "primary",
718
+ completed: "success",
719
+ cancelled: "error"
720
+ };
721
+ var EXPERIMENT_STATUS_LABELS = {
722
+ planned: "Planned",
723
+ ongoing: "Ongoing",
724
+ completed: "Completed",
725
+ cancelled: "Cancelled"
726
+ };
727
+ function formatExperimentStatus(status) {
728
+ if (!status) return "";
729
+ if (status in EXPERIMENT_STATUS_LABELS) return EXPERIMENT_STATUS_LABELS[status];
730
+ const label = String(status).replace(/[-_]+/g, " ").trim();
731
+ return label ? label.replace(/^\w/, (c) => c.toUpperCase()) : "";
732
+ }
733
+ function getExperimentStatusVariant(status) {
734
+ if (status && status in EXPERIMENT_STATUS_VARIANT_MAP) return EXPERIMENT_STATUS_VARIANT_MAP[status];
735
+ return "default";
736
+ }
737
+ function resolveExperimentCode(experiment) {
738
+ if (experiment.experiment_code) return experiment.experiment_code;
739
+ return experiment.id != null ? `EXP-${experiment.id}` : void 0;
740
+ }
741
+ var DATE_PRESET_OPTIONS = [
742
+ {
743
+ value: "",
744
+ label: "Any time"
745
+ },
746
+ {
747
+ value: "last_7_days",
748
+ label: "Last 7 days"
749
+ },
750
+ {
751
+ value: "last_30_days",
752
+ label: "Last 30 days"
753
+ },
754
+ {
755
+ value: "last_90_days",
756
+ label: "Last 90 days"
757
+ }
758
+ ];
759
+ var SORT_OPTIONS = [
760
+ {
761
+ value: "created_at:desc",
762
+ label: "Newest first"
763
+ },
764
+ {
765
+ value: "created_at:asc",
766
+ label: "Oldest first"
767
+ },
768
+ {
769
+ value: "updated_at:desc",
770
+ label: "Recently updated"
771
+ },
772
+ {
773
+ value: "name:asc",
774
+ label: "Name A–Z"
775
+ },
776
+ {
777
+ value: "name:desc",
778
+ label: "Name Z–A"
779
+ }
780
+ ];
781
+ //#endregion
676
782
  //#region src/composables/useApi.ts
677
783
  var apiClientInstance = null;
678
784
  var interceptorAttached = false;
785
+ function joinUrlPath(baseUrl, path) {
786
+ if (!path) return baseUrl;
787
+ const normalizedBase = baseUrl.replace(/\/+$/, "");
788
+ const normalizedPath = path.replace(/^\/+/, "/");
789
+ return `${normalizedBase}${normalizedPath.startsWith("/") ? normalizedPath : `/${normalizedPath}`}`;
790
+ }
679
791
  function getApiClient() {
680
792
  if (!apiClientInstance) apiClientInstance = axios.create({ headers: { "Content-Type": "application/json" } });
681
793
  return apiClientInstance;
@@ -745,10 +857,10 @@ function useApi(options = {}) {
745
857
  return blobUrl;
746
858
  }
747
859
  function buildUrl(path) {
748
- return `${options.baseUrl ?? settingsStore.getApiBaseUrl()}${path}`;
860
+ return joinUrlPath(options.baseUrl ?? settingsStore.getApiBaseUrl(), path);
749
861
  }
750
862
  function buildWsUrl(path) {
751
- return `${settingsStore.getWsBaseUrl()}${path}`;
863
+ return joinUrlPath(settingsStore.getWsBaseUrl(), path);
752
864
  }
753
865
  return {
754
866
  client: apiClient,
@@ -896,98 +1008,6 @@ function useRequestSyncState(defaultErrorMessage = "Request failed.") {
896
1008
  };
897
1009
  }
898
1010
  //#endregion
899
- //#region src/composables/experiment-utils.ts
900
- function formatExperimentDate(dateStr) {
901
- try {
902
- return new Date(dateStr).toLocaleDateString(void 0, {
903
- year: "numeric",
904
- month: "short",
905
- day: "numeric"
906
- });
907
- } catch {
908
- return dateStr;
909
- }
910
- }
911
- function datePresetToISO(preset) {
912
- const now = /* @__PURE__ */ new Date();
913
- const days = preset === "last_7_days" ? 7 : preset === "last_30_days" ? 30 : 90;
914
- return (/* @__PURE__ */ new Date(now.getTime() - days * 864e5)).toISOString();
915
- }
916
- var EXPERIMENT_STATUS_OPTIONS = [
917
- {
918
- value: "",
919
- label: "All statuses"
920
- },
921
- {
922
- value: "planned",
923
- label: "Planned"
924
- },
925
- {
926
- value: "ongoing",
927
- label: "Ongoing"
928
- },
929
- {
930
- value: "completed",
931
- label: "Completed"
932
- },
933
- {
934
- value: "cancelled",
935
- label: "Cancelled"
936
- }
937
- ];
938
- var EXPERIMENT_STATUS_VARIANT_MAP = {
939
- planned: "default",
940
- ongoing: "primary",
941
- completed: "success",
942
- cancelled: "error"
943
- };
944
- var EXPERIMENT_STATUS_LABELS = {
945
- planned: "Planned",
946
- ongoing: "Ongoing",
947
- completed: "Completed",
948
- cancelled: "Cancelled"
949
- };
950
- var DATE_PRESET_OPTIONS = [
951
- {
952
- value: "",
953
- label: "Any time"
954
- },
955
- {
956
- value: "last_7_days",
957
- label: "Last 7 days"
958
- },
959
- {
960
- value: "last_30_days",
961
- label: "Last 30 days"
962
- },
963
- {
964
- value: "last_90_days",
965
- label: "Last 90 days"
966
- }
967
- ];
968
- var SORT_OPTIONS = [
969
- {
970
- value: "created_at:desc",
971
- label: "Newest first"
972
- },
973
- {
974
- value: "created_at:asc",
975
- label: "Oldest first"
976
- },
977
- {
978
- value: "updated_at:desc",
979
- label: "Recently updated"
980
- },
981
- {
982
- value: "name:asc",
983
- label: "Name A–Z"
984
- },
985
- {
986
- value: "name:desc",
987
- label: "Name Z–A"
988
- }
989
- ];
990
- //#endregion
991
1011
  //#region src/composables/useExperimentSelector.ts
992
1012
  function getPlatformContext() {
993
1013
  if (typeof window === "undefined") return void 0;
@@ -1380,7 +1400,7 @@ function usePlatformContext(options = {}) {
1380
1400
  //#endregion
1381
1401
  //#region src/composables/useAppExperiment.ts
1382
1402
  var APP_EXPERIMENT_KEY = Symbol("app-experiment");
1383
- /** Manages the active experiment selection, save flow, and detach action for a plugin's app shell. */
1403
+ /** Manages the current experiment selection, save flow, and detach action for a plugin's AppTopBar app shell. */
1384
1404
  function useAppExperiment(options = {}) {
1385
1405
  const experimentName = ref();
1386
1406
  const experimentCode = ref();
@@ -1394,10 +1414,25 @@ function useAppExperiment(options = {}) {
1394
1414
  const showDetach = computed(() => experimentId.value !== null);
1395
1415
  const saveDisabled = computed(() => toValue(options.saveDisabled) ?? false);
1396
1416
  const saveDisabledMessage = computed(() => toValue(options.saveDisabledMessage));
1417
+ const popover = computed(() => ({
1418
+ experimentName: experimentName.value,
1419
+ experimentCode: experimentCode.value,
1420
+ experimentStatus: experimentStatus.value,
1421
+ showSave: showSave.value,
1422
+ showDetach: showDetach.value,
1423
+ saveDisabled: saveDisabled.value,
1424
+ saveDisabledMessage: saveDisabledMessage.value,
1425
+ saveLoading: saveLoading.value,
1426
+ saveSuccessMessage: saveSuccessMessage.value
1427
+ }));
1428
+ const selectorModal = computed(() => ({
1429
+ modelValue: showModal.value,
1430
+ currentExperimentId: experimentId.value
1431
+ }));
1397
1432
  function set(experiment) {
1398
1433
  experimentId.value = experiment.id;
1399
1434
  experimentName.value = experiment.name;
1400
- experimentCode.value = experiment.experiment_code ?? (experiment.id != null ? `EXP-${experiment.id}` : void 0);
1435
+ experimentCode.value = resolveExperimentCode(experiment);
1401
1436
  experimentStatus.value = experiment.status;
1402
1437
  }
1403
1438
  function clear() {
@@ -1406,6 +1441,10 @@ function useAppExperiment(options = {}) {
1406
1441
  experimentCode.value = void 0;
1407
1442
  experimentStatus.value = void 0;
1408
1443
  }
1444
+ if (options.experiment !== void 0) watch(() => toValue(options.experiment), (experiment) => {
1445
+ if (experiment) set(experiment);
1446
+ else clear();
1447
+ }, { immediate: true });
1409
1448
  function openModal() {
1410
1449
  showModal.value = true;
1411
1450
  }
@@ -1453,6 +1492,8 @@ function useAppExperiment(options = {}) {
1453
1492
  showDetach,
1454
1493
  saveDisabled,
1455
1494
  saveDisabledMessage,
1495
+ popover,
1496
+ selectorModal,
1456
1497
  openModal,
1457
1498
  closeModal,
1458
1499
  handleSelect,
@@ -1464,7 +1505,15 @@ function useAppExperiment(options = {}) {
1464
1505
  clear,
1465
1506
  experimentName: readonly(experimentName),
1466
1507
  experimentCode: readonly(experimentCode),
1467
- experimentId: readonly(experimentId)
1508
+ experimentStatus: readonly(experimentStatus),
1509
+ experimentId: readonly(experimentId),
1510
+ popover,
1511
+ selectorModal,
1512
+ openModal,
1513
+ closeModal,
1514
+ handleSelect,
1515
+ handleSave,
1516
+ handleDetach
1468
1517
  };
1469
1518
  }
1470
1519
  //#endregion
@@ -3022,6 +3071,8 @@ function useBioTemplateComponents(target) {
3022
3071
  return {
3023
3072
  bindings: getBioTemplateComponentBindings(target),
3024
3073
  imports: toBioTemplateComponentImports(target),
3074
+ componentBindings: typeof target === "string" ? [] : toBioTemplateComponentBindings(target),
3075
+ componentBindingsById: typeof target === "string" ? {} : toBioTemplateComponentBindingsById(target),
3025
3076
  componentProps: typeof target === "string" ? [] : toBioTemplateComponentProps(target),
3026
3077
  componentPropsById: typeof target === "string" ? {} : toBioTemplateComponentPropsById(target),
3027
3078
  componentPropsByComponent: typeof target === "string" ? {} : toBioTemplateComponentPropsByComponent(target),
@@ -3043,10 +3094,10 @@ function useBioTemplateWorkspace(target, options = {}) {
3043
3094
  form: workspace.bindings.form,
3044
3095
  sidebar: workspace.bindings.sidebar,
3045
3096
  topBar: workspace.bindings.topBar,
3046
- topBarTabs: workspace.bindings.topBarTabs,
3047
3097
  topBarSettings: workspace.bindings.topBarSettings,
3048
3098
  pillNav: workspace.bindings.pillNav,
3049
3099
  componentBindings: components.bindings,
3100
+ componentBindingsById: components.componentBindingsById,
3050
3101
  componentProps: components.componentProps,
3051
3102
  componentPropsById: components.componentPropsById,
3052
3103
  componentPropsByComponent: components.componentPropsByComponent,
@@ -3070,6 +3121,7 @@ function useBioTemplateWorkspace(target, options = {}) {
3070
3121
  bindings,
3071
3122
  renderer,
3072
3123
  componentBindings: components.bindings,
3124
+ componentBindingsById: components.componentBindingsById,
3073
3125
  componentImports: components.imports,
3074
3126
  componentProps: components.componentProps,
3075
3127
  componentPropsById: components.componentPropsById,
@@ -3105,11 +3157,12 @@ function useBioTemplatePackWorkspace(packId, options = {}) {
3105
3157
  const renderer = computed(() => ({ target: collection.value }));
3106
3158
  const form = computed(() => workspace.value.form);
3107
3159
  const sidebar = computed(() => workspace.value.sidebar);
3108
- const topBar = computed(() => workspace.value.topBar);
3160
+ const topBar = computed(() => workspace.value.topBar.value);
3109
3161
  const pillNav = computed(() => workspace.value.pillNav);
3110
3162
  const topBarSettings = computed(() => workspace.value.topBarSettings);
3111
3163
  const bindings = computed(() => workspace.value.bindings);
3112
3164
  const componentBindings = computed(() => workspace.value.componentBindings);
3165
+ const componentBindingsById = computed(() => workspace.value.componentBindingsById);
3113
3166
  const componentImports = computed(() => workspace.value.componentImports);
3114
3167
  const componentProps = computed(() => workspace.value.componentProps);
3115
3168
  const componentPropsById = computed(() => workspace.value.componentPropsById);
@@ -3151,6 +3204,7 @@ function useBioTemplatePackWorkspace(packId, options = {}) {
3151
3204
  topBarSettings,
3152
3205
  bindings,
3153
3206
  componentBindings,
3207
+ componentBindingsById,
3154
3208
  componentImports,
3155
3209
  componentProps,
3156
3210
  componentPropsById,
@@ -3189,6 +3243,7 @@ function useBioTemplatePresetWorkspace(presetId, options = {}) {
3189
3243
  const workspace = computed(() => useBioTemplateWorkspace(collection.value, resolvedControlOptions));
3190
3244
  const renderer = computed(() => ({ target: collection.value }));
3191
3245
  const componentBindings = computed(() => workspace.value.componentBindings);
3246
+ const componentBindingsById = computed(() => workspace.value.componentBindingsById);
3192
3247
  const componentImports = computed(() => workspace.value.componentImports);
3193
3248
  const componentProps = computed(() => workspace.value.componentProps);
3194
3249
  const componentPropsById = computed(() => workspace.value.componentPropsById);
@@ -3208,11 +3263,6 @@ function useBioTemplatePresetWorkspace(presetId, options = {}) {
3208
3263
  values: controlValues.value,
3209
3264
  "onUpdate:values": setControlValues
3210
3265
  });
3211
- const topBar = reactive({
3212
- tabs: controls.topBarTabs,
3213
- currentTabId: activeControlView.value,
3214
- onTabSelect: (tab) => setActiveControlView(tab.id)
3215
- });
3216
3266
  const pillNav = reactive({
3217
3267
  items: controls.viewItems,
3218
3268
  currentItemId: activeControlView.value,
@@ -3232,12 +3282,6 @@ function useBioTemplatePresetWorkspace(presetId, options = {}) {
3232
3282
  onPillSelect: pillNav.onSelect,
3233
3283
  ...topBarSettings
3234
3284
  }));
3235
- const topBarTabsProps = computed(() => ({
3236
- tabs: topBar.tabs,
3237
- currentTabId: topBar.currentTabId,
3238
- onTabSelect: topBar.onTabSelect,
3239
- ...topBarSettings
3240
- }));
3241
3285
  function getComponentProps(component, options) {
3242
3286
  return workspace.value.getComponentProps(component, options);
3243
3287
  }
@@ -3246,10 +3290,10 @@ function useBioTemplatePresetWorkspace(presetId, options = {}) {
3246
3290
  form,
3247
3291
  sidebar,
3248
3292
  topBar: topBarProps,
3249
- topBarTabs: topBarTabsProps,
3250
3293
  topBarSettings,
3251
3294
  pillNav,
3252
3295
  componentBindings,
3296
+ componentBindingsById,
3253
3297
  componentProps,
3254
3298
  componentPropsById,
3255
3299
  componentPropsByComponent,
@@ -3266,11 +3310,9 @@ function useBioTemplatePresetWorkspace(presetId, options = {}) {
3266
3310
  }, { deep: true });
3267
3311
  watch(activeControlView, (viewId) => {
3268
3312
  sidebar.activeView = viewId;
3269
- topBar.currentTabId = viewId;
3270
3313
  pillNav.currentItemId = viewId;
3271
3314
  }, { flush: "sync" });
3272
3315
  watch(() => sidebar.activeView, setActiveControlView, { flush: "sync" });
3273
- watch(() => topBar.currentTabId, setActiveControlView, { flush: "sync" });
3274
3316
  watch(() => pillNav.currentItemId, setActiveControlView, { flush: "sync" });
3275
3317
  function applyCollection(value) {
3276
3318
  return templateCollection.apply(value);
@@ -3323,13 +3365,14 @@ function useBioTemplatePresetWorkspace(presetId, options = {}) {
3323
3365
  activeControlView,
3324
3366
  form,
3325
3367
  sidebar,
3326
- topBar,
3368
+ topBar: topBarProps,
3327
3369
  pillNav,
3328
3370
  topBarSettings,
3329
3371
  bindings,
3330
3372
  renderer,
3331
3373
  workspace,
3332
3374
  componentBindings,
3375
+ componentBindingsById,
3333
3376
  componentImports,
3334
3377
  componentProps,
3335
3378
  componentPropsById,
@@ -4366,6 +4409,6 @@ function clampRange(start, end, min, max) {
4366
4409
  };
4367
4410
  }
4368
4411
  //#endregion
4369
- export { normalizeSearchQuery as $, useAutoGroup as A, EXPERIMENT_STATUS_VARIANT_MAP as B, useSampleGroups as C, DEFAULT_COLORS as D, hslToHex as E, usePlatformContext as F, useDebouncedWatch as G, datePresetToISO as H, useExperimentSelector as I, useFormBuilder as J, useApi as K, DATE_PRESET_OPTIONS as L, useDoseCalculator as M, APP_EXPERIMENT_KEY as N, extractSamplesFromDesignData as O, useAppExperiment as P, candidateMatchesSearch as Q, EXPERIMENT_STATUS_LABELS as R, useExpansionSet as S, hexToHsl as T, formatExperimentDate as U, SORT_OPTIONS as V, useRequestSyncState as W, useTheme as X, useForm as Y, useToast as Z, useTemplateCollection as _, DEFAULT_UNITS as a, getInjectedPlatformContext as b, useGroupAssignment as c, useBioTemplatePackWorkspace as d, useTextSearch as et, useBioTemplateWorkspace as f, useBioTemplateControls as g, useBioTemplateComponents as h, DEFAULT_PRESETS as i, useWellPlateEditor as j, parseCSV as k, useRackEditor as l, toBioTemplateComponentPropsByComponent as m, useExperimentData as n, useSortedItems as nt, generateDilutionSeries as o, getBioTemplateComponentProps as p, evaluateCondition as q, useProtocolTemplates as r, useReagentSeries as s, useScheduleDrag as t, compareSortValues as tt, useBioTemplatePresetWorkspace as u, useExperimentSave as v, deriveShade as w, resolveCurrentExperimentId as x, currentExperimentFromContext as y, EXPERIMENT_STATUS_OPTIONS as z };
4412
+ export { useTheme as $, useAutoGroup as A, DATE_PRESET_OPTIONS as B, useSampleGroups as C, DEFAULT_COLORS as D, hslToHex as E, usePlatformContext as F, datePresetToISO as G, EXPERIMENT_STATUS_OPTIONS as H, useExperimentSelector as I, getExperimentStatusVariant as J, formatExperimentDate as K, useRequestSyncState as L, useDoseCalculator as M, APP_EXPERIMENT_KEY as N, extractSamplesFromDesignData as O, useAppExperiment as P, useForm as Q, useDebouncedWatch as R, useExpansionSet as S, hexToHsl as T, EXPERIMENT_STATUS_VARIANT_MAP as U, EXPERIMENT_STATUS_LABELS as V, SORT_OPTIONS as W, evaluateCondition as X, resolveExperimentCode as Y, useFormBuilder as Z, useTemplateCollection as _, DEFAULT_UNITS as a, useSortedItems as at, getInjectedPlatformContext as b, useGroupAssignment as c, useBioTemplatePackWorkspace as d, useToast as et, useBioTemplateWorkspace as f, useBioTemplateControls as g, useBioTemplateComponents as h, DEFAULT_PRESETS as i, compareSortValues as it, useWellPlateEditor as j, parseCSV as k, useRackEditor as l, toBioTemplateComponentPropsByComponent as m, useExperimentData as n, normalizeSearchQuery as nt, generateDilutionSeries as o, getBioTemplateComponentProps as p, formatExperimentStatus as q, useProtocolTemplates as r, useTextSearch as rt, useReagentSeries as s, useScheduleDrag as t, candidateMatchesSearch as tt, useBioTemplatePresetWorkspace as u, useExperimentSave as v, deriveShade as w, resolveCurrentExperimentId as x, currentExperimentFromContext as y, useApi as z };
4370
4413
 
4371
- //# sourceMappingURL=useScheduleDrag-D4oWdh41.js.map
4414
+ //# sourceMappingURL=useScheduleDrag-BgzpQT53.js.map