@morscherlab/mint-sdk 1.4.0-beta.12 → 1.4.0-beta.14

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 (77) hide show
  1. package/dist/{AlertBox-BdoZqANv.js → AlertBox-SnsbVow-.js} +3 -3
  2. package/dist/{AlertBox-BdoZqANv.js.map → AlertBox-SnsbVow-.js.map} +1 -1
  3. package/dist/{AppSidebar-DGK5i-hJ.js → AppSidebar-Bi8g9mRt.js} +237 -70
  4. package/dist/{AppSidebar-DGK5i-hJ.js.map → AppSidebar-Bi8g9mRt.js.map} +1 -1
  5. package/dist/{ConfirmDialog-nbJj51is.js → ConfirmDialog-CSls2Nuv.js} +2 -2
  6. package/dist/{ConfirmDialog-nbJj51is.js.map → ConfirmDialog-CSls2Nuv.js.map} +1 -1
  7. package/dist/{ExperimentPopover-CbD7BR_s.js → ExperimentPopover-ChKCrklH.js} +5 -5
  8. package/dist/{ExperimentPopover-CbD7BR_s.js.map → ExperimentPopover-ChKCrklH.js.map} +1 -1
  9. package/dist/{ExperimentSelectorModal-BoofZZxF.js → ExperimentSelectorModal-BqifjNaN.js} +113 -97
  10. package/dist/ExperimentSelectorModal-BqifjNaN.js.map +1 -0
  11. package/dist/{SegmentedControl-BkwYOKpG.js → SegmentedControl-hOgBVdju.js} +2 -2
  12. package/dist/{SegmentedControl-BkwYOKpG.js.map → SegmentedControl-hOgBVdju.js.map} +1 -1
  13. package/dist/{SettingsModal-BXsjIVnm.js → SettingsModal-jra_2u0o.js} +7 -7
  14. package/dist/{SettingsModal-BXsjIVnm.js.map → SettingsModal-jra_2u0o.js.map} +1 -1
  15. package/dist/__stories__/experiment-helpers.d.ts +10 -0
  16. package/dist/components/AppTopBar.vue.d.ts +13 -5
  17. package/dist/components/BaseButton.vue.d.ts +4 -2
  18. package/dist/components/ExperimentSelectorModal.vue.d.ts +15 -1
  19. package/dist/components/internal/AppTopBarPageSelectorInternal.vue.d.ts +2 -1
  20. package/dist/{controlSchemaModel-BF5g4wRC.js → controlSchemaModel-CIH5Hqpw.js} +2 -2
  21. package/dist/{controlSchemaModel-BF5g4wRC.js.map → controlSchemaModel-CIH5Hqpw.js.map} +1 -1
  22. package/dist/{data-ihsBd9bs.js → data-OZ94DhVC.js} +11 -11
  23. package/dist/{data-ihsBd9bs.js.map → data-OZ94DhVC.js.map} +1 -1
  24. package/dist/data.js +8 -8
  25. package/dist/{experimentStatus-Cqp6qNrR.js → experimentStatus-BFrKpHAH.js} +2 -2
  26. package/dist/{experimentStatus-Cqp6qNrR.js.map → experimentStatus-BFrKpHAH.js.map} +1 -1
  27. package/dist/index.js +18 -18
  28. package/dist/{install-CFgfRO64.js → install-Bx_6KwJA.js} +15 -15
  29. package/dist/{install-CFgfRO64.js.map → install-Bx_6KwJA.js.map} +1 -1
  30. package/dist/install.js +1 -1
  31. package/dist/{lab-B-pLwc5U.js → lab-ZDKlx1Oo.js} +10 -10
  32. package/dist/{lab-B-pLwc5U.js.map → lab-ZDKlx1Oo.js.map} +1 -1
  33. package/dist/lab.js +4 -4
  34. package/dist/{records-DnK_1Q_S.js → records-B4yl2oIu.js} +2 -2
  35. package/dist/{records-DnK_1Q_S.js.map → records-B4yl2oIu.js.map} +1 -1
  36. package/dist/{runtime-pKfF_iql.js → runtime-BJvGms6h.js} +9 -9
  37. package/dist/{runtime-pKfF_iql.js.map → runtime-BJvGms6h.js.map} +1 -1
  38. package/dist/runtime.js +6 -6
  39. package/dist/{shell-BIH8Rc21.js → shell-Czyrzk7l.js} +5 -5
  40. package/dist/{shell-BIH8Rc21.js.map → shell-Czyrzk7l.js.map} +1 -1
  41. package/dist/shell.js +5 -5
  42. package/dist/styles.css +296 -45
  43. package/dist/types/index.d.ts +1 -1
  44. package/dist/types/jobs.d.ts +9 -0
  45. package/dist/{useDropdownState-8yWMu-7_.js → useDropdownState-Bb2N4m40.js} +15 -3
  46. package/dist/useDropdownState-Bb2N4m40.js.map +1 -0
  47. package/dist/{useExperimentSamples-BGN1dmcR.js → useExperimentSamples-BLx29CkM.js} +3 -3
  48. package/dist/{useExperimentSamples-BGN1dmcR.js.map → useExperimentSamples-BLx29CkM.js.map} +1 -1
  49. package/dist/{useListReorder-DPynGrCj.js → useListReorder-C_8RYeVP.js} +3 -3
  50. package/dist/{useListReorder-DPynGrCj.js.map → useListReorder-C_8RYeVP.js.map} +1 -1
  51. package/dist/{useRackEditor-B2FrQA0p.js → useRackEditor-BhYlXKFM.js} +8 -8
  52. package/dist/{useRackEditor-B2FrQA0p.js.map → useRackEditor-BhYlXKFM.js.map} +1 -1
  53. package/dist/{useRealtime-yWjTTnc9.js → useRealtime-CUMbW_ln.js} +2 -2
  54. package/dist/{useRealtime-yWjTTnc9.js.map → useRealtime-CUMbW_ln.js.map} +1 -1
  55. package/dist/{useRequest-Dqw12k2s.js → useRequest-C9uwM79q.js} +3 -3
  56. package/dist/{useRequest-Dqw12k2s.js.map → useRequest-C9uwM79q.js.map} +1 -1
  57. package/package.json +1 -1
  58. package/src/__stories__/experiment-helpers.ts +3 -3
  59. package/src/__tests__/components/AppTopBar.test.ts +175 -1
  60. package/src/__tests__/components/AppTopBarPageSelector.test.ts +125 -9
  61. package/src/__tests__/components/BaseButton.test.ts +19 -0
  62. package/src/__tests__/components/ExperimentSelectorModal.test.ts +34 -1
  63. package/src/__tests__/styles/menusShellRefresh.test.ts +8 -2
  64. package/src/components/AppTopBar.story.vue +59 -4
  65. package/src/components/AppTopBar.vue +107 -8
  66. package/src/components/BaseButton.vue +16 -2
  67. package/src/components/ExperimentSelectorModal.story.vue +38 -0
  68. package/src/components/ExperimentSelectorModal.vue +20 -1
  69. package/src/components/internal/AppTopBarPageSelectorInternal.vue +140 -72
  70. package/src/styles/components/app-page-selector.css +120 -45
  71. package/src/styles/components/app-top-bar.css +155 -0
  72. package/src/styles/components/button.css +8 -0
  73. package/src/styles/components/experiment-selector-modal.css +13 -0
  74. package/src/types/index.ts +1 -0
  75. package/src/types/jobs.ts +10 -0
  76. package/dist/ExperimentSelectorModal-BoofZZxF.js.map +0 -1
  77. package/dist/useDropdownState-8yWMu-7_.js.map +0 -1
package/dist/runtime.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { i as AuthenticationRequiredError, o as useApi } from "./experiment-DyO54FQB.js";
2
- import { c as isTerminalJobStatus, d as normalizeJobState, f as resolveJobCapabilities, l as jobStatusLabel, o as resolveCurrentPluginId, s as isActiveJobStatus, u as normalizeJobPercent } from "./records-DnK_1Q_S.js";
3
- import { A as createGeneratedAnalysisTransport, D as GeneratedPathInput_default, _ as getFieldRegistryEntry, j as useJobsEndpoint, v as getTypeDefault } from "./useListReorder-DPynGrCj.js";
4
- import { a as GeneratedPlotlyResult_default, c as downloadEndpoint, d as useEventStream, f as useSettingsEndpoint, i as GeneratedResultRenderer_default, l as pluginFormDataFromPayload, m as resolvePluginBaseUrl, o as createClient, p as buildEndpointUrl, u as uploadEndpoint } from "./useRackEditor-B2FrQA0p.js";
5
- import { a as ComponentBindingRenderer_default, c as generatedJobFormSchema, f as useControlWorkspace, i as RuntimeUpdateNotice_default, l as normalizeGeneratedJobInput, n as PresenceAvatars_default, o as GeneratedPluginView_default, r as usePresence, s as generatedJobDefaults } from "./runtime-pKfF_iql.js";
6
- import { A as getDefaultControlView, C as controlBindings, D as controlsTo, S as useControlSchema, b as defineControls, d as useForm, l as useFormBuilder, u as evaluateCondition, x as getControlDefaults, y as defineControlComponentBindings } from "./AppSidebar-DGK5i-hJ.js";
7
- import { a as combinePluginJobSources, o as useJobCenter, r as useRealtime } from "./useRealtime-yWjTTnc9.js";
2
+ import { c as isTerminalJobStatus, d as normalizeJobState, f as resolveJobCapabilities, l as jobStatusLabel, o as resolveCurrentPluginId, s as isActiveJobStatus, u as normalizeJobPercent } from "./records-B4yl2oIu.js";
3
+ import { A as createGeneratedAnalysisTransport, D as GeneratedPathInput_default, _ as getFieldRegistryEntry, j as useJobsEndpoint, v as getTypeDefault } from "./useListReorder-C_8RYeVP.js";
4
+ import { a as GeneratedPlotlyResult_default, c as downloadEndpoint, d as useEventStream, f as useSettingsEndpoint, i as GeneratedResultRenderer_default, l as pluginFormDataFromPayload, m as resolvePluginBaseUrl, o as createClient, p as buildEndpointUrl, u as uploadEndpoint } from "./useRackEditor-BhYlXKFM.js";
5
+ import { a as ComponentBindingRenderer_default, c as generatedJobFormSchema, f as useControlWorkspace, i as RuntimeUpdateNotice_default, l as normalizeGeneratedJobInput, n as PresenceAvatars_default, o as GeneratedPluginView_default, r as usePresence, s as generatedJobDefaults } from "./runtime-BJvGms6h.js";
6
+ import { A as getDefaultControlView, C as controlBindings, D as controlsTo, S as useControlSchema, b as defineControls, d as useForm, l as useFormBuilder, u as evaluateCondition, x as getControlDefaults, y as defineControlComponentBindings } from "./AppSidebar-Bi8g9mRt.js";
7
+ import { a as combinePluginJobSources, o as useJobCenter, r as useRealtime } from "./useRealtime-CUMbW_ln.js";
8
8
  export { AuthenticationRequiredError, ComponentBindingRenderer_default as ComponentBindingRenderer, GeneratedPathInput_default as GeneratedPathInput, GeneratedPlotlyResult_default as GeneratedPlotlyResult, GeneratedPluginView_default as GeneratedPluginView, GeneratedResultRenderer_default as GeneratedResultRenderer, PresenceAvatars_default as PresenceAvatars, RuntimeUpdateNotice_default as RuntimeUpdateNotice, buildEndpointUrl, combinePluginJobSources, controlBindings, controlsTo, createClient, createGeneratedAnalysisTransport, defineControlComponentBindings, defineControls, downloadEndpoint, evaluateCondition, generatedJobDefaults, generatedJobFormSchema, getControlDefaults, getDefaultControlView, getFieldRegistryEntry, getTypeDefault, isActiveJobStatus, isTerminalJobStatus, jobStatusLabel, normalizeGeneratedJobInput, normalizeJobPercent, normalizeJobState, pluginFormDataFromPayload, resolveCurrentPluginId, resolveJobCapabilities, resolvePluginBaseUrl, uploadEndpoint, useApi, useControlSchema, useControlWorkspace, useEventStream, useForm, useFormBuilder, useJobCenter, useJobsEndpoint, usePresence, useRealtime, useSettingsEndpoint };
@@ -1,7 +1,7 @@
1
- import { i as useEventListener, o as __exportAll, r as useFocusTrap } from "./useDropdownState-8yWMu-7_.js";
2
- import { E as useMenuKeyboard, H as useListSelection, R as useRovingFocus, U as useSelectionLimit } from "./records-DnK_1Q_S.js";
3
- import { B as compareSortValues, V as useSortedItems, i as useReorderAnnouncer, n as reorderList, r as useListReorder, t as REORDER_ANNOUNCER_STYLE } from "./useListReorder-DPynGrCj.js";
4
- import { _ as AppLayout_default, f as AppTopBar_default, t as AppSidebar_default, v as usePluginWorkspace } from "./AppSidebar-DGK5i-hJ.js";
1
+ import { i as useEventListener, o as __exportAll, r as useFocusTrap } from "./useDropdownState-Bb2N4m40.js";
2
+ import { E as useMenuKeyboard, H as useListSelection, R as useRovingFocus, U as useSelectionLimit } from "./records-B4yl2oIu.js";
3
+ import { B as compareSortValues, V as useSortedItems, i as useReorderAnnouncer, n as reorderList, r as useListReorder, t as REORDER_ANNOUNCER_STYLE } from "./useListReorder-C_8RYeVP.js";
4
+ import { _ as AppLayout_default, f as AppTopBar_default, t as AppSidebar_default, v as usePluginWorkspace } from "./AppSidebar-Bi8g9mRt.js";
5
5
  import { t as useDebouncedWatch } from "./useDebouncedWatch-BPwyl6eS.js";
6
6
  import { t as useExpansionSet } from "./useExpansionSet-CvoNMZJi.js";
7
7
  import { computed, createElementBlock, createElementVNode, defineComponent, normalizeClass, onBeforeUnmount, openBlock, shallowRef, toValue, watch } from "vue";
@@ -194,4 +194,4 @@ var shell_exports = /* @__PURE__ */ __exportAll({
194
194
  //#endregion
195
195
  export { useManualLayoutResize as a, resizedVerticalSplitPercent as i, resizedLeadingPanelWidth as n, LayoutResizeHandle_default as o, resizedTrailingPanelWidth as r, shell_exports as t };
196
196
 
197
- //# sourceMappingURL=shell-BIH8Rc21.js.map
197
+ //# sourceMappingURL=shell-Czyrzk7l.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shell-BIH8Rc21.js","names":[],"sources":["../src/components/LayoutResizeHandle.vue","../src/components/LayoutResizeHandle.vue","../src/composables/useManualLayoutResize.ts","../src/shell.ts"],"sourcesContent":["<script setup lang=\"ts\">\n/** Accessible pointer and keyboard handle for resizable workbench panes. */\ninterface Props {\n modelValue: number\n min: number\n max: number\n label: string\n orientation: 'vertical' | 'horizontal'\n edge?: 'left' | 'right'\n step?: number\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n edge: undefined,\n step: 10,\n disabled: false,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: number]\n 'resize-start': [event: PointerEvent]\n}>()\n\nfunction update(value: number): void {\n emit('update:modelValue', Math.min(props.max, Math.max(props.min, value)))\n}\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (props.disabled) return\n const decrement = props.orientation === 'vertical' ? 'ArrowLeft' : 'ArrowUp'\n const increment = props.orientation === 'vertical' ? 'ArrowRight' : 'ArrowDown'\n if (event.key === decrement) update(props.modelValue - props.step)\n else if (event.key === increment) update(props.modelValue + props.step)\n else if (event.key === 'Home') update(props.min)\n else if (event.key === 'End') update(props.max)\n else return\n event.preventDefault()\n}\n</script>\n\n<template>\n <div\n role=\"separator\"\n :tabindex=\"disabled ? -1 : 0\"\n :class=\"[\n 'mint-layout-resize-handle',\n `mint-layout-resize-handle--${orientation}`,\n edge ? `mint-layout-resize-handle--edge-${edge}` : '',\n ]\"\n :aria-label=\"label\"\n :aria-orientation=\"orientation\"\n :aria-valuemin=\"min\"\n :aria-valuemax=\"max\"\n :aria-valuenow=\"modelValue\"\n :aria-disabled=\"disabled || undefined\"\n @pointerdown=\"!disabled && emit('resize-start', $event)\"\n @keydown=\"handleKeydown\"\n >\n <span class=\"mint-layout-resize-handle__bar\" aria-hidden=\"true\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\n/** Accessible pointer and keyboard handle for resizable workbench panes. */\ninterface Props {\n modelValue: number\n min: number\n max: number\n label: string\n orientation: 'vertical' | 'horizontal'\n edge?: 'left' | 'right'\n step?: number\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n edge: undefined,\n step: 10,\n disabled: false,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: number]\n 'resize-start': [event: PointerEvent]\n}>()\n\nfunction update(value: number): void {\n emit('update:modelValue', Math.min(props.max, Math.max(props.min, value)))\n}\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (props.disabled) return\n const decrement = props.orientation === 'vertical' ? 'ArrowLeft' : 'ArrowUp'\n const increment = props.orientation === 'vertical' ? 'ArrowRight' : 'ArrowDown'\n if (event.key === decrement) update(props.modelValue - props.step)\n else if (event.key === increment) update(props.modelValue + props.step)\n else if (event.key === 'Home') update(props.min)\n else if (event.key === 'End') update(props.max)\n else return\n event.preventDefault()\n}\n</script>\n\n<template>\n <div\n role=\"separator\"\n :tabindex=\"disabled ? -1 : 0\"\n :class=\"[\n 'mint-layout-resize-handle',\n `mint-layout-resize-handle--${orientation}`,\n edge ? `mint-layout-resize-handle--edge-${edge}` : '',\n ]\"\n :aria-label=\"label\"\n :aria-orientation=\"orientation\"\n :aria-valuemin=\"min\"\n :aria-valuemax=\"max\"\n :aria-valuenow=\"modelValue\"\n :aria-disabled=\"disabled || undefined\"\n @pointerdown=\"!disabled && emit('resize-start', $event)\"\n @keydown=\"handleKeydown\"\n >\n <span class=\"mint-layout-resize-handle__bar\" aria-hidden=\"true\" />\n </div>\n</template>\n","import { computed, onBeforeUnmount, shallowRef, toValue, watch, type MaybeRefOrGetter } from 'vue'\n\nexport interface ResizePanelWidthConstraints {\n minWidth: number\n maxWidth: number\n mainMinWidth?: number\n layoutGap?: number\n}\n\nexport interface ResizePercentConstraints {\n minPercent: number\n maxPercent: number\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value))\n}\n\nfunction availablePanelWidth(\n containerWidth: number,\n constraints: ResizePanelWidthConstraints,\n): number {\n return Math.min(\n constraints.maxWidth,\n containerWidth - (constraints.mainMinWidth ?? 0) - (constraints.layoutGap ?? 0),\n )\n}\n\nexport function resizedLeadingPanelWidth(\n startWidth: number,\n deltaX: number,\n containerWidth: number,\n constraints: ResizePanelWidthConstraints,\n): number {\n return Math.round(clamp(\n startWidth + deltaX,\n constraints.minWidth,\n Math.max(constraints.minWidth, availablePanelWidth(containerWidth, constraints)),\n ))\n}\n\nexport function resizedTrailingPanelWidth(\n startWidth: number,\n deltaX: number,\n containerWidth: number,\n constraints: ResizePanelWidthConstraints,\n): number {\n return resizedLeadingPanelWidth(startWidth, -deltaX, containerWidth, constraints)\n}\n\nexport function resizedVerticalSplitPercent(\n startPercent: number,\n deltaY: number,\n containerHeight: number,\n constraints: ResizePercentConstraints,\n): number {\n if (containerHeight <= 0) return startPercent\n return Math.round(clamp(\n startPercent + (deltaY / containerHeight) * 100,\n constraints.minPercent,\n constraints.maxPercent,\n ))\n}\n\nexport interface ManualLayoutResizeContext<TKind extends string> {\n kind: TKind\n startValue: number\n deltaX: number\n deltaY: number\n containerRect: DOMRectReadOnly\n secondaryRect: DOMRectReadOnly | null\n}\n\nexport interface ManualLayoutResizeTarget<TKind extends string> {\n cursor?: string\n getContainerElement: () => HTMLElement | null\n getSecondaryElement?: () => HTMLElement | null\n getStartValue: () => number\n onResize: (context: ManualLayoutResizeContext<TKind>) => void\n}\n\n/** Coordinates pointer-driven resizing for one or more layout splitters. */\nexport function useManualLayoutResize<TKind extends string>(options: {\n enabled: MaybeRefOrGetter<boolean>\n resolveTarget: (kind: TKind) => ManualLayoutResizeTarget<TKind> | null\n}) {\n const activeResize = shallowRef<{\n kind: TKind\n startClientX: number\n startClientY: number\n startValue: number\n containerRect: DOMRectReadOnly\n secondaryRect: DOMRectReadOnly | null\n cursor: string\n } | null>(null)\n const isResizing = computed(() => activeResize.value !== null)\n let previousBodyCursor = ''\n let previousBodyUserSelect = ''\n\n function stopResize(): void {\n if (!activeResize.value) return\n activeResize.value = null\n window.removeEventListener('pointermove', handlePointerMove)\n window.removeEventListener('pointerup', stopResize)\n window.removeEventListener('pointercancel', stopResize)\n if (typeof document !== 'undefined') {\n document.body.style.cursor = previousBodyCursor\n document.body.style.userSelect = previousBodyUserSelect\n }\n }\n\n function handlePointerMove(event: PointerEvent): void {\n const state = activeResize.value\n if (!state) return\n options.resolveTarget(state.kind)?.onResize({\n kind: state.kind,\n startValue: state.startValue,\n deltaX: event.clientX - state.startClientX,\n deltaY: event.clientY - state.startClientY,\n containerRect: state.containerRect,\n secondaryRect: state.secondaryRect,\n })\n }\n\n function startResize(kind: TKind, event: PointerEvent): void {\n if (!toValue(options.enabled) || event.button !== 0) return\n const target = options.resolveTarget(kind)\n const containerRect = target?.getContainerElement()?.getBoundingClientRect()\n if (!target || !containerRect) return\n\n event.preventDefault()\n if (event.currentTarget instanceof HTMLElement) {\n event.currentTarget.setPointerCapture(event.pointerId)\n }\n const secondary = target.getSecondaryElement?.() ?? null\n activeResize.value = {\n kind,\n startClientX: event.clientX,\n startClientY: event.clientY,\n startValue: target.getStartValue(),\n containerRect,\n secondaryRect: secondary?.getBoundingClientRect() ?? null,\n cursor: target.cursor ?? 'col-resize',\n }\n\n if (typeof document !== 'undefined') {\n previousBodyCursor = document.body.style.cursor\n previousBodyUserSelect = document.body.style.userSelect\n document.body.style.cursor = activeResize.value.cursor\n document.body.style.userSelect = 'none'\n }\n window.addEventListener('pointermove', handlePointerMove)\n window.addEventListener('pointerup', stopResize)\n window.addEventListener('pointercancel', stopResize)\n }\n\n function isResizingKind(kind: TKind): boolean {\n return activeResize.value?.kind === kind\n }\n\n watch(() => toValue(options.enabled), enabled => { if (!enabled) stopResize() })\n onBeforeUnmount(stopResize)\n\n return { activeResize, isResizing, isResizingKind, startResize, stopResize }\n}\n","// Application shell components (`@morscherlab/mint-sdk/shell`).\n\n// Layout components\nexport { default as AppTopBar } from './components/AppTopBar.vue'\nexport { default as AppSidebar } from './components/AppSidebar.vue'\nexport { default as AppLayout } from './components/AppLayout.vue'\nexport { default as LayoutResizeHandle } from './components/LayoutResizeHandle.vue'\n\n// Headless interaction composables\nexport {\n useEventListener,\n type EventListenerEnabled,\n type EventFor,\n type EventListenerStop,\n type EventMapFor,\n type EventTargetGetter,\n type EventTargetLike,\n type UseEventListenerObjectOptions,\n type UseEventListenerOptions,\n} from './composables/useEventListener'\nexport {\n useDebouncedWatch,\n type DebouncedWatchCallback,\n type DebouncedWatchCleanup,\n type DebouncedWatchSource,\n type UseDebouncedWatchOptions,\n type UseDebouncedWatchReturn,\n} from './composables/useDebouncedWatch'\nexport {\n useFocusTrap,\n type UseFocusTrapOptions,\n type UseFocusTrapReturn,\n} from './composables/useFocusTrap'\nexport {\n useRovingFocus,\n type UseRovingFocusOptions,\n type UseRovingFocusReturn,\n} from './composables/useRovingFocus'\nexport {\n reorderList,\n useListReorder,\n useReorderAnnouncer,\n REORDER_ANNOUNCER_STYLE,\n type ListReorderMove,\n type UseListReorderOptions,\n type UseListReorderReturn,\n type UseReorderAnnouncerReturn,\n} from './composables/useListReorder'\nexport {\n useMenuKeyboard,\n type UseMenuKeyboardOptions,\n type UseMenuKeyboardReturn,\n} from './composables/useMenuKeyboard'\n\n// Layout, selection, expansion and sort primitives\nexport {\n resizedLeadingPanelWidth,\n resizedTrailingPanelWidth,\n resizedVerticalSplitPercent,\n useManualLayoutResize,\n type ManualLayoutResizeContext,\n type ManualLayoutResizeTarget,\n type ResizePanelWidthConstraints,\n type ResizePercentConstraints,\n} from './composables/useManualLayoutResize'\nexport {\n useSelectionLimit,\n type SelectionLimitSource,\n type UseSelectionLimitOptions,\n type UseSelectionLimitReturn,\n} from './composables/useSelectionLimit'\nexport {\n useListSelection,\n type ListSelectionSource,\n type ListSelectionValue,\n type UseListSelectionOptions,\n type UseListSelectionReturn,\n type WidenListSelectionValue,\n} from './composables/useListSelection'\nexport {\n useExpansionSet,\n type ExpansionSetSource,\n type UseExpansionSetOptions,\n type UseExpansionSetReturn,\n} from './composables/useExpansionSet'\nexport {\n compareSortValues,\n useSortedItems,\n type CompareSortValuesOptions,\n type SortComparator,\n type SortComparatorContext,\n type SortDescriptor,\n type SortedItemsSource,\n type SortOrder,\n type UseSortedItemsOptions,\n type UseSortedItemsReturn,\n} from './composables/useSortedItems'\nexport {\n usePluginWorkspace,\n type PluginWorkspaceSlotsLike,\n type UsePluginWorkspaceOptions,\n type UsePluginWorkspaceReturn,\n} from './composables/usePluginWorkspace'\n"],"mappings":"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"}
1
+ {"version":3,"file":"shell-Czyrzk7l.js","names":[],"sources":["../src/components/LayoutResizeHandle.vue","../src/components/LayoutResizeHandle.vue","../src/composables/useManualLayoutResize.ts","../src/shell.ts"],"sourcesContent":["<script setup lang=\"ts\">\n/** Accessible pointer and keyboard handle for resizable workbench panes. */\ninterface Props {\n modelValue: number\n min: number\n max: number\n label: string\n orientation: 'vertical' | 'horizontal'\n edge?: 'left' | 'right'\n step?: number\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n edge: undefined,\n step: 10,\n disabled: false,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: number]\n 'resize-start': [event: PointerEvent]\n}>()\n\nfunction update(value: number): void {\n emit('update:modelValue', Math.min(props.max, Math.max(props.min, value)))\n}\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (props.disabled) return\n const decrement = props.orientation === 'vertical' ? 'ArrowLeft' : 'ArrowUp'\n const increment = props.orientation === 'vertical' ? 'ArrowRight' : 'ArrowDown'\n if (event.key === decrement) update(props.modelValue - props.step)\n else if (event.key === increment) update(props.modelValue + props.step)\n else if (event.key === 'Home') update(props.min)\n else if (event.key === 'End') update(props.max)\n else return\n event.preventDefault()\n}\n</script>\n\n<template>\n <div\n role=\"separator\"\n :tabindex=\"disabled ? -1 : 0\"\n :class=\"[\n 'mint-layout-resize-handle',\n `mint-layout-resize-handle--${orientation}`,\n edge ? `mint-layout-resize-handle--edge-${edge}` : '',\n ]\"\n :aria-label=\"label\"\n :aria-orientation=\"orientation\"\n :aria-valuemin=\"min\"\n :aria-valuemax=\"max\"\n :aria-valuenow=\"modelValue\"\n :aria-disabled=\"disabled || undefined\"\n @pointerdown=\"!disabled && emit('resize-start', $event)\"\n @keydown=\"handleKeydown\"\n >\n <span class=\"mint-layout-resize-handle__bar\" aria-hidden=\"true\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\n/** Accessible pointer and keyboard handle for resizable workbench panes. */\ninterface Props {\n modelValue: number\n min: number\n max: number\n label: string\n orientation: 'vertical' | 'horizontal'\n edge?: 'left' | 'right'\n step?: number\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n edge: undefined,\n step: 10,\n disabled: false,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: number]\n 'resize-start': [event: PointerEvent]\n}>()\n\nfunction update(value: number): void {\n emit('update:modelValue', Math.min(props.max, Math.max(props.min, value)))\n}\n\nfunction handleKeydown(event: KeyboardEvent): void {\n if (props.disabled) return\n const decrement = props.orientation === 'vertical' ? 'ArrowLeft' : 'ArrowUp'\n const increment = props.orientation === 'vertical' ? 'ArrowRight' : 'ArrowDown'\n if (event.key === decrement) update(props.modelValue - props.step)\n else if (event.key === increment) update(props.modelValue + props.step)\n else if (event.key === 'Home') update(props.min)\n else if (event.key === 'End') update(props.max)\n else return\n event.preventDefault()\n}\n</script>\n\n<template>\n <div\n role=\"separator\"\n :tabindex=\"disabled ? -1 : 0\"\n :class=\"[\n 'mint-layout-resize-handle',\n `mint-layout-resize-handle--${orientation}`,\n edge ? `mint-layout-resize-handle--edge-${edge}` : '',\n ]\"\n :aria-label=\"label\"\n :aria-orientation=\"orientation\"\n :aria-valuemin=\"min\"\n :aria-valuemax=\"max\"\n :aria-valuenow=\"modelValue\"\n :aria-disabled=\"disabled || undefined\"\n @pointerdown=\"!disabled && emit('resize-start', $event)\"\n @keydown=\"handleKeydown\"\n >\n <span class=\"mint-layout-resize-handle__bar\" aria-hidden=\"true\" />\n </div>\n</template>\n","import { computed, onBeforeUnmount, shallowRef, toValue, watch, type MaybeRefOrGetter } from 'vue'\n\nexport interface ResizePanelWidthConstraints {\n minWidth: number\n maxWidth: number\n mainMinWidth?: number\n layoutGap?: number\n}\n\nexport interface ResizePercentConstraints {\n minPercent: number\n maxPercent: number\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value))\n}\n\nfunction availablePanelWidth(\n containerWidth: number,\n constraints: ResizePanelWidthConstraints,\n): number {\n return Math.min(\n constraints.maxWidth,\n containerWidth - (constraints.mainMinWidth ?? 0) - (constraints.layoutGap ?? 0),\n )\n}\n\nexport function resizedLeadingPanelWidth(\n startWidth: number,\n deltaX: number,\n containerWidth: number,\n constraints: ResizePanelWidthConstraints,\n): number {\n return Math.round(clamp(\n startWidth + deltaX,\n constraints.minWidth,\n Math.max(constraints.minWidth, availablePanelWidth(containerWidth, constraints)),\n ))\n}\n\nexport function resizedTrailingPanelWidth(\n startWidth: number,\n deltaX: number,\n containerWidth: number,\n constraints: ResizePanelWidthConstraints,\n): number {\n return resizedLeadingPanelWidth(startWidth, -deltaX, containerWidth, constraints)\n}\n\nexport function resizedVerticalSplitPercent(\n startPercent: number,\n deltaY: number,\n containerHeight: number,\n constraints: ResizePercentConstraints,\n): number {\n if (containerHeight <= 0) return startPercent\n return Math.round(clamp(\n startPercent + (deltaY / containerHeight) * 100,\n constraints.minPercent,\n constraints.maxPercent,\n ))\n}\n\nexport interface ManualLayoutResizeContext<TKind extends string> {\n kind: TKind\n startValue: number\n deltaX: number\n deltaY: number\n containerRect: DOMRectReadOnly\n secondaryRect: DOMRectReadOnly | null\n}\n\nexport interface ManualLayoutResizeTarget<TKind extends string> {\n cursor?: string\n getContainerElement: () => HTMLElement | null\n getSecondaryElement?: () => HTMLElement | null\n getStartValue: () => number\n onResize: (context: ManualLayoutResizeContext<TKind>) => void\n}\n\n/** Coordinates pointer-driven resizing for one or more layout splitters. */\nexport function useManualLayoutResize<TKind extends string>(options: {\n enabled: MaybeRefOrGetter<boolean>\n resolveTarget: (kind: TKind) => ManualLayoutResizeTarget<TKind> | null\n}) {\n const activeResize = shallowRef<{\n kind: TKind\n startClientX: number\n startClientY: number\n startValue: number\n containerRect: DOMRectReadOnly\n secondaryRect: DOMRectReadOnly | null\n cursor: string\n } | null>(null)\n const isResizing = computed(() => activeResize.value !== null)\n let previousBodyCursor = ''\n let previousBodyUserSelect = ''\n\n function stopResize(): void {\n if (!activeResize.value) return\n activeResize.value = null\n window.removeEventListener('pointermove', handlePointerMove)\n window.removeEventListener('pointerup', stopResize)\n window.removeEventListener('pointercancel', stopResize)\n if (typeof document !== 'undefined') {\n document.body.style.cursor = previousBodyCursor\n document.body.style.userSelect = previousBodyUserSelect\n }\n }\n\n function handlePointerMove(event: PointerEvent): void {\n const state = activeResize.value\n if (!state) return\n options.resolveTarget(state.kind)?.onResize({\n kind: state.kind,\n startValue: state.startValue,\n deltaX: event.clientX - state.startClientX,\n deltaY: event.clientY - state.startClientY,\n containerRect: state.containerRect,\n secondaryRect: state.secondaryRect,\n })\n }\n\n function startResize(kind: TKind, event: PointerEvent): void {\n if (!toValue(options.enabled) || event.button !== 0) return\n const target = options.resolveTarget(kind)\n const containerRect = target?.getContainerElement()?.getBoundingClientRect()\n if (!target || !containerRect) return\n\n event.preventDefault()\n if (event.currentTarget instanceof HTMLElement) {\n event.currentTarget.setPointerCapture(event.pointerId)\n }\n const secondary = target.getSecondaryElement?.() ?? null\n activeResize.value = {\n kind,\n startClientX: event.clientX,\n startClientY: event.clientY,\n startValue: target.getStartValue(),\n containerRect,\n secondaryRect: secondary?.getBoundingClientRect() ?? null,\n cursor: target.cursor ?? 'col-resize',\n }\n\n if (typeof document !== 'undefined') {\n previousBodyCursor = document.body.style.cursor\n previousBodyUserSelect = document.body.style.userSelect\n document.body.style.cursor = activeResize.value.cursor\n document.body.style.userSelect = 'none'\n }\n window.addEventListener('pointermove', handlePointerMove)\n window.addEventListener('pointerup', stopResize)\n window.addEventListener('pointercancel', stopResize)\n }\n\n function isResizingKind(kind: TKind): boolean {\n return activeResize.value?.kind === kind\n }\n\n watch(() => toValue(options.enabled), enabled => { if (!enabled) stopResize() })\n onBeforeUnmount(stopResize)\n\n return { activeResize, isResizing, isResizingKind, startResize, stopResize }\n}\n","// Application shell components (`@morscherlab/mint-sdk/shell`).\n\n// Layout components\nexport { default as AppTopBar } from './components/AppTopBar.vue'\nexport { default as AppSidebar } from './components/AppSidebar.vue'\nexport { default as AppLayout } from './components/AppLayout.vue'\nexport { default as LayoutResizeHandle } from './components/LayoutResizeHandle.vue'\n\n// Headless interaction composables\nexport {\n useEventListener,\n type EventListenerEnabled,\n type EventFor,\n type EventListenerStop,\n type EventMapFor,\n type EventTargetGetter,\n type EventTargetLike,\n type UseEventListenerObjectOptions,\n type UseEventListenerOptions,\n} from './composables/useEventListener'\nexport {\n useDebouncedWatch,\n type DebouncedWatchCallback,\n type DebouncedWatchCleanup,\n type DebouncedWatchSource,\n type UseDebouncedWatchOptions,\n type UseDebouncedWatchReturn,\n} from './composables/useDebouncedWatch'\nexport {\n useFocusTrap,\n type UseFocusTrapOptions,\n type UseFocusTrapReturn,\n} from './composables/useFocusTrap'\nexport {\n useRovingFocus,\n type UseRovingFocusOptions,\n type UseRovingFocusReturn,\n} from './composables/useRovingFocus'\nexport {\n reorderList,\n useListReorder,\n useReorderAnnouncer,\n REORDER_ANNOUNCER_STYLE,\n type ListReorderMove,\n type UseListReorderOptions,\n type UseListReorderReturn,\n type UseReorderAnnouncerReturn,\n} from './composables/useListReorder'\nexport {\n useMenuKeyboard,\n type UseMenuKeyboardOptions,\n type UseMenuKeyboardReturn,\n} from './composables/useMenuKeyboard'\n\n// Layout, selection, expansion and sort primitives\nexport {\n resizedLeadingPanelWidth,\n resizedTrailingPanelWidth,\n resizedVerticalSplitPercent,\n useManualLayoutResize,\n type ManualLayoutResizeContext,\n type ManualLayoutResizeTarget,\n type ResizePanelWidthConstraints,\n type ResizePercentConstraints,\n} from './composables/useManualLayoutResize'\nexport {\n useSelectionLimit,\n type SelectionLimitSource,\n type UseSelectionLimitOptions,\n type UseSelectionLimitReturn,\n} from './composables/useSelectionLimit'\nexport {\n useListSelection,\n type ListSelectionSource,\n type ListSelectionValue,\n type UseListSelectionOptions,\n type UseListSelectionReturn,\n type WidenListSelectionValue,\n} from './composables/useListSelection'\nexport {\n useExpansionSet,\n type ExpansionSetSource,\n type UseExpansionSetOptions,\n type UseExpansionSetReturn,\n} from './composables/useExpansionSet'\nexport {\n compareSortValues,\n useSortedItems,\n type CompareSortValuesOptions,\n type SortComparator,\n type SortComparatorContext,\n type SortDescriptor,\n type SortedItemsSource,\n type SortOrder,\n type UseSortedItemsOptions,\n type UseSortedItemsReturn,\n} from './composables/useSortedItems'\nexport {\n usePluginWorkspace,\n type PluginWorkspaceSlotsLike,\n type UsePluginWorkspaceOptions,\n type UsePluginWorkspaceReturn,\n} from './composables/usePluginWorkspace'\n"],"mappings":"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"}
package/dist/shell.js CHANGED
@@ -1,8 +1,8 @@
1
- import { i as useEventListener, r as useFocusTrap } from "./useDropdownState-8yWMu-7_.js";
2
- import { E as useMenuKeyboard, H as useListSelection, R as useRovingFocus, U as useSelectionLimit } from "./records-DnK_1Q_S.js";
3
- import { B as compareSortValues, V as useSortedItems, i as useReorderAnnouncer, n as reorderList, r as useListReorder, t as REORDER_ANNOUNCER_STYLE } from "./useListReorder-DPynGrCj.js";
4
- import { _ as AppLayout_default, f as AppTopBar_default, t as AppSidebar_default, v as usePluginWorkspace } from "./AppSidebar-DGK5i-hJ.js";
1
+ import { i as useEventListener, r as useFocusTrap } from "./useDropdownState-Bb2N4m40.js";
2
+ import { E as useMenuKeyboard, H as useListSelection, R as useRovingFocus, U as useSelectionLimit } from "./records-B4yl2oIu.js";
3
+ import { B as compareSortValues, V as useSortedItems, i as useReorderAnnouncer, n as reorderList, r as useListReorder, t as REORDER_ANNOUNCER_STYLE } from "./useListReorder-C_8RYeVP.js";
4
+ import { _ as AppLayout_default, f as AppTopBar_default, t as AppSidebar_default, v as usePluginWorkspace } from "./AppSidebar-Bi8g9mRt.js";
5
5
  import { t as useDebouncedWatch } from "./useDebouncedWatch-BPwyl6eS.js";
6
6
  import { t as useExpansionSet } from "./useExpansionSet-CvoNMZJi.js";
7
- import { a as useManualLayoutResize, i as resizedVerticalSplitPercent, n as resizedLeadingPanelWidth, o as LayoutResizeHandle_default, r as resizedTrailingPanelWidth } from "./shell-BIH8Rc21.js";
7
+ import { a as useManualLayoutResize, i as resizedVerticalSplitPercent, n as resizedLeadingPanelWidth, o as LayoutResizeHandle_default, r as resizedTrailingPanelWidth } from "./shell-Czyrzk7l.js";
8
8
  export { AppLayout_default as AppLayout, AppSidebar_default as AppSidebar, AppTopBar_default as AppTopBar, LayoutResizeHandle_default as LayoutResizeHandle, REORDER_ANNOUNCER_STYLE, compareSortValues, reorderList, resizedLeadingPanelWidth, resizedTrailingPanelWidth, resizedVerticalSplitPercent, useDebouncedWatch, useEventListener, useExpansionSet, useFocusTrap, useListReorder, useListSelection, useManualLayoutResize, useMenuKeyboard, usePluginWorkspace, useReorderAnnouncer, useRovingFocus, useSelectionLimit, useSortedItems };
package/dist/styles.css CHANGED
@@ -2503,6 +2503,161 @@ button, input, select, textarea {
2503
2503
  white-space: nowrap;
2504
2504
  user-select: none;
2505
2505
  }
2506
+
2507
+ /* ─── Run slot: [ experiment | job ] ───
2508
+ While a job shows, one border wraps the experiment chip and the job
2509
+ segment, as the experiment popover does for Save. The wrapper does not
2510
+ clip: the popover panel and the focus rings reach outside it, so each
2511
+ segment rounds its own outer corners. The idle Jobs button stands apart
2512
+ with its own border. */
2513
+ .mint-topbar__run-slot {
2514
+ display: inline-flex;
2515
+ align-items: center;
2516
+ gap: 0.5rem;
2517
+ min-width: 0;
2518
+ }
2519
+
2520
+ .mint-topbar__run-slot--joined {
2521
+ gap: 0;
2522
+ border: 1px solid var(--border-color);
2523
+ border-radius: var(--radius-md);
2524
+ background: var(--bg-card);
2525
+ }
2526
+
2527
+ .mint-topbar__run-slot--joined .mint-experiment-popover,
2528
+ .mint-topbar__run-slot--joined .mint-experiment-popover__trigger {
2529
+ border: 0;
2530
+ border-radius: calc(var(--radius-md) - 1px) 0 0 calc(var(--radius-md) - 1px);
2531
+ }
2532
+
2533
+ /* The job takes the name's place: the name folds away while the job grows in,
2534
+ and the code badge stays. The name stays in the accessible name. A trigger
2535
+ with no code, the empty placeholder and the error text keep their text. */
2536
+ .mint-topbar__run-slot .mint-experiment-popover__trigger-text {
2537
+ transition:
2538
+ max-width 200ms ease,
2539
+ opacity 150ms ease,
2540
+ margin 200ms ease;
2541
+ }
2542
+
2543
+ .mint-topbar__run-slot--joined
2544
+ .mint-experiment-popover__trigger:has(.mint-exp-code)
2545
+ .mint-experiment-popover__trigger-text {
2546
+ max-width: 0 !important; /* beats the inline maxNameWidth */
2547
+ margin-inline-start: -0.5rem; /* takes back the trigger gap */
2548
+ opacity: 0;
2549
+ }
2550
+
2551
+ .mint-topbar__job {
2552
+ display: inline-flex;
2553
+ max-width: 6rem; /* close to the content (icon + bar, or "Jobs"), so the fold is even */
2554
+ overflow: hidden;
2555
+ align-items: center;
2556
+ gap: 0.375rem;
2557
+ flex-shrink: 0;
2558
+ height: 30px;
2559
+ padding: 0 0.625rem;
2560
+ border: 0;
2561
+ background: transparent;
2562
+ color: var(--text-secondary);
2563
+ font: inherit;
2564
+ font-size: 0.75rem;
2565
+ font-weight: 500;
2566
+ white-space: nowrap;
2567
+ cursor: pointer;
2568
+ transition: background-color var(--mint-transition);
2569
+ }
2570
+
2571
+ .mint-topbar__run-slot--joined .mint-topbar__job {
2572
+ border-radius: calc(var(--radius-md) - 1px);
2573
+ }
2574
+
2575
+ .mint-topbar__run-slot--joined .mint-experiment-popover + .mint-topbar__job {
2576
+ border-left: 1px solid var(--border-color);
2577
+ border-radius: 0 calc(var(--radius-md) - 1px) calc(var(--radius-md) - 1px) 0;
2578
+ }
2579
+
2580
+ .mint-topbar__job--idle {
2581
+ height: 32px;
2582
+ border: 1px solid var(--border-color);
2583
+ border-radius: var(--radius-md);
2584
+ background: var(--bg-card);
2585
+ }
2586
+
2587
+ .mint-topbar__job--idle:hover,
2588
+ .mint-topbar__job--neutral:hover {
2589
+ background: var(--bg-hover);
2590
+ }
2591
+
2592
+ .mint-topbar__job:focus-visible {
2593
+ outline: none;
2594
+ box-shadow: inset var(--focus-ring);
2595
+ }
2596
+
2597
+ .mint-topbar__job--primary { background: var(--color-primary-soft); color: var(--_ink-primary); }
2598
+ .mint-topbar__job--warning { background: var(--mint-warning-bg); color: var(--mint-warning-text); }
2599
+ .mint-topbar__job--success { background: var(--mint-success-bg); color: color-mix(in srgb, var(--mint-success) 50%, var(--text-primary)); }
2600
+ .mint-topbar__job--error { background: var(--mint-error-bg); color: var(--_ink-error); }
2601
+
2602
+ .mint-topbar__job--primary:hover,
2603
+ .mint-topbar__job--warning:hover,
2604
+ .mint-topbar__job--success:hover,
2605
+ .mint-topbar__job--error:hover {
2606
+ filter: brightness(0.97);
2607
+ }
2608
+
2609
+ .mint-topbar__job-icon {
2610
+ flex-shrink: 0;
2611
+ }
2612
+
2613
+ .mint-topbar__job-icon--spin {
2614
+ animation: mint-topbar-job-spin 1s linear infinite;
2615
+ }
2616
+
2617
+ @keyframes mint-topbar-job-spin {
2618
+ to { transform: rotate(360deg); }
2619
+ }
2620
+
2621
+ .mint-topbar__job-bar {
2622
+ width: 2rem;
2623
+ height: 4px;
2624
+ border-radius: 2px;
2625
+ background: var(--border-color);
2626
+ overflow: hidden;
2627
+ }
2628
+
2629
+ .mint-topbar__job-bar > span {
2630
+ display: block;
2631
+ height: 100%;
2632
+ background: var(--color-primary);
2633
+ transition: width var(--mint-transition);
2634
+ }
2635
+
2636
+ /* Enter and leave: the job grows in from zero width and folds back out. */
2637
+ .mint-topbar-job-enter-active,
2638
+ .mint-topbar-job-leave-active {
2639
+ transition:
2640
+ max-width 200ms ease,
2641
+ padding 200ms ease,
2642
+ opacity 150ms ease;
2643
+ }
2644
+
2645
+ .mint-topbar-job-enter-from,
2646
+ .mint-topbar-job-leave-to {
2647
+ max-width: 0;
2648
+ padding-inline: 0;
2649
+ opacity: 0;
2650
+ }
2651
+
2652
+ /* Screen-reader only: announces status changes of the shown job. */
2653
+ .mint-topbar__job-status {
2654
+ position: absolute;
2655
+ width: 1px;
2656
+ height: 1px;
2657
+ overflow: hidden;
2658
+ clip-path: inset(50%);
2659
+ white-space: nowrap;
2660
+ }
2506
2661
  /* BaseButton Component Styles */
2507
2662
 
2508
2663
  .mint-button {
@@ -2655,6 +2810,14 @@ button, input, select, textarea {
2655
2810
  height: 1.25rem;
2656
2811
  }
2657
2812
 
2813
+ /* Flex centring centres the line box, and Geist's ascender puts the caps
2814
+ about 1.6px above the middle. Trim the text box to cap height and baseline
2815
+ so the caps sit on the centre line. Browsers without text-box keep the
2816
+ untrimmed box. */
2817
+ .mint-button__label {
2818
+ text-box: trim-both cap alphabetic;
2819
+ }
2820
+
2658
2821
  /* Spinner */
2659
2822
  .mint-button__spinner {
2660
2823
  animation: mint-button-spin 1s linear infinite;
@@ -16785,13 +16948,26 @@ button.mint-unit-input__unit:focus-visible {
16785
16948
  }
16786
16949
 
16787
16950
  /* Footer with clear selection */
16951
+ .mint-experiment-selector__description {
16952
+ padding: 0 1.25rem 0.75rem;
16953
+ font-size: 0.8125rem;
16954
+ color: var(--text-secondary);
16955
+ }
16956
+
16788
16957
  .mint-experiment-selector__footer {
16789
16958
  display: flex;
16959
+ align-items: center;
16960
+ gap: 0.75rem;
16790
16961
  justify-content: flex-start;
16791
16962
  padding: 0.5rem 1.25rem 0.75rem;
16792
16963
  border-top: 1px solid var(--border-light);
16793
16964
  }
16794
16965
 
16966
+ .mint-experiment-selector__footer-slot {
16967
+ flex: 1;
16968
+ min-width: 0;
16969
+ }
16970
+
16795
16971
  .mint-experiment-selector__clear-btn {
16796
16972
  padding: 0.25rem 0;
16797
16973
  border: none;
@@ -17332,54 +17508,79 @@ button.mint-unit-input__unit:focus-visible {
17332
17508
  animation: none;
17333
17509
  }
17334
17510
  }
17335
- /* AppTopBar page selector — left-side route/page dropdown.
17336
- Trigger speaks the field language (5a): 36px (the identity tile height), hover changes the background
17337
- only, open = field focus, inline 12px chevron. The menu keeps the 1.2 panel
17338
- (own card, tinted active row) rather than .mint-popover + .mint-menu-item. */
17511
+ /* AppTopBar page selector — design v2 option C: "<plugin> / <page>" as one switcher.
17512
+ The crumb holds the plugin name, a slash and the tinted 32px trigger. The menu keeps its own
17513
+ card (not .mint-popover): a "<plugin> pages" title, then one row per page with its hint and number key. */
17514
+
17515
+ /* Shrinks with the bar: the plugin name and the page label truncate instead of overlapping the nav. */
17516
+ .mint-page-selector__crumb {
17517
+ display: inline-flex;
17518
+ align-items: center;
17519
+ gap: 0.375rem;
17520
+ min-width: 0;
17521
+ flex-shrink: 1;
17522
+ }
17339
17523
 
17340
- /* Shrinks down to its inline min-width (11.25rem) so a crowded bar truncates the label instead of overlapping the nav. */
17524
+ .mint-page-selector__plugin {
17525
+ min-width: 0;
17526
+ font-size: 0.875rem;
17527
+ font-weight: 600;
17528
+ color: var(--text-primary);
17529
+ white-space: nowrap;
17530
+ overflow: hidden;
17531
+ text-overflow: ellipsis;
17532
+ }
17533
+
17534
+ .mint-page-selector__slash {
17535
+ flex-shrink: 0;
17536
+ font-size: 1.125rem;
17537
+ font-weight: 300;
17538
+ line-height: 1;
17539
+ color: var(--text-muted);
17540
+ }
17541
+
17542
+ /* Anchors the menu under the trigger, not under the plugin name. */
17341
17543
  .mint-page-selector {
17342
17544
  position: relative;
17343
- flex-shrink: 1;
17545
+ display: flex;
17546
+ min-width: 0;
17344
17547
  }
17345
17548
 
17346
17549
  .mint-page-selector__trigger {
17347
17550
  display: inline-flex;
17348
17551
  align-items: center;
17349
- gap: 0.5rem;
17350
- width: 100%;
17351
- height: 2.25rem;
17352
- padding: 0 0.5rem 0 0.4375rem;
17353
- border: 1px solid var(--border-color);
17354
- background: var(--bg-card);
17552
+ gap: 0.375rem;
17553
+ min-width: 0;
17554
+ max-width: 100%;
17555
+ height: 2rem;
17556
+ padding: 0 0.5rem 0 0.375rem;
17557
+ border: 0;
17558
+ background: var(--color-primary-soft);
17355
17559
  color: var(--text-primary);
17356
17560
  border-radius: var(--radius-md);
17357
17561
  font-size: 0.8125rem;
17358
- font-weight: 500;
17562
+ font-weight: 600;
17359
17563
  font-family: inherit;
17360
17564
  cursor: pointer;
17361
17565
  transition:
17362
17566
  background-color var(--mint-transition),
17363
- border-color var(--mint-transition),
17364
17567
  box-shadow var(--mint-transition);
17365
17568
  }
17366
17569
 
17367
- .mint-page-selector__trigger:hover:not(.mint-page-selector__trigger--open) {
17368
- background: var(--bg-hover);
17570
+ .mint-page-selector__trigger:hover {
17571
+ background: color-mix(in srgb, var(--color-primary) 16%, transparent);
17369
17572
  }
17370
17573
 
17371
- .mint-page-selector__trigger:focus-visible,
17372
- .mint-page-selector__trigger--open {
17574
+ .mint-page-selector__trigger:focus-visible {
17373
17575
  outline: none;
17374
- border-color: var(--color-primary);
17375
- box-shadow: var(--focus-ring-soft);
17576
+ box-shadow: var(--focus-ring-offset);
17376
17577
  }
17377
17578
 
17378
17579
  /* Page icon tile is neutral; the plugin carries the color. */
17379
17580
  .mint-page-selector__icon {
17380
17581
  width: 1.25rem;
17381
17582
  height: 1.25rem;
17382
- border-radius: var(--radius-sm);
17583
+ border-radius: var(--radius);
17383
17584
  background: var(--bg-tertiary);
17384
17585
  color: var(--text-secondary-strong);
17385
17586
  display: grid;
@@ -17400,7 +17601,7 @@ button.mint-unit-input__unit:focus-visible {
17400
17601
  .mint-page-selector__trigger-metadata-icon.mint-plugin-icon--sm {
17401
17602
  width: 1.25rem;
17402
17603
  height: 1.25rem;
17403
- border-radius: var(--radius-sm);
17604
+ border-radius: var(--radius);
17404
17605
  }
17405
17606
 
17406
17607
  .mint-page-selector__icon-fallback {
@@ -17410,7 +17611,6 @@ button.mint-unit-input__unit:focus-visible {
17410
17611
  }
17411
17612
 
17412
17613
  .mint-page-selector__label {
17413
- flex: 1;
17414
17614
  min-width: 0;
17415
17615
  text-align: left;
17416
17616
  white-space: nowrap;
@@ -17418,7 +17618,6 @@ button.mint-unit-input__unit:focus-visible {
17418
17618
  text-overflow: ellipsis;
17419
17619
  }
17420
17620
 
17421
- /* The chevron sits inline; the wrap no longer draws a tile. */
17422
17621
  .mint-page-selector__chevron-wrap {
17423
17622
  display: inline-flex;
17424
17623
  color: var(--text-secondary);
@@ -17435,38 +17634,46 @@ button.mint-unit-input__unit:focus-visible {
17435
17634
  transform: rotate(180deg);
17436
17635
  }
17437
17636
 
17637
+ /* max-height: 8 two-line hint rows (8 x 68px) + title (~25px) + padding (8px) = ~577px; a 9th row scrolls. A short window caps it. */
17438
17638
  .mint-page-selector__menu {
17439
17639
  position: absolute;
17640
+ box-sizing: border-box;
17440
17641
  top: calc(100% + 0.375rem);
17441
17642
  left: 0;
17442
- width: 16.25rem;
17643
+ width: 18.75rem;
17644
+ max-height: min(36.25rem, calc(100vh - 6rem));
17645
+ overflow-y: auto;
17443
17646
  background: var(--bg-card);
17444
17647
  border: 1px solid var(--border-color);
17445
17648
  border-radius: var(--radius-lg);
17446
17649
  box-shadow: var(--shadow-md);
17447
- padding: 0.375rem;
17650
+ padding: 0.25rem;
17448
17651
  z-index: 50;
17449
17652
  }
17450
17653
 
17654
+ /* The mockup's 10px uppercase eyebrow breaks rules 2a (no uppercase) and 8d (UI text >= 11px): 11px, sentence case. */
17451
17655
  .mint-page-selector__menu-title {
17452
- padding: 0.375rem 0.625rem 0.5rem;
17453
- font-size: 0.75rem;
17656
+ padding: 0.375rem 0.5rem 0.25rem;
17657
+ font-family: var(--font-mono);
17658
+ font-size: 0.6875rem;
17454
17659
  font-weight: 500;
17455
- color: var(--text-secondary);
17660
+ letter-spacing: 0.06em;
17661
+ color: var(--text-muted);
17456
17662
  }
17457
17663
 
17458
17664
  .mint-page-selector__item {
17459
17665
  display: flex;
17460
- align-items: center;
17666
+ box-sizing: border-box;
17667
+ align-items: flex-start;
17461
17668
  gap: 0.625rem;
17462
17669
  width: 100%;
17463
- padding: 0.5rem 0.625rem;
17670
+ padding: 0.5rem;
17464
17671
  border: 0;
17465
17672
  background: transparent;
17466
- border-radius: 0.4375rem;
17673
+ border-radius: var(--radius);
17467
17674
  color: var(--text-primary);
17468
17675
  font-size: 0.8125rem;
17469
- font-weight: 500;
17676
+ line-height: 1.4;
17470
17677
  font-family: inherit;
17471
17678
  text-align: left;
17472
17679
  text-decoration: none;
@@ -17474,13 +17681,22 @@ button.mint-unit-input__unit:focus-visible {
17474
17681
  transition: background-color var(--mint-transition);
17475
17682
  }
17476
17683
 
17477
- .mint-page-selector__item:hover:not(.mint-page-selector__item--disabled) {
17684
+ /* A row without a hint has one line: centre it on the icon tile. */
17685
+ .mint-page-selector__item:not(:has(.mint-page-selector__item-hint)) {
17686
+ align-items: center;
17687
+ }
17688
+
17689
+ .mint-page-selector__item:hover:not(.mint-page-selector__item--disabled):not(.mint-page-selector__item--active) {
17478
17690
  background: var(--bg-hover);
17479
17691
  }
17480
17692
 
17693
+ .mint-page-selector__item:focus-visible {
17694
+ outline: 2px solid var(--color-primary);
17695
+ outline-offset: -2px;
17696
+ }
17697
+
17481
17698
  .mint-page-selector__item--active {
17482
- background: var(--bg-tertiary);
17483
- font-weight: 600;
17699
+ background: var(--color-primary-soft);
17484
17700
  }
17485
17701
 
17486
17702
  .mint-page-selector__item--disabled {
@@ -17489,9 +17705,9 @@ button.mint-unit-input__unit:focus-visible {
17489
17705
  }
17490
17706
 
17491
17707
  .mint-page-selector__item-icon {
17492
- width: 1.375rem;
17493
- height: 1.375rem;
17494
- border-radius: 0.3125rem;
17708
+ width: 1.75rem;
17709
+ height: 1.75rem;
17710
+ border-radius: var(--radius-md);
17495
17711
  background: var(--bg-tertiary);
17496
17712
  color: var(--text-secondary);
17497
17713
  display: grid;
@@ -17499,6 +17715,10 @@ button.mint-unit-input__unit:focus-visible {
17499
17715
  flex-shrink: 0;
17500
17716
  }
17501
17717
 
17718
+ .mint-page-selector__item-icon .mint-page-selector__icon-fallback {
17719
+ font-size: 0.8125rem;
17720
+ }
17721
+
17502
17722
  .mint-page-selector__item--active .mint-page-selector__item-icon {
17503
17723
  background: var(--color-primary-soft);
17504
17724
  color: var(--color-primary);
@@ -17511,24 +17731,55 @@ button.mint-unit-input__unit:focus-visible {
17511
17731
  }
17512
17732
 
17513
17733
  .mint-page-selector__item-icon svg {
17514
- width: 0.8125rem;
17515
- height: 0.8125rem;
17734
+ width: 0.9375rem;
17735
+ height: 0.9375rem;
17516
17736
  }
17517
17737
 
17518
17738
  .mint-page-selector__metadata-icon.mint-plugin-icon--sm {
17519
- width: 1.375rem;
17520
- height: 1.375rem;
17521
- border-radius: 0.3125rem;
17739
+ width: 1.75rem;
17740
+ height: 1.75rem;
17741
+ border-radius: var(--radius-md);
17522
17742
  }
17523
17743
 
17524
- .mint-page-selector__item-label {
17744
+ .mint-page-selector__item-text {
17525
17745
  flex: 1;
17526
17746
  min-width: 0;
17747
+ display: grid;
17748
+ gap: 1px;
17749
+ }
17750
+
17751
+ .mint-page-selector__item-label {
17752
+ font-weight: 600;
17527
17753
  overflow: hidden;
17528
17754
  text-overflow: ellipsis;
17529
17755
  white-space: nowrap;
17530
17756
  }
17531
17757
 
17758
+ /* --_ink-primary is --color-primary-hover in light mode and stays legible in dark mode. */
17759
+ .mint-page-selector__item--active .mint-page-selector__item-label {
17760
+ color: var(--_ink-primary);
17761
+ }
17762
+
17763
+ .mint-page-selector__item-hint {
17764
+ font-size: 0.75rem;
17765
+ line-height: 1.35;
17766
+ color: var(--text-secondary);
17767
+ }
17768
+
17769
+ /* 11px, the rule 8d floor (the mockup has 10.5px). */
17770
+ .mint-page-selector__item-key {
17771
+ flex-shrink: 0;
17772
+ margin-top: 0.125rem;
17773
+ padding: 0 0.25rem;
17774
+ border: 1px solid var(--border-color);
17775
+ border-radius: var(--radius);
17776
+ font-family: var(--font-mono);
17777
+ font-size: 0.6875rem;
17778
+ font-weight: 500;
17779
+ line-height: 1rem;
17780
+ color: var(--text-muted);
17781
+ }
17782
+
17532
17783
  @media (prefers-reduced-motion: reduce) {
17533
17784
  .mint-page-selector__trigger,
17534
17785
  .mint-page-selector__chevron {
@@ -3,7 +3,7 @@ export type * from './generated-ui';
3
3
  export type { AnalysisArtifactStatus, AnalysisArtifactStatusFilter, AnalysisArtifactSummary, AnalysisArtifactDetail, AnalysisArtifactListResponse, AnalysisArtifactTarget, AnalysisArtifactMetadataUpdate, ArtifactSaveMode, ArtifactFileSource, JsonArtifactSavePayload, FileArtifactCreatePayload, FileArtifactUpdatePayload, HandlerFileArtifactCreatePayload, HandlerFileArtifactUpdatePayload, ArtifactSavePayload, HandlerArtifactSavePayload, ArtifactSaveDialogPayload, ArtifactSaveResult, ArtifactSaveHandler, HandlerArtifactSaveHandler, ArtifactSaveDialogHandler, } from './analysisArtifactTypes';
4
4
  export { ANALYSIS_FILE_ARTIFACT_SCHEMA } from './analysisArtifactTypes';
5
5
  export type { FileBrowserLocation, FileBrowserSortKey, FileDirectoryListing, FileDirectoryTree, FileEntry, FileEntryKind, FilePathCrumb, FileSearchResult, FileSelection, ServerMount, } from './fileBrowserTypes';
6
- export type { JobListPayload, JobProgress, JobSnapshotPayload, JobState, JobStateInput, JobStatus, JobStreamData, } from './jobs';
6
+ export type { JobListPayload, JobProgress, JobSnapshotPayload, JobState, JobStateInput, JobStatus, JobStreamData, TopBarJob, } from './jobs';
7
7
  export type { InjectionMetricSeries, InstrumentAlert, InstrumentAlertLevel, InstrumentAlertList, InstrumentBadgeState, InstrumentLiveProgress, InstrumentLiveStatus, InstrumentState, InstrumentStatus, InstrumentStatusReporter, SampleInfo, SampleInfo as InstrumentSampleInfo, SequenceProgress, StatusPanel, } from './instrument';
8
8
  export type { AccessAudience, AccessAudienceInput, AccessPolicy, AccessControlled, PermissionUser, RoleInfo, } from '../permissions';
9
9
  export type { FormFieldType, FieldCondition, FieldValidation, FormFieldSchema, FormOptionInput, FormSectionSchema, FormStepSchema, FormSchema, FieldEnhancement, FormEnhancements, UseFormBuilderReturn, } from './form-builder';
@@ -53,3 +53,12 @@ export interface JobSnapshotPayload {
53
53
  jobs: JobStateInput[];
54
54
  }
55
55
  export type JobStreamData = JobStateInput | JobSnapshotPayload;
56
+ /** What the top-bar run slot shows for the viewer's own job. The plugin picks the job. */
57
+ export interface TopBarJob {
58
+ /** Lifecycle of the shown job; sets the icon and the tone. */
59
+ status: JobStatus;
60
+ /** Tooltip and accessible name, e.g. "Extracting", "Saved to EXP-0142". Not shown as text. */
61
+ label: string;
62
+ /** 0-100; drawn as a small bar after the icon. */
63
+ percent?: number | null;
64
+ }