├── .gitignore ├── Cantor.framer ├── .gitignore ├── app.coffee ├── framer │ ├── coffee-script.js │ ├── config.json │ ├── framer.generated.js │ ├── framer.init.js │ ├── framer.js │ ├── framer.js.map │ ├── framer.modules.js │ ├── images │ │ ├── cursor-active.png │ │ ├── cursor-active@2x.png │ │ ├── cursor.png │ │ ├── cursor@2x.png │ │ ├── icon-120.png │ │ ├── icon-152.png │ │ ├── icon-180.png │ │ ├── icon-192.png │ │ └── icon-76.png │ ├── style.css │ └── version ├── images │ ├── .gitkeep │ ├── ants.gif │ ├── dash.png │ ├── grid-high-contrast.svg │ ├── grid.svg │ └── triangle@2x.png ├── index.html ├── modules │ ├── TextLayer.coffee │ ├── inline-worker.js │ ├── kaColors.js │ ├── myModule.coffee │ ├── npm.coffee │ ├── recorder.js │ └── utils.coffee ├── node_modules │ └── deep-equal │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── example │ │ └── cmp.js │ │ ├── index.js │ │ ├── lib │ │ ├── is_arguments.js │ │ └── keys.js │ │ ├── package.json │ │ ├── readme.markdown │ │ └── test │ │ └── cmp.js └── recordings │ ├── 1.json │ └── 1.wav ├── Readme.mdown └── Sketches ├── 3d layered operation viz.framer ├── .gitignore ├── app.coffee ├── framer │ ├── coffee-script.js │ ├── config.json │ ├── framer.generated.js │ ├── framer.init.js │ ├── framer.js │ ├── framer.js.map │ ├── framer.modules.js │ ├── images │ │ ├── background.png │ │ ├── cursor-active.png │ │ ├── cursor-active@2x.png │ │ ├── cursor.png │ │ ├── cursor@2x.png │ │ ├── icon-120.png │ │ ├── icon-152.png │ │ ├── icon-180.png │ │ ├── icon-192.png │ │ ├── icon-76.png │ │ ├── icon-arrow.png │ │ ├── icon-arrow@2x.png │ │ ├── icon-close.png │ │ ├── icon-close@2x.png │ │ ├── icon-framer.png │ │ ├── icon-framer@2x.png │ │ ├── icon-share.png │ │ └── icon-share@2x.png │ ├── mirror.css │ ├── style.css │ └── version ├── images │ └── .gitkeep ├── index.html └── modules │ ├── kaColors.js │ └── myModule.coffee ├── Partitive division with stretching.framer ├── .gitignore ├── app.coffee ├── framer │ ├── coffee-script.js │ ├── config.json │ ├── framer.generated.js │ ├── framer.init.js │ ├── framer.js │ ├── framer.js.map │ ├── framer.modules.js │ ├── images │ │ ├── cursor-active.png │ │ ├── cursor-active@2x.png │ │ ├── cursor.png │ │ ├── cursor@2x.png │ │ ├── icon-120.png │ │ ├── icon-152.png │ │ ├── icon-180.png │ │ ├── icon-192.png │ │ └── icon-76.png │ ├── style.css │ └── version ├── images │ ├── .gitkeep │ ├── grid.svg │ └── triangle@2x.png ├── index.html └── modules │ ├── kaColors.js │ └── myModule.coffee ├── Partitive division.framer ├── .gitignore ├── app.coffee ├── framer │ ├── coffee-script.js │ ├── config.json │ ├── framer.generated.js │ ├── framer.init.js │ ├── framer.js │ ├── framer.js.map │ ├── framer.modules.js │ ├── images │ │ ├── cursor-active.png │ │ ├── cursor-active@2x.png │ │ ├── cursor.png │ │ ├── cursor@2x.png │ │ ├── icon-120.png │ │ ├── icon-152.png │ │ ├── icon-180.png │ │ ├── icon-192.png │ │ └── icon-76.png │ ├── style.css │ └── version ├── images │ ├── .gitkeep │ └── grid.svg ├── index.html └── modules │ ├── kaColors.js │ └── myModule.coffee └── syzygy.framer ├── .gitignore ├── app.coffee ├── framer ├── coffee-script.js ├── config.json ├── framer.generated.js ├── framer.init.js ├── framer.js ├── framer.js.map ├── framer.modules.js ├── images │ ├── background.png │ ├── cursor-active.png │ ├── cursor-active@2x.png │ ├── cursor.png │ ├── cursor@2x.png │ ├── icon-120.png │ ├── icon-152.png │ ├── icon-180.png │ ├── icon-192.png │ ├── icon-76.png │ ├── icon-arrow.png │ ├── icon-arrow@2x.png │ ├── icon-close.png │ ├── icon-close@2x.png │ ├── icon-framer.png │ ├── icon-framer@2x.png │ ├── icon-share.png │ └── icon-share@2x.png ├── mirror.css ├── style.css └── version ├── images └── .gitkeep ├── index.html └── modules ├── kaColors.js └── myModule.coffee /.gitignore: -------------------------------------------------------------------------------- 1 | Cantor.framer/framer/metadata.json 2 | Cantor.framer/framer/social* -------------------------------------------------------------------------------- /Cantor.framer/.gitignore: -------------------------------------------------------------------------------- 1 | # Framer Git Ignore 2 | 3 | # General OSX 4 | 5 | .DS_Store 6 | .AppleDouble 7 | .LSOverride 8 | 9 | # Icon must end with two \r 10 | Icon 11 | 12 | 13 | # Thumbnails 14 | ._* 15 | 16 | # Files that might appear in the root of a volume 17 | .DocumentRevisions-V100 18 | .fseventsd 19 | .Spotlight-V100 20 | .TemporaryItems 21 | .Trashes 22 | .VolumeIcon.icns 23 | 24 | # Directories potentially created on remote AFP share 25 | .AppleDB 26 | .AppleDesktop 27 | Network Trash Folder 28 | Temporary Items 29 | .apdisk 30 | 31 | 32 | # Framer Specific 33 | .*.html 34 | framer/*.old* 35 | framer/backup.coffee 36 | framer/backups/* 37 | framer/.*.hash 38 | framer/preview.png 39 | framer/manifest.txt 40 | -------------------------------------------------------------------------------- /Cantor.framer/framer/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "propertyPanelToggleStates" : { 3 | 4 | }, 5 | "deviceOrientation" : 90, 6 | "sharedPrototype" : 1, 7 | "contentScale" : 1, 8 | "deviceType" : "apple-ipad-air-2-silver", 9 | "selectedHand" : "", 10 | "updateDelay" : 0.3, 11 | "deviceScale" : "fit", 12 | "foldedCodeRanges" : [ 13 | 14 | ], 15 | "orientation" : 90, 16 | "fullScreen" : false 17 | } -------------------------------------------------------------------------------- /Cantor.framer/framer/framer.generated.js: -------------------------------------------------------------------------------- 1 | // This is autogenerated by Framer 2 | 3 | 4 | if (!window.Framer && window._bridge) {window._bridge('runtime.error', {message:'[framer.js] Framer library missing or corrupt. Select File → Update Framer Library.'})} 5 | if (DeviceComponent) {DeviceComponent.Devices["iphone-6-silver"].deviceImageJP2 = false}; 6 | if (window.Framer) {window.Framer.Defaults.DeviceView = {"deviceScale":"fit","selectedHand":"","deviceType":"apple-ipad-air-2-silver","contentScale":1,"orientation":90}; 7 | } 8 | if (window.Framer) {window.Framer.Defaults.DeviceComponent = {"deviceScale":"fit","selectedHand":"","deviceType":"apple-ipad-air-2-silver","contentScale":1,"orientation":90}; 9 | } 10 | window.FramerStudioInfo = {"deviceImagesUrl":"\/_server\/resources\/DeviceImages","documentTitle":"Cantor.framer"}; 11 | 12 | Framer.Device = new Framer.DeviceView(); 13 | Framer.Device.setupContext(); -------------------------------------------------------------------------------- /Cantor.framer/framer/framer.init.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | function isFileLoadingAllowed() { 4 | return (window.location.protocol.indexOf("file") == -1) 5 | } 6 | 7 | function isHomeScreened() { 8 | return ("standalone" in window.navigator) && window.navigator.standalone == true 9 | } 10 | 11 | function isCompatibleBrowser() { 12 | return Utils.isWebKit() 13 | } 14 | 15 | var alertNode; 16 | 17 | function dismissAlert() { 18 | alertNode.parentElement.removeChild(alertNode) 19 | loadProject() 20 | } 21 | 22 | function showAlert(html) { 23 | 24 | alertNode = document.createElement("div") 25 | 26 | alertNode.classList.add("framerAlertBackground") 27 | alertNode.innerHTML = html 28 | 29 | document.addEventListener("DOMContentLoaded", function(event) { 30 | document.body.appendChild(alertNode) 31 | }) 32 | 33 | window.dismissAlert = dismissAlert; 34 | } 35 | 36 | function showBrowserAlert() { 37 | var html = "" 38 | html += "
" 39 | html += "Error: Not A WebKit Browser" 40 | html += "Your browser is not supported.
Please use Safari or Chrome.
" 41 | html += "Try anyway" 42 | html += "
" 43 | 44 | showAlert(html) 45 | } 46 | 47 | function showFileLoadingAlert() { 48 | var html = "" 49 | html += "
" 50 | html += "Error: Local File Restrictions" 51 | html += "Preview this prototype with Framer Mirror or learn more about " 52 | html += "file restrictions.
" 53 | html += "Try anyway" 54 | html += "
" 55 | 56 | showAlert(html) 57 | } 58 | 59 | function loadProject() { 60 | CoffeeScript.load("app.coffee") 61 | } 62 | 63 | function setDefaultPageTitle() { 64 | // If no title was set we set it to the project folder name so 65 | // you get a nice name on iOS if you bookmark to desktop. 66 | document.addEventListener("DOMContentLoaded", function() { 67 | if (document.title == "") { 68 | if (window.FramerStudioInfo && window.FramerStudioInfo.documentTitle) { 69 | document.title = window.FramerStudioInfo.documentTitle 70 | } else { 71 | document.title = window.location.pathname.replace(/\//g, "") 72 | } 73 | } 74 | }) 75 | } 76 | 77 | function init() { 78 | 79 | if (Utils.isFramerStudio()) { 80 | return 81 | } 82 | 83 | setDefaultPageTitle() 84 | 85 | if (!isCompatibleBrowser()) { 86 | return showBrowserAlert() 87 | } 88 | 89 | if (!isFileLoadingAllowed()) { 90 | return showFileLoadingAlert() 91 | } 92 | 93 | loadProject() 94 | 95 | } 96 | 97 | init() 98 | 99 | })() 100 | -------------------------------------------------------------------------------- /Cantor.framer/framer/images/cursor-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Khan/Cantor/80c65205a83e58160369806471bdf981c3bfa26a/Cantor.framer/framer/images/cursor-active.png -------------------------------------------------------------------------------- /Cantor.framer/framer/images/cursor-active@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Khan/Cantor/80c65205a83e58160369806471bdf981c3bfa26a/Cantor.framer/framer/images/cursor-active@2x.png -------------------------------------------------------------------------------- /Cantor.framer/framer/images/cursor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Khan/Cantor/80c65205a83e58160369806471bdf981c3bfa26a/Cantor.framer/framer/images/cursor.png -------------------------------------------------------------------------------- /Cantor.framer/framer/images/cursor@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Khan/Cantor/80c65205a83e58160369806471bdf981c3bfa26a/Cantor.framer/framer/images/cursor@2x.png -------------------------------------------------------------------------------- /Cantor.framer/framer/images/icon-120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Khan/Cantor/80c65205a83e58160369806471bdf981c3bfa26a/Cantor.framer/framer/images/icon-120.png -------------------------------------------------------------------------------- /Cantor.framer/framer/images/icon-152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Khan/Cantor/80c65205a83e58160369806471bdf981c3bfa26a/Cantor.framer/framer/images/icon-152.png -------------------------------------------------------------------------------- /Cantor.framer/framer/images/icon-180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Khan/Cantor/80c65205a83e58160369806471bdf981c3bfa26a/Cantor.framer/framer/images/icon-180.png -------------------------------------------------------------------------------- /Cantor.framer/framer/images/icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Khan/Cantor/80c65205a83e58160369806471bdf981c3bfa26a/Cantor.framer/framer/images/icon-192.png -------------------------------------------------------------------------------- /Cantor.framer/framer/images/icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Khan/Cantor/80c65205a83e58160369806471bdf981c3bfa26a/Cantor.framer/framer/images/icon-76.png -------------------------------------------------------------------------------- /Cantor.framer/framer/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | border: none; 5 | -webkit-user-select: none; 6 | -webkit-tap-highlight-color: rgba(0,0,0,0); 7 | } 8 | 9 | body { 10 | background-color: #fff; 11 | font: 28px/1em "Helvetica"; 12 | color: gray; 13 | overflow: hidden; 14 | } 15 | 16 | a { 17 | color: gray; 18 | } 19 | 20 | body { 21 | cursor: url('images/cursor.png') 32 32, auto; 22 | cursor: -webkit-image-set( 23 | url('images/cursor.png') 1x, 24 | url('images/cursor@2x.png') 2x 25 | ) 32 32, auto; 26 | } 27 | 28 | body:active { 29 | cursor: url('images/cursor-active.png') 32 32, auto; 30 | cursor: -webkit-image-set( 31 | url('images/cursor-active.png') 1x, 32 | url('images/cursor-active@2x.png') 2x 33 | ) 32 32, auto; 34 | } 35 | 36 | .framerAlertBackground { 37 | position: absolute; top:0px; left:0px; right:0px; bottom:0px; 38 | z-index: 1000; 39 | background-color: #fff; 40 | } 41 | 42 | .framerAlert { 43 | font:400 14px/1.4 "Helvetica Neue", Helvetica, Arial, sans-serif; 44 | -webkit-font-smoothing:antialiased; 45 | color:#616367; text-align:center; 46 | position: absolute; top:40%; left:50%; width:260px; margin-left:-130px; 47 | } 48 | .framerAlert strong { font-weight:500; color:#000; margin-bottom:8px; display:block; } 49 | .framerAlert a { color:#28AFFA; } 50 | .framerAlert .btn { 51 | font-weight:500; text-decoration:none; line-height:1; 52 | display:inline-block; padding:6px 12px 7px 12px; 53 | border-radius:3px; margin-top:12px; 54 | background:#28AFFA; color:#fff; 55 | } 56 | 57 | ::-webkit-scrollbar { 58 | display: none; 59 | } -------------------------------------------------------------------------------- /Cantor.framer/framer/version: -------------------------------------------------------------------------------- 1 | 4 -------------------------------------------------------------------------------- /Cantor.framer/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Khan/Cantor/80c65205a83e58160369806471bdf981c3bfa26a/Cantor.framer/images/.gitkeep -------------------------------------------------------------------------------- /Cantor.framer/images/ants.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Khan/Cantor/80c65205a83e58160369806471bdf981c3bfa26a/Cantor.framer/images/ants.gif -------------------------------------------------------------------------------- /Cantor.framer/images/dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Khan/Cantor/80c65205a83e58160369806471bdf981c3bfa26a/Cantor.framer/images/dash.png -------------------------------------------------------------------------------- /Cantor.framer/images/grid-high-contrast.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | grid 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Cantor.framer/images/grid.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | grid 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Cantor.framer/images/triangle@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Khan/Cantor/80c65205a83e58160369806471bdf981c3bfa26a/Cantor.framer/images/triangle@2x.png -------------------------------------------------------------------------------- /Cantor.framer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Cantor.framer/modules/TextLayer.coffee: -------------------------------------------------------------------------------- 1 | class TextLayer extends Layer 2 | 3 | constructor: (options={}) -> 4 | @doAutoSize = false 5 | @doAutoSizeHeight = false 6 | options.backgroundColor ?= if options.setup then "hsla(60, 90%, 47%, .4)" else "transparent" 7 | options.color ?= "red" 8 | options.lineHeight ?= 1.25 9 | options.fontFamily ?= "Helvetica" 10 | options.fontSize ?= 20 11 | options.text ?= "Use layer.text to add text" 12 | super options 13 | @style.whiteSpace = "pre-line" # allow \n in .text 14 | @style.outline = "none" # no border when selected 15 | 16 | setStyle: (property, value, pxSuffix = false) -> 17 | @style[property] = if pxSuffix then value+"px" else value 18 | @emit("change:#{property}", value) 19 | if @doAutoSize then @calcSize() 20 | 21 | calcSize: -> 22 | sizeAffectingStyles = 23 | lineHeight: @style["line-height"] 24 | fontSize: @style["font-size"] 25 | fontWeight: @style["font-weight"] 26 | paddingTop: @style["padding-top"] 27 | paddingRight: @style["padding-right"] 28 | paddingBottom: @style["padding-bottom"] 29 | paddingLeft: @style["padding-left"] 30 | textTransform: @style["text-transform"] 31 | borderWidth: @style["border-width"] 32 | letterSpacing: @style["letter-spacing"] 33 | fontFamily: @style["font-family"] 34 | fontStyle: @style["font-style"] 35 | fontVariant: @style["font-variant"] 36 | constraints = {} 37 | if @doAutoSizeHeight then constraints.width = @width 38 | size = Utils.textSize @text, sizeAffectingStyles, constraints 39 | if @style.textAlign is "right" 40 | @width = size.width 41 | @x = @x-@width 42 | else 43 | @width = size.width 44 | @height = size.height 45 | 46 | @define "autoSize", 47 | get: -> @doAutoSize 48 | set: (value) -> 49 | @doAutoSize = value 50 | if @doAutoSize then @calcSize() 51 | @define "autoSizeHeight", 52 | set: (value) -> 53 | @doAutoSize = value 54 | @doAutoSizeHeight = value 55 | if @doAutoSize then @calcSize() 56 | @define "contentEditable", 57 | set: (boolean) -> 58 | @_element.contentEditable = boolean 59 | @ignoreEvents = !boolean 60 | @on "input", -> @calcSize() if @doAutoSize 61 | @define "text", 62 | get: -> @_element.textContent 63 | set: (value) -> 64 | @_element.textContent = value 65 | @emit("change:text", value) 66 | if @doAutoSize then @calcSize() 67 | @define "fontFamily", 68 | get: -> @style.fontFamily 69 | set: (value) -> @setStyle("fontFamily", value) 70 | @define "fontSize", 71 | get: -> @style.fontSize.replace("px","") 72 | set: (value) -> @setStyle("fontSize", value, true) 73 | @define "lineHeight", 74 | get: -> @style.lineHeight 75 | set: (value) -> @setStyle("lineHeight", value) 76 | @define "fontWeight", 77 | get: -> @style.fontWeight 78 | set: (value) -> @setStyle("fontWeight", value) 79 | @define "fontStyle", 80 | get: -> @style.fontStyle 81 | set: (value) -> @setStyle("fontStyle", value) 82 | @define "fontVariant", 83 | get: -> @style.fontVariant 84 | set: (value) -> @setStyle("fontVariant", value) 85 | @define "padding", 86 | set: (value) -> 87 | @setStyle("paddingTop", value, true) 88 | @setStyle("paddingRight", value, true) 89 | @setStyle("paddingBottom", value, true) 90 | @setStyle("paddingLeft", value, true) 91 | @define "paddingTop", 92 | get: -> @style.paddingTop.replace("px","") 93 | set: (value) -> @setStyle("paddingTop", value, true) 94 | @define "paddingRight", 95 | get: -> @style.paddingRight.replace("px","") 96 | set: (value) -> @setStyle("paddingRight", value, true) 97 | @define "paddingBottom", 98 | get: -> @style.paddingBottom.replace("px","") 99 | set: (value) -> @setStyle("paddingBottom", value, true) 100 | @define "paddingLeft", 101 | get: -> @style.paddingLeft.replace("px","") 102 | set: (value) -> @setStyle("paddingLeft", value, true) 103 | @define "textAlign", 104 | set: (value) -> @setStyle("textAlign", value) 105 | @define "textTransform", 106 | get: -> @style.textTransform 107 | set: (value) -> @setStyle("textTransform", value) 108 | @define "letterSpacing", 109 | get: -> @style.letterSpacing.replace("px","") 110 | set: (value) -> @setStyle("letterSpacing", value, true) 111 | @define "length", 112 | get: -> @text.length 113 | 114 | convertToTextLayer = (layer) -> 115 | t = new TextLayer 116 | name: layer.name 117 | frame: layer.frame 118 | parent: layer.parent 119 | 120 | cssObj = {} 121 | css = layer._info.metadata.css 122 | css.forEach (rule) -> 123 | return if _.contains rule, '/*' 124 | arr = rule.split(': ') 125 | cssObj[arr[0]] = arr[1].replace(';','') 126 | t.style = cssObj 127 | 128 | importPath = layer.__framerImportedFromPath 129 | if _.contains importPath, '@2x' 130 | t.fontSize *= 2 131 | t.lineHeight = (parseInt(t.lineHeight)*2)+'px' 132 | t.letterSpacing *= 2 133 | 134 | t.y -= (parseInt(t.lineHeight)-t.fontSize)/2 # compensate for how CSS handles line height 135 | t.y -= t.fontSize * 0.1 # sketch padding 136 | t.x -= t.fontSize * 0.08 # sketch padding 137 | t.width += t.fontSize * 0.5 # sketch padding 138 | 139 | t.text = layer._info.metadata.string 140 | layer.destroy() 141 | return t 142 | 143 | Layer::convertToTextLayer = -> convertToTextLayer(@) 144 | 145 | convertTextLayers = (obj) -> 146 | for prop,layer of obj 147 | if layer._info.kind is "text" 148 | obj[prop] = convertToTextLayer(layer) 149 | 150 | # Backwards compability. Replaced by convertToTextLayer() 151 | Layer::frameAsTextLayer = (properties) -> 152 | t = new TextLayer 153 | t.frame = @frame 154 | t.superLayer = @superLayer 155 | _.extend t,properties 156 | @destroy() 157 | t 158 | 159 | exports.TextLayer = TextLayer 160 | exports.convertTextLayers = convertTextLayers 161 | -------------------------------------------------------------------------------- /Cantor.framer/modules/inline-worker.js: -------------------------------------------------------------------------------- 1 | var WORKER_ENABLED = !!(global === global.window && global.URL && global.Blob && global.Worker); 2 | 3 | function InlineWorker(func, self) { 4 | var _this = this; 5 | var functionBody; 6 | 7 | self = self || {}; 8 | 9 | if (WORKER_ENABLED) { 10 | functionBody = func.toString().trim().match( 11 | /^function\s*\w*\s*\([\w\s,]*\)\s*{([\w\W]*?)}$/ 12 | )[1]; 13 | 14 | return new global.Worker(global.URL.createObjectURL( 15 | new global.Blob([ functionBody ], { type: "text/javascript" }) 16 | )); 17 | } 18 | 19 | function postMessage(data) { 20 | setTimeout(function() { 21 | _this.onmessage({ data: data }); 22 | }, 0); 23 | } 24 | 25 | this.self = self; 26 | this.self.postMessage = postMessage; 27 | 28 | setTimeout(func.bind(self, self), 0); 29 | } 30 | 31 | InlineWorker.prototype.postMessage = function postMessage(data) { 32 | var _this = this; 33 | 34 | setTimeout(function() { 35 | _this.self.onmessage({ data: data }); 36 | }, 0); 37 | }; 38 | 39 | module.exports = InlineWorker; 40 | -------------------------------------------------------------------------------- /Cantor.framer/modules/kaColors.js: -------------------------------------------------------------------------------- 1 | // Khan Academy Color Module 2 | // 3 | // This module is meant to be imported by Framer. To use it in a Framer project: 4 | // kaColors = require "kaColors" 5 | // someLayer.backgroundColor = kaColors.kaGreen 6 | // 7 | // This file is generated by a script. You should not modify it manually. To update this file, rerun generate_framer_color_module.swift. 8 | 9 | exports.alert = "rgba(181, 16, 25, 1.0)"; 10 | exports.kaGreen = "rgba(82, 141, 28, 1.0)"; 11 | exports.kaBlue = "rgba(37, 52, 65, 1.0)"; 12 | exports.mint1 = "rgba(217, 224, 193, 1.0)"; 13 | exports.mint2 = "rgba(233, 240, 215, 1.0)"; 14 | exports.mint3 = "rgba(243, 248, 226, 1.0)"; 15 | exports.black = "rgba(0, 0, 0, 1.0)"; 16 | exports.gray17 = "rgba(25, 27, 33, 1.0)"; 17 | exports.gray25 = "rgba(45, 47, 49, 1.0)"; 18 | exports.gray41 = "rgba(79, 82, 86, 1.0)"; 19 | exports.gray68 = "rgba(117, 122, 129, 1.0)"; 20 | exports.gray76 = "rgba(172, 176, 181, 1.0)"; 21 | exports.gray85 = "rgba(205, 207, 209, 1.0)"; 22 | exports.gray90 = "rgba(220, 223, 224, 1.0)"; 23 | exports.gray95 = "rgba(236, 237, 239, 1.0)"; 24 | exports.gray97 = "rgba(244, 245, 245, 1.0)"; 25 | exports.gray98 = "rgba(249, 249, 249, 1.0)"; 26 | exports.white = "rgba(255, 255, 255, 1.0)"; 27 | exports.math4 = "rgba(13, 67, 83, 1.0)"; 28 | exports.math3 = "rgba(18, 108, 135, 1.0)"; 29 | exports.math1 = "rgba(25, 156, 194, 1.0)"; 30 | exports.math2 = "rgba(85, 209, 229, 1.0)"; 31 | exports.math5 = "rgba(114, 245, 255, 1.0)"; 32 | exports.math6 = "rgba(194, 249, 255, 1.0)"; 33 | exports.partner4 = "rgba(18, 63, 52, 1.0)"; 34 | exports.partner3 = "rgba(29, 111, 93, 1.0)"; 35 | exports.partner1 = "rgba(20, 155, 131, 1.0)"; 36 | exports.partner2 = "rgba(26, 201, 180, 1.0)"; 37 | exports.partner5 = "rgba(43, 236, 203, 1.0)"; 38 | exports.partner6 = "rgba(134, 255, 242, 1.0)"; 39 | exports.cs4 = "rgba(14, 77, 31, 1.0)"; 40 | exports.cs3 = "rgba(22, 131, 48, 1.0)"; 41 | exports.cs1 = "rgba(32, 159, 67, 1.0)"; 42 | exports.cs2 = "rgba(100, 201, 93, 1.0)"; 43 | exports.cs5 = "rgba(124, 244, 110, 1.0)"; 44 | exports.cs6 = "rgba(170, 255, 161, 1.0)"; 45 | exports.economics4 = "rgba(129, 44, 5, 1.0)"; 46 | exports.economics3 = "rgba(149, 71, 9, 1.0)"; 47 | exports.economics1 = "rgba(214, 105, 16, 1.0)"; 48 | exports.economics5 = "rgba(253, 138, 44, 1.0)"; 49 | exports.economics6 = "rgba(253, 173, 94, 1.0)"; 50 | exports.economics7 = "rgba(254, 198, 153, 1.0)"; 51 | exports.economics2 = "rgba(253, 178, 30, 1.0)"; 52 | exports.humanities4 = "rgba(120, 16, 13, 1.0)"; 53 | exports.humanities3 = "rgba(174, 20, 16, 1.0)"; 54 | exports.humanities1 = "rgba(223, 54, 44, 1.0)"; 55 | exports.humanities5 = "rgba(244, 80, 75, 1.0)"; 56 | exports.humanities2 = "rgba(252, 109, 111, 1.0)"; 57 | exports.humanities6 = "rgba(249, 150, 153, 1.0)"; 58 | exports.science4 = "rgba(87, 0, 40, 1.0)"; 59 | exports.science3 = "rgba(138, 0, 61, 1.0)"; 60 | exports.science1 = "rgba(188, 26, 105, 1.0)"; 61 | exports.science5 = "rgba(230, 67, 149, 1.0)"; 62 | exports.science2 = "rgba(252, 122, 186, 1.0)"; 63 | exports.science6 = "rgba(253, 172, 217, 1.0)"; 64 | exports.testprep4 = "rgba(36, 24, 53, 1.0)"; 65 | exports.testprep3 = "rgba(66, 41, 101, 1.0)"; 66 | exports.testprep1 = "rgba(100, 60, 155, 1.0)"; 67 | exports.testprep2 = "rgba(152, 108, 255, 1.0)"; 68 | exports.testprep5 = "rgba(185, 167, 251, 1.0)"; 69 | exports.testprep6 = "rgba(213, 204, 255, 1.0)"; 70 | exports.default4 = "rgba(2, 30, 57, 1.0)"; 71 | exports.default3 = "rgba(5, 51, 105, 1.0)"; 72 | exports.default1 = "rgba(17, 57, 146, 1.0)"; 73 | exports.default6 = "rgba(29, 87, 189, 1.0)"; 74 | exports.default5 = "rgba(48, 123, 222, 1.0)"; 75 | exports.default2 = "rgba(85, 158, 227, 1.0)"; 76 | exports.yellow1 = "rgba(194, 157, 21, 1.0)"; 77 | exports.yellow2 = "rgba(225, 182, 24, 1.0)"; 78 | exports.yellow3 = "rgba(240, 204, 54, 1.0)"; 79 | exports.yellow4 = "rgba(251, 221, 74, 1.0)"; 80 | exports.yellow5 = "rgba(255, 231, 130, 1.0)"; 81 | exports.yellow6 = "rgba(255, 239, 168, 1.0)"; 82 | -------------------------------------------------------------------------------- /Cantor.framer/modules/myModule.coffee: -------------------------------------------------------------------------------- 1 | # Add the following line to your project in Framer Studio. 2 | # myModule = require "myModule" 3 | # Reference the contents by name, like myModule.myFunction() or myModule.myVar 4 | 5 | exports.myVar = "myVariable" 6 | 7 | exports.myFunction = -> 8 | print "myFunction is running" 9 | 10 | exports.myArray = [1, 2, 3] -------------------------------------------------------------------------------- /Cantor.framer/modules/npm.coffee: -------------------------------------------------------------------------------- 1 | exports.deepEqual = require "deep-equal" 2 | -------------------------------------------------------------------------------- /Cantor.framer/modules/recorder.js: -------------------------------------------------------------------------------- 1 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Recorder = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 2 | return Math.max(min, Math.min(max, value)) 3 | 4 | exports.pointInsideLayer = (layer, point) -> 5 | return layer.x <= point.x && layer.maxX > point.x && layer.y <= point.y && layer.maxY > point.y 6 | 7 | exports.layersIntersect = (layerA, layerB) -> 8 | x = Math.max(layerA.x, layerB.x) 9 | y = Math.max(layerA.y, layerB.y) 10 | maxX = Math.min(layerA.maxX, layerB.maxX) 11 | maxY = Math.min(layerA.maxY, layerB.maxY) 12 | return maxX >= x && maxY >= y 13 | 14 | exports.framesIntersect = (frameA, frameB) -> 15 | x = Math.max(frameA.x, frameB.x) 16 | y = Math.max(frameA.y, frameB.y) 17 | maxX = Math.min(frameA.x + frameA.width, frameB.x + frameB.width) 18 | maxY = Math.min(frameA.y + frameA.height, frameB.y + frameB.height) 19 | return maxX >= x && maxY >= y 20 | -------------------------------------------------------------------------------- /Cantor.framer/node_modules/deep-equal/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.8' 4 | - '0.10' 5 | - '0.12' 6 | - 'iojs' 7 | before_install: 8 | - npm install -g npm@latest 9 | -------------------------------------------------------------------------------- /Cantor.framer/node_modules/deep-equal/LICENSE: -------------------------------------------------------------------------------- 1 | This software is released under the MIT license: 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so, 8 | subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /Cantor.framer/node_modules/deep-equal/example/cmp.js: -------------------------------------------------------------------------------- 1 | var equal = require('../'); 2 | console.dir([ 3 | equal( 4 | { a : [ 2, 3 ], b : [ 4 ] }, 5 | { a : [ 2, 3 ], b : [ 4 ] } 6 | ), 7 | equal( 8 | { x : 5, y : [6] }, 9 | { x : 5, y : 6 } 10 | ) 11 | ]); 12 | -------------------------------------------------------------------------------- /Cantor.framer/node_modules/deep-equal/index.js: -------------------------------------------------------------------------------- 1 | var pSlice = Array.prototype.slice; 2 | var objectKeys = require('./lib/keys.js'); 3 | var isArguments = require('./lib/is_arguments.js'); 4 | 5 | var deepEqual = module.exports = function (actual, expected, opts) { 6 | if (!opts) opts = {}; 7 | // 7.1. All identical values are equivalent, as determined by ===. 8 | if (actual === expected) { 9 | return true; 10 | 11 | } else if (actual instanceof Date && expected instanceof Date) { 12 | return actual.getTime() === expected.getTime(); 13 | 14 | // 7.3. Other pairs that do not both pass typeof value == 'object', 15 | // equivalence is determined by ==. 16 | } else if (!actual || !expected || typeof actual != 'object' && typeof expected != 'object') { 17 | return opts.strict ? actual === expected : actual == expected; 18 | 19 | // 7.4. For all other Object pairs, including Array objects, equivalence is 20 | // determined by having the same number of owned properties (as verified 21 | // with Object.prototype.hasOwnProperty.call), the same set of keys 22 | // (although not necessarily the same order), equivalent values for every 23 | // corresponding key, and an identical 'prototype' property. Note: this 24 | // accounts for both named and indexed properties on Arrays. 25 | } else { 26 | return objEquiv(actual, expected, opts); 27 | } 28 | } 29 | 30 | function isUndefinedOrNull(value) { 31 | return value === null || value === undefined; 32 | } 33 | 34 | function isBuffer (x) { 35 | if (!x || typeof x !== 'object' || typeof x.length !== 'number') return false; 36 | if (typeof x.copy !== 'function' || typeof x.slice !== 'function') { 37 | return false; 38 | } 39 | if (x.length > 0 && typeof x[0] !== 'number') return false; 40 | return true; 41 | } 42 | 43 | function objEquiv(a, b, opts) { 44 | var i, key; 45 | if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) 46 | return false; 47 | // an identical 'prototype' property. 48 | if (a.prototype !== b.prototype) return false; 49 | //~~~I've managed to break Object.keys through screwy arguments passing. 50 | // Converting to array solves the problem. 51 | if (isArguments(a)) { 52 | if (!isArguments(b)) { 53 | return false; 54 | } 55 | a = pSlice.call(a); 56 | b = pSlice.call(b); 57 | return deepEqual(a, b, opts); 58 | } 59 | if (isBuffer(a)) { 60 | if (!isBuffer(b)) { 61 | return false; 62 | } 63 | if (a.length !== b.length) return false; 64 | for (i = 0; i < a.length; i++) { 65 | if (a[i] !== b[i]) return false; 66 | } 67 | return true; 68 | } 69 | try { 70 | var ka = objectKeys(a), 71 | kb = objectKeys(b); 72 | } catch (e) {//happens when one is a string literal and the other isn't 73 | return false; 74 | } 75 | // having the same number of owned properties (keys incorporates 76 | // hasOwnProperty) 77 | if (ka.length != kb.length) 78 | return false; 79 | //the same set of keys (although not necessarily the same order), 80 | ka.sort(); 81 | kb.sort(); 82 | //~~~cheap key test 83 | for (i = ka.length - 1; i >= 0; i--) { 84 | if (ka[i] != kb[i]) 85 | return false; 86 | } 87 | //equivalent values for every corresponding key, and 88 | //~~~possibly expensive deep test 89 | for (i = ka.length - 1; i >= 0; i--) { 90 | key = ka[i]; 91 | if (!deepEqual(a[key], b[key], opts)) return false; 92 | } 93 | return typeof a === typeof b; 94 | } 95 | -------------------------------------------------------------------------------- /Cantor.framer/node_modules/deep-equal/lib/is_arguments.js: -------------------------------------------------------------------------------- 1 | var supportsArgumentsClass = (function(){ 2 | return Object.prototype.toString.call(arguments) 3 | })() == '[object Arguments]'; 4 | 5 | exports = module.exports = supportsArgumentsClass ? supported : unsupported; 6 | 7 | exports.supported = supported; 8 | function supported(object) { 9 | return Object.prototype.toString.call(object) == '[object Arguments]'; 10 | }; 11 | 12 | exports.unsupported = unsupported; 13 | function unsupported(object){ 14 | return object && 15 | typeof object == 'object' && 16 | typeof object.length == 'number' && 17 | Object.prototype.hasOwnProperty.call(object, 'callee') && 18 | !Object.prototype.propertyIsEnumerable.call(object, 'callee') || 19 | false; 20 | }; 21 | -------------------------------------------------------------------------------- /Cantor.framer/node_modules/deep-equal/lib/keys.js: -------------------------------------------------------------------------------- 1 | exports = module.exports = typeof Object.keys === 'function' 2 | ? Object.keys : shim; 3 | 4 | exports.shim = shim; 5 | function shim (obj) { 6 | var keys = []; 7 | for (var key in obj) keys.push(key); 8 | return keys; 9 | } 10 | -------------------------------------------------------------------------------- /Cantor.framer/node_modules/deep-equal/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "_args": [ 3 | [ 4 | "deep-equal", 5 | "/Users/andymatuschak/khan/Prototypes/Cantor/Cantor.framer" 6 | ] 7 | ], 8 | "_from": "deep-equal@latest", 9 | "_id": "deep-equal@1.0.1", 10 | "_inCache": true, 11 | "_installable": true, 12 | "_location": "/deep-equal", 13 | "_nodeVersion": "2.4.0", 14 | "_npmUser": { 15 | "email": "substack@gmail.com", 16 | "name": "substack" 17 | }, 18 | "_npmVersion": "3.2.2", 19 | "_phantomChildren": {}, 20 | "_requested": { 21 | "name": "deep-equal", 22 | "raw": "deep-equal", 23 | "rawSpec": "", 24 | "scope": null, 25 | "spec": "latest", 26 | "type": "tag" 27 | }, 28 | "_requiredBy": [ 29 | "#USER" 30 | ], 31 | "_resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", 32 | "_shasum": "f5d260292b660e084eff4cdbc9f08ad3247448b5", 33 | "_shrinkwrap": null, 34 | "_spec": "deep-equal", 35 | "_where": "/Users/andymatuschak/khan/Prototypes/Cantor/Cantor.framer", 36 | "author": { 37 | "email": "mail@substack.net", 38 | "name": "James Halliday", 39 | "url": "http://substack.net" 40 | }, 41 | "bugs": { 42 | "url": "https://github.com/substack/node-deep-equal/issues" 43 | }, 44 | "dependencies": {}, 45 | "description": "node's assert.deepEqual algorithm", 46 | "devDependencies": { 47 | "tape": "^3.5.0" 48 | }, 49 | "directories": { 50 | "example": "example", 51 | "lib": ".", 52 | "test": "test" 53 | }, 54 | "dist": { 55 | "shasum": "f5d260292b660e084eff4cdbc9f08ad3247448b5", 56 | "tarball": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz" 57 | }, 58 | "gitHead": "59c511f5aeae19e3dd1de054077a789d7302be34", 59 | "homepage": "https://github.com/substack/node-deep-equal#readme", 60 | "keywords": [ 61 | "compare", 62 | "equal", 63 | "equality" 64 | ], 65 | "license": "MIT", 66 | "main": "index.js", 67 | "maintainers": [ 68 | { 69 | "name": "substack", 70 | "email": "mail@substack.net" 71 | } 72 | ], 73 | "name": "deep-equal", 74 | "optionalDependencies": {}, 75 | "readme": "ERROR: No README data found!", 76 | "repository": { 77 | "type": "git", 78 | "url": "git+ssh://git@github.com/substack/node-deep-equal.git" 79 | }, 80 | "scripts": { 81 | "test": "tape test/*.js" 82 | }, 83 | "testling": { 84 | "browsers": { 85 | "chrome": [ 86 | 10, 87 | 22 88 | ], 89 | "ff": [ 90 | 10, 91 | 15, 92 | 3.5 93 | ], 94 | "ie": [ 95 | 6, 96 | 7, 97 | 8, 98 | 9 99 | ], 100 | "opera": [ 101 | 12 102 | ], 103 | "safari": [ 104 | 5.1 105 | ] 106 | }, 107 | "files": "test/*.js" 108 | }, 109 | "version": "1.0.1" 110 | } 111 | -------------------------------------------------------------------------------- /Cantor.framer/node_modules/deep-equal/readme.markdown: -------------------------------------------------------------------------------- 1 | # deep-equal 2 | 3 | Node's `assert.deepEqual() algorithm` as a standalone module. 4 | 5 | This module is around [5 times faster](https://gist.github.com/2790507) 6 | than wrapping `assert.deepEqual()` in a `try/catch`. 7 | 8 | [![browser support](https://ci.testling.com/substack/node-deep-equal.png)](https://ci.testling.com/substack/node-deep-equal) 9 | 10 | [![build status](https://secure.travis-ci.org/substack/node-deep-equal.png)](https://travis-ci.org/substack/node-deep-equal) 11 | 12 | # example 13 | 14 | ``` js 15 | var equal = require('deep-equal'); 16 | console.dir([ 17 | equal( 18 | { a : [ 2, 3 ], b : [ 4 ] }, 19 | { a : [ 2, 3 ], b : [ 4 ] } 20 | ), 21 | equal( 22 | { x : 5, y : [6] }, 23 | { x : 5, y : 6 } 24 | ) 25 | ]); 26 | ``` 27 | 28 | # methods 29 | 30 | ``` js 31 | var deepEqual = require('deep-equal') 32 | ``` 33 | 34 | ## deepEqual(a, b, opts) 35 | 36 | Compare objects `a` and `b`, returning whether they are equal according to a 37 | recursive equality algorithm. 38 | 39 | If `opts.strict` is `true`, use strict equality (`===`) to compare leaf nodes. 40 | The default is to use coercive equality (`==`) because that's how 41 | `assert.deepEqual()` works by default. 42 | 43 | # install 44 | 45 | With [npm](http://npmjs.org) do: 46 | 47 | ``` 48 | npm install deep-equal 49 | ``` 50 | 51 | # test 52 | 53 | With [npm](http://npmjs.org) do: 54 | 55 | ``` 56 | npm test 57 | ``` 58 | 59 | # license 60 | 61 | MIT. Derived largely from node's assert module. 62 | -------------------------------------------------------------------------------- /Cantor.framer/node_modules/deep-equal/test/cmp.js: -------------------------------------------------------------------------------- 1 | var test = require('tape'); 2 | var equal = require('../'); 3 | var isArguments = require('../lib/is_arguments.js'); 4 | var objectKeys = require('../lib/keys.js'); 5 | 6 | test('equal', function (t) { 7 | t.ok(equal( 8 | { a : [ 2, 3 ], b : [ 4 ] }, 9 | { a : [ 2, 3 ], b : [ 4 ] } 10 | )); 11 | t.end(); 12 | }); 13 | 14 | test('not equal', function (t) { 15 | t.notOk(equal( 16 | { x : 5, y : [6] }, 17 | { x : 5, y : 6 } 18 | )); 19 | t.end(); 20 | }); 21 | 22 | test('nested nulls', function (t) { 23 | t.ok(equal([ null, null, null ], [ null, null, null ])); 24 | t.end(); 25 | }); 26 | 27 | test('strict equal', function (t) { 28 | t.notOk(equal( 29 | [ { a: 3 }, { b: 4 } ], 30 | [ { a: '3' }, { b: '4' } ], 31 | { strict: true } 32 | )); 33 | t.end(); 34 | }); 35 | 36 | test('non-objects', function (t) { 37 | t.ok(equal(3, 3)); 38 | t.ok(equal('beep', 'beep')); 39 | t.ok(equal('3', 3)); 40 | t.notOk(equal('3', 3, { strict: true })); 41 | t.notOk(equal('3', [3])); 42 | t.end(); 43 | }); 44 | 45 | test('arguments class', function (t) { 46 | t.ok(equal( 47 | (function(){return arguments})(1,2,3), 48 | (function(){return arguments})(1,2,3), 49 | "compares arguments" 50 | )); 51 | t.notOk(equal( 52 | (function(){return arguments})(1,2,3), 53 | [1,2,3], 54 | "differenciates array and arguments" 55 | )); 56 | t.end(); 57 | }); 58 | 59 | test('test the arguments shim', function (t) { 60 | t.ok(isArguments.supported((function(){return arguments})())); 61 | t.notOk(isArguments.supported([1,2,3])); 62 | 63 | t.ok(isArguments.unsupported((function(){return arguments})())); 64 | t.notOk(isArguments.unsupported([1,2,3])); 65 | 66 | t.end(); 67 | }); 68 | 69 | test('test the keys shim', function (t) { 70 | t.deepEqual(objectKeys.shim({ a: 1, b : 2 }), [ 'a', 'b' ]); 71 | t.end(); 72 | }); 73 | 74 | test('dates', function (t) { 75 | var d0 = new Date(1387585278000); 76 | var d1 = new Date('Fri Dec 20 2013 16:21:18 GMT-0800 (PST)'); 77 | t.ok(equal(d0, d1)); 78 | t.end(); 79 | }); 80 | 81 | test('buffers', function (t) { 82 | t.ok(equal(Buffer('xyz'), Buffer('xyz'))); 83 | t.end(); 84 | }); 85 | 86 | test('booleans and arrays', function (t) { 87 | t.notOk(equal(true, [])); 88 | t.end(); 89 | }) 90 | 91 | test('null == undefined', function (t) { 92 | t.ok(equal(null, undefined)) 93 | t.notOk(equal(null, undefined, { strict: true })) 94 | t.end() 95 | }) 96 | -------------------------------------------------------------------------------- /Cantor.framer/recordings/1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Khan/Cantor/80c65205a83e58160369806471bdf981c3bfa26a/Cantor.framer/recordings/1.wav -------------------------------------------------------------------------------- /Readme.mdown: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | Prototypes around a medium and toolset for exploring quantities and arithmetic operations. 4 | 5 | More notes here to come, but in the meantime: 6 | * [A medium supporting the exploration of quantities](http://klr.tumblr.com/post/147245626988/a-medium-supporting-the-exploration-of-quantities) 7 | * [Old and new ways of looking at number](http://klr.tumblr.com/post/149677916243/old-and-new-ways-of-looking-at-numbers) 8 | 9 | # Recording 10 | 11 | We're interested in Cantor interactions which trade off control between recordings and the student. I expect we'll write about that more extensively eventually, but in the meantime, to record an interactive: 12 | 13 | * **Get Cantor ready for recording** (Chrome tries to protect you but gets in the way!) 14 | * Open the project in Framer. 15 | * Click the "Mirror" toolbar icon, then "Open in Browser". 16 | * Copy that URL, then paste it into Chrome Canary. 17 | * Change the IP address in the address bar (e.g. `10.0.0.15`) to `localhost` and hit Return. 18 | * Press the "R" key once to start a test recording. Give Chrome permission to use your microphone. 19 | * Press "R" again to stop the test recording. You should now be ready to record a talky segment! 20 | * **Record a segment**: 21 | * Press the "R" key to start recording (you'll have to approve mic usage the first time). 22 | * Press the "R" key again when you're done. 23 | * Press the "P" key to play back the last recorded segment. 24 | * Press the "D" key to download the last recorded segment (a `wav` and a `json` file). 25 | * **Arrange segments into an interactive sequence**: 26 | * Put the `wav` and `json` files in `Cantor.framer/recordings`. 27 | * Rename them as `1.json`, `2.json`, etc in the order you'd like them to be sequenced. 28 | * **Play back a sequence**: 29 | * Use the ➡ button to play the next segment in the sequence stored in `recordings`. 30 | * Refresh the browser to start over with the first segment again. 31 | * **Share a sequence**: 32 | * Get the files in `recordings` as you want them. 33 | * Click the "Share" toolbar icon in Framer. 34 | -------------------------------------------------------------------------------- /Sketches/3d layered operation viz.framer/.gitignore: -------------------------------------------------------------------------------- 1 | # Framer Git Ignore 2 | 3 | # General OSX 4 | 5 | .DS_Store 6 | .AppleDouble 7 | .LSOverride 8 | 9 | # Icon must end with two \r 10 | Icon 11 | 12 | 13 | # Thumbnails 14 | ._* 15 | 16 | # Files that might appear in the root of a volume 17 | .DocumentRevisions-V100 18 | .fseventsd 19 | .Spotlight-V100 20 | .TemporaryItems 21 | .Trashes 22 | .VolumeIcon.icns 23 | 24 | # Directories potentially created on remote AFP share 25 | .AppleDB 26 | .AppleDesktop 27 | Network Trash Folder 28 | Temporary Items 29 | .apdisk 30 | 31 | 32 | # Framer Specific 33 | .*.html 34 | framer/*.old* 35 | framer/backup.coffee 36 | framer/backups/* 37 | framer/.*.hash 38 | framer/preview.png 39 | framer/manifest.txt 40 | -------------------------------------------------------------------------------- /Sketches/3d layered operation viz.framer/app.coffee: -------------------------------------------------------------------------------- 1 | # Visualizing 10 - 4 + 7 by separating into several layers on drag. 2 | 3 | kaColors = require "kaColors" 4 | 5 | Screen.backgroundColor = "white" 6 | 7 | blockSize = 50 8 | 9 | root = new Layer 10 | size: Screen.size 11 | backgroundColor: "" 12 | perspective: 100 13 | 14 | blockParent = new Layer 15 | y: 300 16 | width: 500 17 | height: 100 18 | parent: root 19 | backgroundColor: "" 20 | x: 125 21 | 22 | blockParent.draggable.enabled = true 23 | blockParent.draggable.horizontal = false 24 | blockParent.draggable.momentum = false 25 | 26 | makeBlock = -> 27 | new Layer 28 | width: blockSize 29 | parent: blockParent 30 | height: blockSize 31 | backgroundColor: kaColors.math1 32 | borderColor: kaColors.math2 33 | borderWidth: 1 34 | 35 | zSpacing = 3 36 | 37 | first = [] 38 | for i in [0...10] 39 | block = makeBlock() 40 | block.x = i * blockSize 41 | block.y = 0 42 | first.push(block) 43 | 44 | second = [] 45 | for i in [0...4] 46 | block = makeBlock() 47 | block.x = i * blockSize + 6 * blockSize 48 | block.y = 0 49 | block.backgroundColor = "white" 50 | block.style["border"] = "1px dashed gray" 51 | second.push(block) 52 | 53 | third = [] 54 | thirdAux = [] 55 | for i in [0...4] 56 | block = makeBlock() 57 | block.x = i * blockSize + 6 * blockSize 58 | block.y = 0 59 | block.backgroundColor = "rgba(25, 156, 194, 1.0)"; 60 | third.push(block) 61 | 62 | for i in [0...3] 63 | block = makeBlock() 64 | block.x = i * blockSize 65 | block.y = blockSize 66 | block.backgroundColor = "rgba(25, 156, 194, 1.0)"; 67 | third.push(block) 68 | 69 | block = makeBlock() 70 | block.x = i * blockSize 71 | block.y = blockSize 72 | block.opacity = 0 73 | block.backgroundColor = kaColors.cs1 74 | block.borderWidth = 0 75 | thirdAux.push(block) 76 | 77 | 78 | 79 | # state = false 80 | root.onTouchStart -> 81 | for block in second 82 | block.animate 83 | properties: {z: zSpacing} 84 | time: 0.2 85 | for block in third 86 | block.animate 87 | properties: 88 | z: zSpacing * 2 89 | backgroundColor: "rgba(32, 159, 67, 0.8)" 90 | borderColor: "rgba(100, 201, 93, 1.0)" 91 | time: 0.2 92 | for block in thirdAux 93 | block.animate 94 | properties: {opacity: 0.4} 95 | time: 0.2 96 | 97 | 98 | root.onTouchEnd -> 99 | for block in second 100 | block.animate 101 | properties: {z: 0} 102 | time: 0.2 103 | for block in third 104 | block.animate 105 | properties: 106 | z: 0 107 | backgroundColor: kaColors.math1 108 | borderColor: kaColors.math2 109 | time: 0.2 110 | for block in thirdAux 111 | block.animate 112 | properties: {opacity: 0} 113 | time: 0.2 -------------------------------------------------------------------------------- /Sketches/3d layered operation viz.framer/framer/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "propertyPanelToggleStates" : { 3 | "Filters" : false 4 | }, 5 | "deviceOrientation" : 0, 6 | "sharedPrototype" : 0, 7 | "contentScale" : 1, 8 | "deviceType" : "apple-iphone-6s-silver", 9 | "selectedHand" : "", 10 | "updateDelay" : 0.3, 11 | "deviceScale" : "fit", 12 | "foldedCodeRanges" : [ 13 | 14 | ], 15 | "orientation" : 0, 16 | "fullScreen" : false 17 | } -------------------------------------------------------------------------------- /Sketches/3d layered operation viz.framer/framer/framer.generated.js: -------------------------------------------------------------------------------- 1 | // This is autogenerated by Framer 2 | 3 | 4 | if (!window.Framer && window._bridge) {window._bridge('runtime.error', {message:'[framer.js] Framer library missing or corrupt. Select File → Update Framer Library.'})} 5 | if (DeviceComponent) {DeviceComponent.Devices["iphone-6-silver"].deviceImageJP2 = false}; 6 | if (window.Framer) {window.Framer.Defaults.DeviceView = {"deviceScale":"fit","selectedHand":"","deviceType":"apple-iphone-6s-silver","contentScale":1,"orientation":0}; 7 | } 8 | if (window.Framer) {window.Framer.Defaults.DeviceComponent = {"deviceScale":"fit","selectedHand":"","deviceType":"apple-iphone-6s-silver","contentScale":1,"orientation":0}; 9 | } 10 | window.FramerStudioInfo = {"deviceImagesUrl":"\/_server\/resources\/DeviceImages","documentTitle":"3d layered operation viz.framer"}; 11 | 12 | Framer.Device = new Framer.DeviceView(); 13 | Framer.Device.setupContext(); -------------------------------------------------------------------------------- /Sketches/3d layered operation viz.framer/framer/framer.init.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | function isFileLoadingAllowed() { 4 | return (window.location.protocol.indexOf("file") == -1) 5 | } 6 | 7 | function isHomeScreened() { 8 | return ("standalone" in window.navigator) && window.navigator.standalone == true 9 | } 10 | 11 | function isCompatibleBrowser() { 12 | return Utils.isWebKit() 13 | } 14 | 15 | var alertNode; 16 | 17 | function dismissAlert() { 18 | alertNode.parentElement.removeChild(alertNode) 19 | loadProject() 20 | } 21 | 22 | function showAlert(html) { 23 | 24 | alertNode = document.createElement("div") 25 | 26 | alertNode.classList.add("framerAlertBackground") 27 | alertNode.innerHTML = html 28 | 29 | document.addEventListener("DOMContentLoaded", function(event) { 30 | document.body.appendChild(alertNode) 31 | }) 32 | 33 | window.dismissAlert = dismissAlert; 34 | } 35 | 36 | function showBrowserAlert() { 37 | var html = "" 38 | html += "
" 39 | html += "Error: Not A WebKit Browser" 40 | html += "Your browser is not supported.
Please use Safari or Chrome.
" 41 | html += "Try anyway" 42 | html += "
" 43 | 44 | showAlert(html) 45 | } 46 | 47 | function showFileLoadingAlert() { 48 | var html = "" 49 | html += "
" 50 | html += "Error: Local File Restrictions" 51 | html += "Preview this prototype with Framer Mirror or learn more about " 52 | html += "file restrictions.
" 53 | html += "Try anyway" 54 | html += "
" 55 | 56 | showAlert(html) 57 | } 58 | 59 | function showHomeScreenAlert() { 60 | 61 | link = document.createElement("link"); 62 | link.href = "framer/mirror.css" 63 | link.type = "text/css" 64 | link.rel = "stylesheet" 65 | link.media = "screen" 66 | 67 | document.addEventListener("DOMContentLoaded", function(event) { 68 | document.getElementsByTagName("head")[0].appendChild(link) 69 | }) 70 | 71 | var html = "" 72 | html += "
" 73 | html += "
" 74 | html += "

Install Prototype

" 75 | html += "

Tap

, then choose 'Add to Home Screen'

" 76 | html += "
" 77 | html += "
" 78 | 79 | showAlert(html) 80 | } 81 | 82 | function loadProject() { 83 | CoffeeScript.load("app.coffee") 84 | } 85 | 86 | function setDefaultPageTitle() { 87 | // If no title was set we set it to the project folder name so 88 | // you get a nice name on iOS if you bookmark to desktop. 89 | document.addEventListener("DOMContentLoaded", function() { 90 | if (document.title == "") { 91 | if (window.FramerStudioInfo && window.FramerStudioInfo.documentTitle) { 92 | document.title = window.FramerStudioInfo.documentTitle 93 | } else { 94 | document.title = window.location.pathname.replace(/\//g, "") 95 | } 96 | } 97 | }) 98 | } 99 | 100 | function init() { 101 | 102 | if (Utils.isFramerStudio()) { 103 | return 104 | } 105 | 106 | setDefaultPageTitle() 107 | 108 | if (!isCompatibleBrowser()) { 109 | return showBrowserAlert() 110 | } 111 | 112 | if (!isFileLoadingAllowed()) { 113 | return showFileLoadingAlert() 114 | } 115 | 116 | // if (Utils.isMobile() && !isHomeScreened()) { 117 | // return showHomeScreenAlert() 118 | // } 119 | 120 | loadProject() 121 | 122 | } 123 | 124 | init() 125 | 126 | })() 127 | -------------------------------------------------------------------------------- /Sketches/3d layered operation viz.framer/framer/framer.modules.js: -------------------------------------------------------------------------------- 1 | require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Sketches/3d layered operation viz.framer/modules/kaColors.js: -------------------------------------------------------------------------------- 1 | // Khan Academy Color Module 2 | // 3 | // This module is meant to be imported by Framer. To use it in a Framer project: 4 | // kaColors = require "kaColors" 5 | // someLayer.backgroundColor = kaColors.kaGreen 6 | // 7 | // This file is generated by a script. You should not modify it manually. To update this file, rerun generate_framer_color_module.swift. 8 | 9 | exports.alert = "rgba(181, 16, 25, 1.0)"; 10 | exports.kaGreen = "rgba(82, 141, 28, 1.0)"; 11 | exports.kaBlue = "rgba(37, 52, 65, 1.0)"; 12 | exports.mint1 = "rgba(217, 224, 193, 1.0)"; 13 | exports.mint2 = "rgba(233, 240, 215, 1.0)"; 14 | exports.mint3 = "rgba(243, 248, 226, 1.0)"; 15 | exports.black = "rgba(0, 0, 0, 1.0)"; 16 | exports.gray17 = "rgba(25, 27, 33, 1.0)"; 17 | exports.gray25 = "rgba(45, 47, 49, 1.0)"; 18 | exports.gray41 = "rgba(79, 82, 86, 1.0)"; 19 | exports.gray68 = "rgba(117, 122, 129, 1.0)"; 20 | exports.gray76 = "rgba(172, 176, 181, 1.0)"; 21 | exports.gray85 = "rgba(205, 207, 209, 1.0)"; 22 | exports.gray90 = "rgba(220, 223, 224, 1.0)"; 23 | exports.gray95 = "rgba(236, 237, 239, 1.0)"; 24 | exports.gray97 = "rgba(244, 245, 245, 1.0)"; 25 | exports.gray98 = "rgba(249, 249, 249, 1.0)"; 26 | exports.white = "rgba(255, 255, 255, 1.0)"; 27 | exports.math4 = "rgba(13, 67, 83, 1.0)"; 28 | exports.math3 = "rgba(18, 108, 135, 1.0)"; 29 | exports.math1 = "rgba(25, 156, 194, 1.0)"; 30 | exports.math2 = "rgba(85, 209, 229, 1.0)"; 31 | exports.math5 = "rgba(114, 245, 255, 1.0)"; 32 | exports.math6 = "rgba(194, 249, 255, 1.0)"; 33 | exports.partner4 = "rgba(18, 63, 52, 1.0)"; 34 | exports.partner3 = "rgba(29, 111, 93, 1.0)"; 35 | exports.partner1 = "rgba(20, 155, 131, 1.0)"; 36 | exports.partner2 = "rgba(26, 201, 180, 1.0)"; 37 | exports.partner5 = "rgba(43, 236, 203, 1.0)"; 38 | exports.partner6 = "rgba(134, 255, 242, 1.0)"; 39 | exports.cs4 = "rgba(14, 77, 31, 1.0)"; 40 | exports.cs3 = "rgba(22, 131, 48, 1.0)"; 41 | exports.cs1 = "rgba(32, 159, 67, 1.0)"; 42 | exports.cs2 = "rgba(100, 201, 93, 1.0)"; 43 | exports.cs5 = "rgba(124, 244, 110, 1.0)"; 44 | exports.cs6 = "rgba(170, 255, 161, 1.0)"; 45 | exports.economics4 = "rgba(129, 44, 5, 1.0)"; 46 | exports.economics3 = "rgba(149, 71, 9, 1.0)"; 47 | exports.economics1 = "rgba(214, 105, 16, 1.0)"; 48 | exports.economics5 = "rgba(253, 138, 44, 1.0)"; 49 | exports.economics6 = "rgba(253, 173, 94, 1.0)"; 50 | exports.economics7 = "rgba(254, 198, 153, 1.0)"; 51 | exports.economics2 = "rgba(253, 178, 30, 1.0)"; 52 | exports.humanities4 = "rgba(120, 16, 13, 1.0)"; 53 | exports.humanities3 = "rgba(174, 20, 16, 1.0)"; 54 | exports.humanities1 = "rgba(223, 54, 44, 1.0)"; 55 | exports.humanities5 = "rgba(244, 80, 75, 1.0)"; 56 | exports.humanities2 = "rgba(252, 109, 111, 1.0)"; 57 | exports.humanities6 = "rgba(249, 150, 153, 1.0)"; 58 | exports.science4 = "rgba(87, 0, 40, 1.0)"; 59 | exports.science3 = "rgba(138, 0, 61, 1.0)"; 60 | exports.science1 = "rgba(188, 26, 105, 1.0)"; 61 | exports.science5 = "rgba(230, 67, 149, 1.0)"; 62 | exports.science2 = "rgba(252, 122, 186, 1.0)"; 63 | exports.science6 = "rgba(253, 172, 217, 1.0)"; 64 | exports.testprep4 = "rgba(36, 24, 53, 1.0)"; 65 | exports.testprep3 = "rgba(66, 41, 101, 1.0)"; 66 | exports.testprep1 = "rgba(100, 60, 155, 1.0)"; 67 | exports.testprep2 = "rgba(152, 108, 255, 1.0)"; 68 | exports.testprep5 = "rgba(185, 167, 251, 1.0)"; 69 | exports.testprep6 = "rgba(213, 204, 255, 1.0)"; 70 | exports.default4 = "rgba(2, 30, 57, 1.0)"; 71 | exports.default3 = "rgba(5, 51, 105, 1.0)"; 72 | exports.default1 = "rgba(17, 57, 146, 1.0)"; 73 | exports.default6 = "rgba(29, 87, 189, 1.0)"; 74 | exports.default5 = "rgba(48, 123, 222, 1.0)"; 75 | exports.default2 = "rgba(85, 158, 227, 1.0)"; 76 | exports.yellow1 = "rgba(194, 157, 21, 1.0)"; 77 | exports.yellow2 = "rgba(225, 182, 24, 1.0)"; 78 | exports.yellow3 = "rgba(240, 204, 54, 1.0)"; 79 | exports.yellow4 = "rgba(251, 221, 74, 1.0)"; 80 | exports.yellow5 = "rgba(255, 231, 130, 1.0)"; 81 | exports.yellow6 = "rgba(255, 239, 168, 1.0)"; 82 | -------------------------------------------------------------------------------- /Sketches/3d layered operation viz.framer/modules/myModule.coffee: -------------------------------------------------------------------------------- 1 | # Add the following line to your project in Framer Studio. 2 | # myModule = require "myModule" 3 | # Reference the contents by name, like myModule.myFunction() or myModule.myVar 4 | 5 | exports.myVar = "myVariable" 6 | 7 | exports.myFunction = -> 8 | print "myFunction is running" 9 | 10 | exports.myArray = [1, 2, 3] -------------------------------------------------------------------------------- /Sketches/Partitive division with stretching.framer/.gitignore: -------------------------------------------------------------------------------- 1 | # Framer Git Ignore 2 | 3 | # General OSX 4 | 5 | .DS_Store 6 | .AppleDouble 7 | .LSOverride 8 | 9 | # Icon must end with two \r 10 | Icon 11 | 12 | # Thumbnails 13 | ._* 14 | 15 | # Files that might appear in the root of a volume 16 | .DocumentRevisions-V100 17 | .fseventsd 18 | .Spotlight-V100 19 | .TemporaryItems 20 | .Trashes 21 | .VolumeIcon.icns 22 | 23 | # Directories potentially created on remote AFP share 24 | .AppleDB 25 | .AppleDesktop 26 | Network Trash Folder 27 | Temporary Items 28 | .apdisk 29 | 30 | # Framer Specific 31 | .*.html 32 | framer/*.old* 33 | framer/.*.hash 34 | framer/backup.coffee 35 | framer/backups/* 36 | framer/manifest.txt 37 | framer/metadata.json 38 | framer/preview.png 39 | framer/social-880x460.png 40 | framer/social-1200x630.png 41 | -------------------------------------------------------------------------------- /Sketches/Partitive division with stretching.framer/app.coffee: -------------------------------------------------------------------------------- 1 | # Project Info 2 | # This info is presented in a widget when you share. 3 | # http://framerjs.com/docs/#info.info 4 | 5 | Framer.Info = 6 | title: "" 7 | author: "Andy Matuschak" 8 | twitter: "" 9 | description: "" 10 | 11 | 12 | kaColors = require "kaColors" 13 | 14 | Canvas.backgroundColor = "white" 15 | 16 | grid = new Layer 17 | width: Screen.width * 10 18 | height: Screen.height * 10 19 | grid.style["background"] = "url('images/#{"grid.svg"}')" 20 | 21 | createLine = -> 22 | line = new Layer 23 | height: 0 24 | width: 100 25 | originX: 0 26 | originY: 0 27 | 28 | # Use Shadow to create centered line 29 | line.shadowSpread = 1 # line size 30 | line.shadowColor = "#ccc" 31 | return line 32 | 33 | lines = [] 34 | for i in [0..10] 35 | lines.push(createLine()) 36 | 37 | 38 | 39 | size = 40 40 | value = 2 41 | division = 4 42 | 43 | moveLine = (targetLayer, x1, y1, x2, y2) -> 44 | 45 | # Set Position 46 | targetLayer.x = x1 47 | targetLayer.y = y1 48 | 49 | # Set "length" 50 | dist = calcDistance(x1, y1, x2, y2) 51 | targetLayer.width = dist 52 | 53 | # Sorry for bad math 54 | angle = calcAngle(x1, y1, x2, y2) 55 | targetLayer.rotation = -angle-90 56 | 57 | # Math Helper Functions 58 | 59 | calcDistance = (p1x, p1y, p2x, p2y) -> 60 | [a, b] = [p1x - p2x, p1y - p2y] 61 | Math.sqrt Math.pow(a, 2) + Math.pow(b, 2) 62 | 63 | class Point 64 | constructor: (@x, @y) -> 65 | draw: (ctx) -> ctx.fillRect @x, @y, 1, 1 66 | toString: -> "(#{@x}, #{@y})" 67 | 68 | calcAngle = (p1x,p1y,p2x,p2y) -> 69 | angle = Math.atan2(p2x - p1x, p2y - p1y) * 180 / Math.PI + 180 70 | return angle 71 | 72 | block = new Layer 73 | backgroundColor: kaColors.math1 74 | x: 120 75 | y: 120 76 | width: size * value 77 | height: size 78 | opacity: 1.0 79 | block.style["mix-blend-mode"] = "screen" 80 | 81 | highlightBlock = new Layer 82 | backgroundColor: kaColors.math2 83 | x: 120 84 | y: 120 85 | width: size * (value / division) 86 | height: size 87 | opacity: 0.5 88 | highlightBlock.style["mix-blend-mode"] = "screen" 89 | 90 | divisionBlock = new Layer 91 | x: 120 92 | y: 200 93 | width: size * division 94 | height: size 95 | backgroundColor: kaColors.cs1 96 | divisionBlock.style["mix-blend-mode"] = "screen" 97 | 98 | 99 | update = -> 100 | value = block.width / size 101 | division = divisionBlock.width / size 102 | highlightBlock.width = size * (value / division) 103 | 104 | for i in [0...lines.length] 105 | if i < Math.ceil(division) 106 | moveLine(lines[i], divisionBlock.x + size*i + 2, divisionBlock.y, block.x + (value / division) * size * i + 2, block.y + size) 107 | lines[i].visible = true 108 | else if i == Math.ceil(division) 109 | maxX = if division >= 1 110 | maxX = block.maxX 111 | else 112 | maxX = block.x + (value / division) * size 113 | moveLine(lines[i], divisionBlock.x + size*(division), divisionBlock.y, maxX, block.y + size) 114 | lines[i].visible = true 115 | else 116 | lines[i].visible = false 117 | 118 | verticalLine.midX = Math.max(block.maxX, divisionBlock.maxX) 119 | knob.midX = verticalLine.midX 120 | 121 | blockResizeStart = (block) -> 122 | (event) -> block.originalWidth = block.width 123 | 124 | blockResizeUpdate = (block) -> 125 | (event) -> 126 | block.width = Math.max(size, block.originalWidth + Math.round(event.offset.x / size) * size) 127 | update() 128 | 129 | 130 | divisionBlock.onPanStart blockResizeStart(divisionBlock) 131 | divisionBlock.onPan blockResizeUpdate(divisionBlock) 132 | 133 | block.onPanStart blockResizeStart(block) 134 | block.onPan blockResizeUpdate(block) 135 | 136 | verticalLine = new Layer 137 | backgroundColor: kaColors.math2 138 | width: 2 139 | height: size * 3 140 | y: block.y 141 | 142 | knob = new Layer 143 | backgroundColor: kaColors.math2 144 | width: 15 145 | height: 15 146 | borderRadius: "50%" 147 | midY: verticalLine.midY 148 | 149 | grid.onPanStart -> 150 | block.originalWidth = block.width 151 | divisionBlock.originalWidth = divisionBlock.width 152 | grid.onPan (event) -> 153 | knob.x += event.delta.x 154 | verticalLine.midX = knob.midX 155 | biggerBlock = if block.width > divisionBlock.width then block else divisionBlock 156 | smallerBlock = if biggerBlock == block then divisionBlock else block 157 | biggerBlock.width = knob.midX - biggerBlock.x 158 | smallerBlock.width = smallerBlock.originalWidth * biggerBlock.width / biggerBlock.originalWidth 159 | update() 160 | 161 | update() -------------------------------------------------------------------------------- /Sketches/Partitive division with stretching.framer/framer/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "propertyPanelToggleStates" : { 3 | 4 | }, 5 | "deviceOrientation" : 0, 6 | "sharedPrototype" : 0, 7 | "contentScale" : 1, 8 | "deviceType" : "fullscreen", 9 | "selectedHand" : "", 10 | "updateDelay" : 0.3, 11 | "deviceScale" : 1, 12 | "foldedCodeRanges" : [ 13 | "{0, 189}" 14 | ], 15 | "orientation" : 0 16 | } -------------------------------------------------------------------------------- /Sketches/Partitive division with stretching.framer/framer/framer.generated.js: -------------------------------------------------------------------------------- 1 | // This is autogenerated by Framer 2 | 3 | 4 | if (!window.Framer && window._bridge) {window._bridge('runtime.error', {message:'[framer.js] Framer library missing or corrupt. Select File → Update Framer Library.'})} 5 | if (DeviceComponent) {DeviceComponent.Devices["iphone-6-silver"].deviceImageJP2 = false}; 6 | if (window.Framer) {window.Framer.Defaults.DeviceView = {"deviceScale":1,"selectedHand":"","deviceType":"fullscreen","contentScale":1,"orientation":0}; 7 | } 8 | if (window.Framer) {window.Framer.Defaults.DeviceComponent = {"deviceScale":1,"selectedHand":"","deviceType":"fullscreen","contentScale":1,"orientation":0}; 9 | } 10 | window.FramerStudioInfo = {"deviceImagesUrl":"\/_server\/resources\/DeviceImages","documentTitle":"Partitive division with stretching.framer"}; 11 | 12 | Framer.Device = new Framer.DeviceView(); 13 | Framer.Device.setupContext(); -------------------------------------------------------------------------------- /Sketches/Partitive division with stretching.framer/framer/framer.init.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | function isFileLoadingAllowed() { 4 | return (window.location.protocol.indexOf("file") == -1) 5 | } 6 | 7 | function isHomeScreened() { 8 | return ("standalone" in window.navigator) && window.navigator.standalone == true 9 | } 10 | 11 | function isCompatibleBrowser() { 12 | return Utils.isWebKit() 13 | } 14 | 15 | var alertNode; 16 | 17 | function dismissAlert() { 18 | alertNode.parentElement.removeChild(alertNode) 19 | loadProject() 20 | } 21 | 22 | function showAlert(html) { 23 | 24 | alertNode = document.createElement("div") 25 | 26 | alertNode.classList.add("framerAlertBackground") 27 | alertNode.innerHTML = html 28 | 29 | document.addEventListener("DOMContentLoaded", function(event) { 30 | document.body.appendChild(alertNode) 31 | }) 32 | 33 | window.dismissAlert = dismissAlert; 34 | } 35 | 36 | function showBrowserAlert() { 37 | var html = "" 38 | html += "
" 39 | html += "Error: Not A WebKit Browser" 40 | html += "Your browser is not supported.
Please use Safari or Chrome.
" 41 | html += "Try anyway" 42 | html += "
" 43 | 44 | showAlert(html) 45 | } 46 | 47 | function showFileLoadingAlert() { 48 | var html = "" 49 | html += "
" 50 | html += "Error: Local File Restrictions" 51 | html += "Preview this prototype with Framer Mirror or learn more about " 52 | html += "file restrictions.
" 53 | html += "Try anyway" 54 | html += "
" 55 | 56 | showAlert(html) 57 | } 58 | 59 | function loadProject() { 60 | CoffeeScript.load("app.coffee") 61 | } 62 | 63 | function setDefaultPageTitle() { 64 | // If no title was set we set it to the project folder name so 65 | // you get a nice name on iOS if you bookmark to desktop. 66 | document.addEventListener("DOMContentLoaded", function() { 67 | if (document.title == "") { 68 | if (window.FramerStudioInfo && window.FramerStudioInfo.documentTitle) { 69 | document.title = window.FramerStudioInfo.documentTitle 70 | } else { 71 | document.title = window.location.pathname.replace(/\//g, "") 72 | } 73 | } 74 | }) 75 | } 76 | 77 | function init() { 78 | 79 | if (Utils.isFramerStudio()) { 80 | return 81 | } 82 | 83 | setDefaultPageTitle() 84 | 85 | if (!isCompatibleBrowser()) { 86 | return showBrowserAlert() 87 | } 88 | 89 | if (!isFileLoadingAllowed()) { 90 | return showFileLoadingAlert() 91 | } 92 | 93 | loadProject() 94 | 95 | } 96 | 97 | init() 98 | 99 | })() 100 | -------------------------------------------------------------------------------- /Sketches/Partitive division with stretching.framer/framer/framer.modules.js: -------------------------------------------------------------------------------- 1 | require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 2 | 3 | 4 | grid 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Sketches/Partitive division with stretching.framer/images/triangle@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Khan/Cantor/80c65205a83e58160369806471bdf981c3bfa26a/Sketches/Partitive division with stretching.framer/images/triangle@2x.png -------------------------------------------------------------------------------- /Sketches/Partitive division with stretching.framer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Sketches/Partitive division with stretching.framer/modules/kaColors.js: -------------------------------------------------------------------------------- 1 | // Khan Academy Color Module 2 | // 3 | // This module is meant to be imported by Framer. To use it in a Framer project: 4 | // kaColors = require "kaColors" 5 | // someLayer.backgroundColor = kaColors.kaGreen 6 | // 7 | // This file is generated by a script. You should not modify it manually. To update this file, rerun generate_framer_color_module.swift. 8 | 9 | exports.alert = "rgba(181, 16, 25, 1.0)"; 10 | exports.kaGreen = "rgba(82, 141, 28, 1.0)"; 11 | exports.kaBlue = "rgba(37, 52, 65, 1.0)"; 12 | exports.mint1 = "rgba(217, 224, 193, 1.0)"; 13 | exports.mint2 = "rgba(233, 240, 215, 1.0)"; 14 | exports.mint3 = "rgba(243, 248, 226, 1.0)"; 15 | exports.black = "rgba(0, 0, 0, 1.0)"; 16 | exports.gray17 = "rgba(25, 27, 33, 1.0)"; 17 | exports.gray25 = "rgba(45, 47, 49, 1.0)"; 18 | exports.gray41 = "rgba(79, 82, 86, 1.0)"; 19 | exports.gray68 = "rgba(117, 122, 129, 1.0)"; 20 | exports.gray76 = "rgba(172, 176, 181, 1.0)"; 21 | exports.gray85 = "rgba(205, 207, 209, 1.0)"; 22 | exports.gray90 = "rgba(220, 223, 224, 1.0)"; 23 | exports.gray95 = "rgba(236, 237, 239, 1.0)"; 24 | exports.gray97 = "rgba(244, 245, 245, 1.0)"; 25 | exports.gray98 = "rgba(249, 249, 249, 1.0)"; 26 | exports.white = "rgba(255, 255, 255, 1.0)"; 27 | exports.math4 = "rgba(13, 67, 83, 1.0)"; 28 | exports.math3 = "rgba(18, 108, 135, 1.0)"; 29 | exports.math1 = "rgba(25, 156, 194, 1.0)"; 30 | exports.math2 = "rgba(85, 209, 229, 1.0)"; 31 | exports.math5 = "rgba(114, 245, 255, 1.0)"; 32 | exports.math6 = "rgba(194, 249, 255, 1.0)"; 33 | exports.partner4 = "rgba(18, 63, 52, 1.0)"; 34 | exports.partner3 = "rgba(29, 111, 93, 1.0)"; 35 | exports.partner1 = "rgba(20, 155, 131, 1.0)"; 36 | exports.partner2 = "rgba(26, 201, 180, 1.0)"; 37 | exports.partner5 = "rgba(43, 236, 203, 1.0)"; 38 | exports.partner6 = "rgba(134, 255, 242, 1.0)"; 39 | exports.cs4 = "rgba(14, 77, 31, 1.0)"; 40 | exports.cs3 = "rgba(22, 131, 48, 1.0)"; 41 | exports.cs1 = "rgba(32, 159, 67, 1.0)"; 42 | exports.cs2 = "rgba(100, 201, 93, 1.0)"; 43 | exports.cs5 = "rgba(124, 244, 110, 1.0)"; 44 | exports.cs6 = "rgba(170, 255, 161, 1.0)"; 45 | exports.economics4 = "rgba(129, 44, 5, 1.0)"; 46 | exports.economics3 = "rgba(149, 71, 9, 1.0)"; 47 | exports.economics1 = "rgba(214, 105, 16, 1.0)"; 48 | exports.economics5 = "rgba(253, 138, 44, 1.0)"; 49 | exports.economics6 = "rgba(253, 173, 94, 1.0)"; 50 | exports.economics7 = "rgba(254, 198, 153, 1.0)"; 51 | exports.economics2 = "rgba(253, 178, 30, 1.0)"; 52 | exports.humanities4 = "rgba(120, 16, 13, 1.0)"; 53 | exports.humanities3 = "rgba(174, 20, 16, 1.0)"; 54 | exports.humanities1 = "rgba(223, 54, 44, 1.0)"; 55 | exports.humanities5 = "rgba(244, 80, 75, 1.0)"; 56 | exports.humanities2 = "rgba(252, 109, 111, 1.0)"; 57 | exports.humanities6 = "rgba(249, 150, 153, 1.0)"; 58 | exports.science4 = "rgba(87, 0, 40, 1.0)"; 59 | exports.science3 = "rgba(138, 0, 61, 1.0)"; 60 | exports.science1 = "rgba(188, 26, 105, 1.0)"; 61 | exports.science5 = "rgba(230, 67, 149, 1.0)"; 62 | exports.science2 = "rgba(252, 122, 186, 1.0)"; 63 | exports.science6 = "rgba(253, 172, 217, 1.0)"; 64 | exports.testprep4 = "rgba(36, 24, 53, 1.0)"; 65 | exports.testprep3 = "rgba(66, 41, 101, 1.0)"; 66 | exports.testprep1 = "rgba(100, 60, 155, 1.0)"; 67 | exports.testprep2 = "rgba(152, 108, 255, 1.0)"; 68 | exports.testprep5 = "rgba(185, 167, 251, 1.0)"; 69 | exports.testprep6 = "rgba(213, 204, 255, 1.0)"; 70 | exports.default4 = "rgba(2, 30, 57, 1.0)"; 71 | exports.default3 = "rgba(5, 51, 105, 1.0)"; 72 | exports.default1 = "rgba(17, 57, 146, 1.0)"; 73 | exports.default6 = "rgba(29, 87, 189, 1.0)"; 74 | exports.default5 = "rgba(48, 123, 222, 1.0)"; 75 | exports.default2 = "rgba(85, 158, 227, 1.0)"; 76 | exports.yellow1 = "rgba(194, 157, 21, 1.0)"; 77 | exports.yellow2 = "rgba(225, 182, 24, 1.0)"; 78 | exports.yellow3 = "rgba(240, 204, 54, 1.0)"; 79 | exports.yellow4 = "rgba(251, 221, 74, 1.0)"; 80 | exports.yellow5 = "rgba(255, 231, 130, 1.0)"; 81 | exports.yellow6 = "rgba(255, 239, 168, 1.0)"; 82 | -------------------------------------------------------------------------------- /Sketches/Partitive division with stretching.framer/modules/myModule.coffee: -------------------------------------------------------------------------------- 1 | # Add the following line to your project in Framer Studio. 2 | # myModule = require "myModule" 3 | # Reference the contents by name, like myModule.myFunction() or myModule.myVar 4 | 5 | exports.myVar = "myVariable" 6 | 7 | exports.myFunction = -> 8 | print "myFunction is running" 9 | 10 | exports.myArray = [1, 2, 3] -------------------------------------------------------------------------------- /Sketches/Partitive division.framer/.gitignore: -------------------------------------------------------------------------------- 1 | # Framer Git Ignore 2 | 3 | # General OSX 4 | 5 | .DS_Store 6 | .AppleDouble 7 | .LSOverride 8 | 9 | # Icon must end with two \r 10 | Icon 11 | 12 | # Thumbnails 13 | ._* 14 | 15 | # Files that might appear in the root of a volume 16 | .DocumentRevisions-V100 17 | .fseventsd 18 | .Spotlight-V100 19 | .TemporaryItems 20 | .Trashes 21 | .VolumeIcon.icns 22 | 23 | # Directories potentially created on remote AFP share 24 | .AppleDB 25 | .AppleDesktop 26 | Network Trash Folder 27 | Temporary Items 28 | .apdisk 29 | 30 | # Framer Specific 31 | .*.html 32 | framer/*.old* 33 | framer/.*.hash 34 | framer/backup.coffee 35 | framer/backups/* 36 | framer/manifest.txt 37 | framer/metadata.json 38 | framer/preview.png 39 | framer/social-880x460.png 40 | framer/social-1200x630.png 41 | -------------------------------------------------------------------------------- /Sketches/Partitive division.framer/app.coffee: -------------------------------------------------------------------------------- 1 | # Project Info 2 | # This info is presented in a widget when you share. 3 | # http://framerjs.com/docs/#info.info 4 | 5 | Framer.Info = 6 | title: "" 7 | author: "Andy Matuschak" 8 | twitter: "" 9 | description: "" 10 | 11 | 12 | kaColors = require "kaColors" 13 | 14 | grid = new Layer 15 | width: Screen.width * 10 16 | height: Screen.height * 10 17 | grid.style["background"] = "url('images/#{"grid.svg"}')" 18 | 19 | 20 | createLine = -> 21 | line = new Layer 22 | height: 0 23 | width: 100 24 | originX: 0 25 | originY: 0 26 | 27 | # Use Shadow to create centered line 28 | line.shadowSpread = 1 # line size 29 | line.shadowColor = "#ccc" 30 | return line 31 | 32 | lines = [] 33 | for i in [0..10] 34 | line = createLine() 35 | lines.push(line) 36 | line.sendToBack() 37 | 38 | size = 40 39 | value = 8 40 | division = 2 41 | 42 | moveLine = (targetLayer, x1, y1, x2, y2) -> 43 | 44 | # Set Position 45 | targetLayer.x = x1 46 | targetLayer.y = y1 47 | 48 | # Set "length" 49 | dist = calcDistance(x1, y1, x2, y2) 50 | targetLayer.width = dist 51 | 52 | # Sorry for bad math 53 | angle = calcAngle(x1, y1, x2, y2) 54 | targetLayer.rotation = -angle-90 55 | 56 | # Math Helper Functions 57 | 58 | calcDistance = (p1x, p1y, p2x, p2y) -> 59 | [a, b] = [p1x - p2x, p1y - p2y] 60 | Math.sqrt Math.pow(a, 2) + Math.pow(b, 2) 61 | 62 | class Point 63 | constructor: (@x, @y) -> 64 | draw: (ctx) -> ctx.fillRect @x, @y, 1, 1 65 | toString: -> "(#{@x}, #{@y})" 66 | 67 | calcAngle = (p1x,p1y,p2x,p2y) -> 68 | angle = Math.atan2(p2x - p1x, p2y - p1y) * 180 / Math.PI + 180 69 | return angle 70 | 71 | block = new Layer 72 | backgroundColor: kaColors.math1 73 | x: 120 74 | y: 120 75 | width: size * value 76 | height: size 77 | opacity: 1.0 78 | block.style["mix-blend-mode"] = "screen" 79 | 80 | highlightLine = createLine() 81 | highlightLine.shadowColor = kaColors.math2 82 | highlightLine.shadowSpread = 2 83 | 84 | highlightBlock = new Layer 85 | backgroundColor: kaColors.math2 86 | x: 120 87 | y: 120 88 | width: size * (value / division) 89 | height: size 90 | opacity: 0.0 91 | highlightBlock.style["mix-blend-mode"] = "screen" 92 | 93 | divisionBlock = new Layer 94 | x: 120 95 | y: 200 96 | width: size * division 97 | height: size 98 | backgroundColor: kaColors.cs1 99 | divisionBlock.style["mix-blend-mode"] = "screen" 100 | 101 | divisionBlock.onPan (event) => 102 | divisionBlock.width += event.deltaX 103 | division = divisionBlock.width / size 104 | highlightBlock.width = size * (value / division) 105 | 106 | moveLine(highlightLine, block.x + 3, block.y + size, block.x + size*value/division, block.y + size) 107 | 108 | for i in [0...lines.length] 109 | if i < Math.ceil(division) 110 | moveLine(lines[i], divisionBlock.x + size*i + 2, divisionBlock.y + 2, block.x + (value / division) * size * i + 2, block.y + size) 111 | lines[i].visible = true 112 | else if i == Math.ceil(division) 113 | maxX = if division >= 1 114 | maxX = block.maxX 115 | else 116 | maxX = block.x + (value / division) * size 117 | moveLine(lines[i], divisionBlock.x + size*(division) + 2, divisionBlock.y + 2, maxX, block.y + size) 118 | lines[i].visible = true 119 | else 120 | lines[i].visible = false -------------------------------------------------------------------------------- /Sketches/Partitive division.framer/framer/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "propertyPanelToggleStates" : { 3 | 4 | }, 5 | "deviceOrientation" : 0, 6 | "sharedPrototype" : 0, 7 | "contentScale" : 1, 8 | "deviceType" : "fullscreen", 9 | "selectedHand" : "", 10 | "updateDelay" : 0.3, 11 | "deviceScale" : 1, 12 | "foldedCodeRanges" : [ 13 | "{0, 189}" 14 | ], 15 | "orientation" : 0 16 | } -------------------------------------------------------------------------------- /Sketches/Partitive division.framer/framer/framer.generated.js: -------------------------------------------------------------------------------- 1 | // This is autogenerated by Framer 2 | 3 | 4 | if (!window.Framer && window._bridge) {window._bridge('runtime.error', {message:'[framer.js] Framer library missing or corrupt. Select File → Update Framer Library.'})} 5 | if (DeviceComponent) {DeviceComponent.Devices["iphone-6-silver"].deviceImageJP2 = false}; 6 | if (window.Framer) {window.Framer.Defaults.DeviceView = {"deviceScale":1,"selectedHand":"","deviceType":"fullscreen","contentScale":1,"orientation":0}; 7 | } 8 | if (window.Framer) {window.Framer.Defaults.DeviceComponent = {"deviceScale":1,"selectedHand":"","deviceType":"fullscreen","contentScale":1,"orientation":0}; 9 | } 10 | window.FramerStudioInfo = {"deviceImagesUrl":"\/_server\/resources\/DeviceImages","documentTitle":"Partitive division.framer"}; 11 | 12 | Framer.Device = new Framer.DeviceView(); 13 | Framer.Device.setupContext(); -------------------------------------------------------------------------------- /Sketches/Partitive division.framer/framer/framer.init.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | function isFileLoadingAllowed() { 4 | return (window.location.protocol.indexOf("file") == -1) 5 | } 6 | 7 | function isHomeScreened() { 8 | return ("standalone" in window.navigator) && window.navigator.standalone == true 9 | } 10 | 11 | function isCompatibleBrowser() { 12 | return Utils.isWebKit() 13 | } 14 | 15 | var alertNode; 16 | 17 | function dismissAlert() { 18 | alertNode.parentElement.removeChild(alertNode) 19 | loadProject() 20 | } 21 | 22 | function showAlert(html) { 23 | 24 | alertNode = document.createElement("div") 25 | 26 | alertNode.classList.add("framerAlertBackground") 27 | alertNode.innerHTML = html 28 | 29 | document.addEventListener("DOMContentLoaded", function(event) { 30 | document.body.appendChild(alertNode) 31 | }) 32 | 33 | window.dismissAlert = dismissAlert; 34 | } 35 | 36 | function showBrowserAlert() { 37 | var html = "" 38 | html += "
" 39 | html += "Error: Not A WebKit Browser" 40 | html += "Your browser is not supported.
Please use Safari or Chrome.
" 41 | html += "Try anyway" 42 | html += "
" 43 | 44 | showAlert(html) 45 | } 46 | 47 | function showFileLoadingAlert() { 48 | var html = "" 49 | html += "
" 50 | html += "Error: Local File Restrictions" 51 | html += "Preview this prototype with Framer Mirror or learn more about " 52 | html += "file restrictions.
" 53 | html += "Try anyway" 54 | html += "
" 55 | 56 | showAlert(html) 57 | } 58 | 59 | function loadProject() { 60 | CoffeeScript.load("app.coffee") 61 | } 62 | 63 | function setDefaultPageTitle() { 64 | // If no title was set we set it to the project folder name so 65 | // you get a nice name on iOS if you bookmark to desktop. 66 | document.addEventListener("DOMContentLoaded", function() { 67 | if (document.title == "") { 68 | if (window.FramerStudioInfo && window.FramerStudioInfo.documentTitle) { 69 | document.title = window.FramerStudioInfo.documentTitle 70 | } else { 71 | document.title = window.location.pathname.replace(/\//g, "") 72 | } 73 | } 74 | }) 75 | } 76 | 77 | function init() { 78 | 79 | if (Utils.isFramerStudio()) { 80 | return 81 | } 82 | 83 | setDefaultPageTitle() 84 | 85 | if (!isCompatibleBrowser()) { 86 | return showBrowserAlert() 87 | } 88 | 89 | if (!isFileLoadingAllowed()) { 90 | return showFileLoadingAlert() 91 | } 92 | 93 | loadProject() 94 | 95 | } 96 | 97 | init() 98 | 99 | })() 100 | -------------------------------------------------------------------------------- /Sketches/Partitive division.framer/framer/framer.modules.js: -------------------------------------------------------------------------------- 1 | require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 2 | 3 | 4 | grid 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Sketches/Partitive division.framer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Sketches/Partitive division.framer/modules/kaColors.js: -------------------------------------------------------------------------------- 1 | // Khan Academy Color Module 2 | // 3 | // This module is meant to be imported by Framer. To use it in a Framer project: 4 | // kaColors = require "kaColors" 5 | // someLayer.backgroundColor = kaColors.kaGreen 6 | // 7 | // This file is generated by a script. You should not modify it manually. To update this file, rerun generate_framer_color_module.swift. 8 | 9 | exports.alert = "rgba(181, 16, 25, 1.0)"; 10 | exports.kaGreen = "rgba(82, 141, 28, 1.0)"; 11 | exports.kaBlue = "rgba(37, 52, 65, 1.0)"; 12 | exports.mint1 = "rgba(217, 224, 193, 1.0)"; 13 | exports.mint2 = "rgba(233, 240, 215, 1.0)"; 14 | exports.mint3 = "rgba(243, 248, 226, 1.0)"; 15 | exports.black = "rgba(0, 0, 0, 1.0)"; 16 | exports.gray17 = "rgba(25, 27, 33, 1.0)"; 17 | exports.gray25 = "rgba(45, 47, 49, 1.0)"; 18 | exports.gray41 = "rgba(79, 82, 86, 1.0)"; 19 | exports.gray68 = "rgba(117, 122, 129, 1.0)"; 20 | exports.gray76 = "rgba(172, 176, 181, 1.0)"; 21 | exports.gray85 = "rgba(205, 207, 209, 1.0)"; 22 | exports.gray90 = "rgba(220, 223, 224, 1.0)"; 23 | exports.gray95 = "rgba(236, 237, 239, 1.0)"; 24 | exports.gray97 = "rgba(244, 245, 245, 1.0)"; 25 | exports.gray98 = "rgba(249, 249, 249, 1.0)"; 26 | exports.white = "rgba(255, 255, 255, 1.0)"; 27 | exports.math4 = "rgba(13, 67, 83, 1.0)"; 28 | exports.math3 = "rgba(18, 108, 135, 1.0)"; 29 | exports.math1 = "rgba(25, 156, 194, 1.0)"; 30 | exports.math2 = "rgba(85, 209, 229, 1.0)"; 31 | exports.math5 = "rgba(114, 245, 255, 1.0)"; 32 | exports.math6 = "rgba(194, 249, 255, 1.0)"; 33 | exports.partner4 = "rgba(18, 63, 52, 1.0)"; 34 | exports.partner3 = "rgba(29, 111, 93, 1.0)"; 35 | exports.partner1 = "rgba(20, 155, 131, 1.0)"; 36 | exports.partner2 = "rgba(26, 201, 180, 1.0)"; 37 | exports.partner5 = "rgba(43, 236, 203, 1.0)"; 38 | exports.partner6 = "rgba(134, 255, 242, 1.0)"; 39 | exports.cs4 = "rgba(14, 77, 31, 1.0)"; 40 | exports.cs3 = "rgba(22, 131, 48, 1.0)"; 41 | exports.cs1 = "rgba(32, 159, 67, 1.0)"; 42 | exports.cs2 = "rgba(100, 201, 93, 1.0)"; 43 | exports.cs5 = "rgba(124, 244, 110, 1.0)"; 44 | exports.cs6 = "rgba(170, 255, 161, 1.0)"; 45 | exports.economics4 = "rgba(129, 44, 5, 1.0)"; 46 | exports.economics3 = "rgba(149, 71, 9, 1.0)"; 47 | exports.economics1 = "rgba(214, 105, 16, 1.0)"; 48 | exports.economics5 = "rgba(253, 138, 44, 1.0)"; 49 | exports.economics6 = "rgba(253, 173, 94, 1.0)"; 50 | exports.economics7 = "rgba(254, 198, 153, 1.0)"; 51 | exports.economics2 = "rgba(253, 178, 30, 1.0)"; 52 | exports.humanities4 = "rgba(120, 16, 13, 1.0)"; 53 | exports.humanities3 = "rgba(174, 20, 16, 1.0)"; 54 | exports.humanities1 = "rgba(223, 54, 44, 1.0)"; 55 | exports.humanities5 = "rgba(244, 80, 75, 1.0)"; 56 | exports.humanities2 = "rgba(252, 109, 111, 1.0)"; 57 | exports.humanities6 = "rgba(249, 150, 153, 1.0)"; 58 | exports.science4 = "rgba(87, 0, 40, 1.0)"; 59 | exports.science3 = "rgba(138, 0, 61, 1.0)"; 60 | exports.science1 = "rgba(188, 26, 105, 1.0)"; 61 | exports.science5 = "rgba(230, 67, 149, 1.0)"; 62 | exports.science2 = "rgba(252, 122, 186, 1.0)"; 63 | exports.science6 = "rgba(253, 172, 217, 1.0)"; 64 | exports.testprep4 = "rgba(36, 24, 53, 1.0)"; 65 | exports.testprep3 = "rgba(66, 41, 101, 1.0)"; 66 | exports.testprep1 = "rgba(100, 60, 155, 1.0)"; 67 | exports.testprep2 = "rgba(152, 108, 255, 1.0)"; 68 | exports.testprep5 = "rgba(185, 167, 251, 1.0)"; 69 | exports.testprep6 = "rgba(213, 204, 255, 1.0)"; 70 | exports.default4 = "rgba(2, 30, 57, 1.0)"; 71 | exports.default3 = "rgba(5, 51, 105, 1.0)"; 72 | exports.default1 = "rgba(17, 57, 146, 1.0)"; 73 | exports.default6 = "rgba(29, 87, 189, 1.0)"; 74 | exports.default5 = "rgba(48, 123, 222, 1.0)"; 75 | exports.default2 = "rgba(85, 158, 227, 1.0)"; 76 | exports.yellow1 = "rgba(194, 157, 21, 1.0)"; 77 | exports.yellow2 = "rgba(225, 182, 24, 1.0)"; 78 | exports.yellow3 = "rgba(240, 204, 54, 1.0)"; 79 | exports.yellow4 = "rgba(251, 221, 74, 1.0)"; 80 | exports.yellow5 = "rgba(255, 231, 130, 1.0)"; 81 | exports.yellow6 = "rgba(255, 239, 168, 1.0)"; 82 | -------------------------------------------------------------------------------- /Sketches/Partitive division.framer/modules/myModule.coffee: -------------------------------------------------------------------------------- 1 | # Add the following line to your project in Framer Studio. 2 | # myModule = require "myModule" 3 | # Reference the contents by name, like myModule.myFunction() or myModule.myVar 4 | 5 | exports.myVar = "myVariable" 6 | 7 | exports.myFunction = -> 8 | print "myFunction is running" 9 | 10 | exports.myArray = [1, 2, 3] -------------------------------------------------------------------------------- /Sketches/syzygy.framer/.gitignore: -------------------------------------------------------------------------------- 1 | # Framer Git Ignore 2 | 3 | # General OSX 4 | 5 | .DS_Store 6 | .AppleDouble 7 | .LSOverride 8 | 9 | # Icon must end with two \r 10 | Icon 11 | 12 | 13 | # Thumbnails 14 | ._* 15 | 16 | # Files that might appear in the root of a volume 17 | .DocumentRevisions-V100 18 | .fseventsd 19 | .Spotlight-V100 20 | .TemporaryItems 21 | .Trashes 22 | .VolumeIcon.icns 23 | 24 | # Directories potentially created on remote AFP share 25 | .AppleDB 26 | .AppleDesktop 27 | Network Trash Folder 28 | Temporary Items 29 | .apdisk 30 | 31 | 32 | # Framer Specific 33 | .*.html 34 | framer/*.old* 35 | framer/backup.coffee 36 | framer/backups/* 37 | framer/.*.hash 38 | framer/preview.png 39 | framer/manifest.txt 40 | -------------------------------------------------------------------------------- /Sketches/syzygy.framer/app.coffee: -------------------------------------------------------------------------------- 1 | # hacks hacks hacks and vineyards 2 | 3 | kaColors = require "kaColors" 4 | 5 | Screen.backgroundColor = "white" 6 | 7 | blockSize = 50 8 | 9 | root = new Layer 10 | size: Screen.size 11 | backgroundColor: "" 12 | perspective: 400 13 | 14 | blockParent = new Layer 15 | x: 0 16 | y: 1000 17 | width: Screen.width 18 | height: Screen.height * 2 19 | parent: root 20 | backgroundColor: "" 21 | 22 | blockParent.draggable.enabled = true 23 | blockParent.draggable.momentum = false 24 | 25 | makeBlock = -> 26 | new Layer 27 | width: 15 28 | parent: blockParent 29 | height: 100 30 | backgroundColor: kaColors.cs1 31 | borderColor: kaColors.cs2 32 | borderWidth: 1 33 | 34 | xSpacing = 60 35 | zSpacing = 50 36 | numRows = 20 37 | numColumns = 30 38 | 39 | elements = [] 40 | for z in [0...numRows] 41 | for i in [0...numColumns] 42 | element = makeBlock() 43 | elements.push(element) 44 | 45 | layout = -> 46 | c = 0 47 | for z in [0...numRows] 48 | for i in [0...numColumns] 49 | e = elements[c] 50 | e.x = i * xSpacing - (numColumns / 2 * xSpacing) + Screen.width / 2 51 | e.z = z * -zSpacing 52 | c += 1 53 | 54 | root.onPan (event) -> 55 | if event.start.y < 700 56 | xSpacing += event.delta.x * 0.1 57 | zSpacing += event.delta.y * 0.1 58 | layout() 59 | 60 | layout() 61 | 62 | bottomLabel = new Layer 63 | y: Screen.height - 135 64 | width: Screen.width 65 | height: 200 66 | backgroundColor: "" 67 | color: kaColors.gray41 68 | z: -1 69 | bottomLabel.html = "

Drag here to move the camera

" 70 | 71 | topLabel = bottomLabel.copy() 72 | topLabel.y = 50 73 | topLabel.html = "

Drag here to change vineyard spacing

" -------------------------------------------------------------------------------- /Sketches/syzygy.framer/framer/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "propertyPanelToggleStates" : { 3 | "Filters" : false 4 | }, 5 | "deviceOrientation" : 0, 6 | "sharedPrototype" : 1, 7 | "contentScale" : 1, 8 | "deviceType" : "apple-iphone-6s-silver", 9 | "selectedHand" : "", 10 | "updateDelay" : 0.3, 11 | "deviceScale" : "fit", 12 | "foldedCodeRanges" : [ 13 | 14 | ], 15 | "orientation" : 0, 16 | "fullScreen" : false 17 | } -------------------------------------------------------------------------------- /Sketches/syzygy.framer/framer/framer.generated.js: -------------------------------------------------------------------------------- 1 | // This is autogenerated by Framer 2 | 3 | 4 | if (!window.Framer && window._bridge) {window._bridge('runtime.error', {message:'[framer.js] Framer library missing or corrupt. Select File → Update Framer Library.'})} 5 | if (DeviceComponent) {DeviceComponent.Devices["iphone-6-silver"].deviceImageJP2 = false}; 6 | if (window.Framer) {window.Framer.Defaults.DeviceView = {"deviceScale":"fit","selectedHand":"","deviceType":"apple-iphone-6s-silver","contentScale":1,"orientation":0}; 7 | } 8 | if (window.Framer) {window.Framer.Defaults.DeviceComponent = {"deviceScale":"fit","selectedHand":"","deviceType":"apple-iphone-6s-silver","contentScale":1,"orientation":0}; 9 | } 10 | window.FramerStudioInfo = {"deviceImagesUrl":"\/_server\/resources\/DeviceImages","documentTitle":"syzygy.framer"}; 11 | 12 | Framer.Device = new Framer.DeviceView(); 13 | Framer.Device.setupContext(); -------------------------------------------------------------------------------- /Sketches/syzygy.framer/framer/framer.init.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | function isFileLoadingAllowed() { 4 | return (window.location.protocol.indexOf("file") == -1) 5 | } 6 | 7 | function isHomeScreened() { 8 | return ("standalone" in window.navigator) && window.navigator.standalone == true 9 | } 10 | 11 | function isCompatibleBrowser() { 12 | return Utils.isWebKit() 13 | } 14 | 15 | var alertNode; 16 | 17 | function dismissAlert() { 18 | alertNode.parentElement.removeChild(alertNode) 19 | loadProject() 20 | } 21 | 22 | function showAlert(html) { 23 | 24 | alertNode = document.createElement("div") 25 | 26 | alertNode.classList.add("framerAlertBackground") 27 | alertNode.innerHTML = html 28 | 29 | document.addEventListener("DOMContentLoaded", function(event) { 30 | document.body.appendChild(alertNode) 31 | }) 32 | 33 | window.dismissAlert = dismissAlert; 34 | } 35 | 36 | function showBrowserAlert() { 37 | var html = "" 38 | html += "
" 39 | html += "Error: Not A WebKit Browser" 40 | html += "Your browser is not supported.
Please use Safari or Chrome.
" 41 | html += "Try anyway" 42 | html += "
" 43 | 44 | showAlert(html) 45 | } 46 | 47 | function showFileLoadingAlert() { 48 | var html = "" 49 | html += "
" 50 | html += "Error: Local File Restrictions" 51 | html += "Preview this prototype with Framer Mirror or learn more about " 52 | html += "file restrictions.
" 53 | html += "Try anyway" 54 | html += "
" 55 | 56 | showAlert(html) 57 | } 58 | 59 | function showHomeScreenAlert() { 60 | 61 | link = document.createElement("link"); 62 | link.href = "framer/mirror.css" 63 | link.type = "text/css" 64 | link.rel = "stylesheet" 65 | link.media = "screen" 66 | 67 | document.addEventListener("DOMContentLoaded", function(event) { 68 | document.getElementsByTagName("head")[0].appendChild(link) 69 | }) 70 | 71 | var html = "" 72 | html += "
" 73 | html += "
" 74 | html += "

Install Prototype

" 75 | html += "

Tap

, then choose 'Add to Home Screen'

" 76 | html += "
" 77 | html += "
" 78 | 79 | showAlert(html) 80 | } 81 | 82 | function loadProject() { 83 | CoffeeScript.load("app.coffee") 84 | } 85 | 86 | function setDefaultPageTitle() { 87 | // If no title was set we set it to the project folder name so 88 | // you get a nice name on iOS if you bookmark to desktop. 89 | document.addEventListener("DOMContentLoaded", function() { 90 | if (document.title == "") { 91 | if (window.FramerStudioInfo && window.FramerStudioInfo.documentTitle) { 92 | document.title = window.FramerStudioInfo.documentTitle 93 | } else { 94 | document.title = window.location.pathname.replace(/\//g, "") 95 | } 96 | } 97 | }) 98 | } 99 | 100 | function init() { 101 | 102 | if (Utils.isFramerStudio()) { 103 | return 104 | } 105 | 106 | setDefaultPageTitle() 107 | 108 | if (!isCompatibleBrowser()) { 109 | return showBrowserAlert() 110 | } 111 | 112 | if (!isFileLoadingAllowed()) { 113 | return showFileLoadingAlert() 114 | } 115 | 116 | // if (Utils.isMobile() && !isHomeScreened()) { 117 | // return showHomeScreenAlert() 118 | // } 119 | 120 | loadProject() 121 | 122 | } 123 | 124 | init() 125 | 126 | })() 127 | -------------------------------------------------------------------------------- /Sketches/syzygy.framer/framer/framer.modules.js: -------------------------------------------------------------------------------- 1 | require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Sketches/syzygy.framer/modules/kaColors.js: -------------------------------------------------------------------------------- 1 | // Khan Academy Color Module 2 | // 3 | // This module is meant to be imported by Framer. To use it in a Framer project: 4 | // kaColors = require "kaColors" 5 | // someLayer.backgroundColor = kaColors.kaGreen 6 | // 7 | // This file is generated by a script. You should not modify it manually. To update this file, rerun generate_framer_color_module.swift. 8 | 9 | exports.alert = "rgba(181, 16, 25, 1.0)"; 10 | exports.kaGreen = "rgba(82, 141, 28, 1.0)"; 11 | exports.kaBlue = "rgba(37, 52, 65, 1.0)"; 12 | exports.mint1 = "rgba(217, 224, 193, 1.0)"; 13 | exports.mint2 = "rgba(233, 240, 215, 1.0)"; 14 | exports.mint3 = "rgba(243, 248, 226, 1.0)"; 15 | exports.black = "rgba(0, 0, 0, 1.0)"; 16 | exports.gray17 = "rgba(25, 27, 33, 1.0)"; 17 | exports.gray25 = "rgba(45, 47, 49, 1.0)"; 18 | exports.gray41 = "rgba(79, 82, 86, 1.0)"; 19 | exports.gray68 = "rgba(117, 122, 129, 1.0)"; 20 | exports.gray76 = "rgba(172, 176, 181, 1.0)"; 21 | exports.gray85 = "rgba(205, 207, 209, 1.0)"; 22 | exports.gray90 = "rgba(220, 223, 224, 1.0)"; 23 | exports.gray95 = "rgba(236, 237, 239, 1.0)"; 24 | exports.gray97 = "rgba(244, 245, 245, 1.0)"; 25 | exports.gray98 = "rgba(249, 249, 249, 1.0)"; 26 | exports.white = "rgba(255, 255, 255, 1.0)"; 27 | exports.math4 = "rgba(13, 67, 83, 1.0)"; 28 | exports.math3 = "rgba(18, 108, 135, 1.0)"; 29 | exports.math1 = "rgba(25, 156, 194, 1.0)"; 30 | exports.math2 = "rgba(85, 209, 229, 1.0)"; 31 | exports.math5 = "rgba(114, 245, 255, 1.0)"; 32 | exports.math6 = "rgba(194, 249, 255, 1.0)"; 33 | exports.partner4 = "rgba(18, 63, 52, 1.0)"; 34 | exports.partner3 = "rgba(29, 111, 93, 1.0)"; 35 | exports.partner1 = "rgba(20, 155, 131, 1.0)"; 36 | exports.partner2 = "rgba(26, 201, 180, 1.0)"; 37 | exports.partner5 = "rgba(43, 236, 203, 1.0)"; 38 | exports.partner6 = "rgba(134, 255, 242, 1.0)"; 39 | exports.cs4 = "rgba(14, 77, 31, 1.0)"; 40 | exports.cs3 = "rgba(22, 131, 48, 1.0)"; 41 | exports.cs1 = "rgba(32, 159, 67, 1.0)"; 42 | exports.cs2 = "rgba(100, 201, 93, 1.0)"; 43 | exports.cs5 = "rgba(124, 244, 110, 1.0)"; 44 | exports.cs6 = "rgba(170, 255, 161, 1.0)"; 45 | exports.economics4 = "rgba(129, 44, 5, 1.0)"; 46 | exports.economics3 = "rgba(149, 71, 9, 1.0)"; 47 | exports.economics1 = "rgba(214, 105, 16, 1.0)"; 48 | exports.economics5 = "rgba(253, 138, 44, 1.0)"; 49 | exports.economics6 = "rgba(253, 173, 94, 1.0)"; 50 | exports.economics7 = "rgba(254, 198, 153, 1.0)"; 51 | exports.economics2 = "rgba(253, 178, 30, 1.0)"; 52 | exports.humanities4 = "rgba(120, 16, 13, 1.0)"; 53 | exports.humanities3 = "rgba(174, 20, 16, 1.0)"; 54 | exports.humanities1 = "rgba(223, 54, 44, 1.0)"; 55 | exports.humanities5 = "rgba(244, 80, 75, 1.0)"; 56 | exports.humanities2 = "rgba(252, 109, 111, 1.0)"; 57 | exports.humanities6 = "rgba(249, 150, 153, 1.0)"; 58 | exports.science4 = "rgba(87, 0, 40, 1.0)"; 59 | exports.science3 = "rgba(138, 0, 61, 1.0)"; 60 | exports.science1 = "rgba(188, 26, 105, 1.0)"; 61 | exports.science5 = "rgba(230, 67, 149, 1.0)"; 62 | exports.science2 = "rgba(252, 122, 186, 1.0)"; 63 | exports.science6 = "rgba(253, 172, 217, 1.0)"; 64 | exports.testprep4 = "rgba(36, 24, 53, 1.0)"; 65 | exports.testprep3 = "rgba(66, 41, 101, 1.0)"; 66 | exports.testprep1 = "rgba(100, 60, 155, 1.0)"; 67 | exports.testprep2 = "rgba(152, 108, 255, 1.0)"; 68 | exports.testprep5 = "rgba(185, 167, 251, 1.0)"; 69 | exports.testprep6 = "rgba(213, 204, 255, 1.0)"; 70 | exports.default4 = "rgba(2, 30, 57, 1.0)"; 71 | exports.default3 = "rgba(5, 51, 105, 1.0)"; 72 | exports.default1 = "rgba(17, 57, 146, 1.0)"; 73 | exports.default6 = "rgba(29, 87, 189, 1.0)"; 74 | exports.default5 = "rgba(48, 123, 222, 1.0)"; 75 | exports.default2 = "rgba(85, 158, 227, 1.0)"; 76 | exports.yellow1 = "rgba(194, 157, 21, 1.0)"; 77 | exports.yellow2 = "rgba(225, 182, 24, 1.0)"; 78 | exports.yellow3 = "rgba(240, 204, 54, 1.0)"; 79 | exports.yellow4 = "rgba(251, 221, 74, 1.0)"; 80 | exports.yellow5 = "rgba(255, 231, 130, 1.0)"; 81 | exports.yellow6 = "rgba(255, 239, 168, 1.0)"; 82 | -------------------------------------------------------------------------------- /Sketches/syzygy.framer/modules/myModule.coffee: -------------------------------------------------------------------------------- 1 | # Add the following line to your project in Framer Studio. 2 | # myModule = require "myModule" 3 | # Reference the contents by name, like myModule.myFunction() or myModule.myVar 4 | 5 | exports.myVar = "myVariable" 6 | 7 | exports.myFunction = -> 8 | print "myFunction is running" 9 | 10 | exports.myArray = [1, 2, 3] --------------------------------------------------------------------------------