slidev-addon-notecell
Version:
A Slidev addon for interactive Jupyter notebook cells with code execution capabilities
278 lines (244 loc) • 8.68 kB
HTML
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NoteCell Addon Test</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
margin: 0;
padding: 20px;
background: #f8fafc;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.demo-section {
background: white;
border-radius: 8px;
padding: 24px;
margin-bottom: 24px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.demo-title {
font-size: 1.5rem;
font-weight: 600;
margin-bottom: 16px;
color: #1f2937;
}
.demo-description {
color: #6b7280;
margin-bottom: 20px;
}
/* NoteCell Styles */
.wrapper-all {
height: 400px;
width: 100%;
display: flex;
flex-flow: column;
overflow: auto;
max-height: 450px;
scrollbar-width: none;
border: 1px solid #e5e7eb;
border-radius: 6px;
}
.thebe-code {
width: 100%;
height: 100%;
position: relative;
}
.thebe-code pre {
margin: 0;
padding: 16px;
background: #f8fafc;
border: none;
border-radius: 6px 6px 0 0;
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
font-size: 14px;
line-height: 1.5;
overflow-x: auto;
}
.output-wrapper {
flex-grow: 1;
width: 100%;
font-size: 0.9rem;
overflow: auto;
padding: 16px;
scrollbar-width: none;
background: white;
border-top: 1px solid #e5e7eb;
min-height: 100px;
}
.thebe-code:before {
content: var(--pseudo-before-content, 'runnable');
background-color: #fbbf24;
color: #92400e;
padding: 4px 8px;
text-align: center;
border-radius: 4px;
font-size: 0.75rem;
font-weight: 500;
z-index: 10;
position: absolute;
top: 8px;
right: 8px;
}
.horizontal-layout {
flex-flow: row;
}
.horizontal-layout .thebe-code {
flex-grow: 1;
width: auto;
margin-right: 1rem;
}
.horizontal-layout .output-wrapper {
width: 50%;
border-top: none;
border-left: 1px solid #e5e7eb;
}
.hide {
display: none;
}
.status-indicator {
padding: 8px 16px;
background: #dbeafe;
color: #1e40af;
border-radius: 4px;
font-size: 0.875rem;
margin-bottom: 16px;
}
.mock-output {
font-family: monospace;
background: #f3f4f6;
padding: 12px;
border-radius: 4px;
border-left: 4px solid #10b981;
}
</style>
</head>
<body>
<div id="app">
<div class="container">
<h1>NoteCell Addon Test</h1>
<p>This page demonstrates the NoteCell component functionality without requiring a full Slidev setup.</p>
<div class="demo-section">
<h2 class="demo-title">Basic Vertical Layout</h2>
<p class="demo-description">Double-click the code area to simulate execution</p>
<mock-note-cell layout="vertical">
<pre><code>print("Hello from Jupyter!")
print("This is an interactive code cell")
# Simple calculation
result = 2 + 2
print(f"2 + 2 = {result}")</code></pre>
</mock-note-cell>
</div>
<div class="demo-section">
<h2 class="demo-title">Horizontal Layout</h2>
<p class="demo-description">Code and output side by side</p>
<mock-note-cell layout="horizontal">
<pre><code>import matplotlib.pyplot as plt
import numpy as np
# Generate sample data
x = np.linspace(0, 10, 100)
y = np.sin(x)
# Create plot
plt.figure(figsize=(8, 4))
plt.plot(x, y, 'b-', linewidth=2)
plt.title('Sine Wave')
plt.show()</code></pre>
</mock-note-cell>
</div>
<div class="demo-section">
<h2 class="demo-title">Component Features</h2>
<div class="status-indicator">
✅ Interactive code execution simulation<br>
✅ Vertical and horizontal layouts<br>
✅ Toggle between code and output views<br>
✅ Status indicators (runnable/running)<br>
✅ Responsive design
</div>
</div>
</div>
</div>
<script>
const { createApp, ref, computed } = Vue;
const MockNoteCell = {
props: {
layout: {
type: String,
default: 'vertical'
}
},
setup(props) {
const isCodeHidden = ref(false);
const isExecuting = ref(false);
const hasOutput = ref(false);
const mockOutput = ref('');
const onDoubleClick = async () => {
if (hasOutput.value && !isCodeHidden.value) {
// Toggle to output view
isCodeHidden.value = true;
return;
}
if (isCodeHidden.value) {
// Toggle back to code view
isCodeHidden.value = false;
return;
}
// Simulate code execution
isExecuting.value = true;
// Simulate execution delay
await new Promise(resolve => setTimeout(resolve, 2000));
// Generate mock output
mockOutput.value = `Hello from Jupyter!
This is an interactive code cell
2 + 2 = 4
[Execution completed in 0.123s]`;
isExecuting.value = false;
hasOutput.value = true;
isCodeHidden.value = true;
};
const statusText = computed(() => {
if (isExecuting.value) return 'running';
if (hasOutput.value) return 'executed';
return 'runnable';
});
return {
isCodeHidden,
isExecuting,
hasOutput,
mockOutput,
onDoubleClick,
statusText
};
},
template: `
<div class="wrapper-all" :class="{ 'horizontal-layout': layout === 'horizontal' }" @dblclick="onDoubleClick">
<div class="thebe-code" :class="{ hide: isCodeHidden }" :style="{ '--pseudo-before-content': "'" + statusText + "'" }">
<slot></slot>
</div>
<div class="output-wrapper" :class="{ hide: !isCodeHidden }">
<div v-if="isExecuting" class="mock-output">
<div>🔄 Executing code...</div>
</div>
<div v-else-if="hasOutput" class="mock-output">
<pre>{{ mockOutput }}</pre>
</div>
<div v-else class="mock-output">
<em>Output will appear here after execution</em>
</div>
</div>
</div>
`
};
createApp({
components: {
MockNoteCell
}
}).mount('#app');
</script>
</body>
</html>