@morscherlab/mint-sdk 1.0.0-rc.4 → 1.0.0-rc.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/dist/__tests__/components/AppTopBar.navigation.test.d.ts +1 -0
- package/dist/__tests__/components/DoseCalculatorVolumeField.test.d.ts +1 -0
- package/dist/__tests__/components/PlateMapEditorToolbarInternal.test.d.ts +1 -0
- package/dist/__tests__/components/PluginWorkspaceView.controls.test.d.ts +1 -0
- package/dist/__tests__/components/PluginWorkspaceView.navigation.test.d.ts +1 -0
- package/dist/__tests__/components/PluginWorkspaceView.shell.test.d.ts +1 -0
- package/dist/__tests__/components/ProtocolStep.presentation.test.d.ts +1 -0
- package/dist/__tests__/components/ProtocolStepEditor.state.test.d.ts +1 -0
- package/dist/__tests__/components/ProtocolStepParameterField.test.d.ts +1 -0
- package/dist/__tests__/components/ReagentList.presentation.test.d.ts +1 -0
- package/dist/__tests__/components/SampleSelector.colors.test.d.ts +1 -0
- package/dist/__tests__/components/SampleSelector.drag.test.d.ts +1 -0
- package/dist/__tests__/components/SampleSelector.groups.test.d.ts +1 -0
- package/dist/__tests__/components/SampleSelector.selection.test.d.ts +1 -0
- package/dist/__tests__/components/SampleSelectorSampleRow.test.d.ts +1 -0
- package/dist/__tests__/components/ScheduleCalendar.test.d.ts +1 -0
- package/dist/__tests__/components/SettingsModal.schema.test.d.ts +1 -0
- package/dist/__tests__/components/WellPlate.colors.test.d.ts +1 -0
- package/dist/__tests__/components/WellPlate.conditions.test.d.ts +1 -0
- package/dist/__tests__/components/WellPlate.geometry.test.d.ts +1 -0
- package/dist/__tests__/components/WellPlate.interaction.test.d.ts +1 -0
- package/dist/__tests__/components/WellPlate.legend.test.d.ts +1 -0
- package/dist/__tests__/components/WellPlate.rendering.test.d.ts +1 -0
- package/dist/__tests__/components/WellPlate.sampleDrop.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/classify.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/columns.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/compose.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/cooccurrence.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/fingerprint.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/integration.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/template.test.d.ts +1 -0
- package/dist/__tests__/composables/autoGroup/tokenize.test.d.ts +1 -0
- package/dist/__tests__/composables/useAutoGroupInputSources.test.d.ts +1 -0
- package/dist/__tests__/composables/useScheduleCalendarLayout.test.d.ts +1 -0
- package/dist/__tests__/docs/extractDocsComponents.test.d.ts +1 -0
- package/dist/__tests__/docs/extractDocsExports.test.d.ts +1 -0
- package/dist/__tests__/docs/extractDocsParsing.test.d.ts +1 -0
- package/dist/__tests__/docs/extractDocsTemplates.test.d.ts +1 -0
- package/dist/__tests__/docs/extractDocsTheme.test.d.ts +1 -0
- package/dist/components/AppSidebar.vue.d.ts +3 -3
- package/dist/components/AppTopBar.navigation.d.ts +11 -0
- package/dist/components/BaseButton.vue.d.ts +1 -1
- package/dist/components/BaseCheckbox.vue.d.ts +1 -1
- package/dist/components/BaseInput.vue.d.ts +2 -2
- package/dist/components/BasePill.vue.d.ts +1 -1
- package/dist/components/BaseRadioGroup.vue.d.ts +1 -1
- package/dist/components/BaseSelect.vue.d.ts +1 -1
- package/dist/components/BaseSlider.vue.d.ts +2 -2
- package/dist/components/BaseTextarea.vue.d.ts +2 -2
- package/dist/components/BaseToggle.vue.d.ts +1 -1
- package/dist/components/BioTemplateExperimentWorkspaceView.vue.d.ts +2 -2
- package/dist/components/BioTemplatePackWorkspaceView.vue.d.ts +1 -1
- package/dist/components/ColorSlider.vue.d.ts +2 -2
- package/dist/components/ConcentrationInput.vue.d.ts +2 -2
- package/dist/components/ControlWorkspaceView.vue.d.ts +3 -3
- package/dist/components/DatePicker.vue.d.ts +1 -1
- package/dist/components/DateTimePicker.vue.d.ts +2 -2
- package/dist/components/DoseCalculatorVolumeField.vue.d.ts +15 -0
- package/dist/components/DoseDesignWorkspaceView.vue.d.ts +1 -1
- package/dist/components/DropdownButton.vue.d.ts +1 -1
- package/dist/components/FileUploader.vue.d.ts +2 -2
- package/dist/components/FormulaInput.vue.d.ts +2 -2
- package/dist/components/IconButton.vue.d.ts +1 -1
- package/dist/components/LoadingSpinner.vue.d.ts +1 -1
- package/dist/components/MoleculeInput.vue.d.ts +2 -2
- package/dist/components/MultiSelect.vue.d.ts +1 -1
- package/dist/components/NumberInput.vue.d.ts +1 -1
- package/dist/components/PlateMapEditor.vue.d.ts +6 -6
- package/dist/components/PluginWorkspaceView.controls.d.ts +28 -0
- package/dist/components/PluginWorkspaceView.navigation.d.ts +29 -0
- package/dist/components/PluginWorkspaceView.props.d.ts +151 -0
- package/dist/components/PluginWorkspaceView.shell.d.ts +19 -0
- package/dist/components/PluginWorkspaceView.vue.d.ts +46 -195
- package/dist/components/ProgressBar.vue.d.ts +1 -1
- package/dist/components/ProtocolStep.presentation.d.ts +4 -0
- package/dist/components/ProtocolStepEditor.state.d.ts +18 -0
- package/dist/components/ProtocolStepParameterField.vue.d.ts +12 -0
- package/dist/components/ReagentList.presentation.d.ts +16 -0
- package/dist/components/ResourceCard.vue.d.ts +1 -1
- package/dist/components/SampleSelector.colors.d.ts +13 -0
- package/dist/components/SampleSelector.drag.d.ts +24 -0
- package/dist/components/SampleSelector.groups.d.ts +15 -0
- package/dist/components/SampleSelector.selection.d.ts +26 -0
- package/dist/components/SampleSelector.vue.d.ts +4 -1
- package/dist/components/SampleSelectorSampleRow.vue.d.ts +21 -0
- package/dist/components/SegmentedControl.vue.d.ts +1 -1
- package/dist/components/SequenceInput.vue.d.ts +2 -2
- package/dist/components/SequenceProgressBar.vue.d.ts +1 -1
- package/dist/components/SettingsModal.schema.d.ts +9 -0
- package/dist/components/StatusIndicator.vue.d.ts +1 -1
- package/dist/components/TagsInput.vue.d.ts +2 -2
- package/dist/components/TimePicker.vue.d.ts +2 -2
- package/dist/components/TimeRangeInput.vue.d.ts +1 -1
- package/dist/components/UnitInput.vue.d.ts +2 -2
- package/dist/components/WellPlate.colors.d.ts +9 -0
- package/dist/components/WellPlate.conditions.d.ts +26 -0
- package/dist/components/WellPlate.geometry.d.ts +23 -0
- package/dist/components/WellPlate.interaction.d.ts +71 -0
- package/dist/components/WellPlate.legend.d.ts +2 -0
- package/dist/components/WellPlate.rendering.d.ts +24 -0
- package/dist/components/WellPlate.sampleDrop.d.ts +8 -0
- package/dist/components/WellPlate.vue.d.ts +1 -1
- package/dist/components/index.js +2 -2
- package/dist/components/internal/ActionItemInternal.vue.d.ts +1 -1
- package/dist/components/internal/PlateMapEditorToolbarInternal.vue.d.ts +28 -0
- package/dist/{components-DafPc4rM.js → components-DtHA2bgp.js} +3754 -2991
- package/dist/components-DtHA2bgp.js.map +1 -0
- package/dist/composables/autoGroup/classKey.d.ts +4 -0
- package/dist/composables/autoGroup/classify.d.ts +28 -0
- package/dist/composables/autoGroup/colors.d.ts +2 -0
- package/dist/composables/autoGroup/columns.d.ts +10 -0
- package/dist/composables/autoGroup/compose.d.ts +8 -0
- package/dist/composables/autoGroup/cooccurrence.d.ts +2 -0
- package/dist/composables/autoGroup/csv-shim.d.ts +2 -0
- package/dist/composables/autoGroup/fingerprint.d.ts +3 -0
- package/dist/composables/autoGroup/index.d.ts +16 -0
- package/dist/composables/autoGroup/replicatePreGroup.d.ts +38 -0
- package/dist/composables/autoGroup/template.d.ts +15 -0
- package/dist/composables/autoGroup/tokenize.d.ts +8 -0
- package/dist/composables/autoGroupConstants.d.ts +1 -0
- package/dist/composables/autoGroupGrouping.d.ts +3 -0
- package/dist/composables/controlComponentBindings.d.ts +1 -1
- package/dist/composables/controlSchemaAdapters.d.ts +1 -1
- package/dist/composables/controlSchemaDoseDesign.d.ts +11 -0
- package/dist/composables/controlSchemaLayout.d.ts +1 -1
- package/dist/composables/controlSchemaModel.d.ts +5 -0
- package/dist/composables/controlSchemaNormalize.d.ts +1 -1
- package/dist/composables/controlSchemaTypes.d.ts +305 -0
- package/dist/composables/controlWorkspaceOptions.d.ts +1 -1
- package/dist/composables/formBuilderSchema.d.ts +18 -0
- package/dist/composables/index.js +3 -3
- package/dist/composables/pluginEndpointBuilder.d.ts +13 -0
- package/dist/composables/protocolTemplateCatalog.d.ts +26 -0
- package/dist/composables/useAutoGroup.d.ts +61 -74
- package/dist/composables/useAutoGroupInputSources.d.ts +32 -0
- package/dist/composables/useBioTemplateControls.d.ts +1 -1
- package/dist/composables/useBioTemplatePresetWorkspace.d.ts +1 -1
- package/dist/composables/useBioTemplateWorkspace.d.ts +1 -1
- package/dist/composables/useControlSchema.d.ts +4 -316
- package/dist/composables/useControlWorkspace.d.ts +1 -1
- package/dist/composables/useForm.d.ts +2 -33
- package/dist/composables/useFormBuilder.d.ts +2 -9
- package/dist/composables/useFormValidation.d.ts +34 -0
- package/dist/composables/usePluginClient.d.ts +1 -4
- package/dist/composables/useProtocolTemplates.d.ts +2 -24
- package/dist/composables/useScheduleCalendarLayout.d.ts +49 -0
- package/dist/{composables-BMkPQhVK.js → composables-Dlg8jenH.js} +33 -31
- package/dist/composables-Dlg8jenH.js.map +1 -0
- package/dist/index.js +4 -4
- package/dist/install.js +2 -2
- package/dist/styles.css +547 -516
- package/dist/templates/controlSchemaTypes.d.ts +1 -1
- package/dist/templates/index.js +1 -1
- package/dist/templates/templateAdapterTypes.d.ts +48 -0
- package/dist/templates/templateCreateOptions.d.ts +165 -0
- package/dist/templates/templateQpcrTypes.d.ts +42 -0
- package/dist/templates/types.d.ts +5 -250
- package/dist/{templates-bUAWMn5L.js → templates-DtdUvJ4c.js} +144 -136
- package/dist/templates-DtdUvJ4c.js.map +1 -0
- package/dist/types/auto-group.d.ts +79 -9
- package/dist/types/componentLabTypes.d.ts +161 -0
- package/dist/types/componentWorkflowTypes.d.ts +150 -0
- package/dist/types/components.d.ts +2 -311
- package/dist/{useProtocolTemplates-QZtHFFH2.js → useProtocolTemplates-Bm5vyH4_.js} +1220 -454
- package/dist/useProtocolTemplates-Bm5vyH4_.js.map +1 -0
- package/package.json +1 -1
- package/src/__tests__/components/AppTopBar.navigation.test.ts +70 -0
- package/src/__tests__/components/DoseCalculatorVolumeField.test.ts +53 -0
- package/src/__tests__/components/PlateMapEditorToolbarInternal.test.ts +54 -0
- package/src/__tests__/components/PluginWorkspaceView.controls.test.ts +156 -0
- package/src/__tests__/components/PluginWorkspaceView.navigation.test.ts +102 -0
- package/src/__tests__/components/PluginWorkspaceView.shell.test.ts +41 -0
- package/src/__tests__/components/ProtocolStep.presentation.test.ts +31 -0
- package/src/__tests__/components/ProtocolStepEditor.state.test.ts +165 -0
- package/src/__tests__/components/ProtocolStepParameterField.test.ts +44 -0
- package/src/__tests__/components/ReagentList.presentation.test.ts +68 -0
- package/src/__tests__/components/SampleSelector.colors.test.ts +49 -0
- package/src/__tests__/components/SampleSelector.drag.test.ts +100 -0
- package/src/__tests__/components/SampleSelector.groups.test.ts +81 -0
- package/src/__tests__/components/SampleSelector.selection.test.ts +70 -0
- package/src/__tests__/components/SampleSelector.test.ts +32 -0
- package/src/__tests__/components/SampleSelectorSampleRow.test.ts +37 -0
- package/src/__tests__/components/ScheduleCalendar.test.ts +44 -0
- package/src/__tests__/components/SettingsModal.schema.test.ts +97 -0
- package/src/__tests__/components/WellPlate.colors.test.ts +28 -0
- package/src/__tests__/components/WellPlate.conditions.test.ts +68 -0
- package/src/__tests__/components/WellPlate.geometry.test.ts +54 -0
- package/src/__tests__/components/WellPlate.interaction.test.ts +171 -0
- package/src/__tests__/components/WellPlate.legend.test.ts +13 -0
- package/src/__tests__/components/WellPlate.rendering.test.ts +122 -0
- package/src/__tests__/components/WellPlate.sampleDrop.test.ts +70 -0
- package/src/__tests__/composables/autoGroup/classify.test.ts +107 -0
- package/src/__tests__/composables/autoGroup/columns.test.ts +135 -0
- package/src/__tests__/composables/autoGroup/compose.test.ts +227 -0
- package/src/__tests__/composables/autoGroup/cooccurrence.test.ts +91 -0
- package/src/__tests__/composables/autoGroup/fingerprint.test.ts +50 -0
- package/src/__tests__/composables/autoGroup/integration.test.ts +79 -0
- package/src/__tests__/composables/autoGroup/template.test.ts +70 -0
- package/src/__tests__/composables/autoGroup/tokenize.test.ts +33 -0
- package/src/__tests__/composables/useAutoGroup.test.ts +129 -625
- package/src/__tests__/composables/useAutoGroupInputSources.test.ts +107 -0
- package/src/__tests__/composables/useControlSchema.test.ts +23 -0
- package/src/__tests__/composables/useScheduleCalendarLayout.test.ts +89 -0
- package/src/__tests__/docs/extractDocsComponents.test.ts +142 -0
- package/src/__tests__/docs/extractDocsExports.test.ts +77 -0
- package/src/__tests__/docs/extractDocsParsing.test.ts +69 -0
- package/src/__tests__/docs/extractDocsTemplates.test.ts +54 -0
- package/src/__tests__/docs/extractDocsTheme.test.ts +89 -0
- package/src/__tests__/docs/frontendDocsCatalog.test.ts +1 -1
- package/src/__tests__/fixtures/auto-group/mixed-lc-ms-batch.txt +187 -0
- package/src/components/AppSidebar.vue +2 -6
- package/src/components/AppTopBar.navigation.ts +62 -0
- package/src/components/AppTopBar.vue +17 -44
- package/src/components/AutoGroupModal.story.vue +50 -0
- package/src/components/AutoGroupModal.vue +441 -158
- package/src/components/ControlWorkspaceView.vue +2 -6
- package/src/components/DoseCalculator.vue +13 -73
- package/src/components/DoseCalculatorVolumeField.vue +61 -0
- package/src/components/ExperimentTimeline.vue +6 -31
- package/src/components/FormBuilder.vue +2 -7
- package/src/components/PlateMapEditor.vue +32 -106
- package/src/components/PluginWorkspaceView.controls.ts +182 -0
- package/src/components/PluginWorkspaceView.navigation.ts +106 -0
- package/src/components/PluginWorkspaceView.props.ts +174 -0
- package/src/components/PluginWorkspaceView.shell.ts +66 -0
- package/src/components/PluginWorkspaceView.vue +85 -404
- package/src/components/ProtocolStep.presentation.ts +31 -0
- package/src/components/ProtocolStepEditor.state.ts +104 -0
- package/src/components/ProtocolStepEditor.vue +48 -179
- package/src/components/ProtocolStepParameterField.vue +134 -0
- package/src/components/ReagentList.presentation.ts +105 -0
- package/src/components/ReagentList.vue +16 -79
- package/src/components/SampleSelector.colors.ts +43 -0
- package/src/components/SampleSelector.drag.ts +164 -0
- package/src/components/SampleSelector.groups.ts +109 -0
- package/src/components/SampleSelector.selection.ts +103 -0
- package/src/components/SampleSelector.vue +82 -349
- package/src/components/SampleSelectorSampleRow.vue +64 -0
- package/src/components/ScheduleCalendar.vue +44 -199
- package/src/components/SettingsModal.schema.ts +71 -0
- package/src/components/SettingsModal.vue +16 -46
- package/src/components/WellPlate.colors.ts +56 -0
- package/src/components/WellPlate.conditions.ts +100 -0
- package/src/components/WellPlate.geometry.ts +91 -0
- package/src/components/WellPlate.interaction.ts +272 -0
- package/src/components/WellPlate.legend.ts +8 -0
- package/src/components/WellPlate.rendering.ts +105 -0
- package/src/components/WellPlate.sampleDrop.ts +73 -0
- package/src/components/WellPlate.vue +102 -550
- package/src/components/internal/PlateMapEditorToolbarInternal.vue +128 -0
- package/src/composables/autoGroup/classKey.ts +5 -0
- package/src/composables/autoGroup/classify.ts +205 -0
- package/src/composables/autoGroup/colors.ts +6 -0
- package/src/composables/autoGroup/columns.ts +226 -0
- package/src/composables/autoGroup/compose.ts +156 -0
- package/src/composables/autoGroup/cooccurrence.ts +46 -0
- package/src/composables/autoGroup/csv-shim.ts +44 -0
- package/src/composables/autoGroup/fingerprint.ts +49 -0
- package/src/composables/autoGroup/index.ts +20 -0
- package/src/composables/autoGroup/replicatePreGroup.ts +90 -0
- package/src/composables/autoGroup/template.ts +126 -0
- package/src/composables/autoGroup/tokenize.ts +41 -0
- package/src/composables/autoGroup/vocab.json +67 -0
- package/src/composables/autoGroupConstants.ts +4 -0
- package/src/composables/autoGroupGrouping.ts +148 -0
- package/src/composables/controlComponentBindings.ts +1 -1
- package/src/composables/controlSchemaAdapters.ts +1 -1
- package/src/composables/controlSchemaDoseDesign.ts +215 -0
- package/src/composables/controlSchemaFormFields.ts +1 -1
- package/src/composables/controlSchemaLayout.ts +1 -1
- package/src/composables/controlSchemaModel.ts +163 -0
- package/src/composables/controlSchemaNormalize.ts +1 -1
- package/src/composables/controlSchemaTypes.ts +364 -0
- package/src/composables/controlWorkspaceOptions.ts +1 -1
- package/src/composables/formBuilderSchema.ts +153 -0
- package/src/composables/pluginEndpointBuilder.ts +203 -0
- package/src/composables/protocolTemplateCatalog.ts +325 -0
- package/src/composables/useAutoGroup.ts +395 -549
- package/src/composables/useAutoGroupInputSources.ts +147 -0
- package/src/composables/useBioTemplateControls.ts +1 -1
- package/src/composables/useBioTemplatePresetWorkspace.ts +1 -1
- package/src/composables/useBioTemplateWorkspace.ts +1 -1
- package/src/composables/useControlSchema.ts +21 -692
- package/src/composables/useControlWorkspace.ts +7 -13
- package/src/composables/useForm.ts +5 -187
- package/src/composables/useFormBuilder.ts +11 -153
- package/src/composables/useFormValidation.ts +154 -0
- package/src/composables/usePluginClient.ts +10 -193
- package/src/composables/useProtocolTemplates.ts +10 -328
- package/src/composables/useScheduleCalendarLayout.ts +287 -0
- package/src/styles/components/auto-group-modal.css +248 -310
- package/src/templates/controlSchemaTypes.ts +1 -1
- package/src/templates/templateAdapterTypes.ts +58 -0
- package/src/templates/templateCreateOptions.ts +208 -0
- package/src/templates/templateQpcrTypes.ts +48 -0
- package/src/templates/types.ts +79 -275
- package/src/types/auto-group.ts +107 -9
- package/src/types/componentLabTypes.ts +235 -0
- package/src/types/componentWorkflowTypes.ts +190 -0
- package/src/types/components.ts +74 -424
- package/dist/components-DafPc4rM.js.map +0 -1
- package/dist/composables-BMkPQhVK.js.map +0 -1
- package/dist/templates-bUAWMn5L.js.map +0 -1
- package/dist/useProtocolTemplates-QZtHFFH2.js.map +0 -1
|
@@ -4,14 +4,26 @@ import { ref, computed } from 'vue'
|
|
|
4
4
|
import BaseButton from './BaseButton.vue'
|
|
5
5
|
import BaseInput from './BaseInput.vue'
|
|
6
6
|
import AutoGroupModal from './AutoGroupModal.vue'
|
|
7
|
+
import SampleSelectorSampleRow from './SampleSelectorSampleRow.vue'
|
|
7
8
|
import type { SampleGroup } from '../types'
|
|
8
9
|
import type { AutoGroupResult } from '../types/auto-group'
|
|
9
|
-
import { DEFAULT_COLORS } from '../composables/useAutoGroup'
|
|
10
10
|
import { useTextSearch } from '../composables/useTextSearch'
|
|
11
|
-
import { useListSelection } from '../composables/useListSelection'
|
|
12
11
|
import { useSampleGroups, type SampleMajorGroup } from '../composables/useSampleGroups'
|
|
13
12
|
import { useExpansionSet } from '../composables/useExpansionSet'
|
|
14
13
|
import { useExperimentSamples } from '../composables/useExperimentSamples'
|
|
14
|
+
import { useSampleSelectorDrag } from './SampleSelector.drag'
|
|
15
|
+
import { useSampleSelectorSelection } from './SampleSelector.selection'
|
|
16
|
+
import {
|
|
17
|
+
applySampleGroupColorEdit,
|
|
18
|
+
createSampleGroup,
|
|
19
|
+
getSampleGroupColorEditSeed,
|
|
20
|
+
type ColorEdit,
|
|
21
|
+
} from './SampleSelector.colors'
|
|
22
|
+
import {
|
|
23
|
+
removeSampleFromGroup as removeSampleFromSampleGroup,
|
|
24
|
+
removeSampleGroup,
|
|
25
|
+
removeSampleMajorGroup,
|
|
26
|
+
} from './SampleSelector.groups'
|
|
15
27
|
|
|
16
28
|
interface Props {
|
|
17
29
|
samples?: string[]
|
|
@@ -41,10 +53,6 @@ const emit = defineEmits<{
|
|
|
41
53
|
}>()
|
|
42
54
|
|
|
43
55
|
// UI State
|
|
44
|
-
type ColorEdit =
|
|
45
|
-
| { kind: 'single'; name: string }
|
|
46
|
-
| { kind: 'family'; names: string[] }
|
|
47
|
-
|
|
48
56
|
const showSmartGroupModal = ref(false)
|
|
49
57
|
const newGroupName = ref('')
|
|
50
58
|
const editingColor = ref<ColorEdit | null>(null)
|
|
@@ -52,24 +60,31 @@ const colorPickerInput = ref<HTMLInputElement | null>(null)
|
|
|
52
60
|
const searchQuery = ref('')
|
|
53
61
|
const groupExpansion = useExpansionSet()
|
|
54
62
|
|
|
55
|
-
// Sample Drag State
|
|
56
|
-
const draggingSample = ref<string | null>(null)
|
|
57
|
-
const dragSourceGroup = ref<string | null>(null)
|
|
58
|
-
const dragOverGroup = ref<string | null>(null)
|
|
59
|
-
|
|
60
|
-
// Group-Reorder Drag State
|
|
61
|
-
type GroupDragKind = 'major' | 'sub' | 'flat'
|
|
62
|
-
const draggingGroup = ref<string | null>(null)
|
|
63
|
-
const draggingGroupKind = ref<GroupDragKind | null>(null)
|
|
64
|
-
const reorderTarget = ref<string | null>(null)
|
|
65
|
-
const reorderPosition = ref<'before' | 'after' | null>(null)
|
|
66
|
-
|
|
67
63
|
// Computed: groups from props
|
|
68
64
|
const internalGroups = computed({
|
|
69
65
|
get: () => props.groups,
|
|
70
66
|
set: (value) => emit('update:groups', value),
|
|
71
67
|
})
|
|
72
68
|
|
|
69
|
+
const {
|
|
70
|
+
draggingSample,
|
|
71
|
+
dragOverGroup,
|
|
72
|
+
draggingGroup,
|
|
73
|
+
draggingGroupKind,
|
|
74
|
+
reorderTarget,
|
|
75
|
+
reorderPosition,
|
|
76
|
+
handleDragStart,
|
|
77
|
+
handleDragEnd,
|
|
78
|
+
handleDragOver,
|
|
79
|
+
handleDragLeave,
|
|
80
|
+
handleDrop,
|
|
81
|
+
handleGroupDragStart,
|
|
82
|
+
handleGroupDragEnd,
|
|
83
|
+
handleGroupDragOver,
|
|
84
|
+
handleGroupDragLeave,
|
|
85
|
+
handleGroupDrop,
|
|
86
|
+
} = useSampleSelectorDrag(internalGroups)
|
|
87
|
+
|
|
73
88
|
const providedSamples = computed(() => props.samples)
|
|
74
89
|
const shouldLoadExperimentSamples = computed(() =>
|
|
75
90
|
props.autoloadExperimentData && providedSamples.value.length === 0,
|
|
@@ -102,61 +117,22 @@ const sampleSearch = useTextSearch({
|
|
|
102
117
|
})
|
|
103
118
|
const filteredSamples = sampleSearch.filteredItems
|
|
104
119
|
|
|
105
|
-
const
|
|
120
|
+
const {
|
|
121
|
+
isAllSelected,
|
|
122
|
+
toggleSelectAll,
|
|
123
|
+
toggleSample,
|
|
124
|
+
toggleGroupSamples,
|
|
125
|
+
toggleMajorGroupSamples,
|
|
126
|
+
isGroupFullySelected,
|
|
127
|
+
isGroupPartiallySelected,
|
|
128
|
+
isMajorGroupFullySelected,
|
|
129
|
+
isMajorGroupPartiallySelected,
|
|
130
|
+
} = useSampleSelectorSelection({
|
|
106
131
|
selected: () => props.modelValue,
|
|
107
|
-
|
|
132
|
+
samples: () => resolvedSamples.value,
|
|
133
|
+
findGroup: sampleGroups.findGroup,
|
|
134
|
+
emitSelected: samples => emit('update:modelValue', samples),
|
|
108
135
|
})
|
|
109
|
-
const isAllSelected = sampleSelection.isAllSelected
|
|
110
|
-
|
|
111
|
-
// Toggle functions
|
|
112
|
-
function toggleSelectAll() {
|
|
113
|
-
emit('update:modelValue', sampleSelection.toggleAll())
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function toggleSample(sample: string) {
|
|
117
|
-
emit('update:modelValue', sampleSelection.toggleValue(sample))
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function toggleSamplesSelection(samples: string[]) {
|
|
121
|
-
emit('update:modelValue', sampleSelection.toggleValues(samples))
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function toggleGroupSamples(groupName: string) {
|
|
125
|
-
const group = sampleGroups.findGroup(groupName)
|
|
126
|
-
if (!group) return
|
|
127
|
-
toggleSamplesSelection(group.samples)
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
function toggleMajorGroupSamples(majorGroup: SampleMajorGroup) {
|
|
131
|
-
toggleSamplesSelection(majorGroup.allSamples)
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Selection state checks
|
|
135
|
-
function isFullySelected(samples: string[]): boolean {
|
|
136
|
-
return sampleSelection.isFullySelected(samples)
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function isPartiallySelected(samples: string[]): boolean {
|
|
140
|
-
return sampleSelection.isPartiallySelected(samples)
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
function isGroupFullySelected(groupName: string): boolean {
|
|
144
|
-
const group = sampleGroups.findGroup(groupName)
|
|
145
|
-
return group ? isFullySelected(group.samples) : false
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
function isGroupPartiallySelected(groupName: string): boolean {
|
|
149
|
-
const group = sampleGroups.findGroup(groupName)
|
|
150
|
-
return group ? isPartiallySelected(group.samples) : false
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
function isMajorGroupFullySelected(majorGroup: SampleMajorGroup): boolean {
|
|
154
|
-
return isFullySelected(majorGroup.allSamples)
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
function isMajorGroupPartiallySelected(majorGroup: SampleMajorGroup): boolean {
|
|
158
|
-
return isPartiallySelected(majorGroup.allSamples)
|
|
159
|
-
}
|
|
160
136
|
|
|
161
137
|
// Expand/collapse
|
|
162
138
|
function toggleGroupExpanded(groupName: string) {
|
|
@@ -195,194 +171,15 @@ function clearGroups() {
|
|
|
195
171
|
}
|
|
196
172
|
|
|
197
173
|
function deleteMajorGroup(majorGroup: SampleMajorGroup) {
|
|
198
|
-
internalGroups.value = internalGroups.value
|
|
199
|
-
g => !majorGroup.subGroups.some(sg => sg.name === g.name)
|
|
200
|
-
)
|
|
174
|
+
internalGroups.value = removeSampleMajorGroup(internalGroups.value, majorGroup)
|
|
201
175
|
}
|
|
202
176
|
|
|
203
177
|
function deleteGroup(groupName: string) {
|
|
204
|
-
internalGroups.value = internalGroups.value
|
|
178
|
+
internalGroups.value = removeSampleGroup(internalGroups.value, groupName)
|
|
205
179
|
}
|
|
206
180
|
|
|
207
181
|
function removeSampleFromGroup(sample: string, groupName: string) {
|
|
208
|
-
internalGroups.value = internalGroups.value
|
|
209
|
-
g.name === groupName
|
|
210
|
-
? { ...g, samples: g.samples.filter((s: string) => s !== sample) }
|
|
211
|
-
: g
|
|
212
|
-
)
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// Drag and Drop handlers
|
|
216
|
-
function handleDragStart(sample: string, sourceGroup: string | null, event: DragEvent) {
|
|
217
|
-
draggingSample.value = sample
|
|
218
|
-
dragSourceGroup.value = sourceGroup
|
|
219
|
-
if (event.dataTransfer) {
|
|
220
|
-
event.dataTransfer.effectAllowed = 'move'
|
|
221
|
-
event.dataTransfer.setData('text/plain', sample)
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
function resetDragState() {
|
|
226
|
-
draggingSample.value = null
|
|
227
|
-
dragSourceGroup.value = null
|
|
228
|
-
dragOverGroup.value = null
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
function handleDragEnd() {
|
|
232
|
-
resetDragState()
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
function handleDragOver(groupName: string, event: DragEvent) {
|
|
236
|
-
// Only accept this drop target when a sample is being dragged; group drags are handled separately.
|
|
237
|
-
if (!draggingSample.value) return
|
|
238
|
-
event.preventDefault()
|
|
239
|
-
if (event.dataTransfer) {
|
|
240
|
-
event.dataTransfer.dropEffect = 'move'
|
|
241
|
-
}
|
|
242
|
-
dragOverGroup.value = groupName
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
function handleDragLeave() {
|
|
246
|
-
dragOverGroup.value = null
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
function handleDrop(targetGroupName: string, event: DragEvent) {
|
|
250
|
-
if (!draggingSample.value) return
|
|
251
|
-
event.preventDefault()
|
|
252
|
-
|
|
253
|
-
const sample = draggingSample.value
|
|
254
|
-
const sourceGroup = dragSourceGroup.value
|
|
255
|
-
|
|
256
|
-
if (sourceGroup === targetGroupName) {
|
|
257
|
-
resetDragState()
|
|
258
|
-
return
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
internalGroups.value = internalGroups.value.map(g => {
|
|
262
|
-
if (sourceGroup && g.name === sourceGroup) {
|
|
263
|
-
return { ...g, samples: g.samples.filter((s: string) => s !== sample) }
|
|
264
|
-
}
|
|
265
|
-
if (g.name === targetGroupName && !g.samples.includes(sample)) {
|
|
266
|
-
return { ...g, samples: [...g.samples, sample] }
|
|
267
|
-
}
|
|
268
|
-
return g
|
|
269
|
-
})
|
|
270
|
-
|
|
271
|
-
resetDragState()
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// Group reorder helpers
|
|
275
|
-
function detectSeparator(groups: SampleGroup[]): string {
|
|
276
|
-
return groups.some(g => g.name.includes('/')) ? '/' : '_'
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
function getMajorPrefix(groupName: string, separator: string): string {
|
|
280
|
-
const parts = groupName.split(separator)
|
|
281
|
-
return parts.length > 1 ? parts[0] : groupName
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
function handleGroupDragStart(name: string, kind: GroupDragKind, event: DragEvent) {
|
|
285
|
-
draggingGroup.value = name
|
|
286
|
-
draggingGroupKind.value = kind
|
|
287
|
-
if (event.dataTransfer) {
|
|
288
|
-
event.dataTransfer.effectAllowed = 'move'
|
|
289
|
-
event.dataTransfer.setData('text/plain', `mint-group:${name}`)
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
function handleGroupDragEnd() {
|
|
294
|
-
draggingGroup.value = null
|
|
295
|
-
draggingGroupKind.value = null
|
|
296
|
-
reorderTarget.value = null
|
|
297
|
-
reorderPosition.value = null
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
function handleGroupDragOver(name: string, kind: GroupDragKind, event: DragEvent) {
|
|
301
|
-
if (!draggingGroup.value || draggingGroupKind.value !== kind) return
|
|
302
|
-
if (draggingGroup.value === name) return
|
|
303
|
-
|
|
304
|
-
// Sub-group reorder is restricted to siblings under the same major prefix —
|
|
305
|
-
// crossing majors would silently rename the group, which is too magical.
|
|
306
|
-
if (kind === 'sub') {
|
|
307
|
-
const sep = detectSeparator(internalGroups.value)
|
|
308
|
-
if (getMajorPrefix(draggingGroup.value, sep) !== getMajorPrefix(name, sep)) return
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
event.preventDefault()
|
|
312
|
-
if (event.dataTransfer) event.dataTransfer.dropEffect = 'move'
|
|
313
|
-
|
|
314
|
-
const rect = (event.currentTarget as HTMLElement).getBoundingClientRect()
|
|
315
|
-
reorderTarget.value = name
|
|
316
|
-
reorderPosition.value = event.clientY < rect.top + rect.height / 2 ? 'before' : 'after'
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
function handleGroupDragLeave(event: DragEvent) {
|
|
320
|
-
const cur = event.currentTarget as HTMLElement
|
|
321
|
-
const rel = event.relatedTarget as Node | null
|
|
322
|
-
if (rel && cur.contains(rel)) return
|
|
323
|
-
reorderTarget.value = null
|
|
324
|
-
reorderPosition.value = null
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
function handleGroupDrop(name: string, kind: GroupDragKind, event: DragEvent) {
|
|
328
|
-
if (!draggingGroup.value || draggingGroupKind.value !== kind) {
|
|
329
|
-
handleGroupDragEnd()
|
|
330
|
-
return
|
|
331
|
-
}
|
|
332
|
-
const position = reorderPosition.value
|
|
333
|
-
if (!position || draggingGroup.value === name) {
|
|
334
|
-
handleGroupDragEnd()
|
|
335
|
-
return
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
event.preventDefault()
|
|
339
|
-
|
|
340
|
-
if (kind === 'major') {
|
|
341
|
-
moveMajorGroup(draggingGroup.value, name, position)
|
|
342
|
-
} else {
|
|
343
|
-
moveGroup(draggingGroup.value, name, position)
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
handleGroupDragEnd()
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
function moveGroup(source: string, target: string, position: 'before' | 'after') {
|
|
350
|
-
if (source === target) return
|
|
351
|
-
const groups = [...internalGroups.value]
|
|
352
|
-
const srcIdx = groups.findIndex(g => g.name === source)
|
|
353
|
-
if (srcIdx === -1) return
|
|
354
|
-
const [item] = groups.splice(srcIdx, 1)
|
|
355
|
-
const targetIdx = groups.findIndex(g => g.name === target)
|
|
356
|
-
if (targetIdx === -1) return
|
|
357
|
-
groups.splice(position === 'before' ? targetIdx : targetIdx + 1, 0, item)
|
|
358
|
-
internalGroups.value = groups
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
function moveMajorGroup(source: string, target: string, position: 'before' | 'after') {
|
|
362
|
-
if (source === target) return
|
|
363
|
-
const groups = [...internalGroups.value]
|
|
364
|
-
const sep = detectSeparator(groups)
|
|
365
|
-
|
|
366
|
-
const isSource = (g: SampleGroup) => getMajorPrefix(g.name, sep) === source
|
|
367
|
-
const isTarget = (g: SampleGroup) => getMajorPrefix(g.name, sep) === target
|
|
368
|
-
|
|
369
|
-
const sourceGroups = groups.filter(isSource)
|
|
370
|
-
if (sourceGroups.length === 0) return
|
|
371
|
-
const remaining = groups.filter(g => !isSource(g))
|
|
372
|
-
|
|
373
|
-
let firstTarget = -1
|
|
374
|
-
let lastTarget = -1
|
|
375
|
-
remaining.forEach((g, i) => {
|
|
376
|
-
if (isTarget(g)) {
|
|
377
|
-
if (firstTarget === -1) firstTarget = i
|
|
378
|
-
lastTarget = i
|
|
379
|
-
}
|
|
380
|
-
})
|
|
381
|
-
if (firstTarget === -1) return
|
|
382
|
-
|
|
383
|
-
const insertIdx = position === 'before' ? firstTarget : lastTarget + 1
|
|
384
|
-
remaining.splice(insertIdx, 0, ...sourceGroups)
|
|
385
|
-
internalGroups.value = remaining
|
|
182
|
+
internalGroups.value = removeSampleFromSampleGroup(internalGroups.value, sample, groupName)
|
|
386
183
|
}
|
|
387
184
|
|
|
388
185
|
// Color picker
|
|
@@ -403,12 +200,7 @@ function handleColorChange(event: Event) {
|
|
|
403
200
|
if (!edit) return
|
|
404
201
|
|
|
405
202
|
const newColor = (event.target as HTMLInputElement).value
|
|
406
|
-
|
|
407
|
-
// computed re-derives shades from it.
|
|
408
|
-
const targets = edit.kind === 'family' ? new Set(edit.names) : new Set([edit.name])
|
|
409
|
-
internalGroups.value = internalGroups.value.map(g =>
|
|
410
|
-
targets.has(g.name) ? { ...g, color: newColor } : g,
|
|
411
|
-
)
|
|
203
|
+
internalGroups.value = applySampleGroupColorEdit(internalGroups.value, edit, newColor)
|
|
412
204
|
editingColor.value = null
|
|
413
205
|
}
|
|
414
206
|
|
|
@@ -417,28 +209,18 @@ function getGroupColor(groupName: string): string {
|
|
|
417
209
|
}
|
|
418
210
|
|
|
419
211
|
const colorPickerSeed = computed(() => {
|
|
420
|
-
|
|
421
|
-
if (!edit) return '#3B82F6'
|
|
422
|
-
return getGroupColor(edit.kind === 'family' ? edit.names[0] : edit.name)
|
|
212
|
+
return getSampleGroupColorEditSeed(editingColor.value, getGroupColor)
|
|
423
213
|
})
|
|
424
214
|
|
|
425
215
|
// New group
|
|
426
216
|
function addNewGroup() {
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
const usedColors = new Set(internalGroups.value.map(g => g.color))
|
|
430
|
-
const availableColor = DEFAULT_COLORS.find(c => !usedColors.has(c)) || DEFAULT_COLORS[0]
|
|
431
|
-
|
|
432
|
-
const newGroup: SampleGroup = {
|
|
433
|
-
name: newGroupName.value.trim(),
|
|
434
|
-
color: availableColor,
|
|
435
|
-
samples: [],
|
|
436
|
-
}
|
|
437
|
-
|
|
217
|
+
const newGroup = createSampleGroup(newGroupName.value, internalGroups.value)
|
|
218
|
+
if (!newGroup) return
|
|
438
219
|
internalGroups.value = [...internalGroups.value, newGroup]
|
|
439
220
|
newGroupName.value = ''
|
|
440
221
|
}
|
|
441
222
|
|
|
223
|
+
defineExpose({ handleSmartGroupApply })
|
|
442
224
|
</script>
|
|
443
225
|
|
|
444
226
|
<template>
|
|
@@ -670,39 +452,20 @@ function addNewGroup() {
|
|
|
670
452
|
class="mint-sample-selector__samples"
|
|
671
453
|
:style="{ borderColor: subGroup.displayBorder }"
|
|
672
454
|
>
|
|
673
|
-
<
|
|
455
|
+
<SampleSelectorSampleRow
|
|
674
456
|
v-for="sample in subGroup.samples"
|
|
675
457
|
:key="sample"
|
|
676
|
-
:
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
458
|
+
:sample="sample"
|
|
459
|
+
:selected="modelValue.includes(sample)"
|
|
460
|
+
:dragging="draggingSample === sample"
|
|
461
|
+
:accent-color="subGroup.displayColor"
|
|
462
|
+
checkbox-size="tiny"
|
|
463
|
+
removable
|
|
681
464
|
@dragstart="handleDragStart(sample, subGroup.name, $event)"
|
|
682
465
|
@dragend="handleDragEnd"
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
</svg>
|
|
687
|
-
<input
|
|
688
|
-
type="checkbox"
|
|
689
|
-
:checked="modelValue.includes(sample)"
|
|
690
|
-
class="mint-sample-selector__checkbox mint-sample-selector__checkbox--tiny"
|
|
691
|
-
:style="{ accentColor: subGroup.displayColor }"
|
|
692
|
-
@change="toggleSample(sample)"
|
|
693
|
-
/>
|
|
694
|
-
<span class="mint-sample-selector__sample-name">{{ sample }}</span>
|
|
695
|
-
<button
|
|
696
|
-
type="button"
|
|
697
|
-
class="mint-sample-selector__remove-btn"
|
|
698
|
-
@click="removeSampleFromGroup(sample, subGroup.name)"
|
|
699
|
-
title="Remove from group"
|
|
700
|
-
>
|
|
701
|
-
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
702
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 12H4" />
|
|
703
|
-
</svg>
|
|
704
|
-
</button>
|
|
705
|
-
</div>
|
|
466
|
+
@toggle="toggleSample(sample)"
|
|
467
|
+
@remove="removeSampleFromGroup(sample, subGroup.name)"
|
|
468
|
+
/>
|
|
706
469
|
</div>
|
|
707
470
|
</Transition>
|
|
708
471
|
</div>
|
|
@@ -796,39 +559,20 @@ function addNewGroup() {
|
|
|
796
559
|
class="mint-sample-selector__samples"
|
|
797
560
|
:style="{ borderColor: group.color + '40' }"
|
|
798
561
|
>
|
|
799
|
-
<
|
|
562
|
+
<SampleSelectorSampleRow
|
|
800
563
|
v-for="sample in group.samples"
|
|
801
564
|
:key="sample"
|
|
802
|
-
:
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
565
|
+
:sample="sample"
|
|
566
|
+
:selected="modelValue.includes(sample)"
|
|
567
|
+
:dragging="draggingSample === sample"
|
|
568
|
+
:accent-color="group.color"
|
|
569
|
+
checkbox-size="tiny"
|
|
570
|
+
removable
|
|
807
571
|
@dragstart="handleDragStart(sample, group.name, $event)"
|
|
808
572
|
@dragend="handleDragEnd"
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
</svg>
|
|
813
|
-
<input
|
|
814
|
-
type="checkbox"
|
|
815
|
-
:checked="modelValue.includes(sample)"
|
|
816
|
-
class="mint-sample-selector__checkbox mint-sample-selector__checkbox--tiny"
|
|
817
|
-
:style="{ accentColor: group.color }"
|
|
818
|
-
@change="toggleSample(sample)"
|
|
819
|
-
/>
|
|
820
|
-
<span class="mint-sample-selector__sample-name">{{ sample }}</span>
|
|
821
|
-
<button
|
|
822
|
-
type="button"
|
|
823
|
-
class="mint-sample-selector__remove-btn"
|
|
824
|
-
@click="removeSampleFromGroup(sample, group.name)"
|
|
825
|
-
title="Remove from group"
|
|
826
|
-
>
|
|
827
|
-
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
828
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 12H4" />
|
|
829
|
-
</svg>
|
|
830
|
-
</button>
|
|
831
|
-
</div>
|
|
573
|
+
@toggle="toggleSample(sample)"
|
|
574
|
+
@remove="removeSampleFromGroup(sample, group.name)"
|
|
575
|
+
/>
|
|
832
576
|
</div>
|
|
833
577
|
</Transition>
|
|
834
578
|
</div>
|
|
@@ -864,28 +608,17 @@ function addNewGroup() {
|
|
|
864
608
|
v-if="isGroupExpanded('__ungrouped__')"
|
|
865
609
|
class="mint-sample-selector__ungrouped-list"
|
|
866
610
|
>
|
|
867
|
-
<
|
|
611
|
+
<SampleSelectorSampleRow
|
|
868
612
|
v-for="sample in ungroupedSamples"
|
|
869
613
|
:key="sample"
|
|
870
|
-
:
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
draggable="true"
|
|
614
|
+
:sample="sample"
|
|
615
|
+
:selected="modelValue.includes(sample)"
|
|
616
|
+
:dragging="draggingSample === sample"
|
|
617
|
+
checkbox-size="small"
|
|
875
618
|
@dragstart="handleDragStart(sample, null, $event)"
|
|
876
619
|
@dragend="handleDragEnd"
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 8h16M4 16h16" />
|
|
880
|
-
</svg>
|
|
881
|
-
<input
|
|
882
|
-
type="checkbox"
|
|
883
|
-
:checked="modelValue.includes(sample)"
|
|
884
|
-
class="mint-sample-selector__checkbox mint-sample-selector__checkbox--small"
|
|
885
|
-
@change="toggleSample(sample)"
|
|
886
|
-
/>
|
|
887
|
-
<span class="mint-sample-selector__sample-name">{{ sample }}</span>
|
|
888
|
-
</div>
|
|
620
|
+
@toggle="toggleSample(sample)"
|
|
621
|
+
/>
|
|
889
622
|
</div>
|
|
890
623
|
</Transition>
|
|
891
624
|
</div>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/** Single draggable sample row used by grouped and ungrouped SampleSelector lists. */
|
|
3
|
+
import { computed } from 'vue'
|
|
4
|
+
|
|
5
|
+
type CheckboxSize = 'small' | 'tiny'
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
sample: string
|
|
9
|
+
selected: boolean
|
|
10
|
+
dragging?: boolean
|
|
11
|
+
accentColor?: string
|
|
12
|
+
checkboxSize?: CheckboxSize
|
|
13
|
+
removable?: boolean
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
17
|
+
dragging: false,
|
|
18
|
+
checkboxSize: 'tiny',
|
|
19
|
+
removable: false,
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
const emit = defineEmits<{
|
|
23
|
+
toggle: []
|
|
24
|
+
remove: []
|
|
25
|
+
}>()
|
|
26
|
+
|
|
27
|
+
const checkboxClasses = computed(() => [
|
|
28
|
+
'mint-sample-selector__checkbox',
|
|
29
|
+
`mint-sample-selector__checkbox--${props.checkboxSize}`,
|
|
30
|
+
])
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<template>
|
|
34
|
+
<div
|
|
35
|
+
:class="[
|
|
36
|
+
'mint-sample-selector__sample',
|
|
37
|
+
dragging ? 'mint-sample-selector__sample--dragging' : '',
|
|
38
|
+
]"
|
|
39
|
+
draggable="true"
|
|
40
|
+
>
|
|
41
|
+
<svg class="mint-sample-selector__drag-handle" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
42
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 8h16M4 16h16" />
|
|
43
|
+
</svg>
|
|
44
|
+
<input
|
|
45
|
+
type="checkbox"
|
|
46
|
+
:checked="selected"
|
|
47
|
+
:class="checkboxClasses"
|
|
48
|
+
:style="accentColor ? { accentColor } : undefined"
|
|
49
|
+
@change="emit('toggle')"
|
|
50
|
+
/>
|
|
51
|
+
<span class="mint-sample-selector__sample-name">{{ sample }}</span>
|
|
52
|
+
<button
|
|
53
|
+
v-if="removable"
|
|
54
|
+
type="button"
|
|
55
|
+
class="mint-sample-selector__remove-btn"
|
|
56
|
+
title="Remove from group"
|
|
57
|
+
@click="emit('remove')"
|
|
58
|
+
>
|
|
59
|
+
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
60
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 12H4" />
|
|
61
|
+
</svg>
|
|
62
|
+
</button>
|
|
63
|
+
</div>
|
|
64
|
+
</template>
|