@morscherlab/mint-sdk 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/dist/{ExperimentSelectorModal-DCXmwKNS.js → ExperimentSelectorModal-DHE9k8TP.js} +3 -3
  2. package/dist/{ExperimentSelectorModal-DCXmwKNS.js.map → ExperimentSelectorModal-DHE9k8TP.js.map} +1 -1
  3. package/dist/{SettingsModal-BYR20I4c.js → SettingsModal-DELMkUFR.js} +39 -16
  4. package/dist/SettingsModal-DELMkUFR.js.map +1 -0
  5. package/dist/{Skeleton-BAF3CKY7.js → Skeleton-jhF9wUkU.js} +17 -7
  6. package/dist/Skeleton-jhF9wUkU.js.map +1 -0
  7. package/dist/__tests__/components/ChartContainer.test.d.ts +1 -0
  8. package/dist/__tests__/components/ChemicalFormula.test.d.ts +1 -0
  9. package/dist/__tests__/components/FormField.test.d.ts +1 -0
  10. package/dist/__tests__/components/LayoutResizeHandle.test.d.ts +1 -0
  11. package/dist/__tests__/components/NumberInput.test.d.ts +1 -0
  12. package/dist/__tests__/components/SearchableSelect.test.d.ts +1 -0
  13. package/dist/__tests__/components/WellPlate.decoration.test.d.ts +1 -0
  14. package/dist/__tests__/composables/localFiles.test.d.ts +1 -0
  15. package/dist/__tests__/composables/useManualLayoutResize.test.d.ts +1 -0
  16. package/dist/__tests__/composables/usePickerSelection.test.d.ts +1 -0
  17. package/dist/__tests__/styles/tokenOnlyColors.test.d.ts +1 -0
  18. package/dist/components/AdductText.vue.d.ts +17 -0
  19. package/dist/components/AppSidebar.vue.d.ts +7 -7
  20. package/dist/components/BasePill.vue.d.ts +3 -0
  21. package/dist/components/BaseTabs.vue.d.ts +1 -4
  22. package/dist/components/ChartContainer.vue.d.ts +19 -5
  23. package/dist/components/ChemicalFormula.vue.d.ts +28 -2
  24. package/dist/components/DataFrame.vue.d.ts +1 -1
  25. package/dist/components/FileUploader.vue.d.ts +3 -0
  26. package/dist/components/FormField.vue.d.ts +8 -1
  27. package/dist/components/LayoutResizeHandle.vue.d.ts +23 -0
  28. package/dist/components/PlotlyChart.vue.d.ts +34 -6
  29. package/dist/components/PluginWorkspaceView.props.d.ts +3 -3
  30. package/dist/components/SearchableSelect.vue.d.ts +57 -0
  31. package/dist/components/WellPlate.vue.d.ts +5 -1
  32. package/dist/components/index.d.ts +3 -1
  33. package/dist/components/index.js +6 -6
  34. package/dist/{components-DIum5hkx.js → components-CxQVQCpP.js} +1215 -546
  35. package/dist/components-CxQVQCpP.js.map +1 -0
  36. package/dist/composables/index.d.ts +1 -0
  37. package/dist/composables/index.js +8 -8
  38. package/dist/composables/pluginWorkspaceModel.d.ts +0 -3
  39. package/dist/composables/useManualLayoutResize.d.ts +56 -0
  40. package/dist/composables/useToast.d.ts +22 -1
  41. package/dist/{composables-mFXsTA4g.js → composables-DAqOU8Aq.js} +97 -8
  42. package/dist/composables-DAqOU8Aq.js.map +1 -0
  43. package/dist/index.js +11 -11
  44. package/dist/install.js +2 -2
  45. package/dist/styles.css +855 -320
  46. package/dist/templates/index.js +2 -2
  47. package/dist/{templates-CmGfmBRA.js → templates-NuaNHohp.js} +2 -2
  48. package/dist/{templates-CmGfmBRA.js.map → templates-NuaNHohp.js.map} +1 -1
  49. package/dist/types/componentLabTypes.d.ts +3 -0
  50. package/dist/types/components.d.ts +26 -1
  51. package/dist/types/form-builder.d.ts +2 -0
  52. package/dist/types/generated-ui.d.ts +2 -0
  53. package/dist/types/index.d.ts +1 -1
  54. package/dist/{useControlSchema-DldpxNOP.js → useControlSchema-vLiRPUmj.js} +181 -71
  55. package/dist/useControlSchema-vLiRPUmj.js.map +1 -0
  56. package/dist/{useExperimentSelector-CEcIaueJ.js → useExperimentSelector-G_CAOFTX.js} +2 -2
  57. package/dist/{useExperimentSelector-CEcIaueJ.js.map → useExperimentSelector-G_CAOFTX.js.map} +1 -1
  58. package/dist/{useFormBuilder-z5L_dUIy.js → useFormBuilder-D37ajgS8.js} +2 -2
  59. package/dist/{useFormBuilder-z5L_dUIy.js.map → useFormBuilder-D37ajgS8.js.map} +1 -1
  60. package/dist/{validation-uwoJGEb6.js → validation-ChMyixAf.js} +21 -9
  61. package/dist/validation-ChMyixAf.js.map +1 -0
  62. package/package.json +1 -1
  63. package/src/__tests__/components/AppSidebar.test.ts +84 -94
  64. package/src/__tests__/components/AppToastContainer.test.ts +55 -1
  65. package/src/__tests__/components/BioTemplatePresetWorkspaceView.test.ts +0 -21
  66. package/src/__tests__/components/ChartContainer.test.ts +24 -0
  67. package/src/__tests__/components/ChemicalFormula.test.ts +27 -0
  68. package/src/__tests__/components/ControlWorkspaceView.test.ts +0 -2
  69. package/src/__tests__/components/DoseDesignWorkspaceView.test.ts +0 -2
  70. package/src/__tests__/components/FormBuilder.test.ts +26 -0
  71. package/src/__tests__/components/FormField.test.ts +26 -0
  72. package/src/__tests__/components/GeneratedPathInput.test.ts +18 -0
  73. package/src/__tests__/components/LayoutResizeHandle.test.ts +19 -0
  74. package/src/__tests__/components/NumberInput.test.ts +149 -0
  75. package/src/__tests__/components/PlotlyChart.test.ts +48 -0
  76. package/src/__tests__/components/PluginWorkspaceView.internal.test.ts +1 -2
  77. package/src/__tests__/components/PluginWorkspaceView.test.ts +1 -2
  78. package/src/__tests__/components/RackEditor.test.ts +9 -0
  79. package/src/__tests__/components/SearchableSelect.test.ts +61 -0
  80. package/src/__tests__/components/WellPlate.decoration.test.ts +28 -0
  81. package/src/__tests__/composables/localFiles.test.ts +57 -0
  82. package/src/__tests__/composables/useManualLayoutResize.test.ts +21 -0
  83. package/src/__tests__/composables/usePickerSelection.test.ts +98 -0
  84. package/src/__tests__/generatedUi.test.ts +111 -0
  85. package/src/__tests__/styles/tokenOnlyColors.test.ts +16 -0
  86. package/src/components/AdductText.story.vue +15 -0
  87. package/src/components/AdductText.vue +40 -0
  88. package/src/components/AppLayout.story.vue +1 -1
  89. package/src/components/AppSidebar.story.vue +7 -10
  90. package/src/components/AppSidebar.vue +178 -58
  91. package/src/components/AppToastContainer.vue +65 -23
  92. package/src/components/BasePill.story.vue +2 -0
  93. package/src/components/BasePill.vue +4 -0
  94. package/src/components/BaseTabs.story.vue +0 -42
  95. package/src/components/BaseTabs.vue +3 -6
  96. package/src/components/ChartContainer.story.vue +21 -0
  97. package/src/components/ChartContainer.vue +27 -6
  98. package/src/components/ChemicalFormula.story.vue +7 -0
  99. package/src/components/ChemicalFormula.vue +40 -11
  100. package/src/components/FileUploader.vue +10 -1
  101. package/src/components/FormField.vue +10 -3
  102. package/src/components/GeneratedPathInput.vue +11 -7
  103. package/src/components/LayoutResizeHandle.story.vue +26 -0
  104. package/src/components/LayoutResizeHandle.vue +62 -0
  105. package/src/components/NumberInput.story.vue +32 -13
  106. package/src/components/NumberInput.vue +145 -56
  107. package/src/components/PlotlyChart.vue +77 -11
  108. package/src/components/PluginWorkspaceView.props.ts +3 -3
  109. package/src/components/RackEditor.vue +38 -32
  110. package/src/components/SearchableSelect.story.vue +24 -0
  111. package/src/components/SearchableSelect.vue +223 -0
  112. package/src/components/WellPlate.story.vue +16 -0
  113. package/src/components/WellPlate.vue +17 -8
  114. package/src/components/index.ts +3 -1
  115. package/src/components/internal/FormFieldRendererInternal.vue +17 -0
  116. package/src/components/internal/WorkspaceSidebarInternal.vue +1 -2
  117. package/src/composables/filePicker/localFiles.ts +21 -14
  118. package/src/composables/filePicker/usePickerSelection.ts +15 -4
  119. package/src/composables/index.ts +10 -0
  120. package/src/composables/pluginWorkspaceModel.ts +0 -3
  121. package/src/composables/useManualLayoutResize.ts +165 -0
  122. package/src/composables/usePluginWorkspace.ts +1 -2
  123. package/src/composables/useToast.ts +21 -5
  124. package/src/generated/schema.ts +58 -18
  125. package/src/styles/components/adduct-text.css +45 -0
  126. package/src/styles/components/app-sidebar.css +282 -121
  127. package/src/styles/components/chart-container.css +92 -0
  128. package/src/styles/components/chemical-formula.css +34 -4
  129. package/src/styles/components/form-builder.css +1 -1
  130. package/src/styles/components/form-field.css +28 -0
  131. package/src/styles/components/layout-resize-handle.css +60 -0
  132. package/src/styles/components/number-input.css +75 -91
  133. package/src/styles/components/pill.css +49 -51
  134. package/src/styles/components/rack-editor.css +31 -9
  135. package/src/styles/components/searchable-select.css +63 -0
  136. package/src/styles/components/segmented-control.css +16 -11
  137. package/src/styles/components/tabs.css +18 -34
  138. package/src/styles/components/toast.css +136 -27
  139. package/src/styles/components/well-plate.css +9 -0
  140. package/src/styles/index.css +3 -0
  141. package/src/styles/variables.css +25 -5
  142. package/src/types/componentLabTypes.ts +6 -0
  143. package/src/types/components.ts +30 -0
  144. package/src/types/form-builder.ts +2 -0
  145. package/src/types/generated-ui.ts +2 -0
  146. package/src/types/index.ts +5 -0
  147. package/dist/SettingsModal-BYR20I4c.js.map +0 -1
  148. package/dist/Skeleton-BAF3CKY7.js.map +0 -1
  149. package/dist/components-DIum5hkx.js.map +0 -1
  150. package/dist/composables-mFXsTA4g.js.map +0 -1
  151. package/dist/useControlSchema-DldpxNOP.js.map +0 -1
  152. package/dist/validation-uwoJGEb6.js.map +0 -1
@@ -12,6 +12,9 @@ export interface Well {
12
12
  value?: number;
13
13
  metadata?: Record<string, unknown>;
14
14
  }
15
+ export type WellClassValue = string | string[] | Record<string, boolean>;
16
+ export type WellClassResolver = (well: Well) => WellClassValue | undefined;
17
+ export type WellStyleResolver = (well: Well) => Record<string, string | number | undefined> | undefined;
15
18
  export type HeatmapColorScale = 'viridis' | 'plasma' | 'turbo' | 'custom';
16
19
  export interface HeatmapConfig {
17
20
  enabled: boolean;
@@ -36,12 +36,33 @@ export interface ModalTab {
36
36
  disabled?: boolean;
37
37
  }
38
38
  export type AlertType = 'success' | 'error' | 'warning' | 'info';
39
+ export interface ToastAction {
40
+ label: string;
41
+ onClick: () => void;
42
+ primary?: boolean;
43
+ }
39
44
  export interface Toast {
40
45
  id: number;
46
+ /** Legacy single-line body; kept as an alias of `title`. */
41
47
  message: string;
42
48
  type: 'success' | 'error' | 'warning' | 'info';
43
49
  duration?: number;
50
+ title?: string;
51
+ detail?: string;
52
+ /** At most two; extra entries are dropped. */
53
+ actions?: ToastAction[];
54
+ /** Render the close button (default true). */
55
+ dismissible?: boolean;
56
+ /** `ttl` (default) shrinks over `duration`; `indeterminate` never auto-dismisses; `none` hides the bar. */
57
+ progress?: 'ttl' | 'indeterminate' | 'none';
58
+ /** Collapsed-stack count; renders the `×N` pill when above 1. */
59
+ count?: number;
44
60
  }
61
+ export type ToastOptions = Omit<Toast, 'id' | 'message' | 'type'> & {
62
+ title: string;
63
+ type?: Toast['type'];
64
+ message?: string;
65
+ };
45
66
  export interface TabItem {
46
67
  id: string;
47
68
  label: string;
@@ -56,6 +77,10 @@ export interface SelectOption<T = string> {
56
77
  label: string;
57
78
  disabled?: boolean;
58
79
  description?: string;
80
+ /** Short trailing classification, count, or status. */
81
+ meta?: string;
82
+ /** Explanation shown for an unavailable option. */
83
+ disabledReason?: string;
59
84
  }
60
85
  export type SelectOptionInput<T extends OptionPrimitive = OptionPrimitive> = SelectOption<T> | T;
61
86
  export interface RadioOption {
@@ -178,7 +203,7 @@ export interface AccountMenuItem {
178
203
  danger?: boolean;
179
204
  divider?: boolean;
180
205
  }
181
- export type { WellPlateFormat, WellState, WellPlateSelectionMode, WellPlateSize, WellShape, Well, HeatmapColorScale, HeatmapConfig, SlotPosition, WellExtendedData, WellEditData, WellEditField, WellSampleDropData, WellSampleDropContext, WellSampleDropParser, WellLegendItem, PlateCondition, ColumnCondition, RowCondition, Rack, RackSampleDropContext, RackSampleDropMapper, SampleType, PlateMap, PlateMapEditorState, ProtocolStepType, ProtocolStepStatus, ProtocolStep, SampleGroup, GroupItem, FileUploaderMode, MoleculeData, StorageCondition, ReagentColumn, Reagent, TreeNodeType, BadgeVariant, TreeNode, } from './componentLabTypes';
206
+ export type { WellPlateFormat, WellState, WellPlateSelectionMode, WellPlateSize, WellShape, Well, WellClassValue, WellClassResolver, WellStyleResolver, HeatmapColorScale, HeatmapConfig, SlotPosition, WellExtendedData, WellEditData, WellEditField, WellSampleDropData, WellSampleDropContext, WellSampleDropParser, WellLegendItem, PlateCondition, ColumnCondition, RowCondition, Rack, RackSampleDropContext, RackSampleDropMapper, SampleType, PlateMap, PlateMapEditorState, ProtocolStepType, ProtocolStepStatus, ProtocolStep, SampleGroup, GroupItem, FileUploaderMode, MoleculeData, StorageCondition, ReagentColumn, Reagent, TreeNodeType, BadgeVariant, TreeNode, } from './componentLabTypes';
182
207
  export interface SegmentedOption {
183
208
  value: string | number;
184
209
  label: string;
@@ -87,6 +87,8 @@ export interface FormFieldSchema extends AccessControlled {
87
87
  colSpan?: number;
88
88
  /** Extra props passed directly to the underlying component. */
89
89
  props?: Record<string, unknown>;
90
+ /** Element type for `tags` fields; `number` parses each entered tag back to a number. */
91
+ itemType?: 'string' | 'number';
90
92
  }
91
93
  export type FormOptionInput = SelectOption<unknown> | OptionPrimitive;
92
94
  export interface FormSectionSchema {
@@ -10,6 +10,8 @@ export interface GeneratedJsonSchema {
10
10
  minimum?: number;
11
11
  maximum?: number;
12
12
  exclusiveMinimum?: number;
13
+ exclusiveMaximum?: number;
14
+ multipleOf?: number;
13
15
  minLength?: number;
14
16
  maxLength?: number;
15
17
  pattern?: string;
@@ -1,4 +1,4 @@
1
- export type { ContainerDirection, ButtonVariant, ButtonSize, ActionMenuItem, InputType, ModalSize, ModalVariant, ModalLayout, ModalTab, AlertType, Toast, TabItem, TabItemInput, OptionPrimitive, SelectOption, SelectOptionInput, RadioOption, RadioOptionInput, FormFieldProps, SectionCardAccent, SectionCardDivider, SidebarBadgeTone, SidebarToolSection, SidebarToolSectionAction, CollapsibleState, TopBarVariant, TopBarSettingsConfig, PillNavOption, PillNavOptionInput, PillNavItem, PillNavItemInput, PageSelectorItem, PageSelectorItemInput, PluginSwitcherPlugin, PluginSwitcherInfo, AccountMenuItem, WellPlateFormat, WellState, WellPlateSelectionMode, WellPlateSize, WellShape, Well, HeatmapColorScale, HeatmapConfig, SlotPosition, WellExtendedData, WellEditData, WellEditField, WellSampleDropData, WellSampleDropContext, WellSampleDropParser, WellLegendItem, PlateCondition, ColumnCondition, RowCondition, Rack, RackSampleDropContext, RackSampleDropMapper, 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, SettingsUserType, SettingsAudience, SettingsAudienceInput, 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, ActionMenuItem, InputType, ModalSize, ModalVariant, ModalLayout, ModalTab, AlertType, Toast, ToastAction, ToastOptions, TabItem, TabItemInput, OptionPrimitive, SelectOption, SelectOptionInput, RadioOption, RadioOptionInput, FormFieldProps, SectionCardAccent, SectionCardDivider, SidebarBadgeTone, SidebarToolSection, SidebarToolSectionAction, CollapsibleState, TopBarVariant, TopBarSettingsConfig, PillNavOption, PillNavOptionInput, PillNavItem, PillNavItemInput, PageSelectorItem, PageSelectorItemInput, PluginSwitcherPlugin, PluginSwitcherInfo, AccountMenuItem, WellPlateFormat, WellState, WellPlateSelectionMode, WellPlateSize, WellShape, Well, WellClassValue, WellClassResolver, WellStyleResolver, HeatmapColorScale, HeatmapConfig, SlotPosition, WellExtendedData, WellEditData, WellEditField, WellSampleDropData, WellSampleDropContext, WellSampleDropParser, WellLegendItem, PlateCondition, ColumnCondition, RowCondition, Rack, RackSampleDropContext, RackSampleDropMapper, 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, SettingsUserType, SettingsAudience, SettingsAudienceInput, 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 * from './generated-ui';
3
3
  export type { AnalysisArtifactStatus, AnalysisArtifactStatusFilter, AnalysisArtifactSummary, AnalysisArtifactDetail, AnalysisArtifactListResponse, AnalysisArtifactTarget, AnalysisArtifactMetadataUpdate, ArtifactSaveMode, ArtifactFileSource, JsonArtifactSavePayload, FileArtifactCreatePayload, FileArtifactUpdatePayload, HandlerFileArtifactCreatePayload, HandlerFileArtifactUpdatePayload, ArtifactSavePayload, HandlerArtifactSavePayload, ArtifactSaveDialogPayload, ArtifactSaveResult, ArtifactSaveHandler, HandlerArtifactSaveHandler, ArtifactSaveDialogHandler, } from './analysisArtifactTypes';
4
4
  export { ANALYSIS_FILE_ARTIFACT_SCHEMA } from './analysisArtifactTypes';
@@ -1,6 +1,6 @@
1
1
  import { f as MintApiError, i as useApi, p as mintApiErrorFromResponse, u as tryUseSettingsStore } from "./errors-BLuqMee5.js";
2
2
  import { c as formatExperimentDate, f as BaseModal_default, h as BaseButton_default, m as useEventListener, p as useFocusTrap } from "./experiment-utils-CV2Wza3z.js";
3
- import { a as BaseSelect_default, i as BasePill_default, n as useRequestSyncState, o as normalizeOptionInput, r as EmptyState_default, s as BaseInput_default, t as Skeleton_default } from "./Skeleton-BAF3CKY7.js";
3
+ import { a as BaseSelect_default, i as BasePill_default, n as useRequestSyncState, o as normalizeOptionInput, r as EmptyState_default, s as BaseInput_default, t as Skeleton_default } from "./Skeleton-jhF9wUkU.js";
4
4
  import { t as useDropdownState } from "./useDropdownState-C7hRiVQf.js";
5
5
  import { hasAllPermissions } from "./permissions.js";
6
6
  import { Fragment, Teleport, Transition, TransitionGroup, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createStaticVNode, createTextVNode, createVNode, defineComponent, getCurrentInstance, getCurrentScope, isRef, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, onScopeDispose, onUnmounted, openBlock, reactive, ref, renderList, renderSlot, shallowRef, toDisplayString, toValue, unref, useId, useSlots, vModelText, watch, withCtx, withDirectives, withKeys, withModifiers } from "vue";
@@ -2155,6 +2155,14 @@ var SecretInput_default = /* @__PURE__ */ defineComponent({
2155
2155
  //#region src/components/NumberInput.vue?vue&type=script&setup=true&lang.ts
2156
2156
  var _hoisted_1$10 = { class: "mint-number-input__field" };
2157
2157
  var _hoisted_2$9 = [
2158
+ "role",
2159
+ "tabindex",
2160
+ "aria-valuenow",
2161
+ "aria-valuemin",
2162
+ "aria-valuemax",
2163
+ "aria-orientation"
2164
+ ];
2165
+ var _hoisted_3$8 = [
2158
2166
  "value",
2159
2167
  "min",
2160
2168
  "max",
@@ -2162,23 +2170,16 @@ var _hoisted_2$9 = [
2162
2170
  "disabled",
2163
2171
  "placeholder"
2164
2172
  ];
2165
- var _hoisted_3$8 = {
2166
- key: 0,
2173
+ var _hoisted_4$8 = {
2174
+ key: 1,
2167
2175
  class: "mint-number-input__unit"
2168
2176
  };
2169
- var _hoisted_4$8 = {
2177
+ var _hoisted_5$7 = {
2170
2178
  class: "mint-number-input__steppers",
2171
2179
  "aria-hidden": "true"
2172
2180
  };
2173
- var _hoisted_5$7 = ["disabled"];
2174
2181
  var _hoisted_6$7 = ["disabled"];
2175
- var _hoisted_7$7 = [
2176
- "value",
2177
- "min",
2178
- "max",
2179
- "step",
2180
- "disabled"
2181
- ];
2182
+ var _hoisted_7$7 = ["disabled"];
2182
2183
  //#endregion
2183
2184
  //#region src/components/NumberInput.vue
2184
2185
  var NumberInput_default = /* @__PURE__ */ defineComponent({
@@ -2202,7 +2203,7 @@ var NumberInput_default = /* @__PURE__ */ defineComponent({
2202
2203
  },
2203
2204
  emits: ["update:modelValue"],
2204
2205
  setup(__props, { emit: __emit }) {
2205
- /** Numeric input with increment/decrement buttons, optional unit label, and slider progress track. */
2206
+ /** Numeric input with always-visible steppers, optional unit label, and (with min+max) an in-field drag-to-scrub range fill. */
2206
2207
  const props = __props;
2207
2208
  const emit = __emit;
2208
2209
  const isSliderMode = computed(() => props.min !== void 0 && props.max !== void 0);
@@ -2212,7 +2213,7 @@ var NumberInput_default = /* @__PURE__ */ defineComponent({
2212
2213
  if (min === void 0 || max === void 0 || props.modelValue === void 0) return 0;
2213
2214
  const range = max - min;
2214
2215
  if (range === 0) return 0;
2215
- return (props.modelValue - min) / range * 100;
2216
+ return Math.min(100, Math.max(0, (props.modelValue - min) / range * 100));
2216
2217
  });
2217
2218
  const canDecrement = computed(() => {
2218
2219
  if (props.modelValue === void 0) return true;
@@ -2230,24 +2231,112 @@ var NumberInput_default = /* @__PURE__ */ defineComponent({
2230
2231
  if (props.max !== void 0 && result > props.max) result = props.max;
2231
2232
  return result;
2232
2233
  }
2234
+ /** Clamp and trim float noise (0.1 + 0.2 → 0.3) without losing real precision. */
2235
+ function settle(value) {
2236
+ return Number(clamp(value).toFixed(10));
2237
+ }
2238
+ /** Snap to the step grid anchored at `min`, for pointer scrubbing. */
2239
+ function snap(value) {
2240
+ const origin = props.min ?? 0;
2241
+ return settle(origin + Math.round((value - origin) / props.step) * props.step);
2242
+ }
2233
2243
  function handleInput(event) {
2234
2244
  const target = event.target;
2235
2245
  const value = target.value === "" ? void 0 : Number(target.value);
2236
2246
  if (value !== void 0 && !isNaN(value)) emit("update:modelValue", clamp(value));
2237
2247
  else emit("update:modelValue", void 0);
2238
2248
  }
2239
- function handleSliderInput(event) {
2240
- const target = event.target;
2241
- const value = Number(target.value);
2242
- if (!isNaN(value)) emit("update:modelValue", clamp(value));
2249
+ function nudge(delta) {
2250
+ if (props.disabled) return;
2251
+ if (delta < 0 && !canDecrement.value) return;
2252
+ if (delta > 0 && !canIncrement.value) return;
2253
+ emit("update:modelValue", settle((props.modelValue ?? (delta < 0 ? props.max ?? 0 : props.min ?? 0)) + delta));
2243
2254
  }
2244
2255
  function decrement() {
2245
- if (props.disabled || !canDecrement.value) return;
2246
- emit("update:modelValue", clamp((props.modelValue ?? props.max ?? 0) - props.step));
2256
+ nudge(-props.step);
2247
2257
  }
2248
2258
  function increment() {
2249
- if (props.disabled || !canIncrement.value) return;
2250
- emit("update:modelValue", clamp((props.modelValue ?? props.min ?? 0) + props.step));
2259
+ nudge(props.step);
2260
+ }
2261
+ function handleKeydown(event, allowJump = false) {
2262
+ if (props.disabled) return;
2263
+ switch (event.key) {
2264
+ case "ArrowUp":
2265
+ increment();
2266
+ break;
2267
+ case "ArrowDown":
2268
+ decrement();
2269
+ break;
2270
+ case "PageUp":
2271
+ nudge(props.step * 10);
2272
+ break;
2273
+ case "PageDown":
2274
+ nudge(-props.step * 10);
2275
+ break;
2276
+ case "Home":
2277
+ if (!allowJump || props.min === void 0) return;
2278
+ emit("update:modelValue", props.min);
2279
+ break;
2280
+ case "End":
2281
+ if (!allowJump || props.max === void 0) return;
2282
+ emit("update:modelValue", props.max);
2283
+ break;
2284
+ default: return;
2285
+ }
2286
+ event.preventDefault();
2287
+ }
2288
+ function scrubTo(clientX, area) {
2289
+ const rect = area.getBoundingClientRect();
2290
+ if (rect.width === 0 || props.min === void 0 || props.max === void 0) return;
2291
+ const ratio = Math.min(1, Math.max(0, (clientX - rect.left) / rect.width));
2292
+ emit("update:modelValue", snap(props.min + ratio * (props.max - props.min)));
2293
+ }
2294
+ let stopScrubbing;
2295
+ onBeforeUnmount(() => stopScrubbing?.());
2296
+ function handleScrubStart(event) {
2297
+ const target = event.target;
2298
+ const onNumber = target.tagName === "INPUT";
2299
+ if (props.disabled || event.button !== 0 || !onNumber && !isSliderMode.value) return;
2300
+ stopScrubbing?.();
2301
+ const area = event.currentTarget;
2302
+ const startValue = props.modelValue ?? props.min ?? 0;
2303
+ const width = area.getBoundingClientRect().width;
2304
+ const unitsPerPixel = isSliderMode.value && width > 0 ? (props.max - props.min) / width : props.step / 8;
2305
+ if (!onNumber) {
2306
+ event.preventDefault();
2307
+ scrubTo(event.clientX, area);
2308
+ }
2309
+ target.setPointerCapture?.(event.pointerId);
2310
+ let dragging = false;
2311
+ const move = (e) => {
2312
+ if (e.pointerId !== event.pointerId) return;
2313
+ if (props.disabled) {
2314
+ stop();
2315
+ return;
2316
+ }
2317
+ if (!onNumber) {
2318
+ scrubTo(e.clientX, area);
2319
+ return;
2320
+ }
2321
+ const delta = e.clientX - event.clientX;
2322
+ if (!dragging && Math.abs(delta) < 4) return;
2323
+ dragging = true;
2324
+ e.preventDefault();
2325
+ emit("update:modelValue", settle(startValue + Math.round(delta * unitsPerPixel / props.step) * props.step));
2326
+ };
2327
+ const stop = () => {
2328
+ area.removeEventListener("pointermove", move);
2329
+ area.removeEventListener("pointerup", stop);
2330
+ area.removeEventListener("pointercancel", stop);
2331
+ area.removeEventListener("lostpointercapture", stop);
2332
+ if (target.hasPointerCapture?.(event.pointerId)) target.releasePointerCapture(event.pointerId);
2333
+ stopScrubbing = void 0;
2334
+ };
2335
+ stopScrubbing = stop;
2336
+ area.addEventListener("pointermove", move);
2337
+ area.addEventListener("pointerup", stop);
2338
+ area.addEventListener("pointercancel", stop);
2339
+ area.addEventListener("lostpointercapture", stop);
2251
2340
  }
2252
2341
  return (_ctx, _cache) => {
2253
2342
  return openBlock(), createElementBlock("div", { class: normalizeClass([
@@ -2256,7 +2345,25 @@ var NumberInput_default = /* @__PURE__ */ defineComponent({
2256
2345
  isSliderMode.value ? "mint-number-input--slider" : "mint-number-input--stepper",
2257
2346
  __props.error ? "mint-number-input--error" : "",
2258
2347
  __props.disabled ? "mint-number-input--disabled" : ""
2259
- ]) }, [createElementVNode("div", _hoisted_1$10, [
2348
+ ]) }, [createElementVNode("div", _hoisted_1$10, [createElementVNode("div", {
2349
+ class: "mint-number-input__scrub",
2350
+ style: normalizeStyle(isSliderMode.value ? { "--mint-number-input-fill": `${sliderPercent.value}%` } : void 0),
2351
+ role: isSliderMode.value ? "slider" : void 0,
2352
+ tabindex: isSliderMode.value && !__props.disabled ? 0 : void 0,
2353
+ "aria-valuenow": isSliderMode.value ? __props.modelValue : void 0,
2354
+ "aria-valuemin": isSliderMode.value ? __props.min : void 0,
2355
+ "aria-valuemax": isSliderMode.value ? __props.max : void 0,
2356
+ "aria-orientation": isSliderMode.value ? "horizontal" : void 0,
2357
+ onPointerdown: handleScrubStart,
2358
+ onKeydown: _cache[0] || (_cache[0] = withModifiers(($event) => isSliderMode.value && handleKeydown($event, true), ["self"]))
2359
+ }, [
2360
+ isSliderMode.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [_cache[1] || (_cache[1] = createElementVNode("span", {
2361
+ class: "mint-number-input__wash",
2362
+ "aria-hidden": "true"
2363
+ }, null, -1)), _cache[2] || (_cache[2] = createElementVNode("span", {
2364
+ class: "mint-number-input__rule",
2365
+ "aria-hidden": "true"
2366
+ }, null, -1))], 64)) : createCommentVNode("", true),
2260
2367
  createElementVNode("input", {
2261
2368
  type: "number",
2262
2369
  value: __props.modelValue,
@@ -2266,50 +2373,37 @@ var NumberInput_default = /* @__PURE__ */ defineComponent({
2266
2373
  disabled: __props.disabled,
2267
2374
  placeholder: __props.placeholder,
2268
2375
  class: normalizeClass(["mint-number-input__input", `mint-number-input__input--${__props.size}`]),
2269
- onInput: handleInput
2270
- }, null, 42, _hoisted_2$9),
2271
- __props.unit ? (openBlock(), createElementBlock("span", _hoisted_3$8, toDisplayString(__props.unit), 1)) : createCommentVNode("", true),
2272
- createElementVNode("div", _hoisted_4$8, [createElementVNode("button", {
2273
- type: "button",
2274
- tabindex: "-1",
2275
- "aria-label": "Increase value",
2276
- disabled: __props.disabled || !canIncrement.value,
2277
- class: "mint-number-input__stepper mint-number-input__stepper--up",
2278
- onClick: increment
2279
- }, [..._cache[0] || (_cache[0] = [createElementVNode("svg", {
2280
- viewBox: "0 0 10 6",
2281
- fill: "none",
2282
- stroke: "currentColor",
2283
- "stroke-width": "1.5",
2284
- "stroke-linecap": "round",
2285
- "stroke-linejoin": "round"
2286
- }, [createElementVNode("path", { d: "M1 5l4-4 4 4" })], -1)])], 8, _hoisted_5$7), createElementVNode("button", {
2287
- type: "button",
2288
- tabindex: "-1",
2289
- "aria-label": "Decrease value",
2290
- disabled: __props.disabled || !canDecrement.value,
2291
- class: "mint-number-input__stepper mint-number-input__stepper--down",
2292
- onClick: decrement
2293
- }, [..._cache[1] || (_cache[1] = [createElementVNode("svg", {
2294
- viewBox: "0 0 10 6",
2295
- fill: "none",
2296
- stroke: "currentColor",
2297
- "stroke-width": "1.5",
2298
- "stroke-linecap": "round",
2299
- "stroke-linejoin": "round"
2300
- }, [createElementVNode("path", { d: "M1 1l4 4 4-4" })], -1)])], 8, _hoisted_6$7)])
2301
- ]), isSliderMode.value ? (openBlock(), createElementBlock("input", {
2302
- key: 0,
2303
- type: "range",
2304
- value: __props.modelValue ?? __props.min,
2305
- min: __props.min,
2306
- max: __props.max,
2307
- step: __props.step,
2308
- disabled: __props.disabled,
2309
- style: normalizeStyle({ "--mint-slider-fill": `${sliderPercent.value}%` }),
2310
- class: "mint-number-input__slider",
2311
- onInput: handleSliderInput
2312
- }, null, 44, _hoisted_7$7)) : createCommentVNode("", true)], 2);
2376
+ onInput: handleInput,
2377
+ onKeydown: handleKeydown
2378
+ }, null, 42, _hoisted_3$8),
2379
+ __props.unit ? (openBlock(), createElementBlock("span", _hoisted_4$8, toDisplayString(__props.unit), 1)) : createCommentVNode("", true)
2380
+ ], 44, _hoisted_2$9), createElementVNode("div", _hoisted_5$7, [createElementVNode("button", {
2381
+ type: "button",
2382
+ tabindex: "-1",
2383
+ "aria-label": "Decrease value",
2384
+ disabled: __props.disabled || !canDecrement.value,
2385
+ class: "mint-number-input__stepper mint-number-input__stepper--down",
2386
+ onClick: decrement
2387
+ }, [..._cache[3] || (_cache[3] = [createElementVNode("svg", {
2388
+ viewBox: "0 0 10 10",
2389
+ fill: "none",
2390
+ stroke: "currentColor",
2391
+ "stroke-width": "1.6",
2392
+ "stroke-linecap": "round"
2393
+ }, [createElementVNode("path", { d: "M2 5h6" })], -1)])], 8, _hoisted_6$7), createElementVNode("button", {
2394
+ type: "button",
2395
+ tabindex: "-1",
2396
+ "aria-label": "Increase value",
2397
+ disabled: __props.disabled || !canIncrement.value,
2398
+ class: "mint-number-input__stepper mint-number-input__stepper--up",
2399
+ onClick: increment
2400
+ }, [..._cache[4] || (_cache[4] = [createElementVNode("svg", {
2401
+ viewBox: "0 0 10 10",
2402
+ fill: "none",
2403
+ stroke: "currentColor",
2404
+ "stroke-width": "1.6",
2405
+ "stroke-linecap": "round"
2406
+ }, [createElementVNode("path", { d: "M5 2v6" }), createElementVNode("path", { d: "M2 5h6" })], -1)])], 8, _hoisted_7$7)])])], 2);
2313
2407
  };
2314
2408
  }
2315
2409
  });
@@ -2386,7 +2480,9 @@ var FileUploader_default = /* @__PURE__ */ defineComponent({
2386
2480
  showFiles: {
2387
2481
  type: Boolean,
2388
2482
  default: true
2389
- }
2483
+ },
2484
+ files: {},
2485
+ rootName: {}
2390
2486
  },
2391
2487
  emits: [
2392
2488
  "upload",
@@ -2401,6 +2497,11 @@ var FileUploader_default = /* @__PURE__ */ defineComponent({
2401
2497
  const inputRef = ref();
2402
2498
  const selectedFiles = ref([]);
2403
2499
  const folderName = ref(null);
2500
+ watch(() => [props.files, props.rootName], ([files, rootName]) => {
2501
+ if (files === void 0) return;
2502
+ selectedFiles.value = [...files];
2503
+ folderName.value = rootName ?? extractFolderName(files);
2504
+ }, { immediate: true });
2404
2505
  const isFolder = computed(() => props.mode === "folder");
2405
2506
  const isMixed = computed(() => props.mode === "file+folder");
2406
2507
  const acceptLabel = computed(() => {
@@ -4722,6 +4823,11 @@ var GeneratedPathInput_default = /* @__PURE__ */ _plugin_vue_export_helper_defau
4722
4823
  const props = __props;
4723
4824
  const emit = __emit;
4724
4825
  const mode = ref("file");
4826
+ const selections = computed(() => Array.isArray(props.modelValue) ? props.modelValue : props.modelValue ? [props.modelValue] : []);
4827
+ const selectedFiles = computed(() => selections.value.flatMap((selection) => selection.files));
4828
+ watch(selections, (current) => {
4829
+ if (current.length) mode.value = current.every((selection) => selection.rootName) ? "folder" : "file";
4830
+ }, { immediate: true });
4725
4831
  const artifactOpen = ref(false);
4726
4832
  const artifactLoading = ref(false);
4727
4833
  const artifactError = ref("");
@@ -4750,7 +4856,7 @@ var GeneratedPathInput_default = /* @__PURE__ */ _plugin_vue_export_helper_defau
4750
4856
  }
4751
4857
  function removeFiles(files) {
4752
4858
  const removed = new Set(files);
4753
- const remaining = (Array.isArray(props.modelValue) ? props.modelValue : props.modelValue ? [props.modelValue] : []).flatMap((selection) => {
4859
+ const remaining = selections.value.flatMap((selection) => {
4754
4860
  const indexes = selection.files.map((file, index) => removed.has(file) ? -1 : index).filter((index) => index >= 0);
4755
4861
  if (!indexes.length) return [];
4756
4862
  return [{
@@ -4831,12 +4937,16 @@ var GeneratedPathInput_default = /* @__PURE__ */ _plugin_vue_export_helper_defau
4831
4937
  (openBlock(), createBlock(FileUploader_default, {
4832
4938
  key: mode.value,
4833
4939
  mode: mode.value,
4940
+ files: selectedFiles.value,
4941
+ "root-name": selections.value[0]?.rootName,
4834
4942
  multiple: __props.multiple && mode.value === "file",
4835
4943
  disabled: __props.disabled,
4836
4944
  onUpload: selectFiles,
4837
4945
  onRemove: removeFiles
4838
4946
  }, null, 8, [
4839
4947
  "mode",
4948
+ "files",
4949
+ "root-name",
4840
4950
  "multiple",
4841
4951
  "disabled"
4842
4952
  ])),
@@ -4857,7 +4967,7 @@ var GeneratedPathInput_default = /* @__PURE__ */ _plugin_vue_export_helper_defau
4857
4967
  ]);
4858
4968
  };
4859
4969
  }
4860
- }), [["__scopeId", "data-v-9011f2f2"]]);
4970
+ }), [["__scopeId", "data-v-9147bd02"]]);
4861
4971
  //#endregion
4862
4972
  //#region src/composables/useChemicalFormula.ts
4863
4973
  var ATOMIC_WEIGHTS = {
@@ -7188,4 +7298,4 @@ function useControlSchema(controls, options = {}) {
7188
7298
  //#endregion
7189
7299
  export { resolveJobCapabilities as $, useConcentrationUnits as A, formatTimeSlot as At, currentExperimentFromContext as B, MultiSelect_default as Bt, controlsToViewIds as C, addMinutes as Ct, getTypeDefault as D, findNearestTimeSlotIndex as Dt, getFieldRegistryEntry as E, findAvailableSlots as Et, ATOMIC_WEIGHTS as F, rangesOverlap as Ft, createGeneratedAnalysisTransport as G, BaseToggle_default as Gt, parseExperimentId as H, useSelectionLimit as Ht, useChemicalFormula as I, snapToSlot as It, isActiveJobStatus as J, BaseTextarea_default as Jt, useGeneratedAnalysis as K, BaseCheckbox_default as Kt, GeneratedPathInput_default as L, toMinutes as Lt, SequenceInput_default as M, generateTimeSlots as Mt, useSequenceUtils as N, isTimeInRange as Nt, ConcentrationInput_default as O, formatDuration as Ot, FormulaInput_default as P, parseTime as Pt, normalizeJobState as Q, ArtifactSelectorModal_default as R, useTimeUtils as Rt, controlsToTopBarSettingsConfig as S, TimePicker_default as St, getDefaultControlView as T, durationMinutes as Tt, resolveCurrentExperimentId as U, BaseSlider_default as Ut, getInjectedPlatformContext as V, useListSelection as Vt, resolveCurrentPluginId as W, BaseRadioGroup_default as Wt, jobStatusLabel as X, isTerminalJobStatus as Y, normalizeJobPercent as Z, controlsToFormSchema as _, pluginSecretLabel as _t, defineDoseCalculatorControlProps as a, AlertBox_default as at, controlsToSettingsSchema as b, usesPluginSecretReferences as bt, defineWellPlateDoseComponentBindings as c, SecretInput_default as ct, defineControlModel as d, PLUGIN_SECRET_REF_KEY as dt, useEventStream as et, resolveControlModel as f, clearPluginSecret as ft, mergeControlWorkspaceOptions as g, pluginSecretId as gt, controlValuesToComponentProps as h, keepPluginSecret as ht, useControlSchema as i, _plugin_vue_export_helper_default as it, MoleculeInput_default as j, fromMinutes as jt, UnitInput_default as k, formatTime as kt, defineWellPlateDoseControlProps as l, PLUGIN_SECRET_FORMAT_KEY as lt, controlValuesToComponentBindingsById as m, isPluginSecretRef as mt, defineControls as n, isObjectLike as nt, defineDoseDesignControlModel as o, FileUploader_default as ot, controlValuesToComponentBindings as p, isPluginSecretLocked as pt, usePluginJobs as q, Tooltip_default as qt, getControlDefaults as r, isRecord as rt, defineWellPlateControlProps as s, NumberInput_default as st, defineControlComponentBindings as t, DateTimePicker_default as tt, useControlWorkspace as u, PLUGIN_SECRET_FORMAT_REF as ut, controlsToSectionFormSchema as v, pluginSecretState as vt, controlsToViewItems as w, compareTime as wt, controlsToSidebarPanels as x, TagsInput_default as xt, controlsToSectionFormSchemas as y, setPluginSecret as yt, useAnalysisArtifacts as z, DatePicker_default as zt };
7190
7300
 
7191
- //# sourceMappingURL=useControlSchema-DldpxNOP.js.map
7301
+ //# sourceMappingURL=useControlSchema-vLiRPUmj.js.map