@morscherlab/mint-sdk 1.4.0-beta.15 → 1.4.0-beta.17

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 (36) hide show
  1. package/dist/{AppSidebar-Bi8g9mRt.js → AppSidebar-CB0-RQ4m.js} +876 -114
  2. package/dist/AppSidebar-CB0-RQ4m.js.map +1 -0
  3. package/dist/{SettingsModal-jra_2u0o.js → SettingsModal-CoZK3EDN.js} +2 -2
  4. package/dist/{SettingsModal-jra_2u0o.js.map → SettingsModal-CoZK3EDN.js.map} +1 -1
  5. package/dist/__tests__/components/AppTopBarOnboarding.test.d.ts +1 -0
  6. package/dist/__tests__/composables/useOnboarding.test.d.ts +1 -0
  7. package/dist/components/AppTopBar.vue.d.ts +4 -4
  8. package/dist/components/internal/AppTopBarOnboardingInternal.vue.d.ts +7 -0
  9. package/dist/components/internal/OnboardingLayerInternal.vue.d.ts +7 -0
  10. package/dist/composables/useOnboarding.d.ts +119 -0
  11. package/dist/index.js +5 -5
  12. package/dist/{install-Bx_6KwJA.js → install-BKgb5qZw.js} +5 -5
  13. package/dist/{install-Bx_6KwJA.js.map → install-BKgb5qZw.js.map} +1 -1
  14. package/dist/install.js +1 -1
  15. package/dist/{runtime-BJvGms6h.js → runtime-Cz1GJa_O.js} +2 -2
  16. package/dist/{runtime-BJvGms6h.js.map → runtime-Cz1GJa_O.js.map} +1 -1
  17. package/dist/runtime.js +2 -2
  18. package/dist/{shell-Czyrzk7l.js → shell-kq9p4VsX.js} +7 -2
  19. package/dist/{shell-Czyrzk7l.js.map → shell-kq9p4VsX.js.map} +1 -1
  20. package/dist/shell.d.ts +1 -0
  21. package/dist/shell.js +3 -3
  22. package/dist/styles.css +385 -0
  23. package/package.json +1 -1
  24. package/src/__tests__/components/AppTopBarOnboarding.test.ts +160 -0
  25. package/src/__tests__/composables/useOnboarding.test.ts +317 -0
  26. package/src/__tests__/styles/v2AuditRules.test.ts +8 -0
  27. package/src/components/AppTopBar.onboarding.story.vue +69 -0
  28. package/src/components/AppTopBar.vue +11 -2
  29. package/src/components/internal/AppTopBarOnboardingInternal.vue +172 -0
  30. package/src/components/internal/OnboardingLayerInternal.vue +173 -0
  31. package/src/composables/useOnboarding.ts +465 -0
  32. package/src/shell.ts +17 -0
  33. package/src/styles/components/onboarding.css +368 -0
  34. package/src/styles/index.css +1 -0
  35. package/src/styles/variables.css +16 -0
  36. package/dist/AppSidebar-Bi8g9mRt.js.map +0 -1
package/dist/runtime.js CHANGED
@@ -2,7 +2,7 @@ import { i as AuthenticationRequiredError, o as useApi } from "./experiment-DyO5
2
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
3
  import { A as createGeneratedAnalysisTransport, D as GeneratedPathInput_default, _ as getFieldRegistryEntry, j as useJobsEndpoint, v as getTypeDefault } from "./useListReorder-C_8RYeVP.js";
4
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";
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-Cz1GJa_O.js";
6
+ import { D as useControlSchema, E as getControlDefaults, F as getDefaultControlView, M as controlsTo, O as controlBindings, T as defineControls, d as useForm, l as useFormBuilder, u as evaluateCondition, w as defineControlComponentBindings } from "./AppSidebar-CB0-RQ4m.js";
7
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
1
  import { i as useEventListener, o as __exportAll, r as useFocusTrap } from "./useDropdownState-Bb2N4m40.js";
2
2
  import { E as useMenuKeyboard, H as useListSelection, R as useRovingFocus, U as useSelectionLimit } from "./records-B4yl2oIu.js";
3
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";
4
+ import { C as usePluginWorkspace, S as AppLayout_default, _ as provideOnboarding, f as AppTopBar_default, g as defineOnboarding, h as ONBOARDING_KEY, m as ANCHOR_WAIT_MS, t as AppSidebar_default, v as useOnboarding } from "./AppSidebar-CB0-RQ4m.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";
@@ -167,12 +167,16 @@ function useManualLayoutResize(options) {
167
167
  //#endregion
168
168
  //#region src/shell.ts
169
169
  var shell_exports = /* @__PURE__ */ __exportAll({
170
+ ANCHOR_WAIT_MS: () => ANCHOR_WAIT_MS,
170
171
  AppLayout: () => AppLayout_default,
171
172
  AppSidebar: () => AppSidebar_default,
172
173
  AppTopBar: () => AppTopBar_default,
173
174
  LayoutResizeHandle: () => LayoutResizeHandle_default,
175
+ ONBOARDING_KEY: () => ONBOARDING_KEY,
174
176
  REORDER_ANNOUNCER_STYLE: () => REORDER_ANNOUNCER_STYLE,
175
177
  compareSortValues: () => compareSortValues,
178
+ defineOnboarding: () => defineOnboarding,
179
+ provideOnboarding: () => provideOnboarding,
176
180
  reorderList: () => reorderList,
177
181
  resizedLeadingPanelWidth: () => resizedLeadingPanelWidth,
178
182
  resizedTrailingPanelWidth: () => resizedTrailingPanelWidth,
@@ -185,6 +189,7 @@ var shell_exports = /* @__PURE__ */ __exportAll({
185
189
  useListSelection: () => useListSelection,
186
190
  useManualLayoutResize: () => useManualLayoutResize,
187
191
  useMenuKeyboard: () => useMenuKeyboard,
192
+ useOnboarding: () => useOnboarding,
188
193
  usePluginWorkspace: () => usePluginWorkspace,
189
194
  useReorderAnnouncer: () => useReorderAnnouncer,
190
195
  useRovingFocus: () => useRovingFocus,
@@ -194,4 +199,4 @@ var shell_exports = /* @__PURE__ */ __exportAll({
194
199
  //#endregion
195
200
  export { useManualLayoutResize as a, resizedVerticalSplitPercent as i, resizedLeadingPanelWidth as n, LayoutResizeHandle_default as o, resizedTrailingPanelWidth as r, shell_exports as t };
196
201
 
197
- //# sourceMappingURL=shell-Czyrzk7l.js.map
202
+ //# sourceMappingURL=shell-kq9p4VsX.js.map
@@ -1 +1 @@
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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"}
1
+ {"version":3,"file":"shell-kq9p4VsX.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\n// Onboarding: tours, the Getting started checklist and what's-new hints\nexport {\n ANCHOR_WAIT_MS,\n defineOnboarding,\n provideOnboarding,\n useOnboarding,\n ONBOARDING_KEY,\n type OnboardingActiveStep,\n type OnboardingDefinition,\n type OnboardingNews,\n type OnboardingState,\n type OnboardingStep,\n type OnboardingTask,\n type OnboardingTour,\n type ProvideOnboardingOptions,\n} from './composables/useOnboarding'\n"],"mappings":"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"}
package/dist/shell.d.ts CHANGED
@@ -14,3 +14,4 @@ export { useListSelection, type ListSelectionSource, type ListSelectionValue, ty
14
14
  export { useExpansionSet, type ExpansionSetSource, type UseExpansionSetOptions, type UseExpansionSetReturn, } from './composables/useExpansionSet';
15
15
  export { compareSortValues, useSortedItems, type CompareSortValuesOptions, type SortComparator, type SortComparatorContext, type SortDescriptor, type SortedItemsSource, type SortOrder, type UseSortedItemsOptions, type UseSortedItemsReturn, } from './composables/useSortedItems';
16
16
  export { usePluginWorkspace, type PluginWorkspaceSlotsLike, type UsePluginWorkspaceOptions, type UsePluginWorkspaceReturn, } from './composables/usePluginWorkspace';
17
+ export { ANCHOR_WAIT_MS, defineOnboarding, provideOnboarding, useOnboarding, ONBOARDING_KEY, type OnboardingActiveStep, type OnboardingDefinition, type OnboardingNews, type OnboardingState, type OnboardingStep, type OnboardingTask, type OnboardingTour, type ProvideOnboardingOptions, } from './composables/useOnboarding';
package/dist/shell.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { i as useEventListener, r as useFocusTrap } from "./useDropdownState-Bb2N4m40.js";
2
2
  import { E as useMenuKeyboard, H as useListSelection, R as useRovingFocus, U as useSelectionLimit } from "./records-B4yl2oIu.js";
3
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";
4
+ import { C as usePluginWorkspace, S as AppLayout_default, _ as provideOnboarding, f as AppTopBar_default, g as defineOnboarding, h as ONBOARDING_KEY, m as ANCHOR_WAIT_MS, t as AppSidebar_default, v as useOnboarding } from "./AppSidebar-CB0-RQ4m.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-Czyrzk7l.js";
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 };
7
+ import { a as useManualLayoutResize, i as resizedVerticalSplitPercent, n as resizedLeadingPanelWidth, o as LayoutResizeHandle_default, r as resizedTrailingPanelWidth } from "./shell-kq9p4VsX.js";
8
+ export { ANCHOR_WAIT_MS, AppLayout_default as AppLayout, AppSidebar_default as AppSidebar, AppTopBar_default as AppTopBar, LayoutResizeHandle_default as LayoutResizeHandle, ONBOARDING_KEY, REORDER_ANNOUNCER_STYLE, compareSortValues, defineOnboarding, provideOnboarding, reorderList, resizedLeadingPanelWidth, resizedTrailingPanelWidth, resizedVerticalSplitPercent, useDebouncedWatch, useEventListener, useExpansionSet, useFocusTrap, useListReorder, useListSelection, useManualLayoutResize, useMenuKeyboard, useOnboarding, usePluginWorkspace, useReorderAnnouncer, useRovingFocus, useSelectionLimit, useSortedItems };
package/dist/styles.css CHANGED
@@ -701,6 +701,22 @@ body {
701
701
  transition: background-color 0.15s, color 0.15s;
702
702
  }
703
703
 
704
+ /* No page-level rubber-band bounce or pull-to-refresh; overflow: hidden does
705
+ not stop it. Panels still scroll, and their overscroll stops at their own
706
+ edge. A browser tab keeps the horizontal swipe for back and forward; an
707
+ installed PWA has no history swipe, so it drops both axes. */
708
+ html,
709
+ body {
710
+ overscroll-behavior-y: none;
711
+ }
712
+
713
+ @media (display-mode: standalone) {
714
+ html,
715
+ body {
716
+ overscroll-behavior: none;
717
+ }
718
+ }
719
+
704
720
  code, pre {
705
721
  font-family: var(--font-mono);
706
722
  }
@@ -5823,6 +5839,375 @@ button, input, select, textarea {
5823
5839
  }
5824
5840
  }
5825
5841
 
5842
+ /* Onboarding: the top-bar Help button and checklist chip, the Help panel,
5843
+ * the tour layer (scrim, hole, card) and the what's-new dots. */
5844
+
5845
+ :root {
5846
+ --mint-onboarding-scrim: rgba(15, 23, 42, 0.45);
5847
+ }
5848
+
5849
+ html.dark {
5850
+ --mint-onboarding-scrim: rgba(2, 6, 23, 0.62);
5851
+ }
5852
+
5853
+ /* ---- Top bar ---- */
5854
+
5855
+ .mint-onboarding-help {
5856
+ position: relative;
5857
+ display: inline-flex;
5858
+ align-items: center;
5859
+ gap: 0.375rem;
5860
+ }
5861
+
5862
+ .mint-topbar__settings-btn--open {
5863
+ background: var(--color-primary-soft);
5864
+ color: var(--_ink-primary);
5865
+ }
5866
+
5867
+ .mint-onboarding-help__chip {
5868
+ display: inline-flex;
5869
+ align-items: center;
5870
+ gap: 0.375rem;
5871
+ height: 2rem;
5872
+ padding: 0 0.625rem;
5873
+ border: 1px solid var(--border-color);
5874
+ border-radius: var(--radius-md);
5875
+ background: transparent;
5876
+ color: var(--text-primary);
5877
+ font: 500 0.8125rem/1 var(--font-sans);
5878
+ white-space: nowrap;
5879
+ cursor: pointer;
5880
+ transition: background-color var(--mint-transition), border-color var(--mint-transition);
5881
+ }
5882
+
5883
+ .mint-onboarding-help__chip:hover {
5884
+ background: var(--bg-hover);
5885
+ }
5886
+
5887
+ .mint-onboarding-help__chip--open {
5888
+ border-color: var(--color-primary);
5889
+ background: var(--color-primary-soft);
5890
+ color: var(--_ink-primary);
5891
+ }
5892
+
5893
+ .mint-onboarding-help__chip:focus-visible {
5894
+ outline: none;
5895
+ box-shadow: var(--focus-ring-offset);
5896
+ }
5897
+
5898
+ .mint-onboarding-help__count {
5899
+ color: var(--text-muted);
5900
+ font: 500 0.75rem/1 var(--font-mono);
5901
+ }
5902
+
5903
+ .mint-onboarding-help__bar {
5904
+ width: 1.75rem;
5905
+ height: 3px;
5906
+ border-radius: 2px;
5907
+ background: var(--bg-tertiary);
5908
+ overflow: hidden;
5909
+ }
5910
+
5911
+ .mint-onboarding-help__bar > span {
5912
+ display: block;
5913
+ height: 100%;
5914
+ background: var(--color-primary);
5915
+ transition: width var(--mint-transition);
5916
+ }
5917
+
5918
+ .mint-onboarding-help__badge {
5919
+ position: absolute;
5920
+ top: -4px;
5921
+ right: -4px;
5922
+ min-width: 16px;
5923
+ height: 16px;
5924
+ padding: 0 4px;
5925
+ box-sizing: border-box;
5926
+ border-radius: 8px;
5927
+ background: var(--color-primary);
5928
+ color: var(--text-on-accent);
5929
+ font: 600 11px/16px var(--font-sans);
5930
+ text-align: center;
5931
+ box-shadow: 0 0 0 2px var(--bg-card);
5932
+ }
5933
+
5934
+ /* ---- Help panel ---- */
5935
+
5936
+ .mint-onboarding-help__panel {
5937
+ position: fixed;
5938
+ z-index: 1000;
5939
+ width: 18rem;
5940
+ padding: 0 0 4px;
5941
+ overflow: hidden;
5942
+ }
5943
+
5944
+ .mint-onboarding-help__header {
5945
+ display: flex;
5946
+ align-items: center;
5947
+ justify-content: space-between;
5948
+ padding: 0.75rem 0.75rem 0.5rem;
5949
+ }
5950
+
5951
+ .mint-onboarding-help__heading {
5952
+ color: var(--text-secondary);
5953
+ font-size: 0.6875rem;
5954
+ font-weight: 600;
5955
+ }
5956
+
5957
+ .mint-onboarding-help__progress {
5958
+ height: 3px;
5959
+ margin: 0 0.75rem 0.25rem;
5960
+ border-radius: 2px;
5961
+ background: var(--bg-tertiary);
5962
+ overflow: hidden;
5963
+ }
5964
+
5965
+ .mint-onboarding-help__progress > span {
5966
+ display: block;
5967
+ height: 100%;
5968
+ background: var(--color-primary);
5969
+ transition: width var(--mint-transition);
5970
+ }
5971
+
5972
+ .mint-onboarding-help__todos {
5973
+ margin: 0;
5974
+ padding: 0;
5975
+ list-style: none;
5976
+ }
5977
+
5978
+ .mint-onboarding-help__todo {
5979
+ display: grid;
5980
+ grid-template-columns: 1rem 1fr auto;
5981
+ align-items: center;
5982
+ gap: 0.5rem;
5983
+ min-height: 1.875rem;
5984
+ padding: 0 0.75rem;
5985
+ color: var(--text-primary);
5986
+ font-size: 0.8125rem;
5987
+ }
5988
+
5989
+ .mint-onboarding-help__check {
5990
+ display: grid;
5991
+ place-items: center;
5992
+ width: 1rem;
5993
+ height: 1rem;
5994
+ box-sizing: border-box;
5995
+ border: 1.5px solid var(--border-color);
5996
+ border-radius: 50%;
5997
+ }
5998
+
5999
+ .mint-onboarding-help__todo--done .mint-onboarding-help__check {
6000
+ border: 0;
6001
+ background: var(--color-primary);
6002
+ color: var(--text-on-accent);
6003
+ }
6004
+
6005
+ .mint-onboarding-help__todo--done .mint-onboarding-help__todo-title {
6006
+ color: var(--text-muted);
6007
+ }
6008
+
6009
+ .mint-onboarding-help__link {
6010
+ padding: 0;
6011
+ border: 0;
6012
+ background: transparent;
6013
+ color: var(--_ink-primary);
6014
+ font-size: 0.75rem;
6015
+ font-weight: 500;
6016
+ white-space: nowrap;
6017
+ cursor: pointer;
6018
+ }
6019
+
6020
+ .mint-onboarding-help__link:hover {
6021
+ text-decoration: underline;
6022
+ }
6023
+
6024
+ .mint-onboarding-help__link:focus-visible {
6025
+ outline: none;
6026
+ border-radius: var(--radius-sm);
6027
+ box-shadow: var(--focus-ring-offset);
6028
+ }
6029
+
6030
+ .mint-onboarding-help__hide {
6031
+ display: block;
6032
+ text-align: left;
6033
+ margin: 0.25rem 0.75rem 0.5rem;
6034
+ color: var(--text-secondary);
6035
+ }
6036
+
6037
+ .mint-onboarding-help__section {
6038
+ padding: 0.625rem 0.75rem 0.25rem;
6039
+ border-top: 1px solid var(--border-color);
6040
+ color: var(--text-secondary);
6041
+ font-size: 0.6875rem;
6042
+ font-weight: 600;
6043
+ }
6044
+
6045
+ .mint-onboarding-help__icon {
6046
+ width: 0.8125rem;
6047
+ height: 0.8125rem;
6048
+ flex-shrink: 0;
6049
+ color: var(--text-muted);
6050
+ }
6051
+
6052
+ .mint-onboarding-help__panel > .mint-menu-item {
6053
+ width: calc(100% - 8px);
6054
+ margin: 0 4px;
6055
+ }
6056
+
6057
+ .mint-onboarding-help__new {
6058
+ margin-left: auto;
6059
+ padding: 3px 4px;
6060
+ border-radius: var(--radius-sm);
6061
+ background: var(--color-primary);
6062
+ color: var(--text-on-accent);
6063
+ font-size: 0.6875rem;
6064
+ font-weight: 600;
6065
+ line-height: 1;
6066
+ }
6067
+
6068
+ /* ---- Tour layer ---- */
6069
+
6070
+ .mint-onboarding {
6071
+ position: fixed;
6072
+ inset: 0;
6073
+ z-index: 1100;
6074
+ pointer-events: none;
6075
+ }
6076
+
6077
+ /* Takes every click outside the card. An advanceOn 'click' step cuts the hole out of it. */
6078
+ .mint-onboarding__blocker {
6079
+ position: absolute;
6080
+ inset: 0;
6081
+ pointer-events: auto;
6082
+ }
6083
+
6084
+ .mint-onboarding__hole {
6085
+ position: fixed;
6086
+ border-radius: var(--radius-lg);
6087
+ box-shadow: 0 0 0 2px var(--color-primary), 0 0 0 9999px var(--mint-onboarding-scrim);
6088
+ pointer-events: none;
6089
+ transition: left 200ms ease, top 200ms ease, width 200ms ease, height 200ms ease;
6090
+ }
6091
+
6092
+ .mint-onboarding__card {
6093
+ position: fixed;
6094
+ display: grid;
6095
+ gap: 0.5rem;
6096
+ box-sizing: border-box;
6097
+ width: 17rem;
6098
+ max-width: calc(100vw - 24px);
6099
+ padding: 0.875rem;
6100
+ border: 1px solid var(--border-color);
6101
+ border-radius: var(--radius-lg);
6102
+ background: var(--bg-card);
6103
+ box-shadow: var(--shadow-lg);
6104
+ color: var(--text-primary);
6105
+ pointer-events: auto;
6106
+ }
6107
+
6108
+ .mint-onboarding__card:focus {
6109
+ outline: none;
6110
+ }
6111
+
6112
+ .mint-onboarding__close {
6113
+ position: absolute;
6114
+ top: 0.5rem;
6115
+ right: 0.5rem;
6116
+ display: grid;
6117
+ place-items: center;
6118
+ width: 1.5rem;
6119
+ height: 1.5rem;
6120
+ padding: 0;
6121
+ border: 0;
6122
+ border-radius: var(--radius);
6123
+ background: transparent;
6124
+ color: var(--text-muted);
6125
+ cursor: pointer;
6126
+ }
6127
+
6128
+ .mint-onboarding__close:hover {
6129
+ background: var(--bg-hover);
6130
+ color: var(--text-primary);
6131
+ }
6132
+
6133
+ .mint-onboarding__close:focus-visible {
6134
+ outline: none;
6135
+ box-shadow: var(--focus-ring-offset);
6136
+ }
6137
+
6138
+ .mint-onboarding__title {
6139
+ margin: 0;
6140
+ padding-right: 1.5rem;
6141
+ font-size: 0.875rem;
6142
+ font-weight: 600;
6143
+ }
6144
+
6145
+ .mint-onboarding__body {
6146
+ margin: 0;
6147
+ color: var(--text-secondary);
6148
+ font-size: 0.8125rem;
6149
+ line-height: 1.45;
6150
+ }
6151
+
6152
+ .mint-onboarding__footer {
6153
+ display: flex;
6154
+ align-items: center;
6155
+ justify-content: flex-end;
6156
+ gap: 0.375rem;
6157
+ margin-top: 0.25rem;
6158
+ }
6159
+
6160
+ .mint-onboarding__count {
6161
+ color: var(--text-muted);
6162
+ font: 500 0.75rem/1.5rem var(--font-mono);
6163
+ margin-top: -0.375rem;
6164
+ }
6165
+
6166
+ /* Read by screen readers only. */
6167
+ .mint-onboarding__sr {
6168
+ position: absolute;
6169
+ width: 1px;
6170
+ height: 1px;
6171
+ overflow: hidden;
6172
+ clip-path: inset(50%);
6173
+ white-space: nowrap;
6174
+ }
6175
+
6176
+ .mint-onboarding__hint {
6177
+ margin-right: auto;
6178
+ color: var(--text-muted);
6179
+ font-size: 0.75rem;
6180
+ }
6181
+
6182
+ /* A dot at the top-right corner of an element with unseen news. */
6183
+ .mint-onboarding__dot {
6184
+ position: fixed;
6185
+ z-index: 40;
6186
+ width: 8px;
6187
+ height: 8px;
6188
+ padding: 0;
6189
+ border: 0;
6190
+ border-radius: 50%;
6191
+ background: var(--color-primary);
6192
+ box-shadow: 0 0 0 2px var(--bg-card);
6193
+ transform: translate(-50%, -50%);
6194
+ cursor: pointer;
6195
+ }
6196
+
6197
+ .mint-onboarding__dot:focus-visible {
6198
+ outline: none;
6199
+ box-shadow: var(--focus-ring-offset);
6200
+ }
6201
+
6202
+ @media (prefers-reduced-motion: reduce) {
6203
+ .mint-onboarding-help__chip,
6204
+ .mint-onboarding-help__bar > span,
6205
+ .mint-onboarding-help__progress > span,
6206
+ .mint-onboarding__hole {
6207
+ transition: none;
6208
+ }
6209
+ }
6210
+
5826
6211
  /* PlateEditor (SDK control refresh 7a).
5827
6212
  * Wells are WellPlate's (2b, 3a); this file owns the shell: tabs, toolbar, rail. */
5828
6213
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@morscherlab/mint-sdk",
3
- "version": "1.4.0-beta.15",
3
+ "version": "1.4.0-beta.17",
4
4
  "description": "MINT Platform SDK — Vue 3 components, composables, and types for plugin development. MINT = Mass-spec INtegrated Toolkit.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",