@morscherlab/mld-sdk 0.6.1 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/components/AuditTrail.vue.d.ts +1 -10
  2. package/dist/components/AuditTrail.vue.js.map +1 -1
  3. package/dist/components/BatchProgressList.vue.d.ts +1 -17
  4. package/dist/components/BatchProgressList.vue.js.map +1 -1
  5. package/dist/components/Breadcrumb.vue.d.ts +1 -5
  6. package/dist/components/Breadcrumb.vue.js.map +1 -1
  7. package/dist/components/DateTimePicker.vue.js +0 -1
  8. package/dist/components/DateTimePicker.vue.js.map +1 -1
  9. package/dist/components/MoleculeInput.vue.d.ts +1 -4
  10. package/dist/components/MoleculeInput.vue.js.map +1 -1
  11. package/dist/components/RackEditor.vue.js +2 -2
  12. package/dist/components/RackEditor.vue.js.map +1 -1
  13. package/dist/components/ReagentList.vue.d.ts +1 -15
  14. package/dist/components/ReagentList.vue.js.map +1 -1
  15. package/dist/components/SampleHierarchyTree.vue.d.ts +1 -12
  16. package/dist/components/SampleHierarchyTree.vue.js.map +1 -1
  17. package/dist/components/ScheduleCalendar.vue.js.map +1 -1
  18. package/dist/components/ScientificNumber.vue.d.ts +1 -1
  19. package/dist/components/ScientificNumber.vue.js.map +1 -1
  20. package/dist/components/SettingsModal.vue.d.ts +1 -5
  21. package/dist/components/SettingsModal.vue.js.map +1 -1
  22. package/dist/components/StepWizard.vue.d.ts +1 -8
  23. package/dist/components/StepWizard.vue.js.map +1 -1
  24. package/dist/components/UnitInput.vue.d.ts +1 -6
  25. package/dist/components/UnitInput.vue.js.map +1 -1
  26. package/dist/styles.css +20 -0
  27. package/dist/types/index.d.ts +1 -1
  28. package/package.json +1 -1
  29. package/src/components/AuditTrail.vue +1 -12
  30. package/src/components/BatchProgressList.vue +1 -20
  31. package/src/components/Breadcrumb.vue +1 -5
  32. package/src/components/DateTimePicker.vue +1 -1
  33. package/src/components/MoleculeInput.story.vue +1 -1
  34. package/src/components/MoleculeInput.vue +1 -5
  35. package/src/components/RackEditor.vue +2 -2
  36. package/src/components/ReagentList.story.vue +1 -1
  37. package/src/components/ReagentList.vue +1 -26
  38. package/src/components/SampleHierarchyTree.story.vue +1 -1
  39. package/src/components/SampleHierarchyTree.vue +1 -25
  40. package/src/components/ScheduleCalendar.vue +1 -1
  41. package/src/components/ScientificNumber.story.vue +1 -2
  42. package/src/components/ScientificNumber.vue +1 -2
  43. package/src/components/SettingsModal.vue +1 -7
  44. package/src/components/StepWizard.vue +1 -10
  45. package/src/components/UnitInput.vue +1 -7
  46. package/src/styles/components/button.css +2 -0
  47. package/src/styles/components/datetime-picker.css +4 -0
  48. package/src/styles/components/rack-editor.css +6 -0
  49. package/src/types/index.ts +10 -0
@@ -1 +1 @@
1
- {"version":3,"file":"StepWizard.vue.js","sources":["../../src/components/StepWizard.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed } from 'vue'\n\ninterface WizardStep {\n id: string\n label: string\n description?: string\n icon?: string\n optional?: boolean\n}\n\ntype WizardStepState = 'pending' | 'active' | 'completed' | 'disabled'\n\ninterface Props {\n steps: WizardStep[]\n modelValue?: number\n linear?: boolean\n showProgress?: boolean\n showStepNumbers?: boolean\n size?: 'sm' | 'md' | 'lg'\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n modelValue: 0,\n linear: true,\n showProgress: true,\n showStepNumbers: true,\n size: 'md',\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [index: number]\n 'complete': []\n 'cancel': []\n 'step-change': [change: [from: number, to: number]]\n}>()\n\nconst stepValidity = ref<boolean[]>([])\n\n// Initialize validity for all steps to true\nif (stepValidity.value.length === 0) {\n stepValidity.value = props.steps.map(() => true)\n}\n\nconst stepStates = computed<WizardStepState[]>(() => {\n return props.steps.map((_, index) => {\n if (index === props.modelValue) return 'active'\n if (index < props.modelValue && stepValidity.value[index] !== false) return 'completed'\n if (index > props.modelValue && props.linear) {\n for (let i = props.modelValue; i < index; i++) {\n if (stepValidity.value[i] === false) return 'disabled'\n }\n }\n return 'pending'\n })\n})\n\nfunction setStepValid(index: number, valid: boolean) {\n if (index >= 0 && index < props.steps.length) {\n stepValidity.value[index] = valid\n }\n}\n\nfunction goToStep(index: number) {\n if (index < 0 || index >= props.steps.length) return\n if (stepStates.value[index] === 'disabled') return\n\n if (props.linear && index > props.modelValue) {\n for (let i = props.modelValue; i < index; i++) {\n if (stepValidity.value[i] === false) return\n }\n }\n\n const from = props.modelValue\n emit('step-change', [from, index])\n emit('update:modelValue', index)\n}\n\nfunction goNext() {\n if (stepValidity.value[props.modelValue] === false) return\n if (props.modelValue < props.steps.length - 1) {\n goToStep(props.modelValue + 1)\n }\n}\n\nfunction goBack() {\n if (props.modelValue > 0) {\n goToStep(props.modelValue - 1)\n }\n}\n\nfunction finish() {\n if (stepValidity.value[props.modelValue] === false) return\n if (props.modelValue === props.steps.length - 1) {\n emit('complete')\n }\n}\n\nfunction cancel() {\n emit('cancel')\n}\n\nfunction handleKeydown(event: KeyboardEvent) {\n switch (event.key) {\n case 'ArrowLeft':\n event.preventDefault()\n goBack()\n break\n case 'ArrowRight':\n event.preventDefault()\n goNext()\n break\n case 'Escape':\n cancel()\n break\n }\n}\n\ndefineExpose({ setStepValid })\n</script>\n\n<template>\n <div\n :class=\"['mld-wizard', `mld-wizard--${props.size}`]\"\n tabindex=\"0\"\n @keydown=\"handleKeydown\"\n >\n <!-- Progress indicator -->\n <div v-if=\"props.showProgress\" class=\"mld-wizard__progress\">\n <slot name=\"progress\" :steps=\"props.steps\" :current=\"props.modelValue\" :states=\"stepStates\">\n <div class=\"mld-wizard__steps-indicator\">\n <template v-for=\"(step, index) in props.steps\" :key=\"step.id\">\n <!-- Connector line (before each step except first) -->\n <div\n v-if=\"index > 0\"\n :class=\"[\n 'mld-wizard__step-connector',\n stepStates[index - 1] === 'completed' ? 'mld-wizard__step-connector--completed' : '',\n ]\"\n />\n <!-- Step indicator -->\n <div\n :class=\"[\n 'mld-wizard__step-indicator',\n `mld-wizard__step-indicator--${stepStates[index]}`,\n ]\"\n @click=\"goToStep(index)\"\n >\n <div class=\"mld-wizard__step-dot\">\n <template v-if=\"stepStates[index] === 'completed'\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n </template>\n <template v-else-if=\"props.showStepNumbers\">\n {{ index + 1 }}\n </template>\n </div>\n <div class=\"mld-wizard__step-label\">{{ step.label }}</div>\n </div>\n </template>\n </div>\n </slot>\n </div>\n\n <!-- Step content -->\n <div class=\"mld-wizard__body\">\n <div\n v-for=\"(step, index) in props.steps\"\n :key=\"step.id\"\n v-show=\"index === props.modelValue\"\n class=\"mld-wizard__step-content\"\n >\n <slot :name=\"`step-${step.id}`\" :step=\"step\" :index=\"index\" />\n </div>\n </div>\n\n <!-- Navigation -->\n <div class=\"mld-wizard__navigation\">\n <slot\n name=\"navigation\"\n :go-back=\"goBack\"\n :go-next=\"goNext\"\n :finish=\"finish\"\n :cancel=\"cancel\"\n :is-first=\"props.modelValue === 0\"\n :is-last=\"props.modelValue === props.steps.length - 1\"\n :can-proceed=\"stepValidity[props.modelValue] !== false\"\n >\n <button\n type=\"button\"\n class=\"mld-wizard__nav-btn mld-wizard__nav-btn--cancel\"\n @click=\"cancel\"\n >\n Cancel\n </button>\n <div style=\"flex: 1\" />\n <button\n type=\"button\"\n class=\"mld-wizard__nav-btn mld-wizard__nav-btn--back\"\n :disabled=\"props.modelValue === 0\"\n @click=\"goBack\"\n >\n Back\n </button>\n <button\n v-if=\"props.modelValue < props.steps.length - 1\"\n type=\"button\"\n class=\"mld-wizard__nav-btn mld-wizard__nav-btn--next\"\n :disabled=\"stepValidity[props.modelValue] === false\"\n @click=\"goNext\"\n >\n Next\n </button>\n <button\n v-else\n type=\"button\"\n class=\"mld-wizard__nav-btn mld-wizard__nav-btn--finish\"\n :disabled=\"stepValidity[props.modelValue] === false\"\n @click=\"finish\"\n >\n Finish\n </button>\n </slot>\n </div>\n </div>\n</template>\n\n<style>\n@import '../styles/components/step-wizard.css';\n</style>\n"],"names":["_createElementBlock","_normalizeClass","_openBlock","_renderSlot","_createElementVNode","_Fragment","_toDisplayString"],"mappings":"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"}
1
+ {"version":3,"file":"StepWizard.vue.js","sources":["../../src/components/StepWizard.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed } from 'vue'\nimport type { WizardStep, WizardStepState } from '../types'\n\ninterface Props {\n steps: WizardStep[]\n modelValue?: number\n linear?: boolean\n showProgress?: boolean\n showStepNumbers?: boolean\n size?: 'sm' | 'md' | 'lg'\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n modelValue: 0,\n linear: true,\n showProgress: true,\n showStepNumbers: true,\n size: 'md',\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [index: number]\n 'complete': []\n 'cancel': []\n 'step-change': [change: [from: number, to: number]]\n}>()\n\nconst stepValidity = ref<boolean[]>([])\n\n// Initialize validity for all steps to true\nif (stepValidity.value.length === 0) {\n stepValidity.value = props.steps.map(() => true)\n}\n\nconst stepStates = computed<WizardStepState[]>(() => {\n return props.steps.map((_, index) => {\n if (index === props.modelValue) return 'active'\n if (index < props.modelValue && stepValidity.value[index] !== false) return 'completed'\n if (index > props.modelValue && props.linear) {\n for (let i = props.modelValue; i < index; i++) {\n if (stepValidity.value[i] === false) return 'disabled'\n }\n }\n return 'pending'\n })\n})\n\nfunction setStepValid(index: number, valid: boolean) {\n if (index >= 0 && index < props.steps.length) {\n stepValidity.value[index] = valid\n }\n}\n\nfunction goToStep(index: number) {\n if (index < 0 || index >= props.steps.length) return\n if (stepStates.value[index] === 'disabled') return\n\n if (props.linear && index > props.modelValue) {\n for (let i = props.modelValue; i < index; i++) {\n if (stepValidity.value[i] === false) return\n }\n }\n\n const from = props.modelValue\n emit('step-change', [from, index])\n emit('update:modelValue', index)\n}\n\nfunction goNext() {\n if (stepValidity.value[props.modelValue] === false) return\n if (props.modelValue < props.steps.length - 1) {\n goToStep(props.modelValue + 1)\n }\n}\n\nfunction goBack() {\n if (props.modelValue > 0) {\n goToStep(props.modelValue - 1)\n }\n}\n\nfunction finish() {\n if (stepValidity.value[props.modelValue] === false) return\n if (props.modelValue === props.steps.length - 1) {\n emit('complete')\n }\n}\n\nfunction cancel() {\n emit('cancel')\n}\n\nfunction handleKeydown(event: KeyboardEvent) {\n switch (event.key) {\n case 'ArrowLeft':\n event.preventDefault()\n goBack()\n break\n case 'ArrowRight':\n event.preventDefault()\n goNext()\n break\n case 'Escape':\n cancel()\n break\n }\n}\n\ndefineExpose({ setStepValid })\n</script>\n\n<template>\n <div\n :class=\"['mld-wizard', `mld-wizard--${props.size}`]\"\n tabindex=\"0\"\n @keydown=\"handleKeydown\"\n >\n <!-- Progress indicator -->\n <div v-if=\"props.showProgress\" class=\"mld-wizard__progress\">\n <slot name=\"progress\" :steps=\"props.steps\" :current=\"props.modelValue\" :states=\"stepStates\">\n <div class=\"mld-wizard__steps-indicator\">\n <template v-for=\"(step, index) in props.steps\" :key=\"step.id\">\n <!-- Connector line (before each step except first) -->\n <div\n v-if=\"index > 0\"\n :class=\"[\n 'mld-wizard__step-connector',\n stepStates[index - 1] === 'completed' ? 'mld-wizard__step-connector--completed' : '',\n ]\"\n />\n <!-- Step indicator -->\n <div\n :class=\"[\n 'mld-wizard__step-indicator',\n `mld-wizard__step-indicator--${stepStates[index]}`,\n ]\"\n @click=\"goToStep(index)\"\n >\n <div class=\"mld-wizard__step-dot\">\n <template v-if=\"stepStates[index] === 'completed'\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n </template>\n <template v-else-if=\"props.showStepNumbers\">\n {{ index + 1 }}\n </template>\n </div>\n <div class=\"mld-wizard__step-label\">{{ step.label }}</div>\n </div>\n </template>\n </div>\n </slot>\n </div>\n\n <!-- Step content -->\n <div class=\"mld-wizard__body\">\n <div\n v-for=\"(step, index) in props.steps\"\n :key=\"step.id\"\n v-show=\"index === props.modelValue\"\n class=\"mld-wizard__step-content\"\n >\n <slot :name=\"`step-${step.id}`\" :step=\"step\" :index=\"index\" />\n </div>\n </div>\n\n <!-- Navigation -->\n <div class=\"mld-wizard__navigation\">\n <slot\n name=\"navigation\"\n :go-back=\"goBack\"\n :go-next=\"goNext\"\n :finish=\"finish\"\n :cancel=\"cancel\"\n :is-first=\"props.modelValue === 0\"\n :is-last=\"props.modelValue === props.steps.length - 1\"\n :can-proceed=\"stepValidity[props.modelValue] !== false\"\n >\n <button\n type=\"button\"\n class=\"mld-wizard__nav-btn mld-wizard__nav-btn--cancel\"\n @click=\"cancel\"\n >\n Cancel\n </button>\n <div style=\"flex: 1\" />\n <button\n type=\"button\"\n class=\"mld-wizard__nav-btn mld-wizard__nav-btn--back\"\n :disabled=\"props.modelValue === 0\"\n @click=\"goBack\"\n >\n Back\n </button>\n <button\n v-if=\"props.modelValue < props.steps.length - 1\"\n type=\"button\"\n class=\"mld-wizard__nav-btn mld-wizard__nav-btn--next\"\n :disabled=\"stepValidity[props.modelValue] === false\"\n @click=\"goNext\"\n >\n Next\n </button>\n <button\n v-else\n type=\"button\"\n class=\"mld-wizard__nav-btn mld-wizard__nav-btn--finish\"\n :disabled=\"stepValidity[props.modelValue] === false\"\n @click=\"finish\"\n >\n Finish\n </button>\n </slot>\n </div>\n </div>\n</template>\n\n<style>\n@import '../styles/components/step-wizard.css';\n</style>\n"],"names":["_createElementBlock","_normalizeClass","_openBlock","_renderSlot","_createElementVNode","_Fragment","_toDisplayString"],"mappings":"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"}
@@ -1,9 +1,4 @@
1
- interface UnitOption {
2
- value: string;
3
- label: string;
4
- factor?: number;
5
- group?: string;
6
- }
1
+ import { UnitOption } from '../types';
7
2
  interface Props {
8
3
  modelValue?: number;
9
4
  unit?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"UnitInput.vue.js","sources":["../../src/components/UnitInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\n\ninterface UnitOption {\n value: string\n label: string\n factor?: number\n group?: string\n}\n\ninterface Props {\n modelValue?: number\n unit?: string\n units: UnitOption[]\n precision?: number\n min?: number\n max?: number\n step?: number\n placeholder?: string\n disabled?: boolean\n error?: boolean\n size?: 'sm' | 'md' | 'lg'\n convertOnUnitChange?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n precision: undefined,\n step: undefined,\n placeholder: 'Enter value',\n disabled: false,\n error: false,\n size: 'md',\n convertOnUnitChange: false,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: number | undefined]\n 'update:unit': [unit: string]\n 'change': [data: { value: number | undefined; unit: string }]\n}>()\n\nconst conversionHint = ref<string | null>(null)\n\nconst currentUnit = computed(() => props.unit || (props.units.length > 0 ? props.units[0].value : ''))\n\n// Group units by their group property\nconst hasGroups = computed(() => props.units.some(u => u.group))\n\nconst groupedUnits = computed(() => {\n if (!hasGroups.value) return null\n const groups = new Map<string, UnitOption[]>()\n const ungrouped: UnitOption[] = []\n for (const u of props.units) {\n if (u.group) {\n if (!groups.has(u.group)) groups.set(u.group, [])\n groups.get(u.group)!.push(u)\n } else {\n ungrouped.push(u)\n }\n }\n return { groups, ungrouped }\n})\n\nfunction findUnit(value: string): UnitOption | undefined {\n return props.units.find(u => u.value === value)\n}\n\nfunction roundToPrecision(value: number): number {\n if (props.precision === undefined) return value\n const factor = Math.pow(10, props.precision)\n return Math.round(value * factor) / factor\n}\n\nfunction clamp(value: number): number {\n let result = value\n if (props.min !== undefined && result < props.min) result = props.min\n if (props.max !== undefined && result > props.max) result = props.max\n return result\n}\n\nfunction handleValueInput(event: Event) {\n const target = event.target as HTMLInputElement\n const value = target.value === '' ? undefined : Number(target.value)\n\n conversionHint.value = null\n\n if (value === undefined || isNaN(value)) {\n emit('update:modelValue', undefined)\n emit('change', { value: undefined, unit: currentUnit.value })\n return\n }\n\n const clamped = clamp(value)\n emit('update:modelValue', clamped)\n emit('change', { value: clamped, unit: currentUnit.value })\n}\n\nfunction handleUnitChange(event: Event) {\n const target = event.target as HTMLSelectElement\n const newUnitValue = target.value\n const oldUnitValue = currentUnit.value\n\n let newValue = props.modelValue\n\n if (props.convertOnUnitChange && newValue !== undefined) {\n const oldUnit = findUnit(oldUnitValue)\n const newUnit = findUnit(newUnitValue)\n\n if (oldUnit?.factor !== undefined && newUnit?.factor !== undefined && newUnit.factor !== 0) {\n const converted = newValue * (oldUnit.factor / newUnit.factor)\n newValue = roundToPrecision(converted)\n newValue = clamp(newValue)\n conversionHint.value = `Converted from ${oldUnit.label} to ${newUnit.label}`\n emit('update:modelValue', newValue)\n }\n }\n\n emit('update:unit', newUnitValue)\n emit('change', { value: newValue, unit: newUnitValue })\n}\n\n// Clear conversion hint after a delay\nwatch(conversionHint, (hint) => {\n if (hint) {\n setTimeout(() => {\n conversionHint.value = null\n }, 3000)\n }\n})\n</script>\n\n<template>\n <div\n :class=\"[\n 'mld-unit-input',\n error ? 'mld-unit-input--error' : '',\n disabled ? 'mld-unit-input--disabled' : '',\n ]\"\n >\n <div class=\"mld-unit-input__controls\">\n <input\n type=\"number\"\n :value=\"modelValue\"\n :min=\"min\"\n :max=\"max\"\n :step=\"step\"\n :disabled=\"disabled\"\n :placeholder=\"placeholder\"\n :class=\"[\n 'mld-unit-input__value',\n `mld-unit-input__value--${size}`,\n disabled ? 'mld-unit-input__value--disabled' : '',\n ]\"\n aria-label=\"Value\"\n @input=\"handleValueInput\"\n />\n\n <div class=\"mld-unit-input__unit\">\n <select\n :value=\"currentUnit\"\n :disabled=\"disabled\"\n :class=\"[\n 'mld-unit-input__unit-select',\n `mld-unit-input__unit-select--${size}`,\n ]\"\n aria-label=\"Unit\"\n @change=\"handleUnitChange\"\n >\n <template v-if=\"groupedUnits\">\n <template v-if=\"groupedUnits.ungrouped.length > 0\">\n <option\n v-for=\"u in groupedUnits.ungrouped\"\n :key=\"u.value\"\n :value=\"u.value\"\n >\n {{ u.label }}\n </option>\n </template>\n <optgroup\n v-for=\"[groupLabel, groupUnits] in groupedUnits.groups\"\n :key=\"groupLabel\"\n :label=\"groupLabel\"\n class=\"mld-unit-input__unit-group\"\n >\n <option\n v-for=\"u in groupUnits\"\n :key=\"u.value\"\n :value=\"u.value\"\n >\n {{ u.label }}\n </option>\n </optgroup>\n </template>\n <template v-else>\n <option\n v-for=\"u in units\"\n :key=\"u.value\"\n :value=\"u.value\"\n >\n {{ u.label }}\n </option>\n </template>\n </select>\n </div>\n </div>\n\n <div\n v-if=\"conversionHint\"\n class=\"mld-unit-input__conversion-hint\"\n >\n {{ conversionHint }}\n </div>\n </div>\n</template>\n\n<style>\n@import '../styles/components/unit-input.css';\n</style>\n"],"names":["_createElementBlock","_normalizeClass","_createElementVNode","_Fragment","_openBlock","_renderList","_toDisplayString"],"mappings":"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"}
1
+ {"version":3,"file":"UnitInput.vue.js","sources":["../../src/components/UnitInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport type { UnitOption } from '../types'\n\ninterface Props {\n modelValue?: number\n unit?: string\n units: UnitOption[]\n precision?: number\n min?: number\n max?: number\n step?: number\n placeholder?: string\n disabled?: boolean\n error?: boolean\n size?: 'sm' | 'md' | 'lg'\n convertOnUnitChange?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n precision: undefined,\n step: undefined,\n placeholder: 'Enter value',\n disabled: false,\n error: false,\n size: 'md',\n convertOnUnitChange: false,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: number | undefined]\n 'update:unit': [unit: string]\n 'change': [data: { value: number | undefined; unit: string }]\n}>()\n\nconst conversionHint = ref<string | null>(null)\n\nconst currentUnit = computed(() => props.unit || (props.units.length > 0 ? props.units[0].value : ''))\n\n// Group units by their group property\nconst hasGroups = computed(() => props.units.some(u => u.group))\n\nconst groupedUnits = computed(() => {\n if (!hasGroups.value) return null\n const groups = new Map<string, UnitOption[]>()\n const ungrouped: UnitOption[] = []\n for (const u of props.units) {\n if (u.group) {\n if (!groups.has(u.group)) groups.set(u.group, [])\n groups.get(u.group)!.push(u)\n } else {\n ungrouped.push(u)\n }\n }\n return { groups, ungrouped }\n})\n\nfunction findUnit(value: string): UnitOption | undefined {\n return props.units.find(u => u.value === value)\n}\n\nfunction roundToPrecision(value: number): number {\n if (props.precision === undefined) return value\n const factor = Math.pow(10, props.precision)\n return Math.round(value * factor) / factor\n}\n\nfunction clamp(value: number): number {\n let result = value\n if (props.min !== undefined && result < props.min) result = props.min\n if (props.max !== undefined && result > props.max) result = props.max\n return result\n}\n\nfunction handleValueInput(event: Event) {\n const target = event.target as HTMLInputElement\n const value = target.value === '' ? undefined : Number(target.value)\n\n conversionHint.value = null\n\n if (value === undefined || isNaN(value)) {\n emit('update:modelValue', undefined)\n emit('change', { value: undefined, unit: currentUnit.value })\n return\n }\n\n const clamped = clamp(value)\n emit('update:modelValue', clamped)\n emit('change', { value: clamped, unit: currentUnit.value })\n}\n\nfunction handleUnitChange(event: Event) {\n const target = event.target as HTMLSelectElement\n const newUnitValue = target.value\n const oldUnitValue = currentUnit.value\n\n let newValue = props.modelValue\n\n if (props.convertOnUnitChange && newValue !== undefined) {\n const oldUnit = findUnit(oldUnitValue)\n const newUnit = findUnit(newUnitValue)\n\n if (oldUnit?.factor !== undefined && newUnit?.factor !== undefined && newUnit.factor !== 0) {\n const converted = newValue * (oldUnit.factor / newUnit.factor)\n newValue = roundToPrecision(converted)\n newValue = clamp(newValue)\n conversionHint.value = `Converted from ${oldUnit.label} to ${newUnit.label}`\n emit('update:modelValue', newValue)\n }\n }\n\n emit('update:unit', newUnitValue)\n emit('change', { value: newValue, unit: newUnitValue })\n}\n\n// Clear conversion hint after a delay\nwatch(conversionHint, (hint) => {\n if (hint) {\n setTimeout(() => {\n conversionHint.value = null\n }, 3000)\n }\n})\n</script>\n\n<template>\n <div\n :class=\"[\n 'mld-unit-input',\n error ? 'mld-unit-input--error' : '',\n disabled ? 'mld-unit-input--disabled' : '',\n ]\"\n >\n <div class=\"mld-unit-input__controls\">\n <input\n type=\"number\"\n :value=\"modelValue\"\n :min=\"min\"\n :max=\"max\"\n :step=\"step\"\n :disabled=\"disabled\"\n :placeholder=\"placeholder\"\n :class=\"[\n 'mld-unit-input__value',\n `mld-unit-input__value--${size}`,\n disabled ? 'mld-unit-input__value--disabled' : '',\n ]\"\n aria-label=\"Value\"\n @input=\"handleValueInput\"\n />\n\n <div class=\"mld-unit-input__unit\">\n <select\n :value=\"currentUnit\"\n :disabled=\"disabled\"\n :class=\"[\n 'mld-unit-input__unit-select',\n `mld-unit-input__unit-select--${size}`,\n ]\"\n aria-label=\"Unit\"\n @change=\"handleUnitChange\"\n >\n <template v-if=\"groupedUnits\">\n <template v-if=\"groupedUnits.ungrouped.length > 0\">\n <option\n v-for=\"u in groupedUnits.ungrouped\"\n :key=\"u.value\"\n :value=\"u.value\"\n >\n {{ u.label }}\n </option>\n </template>\n <optgroup\n v-for=\"[groupLabel, groupUnits] in groupedUnits.groups\"\n :key=\"groupLabel\"\n :label=\"groupLabel\"\n class=\"mld-unit-input__unit-group\"\n >\n <option\n v-for=\"u in groupUnits\"\n :key=\"u.value\"\n :value=\"u.value\"\n >\n {{ u.label }}\n </option>\n </optgroup>\n </template>\n <template v-else>\n <option\n v-for=\"u in units\"\n :key=\"u.value\"\n :value=\"u.value\"\n >\n {{ u.label }}\n </option>\n </template>\n </select>\n </div>\n </div>\n\n <div\n v-if=\"conversionHint\"\n class=\"mld-unit-input__conversion-hint\"\n >\n {{ conversionHint }}\n </div>\n </div>\n</template>\n\n<style>\n@import '../styles/components/unit-input.css';\n</style>\n"],"names":["_createElementBlock","_normalizeClass","_createElementVNode","_Fragment","_openBlock","_renderList","_toDisplayString"],"mappings":"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"}
package/dist/styles.css CHANGED
@@ -1553,6 +1553,8 @@ html.dark .focus\:ring-offset-2:focus {
1553
1553
  border-radius: 0.5rem;
1554
1554
  font-weight: 500;
1555
1555
  transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease;
1556
+ line-height: 1.25;
1557
+ white-space: nowrap;
1556
1558
  cursor: pointer;
1557
1559
  border: none;
1558
1560
  }
@@ -9061,6 +9063,11 @@ html.dark .mld-dataframe__loading {
9061
9063
  letter-spacing: 0.025em;
9062
9064
  color: var(--text-muted);
9063
9065
  }
9066
+ .mld-rack-editor__toolbar-section {
9067
+ display: flex;
9068
+ align-items: center;
9069
+ gap: 0.5rem;
9070
+ }
9064
9071
  .mld-rack-editor__toolbar-divider {
9065
9072
  width: 1px;
9066
9073
  height: 1.5rem;
@@ -11122,6 +11129,9 @@ html.dark .mld-settings-modal__option-btn--active {
11122
11129
  .mld-datetime-picker__footer-btn:hover {
11123
11130
  opacity: 0.8;
11124
11131
  }
11132
+ .mld-datetime-picker__footer-btn + .mld-datetime-picker__footer-btn {
11133
+ margin-left: 0.75rem;
11134
+ }
11125
11135
  .mld-datetime-picker__footer-btn--muted {
11126
11136
  color: var(--text-muted);
11127
11137
  }
@@ -11910,6 +11920,8 @@ html.dark .mld-settings-modal__option-btn--active {
11910
11920
  border-radius: 0.5rem;
11911
11921
  font-weight: 500;
11912
11922
  transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease;
11923
+ line-height: 1.25;
11924
+ white-space: nowrap;
11913
11925
  cursor: pointer;
11914
11926
  border: none;
11915
11927
  }
@@ -17580,6 +17592,11 @@ to {
17580
17592
  letter-spacing: 0.025em;
17581
17593
  color: var(--text-muted);
17582
17594
  }
17595
+ .mld-rack-editor__toolbar-section {
17596
+ display: flex;
17597
+ align-items: center;
17598
+ gap: 0.5rem;
17599
+ }
17583
17600
  .mld-rack-editor__toolbar-divider {
17584
17601
  width: 1px;
17585
17602
  height: 1.5rem;
@@ -22462,6 +22479,9 @@ to { transform: rotate(360deg);
22462
22479
  .mld-datetime-picker__footer-btn:hover {
22463
22480
  opacity: 0.8;
22464
22481
  }
22482
+ .mld-datetime-picker__footer-btn + .mld-datetime-picker__footer-btn {
22483
+ margin-left: 0.75rem;
22484
+ }
22465
22485
  .mld-datetime-picker__footer-btn--muted {
22466
22486
  color: var(--text-muted);
22467
22487
  }
@@ -1,3 +1,3 @@
1
- export type { ContainerDirection, ButtonVariant, ButtonSize, InputType, ModalSize, AlertType, Toast, TabItem, SelectOption, RadioOption, FormFieldProps, SidebarToolSection, CollapsibleState, TopBarVariant, TopBarPage, TopBarTab, TopBarTabOption, TopBarSettingsConfig, WellPlateFormat, WellState, WellPlateSelectionMode, WellPlateSize, WellShape, Well, HeatmapColorScale, HeatmapConfig, SlotPosition, WellExtendedData, WellEditData, WellEditField, WellLegendItem, PlateCondition, ColumnCondition, RowCondition, Rack, SampleType, PlateMap, PlateMapEditorState, ProtocolStepType, ProtocolStepStatus, ProtocolStep, SampleGroup, GroupItem, FileUploaderMode, SegmentedOption, SegmentedControlVariant, SegmentedControlSize, MultiSelectOption, MultiSelectSize, PillVariant, PillSize, CalendarSelectionMode, CalendarMarker, CalendarDayContext, SortDirection, SortState, DataFrameColumn, PaginationState, SpinnerSize, SpinnerVariant, DividerSpacing, StatusType, ProgressVariant, ProgressSize, AvatarSize, EmptyStateColor, EmptyStateSize, BreadcrumbItem, TooltipPosition, ConfirmVariant, SettingsTab, NumberNotation, UnitOption, WizardStep, WizardStepState, AuditEntryType, AuditEntry, BatchItemStatus, BatchItem, BatchSummary, TimePickerFormat, TimeRange, ScheduleView, ScheduleEventStatus, ScheduleEvent, ScheduleBlockedSlot, ScheduleSlotContext, ScheduleEventCreateContext, ScheduleEventUpdateContext, ResourceStatus, ResourceSpec, } from './components';
1
+ export type { ContainerDirection, ButtonVariant, ButtonSize, InputType, ModalSize, AlertType, Toast, TabItem, SelectOption, RadioOption, FormFieldProps, SidebarToolSection, CollapsibleState, TopBarVariant, TopBarPage, TopBarTab, TopBarTabOption, TopBarSettingsConfig, WellPlateFormat, WellState, WellPlateSelectionMode, WellPlateSize, WellShape, Well, HeatmapColorScale, HeatmapConfig, SlotPosition, WellExtendedData, WellEditData, WellEditField, WellLegendItem, PlateCondition, ColumnCondition, RowCondition, Rack, SampleType, PlateMap, PlateMapEditorState, ProtocolStepType, ProtocolStepStatus, ProtocolStep, SampleGroup, GroupItem, FileUploaderMode, SegmentedOption, SegmentedControlVariant, SegmentedControlSize, MultiSelectOption, MultiSelectSize, PillVariant, PillSize, CalendarSelectionMode, CalendarMarker, CalendarDayContext, SortDirection, SortState, DataFrameColumn, PaginationState, SpinnerSize, SpinnerVariant, DividerSpacing, StatusType, ProgressVariant, ProgressSize, AvatarSize, EmptyStateColor, EmptyStateSize, BreadcrumbItem, TooltipPosition, ConfirmVariant, SettingsTab, NumberNotation, UnitOption, WizardStep, WizardStepState, AuditEntryType, AuditEntry, BatchItemStatus, BatchItem, BatchSummary, TimePickerFormat, TimeRange, ScheduleView, ScheduleEventStatus, ScheduleEvent, ScheduleBlockedSlot, ScheduleSlotContext, ScheduleEventCreateContext, ScheduleEventUpdateContext, ResourceStatus, ResourceSpec, MoleculeData, StorageCondition, ReagentColumn, Reagent, TreeNodeType, BadgeVariant, TreeNode, } from './components';
2
2
  export type { AuthConfig, UserInfo, LoginResponse, TokenVerifyResponse, RegisterRequest, UpdateProfileRequest, CredentialInfo, } from './auth';
3
3
  export type { PluginInfo, PluginNavItem, PluginSettings, PluginSettingField, PlatformContext, PlatformContextOptions, PlatformEventType, PlatformEvent, ThemeMode, ColorPalette, TableDensity, } from './platform';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@morscherlab/mld-sdk",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "MLD Platform SDK - Vue 3 components, composables, and types for plugin development",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,17 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { computed, ref } from 'vue'
3
-
4
- type AuditEntryType = 'create' | 'update' | 'delete' | 'system'
5
-
6
- interface AuditEntry {
7
- id: string
8
- type: AuditEntryType
9
- action: string
10
- detail?: string
11
- user?: string
12
- timestamp: Date | string
13
- metadata?: Record<string, unknown>
14
- }
3
+ import type { AuditEntryType, AuditEntry } from '../types'
15
4
 
16
5
  interface Props {
17
6
  entries: AuditEntry[]
@@ -1,25 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { computed, ref, watch, nextTick } from 'vue'
3
-
4
- type BatchItemStatus = 'pending' | 'processing' | 'completed' | 'error' | 'skipped'
5
-
6
- interface BatchItem {
7
- id: string
8
- label: string
9
- status: BatchItemStatus
10
- progress?: number
11
- message?: string
12
- }
13
-
14
- interface BatchSummary {
15
- total: number
16
- completed: number
17
- processing: number
18
- error: number
19
- pending: number
20
- skipped: number
21
- percent: number
22
- }
3
+ import type { BatchItem, BatchSummary } from '../types'
23
4
 
24
5
  interface Props {
25
6
  items: BatchItem[]
@@ -1,9 +1,5 @@
1
1
  <script setup lang="ts">
2
- interface BreadcrumbItem {
3
- label: string
4
- to?: string
5
- href?: string
6
- }
2
+ import type { BreadcrumbItem } from '../types'
7
3
 
8
4
  interface Props {
9
5
  items: BreadcrumbItem[]
@@ -370,7 +370,7 @@ onUnmounted(() => {
370
370
  <div class="mld-datetime-picker__footer">
371
371
  <div>
372
372
  <button type="button" class="mld-datetime-picker__footer-btn" @click="goToToday">Today</button>
373
- <button type="button" class="mld-datetime-picker__footer-btn" style="margin-left: 0.75rem" @click="goToNow">Now</button>
373
+ <button type="button" class="mld-datetime-picker__footer-btn" @click="goToNow">Now</button>
374
374
  </div>
375
375
  <button
376
376
  v-if="clearable && modelValue"
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import MoleculeInput from './MoleculeInput.vue'
3
- import type { MoleculeData } from './MoleculeInput.vue'
3
+ import type { MoleculeData } from '../types'
4
4
 
5
5
  function initState() {
6
6
  return {
@@ -1,10 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue'
3
-
4
- export interface MoleculeData {
5
- smiles: string
6
- molfile: string
7
- }
3
+ import type { MoleculeData } from '../types'
8
4
 
9
5
  interface Props {
10
6
  modelValue?: MoleculeData
@@ -287,7 +287,7 @@ const activeRackWells = computed(() => editor.activeRack.value?.wells ?? {})
287
287
  <div v-if="editor.activeRack.value && !readonly" class="mld-rack-editor__toolbar">
288
288
  <div class="mld-rack-editor__toolbar-group">
289
289
  <!-- Format selector -->
290
- <div style="display: flex; align-items: center; gap: 0.5rem;">
290
+ <div class="mld-rack-editor__toolbar-section">
291
291
  <span class="mld-rack-editor__toolbar-label">Plate</span>
292
292
  <div class="mld-rack-editor__format-btns">
293
293
  <button
@@ -307,7 +307,7 @@ const activeRackWells = computed(() => editor.activeRack.value?.wells ?? {})
307
307
  <div class="mld-rack-editor__toolbar-divider" />
308
308
 
309
309
  <!-- Slot selector -->
310
- <div style="display: flex; align-items: center; gap: 0.5rem;">
310
+ <div class="mld-rack-editor__toolbar-section">
311
311
  <span class="mld-rack-editor__toolbar-label">Slot</span>
312
312
  <div class="mld-rack-editor__slot-btns">
313
313
  <button
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import ReagentList from './ReagentList.vue'
3
- import type { Reagent } from './ReagentList.vue'
3
+ import type { Reagent } from '../types'
4
4
 
5
5
  const today = new Date()
6
6
  const pastDate = new Date(today)
@@ -1,31 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { ref, computed } from 'vue'
3
-
4
- export type StorageCondition = 'RT' | '4C' | '-20C' | '-80C'
5
-
6
- export type ReagentColumn =
7
- | 'name'
8
- | 'catalog'
9
- | 'lot'
10
- | 'expiry'
11
- | 'storage'
12
- | 'location'
13
- | 'stock'
14
- | 'supplier'
15
-
16
- export interface Reagent {
17
- id: string
18
- name: string
19
- catalogNumber?: string
20
- lotNumber?: string
21
- expiryDate?: Date | string
22
- storageCondition?: StorageCondition
23
- location?: string
24
- stockLevel?: number
25
- stockUnit?: string
26
- supplier?: string
27
- url?: string
28
- }
3
+ import type { ReagentColumn, Reagent } from '../types'
29
4
 
30
5
  interface Props {
31
6
  modelValue?: Reagent[]
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import SampleHierarchyTree from './SampleHierarchyTree.vue'
3
- import type { TreeNode } from './SampleHierarchyTree.vue'
3
+ import type { TreeNode } from '../types'
4
4
 
5
5
  const mockNodes: TreeNode[] = [
6
6
  {
@@ -1,31 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import { ref, watch, type VNode } from 'vue'
3
3
  import { h, Transition } from 'vue'
4
-
5
- export type TreeNodeType =
6
- | 'study'
7
- | 'experiment'
8
- | 'plate'
9
- | 'sample'
10
- | 'cell_line'
11
- | 'passage'
12
- | 'clone'
13
- | 'treatment'
14
- | 'folder'
15
- | 'custom'
16
-
17
- export type BadgeVariant = 'default' | 'success' | 'warning' | 'error'
18
-
19
- export interface TreeNode {
20
- id: string
21
- label: string
22
- type?: TreeNodeType
23
- icon?: string
24
- children?: TreeNode[]
25
- metadata?: Record<string, unknown>
26
- badge?: string | number
27
- badgeVariant?: BadgeVariant
28
- }
4
+ import type { TreeNodeType, BadgeVariant, TreeNode } from '../types'
29
5
 
30
6
  interface Props {
31
7
  nodes: TreeNode[]
@@ -360,7 +360,7 @@ onUnmounted(() => {
360
360
  </script>
361
361
 
362
362
  <template>
363
- <div class="mld-schedule" :style="{ '--slot-height': `${SLOT_HEIGHT}px` } as any">
363
+ <div class="mld-schedule" :style="({ '--slot-height': `${SLOT_HEIGHT}px` } as Record<string, string>)">
364
364
  <!-- Header -->
365
365
  <div v-if="showNavigation || showViewToggle" class="mld-schedule__header">
366
366
  <div v-if="showNavigation" class="mld-schedule__nav">
@@ -1,7 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import ScientificNumber from './ScientificNumber.vue'
3
-
4
- type NumberNotation = 'auto' | 'scientific' | 'engineering' | 'compact'
3
+ import type { NumberNotation } from '../types'
5
4
  const notations: NumberNotation[] = ['auto', 'scientific', 'engineering', 'compact']
6
5
  </script>
7
6
 
@@ -1,7 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { computed, ref } from 'vue'
3
-
4
- type NumberNotation = 'auto' | 'scientific' | 'engineering' | 'compact'
3
+ import type { NumberNotation } from '../types'
5
4
 
6
5
  interface Props {
7
6
  value: number
@@ -2,13 +2,7 @@
2
2
  import { ref, computed } from 'vue'
3
3
  import BaseModal from './BaseModal.vue'
4
4
  import { useSettingsStore, colorPalettes } from '../stores/settings'
5
- import type { ThemeMode, ColorPalette, TableDensity } from '../types'
6
-
7
- export interface SettingsTab {
8
- id: string
9
- label: string
10
- icon?: string
11
- }
5
+ import type { ThemeMode, ColorPalette, TableDensity, SettingsTab } from '../types'
12
6
 
13
7
  interface Props {
14
8
  modelValue: boolean
@@ -1,15 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { ref, computed } from 'vue'
3
-
4
- interface WizardStep {
5
- id: string
6
- label: string
7
- description?: string
8
- icon?: string
9
- optional?: boolean
10
- }
11
-
12
- type WizardStepState = 'pending' | 'active' | 'completed' | 'disabled'
3
+ import type { WizardStep, WizardStepState } from '../types'
13
4
 
14
5
  interface Props {
15
6
  steps: WizardStep[]
@@ -1,12 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { computed, ref, watch } from 'vue'
3
-
4
- interface UnitOption {
5
- value: string
6
- label: string
7
- factor?: number
8
- group?: string
9
- }
3
+ import type { UnitOption } from '../types'
10
4
 
11
5
  interface Props {
12
6
  modelValue?: number
@@ -8,6 +8,8 @@
8
8
  border-radius: 0.5rem;
9
9
  font-weight: 500;
10
10
  transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease;
11
+ line-height: 1.25;
12
+ white-space: nowrap;
11
13
  cursor: pointer;
12
14
  border: none;
13
15
  }
@@ -195,6 +195,10 @@
195
195
  opacity: 0.8;
196
196
  }
197
197
 
198
+ .mld-datetime-picker__footer-btn + .mld-datetime-picker__footer-btn {
199
+ margin-left: 0.75rem;
200
+ }
201
+
198
202
  .mld-datetime-picker__footer-btn--muted {
199
203
  color: var(--text-muted);
200
204
  }
@@ -170,6 +170,12 @@
170
170
  color: var(--text-muted);
171
171
  }
172
172
 
173
+ .mld-rack-editor__toolbar-section {
174
+ display: flex;
175
+ align-items: center;
176
+ gap: 0.5rem;
177
+ }
178
+
173
179
  .mld-rack-editor__toolbar-divider {
174
180
  width: 1px;
175
181
  height: 1.5rem;
@@ -120,6 +120,16 @@ export type {
120
120
  // Resource types
121
121
  ResourceStatus,
122
122
  ResourceSpec,
123
+ // MoleculeInput types
124
+ MoleculeData,
125
+ // ReagentList types
126
+ StorageCondition,
127
+ ReagentColumn,
128
+ Reagent,
129
+ // SampleHierarchyTree types
130
+ TreeNodeType,
131
+ BadgeVariant,
132
+ TreeNode,
123
133
  } from './components'
124
134
 
125
135
  // Auth types