From f34d0a29e8b953c8671b98e3e8b8679d952bcb18 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Sat, 13 Aug 2022 18:39:38 +0200 Subject: [PATCH 1/2] memo all things codemirror --- packages/react/dist/index.cjs.js | 4 +- packages/react/dist/index.es.js | 63 ++++++++++++------- packages/react/src/components/CodeMirror6.jsx | 39 ++++++++---- 3 files changed, 70 insertions(+), 36 deletions(-) diff --git a/packages/react/dist/index.cjs.js b/packages/react/dist/index.cjs.js index ed1e922c..70d80108 100644 --- a/packages/react/dist/index.cjs.js +++ b/packages/react/dist/index.cjs.js @@ -1,3 +1,3 @@ -"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});var t=require("react"),re=require("@uiw/react-codemirror"),E=require("@codemirror/view"),L=require("@codemirror/state"),oe=require("@codemirror/lang-javascript"),l=require("@lezer/highlight"),se=require("@uiw/codemirror-themes"),ne=require("react-hook-inview"),ce=require("@strudel.cycles/eval"),ie=require("@strudel.cycles/core/util.mjs"),y=require("@strudel.cycles/tone"),O=require("@strudel.cycles/core"),M=require("@strudel.cycles/midi");function K(e){return e&&typeof e=="object"&&"default"in e?e:{default:e}}var g=K(t),le=K(re),ue=se.createTheme({theme:"dark",settings:{background:"#222",foreground:"#75baff",caret:"#ffcc00",selection:"rgba(128, 203, 196, 0.5)",selectionMatch:"#036dd626",lineHighlight:"#8a91991a",gutterBackground:"transparent",gutterForeground:"#676e95"},styles:[{tag:l.tags.keyword,color:"#c792ea"},{tag:l.tags.operator,color:"#89ddff"},{tag:l.tags.special(l.tags.variableName),color:"#eeffff"},{tag:l.tags.typeName,color:"#f07178"},{tag:l.tags.atom,color:"#f78c6c"},{tag:l.tags.number,color:"#ff5370"},{tag:l.tags.definition(l.tags.variableName),color:"#82aaff"},{tag:l.tags.string,color:"#c3e88d"},{tag:l.tags.special(l.tags.string),color:"#f07178"},{tag:l.tags.comment,color:"#7d8799"},{tag:l.tags.variableName,color:"#f07178"},{tag:l.tags.tagName,color:"#ff5370"},{tag:l.tags.bracket,color:"#a2a1a4"},{tag:l.tags.meta,color:"#ffcb6b"},{tag:l.tags.attributeName,color:"#c792ea"},{tag:l.tags.propertyName,color:"#c792ea"},{tag:l.tags.className,color:"#decb6b"},{tag:l.tags.invalid,color:"#ffffff"}]});const V=L.StateEffect.define(),de=L.StateField.define({create(){return E.Decoration.none},update(e,r){try{for(let n of r.effects)if(n.is(V))if(n.value){const u=E.Decoration.mark({attributes:{style:"background-color: #FFCA2880"}});e=E.Decoration.set([u.range(0,r.newDoc.length)])}else e=E.Decoration.set([]);return e}catch(n){return console.warn("flash error",n),e}},provide:e=>E.EditorView.decorations.from(e)}),Q=e=>{e.dispatch({effects:V.of(!0)}),setTimeout(()=>{e.dispatch({effects:V.of(!1)})},200)},A=L.StateEffect.define(),fe=L.StateField.define({create(){return E.Decoration.none},update(e,r){try{for(let n of r.effects)n.is(A)&&(e=E.Decoration.set(n.value.flatMap(u=>(u.context.locations||[]).map(({start:d,end:i})=>{const s=u.context.color||"#FFCA28";let m=r.newDoc.line(d.line).from+d.column,o=r.newDoc.line(i.line).from+i.column;const c=r.newDoc.length;return m>c||o>c?void 0:E.Decoration.mark({attributes:{style:`outline: 1.5px solid ${s};`}}).range(m,o)})).filter(Boolean),!0));return e}catch{return e}},provide:e=>E.EditorView.decorations.from(e)});function U({value:e,onChange:r,onViewChanged:n,onSelectionChange:u,options:d,editorDidMount:i}){return g.default.createElement(g.default.Fragment,null,g.default.createElement(le.default,{value:e,onChange:s=>{r(s)},onCreateEditor:s=>{n(s)},onUpdate:s=>{s.selectionSet&&u&&u(s.state.selection)},extensions:[oe.javascript(),ue,fe,de]}))}function J(e){const{onEvent:r,onQuery:n,onSchedule:u,ready:d=!0,onDraw:i}=e,[s,m]=t.useState(!1),o=1,c=()=>Math.floor(y.Tone.getTransport().seconds/o),C=(p=c())=>{const S=new O.TimeSpan(p,p+1),N=n?.(new O.State(S))||[];u?.(N,p);const F=S.begin.valueOf();y.Tone.getTransport().cancel(F);const w=(p+1)*o-.5,R=Math.max(y.Tone.getTransport().seconds,w)+.1;y.Tone.getTransport().schedule(()=>{C(p+1)},R),N?.filter(b=>b.part.begin.equals(b.whole?.begin)).forEach(b=>{y.Tone.getTransport().schedule(v=>{r(v,b,y.Tone.getContext().currentTime),y.Tone.Draw.schedule(()=>{i?.(v,b)},v)},b.part.begin.valueOf())})};t.useEffect(()=>{d&&C()},[r,u,n,i,d]);const k=async()=>{m(!0),await y.Tone.start(),y.Tone.getTransport().start("+0.1")},_=()=>{y.Tone.getTransport().pause(),m(!1)};return{start:k,stop:_,onEvent:r,started:s,setStarted:m,toggle:()=>s?_():k(),query:C,activeCycle:c}}function G(e){return t.useEffect(()=>(window.addEventListener("message",e),()=>window.removeEventListener("message",e)),[e]),t.useCallback(r=>window.postMessage(r,"*"),[])}let ge=()=>Math.floor((1+Math.random())*65536).toString(16).substring(1);const me=e=>encodeURIComponent(btoa(e));function X({tune:e,defaultSynth:r,autolink:n=!0,onEvent:u,onDraw:d}){const i=t.useMemo(()=>ge(),[]),[s,m]=t.useState(e),[o,c]=t.useState(),[C,k]=t.useState(""),[_,T]=t.useState(),[p,S]=t.useState(!1),[N,F]=t.useState(""),[w,R]=t.useState(),b=t.useMemo(()=>s!==o||_,[s,o,_]),v=t.useCallback(f=>k(a=>a+`${a?` +"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});var t=require("react"),oe=require("@uiw/react-codemirror"),E=require("@codemirror/view"),L=require("@codemirror/state"),re=require("@codemirror/lang-javascript"),u=require("@lezer/highlight"),se=require("@uiw/codemirror-themes"),ne=require("react-hook-inview"),ce=require("@strudel.cycles/eval"),le=require("@strudel.cycles/core/util.mjs"),y=require("@strudel.cycles/tone"),B=require("@strudel.cycles/core"),M=require("@strudel.cycles/midi");function $(e){return e&&typeof e=="object"&&"default"in e?e:{default:e}}var m=$(t),ie=$(oe),ue=se.createTheme({theme:"dark",settings:{background:"#222",foreground:"#75baff",caret:"#ffcc00",selection:"rgba(128, 203, 196, 0.5)",selectionMatch:"#036dd626",lineHighlight:"#8a91991a",gutterBackground:"transparent",gutterForeground:"#676e95"},styles:[{tag:u.tags.keyword,color:"#c792ea"},{tag:u.tags.operator,color:"#89ddff"},{tag:u.tags.special(u.tags.variableName),color:"#eeffff"},{tag:u.tags.typeName,color:"#f07178"},{tag:u.tags.atom,color:"#f78c6c"},{tag:u.tags.number,color:"#ff5370"},{tag:u.tags.definition(u.tags.variableName),color:"#82aaff"},{tag:u.tags.string,color:"#c3e88d"},{tag:u.tags.special(u.tags.string),color:"#f07178"},{tag:u.tags.comment,color:"#7d8799"},{tag:u.tags.variableName,color:"#f07178"},{tag:u.tags.tagName,color:"#ff5370"},{tag:u.tags.bracket,color:"#a2a1a4"},{tag:u.tags.meta,color:"#ffcb6b"},{tag:u.tags.attributeName,color:"#c792ea"},{tag:u.tags.propertyName,color:"#c792ea"},{tag:u.tags.className,color:"#decb6b"},{tag:u.tags.invalid,color:"#ffffff"}]});const P=L.StateEffect.define(),de=L.StateField.define({create(){return E.Decoration.none},update(e,o){try{for(let n of o.effects)if(n.is(P))if(n.value){const c=E.Decoration.mark({attributes:{style:"background-color: #FFCA2880"}});e=E.Decoration.set([c.range(0,o.newDoc.length)])}else e=E.Decoration.set([]);return e}catch(n){return console.warn("flash error",n),e}},provide:e=>E.EditorView.decorations.from(e)}),K=e=>{e.dispatch({effects:P.of(!0)}),setTimeout(()=>{e.dispatch({effects:P.of(!1)})},200)},A=L.StateEffect.define(),fe=L.StateField.define({create(){return E.Decoration.none},update(e,o){try{for(let n of o.effects)n.is(A)&&(e=E.Decoration.set(n.value.flatMap(c=>(c.context.locations||[]).map(({start:f,end:l})=>{const i=c.context.color||"#FFCA28";let d=o.newDoc.line(f.line).from+f.column,r=o.newDoc.line(l.line).from+l.column;const a=o.newDoc.length;return d>a||r>a?void 0:E.Decoration.mark({attributes:{style:`outline: 1.5px solid ${i};`}}).range(d,r)})).filter(Boolean),!0));return e}catch{return e}},provide:e=>E.EditorView.decorations.from(e)}),ge=[re.javascript(),ue,fe,de];function Q({value:e,onChange:o,onViewChanged:n,onSelectionChange:c,options:f,editorDidMount:l}){const i=t.useCallback(a=>{o?.(a)},[o]),d=t.useCallback(a=>{n?.(a)},[n]),r=t.useCallback(a=>{a.selectionSet&&c&&c?.(a.state.selection)},[c]);return m.default.createElement(m.default.Fragment,null,m.default.createElement(ie.default,{value:e,onChange:i,onCreateEditor:d,onUpdate:r,extensions:ge}))}function J(e){const{onEvent:o,onQuery:n,onSchedule:c,ready:f=!0,onDraw:l}=e,[i,d]=t.useState(!1),r=1,a=()=>Math.floor(y.Tone.getTransport().seconds/r),C=(p=a())=>{const S=new B.TimeSpan(p,p+1),N=n?.(new B.State(S))||[];c?.(N,p);const F=S.begin.valueOf();y.Tone.getTransport().cancel(F);const w=(p+1)*r-.5,R=Math.max(y.Tone.getTransport().seconds,w)+.1;y.Tone.getTransport().schedule(()=>{C(p+1)},R),N?.filter(b=>b.part.begin.equals(b.whole?.begin)).forEach(b=>{y.Tone.getTransport().schedule(v=>{o(v,b,y.Tone.getContext().currentTime),y.Tone.Draw.schedule(()=>{l?.(v,b)},v)},b.part.begin.valueOf())})};t.useEffect(()=>{f&&C()},[o,c,n,l,f]);const k=async()=>{d(!0),await y.Tone.start(),y.Tone.getTransport().start("+0.1")},_=()=>{y.Tone.getTransport().pause(),d(!1)};return{start:k,stop:_,onEvent:o,started:i,setStarted:d,toggle:()=>i?_():k(),query:C,activeCycle:a}}function G(e){return t.useEffect(()=>(window.addEventListener("message",e),()=>window.removeEventListener("message",e)),[e]),t.useCallback(o=>window.postMessage(o,"*"),[])}let me=()=>Math.floor((1+Math.random())*65536).toString(16).substring(1);const he=e=>encodeURIComponent(btoa(e));function X({tune:e,defaultSynth:o,autolink:n=!0,onEvent:c,onDraw:f}){const l=t.useMemo(()=>me(),[]),[i,d]=t.useState(e),[r,a]=t.useState(),[C,k]=t.useState(""),[_,T]=t.useState(),[p,S]=t.useState(!1),[N,F]=t.useState(""),[w,R]=t.useState(),b=t.useMemo(()=>i!==r||_,[i,r,_]),v=t.useCallback(g=>k(s=>s+`${s?` -`:""}${f}`),[]),W=t.useMemo(()=>{if(o&&!o.includes("strudel disable-highlighting"))return(f,a)=>d?.(f,a,o)},[o,d]),P=t.useMemo(()=>o&&o.includes("strudel hide-header"),[o]),H=t.useMemo(()=>o&&o.includes("strudel hide-console"),[o]),h=J({onDraw:W,onEvent:t.useCallback((f,a,ee)=>{try{u?.(a),a.context.logs?.length&&a.context.logs.forEach(v);const{onTrigger:q,velocity:te}=a.context;if(q)q(f,a,ee,1);else if(r){const ae=ie.getPlayableNoteValue(a);r.triggerAttackRelease(ae,a.duration.valueOf(),f,te)}else throw new Error("no defaultSynth passed to useRepl.")}catch(q){console.warn(q),q.message="unplayable event: "+q?.message,v(q.message)}},[u,v,r]),onQuery:t.useCallback(f=>{try{return w?.query(f)||[]}catch(a){return console.warn(a),a.message="query error: "+a.message,T(a),[]}},[w]),onSchedule:t.useCallback((f,a)=>Z(f,a),[]),ready:!!w&&!!o}),j=G(({data:{from:f,type:a}})=>{a==="start"&&f!==i&&(h.setStarted(!1),c(void 0))}),B=t.useCallback(async(f=s)=>{if(o&&!b){T(void 0),h.start();return}try{S(!0);const a=await ce.evaluate(f);h.start(),j({type:"start",from:i}),R(()=>a.pattern),n&&(window.location.hash="#"+encodeURIComponent(btoa(s))),F(me(s)),T(void 0),c(f),S(!1)}catch(a){a.message="evaluation error: "+a.message,console.warn(a),T(a)}},[o,b,s,h,n,i,j]),Z=(f,a)=>{f.length};return{hideHeader:P,hideConsole:H,pending:p,code:s,setCode:m,pattern:w,error:_,cycle:h,setPattern:R,dirty:b,log:C,togglePlay:()=>{h.started?h.stop():B()},setActiveCode:c,activateCode:B,activeCode:o,pushLog:v,hash:N}}function z(...e){return e.filter(Boolean).join(" ")}let x=[],I;function Y({view:e,pattern:r,active:n}){t.useEffect(()=>{if(e)if(r&&n){let d=function(){try{const i=y.Tone.getTransport().seconds,m=[Math.max(I||i,i-1/10),i+1/60];I=i+1/60,x=x.filter(c=>c.whole.end>i);const o=r.queryArc(...m).filter(c=>c.hasOnset());x=x.concat(o),e.dispatch({effects:A.of(x)})}catch{e.dispatch({effects:A.of([])})}u=requestAnimationFrame(d)},u=requestAnimationFrame(d);return()=>{cancelAnimationFrame(u)}}else x=[],e.dispatch({effects:A.of([])})},[r,n,e])}const he="_container_3i85k_1",pe="_header_3i85k_5",be="_buttons_3i85k_9",ve="_button_3i85k_9",ye="_buttonDisabled_3i85k_17",we="_error_3i85k_21",Me="_body_3i85k_25";var D={container:he,header:pe,buttons:be,button:ve,buttonDisabled:ye,error:we,body:Me};function $({type:e}){return g.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:g.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:g.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:g.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 Ee({tune:e,defaultSynth:r,hideOutsideView:n=!1,theme:u,init:d,onEvent:i,enableKeyboard:s}){const{code:m,setCode:o,pattern:c,activeCode:C,activateCode:k,evaluateOnly:_,error:T,cycle:p,dirty:S,togglePlay:N,stop:F}=X({tune:e,defaultSynth:r,autolink:!1,onEvent:i});t.useEffect(()=>{d&&_()},[e,d]);const[w,R]=t.useState(),[b,v]=ne.useInView({threshold:.01}),W=t.useRef(),P=t.useMemo(()=>((v||!n)&&(W.current=!0),v||W.current),[v,n]);return Y({view:w,pattern:c,active:p.started&&!C?.includes("strudel disable-highlighting")}),t.useLayoutEffect(()=>{if(s){const H=async h=>{(h.ctrlKey||h.altKey)&&(h.code==="Enter"?(h.preventDefault(),Q(w),await k()):h.code==="Period"&&(p.stop(),h.preventDefault()))};return window.addEventListener("keydown",H,!0),()=>window.removeEventListener("keydown",H,!0)}},[s,c,m,k,p,w]),g.default.createElement("div",{className:D.container,ref:b},g.default.createElement("div",{className:D.header},g.default.createElement("div",{className:D.buttons},g.default.createElement("button",{className:z(D.button,p.started?"sc-animate-pulse":""),onClick:()=>N()},g.default.createElement($,{type:p.started?"pause":"play"})),g.default.createElement("button",{className:z(S?D.button:D.buttonDisabled),onClick:()=>k()},g.default.createElement($,{type:"refresh"}))),T&&g.default.createElement("div",{className:D.error},T.message)),g.default.createElement("div",{className:D.body},P&&g.default.createElement(U,{value:m,onChange:o,onViewChanged:R})))}function Ce(e){const{ready:r,connected:n,disconnected:u}=e,[d,i]=t.useState(!0),[s,m]=t.useState(M.WebMidi?.outputs||[]);return t.useEffect(()=>{M.enableWebMidi().then(()=>{M.WebMidi.addListener("connected",c=>{m([...M.WebMidi.outputs]),n?.(M.WebMidi,c)}),M.WebMidi.addListener("disconnected",c=>{m([...M.WebMidi.outputs]),u?.(M.WebMidi,c)}),r?.(M.WebMidi),i(!1)}).catch(c=>{if(c){console.error(c),console.warn("Web Midi could not be enabled..");return}})},[r,n,u,s]),{loading:d,outputs:s,outputByName:c=>M.WebMidi.getOutputByName(c)}}exports.CodeMirror=U;exports.MiniRepl=Ee;exports.cx=z;exports.flash=Q;exports.useCycle=J;exports.useHighlighting=Y;exports.usePostMessage=G;exports.useRepl=X;exports.useWebMidi=Ce; +`:""}${g}`),[]),W=t.useMemo(()=>{if(r&&!r.includes("strudel disable-highlighting"))return(g,s)=>f?.(g,s,r)},[r,f]),O=t.useMemo(()=>r&&r.includes("strudel hide-header"),[r]),H=t.useMemo(()=>r&&r.includes("strudel hide-console"),[r]),h=J({onDraw:W,onEvent:t.useCallback((g,s,ee)=>{try{c?.(s),s.context.logs?.length&&s.context.logs.forEach(v);const{onTrigger:q,velocity:te}=s.context;if(q)q(g,s,ee,1);else if(o){const ae=le.getPlayableNoteValue(s);o.triggerAttackRelease(ae,s.duration.valueOf(),g,te)}else throw new Error("no defaultSynth passed to useRepl.")}catch(q){console.warn(q),q.message="unplayable event: "+q?.message,v(q.message)}},[c,v,o]),onQuery:t.useCallback(g=>{try{return w?.query(g)||[]}catch(s){return console.warn(s),s.message="query error: "+s.message,T(s),[]}},[w]),onSchedule:t.useCallback((g,s)=>Z(g),[]),ready:!!w&&!!r}),z=G(({data:{from:g,type:s}})=>{s==="start"&&g!==l&&(h.setStarted(!1),a(void 0))}),j=t.useCallback(async(g=i)=>{if(r&&!b){T(void 0),h.start();return}try{S(!0);const s=await ce.evaluate(g);h.start(),z({type:"start",from:l}),R(()=>s.pattern),n&&(window.location.hash="#"+encodeURIComponent(btoa(i))),F(he(i)),T(void 0),a(g),S(!1)}catch(s){s.message="evaluation error: "+s.message,console.warn(s),T(s)}},[r,b,i,h,n,l,z]),Z=(g,s)=>{g.length};return{hideHeader:O,hideConsole:H,pending:p,code:i,setCode:d,pattern:w,error:_,cycle:h,setPattern:R,dirty:b,log:C,togglePlay:()=>{h.started?h.stop():j()},setActiveCode:a,activateCode:j,activeCode:r,pushLog:v,hash:N}}function V(...e){return e.filter(Boolean).join(" ")}let x=[],I;function Y({view:e,pattern:o,active:n}){t.useEffect(()=>{if(e)if(o&&n){let f=function(){try{const l=y.Tone.getTransport().seconds,d=[Math.max(I||l,l-1/10),l+1/60];I=l+1/60,x=x.filter(a=>a.whole.end>l);const r=o.queryArc(...d).filter(a=>a.hasOnset());x=x.concat(r),console.log("update...",e.state.doc.length),e.dispatch({effects:A.of(x)})}catch{e.dispatch({effects:A.of([])})}c=requestAnimationFrame(f)},c=requestAnimationFrame(f);return()=>{cancelAnimationFrame(c)}}else x=[],e.dispatch({effects:A.of([])})},[o,n,e])}const pe="_container_3i85k_1",be="_header_3i85k_5",ve="_buttons_3i85k_9",ye="_button_3i85k_9",we="_buttonDisabled_3i85k_17",Me="_error_3i85k_21",Ee="_body_3i85k_25";var D={container:pe,header:be,buttons:ve,button:ye,buttonDisabled:we,error:Me,body:Ee};function U({type:e}){return m.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:m.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:m.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:m.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 Ce({tune:e,defaultSynth:o,hideOutsideView:n=!1,theme:c,init:f,onEvent:l,enableKeyboard:i}){const{code:d,setCode:r,pattern:a,activeCode:C,activateCode:k,evaluateOnly:_,error:T,cycle:p,dirty:S,togglePlay:N,stop:F}=X({tune:e,defaultSynth:o,autolink:!1,onEvent:l});t.useEffect(()=>{f&&_()},[e,f]);const[w,R]=t.useState(),[b,v]=ne.useInView({threshold:.01}),W=t.useRef(),O=t.useMemo(()=>((v||!n)&&(W.current=!0),v||W.current),[v,n]);return Y({view:w,pattern:a,active:p.started&&!C?.includes("strudel disable-highlighting")}),t.useLayoutEffect(()=>{if(i){const H=async h=>{(h.ctrlKey||h.altKey)&&(h.code==="Enter"?(h.preventDefault(),K(w),await k()):h.code==="Period"&&(p.stop(),h.preventDefault()))};return window.addEventListener("keydown",H,!0),()=>window.removeEventListener("keydown",H,!0)}},[i,a,d,k,p,w]),m.default.createElement("div",{className:D.container,ref:b},m.default.createElement("div",{className:D.header},m.default.createElement("div",{className:D.buttons},m.default.createElement("button",{className:V(D.button,p.started?"sc-animate-pulse":""),onClick:()=>N()},m.default.createElement(U,{type:p.started?"pause":"play"})),m.default.createElement("button",{className:V(S?D.button:D.buttonDisabled),onClick:()=>k()},m.default.createElement(U,{type:"refresh"}))),T&&m.default.createElement("div",{className:D.error},T.message)),m.default.createElement("div",{className:D.body},O&&m.default.createElement(Q,{value:d,onChange:r,onViewChanged:R})))}function ke(e){const{ready:o,connected:n,disconnected:c}=e,[f,l]=t.useState(!0),[i,d]=t.useState(M.WebMidi?.outputs||[]);return t.useEffect(()=>{M.enableWebMidi().then(()=>{M.WebMidi.addListener("connected",a=>{d([...M.WebMidi.outputs]),n?.(M.WebMidi,a)}),M.WebMidi.addListener("disconnected",a=>{d([...M.WebMidi.outputs]),c?.(M.WebMidi,a)}),o?.(M.WebMidi),l(!1)}).catch(a=>{if(a){console.error(a),console.warn("Web Midi could not be enabled..");return}})},[o,n,c,i]),{loading:f,outputs:i,outputByName:a=>M.WebMidi.getOutputByName(a)}}exports.CodeMirror=Q;exports.MiniRepl=Ce;exports.cx=V;exports.flash=K;exports.useCycle=J;exports.useHighlighting=Y;exports.usePostMessage=G;exports.useRepl=X;exports.useWebMidi=ke; diff --git a/packages/react/dist/index.es.js b/packages/react/dist/index.es.js index 0066e8a0..a5650e46 100644 --- a/packages/react/dist/index.es.js +++ b/packages/react/dist/index.es.js @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useCallback, useMemo, useRef, useLayoutEffect } from 'react'; +import React, { useCallback, useState, useEffect, useMemo, useRef, useLayoutEffect } from 'react'; import _CodeMirror from '@uiw/react-codemirror'; import { Decoration, EditorView } from '@codemirror/view'; import { StateEffect, StateField } from '@codemirror/state'; @@ -89,17 +89,22 @@ const highlightField = StateField.define({ try { for (let e of tr.effects) { if (e.is(setHighlights)) { - highlights = Decoration.set(e.value.flatMap((hap) => (hap.context.locations || []).map(({ start, end }) => { - const color = hap.context.color || "#FFCA28"; - let from = tr.newDoc.line(start.line).from + start.column; - let to = tr.newDoc.line(end.line).from + end.column; - const l = tr.newDoc.length; - if (from > l || to > l) { - return; - } - const mark = Decoration.mark({ attributes: { style: `outline: 1.5px solid ${color};` } }); - return mark.range(from, to); - })).filter(Boolean), true); + highlights = Decoration.set( + e.value.flatMap( + (hap) => (hap.context.locations || []).map(({ start, end }) => { + const color = hap.context.color || "#FFCA28"; + let from = tr.newDoc.line(start.line).from + start.column; + let to = tr.newDoc.line(end.line).from + end.column; + const l = tr.newDoc.length; + if (from > l || to > l) { + return; + } + const mark = Decoration.mark({ attributes: { style: `outline: 1.5px solid ${color};` } }); + return mark.range(from, to); + }) + ).filter(Boolean), + true + ); } } return highlights; @@ -109,21 +114,34 @@ const highlightField = StateField.define({ }, provide: (f) => EditorView.decorations.from(f) }); +const extensions = [javascript(), strudelTheme, highlightField, flashField]; function CodeMirror({ value, onChange, onViewChanged, onSelectionChange, options, editorDidMount }) { - return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(_CodeMirror, { - value, - onChange: (value2) => { - onChange(value2); + const handleOnChange = useCallback( + (value2) => { + onChange?.(value2); }, - onCreateEditor: (view) => { - onViewChanged(view); + [onChange] + ); + const handleOnCreateEditor = useCallback( + (view) => { + onViewChanged?.(view); }, - onUpdate: (viewUpdate) => { + [onViewChanged] + ); + const handleOnUpdate = useCallback( + (viewUpdate) => { if (viewUpdate.selectionSet && onSelectionChange) { - onSelectionChange(viewUpdate.state.selection); + onSelectionChange?.(viewUpdate.state.selection); } }, - extensions: [javascript(), strudelTheme, highlightField, flashField] + [onSelectionChange] + ); + return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(_CodeMirror, { + value, + onChange: handleOnChange, + onCreateEditor: handleOnCreateEditor, + onUpdate: handleOnUpdate, + extensions })); } @@ -300,7 +318,7 @@ function useRepl({ tune, defaultSynth, autolink = true, onEvent, onDraw: onDrawP }, [pattern], ), - onSchedule: useCallback((_events, cycle) => logCycle(_events, cycle), []), + onSchedule: useCallback((_events, cycle) => logCycle(_events), []), ready: !!pattern && !!activeCode, }); @@ -405,6 +423,7 @@ function useHighlighting({ view, pattern, active }) { highlights = highlights.filter((hap) => hap.whole.end > audioTime); // keep only highlights that are still active const haps = pattern.queryArc(...span).filter((hap) => hap.hasOnset()); highlights = highlights.concat(haps); // add potential new onsets + console.log('update...', view.state.doc.length); view.dispatch({ effects: setHighlights.of(highlights) }); // highlight all still active + new active haps } catch (err) { // console.log('error in updateHighlights', err); diff --git a/packages/react/src/components/CodeMirror6.jsx b/packages/react/src/components/CodeMirror6.jsx index 3cb77e46..e0f47b75 100644 --- a/packages/react/src/components/CodeMirror6.jsx +++ b/packages/react/src/components/CodeMirror6.jsx @@ -5,6 +5,7 @@ import { StateField, StateEffect } from '@codemirror/state'; import { javascript } from '@codemirror/lang-javascript'; import strudelTheme from '../themes/strudel-theme'; import './style.css'; +import { useCallback } from 'react'; export const setFlash = StateEffect.define(); const flashField = StateField.define({ @@ -78,23 +79,37 @@ const highlightField = StateField.define({ provide: (f) => EditorView.decorations.from(f), }); +const extensions = [javascript(), strudelTheme, highlightField, flashField]; + export default function CodeMirror({ value, onChange, onViewChanged, onSelectionChange, options, editorDidMount }) { + const handleOnChange = useCallback( + (value) => { + onChange?.(value); + }, + [onChange], + ); + const handleOnCreateEditor = useCallback( + (view) => { + onViewChanged?.(view); + }, + [onViewChanged], + ); + const handleOnUpdate = useCallback( + (viewUpdate) => { + if (viewUpdate.selectionSet && onSelectionChange) { + onSelectionChange?.(viewUpdate.state.selection); + } + }, + [onSelectionChange], + ); return ( <> <_CodeMirror value={value} - onChange={(value) => { - onChange(value); - }} - onCreateEditor={(view) => { - onViewChanged(view); - }} - onUpdate={(viewUpdate) => { - if (viewUpdate.selectionSet && onSelectionChange) { - onSelectionChange(viewUpdate.state.selection); - } - }} - extensions={[javascript(), strudelTheme, highlightField, flashField]} + onChange={handleOnChange} + onCreateEditor={handleOnCreateEditor} + onUpdate={handleOnUpdate} + extensions={extensions} /> ); From 4e09cc14b6e3bfb8248c60b47e356d4c6f83dcb6 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Sun, 14 Aug 2022 11:27:13 +0200 Subject: [PATCH 2/2] fix #178 --- packages/react/dist/index.cjs.js | 4 +-- packages/react/dist/index.es.js | 33 +++++++++---------- packages/react/src/components/CodeMirror6.jsx | 12 +++---- 3 files changed, 23 insertions(+), 26 deletions(-) diff --git a/packages/react/dist/index.cjs.js b/packages/react/dist/index.cjs.js index 70d80108..83d8e376 100644 --- a/packages/react/dist/index.cjs.js +++ b/packages/react/dist/index.cjs.js @@ -1,3 +1,3 @@ -"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});var t=require("react"),oe=require("@uiw/react-codemirror"),E=require("@codemirror/view"),L=require("@codemirror/state"),re=require("@codemirror/lang-javascript"),u=require("@lezer/highlight"),se=require("@uiw/codemirror-themes"),ne=require("react-hook-inview"),ce=require("@strudel.cycles/eval"),le=require("@strudel.cycles/core/util.mjs"),y=require("@strudel.cycles/tone"),B=require("@strudel.cycles/core"),M=require("@strudel.cycles/midi");function $(e){return e&&typeof e=="object"&&"default"in e?e:{default:e}}var m=$(t),ie=$(oe),ue=se.createTheme({theme:"dark",settings:{background:"#222",foreground:"#75baff",caret:"#ffcc00",selection:"rgba(128, 203, 196, 0.5)",selectionMatch:"#036dd626",lineHighlight:"#8a91991a",gutterBackground:"transparent",gutterForeground:"#676e95"},styles:[{tag:u.tags.keyword,color:"#c792ea"},{tag:u.tags.operator,color:"#89ddff"},{tag:u.tags.special(u.tags.variableName),color:"#eeffff"},{tag:u.tags.typeName,color:"#f07178"},{tag:u.tags.atom,color:"#f78c6c"},{tag:u.tags.number,color:"#ff5370"},{tag:u.tags.definition(u.tags.variableName),color:"#82aaff"},{tag:u.tags.string,color:"#c3e88d"},{tag:u.tags.special(u.tags.string),color:"#f07178"},{tag:u.tags.comment,color:"#7d8799"},{tag:u.tags.variableName,color:"#f07178"},{tag:u.tags.tagName,color:"#ff5370"},{tag:u.tags.bracket,color:"#a2a1a4"},{tag:u.tags.meta,color:"#ffcb6b"},{tag:u.tags.attributeName,color:"#c792ea"},{tag:u.tags.propertyName,color:"#c792ea"},{tag:u.tags.className,color:"#decb6b"},{tag:u.tags.invalid,color:"#ffffff"}]});const P=L.StateEffect.define(),de=L.StateField.define({create(){return E.Decoration.none},update(e,o){try{for(let n of o.effects)if(n.is(P))if(n.value){const c=E.Decoration.mark({attributes:{style:"background-color: #FFCA2880"}});e=E.Decoration.set([c.range(0,o.newDoc.length)])}else e=E.Decoration.set([]);return e}catch(n){return console.warn("flash error",n),e}},provide:e=>E.EditorView.decorations.from(e)}),K=e=>{e.dispatch({effects:P.of(!0)}),setTimeout(()=>{e.dispatch({effects:P.of(!1)})},200)},A=L.StateEffect.define(),fe=L.StateField.define({create(){return E.Decoration.none},update(e,o){try{for(let n of o.effects)n.is(A)&&(e=E.Decoration.set(n.value.flatMap(c=>(c.context.locations||[]).map(({start:f,end:l})=>{const i=c.context.color||"#FFCA28";let d=o.newDoc.line(f.line).from+f.column,r=o.newDoc.line(l.line).from+l.column;const a=o.newDoc.length;return d>a||r>a?void 0:E.Decoration.mark({attributes:{style:`outline: 1.5px solid ${i};`}}).range(d,r)})).filter(Boolean),!0));return e}catch{return e}},provide:e=>E.EditorView.decorations.from(e)}),ge=[re.javascript(),ue,fe,de];function Q({value:e,onChange:o,onViewChanged:n,onSelectionChange:c,options:f,editorDidMount:l}){const i=t.useCallback(a=>{o?.(a)},[o]),d=t.useCallback(a=>{n?.(a)},[n]),r=t.useCallback(a=>{a.selectionSet&&c&&c?.(a.state.selection)},[c]);return m.default.createElement(m.default.Fragment,null,m.default.createElement(ie.default,{value:e,onChange:i,onCreateEditor:d,onUpdate:r,extensions:ge}))}function J(e){const{onEvent:o,onQuery:n,onSchedule:c,ready:f=!0,onDraw:l}=e,[i,d]=t.useState(!1),r=1,a=()=>Math.floor(y.Tone.getTransport().seconds/r),C=(p=a())=>{const S=new B.TimeSpan(p,p+1),N=n?.(new B.State(S))||[];c?.(N,p);const F=S.begin.valueOf();y.Tone.getTransport().cancel(F);const w=(p+1)*r-.5,R=Math.max(y.Tone.getTransport().seconds,w)+.1;y.Tone.getTransport().schedule(()=>{C(p+1)},R),N?.filter(b=>b.part.begin.equals(b.whole?.begin)).forEach(b=>{y.Tone.getTransport().schedule(v=>{o(v,b,y.Tone.getContext().currentTime),y.Tone.Draw.schedule(()=>{l?.(v,b)},v)},b.part.begin.valueOf())})};t.useEffect(()=>{f&&C()},[o,c,n,l,f]);const k=async()=>{d(!0),await y.Tone.start(),y.Tone.getTransport().start("+0.1")},_=()=>{y.Tone.getTransport().pause(),d(!1)};return{start:k,stop:_,onEvent:o,started:i,setStarted:d,toggle:()=>i?_():k(),query:C,activeCycle:a}}function G(e){return t.useEffect(()=>(window.addEventListener("message",e),()=>window.removeEventListener("message",e)),[e]),t.useCallback(o=>window.postMessage(o,"*"),[])}let me=()=>Math.floor((1+Math.random())*65536).toString(16).substring(1);const he=e=>encodeURIComponent(btoa(e));function X({tune:e,defaultSynth:o,autolink:n=!0,onEvent:c,onDraw:f}){const l=t.useMemo(()=>me(),[]),[i,d]=t.useState(e),[r,a]=t.useState(),[C,k]=t.useState(""),[_,T]=t.useState(),[p,S]=t.useState(!1),[N,F]=t.useState(""),[w,R]=t.useState(),b=t.useMemo(()=>i!==r||_,[i,r,_]),v=t.useCallback(g=>k(s=>s+`${s?` +"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});var t=require("react"),re=require("@uiw/react-codemirror"),k=require("@codemirror/view"),L=require("@codemirror/state"),oe=require("@codemirror/lang-javascript"),i=require("@lezer/highlight"),se=require("@uiw/codemirror-themes"),ne=require("react-hook-inview"),ce=require("@strudel.cycles/eval"),le=require("@strudel.cycles/core/util.mjs"),y=require("@strudel.cycles/tone"),B=require("@strudel.cycles/core"),E=require("@strudel.cycles/midi");function $(e){return e&&typeof e=="object"&&"default"in e?e:{default:e}}var m=$(t),ie=$(re),ue=se.createTheme({theme:"dark",settings:{background:"#222",foreground:"#75baff",caret:"#ffcc00",selection:"rgba(128, 203, 196, 0.5)",selectionMatch:"#036dd626",lineHighlight:"#8a91991a",gutterBackground:"transparent",gutterForeground:"#676e95"},styles:[{tag:i.tags.keyword,color:"#c792ea"},{tag:i.tags.operator,color:"#89ddff"},{tag:i.tags.special(i.tags.variableName),color:"#eeffff"},{tag:i.tags.typeName,color:"#f07178"},{tag:i.tags.atom,color:"#f78c6c"},{tag:i.tags.number,color:"#ff5370"},{tag:i.tags.definition(i.tags.variableName),color:"#82aaff"},{tag:i.tags.string,color:"#c3e88d"},{tag:i.tags.special(i.tags.string),color:"#f07178"},{tag:i.tags.comment,color:"#7d8799"},{tag:i.tags.variableName,color:"#f07178"},{tag:i.tags.tagName,color:"#ff5370"},{tag:i.tags.bracket,color:"#a2a1a4"},{tag:i.tags.meta,color:"#ffcb6b"},{tag:i.tags.attributeName,color:"#c792ea"},{tag:i.tags.propertyName,color:"#c792ea"},{tag:i.tags.className,color:"#decb6b"},{tag:i.tags.invalid,color:"#ffffff"}]});const P=L.StateEffect.define(),de=L.StateField.define({create(){return k.Decoration.none},update(e,r){try{for(let n of r.effects)if(n.is(P))if(n.value){const u=k.Decoration.mark({attributes:{style:"background-color: #FFCA2880"}});e=k.Decoration.set([u.range(0,r.newDoc.length)])}else e=k.Decoration.set([]);return e}catch(n){return console.warn("flash error",n),e}},provide:e=>k.EditorView.decorations.from(e)}),K=e=>{e.dispatch({effects:P.of(!0)}),setTimeout(()=>{e.dispatch({effects:P.of(!1)})},200)},A=L.StateEffect.define(),fe=L.StateField.define({create(){return k.Decoration.none},update(e,r){try{for(let n of r.effects)if(n.is(A)){const u=n.value.map(d=>(d.context.locations||[]).map(({start:l,end:c})=>{const f=d.context.color||"#FFCA28";let o=r.newDoc.line(l.line).from+l.column,a=r.newDoc.line(c.line).from+c.column;const w=r.newDoc.length;return o>w||a>w?void 0:k.Decoration.mark({attributes:{style:`outline: 1.5px solid ${f};`}}).range(o,a)})).flat().filter(Boolean)||[];e=k.Decoration.set(u,!0)}return e}catch{return k.Decoration.set([])}},provide:e=>k.EditorView.decorations.from(e)}),ge=[oe.javascript(),ue,fe,de];function Q({value:e,onChange:r,onViewChanged:n,onSelectionChange:u,options:d,editorDidMount:l}){const c=t.useCallback(a=>{r?.(a)},[r]),f=t.useCallback(a=>{n?.(a)},[n]),o=t.useCallback(a=>{a.selectionSet&&u&&u?.(a.state.selection)},[u]);return m.default.createElement(m.default.Fragment,null,m.default.createElement(ie.default,{value:e,onChange:c,onCreateEditor:f,onUpdate:o,extensions:ge}))}function J(e){const{onEvent:r,onQuery:n,onSchedule:u,ready:d=!0,onDraw:l}=e,[c,f]=t.useState(!1),o=1,a=()=>Math.floor(y.Tone.getTransport().seconds/o),w=(p=a())=>{const S=new B.TimeSpan(p,p+1),N=n?.(new B.State(S))||[];u?.(N,p);const F=S.begin.valueOf();y.Tone.getTransport().cancel(F);const M=(p+1)*o-.5,R=Math.max(y.Tone.getTransport().seconds,M)+.1;y.Tone.getTransport().schedule(()=>{w(p+1)},R),N?.filter(b=>b.part.begin.equals(b.whole?.begin)).forEach(b=>{y.Tone.getTransport().schedule(v=>{r(v,b,y.Tone.getContext().currentTime),y.Tone.Draw.schedule(()=>{l?.(v,b)},v)},b.part.begin.valueOf())})};t.useEffect(()=>{d&&w()},[r,u,n,l,d]);const C=async()=>{f(!0),await y.Tone.start(),y.Tone.getTransport().start("+0.1")},_=()=>{y.Tone.getTransport().pause(),f(!1)};return{start:C,stop:_,onEvent:r,started:c,setStarted:f,toggle:()=>c?_():C(),query:w,activeCycle:a}}function G(e){return t.useEffect(()=>(window.addEventListener("message",e),()=>window.removeEventListener("message",e)),[e]),t.useCallback(r=>window.postMessage(r,"*"),[])}let me=()=>Math.floor((1+Math.random())*65536).toString(16).substring(1);const he=e=>encodeURIComponent(btoa(e));function X({tune:e,defaultSynth:r,autolink:n=!0,onEvent:u,onDraw:d}){const l=t.useMemo(()=>me(),[]),[c,f]=t.useState(e),[o,a]=t.useState(),[w,C]=t.useState(""),[_,T]=t.useState(),[p,S]=t.useState(!1),[N,F]=t.useState(""),[M,R]=t.useState(),b=t.useMemo(()=>c!==o||_,[c,o,_]),v=t.useCallback(g=>C(s=>s+`${s?` -`:""}${g}`),[]),W=t.useMemo(()=>{if(r&&!r.includes("strudel disable-highlighting"))return(g,s)=>f?.(g,s,r)},[r,f]),O=t.useMemo(()=>r&&r.includes("strudel hide-header"),[r]),H=t.useMemo(()=>r&&r.includes("strudel hide-console"),[r]),h=J({onDraw:W,onEvent:t.useCallback((g,s,ee)=>{try{c?.(s),s.context.logs?.length&&s.context.logs.forEach(v);const{onTrigger:q,velocity:te}=s.context;if(q)q(g,s,ee,1);else if(o){const ae=le.getPlayableNoteValue(s);o.triggerAttackRelease(ae,s.duration.valueOf(),g,te)}else throw new Error("no defaultSynth passed to useRepl.")}catch(q){console.warn(q),q.message="unplayable event: "+q?.message,v(q.message)}},[c,v,o]),onQuery:t.useCallback(g=>{try{return w?.query(g)||[]}catch(s){return console.warn(s),s.message="query error: "+s.message,T(s),[]}},[w]),onSchedule:t.useCallback((g,s)=>Z(g),[]),ready:!!w&&!!r}),z=G(({data:{from:g,type:s}})=>{s==="start"&&g!==l&&(h.setStarted(!1),a(void 0))}),j=t.useCallback(async(g=i)=>{if(r&&!b){T(void 0),h.start();return}try{S(!0);const s=await ce.evaluate(g);h.start(),z({type:"start",from:l}),R(()=>s.pattern),n&&(window.location.hash="#"+encodeURIComponent(btoa(i))),F(he(i)),T(void 0),a(g),S(!1)}catch(s){s.message="evaluation error: "+s.message,console.warn(s),T(s)}},[r,b,i,h,n,l,z]),Z=(g,s)=>{g.length};return{hideHeader:O,hideConsole:H,pending:p,code:i,setCode:d,pattern:w,error:_,cycle:h,setPattern:R,dirty:b,log:C,togglePlay:()=>{h.started?h.stop():j()},setActiveCode:a,activateCode:j,activeCode:r,pushLog:v,hash:N}}function V(...e){return e.filter(Boolean).join(" ")}let x=[],I;function Y({view:e,pattern:o,active:n}){t.useEffect(()=>{if(e)if(o&&n){let f=function(){try{const l=y.Tone.getTransport().seconds,d=[Math.max(I||l,l-1/10),l+1/60];I=l+1/60,x=x.filter(a=>a.whole.end>l);const r=o.queryArc(...d).filter(a=>a.hasOnset());x=x.concat(r),console.log("update...",e.state.doc.length),e.dispatch({effects:A.of(x)})}catch{e.dispatch({effects:A.of([])})}c=requestAnimationFrame(f)},c=requestAnimationFrame(f);return()=>{cancelAnimationFrame(c)}}else x=[],e.dispatch({effects:A.of([])})},[o,n,e])}const pe="_container_3i85k_1",be="_header_3i85k_5",ve="_buttons_3i85k_9",ye="_button_3i85k_9",we="_buttonDisabled_3i85k_17",Me="_error_3i85k_21",Ee="_body_3i85k_25";var D={container:pe,header:be,buttons:ve,button:ye,buttonDisabled:we,error:Me,body:Ee};function U({type:e}){return m.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:m.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:m.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:m.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 Ce({tune:e,defaultSynth:o,hideOutsideView:n=!1,theme:c,init:f,onEvent:l,enableKeyboard:i}){const{code:d,setCode:r,pattern:a,activeCode:C,activateCode:k,evaluateOnly:_,error:T,cycle:p,dirty:S,togglePlay:N,stop:F}=X({tune:e,defaultSynth:o,autolink:!1,onEvent:l});t.useEffect(()=>{f&&_()},[e,f]);const[w,R]=t.useState(),[b,v]=ne.useInView({threshold:.01}),W=t.useRef(),O=t.useMemo(()=>((v||!n)&&(W.current=!0),v||W.current),[v,n]);return Y({view:w,pattern:a,active:p.started&&!C?.includes("strudel disable-highlighting")}),t.useLayoutEffect(()=>{if(i){const H=async h=>{(h.ctrlKey||h.altKey)&&(h.code==="Enter"?(h.preventDefault(),K(w),await k()):h.code==="Period"&&(p.stop(),h.preventDefault()))};return window.addEventListener("keydown",H,!0),()=>window.removeEventListener("keydown",H,!0)}},[i,a,d,k,p,w]),m.default.createElement("div",{className:D.container,ref:b},m.default.createElement("div",{className:D.header},m.default.createElement("div",{className:D.buttons},m.default.createElement("button",{className:V(D.button,p.started?"sc-animate-pulse":""),onClick:()=>N()},m.default.createElement(U,{type:p.started?"pause":"play"})),m.default.createElement("button",{className:V(S?D.button:D.buttonDisabled),onClick:()=>k()},m.default.createElement(U,{type:"refresh"}))),T&&m.default.createElement("div",{className:D.error},T.message)),m.default.createElement("div",{className:D.body},O&&m.default.createElement(Q,{value:d,onChange:r,onViewChanged:R})))}function ke(e){const{ready:o,connected:n,disconnected:c}=e,[f,l]=t.useState(!0),[i,d]=t.useState(M.WebMidi?.outputs||[]);return t.useEffect(()=>{M.enableWebMidi().then(()=>{M.WebMidi.addListener("connected",a=>{d([...M.WebMidi.outputs]),n?.(M.WebMidi,a)}),M.WebMidi.addListener("disconnected",a=>{d([...M.WebMidi.outputs]),c?.(M.WebMidi,a)}),o?.(M.WebMidi),l(!1)}).catch(a=>{if(a){console.error(a),console.warn("Web Midi could not be enabled..");return}})},[o,n,c,i]),{loading:f,outputs:i,outputByName:a=>M.WebMidi.getOutputByName(a)}}exports.CodeMirror=Q;exports.MiniRepl=Ce;exports.cx=V;exports.flash=K;exports.useCycle=J;exports.useHighlighting=Y;exports.usePostMessage=G;exports.useRepl=X;exports.useWebMidi=ke; +`:""}${g}`),[]),W=t.useMemo(()=>{if(o&&!o.includes("strudel disable-highlighting"))return(g,s)=>d?.(g,s,o)},[o,d]),O=t.useMemo(()=>o&&o.includes("strudel hide-header"),[o]),H=t.useMemo(()=>o&&o.includes("strudel hide-console"),[o]),h=J({onDraw:W,onEvent:t.useCallback((g,s,ee)=>{try{u?.(s),s.context.logs?.length&&s.context.logs.forEach(v);const{onTrigger:q,velocity:te}=s.context;if(q)q(g,s,ee,1);else if(r){const ae=le.getPlayableNoteValue(s);r.triggerAttackRelease(ae,s.duration.valueOf(),g,te)}else throw new Error("no defaultSynth passed to useRepl.")}catch(q){console.warn(q),q.message="unplayable event: "+q?.message,v(q.message)}},[u,v,r]),onQuery:t.useCallback(g=>{try{return M?.query(g)||[]}catch(s){return console.warn(s),s.message="query error: "+s.message,T(s),[]}},[M]),onSchedule:t.useCallback((g,s)=>Z(g),[]),ready:!!M&&!!o}),z=G(({data:{from:g,type:s}})=>{s==="start"&&g!==l&&(h.setStarted(!1),a(void 0))}),j=t.useCallback(async(g=c)=>{if(o&&!b){T(void 0),h.start();return}try{S(!0);const s=await ce.evaluate(g);h.start(),z({type:"start",from:l}),R(()=>s.pattern),n&&(window.location.hash="#"+encodeURIComponent(btoa(c))),F(he(c)),T(void 0),a(g),S(!1)}catch(s){s.message="evaluation error: "+s.message,console.warn(s),T(s)}},[o,b,c,h,n,l,z]),Z=(g,s)=>{g.length};return{hideHeader:O,hideConsole:H,pending:p,code:c,setCode:f,pattern:M,error:_,cycle:h,setPattern:R,dirty:b,log:w,togglePlay:()=>{h.started?h.stop():j()},setActiveCode:a,activateCode:j,activeCode:o,pushLog:v,hash:N}}function V(...e){return e.filter(Boolean).join(" ")}let x=[],I;function Y({view:e,pattern:r,active:n}){t.useEffect(()=>{if(e)if(r&&n){let d=function(){try{const l=y.Tone.getTransport().seconds,f=[Math.max(I||l,l-1/10),l+1/60];I=l+1/60,x=x.filter(a=>a.whole.end>l);const o=r.queryArc(...f).filter(a=>a.hasOnset());x=x.concat(o),e.dispatch({effects:A.of(x)})}catch{e.dispatch({effects:A.of([])})}u=requestAnimationFrame(d)},u=requestAnimationFrame(d);return()=>{cancelAnimationFrame(u)}}else x=[],e.dispatch({effects:A.of([])})},[r,n,e])}const pe="_container_3i85k_1",be="_header_3i85k_5",ve="_buttons_3i85k_9",ye="_button_3i85k_9",we="_buttonDisabled_3i85k_17",Me="_error_3i85k_21",Ee="_body_3i85k_25";var D={container:pe,header:be,buttons:ve,button:ye,buttonDisabled:we,error:Me,body:Ee};function U({type:e}){return m.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:m.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:m.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:m.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 ke({tune:e,defaultSynth:r,hideOutsideView:n=!1,theme:u,init:d,onEvent:l,enableKeyboard:c}){const{code:f,setCode:o,pattern:a,activeCode:w,activateCode:C,evaluateOnly:_,error:T,cycle:p,dirty:S,togglePlay:N,stop:F}=X({tune:e,defaultSynth:r,autolink:!1,onEvent:l});t.useEffect(()=>{d&&_()},[e,d]);const[M,R]=t.useState(),[b,v]=ne.useInView({threshold:.01}),W=t.useRef(),O=t.useMemo(()=>((v||!n)&&(W.current=!0),v||W.current),[v,n]);return Y({view:M,pattern:a,active:p.started&&!w?.includes("strudel disable-highlighting")}),t.useLayoutEffect(()=>{if(c){const H=async h=>{(h.ctrlKey||h.altKey)&&(h.code==="Enter"?(h.preventDefault(),K(M),await C()):h.code==="Period"&&(p.stop(),h.preventDefault()))};return window.addEventListener("keydown",H,!0),()=>window.removeEventListener("keydown",H,!0)}},[c,a,f,C,p,M]),m.default.createElement("div",{className:D.container,ref:b},m.default.createElement("div",{className:D.header},m.default.createElement("div",{className:D.buttons},m.default.createElement("button",{className:V(D.button,p.started?"sc-animate-pulse":""),onClick:()=>N()},m.default.createElement(U,{type:p.started?"pause":"play"})),m.default.createElement("button",{className:V(S?D.button:D.buttonDisabled),onClick:()=>C()},m.default.createElement(U,{type:"refresh"}))),T&&m.default.createElement("div",{className:D.error},T.message)),m.default.createElement("div",{className:D.body},O&&m.default.createElement(Q,{value:f,onChange:o,onViewChanged:R})))}function Ce(e){const{ready:r,connected:n,disconnected:u}=e,[d,l]=t.useState(!0),[c,f]=t.useState(E.WebMidi?.outputs||[]);return t.useEffect(()=>{E.enableWebMidi().then(()=>{E.WebMidi.addListener("connected",a=>{f([...E.WebMidi.outputs]),n?.(E.WebMidi,a)}),E.WebMidi.addListener("disconnected",a=>{f([...E.WebMidi.outputs]),u?.(E.WebMidi,a)}),r?.(E.WebMidi),l(!1)}).catch(a=>{if(a){console.error(a),console.warn("Web Midi could not be enabled..");return}})},[r,n,u,c]),{loading:d,outputs:c,outputByName:a=>E.WebMidi.getOutputByName(a)}}exports.CodeMirror=Q;exports.MiniRepl=ke;exports.cx=V;exports.flash=K;exports.useCycle=J;exports.useHighlighting=Y;exports.usePostMessage=G;exports.useRepl=X;exports.useWebMidi=Ce; diff --git a/packages/react/dist/index.es.js b/packages/react/dist/index.es.js index a5650e46..c3540f7d 100644 --- a/packages/react/dist/index.es.js +++ b/packages/react/dist/index.es.js @@ -89,27 +89,25 @@ const highlightField = StateField.define({ try { for (let e of tr.effects) { if (e.is(setHighlights)) { - highlights = Decoration.set( - e.value.flatMap( - (hap) => (hap.context.locations || []).map(({ start, end }) => { - const color = hap.context.color || "#FFCA28"; - let from = tr.newDoc.line(start.line).from + start.column; - let to = tr.newDoc.line(end.line).from + end.column; - const l = tr.newDoc.length; - if (from > l || to > l) { - return; - } - const mark = Decoration.mark({ attributes: { style: `outline: 1.5px solid ${color};` } }); - return mark.range(from, to); - }) - ).filter(Boolean), - true - ); + const marks = e.value.map( + (hap) => (hap.context.locations || []).map(({ start, end }) => { + const color = hap.context.color || "#FFCA28"; + let from = tr.newDoc.line(start.line).from + start.column; + let to = tr.newDoc.line(end.line).from + end.column; + const l = tr.newDoc.length; + if (from > l || to > l) { + return; + } + const mark = Decoration.mark({ attributes: { style: `outline: 1.5px solid ${color};` } }); + return mark.range(from, to); + }) + ).flat().filter(Boolean) || []; + highlights = Decoration.set(marks, true); } } return highlights; } catch (err) { - return highlights; + return Decoration.set([]); } }, provide: (f) => EditorView.decorations.from(f) @@ -423,7 +421,6 @@ function useHighlighting({ view, pattern, active }) { highlights = highlights.filter((hap) => hap.whole.end > audioTime); // keep only highlights that are still active const haps = pattern.queryArc(...span).filter((hap) => hap.hasOnset()); highlights = highlights.concat(haps); // add potential new onsets - console.log('update...', view.state.doc.length); view.dispatch({ effects: setHighlights.of(highlights) }); // highlight all still active + new active haps } catch (err) { // console.log('error in updateHighlights', err); diff --git a/packages/react/src/components/CodeMirror6.jsx b/packages/react/src/components/CodeMirror6.jsx index e0f47b75..8b05a727 100644 --- a/packages/react/src/components/CodeMirror6.jsx +++ b/packages/react/src/components/CodeMirror6.jsx @@ -49,9 +49,9 @@ const highlightField = StateField.define({ try { for (let e of tr.effects) { if (e.is(setHighlights)) { - highlights = Decoration.set( + const marks = e.value - .flatMap((hap) => + .map((hap) => (hap.context.locations || []).map(({ start, end }) => { const color = hap.context.color || '#FFCA28'; let from = tr.newDoc.line(start.line).from + start.column; @@ -65,15 +65,15 @@ const highlightField = StateField.define({ return mark.range(from, to); }), ) - .filter(Boolean), - true, - ); + .flat() + .filter(Boolean) || []; + highlights = Decoration.set(marks, true); } } return highlights; } catch (err) { // console.warn('highlighting error', err); - return highlights; + return Decoration.set([]); } }, provide: (f) => EditorView.decorations.from(f),