Merge branch '74-fix-sandbox-inline-sandbox-sizing-is-incorrect' into 'development'

Resolve "fix(Sandbox): Inline Sandbox sizing is incorrect"

Closes #74

See merge request GeneralProtocols/xo/stack!118
This commit is contained in:
Jim Hamill
2025-08-10 00:26:09 +00:00
3 changed files with 70 additions and 25 deletions
@@ -6,8 +6,9 @@
</template>
<script setup lang="ts">
import { ref, onMounted, watch } from 'vue';
import { ref, onMounted, watch, computed } from 'vue';
import loader, { Monaco } from '@monaco-editor/loader';
import { type editor } from 'monaco-editor';
import { ImportedLib } from '../utils/useXOCashLibs';
@@ -28,16 +29,26 @@ const code = defineModel<string>();
const monacoInstance = ref<Monaco | null>(null);
const editorContainer = ref<HTMLElement | null>(null);
const contentHeight = ref(100);
const editorHeight = computed(() => {
const codeHeight = contentHeight.value;
const height = Math.max(codeHeight, 100);
return height;
})
const emit = defineEmits<{
(e: 'execute'): void;
}>();
defineExpose({
editorHeight,
});
watch(props.libs, async () => {
updateEditorTypes();
});
function updateEditorTypes() {
monacoInstance.value?.languages.typescript.typescriptDefaults.setExtraLibs(
Object.entries(props.libs).map(([name, content]) => {
@@ -128,8 +139,34 @@ onMounted(() => {
editor.onDidChangeModelContent(() => {
code.value = editor.getValue();
});
editor.onDidChangeModelContent(() => {
updateEditorHeight(editor);
})
updateEditorHeight(editor);
});
})
/**
* Update the height of the editor based on the number of lines in the editor.
* NOTE: This is a bit of a hack, as 'height: auto' does not work with Monaco Editor
*
* @param editor - The editor instance.
*/
const updateEditorHeight = (editor: editor.IStandaloneCodeEditor) => {
let lineCount = editor.getModel()?.getLineCount();
if (!lineCount) return;
// Add an extra line to the lineCount
lineCount += 1;
// get font size
const fontSize = editor.getOption(67);
const height = lineCount * fontSize
contentHeight.value = height;
}
</script>
<style scoped>
@@ -1,13 +1,14 @@
<template>
<div class="code-sandbox" :style="sandboxStyle">
<!-- Editor Container -->
<div class="editor-container" :style="editorContainerStyle">
<code-editor v-model="code" @execute="executeCode" :style="editorStyle" :libs="libs" :is-dark="isDark"/>
<code-editor ref="editorRef" v-model="code" @execute="executeCode" :style="editorStyle" :libs="libs" :is-dark="isDark"/>
<div class="editor-buttons">
<button v-if="!hideRunButton" @click="executeCode" class="primary-button ">Run Code</button>
</div>
</div>
<!-- Output Container -->
<div v-if="showLogs || fullHeight" class="output-container" :style="outputContainerStyle">
<div class="output-container-buttons">
<button v-if="!fullHeight" @click="showLogs = false" class="secondary-button">Close</button>
@@ -22,6 +23,7 @@
</div>
</div>
<!-- IFrame for running the code -->
<div class="iframe-container" style="display:none">
<iframe
ref="sandboxIframe"
@@ -93,6 +95,7 @@ const code = ref<string>('');
const logs = ref<ConsoleLog[]>([]);
const showLogs = ref(false);
const sandboxIframe = ref<HTMLIFrameElement | null>(null);
const editorRef = ref<InstanceType<typeof CodeEditor> | null>(null);
// Computed styles based on props
const sandboxStyle = computed(() => ({
@@ -101,14 +104,29 @@ const sandboxStyle = computed(() => ({
flexDirection: 'column'
}));
const editorContainerStyle = computed(() => ({
height: props.fullHeight ? props.editorHeight !== 'auto' ? props.editorHeight : '50%' : 'auto',
flex: props.fullHeight && props.editorHeight === 'auto' ? '1 0 auto' : 'none',
display: 'flex',
flexDirection: 'column',
position: 'relative',
overflow: 'hidden' // Ensure overflowing content doesn't spill out
}));
const editorContainerStyle = computed(() => {
const baseStyle = {
display: 'flex',
flexDirection: 'column',
position: 'relative',
overflow: 'hidden', // Ensure overflowing content doesn't spill out
padding: '16px',
}
if (props.fullHeight) {
return {
...baseStyle,
height: props.editorHeight !== 'auto' ? props.editorHeight : '50%',
flex: props.editorHeight === 'auto' ? '1 0 auto' : 'none',
}
}
return {
...baseStyle,
height: `calc(${editorRef.value?.editorHeight}px + 2 * ${baseStyle.padding})`,
flex: props.editorHeight === 'auto' ? '1 0 auto' : 'none',
}
});
const editorStyle = computed(() => ({
width: '100%',
@@ -379,7 +397,6 @@ defineExpose({
.editor-container {
position: relative;
background: var(--vp-code-block-bg);
padding: 16px;
display: flex;
flex-direction: column;
overflow: hidden; /* Contain overflow */
+3 -12
View File
@@ -26,10 +26,7 @@ The below is Address mess.
<CodeSandbox
:libs="xocashLibs"
height="50em"
editorHeight="30em"
outputHeight="20em"
fullHeight>
>
```
import { Address } from '@xocash/stack';
@@ -55,10 +52,7 @@ We can have more than one per page too. For example:
<CodeSandbox
:libs="xocashLibs"
height="50em"
editorHeight="30em"
outputHeight="20em"
fullHeight>
>
```
import { BlockchainElectrum } from '@xocash/stack';
@@ -82,10 +76,7 @@ The below demonstrates instantiating a wallet.
<CodeSandbox
:libs="xocashLibs"
height="50em"
editorHeight="30em"
outputHeight="20em"
fullHeight>
>
```
import { BlockchainElectrum, WalletP2PKH } from '@xocash/stack';