@morscherlab/mint-sdk 1.4.0-beta.20 → 1.4.0-beta.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{AlertBox-CzLg0UaL.js → AlertBox-DwgNTEqf.js} +3 -3
- package/dist/{AlertBox-CzLg0UaL.js.map → AlertBox-DwgNTEqf.js.map} +1 -1
- package/dist/{AppSidebar-6oTT-gPO.js → AppSidebar-CZZaxni0.js} +7 -7
- package/dist/{AppSidebar-6oTT-gPO.js.map → AppSidebar-CZZaxni0.js.map} +1 -1
- package/dist/{ConfirmDialog-CSls2Nuv.js → ConfirmDialog-CjWoxAD1.js} +2 -2
- package/dist/{ConfirmDialog-CSls2Nuv.js.map → ConfirmDialog-CjWoxAD1.js.map} +1 -1
- package/dist/{ExperimentPopover-9l4QZlvQ.js → ExperimentPopover-DujiuQIO.js} +5 -5
- package/dist/{ExperimentPopover-9l4QZlvQ.js.map → ExperimentPopover-DujiuQIO.js.map} +1 -1
- package/dist/{ExperimentSelectorModal-pR5fK3pA.js → ExperimentSelectorModal-B4j4eUOJ.js} +5 -5
- package/dist/{ExperimentSelectorModal-pR5fK3pA.js.map → ExperimentSelectorModal-B4j4eUOJ.js.map} +1 -1
- package/dist/{SegmentedControl-CJ7EAmOq.js → SegmentedControl-DyUPH3I5.js} +2 -2
- package/dist/{SegmentedControl-CJ7EAmOq.js.map → SegmentedControl-DyUPH3I5.js.map} +1 -1
- package/dist/{SettingsModal-Dyitgzfp.js → SettingsModal-D2MOOtuO.js} +7 -7
- package/dist/{SettingsModal-Dyitgzfp.js.map → SettingsModal-D2MOOtuO.js.map} +1 -1
- package/dist/__tests__/components/FloatingPanelsInModal.test.d.ts +1 -0
- package/dist/__tests__/composables/useFloatingPanel.test.d.ts +1 -0
- package/dist/components/SmartGroupFieldRecipe.vue.d.ts +2 -2
- package/dist/components/internal/AutoGroupModalInternal.vue.d.ts +2 -2
- package/dist/composables/useFileImport.d.ts +7 -0
- package/dist/composables/useFloatingPanel.d.ts +29 -0
- package/dist/{controlSchemaModel-DCUOx8ll.js → controlSchemaModel-Bsg0t5Ab.js} +2 -2
- package/dist/{controlSchemaModel-DCUOx8ll.js.map → controlSchemaModel-Bsg0t5Ab.js.map} +1 -1
- package/dist/{data-DBnmeBZX.js → data-Boeh4uPI.js} +12 -11
- package/dist/{data-DBnmeBZX.js.map → data-Boeh4uPI.js.map} +1 -1
- package/dist/data.d.ts +1 -1
- package/dist/data.js +9 -9
- package/dist/{experimentStatus-BFrKpHAH.js → experimentStatus-DCn2QKG7.js} +2 -2
- package/dist/{experimentStatus-BFrKpHAH.js.map → experimentStatus-DCn2QKG7.js.map} +1 -1
- package/dist/index.js +18 -18
- package/dist/{install-qjELyNwc.js → install-BEHp7Mo-.js} +15 -15
- package/dist/{install-qjELyNwc.js.map → install-BEHp7Mo-.js.map} +1 -1
- package/dist/install.js +1 -1
- package/dist/{lab-UyTbokQC.js → lab-D61eaX6f.js} +10 -10
- package/dist/{lab-UyTbokQC.js.map → lab-D61eaX6f.js.map} +1 -1
- package/dist/lab.js +4 -4
- package/dist/{records-CR_pYzIP.js → records-D4aQXyZu.js} +132 -72
- package/dist/records-D4aQXyZu.js.map +1 -0
- package/dist/{runtime-CoHhBP10.js → runtime-q-R0CNLh.js} +9 -9
- package/dist/{runtime-CoHhBP10.js.map → runtime-q-R0CNLh.js.map} +1 -1
- package/dist/runtime.js +6 -6
- package/dist/{shell-BDuZf2zb.js → shell-6CGFvUUw.js} +5 -5
- package/dist/{shell-BDuZf2zb.js.map → shell-6CGFvUUw.js.map} +1 -1
- package/dist/shell.js +5 -5
- package/dist/styles.css +36 -33
- package/dist/{useDropdownState-Bb2N4m40.js → useDropdownState-uFIz6Yv8.js} +2 -2
- package/dist/useDropdownState-uFIz6Yv8.js.map +1 -0
- package/dist/{useExperimentSamples-Dno1fFMq.js → useExperimentSamples-QEFoq4tf.js} +47 -5
- package/dist/useExperimentSamples-QEFoq4tf.js.map +1 -0
- package/dist/{useListReorder-CQ9OCScc.js → useListReorder-DsuzwWGS.js} +47 -97
- package/dist/useListReorder-DsuzwWGS.js.map +1 -0
- package/dist/{useRackEditor-wL3kPrRT.js → useRackEditor-KpZ4iJ6o.js} +20 -30
- package/dist/useRackEditor-KpZ4iJ6o.js.map +1 -0
- package/dist/{useRealtime-C3whhVvb.js → useRealtime-B58Lo-Tm.js} +3 -3
- package/dist/{useRealtime-C3whhVvb.js.map → useRealtime-B58Lo-Tm.js.map} +1 -1
- package/dist/{useRequest-CDkrXNU7.js → useRequest-BuDmW8Jc.js} +7 -36
- package/dist/useRequest-BuDmW8Jc.js.map +1 -0
- package/package.json +3 -2
- package/src/__tests__/components/ActionMenu.test.ts +2 -2
- package/src/__tests__/components/BaseModal.test.ts +13 -0
- package/src/__tests__/components/FloatingPanelsInModal.test.ts +94 -0
- package/src/__tests__/composables/useFileImport.test.ts +36 -0
- package/src/__tests__/composables/useFloatingPanel.test.ts +68 -0
- package/src/__tests__/fixtures/table-import/cells.xlsx +0 -0
- package/src/__tests__/fixtures/table-import/samples.xlsx +0 -0
- package/src/components/ActionMenu.vue +6 -37
- package/src/components/BaseModal.vue +2 -1
- package/src/components/Tooltip.vue +9 -32
- package/src/components/internal/DatePickerDateInternal.vue +7 -45
- package/src/components/internal/DatePickerDateTimeInternal.vue +7 -1
- package/src/components/internal/DatePickerTimeInternal.vue +8 -1
- package/src/components/internal/NumberUnitInputInternal.vue +4 -18
- package/src/components/internal/SelectMultipleInternal.vue +6 -1
- package/src/components/internal/SelectSearchableInternal.vue +6 -1
- package/src/components/internal/WellEditPopupInternal.vue +11 -22
- package/src/composables/useFileImport.ts +51 -1
- package/src/composables/useFloatingPanel.ts +107 -0
- package/src/data.ts +1 -0
- package/src/styles/components/action-menu.css +1 -1
- package/src/styles/components/app-layout.css +3 -1
- package/src/styles/components/date-picker.css +4 -2
- package/src/styles/components/datetime-picker.css +4 -4
- package/src/styles/components/jobs-status-tray.css +3 -3
- package/src/styles/components/modal.css +1 -1
- package/src/styles/components/onboarding.css +2 -2
- package/src/styles/components/searchable-select.css +3 -7
- package/src/styles/components/time-picker.css +3 -6
- package/src/styles/components/toast.css +1 -1
- package/src/styles/components/tooltip.css +2 -2
- package/src/styles/components/unit-input.css +1 -1
- package/src/styles/components/well-edit-popup.css +2 -2
- package/src/styles/variables.css +6 -0
- package/dist/records-CR_pYzIP.js.map +0 -1
- package/dist/useDropdownState-Bb2N4m40.js.map +0 -1
- package/dist/useExperimentSamples-Dno1fFMq.js.map +0 -1
- package/dist/useListReorder-CQ9OCScc.js.map +0 -1
- package/dist/useRackEditor-wL3kPrRT.js.map +0 -1
- package/dist/useRequest-CDkrXNU7.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useExperimentSamples-QEFoq4tf.js","names":[],"sources":["../src/composables/experimentDesignData.ts","../src/composables/useExperimentData.ts","../src/composables/useFileImport.ts","../src/composables/useExperimentSamples.ts"],"sourcesContent":["import type { SelectOption } from '../types'\nimport { isRecord } from '../utils/records'\n\nexport interface ExperimentDesignDataResponse {\n experiment_id?: number\n plugin_id?: string\n data?: Record<string, unknown>\n schema_version?: string\n updated_at?: string | null\n}\n\nexport interface ExtractExperimentSamplesOptions {\n includeControls?: boolean\n}\n\n\nfunction isPlatformDesignDataResponse(value: Record<string, unknown>): boolean {\n return (\n 'data' in value\n && (\n 'experiment_id' in value\n || 'plugin_id' in value\n || 'schema_version' in value\n || 'updated_at' in value\n )\n )\n}\n\n/** Return the plugin-defined design_data payload from common platform and plugin response shapes. */\nexport function unwrapExperimentDesignData(\n rawData: Record<string, unknown> | null | undefined,\n): Record<string, unknown> | null {\n if (!rawData) return null\n\n if (isRecord(rawData.data) && isPlatformDesignDataResponse(rawData)) {\n return rawData.data\n }\n\n if (isRecord(rawData.design_data)) {\n return rawData.design_data\n }\n\n if (isRecord(rawData.designData)) {\n return rawData.designData\n }\n\n return rawData\n}\n\nfunction shouldIncludeSample(record: Record<string, unknown>, options: ExtractExperimentSamplesOptions): boolean {\n if (options.includeControls) return true\n const rawType = record.sample_type ?? record.sampleType ?? record.type ?? record.well_type ?? record.wellType\n const type = typeof rawType === 'string' ? rawType.toLowerCase() : ''\n return !['blank', 'qc'].includes(type)\n}\n\nfunction readSampleValue(record: Record<string, unknown>): string | null {\n const candidates = [\n record.sample_name,\n record.sampleName,\n record.sample_id,\n record.sampleId,\n record.name,\n record.id,\n record.label,\n ]\n\n for (const candidate of candidates) {\n if (typeof candidate === 'string' && candidate.trim()) {\n return candidate\n }\n if (typeof candidate === 'number' && Number.isFinite(candidate)) {\n return String(candidate)\n }\n }\n\n return null\n}\n\nfunction readSampleLabel(record: Record<string, unknown>, fallback: string): string {\n const label = record.name ?? record.label ?? record.sample_name ?? record.sampleName\n return typeof label === 'string' && label.trim() ? label : fallback\n}\n\nfunction readSampleDescription(record: Record<string, unknown>): string | undefined {\n const parts = [\n record.group,\n record.batch,\n record.batch_id,\n record.batchId,\n record.plate_id,\n record.plateId,\n record.well_id,\n record.wellId,\n ].filter((value): value is string | number =>\n (typeof value === 'string' && value.trim().length > 0)\n || typeof value === 'number',\n )\n\n return parts.length > 0 ? parts.map(String).join(' / ') : undefined\n}\n\nfunction addSampleRecord(\n options: SelectOption<string>[],\n seen: Set<string>,\n value: unknown,\n extractOptions: ExtractExperimentSamplesOptions,\n): void {\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (trimmed && !seen.has(trimmed)) {\n seen.add(trimmed)\n options.push({ value: trimmed, label: trimmed })\n }\n return\n }\n\n if (!isRecord(value) || !shouldIncludeSample(value, extractOptions)) return\n\n const sampleValue = readSampleValue(value)\n if (!sampleValue || seen.has(sampleValue)) return\n\n seen.add(sampleValue)\n options.push({\n value: sampleValue,\n label: readSampleLabel(value, sampleValue),\n description: readSampleDescription(value),\n })\n}\n\nfunction addSampleArray(\n options: SelectOption<string>[],\n seen: Set<string>,\n value: unknown,\n extractOptions: ExtractExperimentSamplesOptions,\n): void {\n if (!Array.isArray(value)) return\n for (const sample of value) {\n addSampleRecord(options, seen, sample, extractOptions)\n }\n}\n\n/** Extract selectable sample options from raw or wrapped experiment design_data. */\nexport function extractSampleOptionsFromDesignData(\n rawData: Record<string, unknown> | null | undefined,\n options: ExtractExperimentSamplesOptions = {},\n): SelectOption<string>[] {\n const designData = unwrapExperimentDesignData(rawData)\n if (!designData) return []\n\n const sampleOptions: SelectOption<string>[] = []\n const seen = new Set<string>()\n\n addSampleArray(sampleOptions, seen, designData.samples, options)\n\n if (isRecord(designData.templates)) {\n for (const template of Object.values(designData.templates)) {\n if (!isRecord(template)) continue\n const templateData = isRecord(template.data) ? template.data : template\n addSampleArray(sampleOptions, seen, templateData.samples, options)\n }\n }\n\n if (Array.isArray(designData.plates)) {\n for (const plate of designData.plates) {\n if (!isRecord(plate)) continue\n addSampleArray(sampleOptions, seen, plate.samples, options)\n }\n }\n\n return sampleOptions\n}\n\n/** Extract SampleSelector-compatible string values from raw or wrapped experiment design_data. */\nexport function extractSampleNamesFromDesignData(\n rawData: Record<string, unknown> | null | undefined,\n options: ExtractExperimentSamplesOptions = {},\n): string[] {\n return extractSampleOptionsFromDesignData(rawData, options).map(sample => sample.value)\n}\n","import { shallowRef, computed, type Ref, type ComputedRef } from 'vue'\nimport { useApi, type UseApiReturn } from './useApi'\nimport { useRequest } from './useRequest'\nimport {\n extractSampleNamesFromDesignData,\n extractSampleOptionsFromDesignData,\n unwrapExperimentDesignData,\n} from './experimentDesignData'\nimport type { TreeNode, SummaryData, SelectOption } from '../types'\n\nexport interface UseExperimentDataOptions {\n apiBaseUrl?: string\n immediate?: boolean\n}\n\nexport interface UseExperimentDataReturn {\n /** Raw experiment data response from `/experiments/{id}/data`, or null. */\n data: Ref<Record<string, unknown> | null>\n /** Plugin-defined design_data payload unwrapped from platform response shapes, or null. */\n designData: ComputedRef<Record<string, unknown> | null>\n /** Sample values extracted from design_data for SampleSelector-style components. */\n sampleNames: ComputedRef<string[]>\n /** Sample options extracted from design_data for select/dropdown components. */\n sampleOptions: ComputedRef<SelectOption<string>[]>\n /** Hierarchy tree rows normalised from `tree_data` or `treeData`. */\n treeData: ComputedRef<TreeNode[]>\n /** Table rows normalised from `table_data` or `tableData`. */\n tableData: ComputedRef<Record<string, unknown>[]>\n /** Summary payload normalised from `summary_data` or `summaryData`, or null. */\n summaryData: ComputedRef<SummaryData | null>\n /** Whether experiment data is currently loading. */\n isLoading: Ref<boolean>\n /** Error message from the last failed fetch, or null. */\n error: Ref<string | null>\n /** Timestamp of the last successful experiment data fetch, or null. */\n lastLoadedAt: Ref<Date | null>\n /** Fetch experiment data for an experiment id. */\n fetch: (experimentId: number) => Promise<Record<string, unknown> | null>\n /** Refetch the most recently fetched experiment id. */\n refresh: () => Promise<void>\n /** Clear local experiment data and current fetch target. */\n clear: () => void\n}\n\n/** Fetches and normalises experiment output data (tree, table, summary) from the platform API. */\nexport function useExperimentData(\n options: UseExperimentDataOptions = {},\n): UseExperimentDataReturn {\n const data = shallowRef<Record<string, unknown> | null>(null)\n const request = useRequest('Failed to fetch experiment data')\n const isLoading = request.isLoading\n const error = request.error\n const lastLoadedAt = request.lastLoadedAt\n let lastExperimentId: number | null = null\n let api: UseApiReturn | null = null\n\n function getApi(): UseApiReturn {\n api ??= useApi({ baseUrl: options.apiBaseUrl })\n return api\n }\n\n const designData = computed<Record<string, unknown> | null>(() =>\n unwrapExperimentDesignData(data.value),\n )\n\n const sampleNames = computed<string[]>(() =>\n extractSampleNamesFromDesignData(designData.value),\n )\n\n const sampleOptions = computed<SelectOption<string>[]>(() =>\n extractSampleOptionsFromDesignData(designData.value),\n )\n\n const treeData = computed<TreeNode[]>(() => {\n if (!designData.value) return []\n const tree = designData.value.tree_data ?? designData.value.treeData\n return Array.isArray(tree) ? tree as TreeNode[] : []\n })\n\n const tableData = computed<Record<string, unknown>[]>(() => {\n if (!designData.value) return []\n const table = designData.value.table_data ?? designData.value.tableData\n return Array.isArray(table) ? table as Record<string, unknown>[] : []\n })\n\n const summaryData = computed<SummaryData | null>(() => {\n if (!designData.value) return null\n const summary = designData.value.summary_data ?? designData.value.summaryData\n if (summary && typeof summary === 'object' && 'metadata' in (summary as Record<string, unknown>)) {\n return summary as SummaryData\n }\n return null\n })\n\n async function fetchData(experimentId: number): Promise<Record<string, unknown> | null> {\n lastExperimentId = experimentId\n try {\n data.value = await request.run(\n () => getApi().get<Record<string, unknown>>(`/experiments/${experimentId}/data`),\n { kind: 'load', errorMessage: 'Failed to fetch experiment data' },\n )\n return data.value\n } catch {\n data.value = null\n return null\n }\n }\n\n async function refresh(): Promise<void> {\n if (lastExperimentId !== null) {\n await fetchData(lastExperimentId)\n }\n }\n\n function clear(): void {\n data.value = null\n lastExperimentId = null\n request.clearError()\n }\n\n return {\n data,\n designData,\n sampleNames,\n sampleOptions,\n treeData,\n tableData,\n summaryData,\n isLoading,\n error,\n lastLoadedAt,\n fetch: fetchData,\n refresh,\n clear,\n }\n}\n","import { ref, shallowRef, type Ref, type ShallowRef } from 'vue'\nimport type { SheetData } from 'read-excel-file/universal'\nimport { readErrorMessage } from '../utils/errors'\n\nexport interface DelimitedTable {\n columns: string[]\n rows: Record<string, string>[]\n rawRows: string[][]\n delimiter: string\n}\n\nexport interface ParseDelimitedTextOptions {\n delimiter?: string\n headers?: readonly string[]\n hasHeaderRow?: boolean\n trim?: boolean\n}\n\nexport interface FileImportValidationOptions {\n accept?: string | readonly string[]\n maxSizeBytes?: number\n}\n\nexport interface FileImportOptions<TResult = string> extends FileImportValidationOptions {\n encoding?: string\n parse?: (text: string, file: File) => TResult | Promise<TResult>\n}\n\nexport interface UseFileImportReturn<TResult> {\n loading: ShallowRef<boolean>\n error: Ref<string | null>\n fileName: Ref<string>\n result: Ref<TResult | null>\n importFile: (file: File) => Promise<TResult>\n clear: () => void\n}\n\n/** Stateful file reader for plugin import flows with shared validation and error handling. */\nexport function useFileImport<TResult = string>(\n options: FileImportOptions<TResult> = {},\n): UseFileImportReturn<TResult> {\n const loading = shallowRef(false)\n const error = ref<string | null>(null)\n const fileName = ref('')\n const result = ref<TResult | null>(null) as Ref<TResult | null>\n\n function clear(): void {\n loading.value = false\n error.value = null\n fileName.value = ''\n result.value = null\n }\n\n async function importFile(file: File): Promise<TResult> {\n loading.value = true\n error.value = null\n fileName.value = file.name\n\n try {\n validateImportFile(file, options)\n const text = await readFileAsText(file, options.encoding)\n const parsed = options.parse\n ? await options.parse(text, file)\n : text as TResult\n result.value = parsed\n return parsed\n } catch (err) {\n const message = readErrorMessage(err, 'Failed to import file.')\n error.value = message\n throw err\n } finally {\n loading.value = false\n }\n }\n\n return {\n loading,\n error,\n fileName,\n result,\n importFile,\n clear,\n }\n}\n\nexport function validateImportFile(file: File, options: FileImportValidationOptions = {}): void {\n if (options.maxSizeBytes !== undefined && file.size > options.maxSizeBytes) {\n throw new Error(`File is too large. Maximum size is ${formatBytes(options.maxSizeBytes)}.`)\n }\n\n const accept = normalizeAccept(options.accept)\n if (accept.length === 0) return\n\n const name = file.name.toLowerCase()\n const type = file.type.toLowerCase()\n const matches = accept.some((entry) => {\n if (entry.startsWith('.')) return name.endsWith(entry)\n if (entry.endsWith('/*')) return type.startsWith(entry.slice(0, -1))\n return type === entry\n })\n\n if (!matches) {\n throw new Error(`Unsupported file type. Expected ${accept.join(', ')}.`)\n }\n}\n\nexport function readFileAsText(file: File, encoding?: string): Promise<string> {\n if (typeof FileReader === 'undefined' && typeof file.text === 'function') {\n return file.text()\n }\n\n return new Promise((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = () => resolve(String(reader.result ?? ''))\n reader.onerror = () => reject(reader.error ?? new Error('Failed to read file.'))\n reader.readAsText(file, encoding)\n })\n}\n\n/**\n * Read a `.csv`, `.tsv` or `.xlsx` upload as comma-delimited CSV text.\n * A `.csv` file (or any other extension) comes back unchanged. An `.xlsx`\n * file gives its first sheet; each cell is its stored value, so number\n * formats such as leading zeros are not applied. Dates become ISO text.\n */\nexport async function readTableFileAsCsv(file: File): Promise<string> {\n const name = file.name.toLowerCase()\n if (name.endsWith('.xlsx')) return rowsToCsv(await readFirstSheet(file))\n const text = await readFileAsText(file)\n return name.endsWith('.tsv') ? rowsToCsv(parseDelimitedRows(text, '\\t')) : text\n}\n\nasync function readFirstSheet(file: File): Promise<string[][]> {\n // Lazy import: plugins that never read .xlsx do not load the library.\n const { readSheet } = await import('read-excel-file/universal')\n let rows: SheetData<string>\n try {\n // Keep the stored text: no trim, and no float parse that rounds big numbers.\n rows = await readSheet(file, { trim: false, parseNumber: text => text })\n } catch {\n throw new Error(`${file.name} is not a valid .xlsx workbook.`)\n }\n return rows.map(row => row.map(formatCell))\n}\n\nfunction formatCell(value: unknown): string {\n if (value === null || value === undefined) return ''\n if (typeof value === 'boolean') return value ? 'TRUE' : 'FALSE'\n if (value instanceof Date) {\n // Excel stores dates as float day counts; round off the float error.\n const [date, time] = new Date(Math.round(value.getTime() / 1000) * 1000)\n .toISOString().slice(0, 19).split('T')\n if (date === '1899-12-30') return time // a time-only cell\n return time === '00:00:00' ? date : `${date}T${time}`\n }\n return String(value)\n}\n\nfunction rowsToCsv(rows: readonly (readonly string[])[]): string {\n return rows.map(row => row.map(quoteCsvField).join(',')).join('\\n')\n}\n\nfunction quoteCsvField(value: string): string {\n return /[\",\\r\\n]/.test(value) ? `\"${value.replace(/\"/g, '\"\"')}\"` : value\n}\n\nexport function parseDelimitedText(\n text: string,\n options: ParseDelimitedTextOptions = {},\n): DelimitedTable {\n const trim = options.trim ?? true\n const delimiter = options.delimiter ?? detectDelimiter(text)\n const rawRows = parseDelimitedRows(text, delimiter)\n .filter(row => row.some(cell => cell.trim().length > 0))\n .map(row => trim ? row.map(cell => cell.trim()) : row)\n\n const hasHeaderRow = options.hasHeaderRow ?? !options.headers\n const columns = options.headers\n ? [...options.headers]\n : hasHeaderRow\n ? rawRows[0] ?? []\n : createColumnNames(maxRowLength(rawRows))\n\n const dataRows = hasHeaderRow && !options.headers ? rawRows.slice(1) : rawRows\n const rows = dataRows.map(row => Object.fromEntries(\n columns.map((column, index) => [column, row[index] ?? '']),\n ))\n\n return {\n columns,\n rows,\n rawRows,\n delimiter,\n }\n}\n\nexport function detectDelimiter(text: string): string {\n const firstLine = text.split(/\\r?\\n/, 1)[0] ?? ''\n const commaCount = countChar(firstLine, ',')\n const tabCount = countChar(firstLine, '\\t')\n const semicolonCount = countChar(firstLine, ';')\n if (tabCount > commaCount && tabCount >= semicolonCount) return '\\t'\n if (semicolonCount > commaCount) return ';'\n return ','\n}\n\nfunction parseDelimitedRows(text: string, delimiter: string): string[][] {\n const rows: string[][] = []\n let row: string[] = []\n let field = ''\n let quoted = false\n\n for (let index = 0; index < text.length; index++) {\n const char = text[index]\n const next = text[index + 1]\n\n if (char === '\"') {\n if (quoted && next === '\"') {\n field += '\"'\n index++\n } else if (quoted || field === '') {\n quoted = !quoted\n } else {\n field += '\"' // a quote inside an unquoted field is text\n }\n continue\n }\n\n if (!quoted && char === delimiter) {\n row.push(field)\n field = ''\n continue\n }\n\n if (!quoted && (char === '\\n' || char === '\\r')) {\n if (char === '\\r' && next === '\\n') index++\n row.push(field)\n rows.push(row)\n row = []\n field = ''\n continue\n }\n\n field += char\n }\n\n row.push(field)\n rows.push(row)\n return rows\n}\n\nfunction normalizeAccept(accept: string | readonly string[] | undefined): string[] {\n if (!accept) return []\n const entries = typeof accept === 'string' ? accept.split(',') : [...accept]\n return entries\n .map((entry: string) => entry.trim().toLowerCase())\n .filter(Boolean)\n}\n\nfunction createColumnNames(count: number): string[] {\n return Array.from({ length: count }, (_, index) => `column_${index + 1}`)\n}\n\nfunction maxRowLength(rows: readonly string[][]): number {\n return rows.reduce((max, row) => Math.max(max, row.length), 0)\n}\n\nfunction countChar(value: string, char: string): number {\n return [...value].filter(candidate => candidate === char).length\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`\n return `${Math.round(bytes / (1024 * 1024))} MB`\n}\n","import {\n computed,\n inject,\n toValue,\n watch,\n type ComputedRef,\n type MaybeRefOrGetter,\n type Ref,\n} from 'vue'\nimport type { SelectOption } from '../types'\nimport { APP_EXPERIMENT_KEY } from './useAppExperiment'\nimport {\n extractSampleNamesFromDesignData,\n extractSampleOptionsFromDesignData,\n unwrapExperimentDesignData,\n type ExtractExperimentSamplesOptions,\n} from './experimentDesignData'\nimport { parseExperimentId } from './platformContextHelpers'\nimport { useExperimentData } from './useExperimentData'\n\nexport type ExperimentIdSource = MaybeRefOrGetter<number | string | null | undefined>\nexport type ExperimentDesignDataSource = MaybeRefOrGetter<Record<string, unknown> | null | undefined>\n\nexport interface UseExperimentSamplesOptions extends ExtractExperimentSamplesOptions {\n /** Experiment id to load from `/experiments/{id}/data`; defaults to provided AppExperiment context. */\n experimentId?: ExperimentIdSource\n /** Pre-fetched design_data or full platform design-data response. */\n designData?: ExperimentDesignDataSource\n /** API base URL override for platform calls. */\n apiBaseUrl?: string\n /** Auto-load when an experiment id becomes available. Defaults to true. */\n immediate?: boolean\n /** Enable or disable automatic loading while keeping derived samples reactive. Defaults to true. */\n enabled?: MaybeRefOrGetter<boolean>\n /** Use `useAppExperiment` provided state when `experimentId` is not set. Defaults to true. */\n syncAppExperiment?: boolean\n}\n\nexport interface UseExperimentSamplesReturn {\n /** Experiment id currently used for automatic sample loading. */\n experimentId: ComputedRef<number | undefined>\n /** Raw `/experiments/{id}/data` response when loaded through the platform API. */\n data: Ref<Record<string, unknown> | null>\n /** Plugin-defined design_data payload from props or platform response. */\n designData: ComputedRef<Record<string, unknown> | null>\n /** SampleSelector-compatible string values extracted from design_data. */\n samples: ComputedRef<string[]>\n /** Select/dropdown-friendly sample options extracted from design_data. */\n sampleOptions: ComputedRef<SelectOption<string>[]>\n isLoading: Ref<boolean>\n error: Ref<string | null>\n lastLoadedAt: Ref<Date | null>\n /** Fetch samples for a specific experiment id, defaulting to the resolved id. */\n fetch: (experimentId?: number | string | null) => Promise<Record<string, unknown> | null>\n /** Refetch the current experiment id. */\n refresh: () => Promise<void>\n /** Clear fetched platform data. */\n clear: () => void\n}\n\n/** Loads experiment design_data and derives samples for SampleSelector-style UIs. */\nexport function useExperimentSamples(\n options: UseExperimentSamplesOptions = {},\n): UseExperimentSamplesReturn {\n const appExperiment = options.syncAppExperiment === false\n ? undefined\n : inject(APP_EXPERIMENT_KEY, undefined)\n const experimentData = useExperimentData({ apiBaseUrl: options.apiBaseUrl })\n\n const experimentId = computed<number | undefined>(() => {\n const explicitId = parseExperimentId(toValue(options.experimentId))\n return explicitId ?? parseExperimentId(appExperiment?.experimentId.value)\n })\n\n const explicitDesignData = computed<Record<string, unknown> | null>(() =>\n unwrapExperimentDesignData(toValue(options.designData) ?? null),\n )\n\n const designData = computed<Record<string, unknown> | null>(() =>\n explicitDesignData.value ?? experimentData.designData.value,\n )\n\n const extractOptions = computed<ExtractExperimentSamplesOptions>(() => ({\n includeControls: options.includeControls,\n }))\n\n const samples = computed<string[]>(() =>\n extractSampleNamesFromDesignData(designData.value, extractOptions.value),\n )\n\n const sampleOptions = computed<SelectOption<string>[]>(() =>\n extractSampleOptionsFromDesignData(designData.value, extractOptions.value),\n )\n\n const enabled = computed(() => toValue(options.enabled) ?? true)\n\n async function fetchSamples(\n id: number | string | null | undefined = experimentId.value,\n ): Promise<Record<string, unknown> | null> {\n const parsedId = parseExperimentId(id)\n if (parsedId === undefined) {\n experimentData.clear()\n return null\n }\n return experimentData.fetch(parsedId)\n }\n\n watch(\n () => ({\n designData: explicitDesignData.value,\n enabled: enabled.value,\n experimentId: experimentId.value,\n }),\n ({ designData: currentDesignData, enabled: isEnabled, experimentId: currentExperimentId }) => {\n if (options.immediate === false || !isEnabled) return\n if (currentDesignData) {\n experimentData.clear()\n return\n }\n if (currentExperimentId === undefined) {\n experimentData.clear()\n return\n }\n void experimentData.fetch(currentExperimentId)\n },\n { immediate: options.immediate !== false },\n )\n\n return {\n experimentId,\n data: experimentData.data,\n designData,\n samples,\n sampleOptions,\n isLoading: experimentData.isLoading,\n error: experimentData.error,\n lastLoadedAt: experimentData.lastLoadedAt,\n fetch: fetchSamples,\n refresh: experimentData.refresh,\n clear: experimentData.clear,\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { a as BaseButton_default, n as BaseModal_default, o as __exportAll, r as useFocusTrap, t as useDropdownState } from "./useDropdownState-
|
|
1
|
+
import { a as BaseButton_default, n as BaseModal_default, o as __exportAll, r as useFocusTrap, t as useDropdownState } from "./useDropdownState-uFIz6Yv8.js";
|
|
2
2
|
import { d as MintApiError, f as mintApiErrorFromResponse, l as tryUseSettingsStore, t as useExperimentStore } from "./experiment-DyO54FQB.js";
|
|
3
|
-
import { C as formatExperimentDate, D as compareTime, E as useMenuKeyboard, F as toMinutes, G as BaseInput_default, M as formatTimeSlot, N as generateTimeSlots, T as FileUploader_default, V as BaseSelect_default, W as
|
|
3
|
+
import { C as formatExperimentDate, D as compareTime, E as useMenuKeyboard, F as toMinutes, G as normalizeOptionInput, K as BaseInput_default, M as formatTimeSlot, N as generateTimeSlots, T as FileUploader_default, V as BaseSelect_default, W as useFloatingPanel, c as SecretInput_default, d as isActiveJobStatus, h as normalizeJobState, i as getInjectedPlatformContext, j as formatTime, k as findNearestTimeSlotIndex, n as ResourcePickerListInternal_default, s as TagsInput_default, z as BaseCheckbox_default } from "./records-D4aQXyZu.js";
|
|
4
4
|
import "./auth-SliLnFre.js";
|
|
5
5
|
import { getRoleInfo, hasAllPermissions, isAdminUser } from "./permissions.js";
|
|
6
|
-
import { Fragment, Teleport, Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createStaticVNode, createTextVNode, createVNode, defineComponent, getCurrentInstance, getCurrentScope, inject, mergeProps, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, onScopeDispose, onUnmounted, openBlock, ref, renderList, renderSlot, shallowRef, toDisplayString, toValue, unref, useAttrs, useId, useTemplateRef, vShow, watch, withCtx, withDirectives, withModifiers } from "vue";
|
|
6
|
+
import { Fragment, Teleport, Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createStaticVNode, createTextVNode, createVNode, defineComponent, getCurrentInstance, getCurrentScope, inject, mergeProps, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, onScopeDispose, onUnmounted, openBlock, ref, renderList, renderSlot, shallowRef, toDisplayString, toValue, unref, useAttrs, useId, useTemplateRef, vShow, watch, withCtx, withDirectives, withKeys, withModifiers } from "vue";
|
|
7
7
|
import { ChevronDown, ChevronUp } from "lucide-vue-next";
|
|
8
|
-
import { autoUpdate, computePosition, flip, offset, shift } from "@floating-ui/dom";
|
|
9
8
|
//#region src/components/BaseRadioGroup.vue?vue&type=script&setup=true&lang.ts
|
|
10
9
|
var _hoisted_1$12 = { class: "mint-radio-option__input-wrapper" };
|
|
11
10
|
var _hoisted_2$12 = [
|
|
@@ -26,7 +25,7 @@ var _hoisted_5$9 = [
|
|
|
26
25
|
"aria-describedby",
|
|
27
26
|
"onChange"
|
|
28
27
|
];
|
|
29
|
-
var _hoisted_6$
|
|
28
|
+
var _hoisted_6$8 = { class: "mint-radio-option__head" };
|
|
30
29
|
var _hoisted_7$8 = { class: "mint-radio-option__title" };
|
|
31
30
|
var _hoisted_8$7 = ["id"];
|
|
32
31
|
//#endregion
|
|
@@ -101,7 +100,7 @@ var BaseRadioGroup_default = /* @__PURE__ */ defineComponent({
|
|
|
101
100
|
class: "mint-radio-option__native",
|
|
102
101
|
onChange: ($event) => handleChange(option.value)
|
|
103
102
|
}, null, 40, _hoisted_5$9),
|
|
104
|
-
createElementVNode("div", _hoisted_6$
|
|
103
|
+
createElementVNode("div", _hoisted_6$8, [createElementVNode("div", { class: normalizeClass([
|
|
105
104
|
"mint-radio-option__circle",
|
|
106
105
|
`mint-radio-option__circle--${props.size}`,
|
|
107
106
|
props.modelValue === option.value ? "mint-radio-option__circle--checked" : ""
|
|
@@ -478,7 +477,7 @@ var _hoisted_2$10 = { class: "mint-date-picker__header" };
|
|
|
478
477
|
var _hoisted_3$10 = ["aria-label"];
|
|
479
478
|
var _hoisted_4$9 = { class: "mint-date-picker__month-year" };
|
|
480
479
|
var _hoisted_5$8 = ["aria-label"];
|
|
481
|
-
var _hoisted_6$
|
|
480
|
+
var _hoisted_6$7 = { class: "mint-date-picker__weekdays" };
|
|
482
481
|
var _hoisted_7$7 = { class: "mint-date-picker__grid" };
|
|
483
482
|
var _hoisted_8$6 = [
|
|
484
483
|
"disabled",
|
|
@@ -556,7 +555,7 @@ var CalendarGridPanelInternal_default = /* @__PURE__ */ defineComponent({
|
|
|
556
555
|
"aria-hidden": "true"
|
|
557
556
|
}, [createElementVNode("path", { d: "m9 18 6-6-6-6" })], -1)])], 8, _hoisted_5$8)
|
|
558
557
|
]),
|
|
559
|
-
createElementVNode("div", _hoisted_6$
|
|
558
|
+
createElementVNode("div", _hoisted_6$7, [(openBlock(true), createElementBlock(Fragment, null, renderList(__props.weekDays, (day) => {
|
|
560
559
|
return openBlock(), createElementBlock("div", {
|
|
561
560
|
key: day,
|
|
562
561
|
class: "mint-date-picker__weekday"
|
|
@@ -625,11 +624,11 @@ var DatePickerDateInternal_default = /* @__PURE__ */ defineComponent({
|
|
|
625
624
|
const props = __props;
|
|
626
625
|
const emit = __emit;
|
|
627
626
|
const dropdownRef = ref(null);
|
|
628
|
-
const dropdownStyle = ref({});
|
|
629
627
|
const { isOpen, triggerRef, open, close, toggle } = useDropdownState({
|
|
630
628
|
rootRef: useTemplateRef("container"),
|
|
631
629
|
insideRefs: [dropdownRef]
|
|
632
630
|
});
|
|
631
|
+
const { style: dropdownStyle } = useFloatingPanel(triggerRef, dropdownRef, isOpen);
|
|
633
632
|
useFocusTrap({
|
|
634
633
|
containerRef: dropdownRef,
|
|
635
634
|
active: isOpen
|
|
@@ -664,38 +663,6 @@ var DatePickerDateInternal_default = /* @__PURE__ */ defineComponent({
|
|
|
664
663
|
open();
|
|
665
664
|
}
|
|
666
665
|
}
|
|
667
|
-
let stopAutoUpdate = null;
|
|
668
|
-
async function updateDropdownPosition() {
|
|
669
|
-
const trigger = triggerRef.value;
|
|
670
|
-
const panel = dropdownRef.value;
|
|
671
|
-
if (!trigger || !panel) return;
|
|
672
|
-
const { x, y } = await computePosition(trigger, panel, {
|
|
673
|
-
placement: "bottom-start",
|
|
674
|
-
strategy: "fixed",
|
|
675
|
-
middleware: [
|
|
676
|
-
offset(4),
|
|
677
|
-
flip(),
|
|
678
|
-
shift({ padding: 8 })
|
|
679
|
-
]
|
|
680
|
-
});
|
|
681
|
-
dropdownStyle.value = {
|
|
682
|
-
position: "fixed",
|
|
683
|
-
top: `${y}px`,
|
|
684
|
-
left: `${x}px`,
|
|
685
|
-
zIndex: "9999"
|
|
686
|
-
};
|
|
687
|
-
}
|
|
688
|
-
function stopPositioning() {
|
|
689
|
-
stopAutoUpdate?.();
|
|
690
|
-
stopAutoUpdate = null;
|
|
691
|
-
}
|
|
692
|
-
function startPositioning() {
|
|
693
|
-
const trigger = triggerRef.value;
|
|
694
|
-
const panel = dropdownRef.value;
|
|
695
|
-
if (!trigger || !panel) return;
|
|
696
|
-
stopPositioning();
|
|
697
|
-
stopAutoUpdate = autoUpdate(trigger, panel, () => void updateDropdownPosition());
|
|
698
|
-
}
|
|
699
666
|
/** Moves focus into the calendar grid: selected day, else today, else the first day. */
|
|
700
667
|
function focusCalendar() {
|
|
701
668
|
const panel = dropdownRef.value;
|
|
@@ -703,20 +670,15 @@ var DatePickerDateInternal_default = /* @__PURE__ */ defineComponent({
|
|
|
703
670
|
(panel.querySelector(".mint-date-picker__day--selected") ?? panel.querySelector(".mint-date-picker__day--today") ?? panel.querySelector(".mint-date-picker__day:not([disabled])"))?.focus();
|
|
704
671
|
}
|
|
705
672
|
watch(isOpen, async (opened) => {
|
|
706
|
-
if (!opened)
|
|
707
|
-
stopPositioning();
|
|
708
|
-
return;
|
|
709
|
-
}
|
|
673
|
+
if (!opened) return;
|
|
710
674
|
if (selectedDate.value) setCurrentMonthFromDate(selectedDate.value);
|
|
711
675
|
await nextTick();
|
|
712
|
-
startPositioning();
|
|
713
676
|
await nextTick();
|
|
714
677
|
focusCalendar();
|
|
715
678
|
});
|
|
716
|
-
onBeforeUnmount(stopPositioning);
|
|
717
679
|
return (_ctx, _cache) => {
|
|
718
680
|
return openBlock(), createElementBlock("div", _hoisted_1$9, [createElementVNode("div", _hoisted_2$9, [
|
|
719
|
-
_cache[
|
|
681
|
+
_cache[2] || (_cache[2] = createStaticVNode("<div class=\"mint-date-picker__icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M8 2v4\"></path><path d=\"M16 2v4\"></path><rect width=\"18\" height=\"18\" x=\"3\" y=\"4\" rx=\"2\"></rect><path d=\"M3 10h18\"></path></svg></div>", 1)),
|
|
720
682
|
createElementVNode("input", {
|
|
721
683
|
ref_key: "triggerRef",
|
|
722
684
|
ref: triggerRef,
|
|
@@ -742,7 +704,7 @@ var DatePickerDateInternal_default = /* @__PURE__ */ defineComponent({
|
|
|
742
704
|
class: "mint-date-picker__clear-btn",
|
|
743
705
|
"aria-label": "Clear date",
|
|
744
706
|
onClick: withModifiers(clear, ["stop"])
|
|
745
|
-
}, [..._cache[
|
|
707
|
+
}, [..._cache[1] || (_cache[1] = [createElementVNode("svg", {
|
|
746
708
|
viewBox: "0 0 24 24",
|
|
747
709
|
fill: "none",
|
|
748
710
|
stroke: "currentColor",
|
|
@@ -764,9 +726,10 @@ var DatePickerDateInternal_default = /* @__PURE__ */ defineComponent({
|
|
|
764
726
|
ref_key: "dropdownRef",
|
|
765
727
|
ref: dropdownRef,
|
|
766
728
|
class: "mint-popover mint-date-picker__dropdown",
|
|
767
|
-
style: normalizeStyle(dropdownStyle
|
|
729
|
+
style: normalizeStyle(unref(dropdownStyle)),
|
|
768
730
|
role: "dialog",
|
|
769
|
-
"aria-label": "Date picker"
|
|
731
|
+
"aria-label": "Date picker",
|
|
732
|
+
onKeydown: _cache[0] || (_cache[0] = withKeys(withModifiers(($event) => unref(close)(true), ["prevent"]), ["escape"]))
|
|
770
733
|
}, [createVNode(CalendarGridPanelInternal_default, {
|
|
771
734
|
"week-days": unref(weekDays),
|
|
772
735
|
"month-year": unref(monthYear),
|
|
@@ -782,7 +745,7 @@ var DatePickerDateInternal_default = /* @__PURE__ */ defineComponent({
|
|
|
782
745
|
"selected-date",
|
|
783
746
|
"onPreviousMonth",
|
|
784
747
|
"onNextMonth"
|
|
785
|
-
])],
|
|
748
|
+
])], 36)) : createCommentVNode("", true)]),
|
|
786
749
|
_: 1
|
|
787
750
|
})]))], 512);
|
|
788
751
|
};
|
|
@@ -803,7 +766,7 @@ var _hoisted_3$8 = [
|
|
|
803
766
|
];
|
|
804
767
|
var _hoisted_4$8 = { class: "mint-datetime-picker__calendar-section" };
|
|
805
768
|
var _hoisted_5$7 = { class: "mint-datetime-picker__time-section" };
|
|
806
|
-
var _hoisted_6$
|
|
769
|
+
var _hoisted_6$6 = { class: "mint-datetime-picker__time-grid" };
|
|
807
770
|
var _hoisted_7$6 = ["disabled", "onClick"];
|
|
808
771
|
var _hoisted_8$5 = { class: "mint-datetime-picker__footer" };
|
|
809
772
|
//#endregion
|
|
@@ -838,10 +801,12 @@ var DatePickerDateTimeInternal_default = /* @__PURE__ */ defineComponent({
|
|
|
838
801
|
const props = __props;
|
|
839
802
|
const emit = __emit;
|
|
840
803
|
const dropdownRef = ref(null);
|
|
804
|
+
const rootRef = useTemplateRef("root");
|
|
841
805
|
const { isOpen, open, close, toggle } = useDropdownState({
|
|
842
|
-
rootRef
|
|
806
|
+
rootRef,
|
|
843
807
|
triggerRef: useTemplateRef("trigger")
|
|
844
808
|
});
|
|
809
|
+
const { style: dropdownStyle } = useFloatingPanel(rootRef, dropdownRef, isOpen);
|
|
845
810
|
useFocusTrap({
|
|
846
811
|
containerRef: dropdownRef,
|
|
847
812
|
active: isOpen
|
|
@@ -949,7 +914,7 @@ var DatePickerDateTimeInternal_default = /* @__PURE__ */ defineComponent({
|
|
|
949
914
|
focusCalendar();
|
|
950
915
|
});
|
|
951
916
|
return (_ctx, _cache) => {
|
|
952
|
-
return openBlock(), createElementBlock("div", _hoisted_1$8, [createElementVNode("div", _hoisted_2$8, [_cache[
|
|
917
|
+
return openBlock(), createElementBlock("div", _hoisted_1$8, [createElementVNode("div", _hoisted_2$8, [_cache[1] || (_cache[1] = createStaticVNode("<div class=\"mint-datetime-picker__icon-calendar\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M8 2v4\"></path><path d=\"M16 2v4\"></path><rect width=\"18\" height=\"18\" x=\"3\" y=\"4\" rx=\"2\"></rect><path d=\"M3 10h18\"></path></svg></div>", 1)), createElementVNode("input", {
|
|
953
918
|
ref: "trigger",
|
|
954
919
|
type: "text",
|
|
955
920
|
readonly: "",
|
|
@@ -980,8 +945,10 @@ var DatePickerDateTimeInternal_default = /* @__PURE__ */ defineComponent({
|
|
|
980
945
|
ref_key: "dropdownRef",
|
|
981
946
|
ref: dropdownRef,
|
|
982
947
|
class: "mint-popover mint-datetime-picker__dropdown",
|
|
948
|
+
style: normalizeStyle(unref(dropdownStyle)),
|
|
983
949
|
role: "dialog",
|
|
984
|
-
"aria-label": "Date and time picker"
|
|
950
|
+
"aria-label": "Date and time picker",
|
|
951
|
+
onKeydown: _cache[0] || (_cache[0] = withKeys(withModifiers(($event) => unref(close)(true), ["prevent"]), ["escape"]))
|
|
985
952
|
}, [
|
|
986
953
|
createElementVNode("div", _hoisted_4$8, [createVNode(CalendarGridPanelInternal_default, {
|
|
987
954
|
"week-days": unref(weekDays),
|
|
@@ -1001,8 +968,8 @@ var DatePickerDateTimeInternal_default = /* @__PURE__ */ defineComponent({
|
|
|
1001
968
|
"onPreviousMonth",
|
|
1002
969
|
"onNextMonth"
|
|
1003
970
|
])]),
|
|
1004
|
-
_cache[
|
|
1005
|
-
createElementVNode("div", _hoisted_5$7, [_cache[
|
|
971
|
+
_cache[3] || (_cache[3] = createElementVNode("div", { class: "mint-datetime-picker__divider" }, null, -1)),
|
|
972
|
+
createElementVNode("div", _hoisted_5$7, [_cache[2] || (_cache[2] = createElementVNode("div", { class: "mint-datetime-picker__time-label" }, "Time", -1)), createElementVNode("div", _hoisted_6$6, [(openBlock(true), createElementBlock(Fragment, null, renderList(timeSlots.value, (time) => {
|
|
1006
973
|
return openBlock(), createElementBlock("button", {
|
|
1007
974
|
key: time,
|
|
1008
975
|
type: "button",
|
|
@@ -1029,7 +996,7 @@ var DatePickerDateTimeInternal_default = /* @__PURE__ */ defineComponent({
|
|
|
1029
996
|
class: "mint-datetime-picker__footer-btn mint-datetime-picker__footer-btn--muted",
|
|
1030
997
|
onClick: clear
|
|
1031
998
|
}, " Clear ")) : createCommentVNode("", true)])
|
|
1032
|
-
],
|
|
999
|
+
], 36)) : createCommentVNode("", true)]),
|
|
1033
1000
|
_: 1
|
|
1034
1001
|
})], 512);
|
|
1035
1002
|
};
|
|
@@ -1046,18 +1013,14 @@ var _hoisted_2$7 = [
|
|
|
1046
1013
|
"aria-controls",
|
|
1047
1014
|
"aria-activedescendant"
|
|
1048
1015
|
];
|
|
1049
|
-
var _hoisted_3$7 =
|
|
1050
|
-
key: 0,
|
|
1051
|
-
class: "mint-popover mint-time-picker__dropdown"
|
|
1052
|
-
};
|
|
1053
|
-
var _hoisted_4$7 = [
|
|
1016
|
+
var _hoisted_3$7 = [
|
|
1054
1017
|
"id",
|
|
1055
1018
|
"aria-selected",
|
|
1056
1019
|
"aria-disabled",
|
|
1057
1020
|
"onClick"
|
|
1058
1021
|
];
|
|
1059
|
-
var
|
|
1060
|
-
var
|
|
1022
|
+
var _hoisted_4$7 = { class: "mint-time-picker__slot-time" };
|
|
1023
|
+
var _hoisted_5$6 = {
|
|
1061
1024
|
key: 0,
|
|
1062
1025
|
class: "mint-time-picker__slot-reason"
|
|
1063
1026
|
};
|
|
@@ -1093,12 +1056,15 @@ var DatePickerTimeInternal_default = /* @__PURE__ */ defineComponent({
|
|
|
1093
1056
|
const props = __props;
|
|
1094
1057
|
const emit = __emit;
|
|
1095
1058
|
const listRef = ref(null);
|
|
1059
|
+
const dropdownRef = ref(null);
|
|
1096
1060
|
const highlightedIndex = ref(-1);
|
|
1097
1061
|
const listboxId = `mint-time-picker-listbox-${useId().replace(/:/g, "")}`;
|
|
1062
|
+
const rootRef = useTemplateRef("root");
|
|
1098
1063
|
const { isOpen, open, close, toggle } = useDropdownState({
|
|
1099
|
-
rootRef
|
|
1064
|
+
rootRef,
|
|
1100
1065
|
triggerRef: useTemplateRef("trigger")
|
|
1101
1066
|
});
|
|
1067
|
+
const { style: dropdownStyle } = useFloatingPanel(rootRef, dropdownRef, isOpen, { matchWidth: true });
|
|
1102
1068
|
/** Id of the highlighted slot, published to the input as `aria-activedescendant`. */
|
|
1103
1069
|
const activeSlotId = computed(() => isOpen.value && highlightedIndex.value >= 0 ? `${listboxId}-option-${highlightedIndex.value}` : void 0);
|
|
1104
1070
|
const slots = computed(() => {
|
|
@@ -1282,7 +1248,13 @@ var DatePickerTimeInternal_default = /* @__PURE__ */ defineComponent({
|
|
|
1282
1248
|
"leave-from-class": "mint-time-picker__dropdown-leave-from",
|
|
1283
1249
|
"leave-to-class": "mint-time-picker__dropdown-leave-to"
|
|
1284
1250
|
}, {
|
|
1285
|
-
default: withCtx(() => [unref(isOpen) ? (openBlock(), createElementBlock("div",
|
|
1251
|
+
default: withCtx(() => [unref(isOpen) ? (openBlock(), createElementBlock("div", {
|
|
1252
|
+
key: 0,
|
|
1253
|
+
ref_key: "dropdownRef",
|
|
1254
|
+
ref: dropdownRef,
|
|
1255
|
+
class: "mint-popover mint-time-picker__dropdown",
|
|
1256
|
+
style: normalizeStyle(unref(dropdownStyle))
|
|
1257
|
+
}, [createElementVNode("ul", {
|
|
1286
1258
|
id: listboxId,
|
|
1287
1259
|
ref_key: "listRef",
|
|
1288
1260
|
ref: listRef,
|
|
@@ -1303,8 +1275,8 @@ var DatePickerTimeInternal_default = /* @__PURE__ */ defineComponent({
|
|
|
1303
1275
|
index === highlightedIndex.value && !isSlotDisabled(slot) ? "mint-menu-item--active mint-time-picker__slot--highlighted" : ""
|
|
1304
1276
|
]),
|
|
1305
1277
|
onClick: ($event) => selectSlot(slot)
|
|
1306
|
-
}, [createElementVNode("span",
|
|
1307
|
-
}), 128))], 512)])) : createCommentVNode("", true)]),
|
|
1278
|
+
}, [createElementVNode("span", _hoisted_4$7, toDisplayString(unref(formatTimeSlot)(slot, __props.format)), 1), slotReason(slot) ? (openBlock(), createElementBlock("span", _hoisted_5$6, toDisplayString(slotReason(slot)), 1)) : createCommentVNode("", true)], 10, _hoisted_3$7);
|
|
1279
|
+
}), 128))], 512)], 4)) : createCommentVNode("", true)]),
|
|
1308
1280
|
_: 1
|
|
1309
1281
|
})], 544);
|
|
1310
1282
|
};
|
|
@@ -1595,34 +1567,12 @@ var NumberUnitInputInternal_default = /* @__PURE__ */ defineComponent({
|
|
|
1595
1567
|
emit("update:unit", newUnitValue);
|
|
1596
1568
|
}
|
|
1597
1569
|
const menuRef = ref(null);
|
|
1598
|
-
const menuStyle = ref({ opacity: "0" });
|
|
1599
1570
|
const { isOpen, rootRef, open, close } = useDropdownState({
|
|
1600
1571
|
triggerRef: useTemplateRef("trigger"),
|
|
1601
|
-
|
|
1602
|
-
insideRefs: [menuRef],
|
|
1603
|
-
onOpen: () => {
|
|
1604
|
-
menuStyle.value = { opacity: "0" };
|
|
1605
|
-
}
|
|
1606
|
-
});
|
|
1607
|
-
/** Teleported + fixed like ActionMenu, so overflow:hidden/auto ancestors never clip the menu. */
|
|
1608
|
-
watch(isOpen, async (opened) => {
|
|
1609
|
-
if (!opened) return;
|
|
1610
|
-
await nextTick();
|
|
1611
|
-
if (!rootRef.value || !menuRef.value) return;
|
|
1612
|
-
const { x, y } = await computePosition(rootRef.value, menuRef.value, {
|
|
1613
|
-
placement: "bottom-end",
|
|
1614
|
-
strategy: "fixed",
|
|
1615
|
-
middleware: [
|
|
1616
|
-
offset(4),
|
|
1617
|
-
flip(),
|
|
1618
|
-
shift({ padding: 8 })
|
|
1619
|
-
]
|
|
1620
|
-
});
|
|
1621
|
-
menuStyle.value = {
|
|
1622
|
-
left: `${x}px`,
|
|
1623
|
-
top: `${y}px`
|
|
1624
|
-
};
|
|
1572
|
+
insideRefs: [menuRef]
|
|
1625
1573
|
});
|
|
1574
|
+
/** Teleported + fixed like ActionMenu, so overflow:hidden/auto ancestors never clip the menu; it follows the field on scroll. */
|
|
1575
|
+
const { style: menuStyle } = useFloatingPanel(rootRef, menuRef, isOpen, { placement: "bottom-end" });
|
|
1626
1576
|
function menuItems() {
|
|
1627
1577
|
return menuRef.value ? Array.from(menuRef.value.querySelectorAll("[role=\"option\"]")) : [];
|
|
1628
1578
|
}
|
|
@@ -1693,7 +1643,7 @@ var NumberUnitInputInternal_default = /* @__PURE__ */ defineComponent({
|
|
|
1693
1643
|
ref_key: "menuRef",
|
|
1694
1644
|
ref: menuRef,
|
|
1695
1645
|
class: "mint-popover mint-unit-input__menu",
|
|
1696
|
-
style: normalizeStyle(menuStyle
|
|
1646
|
+
style: normalizeStyle(unref(menuStyle)),
|
|
1697
1647
|
role: "listbox",
|
|
1698
1648
|
"aria-label": "Unit",
|
|
1699
1649
|
onKeydown: _cache[1] || (_cache[1] = (...args) => unref(handlePanelKeydown) && unref(handlePanelKeydown)(...args))
|
|
@@ -5291,4 +5241,4 @@ function useListReorder(options) {
|
|
|
5291
5241
|
//#endregion
|
|
5292
5242
|
export { useJobsEndpoint as A, compareSortValues as B, FormulaInput_default as C, _plugin_vue_export_helper_default as D, GeneratedPathInput_default as E, applySpecDefaults as F, BaseSlider_default as H, defineDataFrame as I, definePlateEditor as L, usePlatform as M, NumberInput_default as N, GENERATED_JOBS_API_KEY as O, DatePicker_default as P, definePluginWorkspaceView as R, useSequenceUtils as S, renderFormulaParts as T, BaseRadioGroup_default as U, useSortedItems as V, getTypeDefault as _, StepWizard_default as a, MoleculeInput_default as b, normalizeControls as c, numericValue as d, omitUndefined as f, getFieldRegistryEntry as g, replaceRecord as h, useReorderAnnouncer as i, createEventStream as j, createGeneratedAnalysisTransport as k, normalizeOption as l, recordValue as m, reorderList as n, defaultValueForControl as o, orderedUnique as p, useListReorder as r, normalizeControlDefinition as s, REORDER_ANNOUNCER_STYLE as t, humanize as u, ConcentrationInput_default as v, formula_exports as w, SequenceInput_default as x, useConcentrationUnits as y, defineWellPlate as z };
|
|
5293
5243
|
|
|
5294
|
-
//# sourceMappingURL=useListReorder-
|
|
5244
|
+
//# sourceMappingURL=useListReorder-DsuzwWGS.js.map
|