@morscherlab/mint-sdk 1.0.0-beta.3 → 1.0.0-beta.5
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.
- package/README.md +9 -2
- package/dist/__tests__/composables/experiment-utils.test.d.ts +1 -0
- package/dist/__tests__/composables/useApi.test.d.ts +1 -0
- package/dist/components/AppContainer.vue.d.ts +1 -1
- package/dist/components/AppLayout.vue.d.ts +20 -1
- package/dist/components/AppSidebar.vue.d.ts +57 -5
- package/dist/components/AppTopBar.vue.d.ts +7 -25
- package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +3 -1
- package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +1 -0
- package/dist/components/BioTemplatePresetWorkspaceView.vue.d.ts +5 -0
- package/dist/components/ComponentBindingRenderer.vue.d.ts +44 -0
- package/dist/components/ControlWorkspaceView.vue.d.ts +24 -7
- package/dist/components/DoseDesignWorkspaceView.vue.d.ts +149 -0
- package/dist/components/ExperimentTimeline.vue.d.ts +1 -1
- package/dist/components/FormBuilder.vue.d.ts +9 -9
- package/dist/components/PlateMapEditor.vue.d.ts +1 -1
- package/dist/components/PluginWorkspaceView.vue.d.ts +310 -0
- package/dist/components/SettingsModal.vue.d.ts +1 -1
- package/dist/components/WellPlate.vue.d.ts +2 -2
- package/dist/components/index.d.ts +3 -12
- package/dist/components/index.js +3 -3
- package/dist/components/{AppPageSelector.vue.d.ts → internal/AppTopBarPageSelectorInternal.vue.d.ts} +1 -1
- package/dist/components/{AppPillNav.vue.d.ts → internal/AppTopBarPillNavInternal.vue.d.ts} +3 -1
- package/dist/components/{CalendarGridPanel.vue.d.ts → internal/CalendarGridPanelInternal.vue.d.ts} +1 -1
- package/dist/components/internal/FormSectionRenderer.vue.d.ts +4 -4
- package/dist/components/{WellEditPopup.vue.d.ts → internal/WellEditPopupInternal.vue.d.ts} +1 -1
- package/dist/{components-D_Sr0adg.js → components-DihbSJjU.js} +5932 -5408
- package/dist/components-DihbSJjU.js.map +1 -0
- package/dist/composables/experiment-utils.d.ts +8 -0
- package/dist/composables/index.d.ts +5 -7
- package/dist/composables/index.js +4 -4
- package/dist/composables/useAppExperiment.d.ts +31 -2
- package/dist/composables/useBioTemplateComponents.d.ts +5 -3
- package/dist/composables/useBioTemplatePackWorkspace.d.ts +3 -2
- package/dist/composables/useBioTemplatePresetWorkspace.d.ts +6 -5
- package/dist/composables/useBioTemplateWorkspace.d.ts +5 -4
- package/dist/composables/useControlSchema.d.ts +43 -21
- package/dist/composables/usePluginClient.d.ts +5 -2
- package/dist/{composables-C3dpXQN5.js → composables-BcgZ6diz.js} +40 -28
- package/dist/composables-BcgZ6diz.js.map +1 -0
- package/dist/index.d.ts +5 -12
- package/dist/index.js +5 -5
- package/dist/install.js +2 -2
- package/dist/styles.css +5637 -5663
- package/dist/templates/adapters.d.ts +7 -1
- package/dist/templates/catalog.d.ts +5 -5
- package/dist/templates/componentBindings.d.ts +13 -0
- package/dist/templates/index.d.ts +5 -5
- package/dist/templates/index.js +2 -2
- package/dist/templates/presets.d.ts +4 -4
- package/dist/templates/types.d.ts +4 -1
- package/dist/{templates-50NPjaxL.js → templates-Cyt0Suwf.js} +322 -73
- package/dist/templates-Cyt0Suwf.js.map +1 -0
- package/dist/types/components.d.ts +6 -25
- package/dist/types/index.d.ts +1 -1
- package/dist/{useScheduleDrag-D4oWdh41.js → useExperimentData-CM6Y0u5L.js} +400 -357
- package/dist/useExperimentData-CM6Y0u5L.js.map +1 -0
- package/package.json +1 -1
- package/src/__tests__/components/ActionItem.test.ts +6 -6
- package/src/__tests__/components/AppLayout.test.ts +44 -0
- package/src/__tests__/components/AppSidebar.test.ts +130 -2
- package/src/__tests__/components/AppToastContainer.test.ts +0 -11
- package/src/__tests__/components/AppTopBar.test.ts +189 -120
- package/src/__tests__/components/{AppPageSelector.test.ts → AppTopBarPageSelector.test.ts} +8 -8
- package/src/__tests__/components/{AppPillNav.test.ts → AppTopBarPillNav.test.ts} +53 -6
- package/src/__tests__/components/BioTemplateExperimentWorkspaceView.test.ts +7 -1
- package/src/__tests__/components/BioTemplatePackWorkspaceView.test.ts +32 -1
- package/src/__tests__/components/BioTemplatePresetWorkspaceView.test.ts +48 -1
- package/src/__tests__/components/BioTemplateRenderer.test.ts +25 -0
- package/src/__tests__/components/CalendarGridPanel.test.ts +3 -3
- package/src/__tests__/components/ComponentBindingRenderer.test.ts +278 -0
- package/src/__tests__/components/ControlWorkspaceView.test.ts +134 -63
- package/src/__tests__/components/DateTimePicker.test.ts +2 -2
- package/src/__tests__/components/DoseDesignWorkspaceView.test.ts +185 -0
- package/src/__tests__/components/PluginWorkspaceView.test.ts +548 -0
- package/src/__tests__/composables/experiment-utils.test.ts +30 -0
- package/src/__tests__/composables/useApi.test.ts +30 -0
- package/src/__tests__/composables/useAppExperiment.test.ts +100 -1
- package/src/__tests__/composables/useBioTemplatePackWorkspace.test.ts +7 -4
- package/src/__tests__/composables/useBioTemplatePresetWorkspace.test.ts +7 -7
- package/src/__tests__/composables/useBioTemplateWorkspace.test.ts +6 -1
- package/src/__tests__/composables/useControlSchema.test.ts +151 -37
- package/src/__tests__/composables/usePluginClient.test.ts +99 -2
- package/src/__tests__/docs/frontendDocsCatalog.test.ts +120 -25
- package/src/__tests__/templates/templates.test.ts +56 -0
- package/src/components/AppAvatarMenu.vue +3 -3
- package/src/components/AppLayout.story.vue +39 -0
- package/src/components/AppLayout.vue +83 -2
- package/src/components/AppPluginSwitcher.vue +5 -5
- package/src/components/AppSidebar.story.vue +113 -5
- package/src/components/AppSidebar.vue +147 -27
- package/src/components/AppTopBar.story.vue +2 -5
- package/src/components/AppTopBar.vue +35 -425
- package/src/components/BioTemplateExperimentWorkspaceView.story.vue +2 -2
- package/src/components/BioTemplateExperimentWorkspaceView.vue +6 -0
- package/src/components/BioTemplatePackWorkspaceView.story.vue +4 -4
- package/src/components/BioTemplatePackWorkspaceView.vue +1 -0
- package/src/components/BioTemplatePresetWorkspaceView.story.vue +14 -2
- package/src/components/BioTemplatePresetWorkspaceView.vue +12 -3
- package/src/components/BioTemplateRenderer.story.vue +2 -2
- package/src/components/BioTemplateRenderer.vue +15 -227
- package/src/components/ComponentBindingRenderer.story.vue +87 -0
- package/src/components/ComponentBindingRenderer.vue +317 -0
- package/src/components/ControlWorkspaceView.story.vue +20 -9
- package/src/components/ControlWorkspaceView.vue +43 -12
- package/src/components/DatePicker.vue +2 -2
- package/src/components/DateTimePicker.vue +2 -2
- package/src/components/DoseDesignWorkspaceView.story.vue +77 -0
- package/src/components/DoseDesignWorkspaceView.vue +255 -0
- package/src/components/ExperimentPopover.story.vue +2 -2
- package/src/components/ExperimentPopover.vue +2 -6
- package/src/components/ExperimentSelectorModal.vue +6 -5
- package/src/components/FormBuilder.story.vue +190 -0
- package/src/components/PluginWorkspaceView.story.vue +334 -0
- package/src/components/PluginWorkspaceView.vue +708 -0
- package/src/components/SettingsModal.story.vue +87 -0
- package/src/components/WellPlate.vue +2 -2
- package/src/components/index.ts +3 -12
- package/src/components/{AppPageSelector.vue → internal/AppTopBarPageSelectorInternal.vue} +9 -9
- package/src/components/internal/AppTopBarPillNavInternal.vue +194 -0
- package/src/components/{CalendarGridPanel.vue → internal/CalendarGridPanelInternal.vue} +1 -1
- package/src/components/{WellEditPopup.vue → internal/WellEditPopupInternal.vue} +3 -3
- package/src/composables/experiment-utils.ts +26 -0
- package/src/composables/index.ts +21 -7
- package/src/composables/useApi.ts +9 -2
- package/src/composables/useAppExperiment.ts +85 -13
- package/src/composables/useBioTemplateComponents.ts +12 -0
- package/src/composables/useBioTemplatePackWorkspace.ts +6 -2
- package/src/composables/useBioTemplatePresetWorkspace.ts +10 -21
- package/src/composables/useBioTemplateWorkspace.ts +6 -4
- package/src/composables/useControlSchema.ts +157 -69
- package/src/composables/usePluginClient.ts +50 -9
- package/src/index.ts +6 -563
- package/src/styles/components/app-layout.css +82 -0
- package/src/styles/components/app-page-selector.css +1 -1
- package/src/styles/components/app-pill-nav.css +71 -1
- package/src/styles/components/app-sidebar.css +119 -0
- package/src/styles/components/app-top-bar.css +0 -235
- package/src/styles/components/experiment-popover.css +2 -2
- package/src/styles/index.css +0 -1
- package/src/templates/adapters.ts +193 -0
- package/src/templates/catalog.ts +5 -5
- package/src/templates/componentBindings.ts +90 -3
- package/src/templates/index.ts +10 -0
- package/src/templates/packs.ts +10 -1
- package/src/templates/presets.ts +14 -4
- package/src/templates/types.ts +4 -0
- package/src/types/components.ts +6 -31
- package/src/types/index.ts +2 -6
- package/dist/__tests__/composables/usePluginApi.test.d.ts +0 -13
- package/dist/components/FormFieldRenderer.vue.d.ts +0 -28
- package/dist/components/FormSection.vue.d.ts +0 -30
- package/dist/components/GroupingModal.vue.d.ts +0 -12
- package/dist/components/SettingsButton.vue.d.ts +0 -30
- package/dist/components/ToastNotification.vue.d.ts +0 -2
- package/dist/components-D_Sr0adg.js.map +0 -1
- package/dist/composables/usePluginApi.d.ts +0 -22
- package/dist/composables-C3dpXQN5.js.map +0 -1
- package/dist/templates-50NPjaxL.js.map +0 -1
- package/dist/useScheduleDrag-D4oWdh41.js.map +0 -1
- package/src/__tests__/components/FormCompatibility.test.ts +0 -94
- package/src/__tests__/components/GroupingModal.test.ts +0 -73
- package/src/__tests__/components/SettingsButton.test.ts +0 -44
- package/src/__tests__/composables/usePluginApi.test.ts +0 -81
- package/src/components/AppPillNav.vue +0 -71
- package/src/components/FormFieldRenderer.vue +0 -35
- package/src/components/FormSection.vue +0 -37
- package/src/components/GroupingModal.story.vue +0 -52
- package/src/components/GroupingModal.vue +0 -61
- package/src/components/SettingsButton.story.vue +0 -58
- package/src/components/SettingsButton.vue +0 -64
- package/src/components/ToastNotification.vue +0 -9
- package/src/composables/usePluginApi.ts +0 -32
- package/src/styles/components/settings-button.css +0 -31
- /package/dist/__tests__/components/{AppPageSelector.test.d.ts → AppTopBarPageSelector.test.d.ts} +0 -0
- /package/dist/__tests__/components/{AppPillNav.test.d.ts → AppTopBarPillNav.test.d.ts} +0 -0
- /package/dist/__tests__/components/{FormCompatibility.test.d.ts → ComponentBindingRenderer.test.d.ts} +0 -0
- /package/dist/__tests__/components/{GroupingModal.test.d.ts → DoseDesignWorkspaceView.test.d.ts} +0 -0
- /package/dist/__tests__/components/{SettingsButton.test.d.ts → PluginWorkspaceView.test.d.ts} +0 -0
- /package/dist/components/{ActionItem.vue.d.ts → internal/ActionItemInternal.vue.d.ts} +0 -0
- /package/src/components/{ActionItem.vue → internal/ActionItemInternal.vue} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Bn as useConcentrationUnits, Bt as extractTemplateCollection, Fn as useControlWorkspace, In as getFieldRegistryEntry, Ln as getTypeDefault, Nt as createTemplateCollection, _ as toBioTemplateComponentPropsByComponent$1, _t as createBioTemplatePresetCollectionFromControls, an as getBioTemplatePackInfo, b as toBioTemplateComponentUsage, d as getBioTemplateComponentProps$1, g as toBioTemplateComponentProps, gt as createBioTemplatePresetCollection, h as toBioTemplateComponentImports, ht as createBioTemplatePackCollection, i as createBioTemplateControlToolkit, m as toBioTemplateComponentBindingsById, p as toBioTemplateComponentBindings, tn as getBioTemplatePresetInfo, u as getBioTemplateComponentBindings, v as toBioTemplateComponentPropsById, y as toBioTemplateComponentSnippets, zt as ensureTemplateFromCollection } from "./templates-Cyt0Suwf.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
|
|
860
|
+
return joinUrlPath(options.baseUrl ?? settingsStore.getApiBaseUrl(), path);
|
|
749
861
|
}
|
|
750
862
|
function buildWsUrl(path) {
|
|
751
|
-
return
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|
|
@@ -2660,66 +2709,246 @@ function normalizeIds(ids) {
|
|
|
2660
2709
|
return [...new Set(ids.filter(Boolean))];
|
|
2661
2710
|
}
|
|
2662
2711
|
//#endregion
|
|
2663
|
-
//#region src/composables/
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
}
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2712
|
+
//#region src/composables/useScheduleDrag.ts
|
|
2713
|
+
/** Handles pointer-driven create, move, and resize drag interactions for the ScheduleCalendar grid. */
|
|
2714
|
+
function useScheduleDrag(options) {
|
|
2715
|
+
const isDragging = ref(false);
|
|
2716
|
+
const dragState = ref(null);
|
|
2717
|
+
const ghost = computed(() => {
|
|
2718
|
+
if (!dragState.value) return null;
|
|
2719
|
+
const state = dragState.value;
|
|
2720
|
+
const slotH = options.slotHeight.value;
|
|
2721
|
+
const slotMin = options.slotDuration.value;
|
|
2722
|
+
const dayStart = options.dayStartHour.value * 60;
|
|
2723
|
+
if (state.type === "create") {
|
|
2724
|
+
const deltaY = state.currentY - state.startY;
|
|
2725
|
+
const startOffset = state.startY;
|
|
2726
|
+
const endOffset = startOffset + deltaY;
|
|
2727
|
+
const topPx = Math.min(startOffset, endOffset);
|
|
2728
|
+
const bottomPx = Math.max(startOffset, endOffset);
|
|
2729
|
+
const startMinutes = dayStart + Math.round(topPx / slotH * slotMin);
|
|
2730
|
+
const endMinutes = dayStart + Math.round(bottomPx / slotH * slotMin);
|
|
2731
|
+
const snappedStart = snapMinutes(startMinutes, slotMin);
|
|
2732
|
+
const snappedEnd = Math.max(snapMinutes(endMinutes, slotMin), snappedStart + slotMin);
|
|
2733
|
+
const snappedTopPx = (snappedStart - dayStart) / slotMin * slotH;
|
|
2734
|
+
const snappedHeightPx = (snappedEnd - snappedStart) / slotMin * slotH;
|
|
2735
|
+
return {
|
|
2736
|
+
start: minutesToDate(state.startDate, snappedStart),
|
|
2737
|
+
end: minutesToDate(state.startDate, snappedEnd),
|
|
2738
|
+
dayIndex: state.dayIndex,
|
|
2739
|
+
style: {
|
|
2740
|
+
top: `${snappedTopPx}px`,
|
|
2741
|
+
height: `${snappedHeightPx}px`
|
|
2742
|
+
}
|
|
2743
|
+
};
|
|
2744
|
+
}
|
|
2745
|
+
if (state.type === "move" && state.event) {
|
|
2746
|
+
const deltaY = state.currentY - state.startY;
|
|
2747
|
+
const eventStart = dateToMinutes(new Date(state.event.start));
|
|
2748
|
+
const duration = dateToMinutes(new Date(state.event.end)) - eventStart;
|
|
2749
|
+
const newStart = snapMinutes(eventStart + Math.round(deltaY / slotH * slotMin), slotMin);
|
|
2750
|
+
const clamped = clampRange(newStart, newStart + duration, dayStart, options.dayEndHour.value * 60);
|
|
2751
|
+
const topPx = (clamped.start - dayStart) / slotMin * slotH;
|
|
2752
|
+
const heightPx = (clamped.end - clamped.start) / slotMin * slotH;
|
|
2753
|
+
return {
|
|
2754
|
+
start: minutesToDate(state.startDate, clamped.start),
|
|
2755
|
+
end: minutesToDate(state.startDate, clamped.end),
|
|
2756
|
+
dayIndex: state.currentDayIndex,
|
|
2757
|
+
style: {
|
|
2758
|
+
top: `${topPx}px`,
|
|
2759
|
+
height: `${heightPx}px`
|
|
2760
|
+
}
|
|
2761
|
+
};
|
|
2762
|
+
}
|
|
2763
|
+
if ((state.type === "resize-top" || state.type === "resize-bottom") && state.event) {
|
|
2764
|
+
const eventStart = dateToMinutes(new Date(state.event.start));
|
|
2765
|
+
const eventEnd = dateToMinutes(new Date(state.event.end));
|
|
2766
|
+
const deltaY = state.currentY - state.startY;
|
|
2767
|
+
const pixelDelta = Math.round(deltaY / slotH * slotMin);
|
|
2768
|
+
let newStart = eventStart;
|
|
2769
|
+
let newEnd = eventEnd;
|
|
2770
|
+
if (state.type === "resize-top") {
|
|
2771
|
+
newStart = snapMinutes(eventStart + pixelDelta, slotMin);
|
|
2772
|
+
newStart = Math.min(newStart, newEnd - slotMin);
|
|
2773
|
+
} else {
|
|
2774
|
+
newEnd = snapMinutes(eventEnd + pixelDelta, slotMin);
|
|
2775
|
+
newEnd = Math.max(newEnd, newStart + slotMin);
|
|
2776
|
+
}
|
|
2777
|
+
const clamped = clampRange(newStart, newEnd, dayStart, options.dayEndHour.value * 60);
|
|
2778
|
+
const topPx = (clamped.start - dayStart) / slotMin * slotH;
|
|
2779
|
+
const heightPx = (clamped.end - clamped.start) / slotMin * slotH;
|
|
2780
|
+
return {
|
|
2781
|
+
start: minutesToDate(state.startDate, clamped.start),
|
|
2782
|
+
end: minutesToDate(state.startDate, clamped.end),
|
|
2783
|
+
dayIndex: state.dayIndex,
|
|
2784
|
+
style: {
|
|
2785
|
+
top: `${topPx}px`,
|
|
2786
|
+
height: `${heightPx}px`
|
|
2787
|
+
}
|
|
2788
|
+
};
|
|
2789
|
+
}
|
|
2790
|
+
return null;
|
|
2791
|
+
});
|
|
2792
|
+
function startCreate(date, y, dayIndex) {
|
|
2793
|
+
if (options.readonly.value) return;
|
|
2794
|
+
isDragging.value = true;
|
|
2795
|
+
dragState.value = {
|
|
2796
|
+
type: "create",
|
|
2797
|
+
startDate: date,
|
|
2798
|
+
startY: y,
|
|
2799
|
+
currentY: y,
|
|
2800
|
+
dayIndex,
|
|
2801
|
+
currentDayIndex: dayIndex
|
|
2802
|
+
};
|
|
2803
|
+
addListeners();
|
|
2804
|
+
}
|
|
2805
|
+
function startMove(event, y, dayIndex) {
|
|
2806
|
+
if (options.readonly.value || event.draggable === false) return;
|
|
2807
|
+
isDragging.value = true;
|
|
2808
|
+
dragState.value = {
|
|
2809
|
+
type: "move",
|
|
2810
|
+
event,
|
|
2811
|
+
startDate: new Date(event.start),
|
|
2812
|
+
startY: y,
|
|
2813
|
+
currentY: y,
|
|
2814
|
+
dayIndex,
|
|
2815
|
+
currentDayIndex: dayIndex
|
|
2816
|
+
};
|
|
2817
|
+
addListeners();
|
|
2818
|
+
}
|
|
2819
|
+
function startResize(event, edge, y, dayIndex) {
|
|
2820
|
+
if (options.readonly.value || event.resizable === false) return;
|
|
2821
|
+
isDragging.value = true;
|
|
2822
|
+
dragState.value = {
|
|
2823
|
+
type: edge === "top" ? "resize-top" : "resize-bottom",
|
|
2824
|
+
event,
|
|
2825
|
+
startDate: new Date(event.start),
|
|
2826
|
+
startY: y,
|
|
2827
|
+
currentY: y,
|
|
2828
|
+
dayIndex,
|
|
2829
|
+
currentDayIndex: dayIndex
|
|
2830
|
+
};
|
|
2831
|
+
addListeners();
|
|
2832
|
+
}
|
|
2833
|
+
function onPointerMove(e) {
|
|
2834
|
+
if (!dragState.value) return;
|
|
2835
|
+
dragState.value = {
|
|
2836
|
+
...dragState.value,
|
|
2837
|
+
currentY: e.clientY
|
|
2838
|
+
};
|
|
2839
|
+
}
|
|
2840
|
+
function onPointerUp() {
|
|
2841
|
+
if (!dragState.value || !ghost.value) {
|
|
2842
|
+
cleanup();
|
|
2843
|
+
return;
|
|
2844
|
+
}
|
|
2845
|
+
const g = ghost.value;
|
|
2846
|
+
const state = dragState.value;
|
|
2847
|
+
if (state.type === "create" && options.onCreateComplete) options.onCreateComplete(g.start, g.end);
|
|
2848
|
+
else if (state.type === "move" && state.event && options.onMoveComplete) options.onMoveComplete(state.event, g.start, g.end);
|
|
2849
|
+
else if ((state.type === "resize-top" || state.type === "resize-bottom") && state.event && options.onResizeComplete) options.onResizeComplete(state.event, g.start, g.end);
|
|
2850
|
+
cleanup();
|
|
2851
|
+
}
|
|
2852
|
+
function addListeners() {
|
|
2853
|
+
document.addEventListener("pointermove", onPointerMove);
|
|
2854
|
+
document.addEventListener("pointerup", onPointerUp);
|
|
2855
|
+
}
|
|
2856
|
+
function cleanup() {
|
|
2857
|
+
isDragging.value = false;
|
|
2858
|
+
dragState.value = null;
|
|
2859
|
+
document.removeEventListener("pointermove", onPointerMove);
|
|
2860
|
+
document.removeEventListener("pointerup", onPointerUp);
|
|
2861
|
+
}
|
|
2862
|
+
onUnmounted(cleanup);
|
|
2863
|
+
return {
|
|
2864
|
+
isDragging,
|
|
2865
|
+
dragState,
|
|
2866
|
+
ghost,
|
|
2867
|
+
startCreate,
|
|
2868
|
+
startMove,
|
|
2869
|
+
startResize
|
|
2870
|
+
};
|
|
2871
|
+
}
|
|
2872
|
+
function snapMinutes(minutes, step) {
|
|
2873
|
+
return Math.round(minutes / step) * step;
|
|
2874
|
+
}
|
|
2875
|
+
function dateToMinutes(date) {
|
|
2876
|
+
return date.getHours() * 60 + date.getMinutes();
|
|
2877
|
+
}
|
|
2878
|
+
function minutesToDate(baseDate, minutes) {
|
|
2879
|
+
const d = new Date(baseDate);
|
|
2880
|
+
d.setHours(Math.floor(minutes / 60), minutes % 60, 0, 0);
|
|
2881
|
+
return d;
|
|
2882
|
+
}
|
|
2883
|
+
function clampRange(start, end, min, max) {
|
|
2884
|
+
const s = Math.max(start, min);
|
|
2885
|
+
const e = Math.min(end, max);
|
|
2886
|
+
return {
|
|
2887
|
+
start: s,
|
|
2888
|
+
end: Math.max(e, s)
|
|
2889
|
+
};
|
|
2890
|
+
}
|
|
2891
|
+
//#endregion
|
|
2892
|
+
//#region src/composables/platformContextHelpers.ts
|
|
2893
|
+
function getInjectedPlatformContext() {
|
|
2894
|
+
if (typeof window === "undefined") return void 0;
|
|
2895
|
+
return window.__MINT_PLATFORM__;
|
|
2896
|
+
}
|
|
2897
|
+
function getInjectedExperimentContext() {
|
|
2898
|
+
return getInjectedPlatformContext();
|
|
2899
|
+
}
|
|
2900
|
+
function currentExperimentFromContext(context = getInjectedExperimentContext()) {
|
|
2901
|
+
const candidate = context?.currentExperiment ?? context?.experiment;
|
|
2902
|
+
return candidate && typeof candidate === "object" ? candidate : void 0;
|
|
2903
|
+
}
|
|
2904
|
+
function currentExperimentIdFromContext(context = getInjectedExperimentContext()) {
|
|
2905
|
+
return parseExperimentId(context?.currentExperimentId ?? context?.experimentId ?? context?.currentExperiment ?? context?.experiment);
|
|
2906
|
+
}
|
|
2907
|
+
function currentExperimentIdFromUrl() {
|
|
2908
|
+
if (typeof window === "undefined") return void 0;
|
|
2909
|
+
const params = new URLSearchParams(window.location.search);
|
|
2910
|
+
return parseExperimentId(params.get("experimentId") ?? params.get("experiment_id")) ?? experimentIdFromPath(window.location.pathname) ?? experimentIdFromPath(window.location.hash.replace(/^#\/?/, "/"));
|
|
2911
|
+
}
|
|
2912
|
+
function resolveCurrentExperimentId(context = getInjectedExperimentContext()) {
|
|
2913
|
+
return currentExperimentIdFromContext(context) ?? currentExperimentIdFromUrl();
|
|
2914
|
+
}
|
|
2915
|
+
function parseExperimentId(value) {
|
|
2916
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
2917
|
+
if (typeof value === "string" && value.trim()) {
|
|
2918
|
+
const parsed = Number(value);
|
|
2919
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
2920
|
+
}
|
|
2921
|
+
if (value && typeof value === "object" && "id" in value) return parseExperimentId(value.id);
|
|
2922
|
+
}
|
|
2923
|
+
function experimentIdFromPath(path) {
|
|
2924
|
+
const segments = path.split("/").filter(Boolean);
|
|
2925
|
+
for (let index = 0; index < segments.length - 1; index += 1) {
|
|
2926
|
+
const segment = segments[index]?.toLowerCase();
|
|
2927
|
+
if (segment === "experiment" || segment === "experiments") return parseExperimentId(decodeURIComponent(segments[index + 1] ?? ""));
|
|
2928
|
+
}
|
|
2929
|
+
}
|
|
2930
|
+
//#endregion
|
|
2931
|
+
//#region src/composables/useExperimentSave.ts
|
|
2932
|
+
/** Persists experiment design, analysis, and built-in template preset data through the platform API. */
|
|
2933
|
+
function useExperimentSave(options = {}) {
|
|
2934
|
+
const injectedContext = getInjectedPlatformContext();
|
|
2935
|
+
const api = useApi({ baseUrl: options.apiBaseUrl ?? injectedContext?.platformApiUrl });
|
|
2936
|
+
const pluginId = options.pluginId ?? injectedContext?.plugin?.id;
|
|
2937
|
+
const schemaVersion = options.schemaVersion ?? "1.0";
|
|
2938
|
+
const currentExperimentId = computed(() => {
|
|
2939
|
+
return resolveCurrentExperimentId(injectedContext);
|
|
2940
|
+
});
|
|
2941
|
+
const hasCurrentExperiment = computed(() => currentExperimentId.value !== void 0);
|
|
2942
|
+
const request = useRequestSyncState("Experiment request failed.");
|
|
2943
|
+
const isSaving = ref(false);
|
|
2944
|
+
const isLoading = ref(false);
|
|
2945
|
+
const error = request.error;
|
|
2946
|
+
const lastLoadedAt = request.lastLoadedAt;
|
|
2947
|
+
const lastSavedAt = request.lastSavedAt;
|
|
2948
|
+
function requireCurrentExperimentId() {
|
|
2949
|
+
const id = currentExperimentId.value;
|
|
2950
|
+
if (id === void 0) throw new Error("[MINT SDK] No current experiment is selected.");
|
|
2951
|
+
return id;
|
|
2723
2952
|
}
|
|
2724
2953
|
function currentExperimentIdOrError(action) {
|
|
2725
2954
|
const id = currentExperimentId.value;
|
|
@@ -3022,6 +3251,8 @@ function useBioTemplateComponents(target) {
|
|
|
3022
3251
|
return {
|
|
3023
3252
|
bindings: getBioTemplateComponentBindings(target),
|
|
3024
3253
|
imports: toBioTemplateComponentImports(target),
|
|
3254
|
+
componentBindings: typeof target === "string" ? [] : toBioTemplateComponentBindings(target),
|
|
3255
|
+
componentBindingsById: typeof target === "string" ? {} : toBioTemplateComponentBindingsById(target),
|
|
3025
3256
|
componentProps: typeof target === "string" ? [] : toBioTemplateComponentProps(target),
|
|
3026
3257
|
componentPropsById: typeof target === "string" ? {} : toBioTemplateComponentPropsById(target),
|
|
3027
3258
|
componentPropsByComponent: typeof target === "string" ? {} : toBioTemplateComponentPropsByComponent(target),
|
|
@@ -3043,10 +3274,10 @@ function useBioTemplateWorkspace(target, options = {}) {
|
|
|
3043
3274
|
form: workspace.bindings.form,
|
|
3044
3275
|
sidebar: workspace.bindings.sidebar,
|
|
3045
3276
|
topBar: workspace.bindings.topBar,
|
|
3046
|
-
topBarTabs: workspace.bindings.topBarTabs,
|
|
3047
3277
|
topBarSettings: workspace.bindings.topBarSettings,
|
|
3048
3278
|
pillNav: workspace.bindings.pillNav,
|
|
3049
3279
|
componentBindings: components.bindings,
|
|
3280
|
+
componentBindingsById: components.componentBindingsById,
|
|
3050
3281
|
componentProps: components.componentProps,
|
|
3051
3282
|
componentPropsById: components.componentPropsById,
|
|
3052
3283
|
componentPropsByComponent: components.componentPropsByComponent,
|
|
@@ -3070,6 +3301,7 @@ function useBioTemplateWorkspace(target, options = {}) {
|
|
|
3070
3301
|
bindings,
|
|
3071
3302
|
renderer,
|
|
3072
3303
|
componentBindings: components.bindings,
|
|
3304
|
+
componentBindingsById: components.componentBindingsById,
|
|
3073
3305
|
componentImports: components.imports,
|
|
3074
3306
|
componentProps: components.componentProps,
|
|
3075
3307
|
componentPropsById: components.componentPropsById,
|
|
@@ -3105,11 +3337,12 @@ function useBioTemplatePackWorkspace(packId, options = {}) {
|
|
|
3105
3337
|
const renderer = computed(() => ({ target: collection.value }));
|
|
3106
3338
|
const form = computed(() => workspace.value.form);
|
|
3107
3339
|
const sidebar = computed(() => workspace.value.sidebar);
|
|
3108
|
-
const topBar = computed(() => workspace.value.topBar);
|
|
3340
|
+
const topBar = computed(() => workspace.value.topBar.value);
|
|
3109
3341
|
const pillNav = computed(() => workspace.value.pillNav);
|
|
3110
3342
|
const topBarSettings = computed(() => workspace.value.topBarSettings);
|
|
3111
3343
|
const bindings = computed(() => workspace.value.bindings);
|
|
3112
3344
|
const componentBindings = computed(() => workspace.value.componentBindings);
|
|
3345
|
+
const componentBindingsById = computed(() => workspace.value.componentBindingsById);
|
|
3113
3346
|
const componentImports = computed(() => workspace.value.componentImports);
|
|
3114
3347
|
const componentProps = computed(() => workspace.value.componentProps);
|
|
3115
3348
|
const componentPropsById = computed(() => workspace.value.componentPropsById);
|
|
@@ -3151,6 +3384,7 @@ function useBioTemplatePackWorkspace(packId, options = {}) {
|
|
|
3151
3384
|
topBarSettings,
|
|
3152
3385
|
bindings,
|
|
3153
3386
|
componentBindings,
|
|
3387
|
+
componentBindingsById,
|
|
3154
3388
|
componentImports,
|
|
3155
3389
|
componentProps,
|
|
3156
3390
|
componentPropsById,
|
|
@@ -3189,6 +3423,7 @@ function useBioTemplatePresetWorkspace(presetId, options = {}) {
|
|
|
3189
3423
|
const workspace = computed(() => useBioTemplateWorkspace(collection.value, resolvedControlOptions));
|
|
3190
3424
|
const renderer = computed(() => ({ target: collection.value }));
|
|
3191
3425
|
const componentBindings = computed(() => workspace.value.componentBindings);
|
|
3426
|
+
const componentBindingsById = computed(() => workspace.value.componentBindingsById);
|
|
3192
3427
|
const componentImports = computed(() => workspace.value.componentImports);
|
|
3193
3428
|
const componentProps = computed(() => workspace.value.componentProps);
|
|
3194
3429
|
const componentPropsById = computed(() => workspace.value.componentPropsById);
|
|
@@ -3208,11 +3443,6 @@ function useBioTemplatePresetWorkspace(presetId, options = {}) {
|
|
|
3208
3443
|
values: controlValues.value,
|
|
3209
3444
|
"onUpdate:values": setControlValues
|
|
3210
3445
|
});
|
|
3211
|
-
const topBar = reactive({
|
|
3212
|
-
tabs: controls.topBarTabs,
|
|
3213
|
-
currentTabId: activeControlView.value,
|
|
3214
|
-
onTabSelect: (tab) => setActiveControlView(tab.id)
|
|
3215
|
-
});
|
|
3216
3446
|
const pillNav = reactive({
|
|
3217
3447
|
items: controls.viewItems,
|
|
3218
3448
|
currentItemId: activeControlView.value,
|
|
@@ -3232,12 +3462,6 @@ function useBioTemplatePresetWorkspace(presetId, options = {}) {
|
|
|
3232
3462
|
onPillSelect: pillNav.onSelect,
|
|
3233
3463
|
...topBarSettings
|
|
3234
3464
|
}));
|
|
3235
|
-
const topBarTabsProps = computed(() => ({
|
|
3236
|
-
tabs: topBar.tabs,
|
|
3237
|
-
currentTabId: topBar.currentTabId,
|
|
3238
|
-
onTabSelect: topBar.onTabSelect,
|
|
3239
|
-
...topBarSettings
|
|
3240
|
-
}));
|
|
3241
3465
|
function getComponentProps(component, options) {
|
|
3242
3466
|
return workspace.value.getComponentProps(component, options);
|
|
3243
3467
|
}
|
|
@@ -3246,10 +3470,10 @@ function useBioTemplatePresetWorkspace(presetId, options = {}) {
|
|
|
3246
3470
|
form,
|
|
3247
3471
|
sidebar,
|
|
3248
3472
|
topBar: topBarProps,
|
|
3249
|
-
topBarTabs: topBarTabsProps,
|
|
3250
3473
|
topBarSettings,
|
|
3251
3474
|
pillNav,
|
|
3252
3475
|
componentBindings,
|
|
3476
|
+
componentBindingsById,
|
|
3253
3477
|
componentProps,
|
|
3254
3478
|
componentPropsById,
|
|
3255
3479
|
componentPropsByComponent,
|
|
@@ -3266,11 +3490,9 @@ function useBioTemplatePresetWorkspace(presetId, options = {}) {
|
|
|
3266
3490
|
}, { deep: true });
|
|
3267
3491
|
watch(activeControlView, (viewId) => {
|
|
3268
3492
|
sidebar.activeView = viewId;
|
|
3269
|
-
topBar.currentTabId = viewId;
|
|
3270
3493
|
pillNav.currentItemId = viewId;
|
|
3271
3494
|
}, { flush: "sync" });
|
|
3272
3495
|
watch(() => sidebar.activeView, setActiveControlView, { flush: "sync" });
|
|
3273
|
-
watch(() => topBar.currentTabId, setActiveControlView, { flush: "sync" });
|
|
3274
3496
|
watch(() => pillNav.currentItemId, setActiveControlView, { flush: "sync" });
|
|
3275
3497
|
function applyCollection(value) {
|
|
3276
3498
|
return templateCollection.apply(value);
|
|
@@ -3323,13 +3545,14 @@ function useBioTemplatePresetWorkspace(presetId, options = {}) {
|
|
|
3323
3545
|
activeControlView,
|
|
3324
3546
|
form,
|
|
3325
3547
|
sidebar,
|
|
3326
|
-
topBar,
|
|
3548
|
+
topBar: topBarProps,
|
|
3327
3549
|
pillNav,
|
|
3328
3550
|
topBarSettings,
|
|
3329
3551
|
bindings,
|
|
3330
3552
|
renderer,
|
|
3331
3553
|
workspace,
|
|
3332
3554
|
componentBindings,
|
|
3555
|
+
componentBindingsById,
|
|
3333
3556
|
componentImports,
|
|
3334
3557
|
componentProps,
|
|
3335
3558
|
componentPropsById,
|
|
@@ -4186,186 +4409,6 @@ function useExperimentData(options = {}) {
|
|
|
4186
4409
|
};
|
|
4187
4410
|
}
|
|
4188
4411
|
//#endregion
|
|
4189
|
-
|
|
4190
|
-
/** Handles pointer-driven create, move, and resize drag interactions for the ScheduleCalendar grid. */
|
|
4191
|
-
function useScheduleDrag(options) {
|
|
4192
|
-
const isDragging = ref(false);
|
|
4193
|
-
const dragState = ref(null);
|
|
4194
|
-
const ghost = computed(() => {
|
|
4195
|
-
if (!dragState.value) return null;
|
|
4196
|
-
const state = dragState.value;
|
|
4197
|
-
const slotH = options.slotHeight.value;
|
|
4198
|
-
const slotMin = options.slotDuration.value;
|
|
4199
|
-
const dayStart = options.dayStartHour.value * 60;
|
|
4200
|
-
if (state.type === "create") {
|
|
4201
|
-
const deltaY = state.currentY - state.startY;
|
|
4202
|
-
const startOffset = state.startY;
|
|
4203
|
-
const endOffset = startOffset + deltaY;
|
|
4204
|
-
const topPx = Math.min(startOffset, endOffset);
|
|
4205
|
-
const bottomPx = Math.max(startOffset, endOffset);
|
|
4206
|
-
const startMinutes = dayStart + Math.round(topPx / slotH * slotMin);
|
|
4207
|
-
const endMinutes = dayStart + Math.round(bottomPx / slotH * slotMin);
|
|
4208
|
-
const snappedStart = snapMinutes(startMinutes, slotMin);
|
|
4209
|
-
const snappedEnd = Math.max(snapMinutes(endMinutes, slotMin), snappedStart + slotMin);
|
|
4210
|
-
const snappedTopPx = (snappedStart - dayStart) / slotMin * slotH;
|
|
4211
|
-
const snappedHeightPx = (snappedEnd - snappedStart) / slotMin * slotH;
|
|
4212
|
-
return {
|
|
4213
|
-
start: minutesToDate(state.startDate, snappedStart),
|
|
4214
|
-
end: minutesToDate(state.startDate, snappedEnd),
|
|
4215
|
-
dayIndex: state.dayIndex,
|
|
4216
|
-
style: {
|
|
4217
|
-
top: `${snappedTopPx}px`,
|
|
4218
|
-
height: `${snappedHeightPx}px`
|
|
4219
|
-
}
|
|
4220
|
-
};
|
|
4221
|
-
}
|
|
4222
|
-
if (state.type === "move" && state.event) {
|
|
4223
|
-
const deltaY = state.currentY - state.startY;
|
|
4224
|
-
const eventStart = dateToMinutes(new Date(state.event.start));
|
|
4225
|
-
const duration = dateToMinutes(new Date(state.event.end)) - eventStart;
|
|
4226
|
-
const newStart = snapMinutes(eventStart + Math.round(deltaY / slotH * slotMin), slotMin);
|
|
4227
|
-
const clamped = clampRange(newStart, newStart + duration, dayStart, options.dayEndHour.value * 60);
|
|
4228
|
-
const topPx = (clamped.start - dayStart) / slotMin * slotH;
|
|
4229
|
-
const heightPx = (clamped.end - clamped.start) / slotMin * slotH;
|
|
4230
|
-
return {
|
|
4231
|
-
start: minutesToDate(state.startDate, clamped.start),
|
|
4232
|
-
end: minutesToDate(state.startDate, clamped.end),
|
|
4233
|
-
dayIndex: state.currentDayIndex,
|
|
4234
|
-
style: {
|
|
4235
|
-
top: `${topPx}px`,
|
|
4236
|
-
height: `${heightPx}px`
|
|
4237
|
-
}
|
|
4238
|
-
};
|
|
4239
|
-
}
|
|
4240
|
-
if ((state.type === "resize-top" || state.type === "resize-bottom") && state.event) {
|
|
4241
|
-
const eventStart = dateToMinutes(new Date(state.event.start));
|
|
4242
|
-
const eventEnd = dateToMinutes(new Date(state.event.end));
|
|
4243
|
-
const deltaY = state.currentY - state.startY;
|
|
4244
|
-
const pixelDelta = Math.round(deltaY / slotH * slotMin);
|
|
4245
|
-
let newStart = eventStart;
|
|
4246
|
-
let newEnd = eventEnd;
|
|
4247
|
-
if (state.type === "resize-top") {
|
|
4248
|
-
newStart = snapMinutes(eventStart + pixelDelta, slotMin);
|
|
4249
|
-
newStart = Math.min(newStart, newEnd - slotMin);
|
|
4250
|
-
} else {
|
|
4251
|
-
newEnd = snapMinutes(eventEnd + pixelDelta, slotMin);
|
|
4252
|
-
newEnd = Math.max(newEnd, newStart + slotMin);
|
|
4253
|
-
}
|
|
4254
|
-
const clamped = clampRange(newStart, newEnd, dayStart, options.dayEndHour.value * 60);
|
|
4255
|
-
const topPx = (clamped.start - dayStart) / slotMin * slotH;
|
|
4256
|
-
const heightPx = (clamped.end - clamped.start) / slotMin * slotH;
|
|
4257
|
-
return {
|
|
4258
|
-
start: minutesToDate(state.startDate, clamped.start),
|
|
4259
|
-
end: minutesToDate(state.startDate, clamped.end),
|
|
4260
|
-
dayIndex: state.dayIndex,
|
|
4261
|
-
style: {
|
|
4262
|
-
top: `${topPx}px`,
|
|
4263
|
-
height: `${heightPx}px`
|
|
4264
|
-
}
|
|
4265
|
-
};
|
|
4266
|
-
}
|
|
4267
|
-
return null;
|
|
4268
|
-
});
|
|
4269
|
-
function startCreate(date, y, dayIndex) {
|
|
4270
|
-
if (options.readonly.value) return;
|
|
4271
|
-
isDragging.value = true;
|
|
4272
|
-
dragState.value = {
|
|
4273
|
-
type: "create",
|
|
4274
|
-
startDate: date,
|
|
4275
|
-
startY: y,
|
|
4276
|
-
currentY: y,
|
|
4277
|
-
dayIndex,
|
|
4278
|
-
currentDayIndex: dayIndex
|
|
4279
|
-
};
|
|
4280
|
-
addListeners();
|
|
4281
|
-
}
|
|
4282
|
-
function startMove(event, y, dayIndex) {
|
|
4283
|
-
if (options.readonly.value || event.draggable === false) return;
|
|
4284
|
-
isDragging.value = true;
|
|
4285
|
-
dragState.value = {
|
|
4286
|
-
type: "move",
|
|
4287
|
-
event,
|
|
4288
|
-
startDate: new Date(event.start),
|
|
4289
|
-
startY: y,
|
|
4290
|
-
currentY: y,
|
|
4291
|
-
dayIndex,
|
|
4292
|
-
currentDayIndex: dayIndex
|
|
4293
|
-
};
|
|
4294
|
-
addListeners();
|
|
4295
|
-
}
|
|
4296
|
-
function startResize(event, edge, y, dayIndex) {
|
|
4297
|
-
if (options.readonly.value || event.resizable === false) return;
|
|
4298
|
-
isDragging.value = true;
|
|
4299
|
-
dragState.value = {
|
|
4300
|
-
type: edge === "top" ? "resize-top" : "resize-bottom",
|
|
4301
|
-
event,
|
|
4302
|
-
startDate: new Date(event.start),
|
|
4303
|
-
startY: y,
|
|
4304
|
-
currentY: y,
|
|
4305
|
-
dayIndex,
|
|
4306
|
-
currentDayIndex: dayIndex
|
|
4307
|
-
};
|
|
4308
|
-
addListeners();
|
|
4309
|
-
}
|
|
4310
|
-
function onPointerMove(e) {
|
|
4311
|
-
if (!dragState.value) return;
|
|
4312
|
-
dragState.value = {
|
|
4313
|
-
...dragState.value,
|
|
4314
|
-
currentY: e.clientY
|
|
4315
|
-
};
|
|
4316
|
-
}
|
|
4317
|
-
function onPointerUp() {
|
|
4318
|
-
if (!dragState.value || !ghost.value) {
|
|
4319
|
-
cleanup();
|
|
4320
|
-
return;
|
|
4321
|
-
}
|
|
4322
|
-
const g = ghost.value;
|
|
4323
|
-
const state = dragState.value;
|
|
4324
|
-
if (state.type === "create" && options.onCreateComplete) options.onCreateComplete(g.start, g.end);
|
|
4325
|
-
else if (state.type === "move" && state.event && options.onMoveComplete) options.onMoveComplete(state.event, g.start, g.end);
|
|
4326
|
-
else if ((state.type === "resize-top" || state.type === "resize-bottom") && state.event && options.onResizeComplete) options.onResizeComplete(state.event, g.start, g.end);
|
|
4327
|
-
cleanup();
|
|
4328
|
-
}
|
|
4329
|
-
function addListeners() {
|
|
4330
|
-
document.addEventListener("pointermove", onPointerMove);
|
|
4331
|
-
document.addEventListener("pointerup", onPointerUp);
|
|
4332
|
-
}
|
|
4333
|
-
function cleanup() {
|
|
4334
|
-
isDragging.value = false;
|
|
4335
|
-
dragState.value = null;
|
|
4336
|
-
document.removeEventListener("pointermove", onPointerMove);
|
|
4337
|
-
document.removeEventListener("pointerup", onPointerUp);
|
|
4338
|
-
}
|
|
4339
|
-
onUnmounted(cleanup);
|
|
4340
|
-
return {
|
|
4341
|
-
isDragging,
|
|
4342
|
-
dragState,
|
|
4343
|
-
ghost,
|
|
4344
|
-
startCreate,
|
|
4345
|
-
startMove,
|
|
4346
|
-
startResize
|
|
4347
|
-
};
|
|
4348
|
-
}
|
|
4349
|
-
function snapMinutes(minutes, step) {
|
|
4350
|
-
return Math.round(minutes / step) * step;
|
|
4351
|
-
}
|
|
4352
|
-
function dateToMinutes(date) {
|
|
4353
|
-
return date.getHours() * 60 + date.getMinutes();
|
|
4354
|
-
}
|
|
4355
|
-
function minutesToDate(baseDate, minutes) {
|
|
4356
|
-
const d = new Date(baseDate);
|
|
4357
|
-
d.setHours(Math.floor(minutes / 60), minutes % 60, 0, 0);
|
|
4358
|
-
return d;
|
|
4359
|
-
}
|
|
4360
|
-
function clampRange(start, end, min, max) {
|
|
4361
|
-
const s = Math.max(start, min);
|
|
4362
|
-
const e = Math.min(end, max);
|
|
4363
|
-
return {
|
|
4364
|
-
start: s,
|
|
4365
|
-
end: Math.max(e, s)
|
|
4366
|
-
};
|
|
4367
|
-
}
|
|
4368
|
-
//#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, useExperimentSave as _, generateDilutionSeries as a, useSortedItems as at, resolveCurrentExperimentId as b, useRackEditor as c, useBioTemplateWorkspace as d, useToast as et, getBioTemplateComponentProps as f, useTemplateCollection as g, useBioTemplateControls as h, DEFAULT_UNITS as i, compareSortValues as it, useWellPlateEditor as j, parseCSV as k, useBioTemplatePresetWorkspace as l, useBioTemplateComponents as m, useProtocolTemplates as n, normalizeSearchQuery as nt, useReagentSeries as o, toBioTemplateComponentPropsByComponent as p, formatExperimentStatus as q, DEFAULT_PRESETS as r, useTextSearch as rt, useGroupAssignment as s, useExperimentData as t, candidateMatchesSearch as tt, useBioTemplatePackWorkspace as u, currentExperimentFromContext as v, deriveShade as w, useScheduleDrag as x, getInjectedPlatformContext as y, useApi as z };
|
|
4370
4413
|
|
|
4371
|
-
//# sourceMappingURL=
|
|
4414
|
+
//# sourceMappingURL=useExperimentData-CM6Y0u5L.js.map
|