import XMarkIcon from '@heroicons/react/20/solid/XMarkIcon'; import { logger } from '@strudel.cycles/core'; import { useEvent, cx } from '@strudel.cycles/react'; // import { cx } from '@strudel.cycles/react'; import { nanoid } from 'nanoid'; import React, { useCallback, useLayoutEffect, useRef, useState } from 'react'; import { loadedSamples } from './Repl'; import { Reference } from './Reference'; import { themes } from './themes.mjs'; import useStore from '../useStore.mjs'; export function Footer({ context }) { // const [activeFooter, setActiveFooter] = useState('console'); // const { activeFooter, setActiveFooter, isZen } = useContext?.(ReplContext); const { activeFooter, setActiveFooter, isZen } = context; const footerContent = useRef(); const [log, setLog] = useState([]); useLayoutEffect(() => { if (footerContent.current && activeFooter === 'console') { // scroll log box to bottom when log changes footerContent.current.scrollTop = footerContent.current?.scrollHeight; } }, [log, activeFooter]); useLayoutEffect(() => { if (!footerContent.current) { } else if (activeFooter === 'console') { footerContent.current.scrollTop = footerContent.current?.scrollHeight; } else { footerContent.current.scrollTop = 0; } }, [activeFooter]); useLogger( useCallback((e) => { const { message, type, data } = e.detail; setLog((l) => { const lastLog = l.length ? l[l.length - 1] : undefined; const id = nanoid(12); // if (type === 'loaded-sample' && lastLog.type === 'load-sample' && lastLog.url === data.url) { if (type === 'loaded-sample') { // const loadIndex = l.length - 1; const loadIndex = l.findIndex(({ data: { url }, type }) => type === 'load-sample' && url === data.url); l[loadIndex] = { message, type, id, data }; } else if (lastLog && lastLog.message === message) { l = l.slice(0, -1).concat([{ message, type, count: (lastLog.count ?? 1) + 1, id, data }]); } else { l = l.concat([{ message, type, id, data }]); } return l.slice(-20); }); }, []), ); const FooterTab = ({ children, name, label }) => ( <>
You have found strudel, a new live coding platform to write dynamic music
pieces in the browser! It is free and open-source and made for beginners and experts alike. To get started:
1. hit play - 2. change something -{' '}
3. hit update
If you don't like what you hear, try shuffle!
To learn more about what this all means, check out the{' '} interactive tutorial . Also feel free to join the{' '} tidalcycles discord channel {' '} to ask any questions, give feedback or just say hello.
strudel is a JavaScript version of{' '} tidalcycles , which is a popular live coding language for music, written in Haskell. You can find the source code at{' '} github . Please consider to{' '} support this project {' '} to ensure ongoing development 💖
{`███████╗████████╗██████╗ ██╗ ██╗██████╗ ███████╗██╗
██╔════╝╚══██╔══╝██╔══██╗██║ ██║██╔══██╗██╔════╝██║
███████╗ ██║ ██████╔╝██║ ██║██║ ██║█████╗ ██║
╚════██║ ██║ ██╔══██╗██║ ██║██║ ██║██╔══╝ ██║
███████║ ██║ ██║ ██║╚██████╔╝██████╔╝███████╗███████╗
╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚══════╝`}
{log.map((l, i) => {
const message = linkify(l.message);
return (