diff --git a/assets/raccoon.png b/assets/images/raccoon.png similarity index 100% rename from assets/raccoon.png rename to assets/images/raccoon.png diff --git a/fonts/chicago.woff2 b/fonts/chicago.woff2 new file mode 100644 index 0000000..cdbbccc Binary files /dev/null and b/fonts/chicago.woff2 differ diff --git a/index.html b/index.html index 112407f..0290442 100755 --- a/index.html +++ b/index.html @@ -55,7 +55,7 @@ "content": "context = require \"./lib/audio-context\"\n\nbufferLoader = (url) ->\n new Promise (resolve, reject) ->\n fetch(url)\n .then (response) ->\n throw response unless response.ok\n response.arrayBuffer()\n .then (buffer) ->\n context.decodeAudioData buffer, resolve, reject\n\nblobLoader = (url) ->\n fetch(url)\n .then (response) ->\n throw response unless response.ok\n response.blob()\n\nBASE_PATH = window.location\nurlFor = (path) ->\n \"#{BASE_PATH}assets/#{path}\"\n\nimgLoader = (url) ->\n new Promise (resolve, reject) ->\n image = new Image\n image.crossOrigin = true\n image.src = url\n image.onload = ->\n resolve image\n image.onerror = reject\n\nmodule.exports = Sample =\n load: (data) ->\n {sample} = data\n\n # Load audio buffer\n bufferLoader(urlFor(sample))\n .then (buffer) ->\n Object.assign data,\n buffer: buffer\n\n loadPack: ->\n imgLoader urlFor \"images/default.png\"\n .then (img) ->\n # TODO: a cleaner way to pass this to applySampleCSS\n Sample.image = img\n\n Promise.all defaultPack.map (sample, i) ->\n # Get blob url\n canvas = document.createElement 'canvas'\n canvas.width = 48\n canvas.height = 48\n ctx = canvas.getContext('2d')\n\n ctx.drawImage(img, i * 48, 0, 48, 48, 0, 0, 48, 48)\n\n new Promise (resolve, reject) ->\n canvas.toBlob (blob) ->\n url = URL.createObjectURL blob\n sample.cursor = \"url(#{url}) #{24} #{24}, default\"\n sample.url = url\n resolve()\n\n .then ->\n Promise.all(defaultPack.map(Sample.load))\n\n # Export all image/activeImage sprites to a single png\n # This is going to be part of the future format\n exportPNG: (samples) ->\n canvas = document.createElement 'canvas'\n canvas.width = 48 * samples.length\n canvas.height = 96\n ctx = canvas.getContext('2d')\n\n # All images are 48x48\n samples.forEach ({image, activeImage}, i) ->\n x = 48 * i\n ctx.drawImage(image, x, 0) #normal\n ctx.drawImage(activeImage, x, 48) # active y=48\n\n canvas.toBlob (blob) ->\n url = URL.createObjectURL(blob)\n window.open url, \"_blank\"\n\n# Load Editor sound effects, currently just the eraser\nbufferLoader(\"#{BASE_PATH}assets/erase2.wav\")\n.then (buffer) ->\n Sample.fx =\n eraser: buffer\n\nsamples =\n synth:\n sample: \"synth.wav\"\n piano:\n sample: \"piano.wav\"\n pan: -0.5\n guitar:\n sample: \"guitar.wav\"\n pan: 0.25\n bass:\n sample: \"16.wav\"\n horn:\n sample: \"horn.wav\"\n pan: -0.333\n orch_hit:\n sample: \"orch_hit.wav\"\n pan: 0.25\n chime:\n sample: \"5.wav\"\n pan: 0.5\n organ:\n sample: \"organ.wav\"\n pan: -0.25\n drum:\n sample: \"drum.wav\"\n snare:\n sample: \"snare.wav\"\n woodblock:\n sample: \"14.wav\"\n pan: -0.333\n clap:\n sample: \"clap.wav\"\n hat:\n sample: \"hat.wav\"\n pan: 0.333\n baby:\n sample: \"baby.wav\"\n pan: -0.5\n yoshi:\n sample: \"yoshi.wav\"\n pan: 0.5\n pig:\n sample: \"oink.wav\"\n cat:\n sample: \"cat.wav\"\n pan: 0.25\n dog:\n sample: \"dog.wav\"\n pan: -0.25\n french:\n sample: \"french-horn.wav\"\n pan: 0.333\n pitchShift: 0\n nylon:\n sample: \"nylon-guitar2.wav\"\n pan: -0.25\n pitchShift: -12\n snare2:\n sample: \"snare2.wav\"\n pitchShift: 0\n\ndefaultPack = Object.keys(samples).map (name, i) ->\n sample = samples[name]\n sample.name = name\n sample.index = i\n sample.pitchShift ?= -5 # These samples are pitched to F, the -5 pithces them to C\n sample.pan ?= 0\n sample.volume ?= 1\n\n sample\n" }, "style.styl": { - "content": "primary-color-dark = #4a148c\nprimary-color = #673ab7\nhighlight-color = #FFE0B2\nactive-color = #FFC107\nbg-color = #ede7f6\n\npixelated()\n -ms-interpolation-mode: nearest-neighbor\n image-rendering: crisp-edges\n image-rendering: pixelated\n\n@font-face\n font-display: auto\n font-family: 'Chicago'\n src: url('https://danielx.net/fonts/chicago.woff2') format('woff2'),\n url('https://danielx.net/fonts/chicago.woff') format('woff')\n font-weight: normal\n font-style: normal\n\n*\n box-sizing: border-box\n\nimg\n max-width: 100%\n\n.hidden\n display: none !important\n\n#modal \n > *\n border: 1px solid primary-color\n border-radius: 4px\n box-shadow: 1px 2px 0px primary-color\n color: inherit\n padding: 1rem\n\n > h1, > h2\n margin-top: 0\n\n > section.purchase\n background-color: transparent\n border: none\n border-radius: 0\n box-shadow: none\n padding: 0\n\n > .publish\n > p.status:empty\n margin: 0\n \n > pre\n user-select: all\n \n > actions\n display: flex\n > button:last-child\n margin-left: auto\n\n:focus\n color: white\n background-color: primary-color\n outline: none\n\nhtml, body\n height: 100%\n\nbody\n color: #241440\n display: flex\n font-family: Chicago, sans-serif\n font-size: 16px\n line-height: 1rem\n margin: 0\n overflow: hidden\n user-select: none\n\np\n font-family: sans-serif\n\n// Input and form things\ninput, textarea, select, button\n font-family: inherit\n\ninput\n background-color: bg-color\n border: 1px solid primary-color\n border-radius: 4px\n box-shadow: 1px 2px 0px primary-color inset\n color: primary-color\n font-size: inherit\n padding: 2px 0.25em\n\n // Firefox number spinners are a crime to my eyes ;_;\n // TODO Custom style for number spinners on all browsers\n &[type=\"number\"]\n -moz-appearance: textfield\n \n &:focus\n background-color: active-color\n color: rgba(0, 0, 0, 0.69)\n\n@keyframes note-active\n from\n background-color: rgba(0, 0, 0, 0)\n\n to\n background-color: rgba(255, 0, 255, 0)\n\n// Background has to be on ::after so it is above the ledger lines on ::before\n// Accidentals are in ::after content, vertically centered and left of the bg\nnote\n font-size: 48px\n height: 48px\n pixelated()\n position: absolute\n width: 48px\n\n &.active\n animation-name: note-active\n animation-duration: 0.25s\n\n &::after\n align-items: center\n background-repeat: no-repeat\n background-position: 100% 50%\n content: \"\"\n display: flex\n position: absolute\n left: 0\n top: 0\n width: 100%\n height: 100%\n text-indent: -12px\n\n &.♭\n &::after\n content: \"♭\"\n\n &.♯\n &::after\n content: \"♯\"\n\n // Extra ledger lines\n &.C4, &.A5, &.C6, &.C2, &.E2, &.B5, &.D2\n &::before\n content: \"\"\n width: 48px\n left: 0px\n top: 23px\n position: absolute\n height: 0\n border-bottom: 2px solid black\n\n &.B5\n &::before\n top: 40px\n\n &.D2\n &::before\n top: -8px\n\nsong-section\n height: 483px\n position: absolute\n top: -241px\n\n &::after\n content: \"\"\n border-right: 2px solid black\n height: 100%\n position: absolute\n right: 10px\n\n > span.measure-number\n background-color: rgba(255, 255, 255, 0.9375)\n border: 1px solid black\n box-shadow: 1px 1px 0 0 rgba(0,0,0,0.5)\n font-style: italic\n left: 0px\n padding: 2px 6px 2px 4px\n position: absolute\n top: -132px\n\n > div.key-signature\n &.s > ::after\n content: \"♯\"\n\n &.f > ::after\n content: \"♭\"\n\n > *\n display: none\n font-size: 96px\n height: 48px\n position: absolute\n width: 48px\n\n &::after\n align-items: center\n display: flex\n height: 100%\n width: 100%\n\n &.s1, &.s2, &.s3, &.s4, &.s5, &.s6, &.s7\n > :nth-child(1)\n display: initial\n top: -24px\n left: -96px\n &.s2, &.s3, &.s4, &.s5, &.s6, &.s7\n > :nth-child(2)\n display: initial\n top: 48px\n left: -72px\n &.s3, &.s4, &.s5, &.s6, &.s7\n > :nth-child(3)\n display: initial\n top: -48px\n left: -48px\n &.s4, &.s5, &.s6, &.s7\n > :nth-child(4)\n display: initial\n top: 24px\n left: -24px\n &.s5, &.s6, &.s7\n > :nth-child(5)\n display: initial\n top: 96px\n left: 0\n &.s6, &.s7\n > :nth-child(6)\n display: initial\n top: 0px\n left: 24px\n &.s7\n > :nth-child(7)\n display: initial\n top: 72px\n left: 48px\n \n &.f1, &.f2, &.f3, &.f4, &.f5, &.f6, &.f7\n > :nth-child(1)\n display: initial\n top: 72px\n left: -96px\n &.f2, &.f3, &.f4, &.f5, &.f6, &.f7\n > :nth-child(2)\n display: initial\n top: 0px\n left: -72px\n &.f3, &.f4, &.f5, &.f6, &.f7\n > :nth-child(3)\n display: initial\n top: 96px\n left: -48px\n &.f4, &.f5, &.f6, &.f7\n > :nth-child(4)\n display: initial\n top: 24px\n left: -24px\n &.f5, &.f6, &.f7\n > :nth-child(5)\n display: initial\n top: -48px\n left: 0\n &.f6, &.f7\n > :nth-child(6)\n display: initial\n top: 48px\n left: 24px\n &.f7\n > :nth-child(7)\n display: initial\n top: -24px\n left: 48px\n\ntd\n > select\n width: 100%\n > input\n border-radius: 0\n box-shadow: none\n > aside.fx-picker\n > label\n display: none\n\n &.sprite\n text-align: center\n vertical-align: middle\n\n > img\n margin-right: 1rem\n vertical-align: middle\n \n &.input\n > input[type=number]\n display: block\n margin: auto\n width: 60px\n\nsection.settings\n overflow: auto\n padding: 1rem\n position: relative\n\n > h2\n margin: 0 0 1rem\n > button.close\n position: absolute\n top: 1rem\n right: 1rem\n\n > table\n margin: 0 -8px\n width: calc(100% + 16px)\n\nsection.demo-picker\n overflow: auto\n padding: 1rem\n position: relative\n\n > h2\n margin: 0 0 1rem\n > button.close\n position: absolute\n top: 1rem\n right: 1rem\n\n > table\n font-size: 18px\n > tbody\n > tr\n cursor: pointer\n line-height: 2rem\n\n &:hover\n background-color: rgba(103, 58, 183, 0.19)\n\nviewport\n background-attachment: local\n background-color: bg-color\n display: flex\n height: 100%\n align-items: center\n overflow-x: scroll\n overflow-y: hidden\n\n > staff\n background-color: rgba(255, 255, 255, 0.9375)\n border: 1px solid rgba(0, 0, 0, 0.5)\n box-sizing: content-box\n box-shadow: 1px 1px 0 0 rgba(0, 0, 0, 0.5)\n display: block\n flex: 0 0 auto\n padding: 96px 0\n position: relative\n margin: 0 48px\n z-index: 0\n\n // Hack for right margin inside scrollable viewport\n // Also serving as song end bar\n &::after\n border-left: 8px solid black\n content: \"\"\n position: absolute\n right: -48px\n top: 96px\n width: 48px\n height: calc(100% - 192px)\n z-index: -1\n\n > z-meter\n display: block\n position: absolute\n left: 256px\n top: 96px\n height: calc(100% - 192px)\n width: calc(100% - 256px)\n\n &::before\n content: \"\"\n border-left: 2px solid black\n position: absolute\n height: 100%\n left: -257px\n\n > div.repeat\n position: absolute\n right: 0\n height: 100%\n\n &::before, &::after\n content: \"\"\n display: block\n background-color: black\n border-radius: 100%\n position: absolute\n width: 16px\n height: 16px\n right: 16px\n top: 66px\n\n &::after\n top: 114px\n \n &.bass\n position: relative\n top: 288px\n\n > notes\n display: block\n position: absolute\n left: 256px\n top: 337px\n\n > pattern-preview\n opacity: 0.5\n position: absolute\n\n > selection\n background-color: rgba(103, 58, 183, 0.25)\n border: 2px dashed primary-color\n position: absolute\n left: -150px\n z-index: 20\n\n > button\n display: none\n position: absolute\n top: 0\n left: 0\n right: 0\n bottom: 0\n margin: auto\n width: 48px\n height: 48px\n\n &.up\n bottom: calc(100%+4px)\n top: auto\n &.down\n top: calc(100%+4px)\n bottom: auto\n &.left\n right: calc(100%+4px)\n left: auto\n &.right\n left: calc(100%+4px)\n right: auto\n\n > actions\n display: none\n position: absolute\n\n > button\n margin-left: 4px\n\n &.t > actions\n top: 0\n &.b > actions\n bottom: 0\n &.l > actions\n left: 0\n &.r > actions\n right: 0\n\n &.set \n > actions\n display: flex\n > button\n display: block\n\n > lines\n display: block\n margin-bottom: 48px\n \n &:nth-child(2)\n margin-bottom: 0\n\n > line:last-child\n height: 0\n\n > line\n border-top: 3px solid black\n display: block\n height: 48px\n\n > playhead\n border-left: 1px solid rgba(103, 58, 183, 0.5)\n border-right: 1px solid rgba(103, 58, 183, 0.5)\n position: absolute\n top: 0\n height: 674px\n width: 2px\n z-index: 10\n\n &.buffer-start\n display: none\n border-color: rgba(255, 0, 0, 0.5)\n\n &.buffer-end\n display: none\n border-color: rgba(0, 0, 255, 0.5)\n\n > img\n position: absolute\n height: 600px\n top: -94px\n left: -120px\n\n &:last-child\n left: -100px\n top: 181px\n\nform\n > label\n display: block\n\n > h3\n font-size: 1rem\n\n &.inline\n display: inline-block\n margin-right: 0.5em\n\n > input\n padding-left: 2px\n width: 100%\n\n > actions\n display: flex\n justify-content: space-between\n margin-top: 1em\n\n &.purchase\n width: 672px\n\napp\n display: flex\n flex: 1 0\n height: 100%\n flex-direction: column\n\nbutton.loop\n font-size: 32px\n line-height: 1rem\n\naside.meter-picker\n margin-left: 8px\n > button\n border-radius: 0\n\n &:first-child\n border-top-left-radius: 4px\n border-bottom-left-radius: 4px\n\n &:last-child\n border-top-right-radius: 4px\n border-bottom-right-radius: 4px\n\naside.note-control\n > section\n display: flex\n margin-left: 1rem\n \n > label\n display: flex\n align-items: center\n margin-right: 4px\n\n > button\n flex: 0 0 auto\n font-size: 20px\n line-height: 1rem\n width: 36px\n\n border-radius: 0\n\n &.triplet\n font-size: 16px\n\n &:nth-child(n + 3)\n border-left: 0\n\n &:nth-child(2)\n border-top-left-radius: 4px\n border-bottom-left-radius: 4px\n\n &.snap\n > button\n &:nth-child(5)\n border-top-right-radius: 4px\n border-bottom-right-radius: 4px\n \n > input\n margin-left: 5px\n width: 60px\n\n &.accidental\n > button:nth-child(4)\n border-top-right-radius: 4px\n border-bottom-right-radius: 4px\n\nsection.persistence\n display: flex\n flex-direction: column\n padding: 1rem\n width: 480px\n\n > button\n margin-top: 8px\n width: 100%\n\n &:first-child\n margin-top: 0\n\nabout > actions\n > button, a.button\n width: 100%\n margin-top: 8px\n\naside\n display: flex\n > label\n display: flex\n align-items: center\n margin-right: 4px\n margin-left: 1rem\n\naside.stereo-analyser\n > canvas\n border: 1px solid #673ab7\n border-radius: 4px\n\naside.fx-picker\n display: flex\n\n > button\n background-size: 100%\n border: 1px solid #673ab7\n border-radius: 4px\n height: 36px\n padding: 0\n margin-left: 2px\n width: 36px\n\naside.actions\n background-color: white\n border-top: 2px solid primary-color\n display: flex\n flex: 0 0 auto\n flex-direction: column\n padding: 4px 4px 0px 4px\n width: 100%\n\n > section:nth-child(2)\n > button, > a.button\n padding: 15px 8px\n\n > section\n display: flex\n &:last-child\n margin-top: 8px\n\n > section.buttons\n > *\n margin-bottom: 6px\n \n &:nth-child(n + 2)\n margin-left: 4px\n \n > form\n display: flex\n \n > button, > a.button\n flex: 0 0 auto\n\n > label\n align-items: center\n border: 1px solid #673ab7\n border-radius: 4px\n box-shadow: 1px 2px 0px #673ab7\n color: #673ab7\n display: flex\n flex-direction: column\n padding: 5px 8px 4px\n white-space: nowrap\n \n > input\n padding: 2px 0 0\n text-align: center\n width: 60px\n \n > h2\n display: block\n font-size: 1em\n font-weight: normal\n margin: 0 0 4px\n \n > .right\n margin-left: auto\n\nactions > label\n background-color: white\n border 1px solid primary-color\n border-radius: 4px\n box-shadow: 1px 2px 0px primary-color\n color: #673ab7\n cursor: pointer\n font: inherit\n line-height: 1em\n padding: 9px 16px\n &:nth-child(n + 2)\n margin-left: 4px\n\na.button\n align-items: center\n display: inline-flex\n justify-content: center\n text-align: center\n text-decoration: none\n\n // Hack for merch icon spacing\n > :nth-child(2)\n margin-left: 5px\n\nbutton, a.button\n background-color: white\n border 1px solid primary-color\n border-radius: 4px\n box-shadow: 1px 2px 0px primary-color\n color: #673ab7\n cursor: pointer\n font-size: inherit\n line-height: 1em\n padding: 9px 8px\n white-space: nowrap\n\n &.full\n width: 100%\n\n &:focus\n background-color: active-color\n color: rgba(0, 0, 0, 0.69)\n outline-offset: 4px\n\n &:active, &.active\n background-color: primary-color\n border 1px solid primary-color\n color: white\n box-shadow: 1px 2px 0px #241440 inset\n\n &:disabled\n background-color: #eee\n border-color: #4e4e4e\n box-shadow: 1px 2px 0px #4e4e4e\n color: #4e4e4e\n cursor: default\n\ntools, patterns\n background-color: white\n border-bottom: 2px solid primary-color\n display: flex\n width: 100%\n\n > *\n background-repeat: no-repeat\n background-position: 50% 50%\n border-right: 1px solid primary-color\n cursor: pointer\n display: block\n width: 49px\n height: 48px\n &:hover\n background-color: highlight-color\n &.active\n background-color: active-color\n\n > tool.eraser\n order: 2\n background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAAIdJREFUeJzNUsERwCAIw15n031wDt0Hl0s/9VoF9NnmZzRBCERfI2zusdOtDABmopRGVoRCrdviADNMiADM6L873Mql2NYiw3E2WItzVi2dSuw8JBHNvQyegcU4vmjNFesWZrHFTSlYQ/RhRDgatKZFnXPy7zMIoVaYa3fH5i3PTHira4r/gQv1W1E4p9FksQAAAABJRU5ErkJggg==\")\n\n > .selection\n order: 2\n background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAiUlEQVRYR+1XQQrAIAyr/3/0RLAyqoUdzNJDvFnEpkkM2MzssX21Qw1SGo0igHfNgfiZ6/sI4HqDSVs6wGlaCNXZpQ7gN80jkIxyNAtLkjIA0BOn99O0d0RlJIjvFC3JZkJ0Q3kgMqAcWIwoB8oEkXKAHsV0APIAXQI6AHkA9vf78jUbZ+gAaB7opmM7IWnG3nUAAAAASUVORK5CYII=\")\n\ntools\n > *\n pixelated()\n\npatterns\n margin-top: -1px\n\n &:empty\n display: none\n\n > pattern\n display: flex\n padding: 0 8px\n align-items: center\n width: 64px\n overflow: hidden\n\n > preview\n position: relative\n transform: scale(0.0625, 0.0625)\n top: -14px\n\n > *\n transform: scale(4)\n\npre.position\n background-color: rgba(255, 255, 255, 0.9375)\n border: 1px solid black\n box-shadow: 1px 1px 0 0 rgba(0,0,0,0.5)\n padding: 2px 6px 2px 4px\n font-family: inherit\n pointer-events: none\n padding: 4px\n position: absolute\n left: 1rem\n top: calc(45px + 1rem)\n\n &:empty\n display: none\n\npre.debug\n &:empty\n display: none\n\n@media only screen and (max-width: 768px)\n aside.actions\n border-top: none\n padding-top: 0\n > section\n &:first-child\n display: none\n &:nth-child(2)\n margin-top: 0\n\n button\n > span.description\n display: none\n\n tools, patterns\n order: 2\n border: none\n width: 49px\n height: 48px\n\n > *\n border-top: 1px solid primary-color\n display: none\n\n tool.active\n display: block\n\n pattern.active\n display: flex\n\n &.open\n background-color: primary-color\n display: grid\n grid-gap: 1px\n position: absolute\n width: 100%\n height: 100%\n grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr\n z-index: 1\n\n > *\n background-color: white\n background-size: 100%\n border: none\n display: block\n image-rendering: pixelated\n height: 100%\n width: 100%\n\n &:hover\n background-color: #FFE0B2\n" + "content": "primary-color-dark = #4a148c\nprimary-color = #673ab7\nhighlight-color = #FFE0B2\nactive-color = #FFC107\nbg-color = #ede7f6\n\npixelated()\n -ms-interpolation-mode: nearest-neighbor\n image-rendering: crisp-edges\n image-rendering: pixelated\n\n@font-face\n font-display: auto\n font-family: 'Chicago'\n src: url('assets/fonts/chicago.woff2') format('woff2'),\n url('assets/fonts/chicago.woff') format('woff')\n font-weight: normal\n font-style: normal\n\n*\n box-sizing: border-box\n\nimg\n max-width: 100%\n\n.hidden\n display: none !important\n\n#modal \n > *\n border: 1px solid primary-color\n border-radius: 4px\n box-shadow: 1px 2px 0px primary-color\n color: inherit\n padding: 1rem\n\n > h1, > h2\n margin-top: 0\n\n > section.purchase\n background-color: transparent\n border: none\n border-radius: 0\n box-shadow: none\n padding: 0\n\n > .publish\n > p.status:empty\n margin: 0\n \n > pre\n user-select: all\n \n > actions\n display: flex\n > button:last-child\n margin-left: auto\n\n:focus\n color: white\n background-color: primary-color\n outline: none\n\nhtml, body\n height: 100%\n\nbody\n color: #241440\n display: flex\n font-family: Chicago, sans-serif\n font-size: 16px\n line-height: 1rem\n margin: 0\n overflow: hidden\n user-select: none\n\np\n font-family: sans-serif\n\n// Input and form things\ninput, textarea, select, button\n font-family: inherit\n\ninput\n background-color: bg-color\n border: 1px solid primary-color\n border-radius: 4px\n box-shadow: 1px 2px 0px primary-color inset\n color: primary-color\n font-size: inherit\n padding: 2px 0.25em\n\n // Firefox number spinners are a crime to my eyes ;_;\n // TODO Custom style for number spinners on all browsers\n &[type=\"number\"]\n -moz-appearance: textfield\n \n &:focus\n background-color: active-color\n color: rgba(0, 0, 0, 0.69)\n\n@keyframes note-active\n from\n background-color: rgba(0, 0, 0, 0)\n\n to\n background-color: rgba(255, 0, 255, 0)\n\n// Background has to be on ::after so it is above the ledger lines on ::before\n// Accidentals are in ::after content, vertically centered and left of the bg\nnote\n font-size: 48px\n height: 48px\n pixelated()\n position: absolute\n width: 48px\n\n &.active\n animation-name: note-active\n animation-duration: 0.25s\n\n &::after\n align-items: center\n background-repeat: no-repeat\n background-position: 100% 50%\n content: \"\"\n display: flex\n position: absolute\n left: 0\n top: 0\n width: 100%\n height: 100%\n text-indent: -12px\n\n &.♭\n &::after\n content: \"♭\"\n\n &.♯\n &::after\n content: \"♯\"\n\n // Extra ledger lines\n &.C4, &.A5, &.C6, &.C2, &.E2, &.B5, &.D2\n &::before\n content: \"\"\n width: 48px\n left: 0px\n top: 23px\n position: absolute\n height: 0\n border-bottom: 2px solid black\n\n &.B5\n &::before\n top: 40px\n\n &.D2\n &::before\n top: -8px\n\nsong-section\n height: 483px\n position: absolute\n top: -241px\n\n &::after\n content: \"\"\n border-right: 2px solid black\n height: 100%\n position: absolute\n right: 10px\n\n > span.measure-number\n background-color: rgba(255, 255, 255, 0.9375)\n border: 1px solid black\n box-shadow: 1px 1px 0 0 rgba(0,0,0,0.5)\n font-style: italic\n left: 0px\n padding: 2px 6px 2px 4px\n position: absolute\n top: -132px\n\n > div.key-signature\n &.s > ::after\n content: \"♯\"\n\n &.f > ::after\n content: \"♭\"\n\n > *\n display: none\n font-size: 96px\n height: 48px\n position: absolute\n width: 48px\n\n &::after\n align-items: center\n display: flex\n height: 100%\n width: 100%\n\n &.s1, &.s2, &.s3, &.s4, &.s5, &.s6, &.s7\n > :nth-child(1)\n display: initial\n top: -24px\n left: -96px\n &.s2, &.s3, &.s4, &.s5, &.s6, &.s7\n > :nth-child(2)\n display: initial\n top: 48px\n left: -72px\n &.s3, &.s4, &.s5, &.s6, &.s7\n > :nth-child(3)\n display: initial\n top: -48px\n left: -48px\n &.s4, &.s5, &.s6, &.s7\n > :nth-child(4)\n display: initial\n top: 24px\n left: -24px\n &.s5, &.s6, &.s7\n > :nth-child(5)\n display: initial\n top: 96px\n left: 0\n &.s6, &.s7\n > :nth-child(6)\n display: initial\n top: 0px\n left: 24px\n &.s7\n > :nth-child(7)\n display: initial\n top: 72px\n left: 48px\n \n &.f1, &.f2, &.f3, &.f4, &.f5, &.f6, &.f7\n > :nth-child(1)\n display: initial\n top: 72px\n left: -96px\n &.f2, &.f3, &.f4, &.f5, &.f6, &.f7\n > :nth-child(2)\n display: initial\n top: 0px\n left: -72px\n &.f3, &.f4, &.f5, &.f6, &.f7\n > :nth-child(3)\n display: initial\n top: 96px\n left: -48px\n &.f4, &.f5, &.f6, &.f7\n > :nth-child(4)\n display: initial\n top: 24px\n left: -24px\n &.f5, &.f6, &.f7\n > :nth-child(5)\n display: initial\n top: -48px\n left: 0\n &.f6, &.f7\n > :nth-child(6)\n display: initial\n top: 48px\n left: 24px\n &.f7\n > :nth-child(7)\n display: initial\n top: -24px\n left: 48px\n\ntd\n > select\n width: 100%\n > input\n border-radius: 0\n box-shadow: none\n > aside.fx-picker\n > label\n display: none\n\n &.sprite\n text-align: center\n vertical-align: middle\n\n > img\n margin-right: 1rem\n vertical-align: middle\n \n &.input\n > input[type=number]\n display: block\n margin: auto\n width: 60px\n\nsection.settings\n overflow: auto\n padding: 1rem\n position: relative\n\n > h2\n margin: 0 0 1rem\n > button.close\n position: absolute\n top: 1rem\n right: 1rem\n\n > table\n margin: 0 -8px\n width: calc(100% + 16px)\n\nsection.demo-picker\n overflow: auto\n padding: 1rem\n position: relative\n\n > h2\n margin: 0 0 1rem\n > button.close\n position: absolute\n top: 1rem\n right: 1rem\n\n > table\n font-size: 18px\n > tbody\n > tr\n cursor: pointer\n line-height: 2rem\n\n &:hover\n background-color: rgba(103, 58, 183, 0.19)\n\nviewport\n background-attachment: local\n background-color: bg-color\n display: flex\n height: 100%\n align-items: center\n overflow-x: scroll\n overflow-y: hidden\n\n > staff\n background-color: rgba(255, 255, 255, 0.9375)\n border: 1px solid rgba(0, 0, 0, 0.5)\n box-sizing: content-box\n box-shadow: 1px 1px 0 0 rgba(0, 0, 0, 0.5)\n display: block\n flex: 0 0 auto\n padding: 96px 0\n position: relative\n margin: 0 48px\n z-index: 0\n\n // Hack for right margin inside scrollable viewport\n // Also serving as song end bar\n &::after\n border-left: 8px solid black\n content: \"\"\n position: absolute\n right: -48px\n top: 96px\n width: 48px\n height: calc(100% - 192px)\n z-index: -1\n\n > z-meter\n display: block\n position: absolute\n left: 256px\n top: 96px\n height: calc(100% - 192px)\n width: calc(100% - 256px)\n\n &::before\n content: \"\"\n border-left: 2px solid black\n position: absolute\n height: 100%\n left: -257px\n\n > div.repeat\n position: absolute\n right: 0\n height: 100%\n\n &::before, &::after\n content: \"\"\n display: block\n background-color: black\n border-radius: 100%\n position: absolute\n width: 16px\n height: 16px\n right: 16px\n top: 66px\n\n &::after\n top: 114px\n \n &.bass\n position: relative\n top: 288px\n\n > notes\n display: block\n position: absolute\n left: 256px\n top: 337px\n\n > pattern-preview\n opacity: 0.5\n position: absolute\n\n > selection\n background-color: rgba(103, 58, 183, 0.25)\n border: 2px dashed primary-color\n position: absolute\n left: -150px\n z-index: 20\n\n > button\n display: none\n position: absolute\n top: 0\n left: 0\n right: 0\n bottom: 0\n margin: auto\n width: 48px\n height: 48px\n\n &.up\n bottom: calc(100%+4px)\n top: auto\n &.down\n top: calc(100%+4px)\n bottom: auto\n &.left\n right: calc(100%+4px)\n left: auto\n &.right\n left: calc(100%+4px)\n right: auto\n\n > actions\n display: none\n position: absolute\n\n > button\n margin-left: 4px\n\n &.t > actions\n top: 0\n &.b > actions\n bottom: 0\n &.l > actions\n left: 0\n &.r > actions\n right: 0\n\n &.set \n > actions\n display: flex\n > button\n display: block\n\n > lines\n display: block\n margin-bottom: 48px\n \n &:nth-child(2)\n margin-bottom: 0\n\n > line:last-child\n height: 0\n\n > line\n border-top: 3px solid black\n display: block\n height: 48px\n\n > playhead\n border-left: 1px solid rgba(103, 58, 183, 0.5)\n border-right: 1px solid rgba(103, 58, 183, 0.5)\n position: absolute\n top: 0\n height: 674px\n width: 2px\n z-index: 10\n\n &.buffer-start\n display: none\n border-color: rgba(255, 0, 0, 0.5)\n\n &.buffer-end\n display: none\n border-color: rgba(0, 0, 255, 0.5)\n\n > img\n position: absolute\n height: 600px\n top: -94px\n left: -120px\n\n &:last-child\n left: -100px\n top: 181px\n\nform\n > label\n display: block\n\n > h3\n font-size: 1rem\n\n &.inline\n display: inline-block\n margin-right: 0.5em\n\n > input\n padding-left: 2px\n width: 100%\n\n > actions\n display: flex\n justify-content: space-between\n margin-top: 1em\n\n &.purchase\n width: 672px\n\napp\n display: flex\n flex: 1 0\n height: 100%\n flex-direction: column\n\nbutton.loop\n font-size: 32px\n line-height: 1rem\n\naside.meter-picker\n margin-left: 8px\n > button\n border-radius: 0\n\n &:first-child\n border-top-left-radius: 4px\n border-bottom-left-radius: 4px\n\n &:last-child\n border-top-right-radius: 4px\n border-bottom-right-radius: 4px\n\naside.note-control\n > section\n display: flex\n margin-left: 1rem\n \n > label\n display: flex\n align-items: center\n margin-right: 4px\n\n > button\n flex: 0 0 auto\n font-size: 20px\n line-height: 1rem\n width: 36px\n\n border-radius: 0\n\n &.triplet\n font-size: 16px\n\n &:nth-child(n + 3)\n border-left: 0\n\n &:nth-child(2)\n border-top-left-radius: 4px\n border-bottom-left-radius: 4px\n\n &.snap\n > button\n &:nth-child(5)\n border-top-right-radius: 4px\n border-bottom-right-radius: 4px\n \n > input\n margin-left: 5px\n width: 60px\n\n &.accidental\n > button:nth-child(4)\n border-top-right-radius: 4px\n border-bottom-right-radius: 4px\n\nsection.persistence\n display: flex\n flex-direction: column\n padding: 1rem\n width: 480px\n\n > button\n margin-top: 8px\n width: 100%\n\n &:first-child\n margin-top: 0\n\nabout > actions\n > button, a.button\n width: 100%\n margin-top: 8px\n\naside\n display: flex\n > label\n display: flex\n align-items: center\n margin-right: 4px\n margin-left: 1rem\n\naside.stereo-analyser\n > canvas\n border: 1px solid #673ab7\n border-radius: 4px\n\naside.fx-picker\n display: flex\n\n > button\n background-size: 100%\n border: 1px solid #673ab7\n border-radius: 4px\n height: 36px\n padding: 0\n margin-left: 2px\n width: 36px\n\naside.actions\n background-color: white\n border-top: 2px solid primary-color\n display: flex\n flex: 0 0 auto\n flex-direction: column\n padding: 4px 4px 0px 4px\n width: 100%\n\n > section:nth-child(2)\n > button, > a.button\n padding: 15px 8px\n\n > section\n display: flex\n &:last-child\n margin-top: 8px\n\n > section.buttons\n > *\n margin-bottom: 6px\n \n &:nth-child(n + 2)\n margin-left: 4px\n \n > form\n display: flex\n \n > button, > a.button\n flex: 0 0 auto\n\n > label\n align-items: center\n border: 1px solid #673ab7\n border-radius: 4px\n box-shadow: 1px 2px 0px #673ab7\n color: #673ab7\n display: flex\n flex-direction: column\n padding: 5px 8px 4px\n white-space: nowrap\n \n > input\n padding: 2px 0 0\n text-align: center\n width: 60px\n \n > h2\n display: block\n font-size: 1em\n font-weight: normal\n margin: 0 0 4px\n \n > .right\n margin-left: auto\n\nactions > label\n background-color: white\n border 1px solid primary-color\n border-radius: 4px\n box-shadow: 1px 2px 0px primary-color\n color: #673ab7\n cursor: pointer\n font: inherit\n line-height: 1em\n padding: 9px 16px\n &:nth-child(n + 2)\n margin-left: 4px\n\na.button\n align-items: center\n display: inline-flex\n justify-content: center\n text-align: center\n text-decoration: none\n\n // Hack for merch icon spacing\n > :nth-child(2)\n margin-left: 5px\n\nbutton, a.button\n background-color: white\n border 1px solid primary-color\n border-radius: 4px\n box-shadow: 1px 2px 0px primary-color\n color: #673ab7\n cursor: pointer\n font-size: inherit\n line-height: 1em\n padding: 9px 8px\n white-space: nowrap\n\n &.full\n width: 100%\n\n &:focus\n background-color: active-color\n color: rgba(0, 0, 0, 0.69)\n outline-offset: 4px\n\n &:active, &.active\n background-color: primary-color\n border 1px solid primary-color\n color: white\n box-shadow: 1px 2px 0px #241440 inset\n\n &:disabled\n background-color: #eee\n border-color: #4e4e4e\n box-shadow: 1px 2px 0px #4e4e4e\n color: #4e4e4e\n cursor: default\n\ntools, patterns\n background-color: white\n border-bottom: 2px solid primary-color\n display: flex\n width: 100%\n\n > *\n background-repeat: no-repeat\n background-position: 50% 50%\n border-right: 1px solid primary-color\n cursor: pointer\n display: block\n width: 49px\n height: 48px\n &:hover\n background-color: highlight-color\n &.active\n background-color: active-color\n\n > tool.eraser\n order: 2\n background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAAIdJREFUeJzNUsERwCAIw15n031wDt0Hl0s/9VoF9NnmZzRBCERfI2zusdOtDABmopRGVoRCrdviADNMiADM6L873Mql2NYiw3E2WItzVi2dSuw8JBHNvQyegcU4vmjNFesWZrHFTSlYQ/RhRDgatKZFnXPy7zMIoVaYa3fH5i3PTHira4r/gQv1W1E4p9FksQAAAABJRU5ErkJggg==\")\n\n > .selection\n order: 2\n background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAiUlEQVRYR+1XQQrAIAyr/3/0RLAyqoUdzNJDvFnEpkkM2MzssX21Qw1SGo0igHfNgfiZ6/sI4HqDSVs6wGlaCNXZpQ7gN80jkIxyNAtLkjIA0BOn99O0d0RlJIjvFC3JZkJ0Q3kgMqAcWIwoB8oEkXKAHsV0APIAXQI6AHkA9vf78jUbZ+gAaB7opmM7IWnG3nUAAAAASUVORK5CYII=\")\n\ntools\n > *\n pixelated()\n\npatterns\n margin-top: -1px\n\n &:empty\n display: none\n\n > pattern\n display: flex\n padding: 0 8px\n align-items: center\n width: 64px\n overflow: hidden\n\n > preview\n position: relative\n transform: scale(0.0625, 0.0625)\n top: -14px\n\n > *\n transform: scale(4)\n\npre.position\n background-color: rgba(255, 255, 255, 0.9375)\n border: 1px solid black\n box-shadow: 1px 1px 0 0 rgba(0,0,0,0.5)\n padding: 2px 6px 2px 4px\n font-family: inherit\n pointer-events: none\n padding: 4px\n position: absolute\n left: 1rem\n top: calc(45px + 1rem)\n\n &:empty\n display: none\n\npre.debug\n &:empty\n display: none\n\n@media only screen and (max-width: 768px)\n aside.actions\n border-top: none\n padding-top: 0\n > section\n &:first-child\n display: none\n &:nth-child(2)\n margin-top: 0\n\n button\n > span.description\n display: none\n\n tools, patterns\n order: 2\n border: none\n width: 49px\n height: 48px\n\n > *\n border-top: 1px solid primary-color\n display: none\n\n tool.active\n display: block\n\n pattern.active\n display: flex\n\n &.open\n background-color: primary-color\n display: grid\n grid-gap: 1px\n position: absolute\n width: 100%\n height: 100%\n grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr\n z-index: 1\n\n > *\n background-color: white\n background-size: 100%\n border: none\n display: block\n image-rendering: pixelated\n height: 100%\n width: 100%\n\n &:hover\n background-color: #FFE0B2\n" }, "templates/about.jadelet": { "content": "about\n h1 About\n\n p ProTip™ hold Shift to sharp, Ctrl to flat\n\n p\n | By\n a(href=\"https://danielx.net\") Daniel X. Moore\n | creator of\n a(href=\"https://whimsy.space\") Whimsy.Space\n\n p\n" @@ -427,7 +427,7 @@ "content": "" }, "templates/persistence.jadelet": { - "content": "section.persistence\n button(click=@showDemoSongPicker) Load a demo song\n button(click=@saveFile) Save to disk\n button(click=@openFile) Load from disk\n\n button(click=@loadFromURLString) Load from URL\n button(click=@exportAudio) Export to .wav or .mp3\n" + "content": "section.persistence\n button(click=@showDemoSongPicker) Load a demo song\n button(click=@saveFile) Save to disk\n button(click=@openFile) Load from disk\n button(click=@exportAudio) Export to .wav or .mp3\n" }, "templates/arranger.jadelet": { "content": "section.arranger\n h2 Sections\n table\n thead\n tr\n th Name\n th Time Signature\n th Key Signature\n th Length\n th Tempo\n th FX\n th Action\n tbody\n @items\n actions\n button(click=@newSection) + New Section\n" @@ -865,7 +865,7 @@ "content": "var Observable;\n\nObservable = system.ui.Observable;\n\nmodule.exports = {\n name: \"Delay\",\n value: Observable(100),\n min: 0,\n max: 250,\n unit: \"ms\"\n};\n" }, "templates/persistence": { - "content": "module.exports = system.ui.Jadelet.exec([\"section\",{\"class\":[\"persistence\"]},[[\"button\",{\"click\":{\"bind\":\"showDemoSongPicker\"}},[\"Load a demo song\"]],[\"button\",{\"click\":{\"bind\":\"saveFile\"}},[\"Save to disk\"]],[\"button\",{\"click\":{\"bind\":\"openFile\"}},[\"Load from disk\"]],[\"button\",{\"click\":{\"bind\":\"loadFromURLString\"}},[\"Load from URL\"]],[\"button\",{\"click\":{\"bind\":\"exportAudio\"}},[\"Export to .wav or .mp3\"]]]]);" + "content": "module.exports = system.ui.Jadelet.exec([\"section\",{\"class\":[\"persistence\"]},[[\"button\",{\"click\":{\"bind\":\"showDemoSongPicker\"}},[\"Load a demo song\"]],[\"button\",{\"click\":{\"bind\":\"saveFile\"}},[\"Save to disk\"]],[\"button\",{\"click\":{\"bind\":\"openFile\"}},[\"Load from disk\"]],[\"button\",{\"click\":{\"bind\":\"exportAudio\"}},[\"Export to .wav or .mp3\"]]]]);" }, "templates/arranger": { "content": "module.exports = system.ui.Jadelet.exec([\"section\",{\"class\":[\"arranger\"]},[[\"h2\",{},[\"Sections\"]],[\"table\",{},[[\"thead\",{},[[\"tr\",{},[[\"th\",{},[\"Name\"]],[\"th\",{},[\"Time Signature\"]],[\"th\",{},[\"Key Signature\"]],[\"th\",{},[\"Length\"]],[\"th\",{},[\"Tempo\"]],[\"th\",{},[\"FX\"]],[\"th\",{},[\"Action\"]]]]]],[\"tbody\",{},[{\"bind\":\"items\"}]]]],[\"actions\",{},[[\"button\",{\"click\":{\"bind\":\"newSection\"}},[\"+ New Section\"]]]]]]);"