Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"url": "git+https://github.com/opencor/webapp.git"
},
"type": "module",
"version": "0.20260610.2",
"version": "0.20260610.3",
"engines": {
"bun": ">=1.2.0"
},
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
},
"./style.css": "./dist/opencor.css"
},
"version": "0.20260610.2",
"version": "0.20260610.3",
"libopencorVersion": "0.20260604.0",
"scripts": {
"build": "vite build && bun scripts/generate.version.js",
Expand Down
17 changes: 17 additions & 0 deletions src/renderer/src/common/vueCommon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,20 @@ export const trackElementHeight = (

return stopTrackingElementHeight;
};

// A composable that provides the `.opencor` element as an append target for overlays.
// Note: this is needed when OpenCOR is embedded as a Vue 3 component in a host app that uses full-screen mode. In such
// a case, the Fullscreen API only renders the full-screen element and its descendants, so teleporting to
// `document.body` makes overlays invisible. Instead, teleporting to `.opencor` means that overlays are visible in
// full-screen mode. And, since `.opencor` is a child of the full-screen element, they are also visible in normal
// mode.

export const useAppendTarget = () => {
const appendTarget = vue.shallowRef<HTMLElement | undefined>(undefined);

vue.onMounted(() => {
appendTarget.value = (document.querySelector('.opencor') as HTMLElement | null) ?? undefined;
});

return appendTarget;
};
11 changes: 10 additions & 1 deletion src/renderer/src/components/OpenCOR.vue
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,16 @@ vue.watch(
// VueTippy.

if (crtVueAppInstance && crtGlobalProperties && !crtGlobalProperties[vueTippyInstalledFlag]) {
crtVueAppInstance.use(dependencies._vueTippy);
// Append Tippy tooltips to `.opencor` rather than `document.body` so that they stay within the component's
// stacking context. This is critical when OpenCOR is embedded as a Vue 3 component in a host app in full-screen
// mode (`document.body` can be hidden behind the host's full-screen container, whereas `.opencor` lives inside
// it).

crtVueAppInstance.use(dependencies._vueTippy, {
defaultProps: {
appendTo: () => document.querySelector('.opencor') || document.body
}
});

crtGlobalProperties[vueTippyInstalledFlag] = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@
optionValue="value"
class="w-full"
size="small"
:appendTo="issuesContainer"
/>
<label>Type</label>
</FloatLabel>
Expand Down Expand Up @@ -343,6 +344,7 @@
size="small"
filter filterMode="lenient"
:options="editableModelParameters"
:appendTo="issuesContainer"
/>
<label>Model parameter</label>
</FloatLabel>
Expand Down Expand Up @@ -417,6 +419,7 @@
size="small"
filter filterMode="lenient"
:options="allModelParameters"
:appendTo="issuesContainer"
/>
<label>Model parameter</label>
</FloatLabel>
Expand Down Expand Up @@ -562,6 +565,7 @@
size="small"
filter filterMode="lenient"
:options="externalDataSeries(externalDataFile)"
:appendTo="issuesContainer"
/>
<label>External data</label>
</FloatLabel>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
:options="standardParameters"
size="small"
class="w-full"
:appendTo="appendTarget"
@change="updatePlot()"
/>
</Fieldset>
Expand All @@ -73,6 +74,7 @@
:options="standardParameters"
size="small"
class="w-full"
:appendTo="appendTarget"
@change="updatePlot()"
/>
</Fieldset>
Expand Down Expand Up @@ -234,7 +236,7 @@
@ok="onInteractiveSettingsOk"
@close="interactiveSettingsVisible = false"
/>
<Popover ref="interactiveRunColorPopoverRef" appendTo="self">
<Popover ref="interactiveRunColorPopoverRef" :appendTo="appendTarget">
<div class="flex gap-2">
<button class="color-swatch cursor-pointer w-6 h-6 outline-2 outline-transparent rounded-md hover:scale-[1.15]"
v-for="(name, color) in colors.PALETTE" :key="color"
Expand All @@ -260,6 +262,7 @@ import type { IOpenCORExternalDataEvent, IOpenCORSimulationDataEvent } from '../
import * as colors from '../../common/colors';
import * as common from '../../common/common';
import * as dependencies from '../../common/dependencies';
import * as vueCommon from '../../common/vueCommon';
import * as externalData from '../../common/externalData';
import * as locCommon from '../../common/locCommon';
import * as locApi from '../../libopencor/locApi';
Expand Down Expand Up @@ -612,6 +615,7 @@ let interactiveTrackedRunId = 0;
const interactiveRunColorPopoverIndex = vue.ref<number>(-1);
const interactiveRunColorPopoverRef = vue.ref<InstanceType<typeof Popover> | undefined>();
const interactiveGraphPanelRefs = vue.ref<Record<number, InstanceType<typeof GraphPanelWidget> | undefined>>({});
const appendTarget = vueCommon.useAppendTarget();
const interactiveCompData = vue.computed<IGraphPanelData[]>(() => {
// Combine the live data with the data from the tracked runs.

Expand Down
3 changes: 2 additions & 1 deletion src/renderer/src/components/widgets/GraphPanelWidget.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div class="flex flex-row h-full">
<div v-if="showMarker" class="w-0.75 bg-primary" />
<div ref="mainDivRef" class="grow h-full" @contextmenu="onContextMenu" />
<ContextMenu ref="contextMenuRef" :model="contextMenuItems" />
<ContextMenu ref="contextMenuRef" :model="contextMenuItems" :appendTo="appendTarget" />
</div>
</template>

Expand Down Expand Up @@ -127,6 +127,7 @@ const mainDivRef = vue.ref<HTMLElement | null>(null);
const margins = vue.ref<IGraphPanelMargins>({ left: -1, right: -1 });
const theme = vueCommon.useTheme();
const contextMenuRef = vue.ref<InstanceType<typeof ContextMenu> | null>(null);
const appendTarget = vueCommon.useAppendTarget();
const progressMessage = vue.inject<IProgressMessage>('progressMessage');
let updatingMargins = false;
let plotIsReady = false;
Expand Down
4 changes: 4 additions & 0 deletions src/renderer/src/components/widgets/InputWidget.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
:options="possibleValues"
optionLabel="name"
@change="selectChange"
:appendTo="appendTarget"
class="w-full"
size="small"
/>
Expand All @@ -32,6 +33,7 @@
<script setup lang="ts">
import * as vue from 'vue';

import * as vueCommon from '../../common/vueCommon';
import type * as locApi from '../../libopencor/locApi';

const value = defineModel<number>({ required: true });
Expand All @@ -50,6 +52,8 @@ let oldValue = value.value;
const discreteValue = vue.ref<locApi.IUiJsonDiscreteInputPossibleValue | undefined>(
props.possibleValues?.find((possibleValue) => possibleValue.value === value.value)
);
const appendTarget = vueCommon.useAppendTarget();

const compStepValue = vue.computed<number>(() => {
if (props.stepValue !== undefined) {
return props.stepValue;
Expand Down
Loading