diff --git a/packages/react/dist/index.cjs.js b/packages/react/dist/index.cjs.js index ca537205..cd672e9e 100644 --- a/packages/react/dist/index.cjs.js +++ b/packages/react/dist/index.cjs.js @@ -1 +1 @@ -"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const t=require("react"),G=require("@uiw/react-codemirror"),b=require("@codemirror/view"),R=require("@codemirror/state"),Q=require("@codemirror/lang-javascript"),o=require("@lezer/highlight"),W=require("@uiw/codemirror-themes"),X=require("react-hook-inview"),V=require("@strudel.cycles/webaudio"),Y=require("@strudel.cycles/core"),Z=require("@strudel.cycles/transpiler"),j=e=>e&&typeof e=="object"&&"default"in e?e:{default:e},n=j(t),ee=j(G),te=W.createTheme({theme:"dark",settings:{background:"#222",foreground:"#75baff",caret:"#ffcc00",selection:"rgba(128, 203, 196, 0.5)",selectionMatch:"#036dd626",lineHighlight:"#00000050",gutterBackground:"transparent",gutterForeground:"#8a919966"},styles:[{tag:o.tags.keyword,color:"#c792ea"},{tag:o.tags.operator,color:"#89ddff"},{tag:o.tags.special(o.tags.variableName),color:"#eeffff"},{tag:o.tags.typeName,color:"#c3e88d"},{tag:o.tags.atom,color:"#f78c6c"},{tag:o.tags.number,color:"#c3e88d"},{tag:o.tags.definition(o.tags.variableName),color:"#82aaff"},{tag:o.tags.string,color:"#c3e88d"},{tag:o.tags.special(o.tags.string),color:"#c3e88d"},{tag:o.tags.comment,color:"#7d8799"},{tag:o.tags.variableName,color:"#c792ea"},{tag:o.tags.tagName,color:"#c3e88d"},{tag:o.tags.bracket,color:"#525154"},{tag:o.tags.meta,color:"#ffcb6b"},{tag:o.tags.attributeName,color:"#c792ea"},{tag:o.tags.propertyName,color:"#c792ea"},{tag:o.tags.className,color:"#decb6b"},{tag:o.tags.invalid,color:"#ffffff"}]});const P=R.StateEffect.define(),re=R.StateField.define({create(){return b.Decoration.none},update(e,r){try{for(let a of r.effects)if(a.is(P))if(a.value){const s=b.Decoration.mark({attributes:{style:"background-color: #FFCA2880"}});e=b.Decoration.set([s.range(0,r.newDoc.length)])}else e=b.Decoration.set([]);return e}catch(a){return console.warn("flash error",a),e}},provide:e=>b.EditorView.decorations.from(e)}),B=e=>{e.dispatch({effects:P.of(!0)}),setTimeout(()=>{e.dispatch({effects:P.of(!1)})},200)},N=R.StateEffect.define(),oe=R.StateField.define({create(){return b.Decoration.none},update(e,r){try{for(let a of r.effects)if(a.is(N)){const s=a.value.map(c=>(c.context.locations||[]).map(({start:m,end:u})=>{const d=c.context.color||"#FFCA28";let i=r.newDoc.line(m.line).from+m.column,l=r.newDoc.line(u.line).from+u.column;const h=r.newDoc.length;return i>h||l>h?void 0:b.Decoration.mark({attributes:{style:`outline: 1.5px solid ${d};`}}).range(i,l)})).flat().filter(Boolean)||[];e=b.Decoration.set(s,!0)}return e}catch{return b.Decoration.set([])}},provide:e=>b.EditorView.decorations.from(e)}),ae=[Q.javascript(),te,oe,re];function I({value:e,onChange:r,onViewChanged:a,onSelectionChange:s,options:c,editorDidMount:m}){const u=t.useCallback(l=>{r?.(l)},[r]),d=t.useCallback(l=>{a?.(l)},[a]),i=t.useCallback(l=>{l.selectionSet&&s&&s?.(l.state.selection)},[s]);return n.default.createElement(n.default.Fragment,null,n.default.createElement(ee.default,{value:e,onChange:u,onCreateEditor:d,onUpdate:i,extensions:ae}))}function H(...e){return e.filter(Boolean).join(" ")}function K({view:e,pattern:r,active:a,getTime:s}){const c=t.useRef([]),m=t.useRef();t.useEffect(()=>{if(e)if(r&&a){let d=function(){try{const i=s(),h=[Math.max(m.current||i,i-1/10,0),i+1/60];m.current=h[1],c.current=c.current.filter(p=>p.whole.end>i);const v=r.queryArc(...h).filter(p=>p.hasOnset());c.current=c.current.concat(v),e.dispatch({effects:N.of(c.current)})}catch{e.dispatch({effects:N.of([])})}u=requestAnimationFrame(d)},u=requestAnimationFrame(d);return()=>{cancelAnimationFrame(u)}}else c.current=[],e.dispatch({effects:N.of([])})},[r,a,e])}const ne="_container_3i85k_1",se="_header_3i85k_5",ce="_buttons_3i85k_9",ie="_button_3i85k_9",le="_buttonDisabled_3i85k_17",ue="_error_3i85k_21",de="_body_3i85k_25",E={container:ne,header:se,buttons:ce,button:ie,buttonDisabled:le,error:ue,body:de};function z({type:e}){return n.default.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",className:"sc-h-5 sc-w-5",viewBox:"0 0 20 20",fill:"currentColor"},{refresh:n.default.createElement("path",{fillRule:"evenodd",d:"M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm.008 9.057a1 1 0 011.276.61A5.002 5.002 0 0014.001 13H11a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 01.61-1.276z",clipRule:"evenodd"}),play:n.default.createElement("path",{fillRule:"evenodd",d:"M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z",clipRule:"evenodd"}),pause:n.default.createElement("path",{fillRule:"evenodd",d:"M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 012 0v4a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v4a1 1 0 102 0V8a1 1 0 00-1-1z",clipRule:"evenodd"})}[e])}function O({defaultOutput:e,interval:r,getTime:a,evalOnMount:s=!1,initialCode:c="",autolink:m=!1,beforeEval:u,afterEval:d,onEvalError:i,onToggle:l}){const[h,v]=t.useState(),[p,D]=t.useState(),[w,k]=t.useState(c),[y,q]=t.useState(),[F,_]=t.useState(),[C,A]=t.useState(!1),M=w!==y,{scheduler:f,evaluate:x,start:U,stop:J,pause:$}=t.useMemo(()=>Y.repl({interval:r,defaultOutput:e,onSchedulerError:v,onEvalError:g=>{D(g),i?.(g)},getTime:a,transpiler:Z.transpiler,beforeEval:({code:g})=>{k(g),u?.()},afterEval:({pattern:g,code:T})=>{q(T),_(g),D(),v(),m&&(window.location.hash="#"+encodeURIComponent(btoa(T))),d?.()},onToggle:g=>{A(g),l?.(g)}}),[e,r,a]),S=t.useCallback(async(g=!0)=>x(w,g),[x,w]),L=t.useRef();return t.useEffect(()=>{!L.current&&s&&w&&(L.current=!0,S())},[S,s,w]),t.useEffect(()=>()=>{f.stop()},[f]),{code:w,setCode:k,error:h||p,schedulerError:h,scheduler:f,evalError:p,evaluate:x,activateCode:S,activeCode:y,isDirty:M,pattern:F,started:C,start:U,stop:J,pause:$,togglePlay:async()=>{C?f.pause():await S()}}}const fe=()=>V.getAudioContext().currentTime;function ge({tune:e,hideOutsideView:r=!1,init:a,enableKeyboard:s}){const{code:c,setCode:m,evaluate:u,activateCode:d,error:i,isDirty:l,activeCode:h,pattern:v,started:p,scheduler:D,togglePlay:w,stop:k}=O({initialCode:e,defaultOutput:V.webaudioOutput,getTime:fe}),[y,q]=t.useState(),[F,_]=X.useInView({threshold:.01}),C=t.useRef(),A=t.useMemo(()=>((_||!r)&&(C.current=!0),_||C.current),[_,r]);return K({view:y,pattern:v,active:p&&!h?.includes("strudel disable-highlighting"),getTime:()=>D.getPhase()}),t.useLayoutEffect(()=>{if(s){const M=async f=>{(f.ctrlKey||f.altKey)&&(f.code==="Enter"?(f.preventDefault(),B(y),await d()):f.code==="Period"&&(k(),f.preventDefault()))};return window.addEventListener("keydown",M,!0),()=>window.removeEventListener("keydown",M,!0)}},[s,v,c,u,k,y]),n.default.createElement("div",{className:E.container,ref:F},n.default.createElement("div",{className:E.header},n.default.createElement("div",{className:E.buttons},n.default.createElement("button",{className:H(E.button,p?"sc-animate-pulse":""),onClick:()=>w()},n.default.createElement(z,{type:p?"pause":"play"})),n.default.createElement("button",{className:H(l?E.button:E.buttonDisabled),onClick:()=>d()},n.default.createElement(z,{type:"refresh"}))),i&&n.default.createElement("div",{className:E.error},i.message)),n.default.createElement("div",{className:E.body},A&&n.default.createElement(I,{value:c,onChange:m,onViewChanged:q})))}function me(e){return t.useEffect(()=>(window.addEventListener("message",e),()=>window.removeEventListener("message",e)),[e]),t.useCallback(r=>window.postMessage(r,"*"),[])}const he=e=>t.useLayoutEffect(()=>(window.addEventListener("keydown",e,!0),()=>window.removeEventListener("keydown",e,!0)),[e]);exports.CodeMirror=I;exports.MiniRepl=ge;exports.cx=H;exports.flash=B;exports.useHighlighting=K;exports.useKeydown=he;exports.usePostMessage=me;exports.useStrudel=O; +"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const t=require("react"),X=require("@uiw/react-codemirror"),p=require("@codemirror/view"),A=require("@codemirror/state"),Y=require("@codemirror/lang-javascript"),o=require("@lezer/highlight"),Z=require("@uiw/codemirror-themes"),ee=require("react-hook-inview"),B=require("@strudel.cycles/webaudio"),te=require("@strudel.cycles/core"),re=require("@strudel.cycles/transpiler"),I=e=>e&&typeof e=="object"&&"default"in e?e:{default:e},n=I(t),oe=I(X),ae=Z.createTheme({theme:"dark",settings:{background:"#222",foreground:"#75baff",caret:"#ffcc00",selection:"rgba(128, 203, 196, 0.5)",selectionMatch:"#036dd626",lineHighlight:"#00000050",gutterBackground:"transparent",gutterForeground:"#8a919966"},styles:[{tag:o.tags.keyword,color:"#c792ea"},{tag:o.tags.operator,color:"#89ddff"},{tag:o.tags.special(o.tags.variableName),color:"#eeffff"},{tag:o.tags.typeName,color:"#c3e88d"},{tag:o.tags.atom,color:"#f78c6c"},{tag:o.tags.number,color:"#c3e88d"},{tag:o.tags.definition(o.tags.variableName),color:"#82aaff"},{tag:o.tags.string,color:"#c3e88d"},{tag:o.tags.special(o.tags.string),color:"#c3e88d"},{tag:o.tags.comment,color:"#7d8799"},{tag:o.tags.variableName,color:"#c792ea"},{tag:o.tags.tagName,color:"#c3e88d"},{tag:o.tags.bracket,color:"#525154"},{tag:o.tags.meta,color:"#ffcb6b"},{tag:o.tags.attributeName,color:"#c792ea"},{tag:o.tags.propertyName,color:"#c792ea"},{tag:o.tags.className,color:"#decb6b"},{tag:o.tags.invalid,color:"#ffffff"}]});const L=A.StateEffect.define(),ne=A.StateField.define({create(){return p.Decoration.none},update(e,r){try{for(let a of r.effects)if(a.is(L))if(a.value){const s=p.Decoration.mark({attributes:{style:"background-color: #FFCA2880"}});e=p.Decoration.set([s.range(0,r.newDoc.length)])}else e=p.Decoration.set([]);return e}catch(a){return console.warn("flash error",a),e}},provide:e=>p.EditorView.decorations.from(e)}),K=e=>{e.dispatch({effects:L.of(!0)}),setTimeout(()=>{e.dispatch({effects:L.of(!1)})},200)},x=A.StateEffect.define(),se=A.StateField.define({create(){return p.Decoration.none},update(e,r){try{for(let a of r.effects)if(a.is(x)){const s=a.value.map(c=>(c.context.locations||[]).map(({start:g,end:d})=>{const f=c.context.color||"#FFCA28";let i=r.newDoc.line(g.line).from+g.column,l=r.newDoc.line(d.line).from+d.column;const m=r.newDoc.length;return i>m||l>m?void 0:p.Decoration.mark({attributes:{style:`outline: 1.5px solid ${f};`}}).range(i,l)})).flat().filter(Boolean)||[];e=p.Decoration.set(s,!0)}return e}catch{return p.Decoration.set([])}},provide:e=>p.EditorView.decorations.from(e)}),ce=[Y.javascript(),ae,se,ne];function O({value:e,onChange:r,onViewChanged:a,onSelectionChange:s,options:c,editorDidMount:g}){const d=t.useCallback(l=>{r?.(l)},[r]),f=t.useCallback(l=>{a?.(l)},[a]),i=t.useCallback(l=>{l.selectionSet&&s&&s?.(l.state.selection)},[s]);return n.default.createElement(n.default.Fragment,null,n.default.createElement(oe.default,{value:e,onChange:d,onCreateEditor:f,onUpdate:i,extensions:ce}))}function T(...e){return e.filter(Boolean).join(" ")}function U({view:e,pattern:r,active:a,getTime:s}){const c=t.useRef([]),g=t.useRef();t.useEffect(()=>{if(e)if(r&&a){let f=function(){try{const i=s(),m=[Math.max(g.current||i,i-1/10,0),i+1/60];g.current=m[1],c.current=c.current.filter(h=>h.whole.end>i);const v=r.queryArc(...m).filter(h=>h.hasOnset());c.current=c.current.concat(v),e.dispatch({effects:x.of(c.current)})}catch{e.dispatch({effects:x.of([])})}d=requestAnimationFrame(f)},d=requestAnimationFrame(f);return()=>{cancelAnimationFrame(d)}}else c.current=[],e.dispatch({effects:x.of([])})},[r,a,e])}const ie="_container_3i85k_1",le="_header_3i85k_5",ue="_buttons_3i85k_9",de="_button_3i85k_9",fe="_buttonDisabled_3i85k_17",ge="_error_3i85k_21",me="_body_3i85k_25",E={container:ie,header:le,buttons:ue,button:de,buttonDisabled:fe,error:ge,body:me};function j({type:e}){return n.default.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",className:"sc-h-5 sc-w-5",viewBox:"0 0 20 20",fill:"currentColor"},{refresh:n.default.createElement("path",{fillRule:"evenodd",d:"M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm.008 9.057a1 1 0 011.276.61A5.002 5.002 0 0014.001 13H11a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 01.61-1.276z",clipRule:"evenodd"}),play:n.default.createElement("path",{fillRule:"evenodd",d:"M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z",clipRule:"evenodd"}),pause:n.default.createElement("path",{fillRule:"evenodd",d:"M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 012 0v4a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v4a1 1 0 102 0V8a1 1 0 00-1-1z",clipRule:"evenodd"})}[e])}function J(e){return t.useEffect(()=>(window.addEventListener("message",e),()=>window.removeEventListener("message",e)),[e]),t.useCallback(r=>window.postMessage(r,"*"),[])}function $({defaultOutput:e,interval:r,getTime:a,evalOnMount:s=!1,initialCode:c="",autolink:g=!1,beforeEval:d,afterEval:f,onEvalError:i,onToggle:l}){const m=t.useMemo(()=>he(),[]),[v,h]=t.useState(),[_,C]=t.useState(),[b,y]=t.useState(c),[M,P]=t.useState(),[k,D]=t.useState(),[S,N]=t.useState(!1),w=b!==M,{scheduler:R,evaluate:H,start:G,stop:z,pause:Q}=t.useMemo(()=>te.repl({interval:r,defaultOutput:e,onSchedulerError:h,onEvalError:u=>{C(u),i?.(u)},getTime:a,transpiler:re.transpiler,beforeEval:({code:u})=>{y(u),d?.()},afterEval:({pattern:u,code:F})=>{P(F),D(u),C(),h(),g&&(window.location.hash="#"+encodeURIComponent(btoa(F))),f?.()},onToggle:u=>{N(u),l?.(u)}}),[e,r,a]),W=J(({data:{from:u,type:F}})=>{F==="start"&&u!==m&&z()}),q=t.useCallback(async(u=!0)=>{await H(b,u),W({type:"start",from:m})},[H,b]),V=t.useRef();return t.useEffect(()=>{!V.current&&s&&b&&(V.current=!0,q())},[q,s,b]),t.useEffect(()=>()=>{R.stop()},[R]),{code:b,setCode:y,error:v||_,schedulerError:v,scheduler:R,evalError:_,evaluate:H,activateCode:q,activeCode:M,isDirty:w,pattern:k,started:S,start:G,stop:z,pause:Q,togglePlay:async()=>{S?R.pause():await q()}}}function he(){return Math.floor((1+Math.random())*65536).toString(16).substring(1)}const pe=()=>B.getAudioContext().currentTime;function be({tune:e,hideOutsideView:r=!1,init:a,enableKeyboard:s}){const{code:c,setCode:g,evaluate:d,activateCode:f,error:i,isDirty:l,activeCode:m,pattern:v,started:h,scheduler:_,togglePlay:C,stop:b}=$({initialCode:e,defaultOutput:B.webaudioOutput,getTime:pe}),[y,M]=t.useState(),[P,k]=ee.useInView({threshold:.01}),D=t.useRef(),S=t.useMemo(()=>((k||!r)&&(D.current=!0),k||D.current),[k,r]);return U({view:y,pattern:v,active:h&&!m?.includes("strudel disable-highlighting"),getTime:()=>_.getPhase()}),t.useLayoutEffect(()=>{if(s){const N=async w=>{(w.ctrlKey||w.altKey)&&(w.code==="Enter"?(w.preventDefault(),K(y),await f()):w.code==="Period"&&(b(),w.preventDefault()))};return window.addEventListener("keydown",N,!0),()=>window.removeEventListener("keydown",N,!0)}},[s,v,c,d,b,y]),n.default.createElement("div",{className:E.container,ref:P},n.default.createElement("div",{className:E.header},n.default.createElement("div",{className:E.buttons},n.default.createElement("button",{className:T(E.button,h?"sc-animate-pulse":""),onClick:()=>C()},n.default.createElement(j,{type:h?"pause":"play"})),n.default.createElement("button",{className:T(l?E.button:E.buttonDisabled),onClick:()=>f()},n.default.createElement(j,{type:"refresh"}))),i&&n.default.createElement("div",{className:E.error},i.message)),n.default.createElement("div",{className:E.body},S&&n.default.createElement(O,{value:c,onChange:g,onViewChanged:M})))}const ve=e=>t.useLayoutEffect(()=>(window.addEventListener("keydown",e,!0),()=>window.removeEventListener("keydown",e,!0)),[e]);exports.CodeMirror=O;exports.MiniRepl=be;exports.cx=T;exports.flash=K;exports.useHighlighting=U;exports.useKeydown=ve;exports.usePostMessage=J;exports.useStrudel=$; diff --git a/packages/react/dist/index.es.js b/packages/react/dist/index.es.js index bbd3b758..499895c3 100644 --- a/packages/react/dist/index.es.js +++ b/packages/react/dist/index.es.js @@ -1,15 +1,15 @@ -import n, { useCallback as N, useRef as x, useEffect as R, useState as w, useMemo as I, useLayoutEffect as K } from "react"; -import Q from "@uiw/react-codemirror"; -import { Decoration as E, EditorView as O } from "@codemirror/view"; -import { StateEffect as j, StateField as U } from "@codemirror/state"; -import { javascript as W } from "@codemirror/lang-javascript"; +import n, { useCallback as _, useRef as H, useEffect as L, useMemo as V, useState as w, useLayoutEffect as j } from "react"; +import X from "@uiw/react-codemirror"; +import { Decoration as E, EditorView as U } from "@codemirror/view"; +import { StateEffect as $, StateField as G } from "@codemirror/state"; +import { javascript as Y } from "@codemirror/lang-javascript"; import { tags as r } from "@lezer/highlight"; -import { createTheme as X } from "@uiw/codemirror-themes"; -import { useInView as Y } from "react-hook-inview"; -import { webaudioOutput as Z, getAudioContext as ee } from "@strudel.cycles/webaudio"; -import { repl as te } from "@strudel.cycles/core"; -import { transpiler as re } from "@strudel.cycles/transpiler"; -const oe = X({ +import { createTheme as Z } from "@uiw/codemirror-themes"; +import { useInView as ee } from "react-hook-inview"; +import { webaudioOutput as te, getAudioContext as re } from "@strudel.cycles/webaudio"; +import { repl as oe } from "@strudel.cycles/core"; +import { transpiler as ne } from "@strudel.cycles/transpiler"; +const ae = Z({ theme: "dark", settings: { background: "#222", @@ -42,14 +42,14 @@ const oe = X({ { tag: r.invalid, color: "#ffffff" } ] }); -const T = j.define(), ne = U.define({ +const B = $.define(), se = G.define({ create() { return E.none; }, update(e, t) { try { for (let o of t.effects) - if (o.is(T)) + if (o.is(B)) if (o.value) { const a = E.mark({ attributes: { style: "background-color: #FFCA2880" } }); e = E.set([a.range(0, t.newDoc.length)]); @@ -60,25 +60,25 @@ const T = j.define(), ne = U.define({ return console.warn("flash error", o), e; } }, - provide: (e) => O.decorations.from(e) -}), ae = (e) => { - e.dispatch({ effects: T.of(!0) }), setTimeout(() => { - e.dispatch({ effects: T.of(!1) }); + provide: (e) => U.decorations.from(e) +}), ce = (e) => { + e.dispatch({ effects: B.of(!0) }), setTimeout(() => { + e.dispatch({ effects: B.of(!1) }); }, 200); -}, A = j.define(), se = U.define({ +}, z = $.define(), ie = G.define({ create() { return E.none; }, update(e, t) { try { for (let o of t.effects) - if (o.is(A)) { + if (o.is(z)) { const a = o.value.map( - (s) => (s.context.locations || []).map(({ start: m, end: l }) => { - const d = s.context.color || "#FFCA28"; - let c = t.newDoc.line(m.line).from + m.column, i = t.newDoc.line(l.line).from + l.column; - const g = t.newDoc.length; - return c > g || i > g ? void 0 : E.mark({ attributes: { style: `outline: 1.5px solid ${d};` } }).range(c, i); + (s) => (s.context.locations || []).map(({ start: f, end: d }) => { + const u = s.context.color || "#FFCA28"; + let c = t.newDoc.line(f.line).from + f.column, i = t.newDoc.line(d.line).from + d.column; + const m = t.newDoc.length; + return c > m || i > m ? void 0 : E.mark({ attributes: { style: `outline: 1.5px solid ${u};` } }).range(c, i); }) ).flat().filter(Boolean) || []; e = E.set(a, !0); @@ -88,69 +88,69 @@ const T = j.define(), ne = U.define({ return E.set([]); } }, - provide: (e) => O.decorations.from(e) -}), ce = [W(), oe, se, ne]; -function ie({ value: e, onChange: t, onViewChanged: o, onSelectionChange: a, options: s, editorDidMount: m }) { - const l = N( + provide: (e) => U.decorations.from(e) +}), le = [Y(), ae, ie, se]; +function de({ value: e, onChange: t, onViewChanged: o, onSelectionChange: a, options: s, editorDidMount: f }) { + const d = _( (i) => { t?.(i); }, [t] - ), d = N( + ), u = _( (i) => { o?.(i); }, [o] - ), c = N( + ), c = _( (i) => { i.selectionSet && a && a?.(i.state.selection); }, [a] ); - return /* @__PURE__ */ n.createElement(n.Fragment, null, /* @__PURE__ */ n.createElement(Q, { + return /* @__PURE__ */ n.createElement(n.Fragment, null, /* @__PURE__ */ n.createElement(X, { value: e, - onChange: l, - onCreateEditor: d, + onChange: d, + onCreateEditor: u, onUpdate: c, - extensions: ce + extensions: le })); } -function B(...e) { +function K(...e) { return e.filter(Boolean).join(" "); } -function le({ view: e, pattern: t, active: o, getTime: a }) { - const s = x([]), m = x(); - R(() => { +function ue({ view: e, pattern: t, active: o, getTime: a }) { + const s = H([]), f = H(); + L(() => { if (e) if (t && o) { - let d = function() { + let u = function() { try { - const c = a(), g = [Math.max(m.current || c, c - 1 / 10, 0), c + 1 / 60]; - m.current = g[1], s.current = s.current.filter((p) => p.whole.end > c); - const h = t.queryArc(...g).filter((p) => p.hasOnset()); - s.current = s.current.concat(h), e.dispatch({ effects: A.of(s.current) }); + const c = a(), m = [Math.max(f.current || c, c - 1 / 10, 0), c + 1 / 60]; + f.current = m[1], s.current = s.current.filter((g) => g.whole.end > c); + const h = t.queryArc(...m).filter((g) => g.hasOnset()); + s.current = s.current.concat(h), e.dispatch({ effects: z.of(s.current) }); } catch { - e.dispatch({ effects: A.of([]) }); + e.dispatch({ effects: z.of([]) }); } - l = requestAnimationFrame(d); - }, l = requestAnimationFrame(d); + d = requestAnimationFrame(u); + }, d = requestAnimationFrame(u); return () => { - cancelAnimationFrame(l); + cancelAnimationFrame(d); }; } else - s.current = [], e.dispatch({ effects: A.of([]) }); + s.current = [], e.dispatch({ effects: z.of([]) }); }, [t, o, e]); } -const de = "_container_3i85k_1", ue = "_header_3i85k_5", fe = "_buttons_3i85k_9", me = "_button_3i85k_9", ge = "_buttonDisabled_3i85k_17", pe = "_error_3i85k_21", he = "_body_3i85k_25", b = { - container: de, - header: ue, - buttons: fe, - button: me, - buttonDisabled: ge, - error: pe, - body: he +const fe = "_container_3i85k_1", me = "_header_3i85k_5", ge = "_buttons_3i85k_9", pe = "_button_3i85k_9", he = "_buttonDisabled_3i85k_17", be = "_error_3i85k_21", ve = "_body_3i85k_25", v = { + container: fe, + header: me, + buttons: ge, + button: pe, + buttonDisabled: he, + error: be, + body: ve }; -function q({ type: e }) { +function O({ type: e }) { return /* @__PURE__ */ n.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "sc-h-5 sc-w-5", @@ -174,137 +174,147 @@ function q({ type: e }) { }) }[e]); } -function ve({ +function Ee(e) { + return L(() => (window.addEventListener("message", e), () => window.removeEventListener("message", e)), [e]), _((t) => window.postMessage(t, "*"), []); +} +function we({ defaultOutput: e, interval: t, getTime: o, evalOnMount: a = !1, initialCode: s = "", - autolink: m = !1, - beforeEval: l, - afterEval: d, + autolink: f = !1, + beforeEval: d, + afterEval: u, onEvalError: c, onToggle: i }) { - const [g, h] = w(), [p, D] = w(), [v, k] = w(s), [y, P] = w(), [z, _] = w(), [C, H] = w(!1), F = v !== y, { scheduler: u, evaluate: L, start: $, stop: G, pause: J } = I( - () => te({ + const m = V(() => ye(), []), [h, g] = w(), [C, N] = w(), [p, y] = w(s), [M, S] = w(), [k, D] = w(), [F, x] = w(!1), b = p !== M, { scheduler: A, evaluate: T, start: J, stop: q, pause: Q } = V( + () => oe({ interval: t, defaultOutput: e, - onSchedulerError: h, - onEvalError: (f) => { - D(f), c?.(f); + onSchedulerError: g, + onEvalError: (l) => { + N(l), c?.(l); }, getTime: o, - transpiler: re, - beforeEval: ({ code: f }) => { - k(f), l?.(); + transpiler: ne, + beforeEval: ({ code: l }) => { + y(l), d?.(); }, - afterEval: ({ pattern: f, code: S }) => { - P(S), _(f), D(), h(), m && (window.location.hash = "#" + encodeURIComponent(btoa(S))), d?.(); + afterEval: ({ pattern: l, code: P }) => { + S(P), D(l), N(), g(), f && (window.location.hash = "#" + encodeURIComponent(btoa(P))), u?.(); }, - onToggle: (f) => { - H(f), i?.(f); + onToggle: (l) => { + x(l), i?.(l); } }), [e, t, o] - ), M = N(async (f = !0) => L(v, f), [L, v]), V = x(); - return R(() => { - !V.current && a && v && (V.current = !0, M()); - }, [M, a, v]), R(() => () => { - u.stop(); - }, [u]), { - code: v, - setCode: k, - error: g || p, - schedulerError: g, - scheduler: u, - evalError: p, - evaluate: L, - activateCode: M, - activeCode: y, - isDirty: F, - pattern: z, - started: C, - start: $, - stop: G, - pause: J, + ), W = Ee(({ data: { from: l, type: P } }) => { + P === "start" && l !== m && q(); + }), R = _( + async (l = !0) => { + await T(p, l), W({ type: "start", from: m }); + }, + [T, p] + ), I = H(); + return L(() => { + !I.current && a && p && (I.current = !0, R()); + }, [R, a, p]), L(() => () => { + A.stop(); + }, [A]), { + code: p, + setCode: y, + error: h || C, + schedulerError: h, + scheduler: A, + evalError: C, + evaluate: T, + activateCode: R, + activeCode: M, + isDirty: b, + pattern: k, + started: F, + start: J, + stop: q, + pause: Q, togglePlay: async () => { - C ? u.pause() : await M(); + F ? A.pause() : await R(); } }; } -const be = () => ee().currentTime; -function Pe({ tune: e, hideOutsideView: t = !1, init: o, enableKeyboard: a }) { +function ye() { + return Math.floor((1 + Math.random()) * 65536).toString(16).substring(1); +} +const ke = () => re().currentTime; +function Se({ tune: e, hideOutsideView: t = !1, init: o, enableKeyboard: a }) { const { code: s, - setCode: m, - evaluate: l, - activateCode: d, + setCode: f, + evaluate: d, + activateCode: u, error: c, isDirty: i, - activeCode: g, + activeCode: m, pattern: h, - started: p, - scheduler: D, - togglePlay: v, - stop: k - } = ve({ + started: g, + scheduler: C, + togglePlay: N, + stop: p + } = we({ initialCode: e, - defaultOutput: Z, - getTime: be - }), [y, P] = w(), [z, _] = Y({ + defaultOutput: te, + getTime: ke + }), [y, M] = w(), [S, k] = ee({ threshold: 0.01 - }), C = x(), H = I(() => ((_ || !t) && (C.current = !0), _ || C.current), [_, t]); - return le({ + }), D = H(), F = V(() => ((k || !t) && (D.current = !0), k || D.current), [k, t]); + return ue({ view: y, pattern: h, - active: p && !g?.includes("strudel disable-highlighting"), - getTime: () => D.getPhase() - }), K(() => { + active: g && !m?.includes("strudel disable-highlighting"), + getTime: () => C.getPhase() + }), j(() => { if (a) { - const F = async (u) => { - (u.ctrlKey || u.altKey) && (u.code === "Enter" ? (u.preventDefault(), ae(y), await d()) : u.code === "Period" && (k(), u.preventDefault())); + const x = async (b) => { + (b.ctrlKey || b.altKey) && (b.code === "Enter" ? (b.preventDefault(), ce(y), await u()) : b.code === "Period" && (p(), b.preventDefault())); }; - return window.addEventListener("keydown", F, !0), () => window.removeEventListener("keydown", F, !0); + return window.addEventListener("keydown", x, !0), () => window.removeEventListener("keydown", x, !0); } - }, [a, h, s, l, k, y]), /* @__PURE__ */ n.createElement("div", { - className: b.container, - ref: z + }, [a, h, s, d, p, y]), /* @__PURE__ */ n.createElement("div", { + className: v.container, + ref: S }, /* @__PURE__ */ n.createElement("div", { - className: b.header + className: v.header }, /* @__PURE__ */ n.createElement("div", { - className: b.buttons + className: v.buttons }, /* @__PURE__ */ n.createElement("button", { - className: B(b.button, p ? "sc-animate-pulse" : ""), - onClick: () => v() - }, /* @__PURE__ */ n.createElement(q, { - type: p ? "pause" : "play" + className: K(v.button, g ? "sc-animate-pulse" : ""), + onClick: () => N() + }, /* @__PURE__ */ n.createElement(O, { + type: g ? "pause" : "play" })), /* @__PURE__ */ n.createElement("button", { - className: B(i ? b.button : b.buttonDisabled), - onClick: () => d() - }, /* @__PURE__ */ n.createElement(q, { + className: K(i ? v.button : v.buttonDisabled), + onClick: () => u() + }, /* @__PURE__ */ n.createElement(O, { type: "refresh" }))), c && /* @__PURE__ */ n.createElement("div", { - className: b.error + className: v.error }, c.message)), /* @__PURE__ */ n.createElement("div", { - className: b.body - }, H && /* @__PURE__ */ n.createElement(ie, { + className: v.body + }, F && /* @__PURE__ */ n.createElement(de, { value: s, - onChange: m, - onViewChanged: P + onChange: f, + onViewChanged: M }))); } -function ze(e) { - return R(() => (window.addEventListener("message", e), () => window.removeEventListener("message", e)), [e]), N((t) => window.postMessage(t, "*"), []); -} -const He = (e) => K(() => (window.addEventListener("keydown", e, !0), () => window.removeEventListener("keydown", e, !0)), [e]); +const Te = (e) => j(() => (window.addEventListener("keydown", e, !0), () => window.removeEventListener("keydown", e, !0)), [e]); export { - ie as CodeMirror, - Pe as MiniRepl, - B as cx, - ae as flash, - le as useHighlighting, - He as useKeydown, - ze as usePostMessage, - ve as useStrudel + de as CodeMirror, + Se as MiniRepl, + K as cx, + ce as flash, + ue as useHighlighting, + Te as useKeydown, + Ee as usePostMessage, + we as useStrudel }; diff --git a/packages/react/src/hooks/useStrudel.mjs b/packages/react/src/hooks/useStrudel.mjs index 14fabfb4..82326415 100644 --- a/packages/react/src/hooks/useStrudel.mjs +++ b/packages/react/src/hooks/useStrudel.mjs @@ -1,6 +1,7 @@ import { useRef, useCallback, useEffect, useMemo, useState } from 'react'; import { repl } from '@strudel.cycles/core'; import { transpiler } from '@strudel.cycles/transpiler'; +import usePostMessage from './usePostMessage.mjs'; function useStrudel({ defaultOutput, @@ -14,6 +15,7 @@ function useStrudel({ onEvalError, onToggle, }) { + const id = useMemo(() => s4(), []); // scheduler const [schedulerError, setSchedulerError] = useState(); const [evalError, setEvalError] = useState(); @@ -57,7 +59,19 @@ function useStrudel({ }), [defaultOutput, interval, getTime], ); - const activateCode = useCallback(async (autostart = true) => evaluate(code, autostart), [evaluate, code]); + const broadcast = usePostMessage(({ data: { from, type } }) => { + if (type === 'start' && from !== id) { + // console.log('message', from, type); + stop(); + } + }); + const activateCode = useCallback( + async (autostart = true) => { + await evaluate(code, autostart); + broadcast({ type: 'start', from: id }); + }, + [evaluate, code], + ); const inited = useRef(); useEffect(() => { @@ -103,3 +117,9 @@ function useStrudel({ } export default useStrudel; + +function s4() { + return Math.floor((1 + Math.random()) * 0x10000) + .toString(16) + .substring(1); +} diff --git a/tutorial/MiniRepl.jsx b/tutorial/MiniRepl.jsx index ef63d563..c86a83fd 100644 --- a/tutorial/MiniRepl.jsx +++ b/tutorial/MiniRepl.jsx @@ -19,7 +19,7 @@ evalScope( import('@strudel.cycles/osc'), ); -prebake(); +// prebake(); export function MiniRepl({ tune }) { return <_MiniRepl tune={tune} hideOutsideView={true} />;