Last active
December 14, 2021 12:49
-
-
Save elliottkember/b1d4614f120afc5ef82f to your computer and use it in GitHub Desktop.
Layer browser for imported Sketch / PSD files in Framer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class LayerBrowser | |
constructor: (options) -> | |
@objects = [] | |
@restore = options.restore | |
@_setup() | |
@add options.import if options.import | |
add: (object) -> | |
@objects.push object | |
for layerName in Object.keys(object) | |
layer = object[layerName] | |
if @restore | |
if localStorage[layerName] | |
layer.visible = localStorage[layerName] != "hidden" | |
layer.on "change:visible", -> | |
localStorage[layerName] = if layer.visible then "visible" else "hidden" | |
@_draw() | |
_setup: -> | |
@layer = new Layer x: 20, y: 20, width: 250, height: 20, opacity: 0.95 | |
@layer.draggable.enabled = true | |
@layer.style = | |
backgroundColor: '#999' | |
"border": "1px solid rgba(86, 86, 86, 0.87)" | |
"-webkit-border-radius": "6px" | |
"-moz-box-shadow": "0 2px 7px rgba(0, 0, 0, 0.81)" | |
"box-shadow": "0 2px 7px rgba(0, 0, 0, 0.81)" | |
"border-bottom": "1px solid rgba(66, 66, 66, 0.87)" | |
"border-top": "none" | |
"cursor": "default" | |
"max-height": "400px" | |
@header = new Layer x: 0, y: 0, width: @layer.width, height: 20, superLayer: @layer | |
@header.style = | |
"box-shadow": "none" | |
"font": '11px/15px "Lucida Grande"' | |
"border-top": "1px solid rgba(151, 151, 151, 0.92)" | |
"height": "20px" | |
"-webkit-border-top-left-radius": "6px" | |
"-webkit-border-bottom-left-radius": "0px" | |
"-webkit-border-bottom-right-radius": "0px" | |
"background-image": "-webkit-gradient(linear, left top, left bottom, from(rgba(108, 108, 108, 0.9)), color-stop(0.5, rgba(87, 87, 87, 0.88)), color-stop(0.5, rgba(75, 75, 75, 0.86)), to(rgba(75, 75, 75, 0.86)))" | |
@close = new Layer x: 4, y: 2, width: 13, height: 13, superLayer: @header, backgroundColor: 'transparent' | |
@close.style = | |
"textAlign": 'center' | |
"borderRadius": '10px' | |
"opacity": 1 | |
"width": "13px" | |
"height": "13px" | |
"background-image": "url(layerbrowser/z_close.png)" | |
"display": "block" | |
"position": "absolute" | |
"margin-top": "1px" | |
"-webkit-transition-duration": "0.1s" | |
"-webkit-transition-property": "opacity" | |
"cursor": "pointer" | |
@close.on Events.Click, => | |
if @layer.height == 20 | |
@_draw() | |
@close.animate time: 0.1, properties: rotationZ: 0 | |
else | |
@close.animate time: 0.1, properties: rotationZ: -45 | |
@layer.height = 20 | |
@contentLayer = new Layer superLayer: @layer, y: 20, height: 150, width: @layer.width | |
@contentLayer.style = | |
"width": "100%" | |
"height": "100%" | |
"max-height": "380px" | |
"overflow": "scroll" | |
"position": "relative" | |
"overflow-y": "auto" | |
"pointer-events": "auto" | |
"-webkit-border-radius": "0 0 6px 6px" | |
@contentLayer.on Events.TouchStart, (e) => | |
e.stopPropagation() | |
@_reset() | |
_reset: -> | |
@contentLayer._element.innerHTML = "" | |
_draw: -> | |
@_reset() | |
@lines = [] | |
indent = 0 | |
for object in @objects | |
for key in Object.keys object | |
layer = object[key] | |
if !layer.superLayer | |
@_drawLayer layer | |
_line: (layer, lineHeight, lineNumber, indent) -> | |
line = new Layer | |
x: 0, | |
y: lineNumber * lineHeight | |
width: @layer.width, | |
height: lineHeight | |
backgroundColor: 'transparent' | |
line.style = | |
"fontSize": "12px" | |
"borderBottom": "1px solid rgba(255, 255, 255, 0.1)" | |
"paddingTop": "4px" | |
"paddingLeft": 10 * indent + 10 + "px" | |
"backgroundColor": 'rgba(79, 79, 79, 0.87)' | |
"font": 'normal 11px/18px "Lucida Grande"' | |
"color": 'rgba(255, 255, 255, 0.85)' | |
"border-left": "1px solid rgba(255, 255, 255, 0.12)" | |
"border-right": "1px solid rgba(255, 255, 255, 0.12)" | |
"-webkit-transition-duration": "0.07s" | |
"-webkit-transition-property": "background" | |
html = "" | |
html += " " for [0...indent] | |
line.html = html | |
if !layer.visible | |
line.backgroundColor = 'rgba(100, 100, 100, 0.87)' | |
if layer.subLayers.length > 0 | |
line.html += "▶ " | |
else | |
line.backgroundColor = 'rgba(79, 79, 79, 0.87)' | |
if layer.subLayers.length > 0 | |
line.html += "▼ " | |
line.html += "#{layer.name}" | |
originalBackground = line.backgroundColor | |
layer.on Events.MouseOver, => line.backgroundColor = 'rgba(79, 79, 79, 0.1)' | |
layer.on Events.MouseOut, => line.backgroundColor = originalBackground | |
line.on Events.MouseOver, => layer.style['outline'] = '1px solid red' | |
line.on Events.MouseOut, => layer.style['outline'] = 'none' | |
selectHTML = (states, selectedState) -> | |
select = "<select>" | |
for state in states | |
select += "<option #{'selected' if state == selectedState}>#{state}</option>" | |
select += "</select>" | |
if Object.keys(layer.states._states).length > 1 | |
selectLayer = new Layer | |
superLayer: line | |
maxX: line.width - 10 | |
y: -line.height + 5 | |
height: line.height | |
backgroundColor: 'transparent' | |
selectLayer.html = selectHTML(Object.keys(layer.states._states), layer.states.current) | |
layer.states.on Events.StateDidSwitch, (oldState, newState) => | |
selectLayer.html = selectHTML(Object.keys(layer.states._states), newState) | |
# Change the layer's state when the input changes | |
selectLayer.on "change", (e) => layer.states.switch e.target.value | |
# Don't let this propagate up and show/hide the layer | |
selectLayer.on Events.Click, (e) => e.stopPropagation() | |
line.on Events.Click, => | |
layer.visible = !layer.visible | |
localStorage[layer.name] = (if layer.visible then "visible" else "hidden") | |
# This used to toggle all sublayers when restoring a layer. I don't know whether I like this so much. Hiding a layer should hide its sublayers anyway. | |
# for layer in layer.subLayers | |
# localStorage[layer.name] = "visible" if @restore | |
# layer.visible = true | |
@_draw() | |
line | |
_drawLayer: (layer, indent=0) -> | |
lineHeight = 24 | |
line = @_line layer, lineHeight, @lines.length, indent | |
# We have an array of these for telling what the legend's height should be | |
@lines.push line | |
# Add the line to the legend! | |
@contentLayer.addSubLayer(line) | |
# Make sure the legend is the right height! | |
@layer.height = @lines.length * line.height + 20 | |
@contentLayer.height = @lines.length * line.height + 20 | |
# Print all visible sublayers' lines if this layer is visible. | |
if layer.subLayers && layer.visible | |
for subLayer in layer.subLayers | |
@_drawLayer(subLayer, indent + 1) | |
exports = window if typeof exports == 'undefined' | |
exports.LayerBrowser = LayerBrowser |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Import the script | |
eval CoffeeScript.compile "layerbrowser.coffee" | |
# Load some layers | |
layers = Framer.Importer.load "imported/my-sketch-file" | |
# create a browser! | |
layerBrowser = new LayerBrowser restore: true, import: layers |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment