@morscherlab/mld-sdk 0.7.6 → 0.7.8

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 (54) hide show
  1. package/dist/components/AutoGroupModal.vue.js +2 -2
  2. package/dist/components/AutoGroupModal.vue.js.map +1 -1
  3. package/dist/components/ExperimentSelectorModal.vue.d.ts +20 -0
  4. package/dist/components/ExperimentSelectorModal.vue.js +164 -0
  5. package/dist/components/ExperimentSelectorModal.vue.js.map +1 -0
  6. package/dist/components/ExperimentSelectorModal.vue3.js +6 -0
  7. package/dist/components/ExperimentSelectorModal.vue3.js.map +1 -0
  8. package/dist/components/FitPanel.vue.d.ts +46 -0
  9. package/dist/components/FitPanel.vue.js +118 -0
  10. package/dist/components/FitPanel.vue.js.map +1 -0
  11. package/dist/components/FitPanel.vue3.js +6 -0
  12. package/dist/components/FitPanel.vue3.js.map +1 -0
  13. package/dist/components/NumberInput.vue.js +53 -50
  14. package/dist/components/NumberInput.vue.js.map +1 -1
  15. package/dist/components/index.d.ts +2 -0
  16. package/dist/components/index.js +6 -0
  17. package/dist/components/index.js.map +1 -1
  18. package/dist/composables/index.d.ts +1 -0
  19. package/dist/composables/index.js +2 -0
  20. package/dist/composables/index.js.map +1 -1
  21. package/dist/composables/useAutoGroup.d.ts +1 -0
  22. package/dist/composables/useAutoGroup.js +24 -4
  23. package/dist/composables/useAutoGroup.js.map +1 -1
  24. package/dist/composables/useExperimentSelector.d.ts +20 -0
  25. package/dist/composables/useExperimentSelector.js +82 -0
  26. package/dist/composables/useExperimentSelector.js.map +1 -0
  27. package/dist/index.d.ts +3 -3
  28. package/dist/index.js +8 -0
  29. package/dist/index.js.map +1 -1
  30. package/dist/styles.css +340 -18
  31. package/dist/types/components.d.ts +30 -0
  32. package/dist/types/index.d.ts +1 -1
  33. package/package.json +1 -1
  34. package/src/__tests__/composables/useAutoGroup.test.ts +133 -0
  35. package/src/components/AutoGroupModal.story.vue +100 -32
  36. package/src/components/AutoGroupModal.vue +2 -2
  37. package/src/components/ExperimentSelectorModal.vue +157 -0
  38. package/src/components/FitPanel.vue +119 -0
  39. package/src/components/NumberInput.vue +33 -31
  40. package/src/components/index.ts +4 -0
  41. package/src/composables/index.ts +5 -0
  42. package/src/composables/useAutoGroup.ts +34 -5
  43. package/src/composables/useExperimentSelector.ts +113 -0
  44. package/src/index.ts +15 -0
  45. package/src/styles/components/app-sidebar.css +1 -1
  46. package/src/styles/components/auto-group-modal.css +5 -4
  47. package/src/styles/components/experiment-selector-modal.css +101 -0
  48. package/src/styles/components/fit-panel.css +67 -0
  49. package/src/styles/components/modal.css +6 -0
  50. package/src/styles/components/number-input.css +7 -5
  51. package/src/styles/components/step-wizard.css +5 -0
  52. package/src/styles/index.css +2 -0
  53. package/src/types/components.ts +38 -0
  54. package/src/types/index.ts +8 -0
@@ -101,7 +101,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
101
101
  autoGroup.rawText.value = props.samples.join("\n");
102
102
  }
103
103
  }
104
- });
104
+ }, { immediate: true });
105
105
  const allSteps = [
106
106
  { id: "input", label: "Input" },
107
107
  { id: "outliers", label: "Outliers" },
@@ -297,7 +297,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
297
297
  "step-outliers": withCtx(() => [
298
298
  createElementVNode("div", _hoisted_10, [
299
299
  createElementVNode("div", _hoisted_11, [
300
- createTextVNode(toDisplayString(unref(autoGroup).outliers.value.length) + " of " + toDisplayString(unref(autoGroup).samples.value.length) + " samples have irregular structure (fewer than " + toDisplayString(unref(autoGroup).minFieldCount.value) + " fields, delimiter ", 1),
300
+ createTextVNode(toDisplayString(unref(autoGroup).outliers.value.length) + " of " + toDisplayString(unref(autoGroup).samples.value.length) + " samples have irregular structure (fewer than " + toDisplayString(unref(autoGroup).dominantFieldCount.value) + " fields, delimiter ", 1),
301
301
  createElementVNode("code", null, toDisplayString(unref(autoGroup).delimiter.value), 1),
302
302
  _cache[14] || (_cache[14] = createTextVNode(") ", -1))
303
303
  ]),
@@ -1 +1 @@
1
- {"version":3,"file":"AutoGroupModal.vue.js","sources":["../../src/components/AutoGroupModal.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, watch } from 'vue'\nimport BaseModal from './BaseModal.vue'\nimport BaseButton from './BaseButton.vue'\nimport BaseInput from './BaseInput.vue'\nimport StepWizard from './StepWizard.vue'\nimport { useAutoGroup, parseCSV } from '../composables/useAutoGroup'\nimport type { WizardStep } from '../types/components'\nimport type { AutoGroupResult } from '../types/auto-group'\n\ninterface Props {\n modelValue: boolean\n samples?: string[]\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n samples: () => [],\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean]\n 'apply': [result: AutoGroupResult]\n}>()\n\nconst autoGroup = useAutoGroup()\nconst wizardRef = ref<InstanceType<typeof StepWizard> | null>(null)\nconst currentStep = ref(0)\nconst isDragOver = ref(false)\nconst csvFileName = ref('')\n\n// Pre-fill from props\nwatch(() => props.modelValue, (open) => {\n if (open) {\n autoGroup.reset()\n currentStep.value = 0\n csvFileName.value = ''\n if (props.samples.length > 0) {\n autoGroup.rawText.value = props.samples.join('\\n')\n }\n }\n})\n\n// Dynamic steps: skip outlier step when no outliers\nconst allSteps: WizardStep[] = [\n { id: 'input', label: 'Input' },\n { id: 'outliers', label: 'Outliers' },\n { id: 'fields', label: 'Fields' },\n { id: 'preview', label: 'Preview' },\n]\n\nconst dynamicSteps = computed<WizardStep[]>(() => {\n if (autoGroup.hasOutliers.value) {\n return allSteps\n }\n return allSteps.filter(s => s.id !== 'outliers')\n})\n\n// Map current step index to step ID\nconst currentStepId = computed(() => {\n const step = dynamicSteps.value[currentStep.value]\n return step?.id ?? 'input'\n})\n\n// Clamp step when dynamic steps change\nwatch(() => dynamicSteps.value.length, (newLen) => {\n if (currentStep.value >= newLen) {\n currentStep.value = newLen - 1\n }\n})\n\n// Step validity\nconst inputValid = computed(() => autoGroup.samples.value.length > 0)\nconst fieldsValid = computed(() => autoGroup.enabledFields.value.size > 0)\n\nwatch([inputValid, fieldsValid, dynamicSteps], () => {\n if (!wizardRef.value) return\n const steps = dynamicSteps.value\n for (let i = 0; i < steps.length; i++) {\n const id = steps[i].id\n if (id === 'input') wizardRef.value.setStepValid(i, inputValid.value)\n else if (id === 'outliers') wizardRef.value.setStepValid(i, true)\n else if (id === 'fields') wizardRef.value.setStepValid(i, fieldsValid.value)\n else if (id === 'preview') wizardRef.value.setStepValid(i, true)\n }\n}, { immediate: true })\n\n// Navigation\nfunction handleNext() {\n if (currentStepId.value === 'input') {\n autoGroup.parseInput()\n }\n // StepWizard handles the actual navigation via v-model\n}\n\nfunction handleApply() {\n emit('apply', autoGroup.result.value)\n emit('update:modelValue', false)\n}\n\nfunction handleCancel() {\n emit('update:modelValue', false)\n}\n\n// CSV file handling\nfunction handleFileDrop(event: DragEvent) {\n event.preventDefault()\n isDragOver.value = false\n const files = event.dataTransfer?.files\n if (files && files.length > 0) {\n processFile(files[0])\n }\n}\n\nfunction handleFileInput(event: Event) {\n const target = event.target as HTMLInputElement\n if (target.files && target.files.length > 0) {\n processFile(target.files[0])\n }\n}\n\nasync function processFile(file: File) {\n if (!file.name.endsWith('.csv') && !file.name.endsWith('.tsv')) return\n\n try {\n const text = await file.text()\n const parsed = parseCSV(text)\n autoGroup.inputMode.value = 'csv'\n autoGroup.csvData.value = parsed\n csvFileName.value = file.name\n } catch {\n // CSV parse error — stay in current state\n }\n}\n\nfunction clearCsvFile() {\n autoGroup.csvData.value = null\n autoGroup.inputMode.value = 'paste'\n csvFileName.value = ''\n}\n\n// Last step check\nconst isLastStep = computed(() => currentStep.value === dynamicSteps.value.length - 1)\nconst isFirstStep = computed(() => currentStep.value === 0)\n</script>\n\n<template>\n <BaseModal\n :model-value=\"modelValue\"\n title=\"Smart Group\"\n size=\"lg\"\n @update:model-value=\"emit('update:modelValue', $event)\"\n @close=\"handleCancel\"\n >\n <div class=\"mld-auto-group\">\n <StepWizard\n ref=\"wizardRef\"\n v-model=\"currentStep\"\n :steps=\"dynamicSteps\"\n :linear=\"true\"\n size=\"sm\"\n >\n <!-- Step: Input -->\n <template #step-input>\n <div class=\"mld-auto-group__input-step\">\n <!-- Mode toggle -->\n <div class=\"mld-auto-group__mode-toggle\">\n <BaseButton\n :variant=\"autoGroup.inputMode.value === 'paste' ? 'primary' : 'secondary'\"\n size=\"sm\"\n @click=\"autoGroup.inputMode.value = 'paste'\"\n >\n Paste\n </BaseButton>\n <BaseButton\n :variant=\"autoGroup.inputMode.value === 'csv' ? 'primary' : 'secondary'\"\n size=\"sm\"\n @click=\"autoGroup.inputMode.value = 'csv'\"\n >\n CSV\n </BaseButton>\n </div>\n\n <!-- Paste mode -->\n <div v-if=\"autoGroup.inputMode.value === 'paste'\" class=\"mld-auto-group__paste\">\n <textarea\n v-model=\"autoGroup.rawText.value\"\n class=\"mld-auto-group__textarea\"\n rows=\"12\"\n placeholder=\"Paste sample names, one per line...\"\n />\n <div v-if=\"autoGroup.samples.value.length > 0\" class=\"mld-auto-group__sample-count\">\n {{ autoGroup.samples.value.length }} samples\n </div>\n </div>\n\n <!-- CSV mode -->\n <div v-if=\"autoGroup.inputMode.value === 'csv'\" class=\"mld-auto-group__csv\">\n <div v-if=\"!autoGroup.csvData.value\"\n :class=\"[\n 'mld-auto-group__dropzone',\n isDragOver ? 'mld-auto-group__dropzone--dragover' : '',\n ]\"\n @drop=\"handleFileDrop\"\n @dragover.prevent=\"isDragOver = true\"\n @dragleave=\"isDragOver = false\"\n >\n <input\n type=\"file\"\n accept=\".csv,.tsv\"\n class=\"mld-auto-group__file-input\"\n @change=\"handleFileInput\"\n />\n <svg class=\"mld-auto-group__upload-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" d=\"M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>\n <p class=\"mld-auto-group__upload-text\">\n <span class=\"mld-auto-group__upload-highlight\">Click to upload</span>\n or drag and drop a CSV file\n </p>\n </div>\n\n <div v-else class=\"mld-auto-group__file-info\">\n <svg class=\"mld-auto-group__file-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>\n <span class=\"mld-auto-group__file-name\">{{ csvFileName }}</span>\n <span class=\"mld-auto-group__file-rows\">{{ autoGroup.csvData.value.rows.length }} rows</span>\n <button type=\"button\" class=\"mld-auto-group__file-clear\" @click=\"clearCsvFile\">\n Change file\n </button>\n </div>\n </div>\n </div>\n </template>\n\n <!-- Step: Outliers -->\n <template #step-outliers>\n <div class=\"mld-auto-group__outlier-step\">\n <div class=\"mld-auto-group__outlier-banner\">\n {{ autoGroup.outliers.value.length }} of {{ autoGroup.samples.value.length }}\n samples have irregular structure\n (fewer than {{ autoGroup.minFieldCount.value }} fields, delimiter\n <code>{{ autoGroup.delimiter.value }}</code>)\n </div>\n\n <div class=\"mld-auto-group__outlier-batch\">\n <BaseButton size=\"sm\" variant=\"secondary\" @click=\"autoGroup.setAllOutlierActions('include')\">\n Include All\n </BaseButton>\n <BaseButton size=\"sm\" variant=\"secondary\" @click=\"autoGroup.setAllOutlierActions('exclude')\">\n Exclude All\n </BaseButton>\n </div>\n\n <div class=\"mld-auto-group__outlier-list\">\n <div\n v-for=\"outlier in autoGroup.outliers.value\"\n :key=\"outlier.index\"\n class=\"mld-auto-group__outlier-item\"\n >\n <div class=\"mld-auto-group__outlier-info\">\n <code class=\"mld-auto-group__outlier-name\">{{ outlier.sample }}</code>\n <span class=\"mld-auto-group__outlier-badge\">{{ outlier.fieldCount }} fields</span>\n </div>\n <div class=\"mld-auto-group__outlier-actions\">\n <button\n type=\"button\"\n :class=\"['mld-auto-group__action-btn', outlier.action === 'include' ? 'mld-auto-group__action-btn--active' : '']\"\n @click=\"autoGroup.setOutlierAction(outlier.index, 'include')\"\n >Include</button>\n <button\n type=\"button\"\n :class=\"['mld-auto-group__action-btn', outlier.action === 'exclude' ? 'mld-auto-group__action-btn--active mld-auto-group__action-btn--exclude' : '']\"\n @click=\"autoGroup.setOutlierAction(outlier.index, 'exclude')\"\n >Exclude</button>\n <button\n type=\"button\"\n :class=\"['mld-auto-group__action-btn', outlier.action === 'qc' ? 'mld-auto-group__action-btn--active mld-auto-group__action-btn--qc' : '']\"\n @click=\"autoGroup.setOutlierAction(outlier.index, 'qc')\"\n >QC</button>\n </div>\n </div>\n </div>\n </div>\n </template>\n\n <!-- Step: Fields -->\n <template #step-fields>\n <div class=\"mld-auto-group__field-step\">\n <div class=\"mld-auto-group__field-grid\">\n <div\n v-for=\"col in autoGroup.effectiveColumns.value\"\n :key=\"col.index\"\n :class=\"[\n 'mld-auto-group__field-card',\n autoGroup.enabledFields.value.has(col.index) ? 'mld-auto-group__field-card--enabled' : '',\n ]\"\n >\n <div class=\"mld-auto-group__field-header\">\n <label class=\"mld-auto-group__field-toggle\">\n <input\n type=\"checkbox\"\n :checked=\"autoGroup.enabledFields.value.has(col.index)\"\n @change=\"autoGroup.toggleField(col.index)\"\n />\n <span class=\"mld-auto-group__field-toggle-label\">Group by</span>\n </label>\n <span class=\"mld-auto-group__field-cardinality\">{{ col.cardinality }} unique</span>\n </div>\n\n <BaseInput\n :model-value=\"col.name\"\n placeholder=\"Field name...\"\n class=\"mld-auto-group__field-name-input\"\n @update:model-value=\"autoGroup.renameField(col.index, String($event ?? ''))\"\n />\n\n <div class=\"mld-auto-group__field-values\">\n <span\n v-for=\"val in col.uniqueValues.slice(0, 5)\"\n :key=\"val\"\n class=\"mld-auto-group__field-value\"\n >{{ val }}</span>\n <span\n v-if=\"col.uniqueValues.length > 5\"\n class=\"mld-auto-group__field-more\"\n >+{{ col.uniqueValues.length - 5 }} more</span>\n </div>\n </div>\n </div>\n\n <div v-if=\"autoGroup.enabledFields.value.size > 0\" class=\"mld-auto-group__field-summary\">\n Grouping by:\n <strong>{{\n autoGroup.effectiveColumns.value\n .filter(c => autoGroup.enabledFields.value.has(c.index))\n .map(c => c.name)\n .join(' / ')\n }}</strong>\n </div>\n\n <div v-if=\"autoGroup.enabledFields.value.size === 0\" class=\"mld-auto-group__field-warning\">\n Select at least one field for grouping\n </div>\n </div>\n </template>\n\n <!-- Step: Preview -->\n <template #step-preview>\n <div class=\"mld-auto-group__preview-step\">\n <div class=\"mld-auto-group__preview-summary\">\n <span class=\"mld-auto-group__preview-stat\">\n <strong>{{ autoGroup.groups.value.length }}</strong> groups\n </span>\n <span class=\"mld-auto-group__preview-stat\">\n <strong>{{ autoGroup.groups.value.reduce((sum, g) => sum + g.samples.length, 0) }}</strong> samples\n </span>\n <span v-if=\"autoGroup.excludedSamples.value.length > 0\" class=\"mld-auto-group__preview-stat mld-auto-group__preview-stat--excluded\">\n <strong>{{ autoGroup.excludedSamples.value.length }}</strong> excluded\n </span>\n </div>\n\n <div class=\"mld-auto-group__preview-groups\">\n <details\n v-for=\"group in autoGroup.groups.value\"\n :key=\"group.name\"\n class=\"mld-auto-group__preview-group\"\n >\n <summary class=\"mld-auto-group__preview-group-header\">\n <span\n class=\"mld-auto-group__preview-dot\"\n :style=\"{ backgroundColor: group.color }\"\n />\n <span class=\"mld-auto-group__preview-group-name\">{{ group.name }}</span>\n <span\n class=\"mld-auto-group__preview-group-count\"\n :style=\"{ backgroundColor: group.color + '20', color: group.color }\"\n >{{ group.samples.length }}</span>\n </summary>\n <div class=\"mld-auto-group__preview-samples\">\n <span\n v-for=\"sample in group.samples\"\n :key=\"sample\"\n class=\"mld-auto-group__preview-sample\"\n >{{ sample }}</span>\n </div>\n </details>\n </div>\n\n <div v-if=\"autoGroup.excludedSamples.value.length > 0\" class=\"mld-auto-group__preview-excluded\">\n <div class=\"mld-auto-group__preview-excluded-title\">Excluded Samples</div>\n <div class=\"mld-auto-group__preview-excluded-list\">\n <span\n v-for=\"sample in autoGroup.excludedSamples.value\"\n :key=\"sample\"\n class=\"mld-auto-group__preview-sample mld-auto-group__preview-sample--excluded\"\n >{{ sample }}</span>\n </div>\n </div>\n </div>\n </template>\n\n <!-- Custom navigation -->\n <template #navigation=\"{ goBack, goNext, canProceed }\">\n <div class=\"mld-auto-group__nav\">\n <BaseButton variant=\"secondary\" @click=\"handleCancel\">\n Cancel\n </BaseButton>\n <div style=\"flex: 1\" />\n <BaseButton\n v-if=\"!isFirstStep\"\n variant=\"secondary\"\n @click=\"goBack\"\n >\n Back\n </BaseButton>\n <BaseButton\n v-if=\"!isLastStep\"\n variant=\"primary\"\n :disabled=\"!canProceed\"\n @click=\"() => { handleNext(); goNext() }\"\n >\n Next\n </BaseButton>\n <BaseButton\n v-if=\"isLastStep\"\n variant=\"primary\"\n @click=\"handleApply\"\n >\n Apply\n </BaseButton>\n </div>\n </template>\n </StepWizard>\n </div>\n </BaseModal>\n</template>\n\n<style>\n@import '../styles/components/auto-group-modal.css';\n</style>\n"],"names":["_createBlock","BaseModal","_createElementVNode","_createVNode","StepWizard","BaseButton","_unref","_openBlock","_createElementBlock","_toDisplayString","_normalizeClass","_Fragment","BaseInput","_normalizeStyle","_renderList"],"mappings":"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"}
1
+ {"version":3,"file":"AutoGroupModal.vue.js","sources":["../../src/components/AutoGroupModal.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, watch } from 'vue'\nimport BaseModal from './BaseModal.vue'\nimport BaseButton from './BaseButton.vue'\nimport BaseInput from './BaseInput.vue'\nimport StepWizard from './StepWizard.vue'\nimport { useAutoGroup, parseCSV } from '../composables/useAutoGroup'\nimport type { WizardStep } from '../types/components'\nimport type { AutoGroupResult } from '../types/auto-group'\n\ninterface Props {\n modelValue: boolean\n samples?: string[]\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n samples: () => [],\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean]\n 'apply': [result: AutoGroupResult]\n}>()\n\nconst autoGroup = useAutoGroup()\nconst wizardRef = ref<InstanceType<typeof StepWizard> | null>(null)\nconst currentStep = ref(0)\nconst isDragOver = ref(false)\nconst csvFileName = ref('')\n\n// Pre-fill from props\nwatch(() => props.modelValue, (open) => {\n if (open) {\n autoGroup.reset()\n currentStep.value = 0\n csvFileName.value = ''\n if (props.samples.length > 0) {\n autoGroup.rawText.value = props.samples.join('\\n')\n }\n }\n}, { immediate: true })\n\n// Dynamic steps: skip outlier step when no outliers\nconst allSteps: WizardStep[] = [\n { id: 'input', label: 'Input' },\n { id: 'outliers', label: 'Outliers' },\n { id: 'fields', label: 'Fields' },\n { id: 'preview', label: 'Preview' },\n]\n\nconst dynamicSteps = computed<WizardStep[]>(() => {\n if (autoGroup.hasOutliers.value) {\n return allSteps\n }\n return allSteps.filter(s => s.id !== 'outliers')\n})\n\n// Map current step index to step ID\nconst currentStepId = computed(() => {\n const step = dynamicSteps.value[currentStep.value]\n return step?.id ?? 'input'\n})\n\n// Clamp step when dynamic steps change\nwatch(() => dynamicSteps.value.length, (newLen) => {\n if (currentStep.value >= newLen) {\n currentStep.value = newLen - 1\n }\n})\n\n// Step validity\nconst inputValid = computed(() => autoGroup.samples.value.length > 0)\nconst fieldsValid = computed(() => autoGroup.enabledFields.value.size > 0)\n\nwatch([inputValid, fieldsValid, dynamicSteps], () => {\n if (!wizardRef.value) return\n const steps = dynamicSteps.value\n for (let i = 0; i < steps.length; i++) {\n const id = steps[i].id\n if (id === 'input') wizardRef.value.setStepValid(i, inputValid.value)\n else if (id === 'outliers') wizardRef.value.setStepValid(i, true)\n else if (id === 'fields') wizardRef.value.setStepValid(i, fieldsValid.value)\n else if (id === 'preview') wizardRef.value.setStepValid(i, true)\n }\n}, { immediate: true })\n\n// Navigation\nfunction handleNext() {\n if (currentStepId.value === 'input') {\n autoGroup.parseInput()\n }\n // StepWizard handles the actual navigation via v-model\n}\n\nfunction handleApply() {\n emit('apply', autoGroup.result.value)\n emit('update:modelValue', false)\n}\n\nfunction handleCancel() {\n emit('update:modelValue', false)\n}\n\n// CSV file handling\nfunction handleFileDrop(event: DragEvent) {\n event.preventDefault()\n isDragOver.value = false\n const files = event.dataTransfer?.files\n if (files && files.length > 0) {\n processFile(files[0])\n }\n}\n\nfunction handleFileInput(event: Event) {\n const target = event.target as HTMLInputElement\n if (target.files && target.files.length > 0) {\n processFile(target.files[0])\n }\n}\n\nasync function processFile(file: File) {\n if (!file.name.endsWith('.csv') && !file.name.endsWith('.tsv')) return\n\n try {\n const text = await file.text()\n const parsed = parseCSV(text)\n autoGroup.inputMode.value = 'csv'\n autoGroup.csvData.value = parsed\n csvFileName.value = file.name\n } catch {\n // CSV parse error — stay in current state\n }\n}\n\nfunction clearCsvFile() {\n autoGroup.csvData.value = null\n autoGroup.inputMode.value = 'paste'\n csvFileName.value = ''\n}\n\n// Last step check\nconst isLastStep = computed(() => currentStep.value === dynamicSteps.value.length - 1)\nconst isFirstStep = computed(() => currentStep.value === 0)\n</script>\n\n<template>\n <BaseModal\n :model-value=\"modelValue\"\n title=\"Smart Group\"\n size=\"lg\"\n @update:model-value=\"emit('update:modelValue', $event)\"\n @close=\"handleCancel\"\n >\n <div class=\"mld-auto-group\">\n <StepWizard\n ref=\"wizardRef\"\n v-model=\"currentStep\"\n :steps=\"dynamicSteps\"\n :linear=\"true\"\n size=\"sm\"\n >\n <!-- Step: Input -->\n <template #step-input>\n <div class=\"mld-auto-group__input-step\">\n <!-- Mode toggle -->\n <div class=\"mld-auto-group__mode-toggle\">\n <BaseButton\n :variant=\"autoGroup.inputMode.value === 'paste' ? 'primary' : 'secondary'\"\n size=\"sm\"\n @click=\"autoGroup.inputMode.value = 'paste'\"\n >\n Paste\n </BaseButton>\n <BaseButton\n :variant=\"autoGroup.inputMode.value === 'csv' ? 'primary' : 'secondary'\"\n size=\"sm\"\n @click=\"autoGroup.inputMode.value = 'csv'\"\n >\n CSV\n </BaseButton>\n </div>\n\n <!-- Paste mode -->\n <div v-if=\"autoGroup.inputMode.value === 'paste'\" class=\"mld-auto-group__paste\">\n <textarea\n v-model=\"autoGroup.rawText.value\"\n class=\"mld-auto-group__textarea\"\n rows=\"12\"\n placeholder=\"Paste sample names, one per line...\"\n />\n <div v-if=\"autoGroup.samples.value.length > 0\" class=\"mld-auto-group__sample-count\">\n {{ autoGroup.samples.value.length }} samples\n </div>\n </div>\n\n <!-- CSV mode -->\n <div v-if=\"autoGroup.inputMode.value === 'csv'\" class=\"mld-auto-group__csv\">\n <div v-if=\"!autoGroup.csvData.value\"\n :class=\"[\n 'mld-auto-group__dropzone',\n isDragOver ? 'mld-auto-group__dropzone--dragover' : '',\n ]\"\n @drop=\"handleFileDrop\"\n @dragover.prevent=\"isDragOver = true\"\n @dragleave=\"isDragOver = false\"\n >\n <input\n type=\"file\"\n accept=\".csv,.tsv\"\n class=\"mld-auto-group__file-input\"\n @change=\"handleFileInput\"\n />\n <svg class=\"mld-auto-group__upload-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" d=\"M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>\n <p class=\"mld-auto-group__upload-text\">\n <span class=\"mld-auto-group__upload-highlight\">Click to upload</span>\n or drag and drop a CSV file\n </p>\n </div>\n\n <div v-else class=\"mld-auto-group__file-info\">\n <svg class=\"mld-auto-group__file-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>\n <span class=\"mld-auto-group__file-name\">{{ csvFileName }}</span>\n <span class=\"mld-auto-group__file-rows\">{{ autoGroup.csvData.value.rows.length }} rows</span>\n <button type=\"button\" class=\"mld-auto-group__file-clear\" @click=\"clearCsvFile\">\n Change file\n </button>\n </div>\n </div>\n </div>\n </template>\n\n <!-- Step: Outliers -->\n <template #step-outliers>\n <div class=\"mld-auto-group__outlier-step\">\n <div class=\"mld-auto-group__outlier-banner\">\n {{ autoGroup.outliers.value.length }} of {{ autoGroup.samples.value.length }}\n samples have irregular structure\n (fewer than {{ autoGroup.dominantFieldCount.value }} fields, delimiter\n <code>{{ autoGroup.delimiter.value }}</code>)\n </div>\n\n <div class=\"mld-auto-group__outlier-batch\">\n <BaseButton size=\"sm\" variant=\"secondary\" @click=\"autoGroup.setAllOutlierActions('include')\">\n Include All\n </BaseButton>\n <BaseButton size=\"sm\" variant=\"secondary\" @click=\"autoGroup.setAllOutlierActions('exclude')\">\n Exclude All\n </BaseButton>\n </div>\n\n <div class=\"mld-auto-group__outlier-list\">\n <div\n v-for=\"outlier in autoGroup.outliers.value\"\n :key=\"outlier.index\"\n class=\"mld-auto-group__outlier-item\"\n >\n <div class=\"mld-auto-group__outlier-info\">\n <code class=\"mld-auto-group__outlier-name\">{{ outlier.sample }}</code>\n <span class=\"mld-auto-group__outlier-badge\">{{ outlier.fieldCount }} fields</span>\n </div>\n <div class=\"mld-auto-group__outlier-actions\">\n <button\n type=\"button\"\n :class=\"['mld-auto-group__action-btn', outlier.action === 'include' ? 'mld-auto-group__action-btn--active' : '']\"\n @click=\"autoGroup.setOutlierAction(outlier.index, 'include')\"\n >Include</button>\n <button\n type=\"button\"\n :class=\"['mld-auto-group__action-btn', outlier.action === 'exclude' ? 'mld-auto-group__action-btn--active mld-auto-group__action-btn--exclude' : '']\"\n @click=\"autoGroup.setOutlierAction(outlier.index, 'exclude')\"\n >Exclude</button>\n <button\n type=\"button\"\n :class=\"['mld-auto-group__action-btn', outlier.action === 'qc' ? 'mld-auto-group__action-btn--active mld-auto-group__action-btn--qc' : '']\"\n @click=\"autoGroup.setOutlierAction(outlier.index, 'qc')\"\n >QC</button>\n </div>\n </div>\n </div>\n </div>\n </template>\n\n <!-- Step: Fields -->\n <template #step-fields>\n <div class=\"mld-auto-group__field-step\">\n <div class=\"mld-auto-group__field-grid\">\n <div\n v-for=\"col in autoGroup.effectiveColumns.value\"\n :key=\"col.index\"\n :class=\"[\n 'mld-auto-group__field-card',\n autoGroup.enabledFields.value.has(col.index) ? 'mld-auto-group__field-card--enabled' : '',\n ]\"\n >\n <div class=\"mld-auto-group__field-header\">\n <label class=\"mld-auto-group__field-toggle\">\n <input\n type=\"checkbox\"\n :checked=\"autoGroup.enabledFields.value.has(col.index)\"\n @change=\"autoGroup.toggleField(col.index)\"\n />\n <span class=\"mld-auto-group__field-toggle-label\">Group by</span>\n </label>\n <span class=\"mld-auto-group__field-cardinality\">{{ col.cardinality }} unique</span>\n </div>\n\n <BaseInput\n :model-value=\"col.name\"\n placeholder=\"Field name...\"\n class=\"mld-auto-group__field-name-input\"\n @update:model-value=\"autoGroup.renameField(col.index, String($event ?? ''))\"\n />\n\n <div class=\"mld-auto-group__field-values\">\n <span\n v-for=\"val in col.uniqueValues.slice(0, 5)\"\n :key=\"val\"\n class=\"mld-auto-group__field-value\"\n >{{ val }}</span>\n <span\n v-if=\"col.uniqueValues.length > 5\"\n class=\"mld-auto-group__field-more\"\n >+{{ col.uniqueValues.length - 5 }} more</span>\n </div>\n </div>\n </div>\n\n <div v-if=\"autoGroup.enabledFields.value.size > 0\" class=\"mld-auto-group__field-summary\">\n Grouping by:\n <strong>{{\n autoGroup.effectiveColumns.value\n .filter(c => autoGroup.enabledFields.value.has(c.index))\n .map(c => c.name)\n .join(' / ')\n }}</strong>\n </div>\n\n <div v-if=\"autoGroup.enabledFields.value.size === 0\" class=\"mld-auto-group__field-warning\">\n Select at least one field for grouping\n </div>\n </div>\n </template>\n\n <!-- Step: Preview -->\n <template #step-preview>\n <div class=\"mld-auto-group__preview-step\">\n <div class=\"mld-auto-group__preview-summary\">\n <span class=\"mld-auto-group__preview-stat\">\n <strong>{{ autoGroup.groups.value.length }}</strong> groups\n </span>\n <span class=\"mld-auto-group__preview-stat\">\n <strong>{{ autoGroup.groups.value.reduce((sum, g) => sum + g.samples.length, 0) }}</strong> samples\n </span>\n <span v-if=\"autoGroup.excludedSamples.value.length > 0\" class=\"mld-auto-group__preview-stat mld-auto-group__preview-stat--excluded\">\n <strong>{{ autoGroup.excludedSamples.value.length }}</strong> excluded\n </span>\n </div>\n\n <div class=\"mld-auto-group__preview-groups\">\n <details\n v-for=\"group in autoGroup.groups.value\"\n :key=\"group.name\"\n class=\"mld-auto-group__preview-group\"\n >\n <summary class=\"mld-auto-group__preview-group-header\">\n <span\n class=\"mld-auto-group__preview-dot\"\n :style=\"{ backgroundColor: group.color }\"\n />\n <span class=\"mld-auto-group__preview-group-name\">{{ group.name }}</span>\n <span\n class=\"mld-auto-group__preview-group-count\"\n :style=\"{ backgroundColor: group.color + '20', color: group.color }\"\n >{{ group.samples.length }}</span>\n </summary>\n <div class=\"mld-auto-group__preview-samples\">\n <span\n v-for=\"sample in group.samples\"\n :key=\"sample\"\n class=\"mld-auto-group__preview-sample\"\n >{{ sample }}</span>\n </div>\n </details>\n </div>\n\n <div v-if=\"autoGroup.excludedSamples.value.length > 0\" class=\"mld-auto-group__preview-excluded\">\n <div class=\"mld-auto-group__preview-excluded-title\">Excluded Samples</div>\n <div class=\"mld-auto-group__preview-excluded-list\">\n <span\n v-for=\"sample in autoGroup.excludedSamples.value\"\n :key=\"sample\"\n class=\"mld-auto-group__preview-sample mld-auto-group__preview-sample--excluded\"\n >{{ sample }}</span>\n </div>\n </div>\n </div>\n </template>\n\n <!-- Custom navigation -->\n <template #navigation=\"{ goBack, goNext, canProceed }\">\n <div class=\"mld-auto-group__nav\">\n <BaseButton variant=\"secondary\" @click=\"handleCancel\">\n Cancel\n </BaseButton>\n <div style=\"flex: 1\" />\n <BaseButton\n v-if=\"!isFirstStep\"\n variant=\"secondary\"\n @click=\"goBack\"\n >\n Back\n </BaseButton>\n <BaseButton\n v-if=\"!isLastStep\"\n variant=\"primary\"\n :disabled=\"!canProceed\"\n @click=\"() => { handleNext(); goNext() }\"\n >\n Next\n </BaseButton>\n <BaseButton\n v-if=\"isLastStep\"\n variant=\"primary\"\n @click=\"handleApply\"\n >\n Apply\n </BaseButton>\n </div>\n </template>\n </StepWizard>\n </div>\n </BaseModal>\n</template>\n\n<style>\n@import '../styles/components/auto-group-modal.css';\n</style>\n"],"names":["_createBlock","BaseModal","_createElementVNode","_createVNode","StepWizard","BaseButton","_unref","_openBlock","_createElementBlock","_toDisplayString","_normalizeClass","_Fragment","BaseInput","_normalizeStyle","_renderList"],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { ModalSize, ExperimentSummary } from '../types';
2
+ interface Props {
3
+ modelValue: boolean;
4
+ experimentType?: string;
5
+ currentExperimentId?: number | null;
6
+ title?: string;
7
+ size?: ModalSize;
8
+ }
9
+ declare const _default: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
10
+ select: (experiment: ExperimentSummary) => any;
11
+ "update:modelValue": (value: boolean) => any;
12
+ }, string, import('vue').PublicProps, Readonly<Props> & Readonly<{
13
+ onSelect?: ((experiment: ExperimentSummary) => any) | undefined;
14
+ "onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
15
+ }>, {
16
+ size: ModalSize;
17
+ title: string;
18
+ currentExperimentId: number | null;
19
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
20
+ export default _default;
@@ -0,0 +1,164 @@
1
+ import { defineComponent, watch, openBlock, createBlock, withCtx, createElementVNode, createVNode, unref, createElementBlock, toDisplayString, Fragment, renderList, normalizeClass, createCommentVNode, createTextVNode } from "vue";
2
+ import { useExperimentSelector } from "../composables/useExperimentSelector.js";
3
+ import _sfc_main$1 from "./BaseModal.vue.js";
4
+ /* empty css */
5
+ import _sfc_main$2 from "./BaseInput.vue.js";
6
+ /* empty css */
7
+ import _sfc_main$3 from "./BaseSelect.vue.js";
8
+ /* empty css */
9
+ import _sfc_main$6 from "./BasePill.vue.js";
10
+ /* empty css */
11
+ import _sfc_main$4 from "./LoadingSpinner.vue.js";
12
+ /* empty css */
13
+ import _sfc_main$5 from "./EmptyState.vue.js";
14
+ /* empty css */
15
+ const _hoisted_1 = { class: "mld-experiment-selector" };
16
+ const _hoisted_2 = { class: "mld-experiment-selector__filters" };
17
+ const _hoisted_3 = { class: "mld-experiment-selector__search" };
18
+ const _hoisted_4 = { class: "mld-experiment-selector__status-filter" };
19
+ const _hoisted_5 = {
20
+ key: 0,
21
+ class: "mld-experiment-selector__loading"
22
+ };
23
+ const _hoisted_6 = {
24
+ key: 1,
25
+ class: "mld-experiment-selector__error"
26
+ };
27
+ const _hoisted_7 = {
28
+ key: 3,
29
+ class: "mld-experiment-selector__list"
30
+ };
31
+ const _hoisted_8 = ["onClick"];
32
+ const _hoisted_9 = { class: "mld-experiment-selector__row-content" };
33
+ const _hoisted_10 = { class: "mld-experiment-selector__name" };
34
+ const _hoisted_11 = { class: "mld-experiment-selector__meta" };
35
+ const _hoisted_12 = { key: 0 };
36
+ const _sfc_main = /* @__PURE__ */ defineComponent({
37
+ __name: "ExperimentSelectorModal",
38
+ props: {
39
+ modelValue: { type: Boolean },
40
+ experimentType: {},
41
+ currentExperimentId: { default: null },
42
+ title: { default: "Select Experiment" },
43
+ size: { default: "md" }
44
+ },
45
+ emits: ["update:modelValue", "select"],
46
+ setup(__props, { emit: __emit }) {
47
+ const props = __props;
48
+ const emit = __emit;
49
+ const {
50
+ experiments,
51
+ filters,
52
+ isLoading,
53
+ error,
54
+ fetch: fetchExperiments
55
+ } = useExperimentSelector({
56
+ experimentType: props.experimentType
57
+ });
58
+ const statusOptions = [
59
+ { value: "", label: "All statuses" },
60
+ { value: "planned", label: "Planned" },
61
+ { value: "ongoing", label: "Ongoing" },
62
+ { value: "completed", label: "Completed" }
63
+ ];
64
+ const statusVariantMap = {
65
+ planned: "default",
66
+ ongoing: "primary",
67
+ completed: "success"
68
+ };
69
+ function handleStatusChange(value) {
70
+ filters.status = String(value) || null;
71
+ }
72
+ function handleSelect(experiment) {
73
+ emit("select", experiment);
74
+ emit("update:modelValue", false);
75
+ }
76
+ function formatDate(dateStr) {
77
+ try {
78
+ return new Date(dateStr).toLocaleDateString(void 0, {
79
+ year: "numeric",
80
+ month: "short",
81
+ day: "numeric"
82
+ });
83
+ } catch {
84
+ return dateStr;
85
+ }
86
+ }
87
+ watch(
88
+ () => props.modelValue,
89
+ (isOpen) => {
90
+ if (isOpen) fetchExperiments();
91
+ }
92
+ );
93
+ return (_ctx, _cache) => {
94
+ return openBlock(), createBlock(_sfc_main$1, {
95
+ "model-value": __props.modelValue,
96
+ title: __props.title,
97
+ size: __props.size,
98
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => emit("update:modelValue", $event))
99
+ }, {
100
+ default: withCtx(() => [
101
+ createElementVNode("div", _hoisted_1, [
102
+ createElementVNode("div", _hoisted_2, [
103
+ createElementVNode("div", _hoisted_3, [
104
+ createVNode(_sfc_main$2, {
105
+ modelValue: unref(filters).search,
106
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => unref(filters).search = $event),
107
+ placeholder: "Search experiments...",
108
+ size: "sm",
109
+ type: "search"
110
+ }, null, 8, ["modelValue"])
111
+ ]),
112
+ createElementVNode("div", _hoisted_4, [
113
+ createVNode(_sfc_main$3, {
114
+ "model-value": unref(filters).status ?? "",
115
+ options: statusOptions,
116
+ size: "sm",
117
+ "onUpdate:modelValue": handleStatusChange
118
+ }, null, 8, ["model-value"])
119
+ ])
120
+ ]),
121
+ unref(isLoading) ? (openBlock(), createElementBlock("div", _hoisted_5, [
122
+ createVNode(_sfc_main$4, { size: "md" })
123
+ ])) : unref(error) ? (openBlock(), createElementBlock("div", _hoisted_6, toDisplayString(unref(error)), 1)) : unref(experiments).length === 0 ? (openBlock(), createBlock(_sfc_main$5, {
124
+ key: 2,
125
+ title: "No experiments found",
126
+ description: "Try adjusting your search or filters.",
127
+ size: "sm"
128
+ })) : (openBlock(), createElementBlock("div", _hoisted_7, [
129
+ (openBlock(true), createElementBlock(Fragment, null, renderList(unref(experiments), (exp) => {
130
+ return openBlock(), createElementBlock("div", {
131
+ key: exp.id,
132
+ class: normalizeClass(["mld-experiment-selector__row", { "mld-experiment-selector__row--active": exp.id === __props.currentExperimentId }]),
133
+ onClick: ($event) => handleSelect(exp)
134
+ }, [
135
+ createElementVNode("div", _hoisted_9, [
136
+ createElementVNode("div", _hoisted_10, toDisplayString(exp.name), 1),
137
+ createElementVNode("div", _hoisted_11, [
138
+ exp.project ? (openBlock(), createElementBlock("span", _hoisted_12, toDisplayString(exp.project), 1)) : createCommentVNode("", true),
139
+ createElementVNode("span", null, toDisplayString(formatDate(exp.created_at)), 1)
140
+ ])
141
+ ]),
142
+ createVNode(_sfc_main$6, {
143
+ variant: statusVariantMap[exp.status],
144
+ size: "sm"
145
+ }, {
146
+ default: withCtx(() => [
147
+ createTextVNode(toDisplayString(exp.status), 1)
148
+ ]),
149
+ _: 2
150
+ }, 1032, ["variant"])
151
+ ], 10, _hoisted_8);
152
+ }), 128))
153
+ ]))
154
+ ])
155
+ ]),
156
+ _: 1
157
+ }, 8, ["model-value", "title", "size"]);
158
+ };
159
+ }
160
+ });
161
+ export {
162
+ _sfc_main as default
163
+ };
164
+ //# sourceMappingURL=ExperimentSelectorModal.vue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExperimentSelectorModal.vue.js","sources":["../../src/components/ExperimentSelectorModal.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { watch } from 'vue'\nimport type { ModalSize, ExperimentSummary, ExperimentStatus, SelectOption } from '../types'\nimport { useExperimentSelector } from '../composables/useExperimentSelector'\nimport BaseModal from './BaseModal.vue'\nimport BaseInput from './BaseInput.vue'\nimport BaseSelect from './BaseSelect.vue'\nimport BasePill from './BasePill.vue'\nimport LoadingSpinner from './LoadingSpinner.vue'\nimport EmptyState from './EmptyState.vue'\n\ninterface Props {\n modelValue: boolean\n experimentType?: string\n currentExperimentId?: number | null\n title?: string\n size?: ModalSize\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n currentExperimentId: null,\n title: 'Select Experiment',\n size: 'md',\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean]\n select: [experiment: ExperimentSummary]\n}>()\n\nconst {\n experiments,\n filters,\n isLoading,\n error,\n fetch: fetchExperiments,\n} = useExperimentSelector({\n experimentType: props.experimentType,\n})\n\nconst statusOptions: SelectOption<string>[] = [\n { value: '', label: 'All statuses' },\n { value: 'planned', label: 'Planned' },\n { value: 'ongoing', label: 'Ongoing' },\n { value: 'completed', label: 'Completed' },\n]\n\nconst statusVariantMap: Record<ExperimentStatus, string> = {\n planned: 'default',\n ongoing: 'primary',\n completed: 'success',\n}\n\nfunction handleStatusChange(value: string | number) {\n filters.status = (String(value) || null) as ExperimentStatus | null\n}\n\nfunction handleSelect(experiment: ExperimentSummary) {\n emit('select', experiment)\n emit('update:modelValue', false)\n}\n\nfunction formatDate(dateStr: string): string {\n try {\n return new Date(dateStr).toLocaleDateString(undefined, {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n })\n } catch {\n return dateStr\n }\n}\n\n// Fetch on open\nwatch(\n () => props.modelValue,\n (isOpen) => {\n if (isOpen) fetchExperiments()\n },\n)\n</script>\n\n<template>\n <BaseModal\n :model-value=\"modelValue\"\n :title=\"title\"\n :size=\"size\"\n @update:model-value=\"emit('update:modelValue', $event)\"\n >\n <div class=\"mld-experiment-selector\">\n <!-- Filter bar -->\n <div class=\"mld-experiment-selector__filters\">\n <div class=\"mld-experiment-selector__search\">\n <BaseInput\n v-model=\"filters.search\"\n placeholder=\"Search experiments...\"\n size=\"sm\"\n type=\"search\"\n />\n </div>\n <div class=\"mld-experiment-selector__status-filter\">\n <BaseSelect\n :model-value=\"filters.status ?? ''\"\n :options=\"statusOptions\"\n size=\"sm\"\n @update:model-value=\"handleStatusChange\"\n />\n </div>\n </div>\n\n <!-- Loading -->\n <div v-if=\"isLoading\" class=\"mld-experiment-selector__loading\">\n <LoadingSpinner size=\"md\" />\n </div>\n\n <!-- Error -->\n <div v-else-if=\"error\" class=\"mld-experiment-selector__error\">\n {{ error }}\n </div>\n\n <!-- Empty -->\n <EmptyState\n v-else-if=\"experiments.length === 0\"\n title=\"No experiments found\"\n description=\"Try adjusting your search or filters.\"\n size=\"sm\"\n />\n\n <!-- Experiment list -->\n <div v-else class=\"mld-experiment-selector__list\">\n <div\n v-for=\"exp in experiments\"\n :key=\"exp.id\"\n class=\"mld-experiment-selector__row\"\n :class=\"{ 'mld-experiment-selector__row--active': exp.id === currentExperimentId }\"\n @click=\"handleSelect(exp)\"\n >\n <div class=\"mld-experiment-selector__row-content\">\n <div class=\"mld-experiment-selector__name\">{{ exp.name }}</div>\n <div class=\"mld-experiment-selector__meta\">\n <span v-if=\"exp.project\">{{ exp.project }}</span>\n <span>{{ formatDate(exp.created_at) }}</span>\n </div>\n </div>\n <BasePill :variant=\"statusVariantMap[exp.status] as any\" size=\"sm\">\n {{ exp.status }}\n </BasePill>\n </div>\n </div>\n </div>\n </BaseModal>\n</template>\n\n<style>\n@import '../styles/components/experiment-selector-modal.css';\n</style>\n"],"names":["_createBlock","BaseModal","_createElementVNode","_createVNode","BaseInput","_unref","BaseSelect","_openBlock","_createElementBlock","LoadingSpinner","_toDisplayString","EmptyState","_Fragment","_renderList","BasePill","_createTextVNode"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import _sfc_main from "./ExperimentSelectorModal.vue.js";
2
+ /* empty css */
3
+ export {
4
+ _sfc_main as default
5
+ };
6
+ //# sourceMappingURL=ExperimentSelectorModal.vue3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExperimentSelectorModal.vue3.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
@@ -0,0 +1,46 @@
1
+ import { FitState, FitResultSummary } from '../types';
2
+ interface Props {
3
+ state?: FitState;
4
+ progress?: number;
5
+ progressLabel?: string;
6
+ indeterminate?: boolean;
7
+ results?: FitResultSummary[];
8
+ errorMessage?: string;
9
+ runLabel?: string;
10
+ cancelLabel?: string;
11
+ disabled?: boolean;
12
+ }
13
+ declare function __VLS_template(): {
14
+ attrs: Partial<{}>;
15
+ slots: {
16
+ controls?(_: {}): any;
17
+ results?(_: {}): any;
18
+ footer?(_: {}): any;
19
+ };
20
+ refs: {};
21
+ rootEl: HTMLDivElement;
22
+ };
23
+ type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
24
+ declare const __VLS_component: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
25
+ cancel: () => any;
26
+ run: () => any;
27
+ }, string, import('vue').PublicProps, Readonly<Props> & Readonly<{
28
+ onCancel?: (() => any) | undefined;
29
+ onRun?: (() => any) | undefined;
30
+ }>, {
31
+ disabled: boolean;
32
+ progress: number;
33
+ indeterminate: boolean;
34
+ state: FitState;
35
+ results: FitResultSummary[];
36
+ cancelLabel: string;
37
+ progressLabel: string;
38
+ runLabel: string;
39
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
40
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
41
+ export default _default;
42
+ type __VLS_WithTemplateSlots<T, S> = T & {
43
+ new (): {
44
+ $slots: S;
45
+ };
46
+ };
@@ -0,0 +1,118 @@
1
+ import { defineComponent, computed, openBlock, createElementBlock, renderSlot, createElementVNode, createBlock, withCtx, createTextVNode, toDisplayString, createCommentVNode, createVNode, Fragment, renderList, normalizeClass } from "vue";
2
+ import _sfc_main$1 from "./BaseButton.vue.js";
3
+ /* empty css */
4
+ import _sfc_main$2 from "./ProgressBar.vue.js";
5
+ /* empty css */
6
+ import _sfc_main$3 from "./AlertBox.vue.js";
7
+ /* empty css */
8
+ const _hoisted_1 = { class: "mld-fit-panel" };
9
+ const _hoisted_2 = { class: "mld-fit-panel__actions" };
10
+ const _hoisted_3 = {
11
+ key: 0,
12
+ class: "mld-fit-panel__progress"
13
+ };
14
+ const _hoisted_4 = {
15
+ key: 1,
16
+ class: "mld-fit-panel__results"
17
+ };
18
+ const _hoisted_5 = { class: "mld-fit-panel__result-list" };
19
+ const _hoisted_6 = { class: "mld-fit-panel__result-label" };
20
+ const _sfc_main = /* @__PURE__ */ defineComponent({
21
+ __name: "FitPanel",
22
+ props: {
23
+ state: { default: "idle" },
24
+ progress: { default: 0 },
25
+ progressLabel: { default: "Fitting..." },
26
+ indeterminate: { type: Boolean, default: false },
27
+ results: { default: () => [] },
28
+ errorMessage: {},
29
+ runLabel: { default: "Run Fit" },
30
+ cancelLabel: { default: "Cancel" },
31
+ disabled: { type: Boolean, default: false }
32
+ },
33
+ emits: ["run", "cancel"],
34
+ setup(__props, { emit: __emit }) {
35
+ const props = __props;
36
+ const emit = __emit;
37
+ const isRunning = computed(() => props.state === "running");
38
+ const showRunButton = computed(() => !isRunning.value);
39
+ const showResults = computed(() => props.state === "completed" && props.results.length > 0);
40
+ const showError = computed(() => props.state === "error" && props.errorMessage);
41
+ function variantClass(variant) {
42
+ if (!variant || variant === "default") return "";
43
+ return `mld-fit-panel__result-value--${variant}`;
44
+ }
45
+ return (_ctx, _cache) => {
46
+ return openBlock(), createElementBlock("div", _hoisted_1, [
47
+ renderSlot(_ctx.$slots, "controls"),
48
+ createElementVNode("div", _hoisted_2, [
49
+ showRunButton.value ? (openBlock(), createBlock(_sfc_main$1, {
50
+ key: 0,
51
+ variant: "primary",
52
+ size: "sm",
53
+ disabled: __props.disabled,
54
+ "full-width": "",
55
+ onClick: _cache[0] || (_cache[0] = ($event) => emit("run"))
56
+ }, {
57
+ default: withCtx(() => [
58
+ createTextVNode(toDisplayString(__props.runLabel), 1)
59
+ ]),
60
+ _: 1
61
+ }, 8, ["disabled"])) : createCommentVNode("", true),
62
+ isRunning.value ? (openBlock(), createBlock(_sfc_main$1, {
63
+ key: 1,
64
+ variant: "ghost",
65
+ size: "sm",
66
+ "full-width": "",
67
+ onClick: _cache[1] || (_cache[1] = ($event) => emit("cancel"))
68
+ }, {
69
+ default: withCtx(() => [
70
+ createTextVNode(toDisplayString(__props.cancelLabel), 1)
71
+ ]),
72
+ _: 1
73
+ })) : createCommentVNode("", true)
74
+ ]),
75
+ isRunning.value ? (openBlock(), createElementBlock("div", _hoisted_3, [
76
+ createVNode(_sfc_main$2, {
77
+ value: __props.progress,
78
+ label: __props.progressLabel,
79
+ indeterminate: __props.indeterminate,
80
+ "show-value": !__props.indeterminate,
81
+ size: "sm"
82
+ }, null, 8, ["value", "label", "indeterminate", "show-value"])
83
+ ])) : createCommentVNode("", true),
84
+ showResults.value ? (openBlock(), createElementBlock("div", _hoisted_4, [
85
+ renderSlot(_ctx.$slots, "results", {}, () => [
86
+ createElementVNode("div", _hoisted_5, [
87
+ (openBlock(true), createElementBlock(Fragment, null, renderList(__props.results, (item, idx) => {
88
+ return openBlock(), createElementBlock("div", {
89
+ key: idx,
90
+ class: "mld-fit-panel__result-row"
91
+ }, [
92
+ createElementVNode("span", _hoisted_6, toDisplayString(item.label), 1),
93
+ createElementVNode("span", {
94
+ class: normalizeClass(["mld-fit-panel__result-value", variantClass(item.variant)])
95
+ }, toDisplayString(item.value), 3)
96
+ ]);
97
+ }), 128))
98
+ ])
99
+ ])
100
+ ])) : createCommentVNode("", true),
101
+ showError.value ? (openBlock(), createBlock(_sfc_main$3, {
102
+ key: 2,
103
+ type: "error"
104
+ }, {
105
+ default: withCtx(() => [
106
+ createTextVNode(toDisplayString(__props.errorMessage), 1)
107
+ ]),
108
+ _: 1
109
+ })) : createCommentVNode("", true),
110
+ renderSlot(_ctx.$slots, "footer")
111
+ ]);
112
+ };
113
+ }
114
+ });
115
+ export {
116
+ _sfc_main as default
117
+ };
118
+ //# sourceMappingURL=FitPanel.vue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FitPanel.vue.js","sources":["../../src/components/FitPanel.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { FitState, FitResultSummary } from '../types'\nimport BaseButton from './BaseButton.vue'\nimport ProgressBar from './ProgressBar.vue'\nimport AlertBox from './AlertBox.vue'\n\ninterface Props {\n state?: FitState\n progress?: number\n progressLabel?: string\n indeterminate?: boolean\n results?: FitResultSummary[]\n errorMessage?: string\n runLabel?: string\n cancelLabel?: string\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n state: 'idle',\n progress: 0,\n progressLabel: 'Fitting...',\n indeterminate: false,\n results: () => [],\n runLabel: 'Run Fit',\n cancelLabel: 'Cancel',\n disabled: false,\n})\n\nconst emit = defineEmits<{\n run: []\n cancel: []\n}>()\n\nconst isRunning = computed(() => props.state === 'running')\nconst showRunButton = computed(() => !isRunning.value)\nconst showResults = computed(() => props.state === 'completed' && props.results.length > 0)\nconst showError = computed(() => props.state === 'error' && props.errorMessage)\n\nfunction variantClass(variant?: string): string {\n if (!variant || variant === 'default') return ''\n return `mld-fit-panel__result-value--${variant}`\n}\n</script>\n\n<template>\n <div class=\"mld-fit-panel\">\n <!-- Plugin controls slot -->\n <slot name=\"controls\" />\n\n <!-- Action bar -->\n <div class=\"mld-fit-panel__actions\">\n <BaseButton\n v-if=\"showRunButton\"\n variant=\"primary\"\n size=\"sm\"\n :disabled=\"disabled\"\n full-width\n @click=\"emit('run')\"\n >\n {{ runLabel }}\n </BaseButton>\n <BaseButton\n v-if=\"isRunning\"\n variant=\"ghost\"\n size=\"sm\"\n full-width\n @click=\"emit('cancel')\"\n >\n {{ cancelLabel }}\n </BaseButton>\n </div>\n\n <!-- Progress -->\n <div v-if=\"isRunning\" class=\"mld-fit-panel__progress\">\n <ProgressBar\n :value=\"progress\"\n :label=\"progressLabel\"\n :indeterminate=\"indeterminate\"\n :show-value=\"!indeterminate\"\n size=\"sm\"\n />\n </div>\n\n <!-- Results -->\n <div v-if=\"showResults\" class=\"mld-fit-panel__results\">\n <slot name=\"results\">\n <div class=\"mld-fit-panel__result-list\">\n <div\n v-for=\"(item, idx) in results\"\n :key=\"idx\"\n class=\"mld-fit-panel__result-row\"\n >\n <span class=\"mld-fit-panel__result-label\">{{ item.label }}</span>\n <span\n class=\"mld-fit-panel__result-value\"\n :class=\"variantClass(item.variant)\"\n >\n {{ item.value }}\n </span>\n </div>\n </div>\n </slot>\n </div>\n\n <!-- Error -->\n <AlertBox v-if=\"showError\" type=\"error\">\n {{ errorMessage }}\n </AlertBox>\n\n <!-- Footer slot -->\n <slot name=\"footer\" />\n </div>\n</template>\n\n<style>\n@import '../styles/components/fit-panel.css';\n</style>\n"],"names":["_openBlock","_createElementBlock","_renderSlot","_createElementVNode","_createBlock","BaseButton","_createVNode","ProgressBar","_Fragment","_renderList","_toDisplayString","AlertBox"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmBA,UAAM,QAAQ;AAWd,UAAM,OAAO;AAKb,UAAM,YAAY,SAAS,MAAM,MAAM,UAAU,SAAS;AAC1D,UAAM,gBAAgB,SAAS,MAAM,CAAC,UAAU,KAAK;AACrD,UAAM,cAAc,SAAS,MAAM,MAAM,UAAU,eAAe,MAAM,QAAQ,SAAS,CAAC;AAC1F,UAAM,YAAY,SAAS,MAAM,MAAM,UAAU,WAAW,MAAM,YAAY;AAE9E,aAAS,aAAa,SAA0B;AAC9C,UAAI,CAAC,WAAW,YAAY,UAAW,QAAO;AAC9C,aAAO,gCAAgC,OAAO;AAAA,IAChD;;AAIE,aAAAA,UAAA,GAAAC,mBAkEM,OAlEN,YAkEM;AAAA,QAhEJC,WAAwB,KAAA,QAAA,UAAA;AAAA,QAGxBC,mBAoBM,OApBN,YAoBM;AAAA,UAlBI,cAAA,sBADRC,YASaC,aAAA;AAAA;YAPX,SAAQ;AAAA,YACR,MAAK;AAAA,YACJ,UAAU,QAAA;AAAA,YACX,cAAA;AAAA,YACC,+CAAO,KAAI,KAAA;AAAA,UAAA;6BAEZ,MAAc;AAAA,8CAAX,QAAA,QAAQ,GAAA,CAAA;AAAA,YAAA;;;UAGL,UAAA,sBADRD,YAQaC,aAAA;AAAA;YANX,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,cAAA;AAAA,YACC,+CAAO,KAAI,QAAA;AAAA,UAAA;6BAEZ,MAAiB;AAAA,8CAAd,QAAA,WAAW,GAAA,CAAA;AAAA,YAAA;;;;QAKP,UAAA,SAAXL,UAAA,GAAAC,mBAQM,OARN,YAQM;AAAA,UAPJK,YAMEC,aAAA;AAAA,YALC,OAAO,QAAA;AAAA,YACP,OAAO,QAAA;AAAA,YACP,eAAe,QAAA;AAAA,YACf,eAAa,QAAA;AAAA,YACd,MAAK;AAAA,UAAA;;QAKE,YAAA,SAAXP,UAAA,GAAAC,mBAkBM,OAlBN,YAkBM;AAAA,UAjBJC,WAgBO,4BAhBP,MAgBO;AAAA,YAfLC,mBAcM,OAdN,YAcM;AAAA,eAbJH,UAAA,IAAA,GAAAC,mBAYMO,UAAA,MAAAC,WAXkB,QAAA,SAAO,CAArB,MAAM,QAAG;oCADnBR,mBAYM,OAAA;AAAA,kBAVH,KAAK;AAAA,kBACN,OAAM;AAAA,gBAAA;kBAENE,mBAAiE,QAAjE,YAAiEO,gBAApB,KAAK,KAAK,GAAA,CAAA;AAAA,kBACvDP,mBAKO,QAAA;AAAA,oBAJL,uBAAM,+BACE,aAAa,KAAK,OAAO,CAAA,CAAA;AAAA,kBAAA,GAE9BO,gBAAA,KAAK,KAAK,GAAA,CAAA;AAAA,gBAAA;;;;;QAQP,UAAA,sBAAhBN,YAEWO,aAAA;AAAA;UAFgB,MAAK;AAAA,QAAA;2BAC9B,MAAkB;AAAA,4CAAf,QAAA,YAAY,GAAA,CAAA;AAAA,UAAA;;;QAIjBT,WAAsB,KAAA,QAAA,QAAA;AAAA,MAAA;;;;"}
@@ -0,0 +1,6 @@
1
+ import _sfc_main from "./FitPanel.vue.js";
2
+ /* empty css */
3
+ export {
4
+ _sfc_main as default
5
+ };
6
+ //# sourceMappingURL=FitPanel.vue3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FitPanel.vue3.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}