mirror of
https://codeberg.org/uzu/strudel
synced 2026-10-07 09:28:07 -04:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 90c05ec38a | |||
| 7e0eed87cb | |||
| 1a1197f67a | |||
| 28db6d1fd4 | |||
| dc9cadc979 | |||
| f99b13efc2 | |||
| 4993ec4cbf | |||
| 8e5ca57edd | |||
| 107a3acd3a | |||
| 1d887e81ef | |||
| 3c5afb32f3 | |||
| 76cbd23859 | |||
| b436ae789c | |||
| 275731afc7 | |||
| 5cb2214d88 |
@@ -24,7 +24,12 @@ import { sliderPlugin, updateSliderWidgets } from './slider.mjs';
|
|||||||
import { activateTheme, initTheme, theme } from './themes.mjs';
|
import { activateTheme, initTheme, theme } from './themes.mjs';
|
||||||
import { isTooltipEnabled } from './tooltip.mjs';
|
import { isTooltipEnabled } from './tooltip.mjs';
|
||||||
import { updateWidgets, widgetPlugin } from './widget.mjs';
|
import { updateWidgets, widgetPlugin } from './widget.mjs';
|
||||||
import { jumpToCharacter } from './labelJump.mjs';
|
import {
|
||||||
|
deleteAllInlineBeforeCharacter,
|
||||||
|
InsertCharBeforeChar,
|
||||||
|
jumpToCharacter,
|
||||||
|
jumpToNextCharacter,
|
||||||
|
} from './labelJump.mjs';
|
||||||
|
|
||||||
export { toggleBlockComment, toggleBlockCommentByLine, toggleComment, toggleLineComment } from '@codemirror/commands';
|
export { toggleBlockComment, toggleBlockCommentByLine, toggleComment, toggleLineComment } from '@codemirror/commands';
|
||||||
|
|
||||||
@@ -74,6 +79,10 @@ export const codemirrorSettings = persistentAtom('codemirror-settings', defaultS
|
|||||||
decode: JSON.parse,
|
decode: JSON.parse,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const ANON_LABEL = '$';
|
||||||
|
const SOLO_LABEL = 'S';
|
||||||
|
const MUTE_LABEL = '_';
|
||||||
|
|
||||||
// https://codemirror.net/docs/guide/
|
// https://codemirror.net/docs/guide/
|
||||||
export function initEditor({ initialCode = '', onChange, onEvaluate, onStop, root, mondo }) {
|
export function initEditor({ initialCode = '', onChange, onEvaluate, onStop, root, mondo }) {
|
||||||
const settings = codemirrorSettings.get();
|
const settings = codemirrorSettings.get();
|
||||||
@@ -122,12 +131,75 @@ export function initEditor({ initialCode = '', onChange, onEvaluate, onStop, roo
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'Alt-w',
|
key: 'Alt-w',
|
||||||
run: (view) => jumpToCharacter(view, '$', 1),
|
run: (view) => jumpToNextCharacter(view, ANON_LABEL, 1),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'Alt-q',
|
key: 'Alt-q',
|
||||||
run: (view) => jumpToCharacter(view, '$', -1),
|
run: (view) => {
|
||||||
|
return jumpToNextCharacter(view, ANON_LABEL, -1);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
// clear all muted
|
||||||
|
{
|
||||||
|
key: `Alt-Ctrl-0`,
|
||||||
|
run: (view) => {
|
||||||
|
return deleteAllInlineBeforeCharacter(view, MUTE_LABEL + ANON_LABEL);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// clear all solod
|
||||||
|
{
|
||||||
|
key: `Alt-Shift-0`,
|
||||||
|
run: (view) => {
|
||||||
|
return deleteAllInlineBeforeCharacter(view, SOLO_LABEL + ANON_LABEL);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// clear all solo and mute
|
||||||
|
{
|
||||||
|
key: `Ctrl-Shift-0`,
|
||||||
|
run: (view) => {
|
||||||
|
return deleteAllInlineBeforeCharacter(view, ANON_LABEL);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...Array.from({ length: 9 }).map((_, i) => {
|
||||||
|
let num = i + 1;
|
||||||
|
return {
|
||||||
|
key: `Alt-${num}`,
|
||||||
|
run: (view) => {
|
||||||
|
return jumpToCharacter(view, ANON_LABEL, i);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
// handle solo toggles 1-9
|
||||||
|
...Array.from({ length: 9 }).map((_, i) => {
|
||||||
|
let num = i + 1;
|
||||||
|
return {
|
||||||
|
key: `Alt-Shift-${num}`,
|
||||||
|
run: (view) => {
|
||||||
|
return InsertCharBeforeChar(view, ANON_LABEL, SOLO_LABEL, i);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
// handle mute toggles 1-9
|
||||||
|
...Array.from({ length: 9 }).map((_, i) => {
|
||||||
|
let num = i + 1;
|
||||||
|
return {
|
||||||
|
key: `Alt-Ctrl-${num}`,
|
||||||
|
run: (view) => {
|
||||||
|
return InsertCharBeforeChar(view, ANON_LABEL, MUTE_LABEL, i);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
// Handle clearing mutes and solos 1-9
|
||||||
|
...Array.from({ length: 9 }).map((_, i) => {
|
||||||
|
let num = i + 1;
|
||||||
|
return {
|
||||||
|
key: `Ctrl-Shift-${num}`,
|
||||||
|
run: (view) => {
|
||||||
|
return InsertCharBeforeChar(view, ANON_LABEL,'', i);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
/* {
|
/* {
|
||||||
key: 'Ctrl-Shift-.',
|
key: 'Ctrl-Shift-.',
|
||||||
run: () => (onPanic ? onPanic() : onStop?.()),
|
run: () => (onPanic ? onPanic() : onStop?.()),
|
||||||
|
|||||||
@@ -1,18 +1,54 @@
|
|||||||
import { EditorSelection } from '@codemirror/state';
|
import { EditorSelection } from '@codemirror/state';
|
||||||
import { SearchCursor } from '@codemirror/search';
|
import { SearchCursor } from '@codemirror/search';
|
||||||
|
import { EditorView } from '@codemirror/view';
|
||||||
|
import { syntaxTree } from '@codemirror/language';
|
||||||
|
|
||||||
export function jumpToCharacter(view, character, direction = 1) {
|
/**
|
||||||
const { state, dispatch } = view;
|
* gets all of the positions of a character in a document, excluding commented out lines
|
||||||
const pos = state.selection.main.head;
|
* @param { EditorState} state
|
||||||
|
* @param {String} character
|
||||||
|
* @returns {number[]}
|
||||||
|
*/
|
||||||
|
function getCharacterPositions(state, character) {
|
||||||
const cursor = new SearchCursor(state.doc, character);
|
const cursor = new SearchCursor(state.doc, character);
|
||||||
|
|
||||||
let characterPositions = [];
|
const characterPositions = [];
|
||||||
let jumpPos;
|
|
||||||
while (!cursor.next().done) {
|
while (!cursor.next().done) {
|
||||||
characterPositions.push(cursor.value.to);
|
|
||||||
|
const linestartpos = state.doc.lineAt(cursor.value.to).from
|
||||||
|
if (!isLineCommentedOut(state, linestartpos)) {
|
||||||
|
|
||||||
|
characterPositions.push(cursor.value.to);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return characterPositions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isLineCommentedOut(state, pos) {
|
||||||
|
|
||||||
|
const line = state.doc.lineAt(pos);
|
||||||
|
// remove white space
|
||||||
|
pos = line.from + line.text.search(/\S/)
|
||||||
|
|
||||||
|
const tree = syntaxTree(state);
|
||||||
|
const node = tree.resolveInner(pos, 1)
|
||||||
|
return node.name.includes("Comment")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jump to the next character in a document
|
||||||
|
* @param {EditorView} view
|
||||||
|
* @param {String} character
|
||||||
|
* @param {number} direction 0 or 1
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
export function jumpToNextCharacter(view, character, direction = 1) {
|
||||||
|
const { state, dispatch } = view;
|
||||||
|
const pos = state.selection.main.head;
|
||||||
|
let jumpPos;
|
||||||
|
const characterPositions = getCharacterPositions(state, character);
|
||||||
if (!characterPositions.length) {
|
if (!characterPositions.length) {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
if (direction > 0) {
|
if (direction > 0) {
|
||||||
jumpPos = characterPositions.find((x) => x > pos + 1) ?? characterPositions.at(0); // Loop back around for convenience
|
jumpPos = characterPositions.find((x) => x > pos + 1) ?? characterPositions.at(0); // Loop back around for convenience
|
||||||
@@ -21,11 +57,97 @@ export function jumpToCharacter(view, character, direction = 1) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (jumpPos == null) {
|
if (jumpPos == null) {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
const selection = EditorSelection.cursor(jumpPos - 1);
|
||||||
dispatch({
|
dispatch({
|
||||||
selection: EditorSelection.cursor(jumpPos - 1),
|
selection,
|
||||||
scrollIntoView: true,
|
effects: EditorView.scrollIntoView(
|
||||||
|
selection.head,
|
||||||
|
{ y: "start" }
|
||||||
|
)
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {EditorView} view
|
||||||
|
* @param {String} character
|
||||||
|
* @param {number} index the instance of the character
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function jumpToCharacter(view, character, index) {
|
||||||
|
const { state, dispatch } = view;
|
||||||
|
const characterPositions = getCharacterPositions(state, character);
|
||||||
|
const pos = characterPositions.at(index) ?? characterPositions.at(-1);
|
||||||
|
if (pos == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const selection = EditorSelection.cursor(pos - 1);
|
||||||
|
dispatch({
|
||||||
|
selection,
|
||||||
|
effects: EditorView.scrollIntoView(
|
||||||
|
selection.head,
|
||||||
|
{ y: "start" }
|
||||||
|
)
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {EditorView} view
|
||||||
|
* @param {String} character
|
||||||
|
* @returns {true}
|
||||||
|
*/
|
||||||
|
export function deleteAllInlineBeforeCharacter(view, character) {
|
||||||
|
const { state, dispatch } = view;
|
||||||
|
const characterPositions = getCharacterPositions(state, character);
|
||||||
|
|
||||||
|
const changes = [];
|
||||||
|
characterPositions.forEach((pos) => {
|
||||||
|
const line = state.doc.lineAt(pos);
|
||||||
|
if (state.doc.sliceString(line.from, line.from + 2) === COMMENT_STRING) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
changes.push({
|
||||||
|
from: line.from,
|
||||||
|
to: pos - 1,
|
||||||
|
insert: '',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
dispatch({ changes });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {EditorView} view
|
||||||
|
* @param {String} character
|
||||||
|
* @param {String} character2
|
||||||
|
* @param {number} index
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function InsertCharBeforeChar(view, character, character2, index) {
|
||||||
|
const { state, dispatch } = view;
|
||||||
|
|
||||||
|
const changes = [];
|
||||||
|
const characterPositions = getCharacterPositions(state, character);
|
||||||
|
const labelpos = characterPositions.at(index) ?? characterPositions.at(-1);
|
||||||
|
const line = state.doc.lineAt(labelpos);
|
||||||
|
|
||||||
|
//delete preceeding characters
|
||||||
|
changes.push({
|
||||||
|
from: line.from,
|
||||||
|
to: labelpos - 1,
|
||||||
|
insert: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
changes.push({
|
||||||
|
insert: character2,
|
||||||
|
from: line.from,
|
||||||
|
});
|
||||||
|
|
||||||
|
dispatch({ changes });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import Loader from '@src/repl/components/Loader';
|
import Loader from '@src/repl/components/Loader';
|
||||||
import { HorizontalPanel } from '@src/repl/components/panel/Panel';
|
import { BottomPanel } from '@src/repl/components/panel/Panel';
|
||||||
import { Code } from '@src/repl/components/Code';
|
import { Code } from '@src/repl/components/Code';
|
||||||
import BigPlayButton from '@src/repl/components/BigPlayButton';
|
import BigPlayButton from '@src/repl/components/BigPlayButton';
|
||||||
import UserFacingErrorMessage from '@src/repl/components/UserFacingErrorMessage';
|
import UserFacingErrorMessage from '@src/repl/components/UserFacingErrorMessage';
|
||||||
@@ -20,7 +20,7 @@ export default function UdelsEditor(Props) {
|
|||||||
<Code containerRef={containerRef} editorRef={editorRef} init={init} />
|
<Code containerRef={containerRef} editorRef={editorRef} init={init} />
|
||||||
</div>
|
</div>
|
||||||
<UserFacingErrorMessage error={error} />
|
<UserFacingErrorMessage error={error} />
|
||||||
<HorizontalPanel context={context} />
|
<BottomPanel context={context} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Code } from '@src/repl/components/Code';
|
import { Code } from '@src/repl/components/Code';
|
||||||
import Loader from '@src/repl/components/Loader';
|
import Loader from '@src/repl/components/Loader';
|
||||||
import { HorizontalPanel, MainPanel, VerticalPanel } from '@src/repl/components/panel/Panel';
|
import { BottomPanel, MainPanel, RightPanel } from '@src/repl/components/panel/Panel';
|
||||||
import UserFacingErrorMessage from '@src/repl/components/UserFacingErrorMessage';
|
import UserFacingErrorMessage from '@src/repl/components/UserFacingErrorMessage';
|
||||||
import { useSettings } from '@src/settings.mjs';
|
import { useSettings } from '@src/settings.mjs';
|
||||||
|
|
||||||
@@ -21,13 +21,13 @@ export default function ReplEditor(Props) {
|
|||||||
<div className="flex flex-col grow overflow-hidden">
|
<div className="flex flex-col grow overflow-hidden">
|
||||||
{/* <MainPanel context={context} isEmbedded={isEmbedded} className="hidden sm:block" /> */}
|
{/* <MainPanel context={context} isEmbedded={isEmbedded} className="hidden sm:block" /> */}
|
||||||
<MainPanel context={context} isEmbedded={isEmbedded} />
|
<MainPanel context={context} isEmbedded={isEmbedded} />
|
||||||
<div className="flex overflow-hidden">
|
<div className="flex overflow-hidden h-full">
|
||||||
<Code containerRef={containerRef} editorRef={editorRef} init={init} />
|
<Code containerRef={containerRef} editorRef={editorRef} init={init} />
|
||||||
{!isZen && panelPosition === 'right' && <VerticalPanel context={context} />}
|
{!isZen && panelPosition === 'right' && <RightPanel context={context} />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<UserFacingErrorMessage error={error} />
|
<UserFacingErrorMessage error={error} />
|
||||||
{!isZen && panelPosition === 'bottom' && <HorizontalPanel context={context} />}
|
{!isZen && panelPosition === 'bottom' && <BottomPanel context={context} />}
|
||||||
{/* <MainPanel context={context} isEmbedded={isEmbedded} className="block sm:hidden" /> */}
|
{/* <MainPanel context={context} isEmbedded={isEmbedded} className="block sm:hidden" /> */}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,13 +2,21 @@ import cx from '@src/cx.mjs';
|
|||||||
import { useSettings } from '../../../settings.mjs';
|
import { useSettings } from '../../../settings.mjs';
|
||||||
import { useStore } from '@nanostores/react';
|
import { useStore } from '@nanostores/react';
|
||||||
import { $strudel_log_history } from '../useLogger';
|
import { $strudel_log_history } from '../useLogger';
|
||||||
|
import { useEffect, useRef } from 'react';
|
||||||
|
|
||||||
export function ConsoleTab() {
|
export function ConsoleTab() {
|
||||||
const log = useStore($strudel_log_history);
|
const log = useStore($strudel_log_history);
|
||||||
const { fontFamily } = useSettings();
|
const { fontFamily } = useSettings();
|
||||||
|
const scrollRef = useRef();
|
||||||
|
// scroll to bottom when log changes
|
||||||
|
useEffect(() => {
|
||||||
|
if (scrollRef.current) {
|
||||||
|
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
|
||||||
|
}
|
||||||
|
}, [log]);
|
||||||
return (
|
return (
|
||||||
<div id="console-tab" className="break-all w-full h-full" style={{ fontFamily }}>
|
<div id="console-tab" className="break-all w-full h-full" style={{ fontFamily }}>
|
||||||
<div className="h-full w-full overflow-auto space-y-1 p-2 rounded-md">
|
<div className="h-full w-full overflow-auto space-y-1 p-2 rounded-md" ref={scrollRef}>
|
||||||
{' '}
|
{' '}
|
||||||
{/* bg-background */}
|
{/* bg-background */}
|
||||||
{log.map((l, i) => {
|
{log.map((l, i) => {
|
||||||
@@ -18,12 +26,13 @@ export function ConsoleTab() {
|
|||||||
<div
|
<div
|
||||||
key={l.id}
|
key={l.id}
|
||||||
className={cx(
|
className={cx(
|
||||||
|
'whitespace-nowrap',
|
||||||
l.type === 'error' ? 'text-background bg-foreground' : 'text-foreground',
|
l.type === 'error' ? 'text-background bg-foreground' : 'text-foreground',
|
||||||
l.type === 'highlight' && 'underline',
|
l.type === 'highlight' && 'underline',
|
||||||
)}
|
)}
|
||||||
style={color ? { color } : {}}
|
style={color ? { color } : {}}
|
||||||
>
|
>
|
||||||
<span dangerouslySetInnerHTML={{ __html: message }} />
|
<span dangerouslySetInnerHTML={{ __html: message }} className="whitespace-nowrap" />
|
||||||
{l.count ? ` (${l.count})` : ''}
|
{l.count ? ` (${l.count})` : ''}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -48,11 +48,8 @@ export function MainPanel({ context, isEmbedded = false, className }) {
|
|||||||
<nav
|
<nav
|
||||||
id="header"
|
id="header"
|
||||||
className={cx(
|
className={cx(
|
||||||
//'border-t sm:border-b sm:border-t-0 border-muted',
|
|
||||||
'border-b border-muted',
|
|
||||||
'flex-none text-black z-[100] text-sm select-none min-h-10 max-h-10',
|
'flex-none text-black z-[100] text-sm select-none min-h-10 max-h-10',
|
||||||
!isZen && !isEmbedded && 'bg-lineHighlight',
|
!isZen && !isEmbedded && 'border-b border-muted bg-lineHighlight',
|
||||||
// isZen ? 'h-12 w-8 fixed top-0 left-0' : 'h-10 sticky top-0 w-full justify-between',
|
|
||||||
isZen ? 'h-12 w-8 fixed top-0 left-0' : '',
|
isZen ? 'h-12 w-8 fixed top-0 left-0' : '',
|
||||||
'flex items-center',
|
'flex items-center',
|
||||||
className,
|
className,
|
||||||
@@ -60,8 +57,6 @@ export function MainPanel({ context, isEmbedded = false, className }) {
|
|||||||
style={{ fontFamily }}
|
style={{ fontFamily }}
|
||||||
>
|
>
|
||||||
<div className={cx('flex w-full justify-between')}>
|
<div className={cx('flex w-full justify-between')}>
|
||||||
{' '}
|
|
||||||
{/*flex-wrap*/}
|
|
||||||
<div className="px-3 py-1 flex space-x-2 select-none">
|
<div className="px-3 py-1 flex space-x-2 select-none">
|
||||||
<h1
|
<h1
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -77,11 +72,6 @@ export function MainPanel({ context, isEmbedded = false, className }) {
|
|||||||
<div className="space-x-2 flex items-baseline">
|
<div className="space-x-2 flex items-baseline">
|
||||||
<span className="hidden sm:block">strudel</span>
|
<span className="hidden sm:block">strudel</span>
|
||||||
<span className="text-sm font-medium hidden sm:block">REPL</span>
|
<span className="text-sm font-medium hidden sm:block">REPL</span>
|
||||||
{/* !isEmbedded && isButtonRowHidden && (
|
|
||||||
<a href={`${baseNoTrailing}/learn`} className="text-sm opacity-25 font-medium">
|
|
||||||
DOCS
|
|
||||||
</a>
|
|
||||||
) */}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</h1>
|
</h1>
|
||||||
@@ -89,7 +79,6 @@ export function MainPanel({ context, isEmbedded = false, className }) {
|
|||||||
{!isZen && (
|
{!isZen && (
|
||||||
<div className="flex grow justify-end">
|
<div className="flex grow justify-end">
|
||||||
{!isButtonRowHidden && <MainMenu isEmbedded={isEmbedded} context={context} />}
|
{!isButtonRowHidden && <MainMenu isEmbedded={isEmbedded} context={context} />}
|
||||||
{/* className="hidden sm:flex" */}
|
|
||||||
<PanelToggle isEmbedded={isEmbedded} isZen={isZen} />
|
<PanelToggle isEmbedded={isEmbedded} isZen={isZen} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -101,7 +90,6 @@ export function MainPanel({ context, isEmbedded = false, className }) {
|
|||||||
export function Footer({ context, isEmbedded = false }) {
|
export function Footer({ context, isEmbedded = false }) {
|
||||||
return (
|
return (
|
||||||
<div className="border-t border-muted bg-lineHighlight block lg:hidden">
|
<div className="border-t border-muted bg-lineHighlight block lg:hidden">
|
||||||
{/* block lg:hidden */}
|
|
||||||
<MainMenu context={context} isEmbedded={isEmbedded} />
|
<MainMenu context={context} isEmbedded={isEmbedded} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -117,15 +105,10 @@ function MainMenu({ context, isEmbedded = false, className }) {
|
|||||||
title={started ? 'stop' : 'play'}
|
title={started ? 'stop' : 'play'}
|
||||||
className={cx('px-2 hover:opacity-50', !started && !isCSSAnimationDisabled && 'animate-pulse')}
|
className={cx('px-2 hover:opacity-50', !started && !isCSSAnimationDisabled && 'animate-pulse')}
|
||||||
>
|
>
|
||||||
{/* {!pending ? ( */}
|
|
||||||
<span className={cx('flex items-center space-x-2')}>
|
<span className={cx('flex items-center space-x-2')}>
|
||||||
{/* {started ? <StopCircleIcon className="w-5 h-5" /> : <PlayCircleIcon className="w-5 h-5" />} */}
|
|
||||||
{started ? <StopIcon className="w-5 h-5" /> : <PlayIcon className="w-5 h-5" />}
|
{started ? <StopIcon className="w-5 h-5" /> : <PlayIcon className="w-5 h-5" />}
|
||||||
{!isEmbedded && <span>{started ? 'stop' : 'play'}</span>}
|
{!isEmbedded && <span>{pending ? '...' : started ? 'stop' : 'play'}</span>}
|
||||||
</span>
|
</span>
|
||||||
{/* ) : (
|
|
||||||
<>loading...</>
|
|
||||||
)} */}
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={handleEvaluate}
|
onClick={handleEvaluate}
|
||||||
@@ -162,7 +145,7 @@ function PanelCloseButton() {
|
|||||||
isPanelOpen && (
|
isPanelOpen && (
|
||||||
<button
|
<button
|
||||||
onClick={() => setIsPanelOpened(false)}
|
onClick={() => setIsPanelOpened(false)}
|
||||||
className={cx('border-l border-muted px-2 py-0 text-foreground hover:opacity-50')}
|
className={cx('px-2 py-0 text-foreground hover:opacity-50')}
|
||||||
aria-label="Close Menu"
|
aria-label="Close Menu"
|
||||||
>
|
>
|
||||||
<XMarkIcon className="w-6 h-6" />
|
<XMarkIcon className="w-6 h-6" />
|
||||||
@@ -171,7 +154,7 @@ function PanelCloseButton() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function HorizontalPanel({ context }) {
|
export function BottomPanel({ context }) {
|
||||||
const { isPanelOpen, activeFooter: tab } = useSettings();
|
const { isPanelOpen, activeFooter: tab } = useSettings();
|
||||||
return (
|
return (
|
||||||
<PanelNav
|
<PanelNav
|
||||||
@@ -182,7 +165,7 @@ export function HorizontalPanel({ context }) {
|
|||||||
>
|
>
|
||||||
<div className="flex justify-between min-h-10 max-h-10 grid-cols-2 items-center border-t border-muted">
|
<div className="flex justify-between min-h-10 max-h-10 grid-cols-2 items-center border-t border-muted">
|
||||||
<PanelCloseButton />
|
<PanelCloseButton />
|
||||||
<Tabs setTab={setTab} tab={tab} />
|
<Tabs setTab={setTab} tab={tab} className={cx(isPanelOpen && 'border-l border-muted')} />
|
||||||
</div>
|
</div>
|
||||||
{isPanelOpen && (
|
{isPanelOpen && (
|
||||||
<div className="w-full h-full overflow-auto border-t border-muted">
|
<div className="w-full h-full overflow-auto border-t border-muted">
|
||||||
@@ -193,7 +176,7 @@ export function HorizontalPanel({ context }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function VerticalPanel({ context }) {
|
export function RightPanel({ context }) {
|
||||||
const settings = useSettings();
|
const settings = useSettings();
|
||||||
const { activeFooter: tab, isPanelOpen } = settings;
|
const { activeFooter: tab, isPanelOpen } = settings;
|
||||||
if (!isPanelOpen) {
|
if (!isPanelOpen) {
|
||||||
@@ -203,24 +186,16 @@ export function VerticalPanel({ context }) {
|
|||||||
<PanelNav
|
<PanelNav
|
||||||
settings={settings}
|
settings={settings}
|
||||||
className={cx(
|
className={cx(
|
||||||
//'border-l border-muted shrink-0',
|
'border-l border-muted shrink-0 h-full overflow-hidden',
|
||||||
'border-0 border-muted shrink-0 h-full overflow-hidden',
|
isPanelOpen ? `min-w-[min(600px,100vw)] max-w-[min(600px,80vw)]` : 'min-w-12 max-w-12',
|
||||||
isPanelOpen
|
|
||||||
? //? `min-w-full max-w-full lg:min-w-[min(600px,100vw)] lg:max-w-[min(600px,80vw)]`
|
|
||||||
`min-w-[min(600px,100vw)] max-w-[min(600px,80vw)]`
|
|
||||||
: 'min-w-12 max-w-12',
|
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className={cx('flex flex-col h-full')}>
|
<div className={cx('flex flex-col h-full')}>
|
||||||
<div className="flex justify-between w-full overflow-hidden border-b border-muted min-h-10 max-h-10">
|
<div className="flex justify-between w-full overflow-hidden border-b border-muted min-h-10 max-h-10">
|
||||||
{/* <div className="block sm:hidden text-foreground px-3 py-2 border-l border-muted">
|
|
||||||
<LogoButton context={context} />
|
|
||||||
</div> */}
|
|
||||||
<PanelCloseButton />
|
<PanelCloseButton />
|
||||||
<Tabs setTab={setTab} tab={tab} />
|
<Tabs setTab={setTab} tab={tab} className="border-l border-muted" />
|
||||||
{/* <PanelCloseButton /> */}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="overflow-auto h-full border-l border-muted">
|
<div className="overflow-auto h-full">
|
||||||
<PanelContent context={context} tab={tab} />
|
<PanelContent context={context} tab={tab} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -301,7 +276,7 @@ function Tabs({ className }) {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cx(
|
className={cx(
|
||||||
'px-2 border-l border-muted w-full flex select-none max-w-full h-10 max-h-10 min-h-10 overflow-auto items-center',
|
'px-2 w-full flex select-none max-w-full h-10 max-h-10 min-h-10 overflow-auto items-center',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -320,14 +295,10 @@ export function PanelToggle({ isEmbedded, isZen }) {
|
|||||||
!isZen &&
|
!isZen &&
|
||||||
panelPosition === 'right' && (
|
panelPosition === 'right' && (
|
||||||
<button
|
<button
|
||||||
title="share"
|
title="menu"
|
||||||
className={cx(
|
className={cx('border-l border-muted px-2 py-0 text-foreground hover:opacity-50')}
|
||||||
'border-l border-muted px-2 py-0 text-foreground hover:opacity-50' /* , isPanelOpen && 'hidden' */,
|
|
||||||
)}
|
|
||||||
onClick={() => setIsPanelOpened(!isPanelOpen)}
|
onClick={() => setIsPanelOpened(!isPanelOpen)}
|
||||||
>
|
>
|
||||||
{/* <span>menu</span> */}
|
|
||||||
{/* isPanelOpen ? <XMarkIcon className="w-6 h-6" /> : <Bars3Icon className="w-6 h-6" /> */}
|
|
||||||
<Bars3Icon className="w-6 h-6" />
|
<Bars3Icon className="w-6 h-6" />
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ function getUpdatedLog(log, event) {
|
|||||||
} else {
|
} else {
|
||||||
log = log.concat([{ message, type, id, data }]);
|
log = log.concat([{ message, type, id, data }]);
|
||||||
}
|
}
|
||||||
return log.slice(-20);
|
return log.slice(-40);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useLogger() {
|
export function useLogger() {
|
||||||
|
|||||||
Reference in New Issue
Block a user