mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-21 10:38:37 +00:00
Merge pull request #667 from tidalcycles/toggle-sidebar
togglable panel position
This commit is contained in:
commit
9287b8ea42
@ -18,3 +18,4 @@ vite.config.js
|
|||||||
**/*.json
|
**/*.json
|
||||||
**/dev-dist
|
**/dev-dist
|
||||||
**/dist
|
**/dist
|
||||||
|
/src-tauri/target/**/*
|
||||||
@ -16,7 +16,7 @@ const TAURI = window.__TAURI__;
|
|||||||
export function Footer({ context }) {
|
export function Footer({ context }) {
|
||||||
const footerContent = useRef();
|
const footerContent = useRef();
|
||||||
const [log, setLog] = useState([]);
|
const [log, setLog] = useState([]);
|
||||||
const { activeFooter, isZen } = useSettings();
|
const { activeFooter, isZen, panelPosition } = useSettings();
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (footerContent.current && activeFooter === 'console') {
|
if (footerContent.current && activeFooter === 'console') {
|
||||||
@ -71,8 +71,15 @@ export function Footer({ context }) {
|
|||||||
if (isZen) {
|
if (isZen) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isActive = activeFooter !== '';
|
||||||
|
|
||||||
|
let positions = {
|
||||||
|
right: cx('max-w-full flex-grow-0 flex-none overflow-hidden', isActive ? 'w-[600px] h-full' : 'absolute right-0'),
|
||||||
|
bottom: cx('relative', isActive ? 'h-[360px] min-h-[360px]' : ''),
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<footer className="bg-lineHighlight z-[20]">
|
<nav className={cx('bg-lineHighlight z-[1000] flex flex-col', positions[panelPosition])}>
|
||||||
<div className="flex justify-between px-2">
|
<div className="flex justify-between px-2">
|
||||||
<div className={cx('flex select-none max-w-full overflow-auto', activeFooter && 'pb-2')}>
|
<div className={cx('flex select-none max-w-full overflow-auto', activeFooter && 'pb-2')}>
|
||||||
<FooterTab name="intro" label="welcome" />
|
<FooterTab name="intro" label="welcome" />
|
||||||
@ -83,22 +90,24 @@ export function Footer({ context }) {
|
|||||||
{TAURI && <FooterTab name="files" />}
|
{TAURI && <FooterTab name="files" />}
|
||||||
</div>
|
</div>
|
||||||
{activeFooter !== '' && (
|
{activeFooter !== '' && (
|
||||||
<button onClick={() => setActiveFooter('')} className="text-foreground" aria-label="Close Panel">
|
<button onClick={() => setActiveFooter('')} className="text-foreground px-2" aria-label="Close Panel">
|
||||||
<XMarkIcon className="w-5 h-5" />
|
<XMarkIcon className="w-5 h-5" />
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{activeFooter !== '' && (
|
{activeFooter !== '' && (
|
||||||
<div className="text-white flex-none h-[360px] overflow-auto max-w-full relative" ref={footerContent}>
|
<div className="relative overflow-hidden">
|
||||||
{activeFooter === 'intro' && <WelcomeTab />}
|
<div className="text-white overflow-auto h-full max-w-full" ref={footerContent}>
|
||||||
{activeFooter === 'console' && <ConsoleTab log={log} />}
|
{activeFooter === 'intro' && <WelcomeTab />}
|
||||||
{activeFooter === 'sounds' && <SoundsTab />}
|
{activeFooter === 'console' && <ConsoleTab log={log} />}
|
||||||
{activeFooter === 'reference' && <Reference />}
|
{activeFooter === 'sounds' && <SoundsTab />}
|
||||||
{activeFooter === 'settings' && <SettingsTab scheduler={context.scheduler} />}
|
{activeFooter === 'reference' && <Reference />}
|
||||||
{activeFooter === 'files' && <FilesTab />}
|
{activeFooter === 'settings' && <SettingsTab scheduler={context.scheduler} />}
|
||||||
|
{activeFooter === 'files' && <FilesTab />}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</footer>
|
</nav>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,6 +386,7 @@ function SettingsTab({ scheduler }) {
|
|||||||
isLineWrappingEnabled,
|
isLineWrappingEnabled,
|
||||||
fontSize,
|
fontSize,
|
||||||
fontFamily,
|
fontFamily,
|
||||||
|
panelPosition,
|
||||||
} = useSettings();
|
} = useSettings();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -420,14 +430,21 @@ function SettingsTab({ scheduler }) {
|
|||||||
/>
|
/>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
<FormItem label="Keybindings">
|
||||||
<FormItem label="Keybindings">
|
<ButtonGroup
|
||||||
<ButtonGroup
|
value={keybindings}
|
||||||
value={keybindings}
|
onChange={(keybindings) => settingsMap.setKey('keybindings', keybindings)}
|
||||||
onChange={(keybindings) => settingsMap.setKey('keybindings', keybindings)}
|
items={{ codemirror: 'Codemirror', vim: 'Vim', emacs: 'Emacs' }}
|
||||||
items={{ codemirror: 'Codemirror', vim: 'Vim', emacs: 'Emacs' }}
|
></ButtonGroup>
|
||||||
></ButtonGroup>
|
</FormItem>
|
||||||
</FormItem>
|
<FormItem label="Panel Position">
|
||||||
|
<ButtonGroup
|
||||||
|
value={panelPosition}
|
||||||
|
onChange={(value) => settingsMap.setKey('panelPosition', value)}
|
||||||
|
items={{ bottom: 'Bottom', right: 'Right' }}
|
||||||
|
></ButtonGroup>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="Code Settings">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label="Display line numbers"
|
label="Display line numbers"
|
||||||
onChange={(cbEvent) => settingsMap.setKey('isLineNumbersDisplayed', cbEvent.target.checked)}
|
onChange={(cbEvent) => settingsMap.setKey('isLineNumbersDisplayed', cbEvent.target.checked)}
|
||||||
@ -443,7 +460,8 @@ function SettingsTab({ scheduler }) {
|
|||||||
onChange={(cbEvent) => settingsMap.setKey('isLineWrappingEnabled', cbEvent.target.checked)}
|
onChange={(cbEvent) => settingsMap.setKey('isLineWrappingEnabled', cbEvent.target.checked)}
|
||||||
value={isLineWrappingEnabled}
|
value={isLineWrappingEnabled}
|
||||||
/>
|
/>
|
||||||
</div>
|
</FormItem>
|
||||||
|
<FormItem label="Zen Mode">Try clicking the logo in the top left!</FormItem>
|
||||||
<FormItem label="Reset Settings">
|
<FormItem label="Reset Settings">
|
||||||
<button
|
<button
|
||||||
className="bg-background p-2 max-w-[300px] rounded-md hover:opacity-50"
|
className="bg-background p-2 max-w-[300px] rounded-md hover:opacity-50"
|
||||||
|
|||||||
@ -30,8 +30,9 @@ export function Header({ context }) {
|
|||||||
<header
|
<header
|
||||||
id="header"
|
id="header"
|
||||||
className={cx(
|
className={cx(
|
||||||
'py-1 flex-none w-full text-black justify-between z-[100] text-lg select-none sticky top-0',
|
'flex-none text-black z-[100] text-lg select-none',
|
||||||
!isZen && !isEmbedded && 'bg-lineHighlight',
|
!isZen && !isEmbedded && 'bg-lineHighlight',
|
||||||
|
isZen ? 'h-12 w-8 fixed top-0 left-0' : 'sticky top-0 w-full py-1 justify-between',
|
||||||
isEmbedded ? 'flex' : 'md:flex',
|
isEmbedded ? 'flex' : 'md:flex',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -5,7 +5,7 @@ const visibleFunctions = jsdocJson.docs
|
|||||||
|
|
||||||
export function Reference() {
|
export function Reference() {
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full w-full pt-2 text-foreground">
|
<div className="flex h-full w-full pt-2 text-foreground overflow-hidden">
|
||||||
<div className="w-42 flex-none h-full overflow-y-auto overflow-x-hidden pr-4">
|
<div className="w-42 flex-none h-full overflow-y-auto overflow-x-hidden pr-4">
|
||||||
{visibleFunctions.map((entry, i) => (
|
{visibleFunctions.map((entry, i) => (
|
||||||
<a key={i} className="cursor-pointer block hover:bg-lineHighlight py-1 px-4" href={`#doc-${i}`}>
|
<a key={i} className="cursor-pointer block hover:bg-lineHighlight py-1 px-4" href={`#doc-${i}`}>
|
||||||
@ -14,7 +14,7 @@ export function Reference() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className="break-normal w-full h-full overflow-auto pl-4 flex relative">
|
<div className="break-normal w-full h-full overflow-auto pl-4 flex relative">
|
||||||
<div className="prose dark:prose-invert">
|
<div className="prose dark:prose-invert max-w-full pr-4">
|
||||||
<h2>API Reference</h2>
|
<h2>API Reference</h2>
|
||||||
<p>
|
<p>
|
||||||
This is the long list functions you can use! Remember that you don't need to remember all of those and that
|
This is the long list functions you can use! Remember that you don't need to remember all of those and that
|
||||||
|
|||||||
@ -122,6 +122,7 @@ export function Repl({ embedded = false }) {
|
|||||||
isLineNumbersDisplayed,
|
isLineNumbersDisplayed,
|
||||||
isAutoCompletionEnabled,
|
isAutoCompletionEnabled,
|
||||||
isLineWrappingEnabled,
|
isLineWrappingEnabled,
|
||||||
|
panelPosition,
|
||||||
} = useSettings();
|
} = useSettings();
|
||||||
|
|
||||||
const { code, setCode, scheduler, evaluate, activateCode, isDirty, activeCode, pattern, started, stop, error } =
|
const { code, setCode, scheduler, evaluate, activateCode, isDirty, activeCode, pattern, started, stop, error } =
|
||||||
@ -289,30 +290,12 @@ export function Repl({ embedded = false }) {
|
|||||||
<ReplContext.Provider value={context}>
|
<ReplContext.Provider value={context}>
|
||||||
<div
|
<div
|
||||||
className={cx(
|
className={cx(
|
||||||
'h-full flex flex-col',
|
'h-full flex flex-col relative',
|
||||||
// 'bg-gradient-to-t from-green-900 to-slate-900', //
|
// overflow-hidden
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Loader active={pending} />
|
<Loader active={pending} />
|
||||||
<Header context={context} />
|
<Header context={context} />
|
||||||
<section className="grow flex text-gray-100 relative overflow-auto cursor-text pb-0" id="code">
|
|
||||||
<CodeMirror
|
|
||||||
theme={currentTheme}
|
|
||||||
value={code}
|
|
||||||
keybindings={keybindings}
|
|
||||||
isLineNumbersDisplayed={isLineNumbersDisplayed}
|
|
||||||
isAutoCompletionEnabled={isAutoCompletionEnabled}
|
|
||||||
isLineWrappingEnabled={isLineWrappingEnabled}
|
|
||||||
fontSize={fontSize}
|
|
||||||
fontFamily={fontFamily}
|
|
||||||
onChange={handleChangeCode}
|
|
||||||
onViewChanged={handleViewChanged}
|
|
||||||
onSelectionChange={handleSelectionChange}
|
|
||||||
/>
|
|
||||||
</section>
|
|
||||||
{error && (
|
|
||||||
<div className="text-red-500 p-4 bg-lineHighlight animate-pulse">{error.message || 'Unknown Error :-/'}</div>
|
|
||||||
)}
|
|
||||||
{isEmbedded && !started && (
|
{isEmbedded && !started && (
|
||||||
<button
|
<button
|
||||||
onClick={() => handleTogglePlay()}
|
onClick={() => handleTogglePlay()}
|
||||||
@ -322,7 +305,28 @@ export function Repl({ embedded = false }) {
|
|||||||
<span>play</span>
|
<span>play</span>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{!isEmbedded && <Footer context={context} />}
|
<div className="grow flex relative overflow-hidden">
|
||||||
|
<section className="text-gray-100 cursor-text pb-0 overflow-auto grow" id="code">
|
||||||
|
<CodeMirror
|
||||||
|
theme={currentTheme}
|
||||||
|
value={code}
|
||||||
|
keybindings={keybindings}
|
||||||
|
isLineNumbersDisplayed={isLineNumbersDisplayed}
|
||||||
|
isAutoCompletionEnabled={isAutoCompletionEnabled}
|
||||||
|
isLineWrappingEnabled={isLineWrappingEnabled}
|
||||||
|
fontSize={fontSize}
|
||||||
|
fontFamily={fontFamily}
|
||||||
|
onChange={handleChangeCode}
|
||||||
|
onViewChanged={handleViewChanged}
|
||||||
|
onSelectionChange={handleSelectionChange}
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
{panelPosition === 'right' && !isEmbedded && <Footer context={context} />}
|
||||||
|
</div>
|
||||||
|
{error && (
|
||||||
|
<div className="text-red-500 p-4 bg-lineHighlight animate-pulse">{error.message || 'Unknown Error :-/'}</div>
|
||||||
|
)}
|
||||||
|
{panelPosition === 'bottom' && !isEmbedded && <Footer context={context} />}
|
||||||
</div>
|
</div>
|
||||||
</ReplContext.Provider>
|
</ReplContext.Provider>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -14,6 +14,7 @@ export const defaultSettings = {
|
|||||||
latestCode: '',
|
latestCode: '',
|
||||||
isZen: false,
|
isZen: false,
|
||||||
soundsFilter: 'all',
|
soundsFilter: 'all',
|
||||||
|
panelPosition: 'bottom',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const settingsMap = persistentMap('strudel-settings', defaultSettings);
|
export const settingsMap = persistentMap('strudel-settings', defaultSettings);
|
||||||
@ -27,6 +28,7 @@ export function useSettings() {
|
|||||||
isAutoCompletionEnabled: [true, 'true'].includes(state.isAutoCompletionEnabled) ? true : false,
|
isAutoCompletionEnabled: [true, 'true'].includes(state.isAutoCompletionEnabled) ? true : false,
|
||||||
isLineWrappingEnabled: [true, 'true'].includes(state.isLineWrappingEnabled) ? true : false,
|
isLineWrappingEnabled: [true, 'true'].includes(state.isLineWrappingEnabled) ? true : false,
|
||||||
fontSize: Number(state.fontSize),
|
fontSize: Number(state.fontSize),
|
||||||
|
panelPosition: state.activeFooter !== '' ? state.panelPosition : 'bottom',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user