├── .DS_Store
├── README.md
├── framer-md-app.framer
├── ..social.html.icloud
├── ..viewer.html.icloud
├── .app.coffee.icloud
├── .gitignore
├── .gitignore 2
├── .index.html.icloud
├── framer
│ ├── ..framer.modules.js.hash.icloud
│ ├── .bookmark
│ ├── .bookmark 2
│ ├── .config.json.icloud
│ ├── .design.vekter.icloud
│ ├── .framer.js.map.icloud
│ ├── .manifest.txt.icloud
│ ├── .preview.png.icloud
│ ├── .social-800x600.png.icloud
│ ├── .social-80x80.png.icloud
│ ├── .social-880x460.png.icloud
│ ├── .style.css.icloud
│ ├── coffee-script.js
│ ├── config 2.json
│ ├── design 2.vekter
│ ├── framer 2.js
│ ├── framer.generated.js
│ ├── framer.init.js
│ ├── framer.js
│ ├── framer.modules.js
│ ├── framer.vekter.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
│ └── version
├── images
│ ├── .gitkeep
│ └── .gitkeep 2
└── modules
│ ├── fmd.sublime-workspace
│ ├── md-components
│ ├── ActionButton.coffee
│ ├── App.coffee
│ ├── BottomNav.coffee
│ ├── Button.coffee
│ ├── Card.coffee
│ ├── Checkbox.coffee
│ ├── Dialog.coffee
│ ├── Divider.coffee
│ ├── Dropdown.coffee
│ ├── Elevation.coffee
│ ├── GridList.coffee
│ ├── Header.coffee
│ ├── Icon.coffee
│ ├── Menu.coffee
│ ├── MenuButton.coffee
│ ├── MenuOverlay.coffee
│ ├── Notification.coffee
│ ├── Page.coffee
│ ├── Radiobox.coffee
│ ├── Ripple.coffee
│ ├── RowItem.coffee
│ ├── Select.coffee
│ ├── Slider.coffee
│ ├── Snackbar.coffee
│ ├── StackView.coffee
│ ├── StatusBar.coffee
│ ├── Switch.coffee
│ ├── Table.coffee
│ ├── TableCard.coffee
│ ├── TextArea.coffee
│ ├── TextField.coffee
│ ├── Theme.coffee
│ ├── Tile.coffee
│ ├── Toast.coffee
│ ├── Type.coffee
│ └── View.coffee
│ ├── md-fonts
│ ├── Apache License.txt
│ ├── Roboto-Black.ttf
│ ├── Roboto-BlackItalic.ttf
│ ├── Roboto-Bold.ttf
│ ├── Roboto-BoldItalic.ttf
│ ├── Roboto-Italic.ttf
│ ├── Roboto-Light.ttf
│ ├── Roboto-LightItalic.ttf
│ ├── Roboto-Medium.ttf
│ ├── Roboto-MediumItalic.ttf
│ ├── Roboto-Regular.ttf
│ ├── Roboto-Thin.ttf
│ └── Roboto-ThinItalic.ttf
│ ├── md-images
│ ├── Group.svg
│ ├── keyboard.png
│ ├── nav_bar.png
│ ├── status_bar.png
│ └── status_bar.svg
│ └── md.coffee
└── framer-md-dev.framer
├── ..social.html.icloud
├── ..viewer 2.html.icloud
├── .gitignore
├── app.coffee
├── framer
├── .bookmark
├── coffee-script.js
├── config.json
├── design.vekter
├── framer.generated.js
├── framer.init.js
├── framer.js
├── framer.js.map
├── framer.modules.js
├── framer.vekter.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
├── index.html
└── modules
├── fmd.sublime-workspace
├── md-components
├── ActionButton.coffee
├── App.coffee
├── BottomNav.coffee
├── Button.coffee
├── Card.coffee
├── Checkbox.coffee
├── Dialog.coffee
├── Divider.coffee
├── Dropdown.coffee
├── Elevation.coffee
├── GridList.coffee
├── Header.coffee
├── Icon.coffee
├── Menu.coffee
├── MenuButton.coffee
├── MenuOverlay.coffee
├── Notification.coffee
├── Page.coffee
├── Radiobox.coffee
├── Ripple.coffee
├── RowItem.coffee
├── Select.coffee
├── Slider.coffee
├── Snackbar.coffee
├── StackView.coffee
├── StatusBar.coffee
├── Switch.coffee
├── Table.coffee
├── TableCard.coffee
├── TextArea.coffee
├── TextField.coffee
├── Theme.coffee
├── Tile.coffee
├── Toast.coffee
├── Type.coffee
└── View.coffee
├── md-fonts
├── Apache License.txt
├── Roboto-Black.ttf
├── Roboto-BlackItalic.ttf
├── Roboto-Bold.ttf
├── Roboto-BoldItalic.ttf
├── Roboto-Italic.ttf
├── Roboto-Light.ttf
├── Roboto-LightItalic.ttf
├── Roboto-Medium.ttf
├── Roboto-MediumItalic.ttf
├── Roboto-Regular.ttf
├── Roboto-Thin.ttf
└── Roboto-ThinItalic.ttf
├── md-images
├── Group.svg
├── keyboard.png
├── nav_bar.png
├── status_bar.png
└── status_bar.svg
└── md.coffee
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/.DS_Store
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # framer-md
2 | A Material Design UI kit for Framer.
3 |
--------------------------------------------------------------------------------
/framer-md-app.framer/..social.html.icloud:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/..social.html.icloud
--------------------------------------------------------------------------------
/framer-md-app.framer/..viewer.html.icloud:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/..viewer.html.icloud
--------------------------------------------------------------------------------
/framer-md-app.framer/.app.coffee.icloud:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/.app.coffee.icloud
--------------------------------------------------------------------------------
/framer-md-app.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 | .app.js
33 | framer/*.old*
34 | framer/.*.hash
35 | framer/backup.coffee
36 | framer/backups/*
37 | framer/manifest.txt
38 | framer/preview.png
39 | framer/social-*x*.png
40 |
--------------------------------------------------------------------------------
/framer-md-app.framer/.gitignore 2:
--------------------------------------------------------------------------------
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 | .app.js
33 | framer/*.old*
34 | framer/.*.hash
35 | framer/backup.coffee
36 | framer/backups/*
37 | framer/manifest.txt
38 | framer/preview.png
39 | framer/social-*x*.png
40 |
--------------------------------------------------------------------------------
/framer-md-app.framer/.index.html.icloud:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/.index.html.icloud
--------------------------------------------------------------------------------
/framer-md-app.framer/framer/..framer.modules.js.hash.icloud:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/framer/..framer.modules.js.hash.icloud
--------------------------------------------------------------------------------
/framer-md-app.framer/framer/.bookmark:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/framer/.bookmark
--------------------------------------------------------------------------------
/framer-md-app.framer/framer/.bookmark 2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/framer/.bookmark 2
--------------------------------------------------------------------------------
/framer-md-app.framer/framer/.config.json.icloud:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/framer/.config.json.icloud
--------------------------------------------------------------------------------
/framer-md-app.framer/framer/.design.vekter.icloud:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/framer/.design.vekter.icloud
--------------------------------------------------------------------------------
/framer-md-app.framer/framer/.framer.js.map.icloud:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/framer/.framer.js.map.icloud
--------------------------------------------------------------------------------
/framer-md-app.framer/framer/.manifest.txt.icloud:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/framer/.manifest.txt.icloud
--------------------------------------------------------------------------------
/framer-md-app.framer/framer/.preview.png.icloud:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/framer/.preview.png.icloud
--------------------------------------------------------------------------------
/framer-md-app.framer/framer/.social-800x600.png.icloud:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/framer/.social-800x600.png.icloud
--------------------------------------------------------------------------------
/framer-md-app.framer/framer/.social-80x80.png.icloud:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/framer/.social-80x80.png.icloud
--------------------------------------------------------------------------------
/framer-md-app.framer/framer/.social-880x460.png.icloud:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/framer/.social-880x460.png.icloud
--------------------------------------------------------------------------------
/framer-md-app.framer/framer/.style.css.icloud:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/framer/.style.css.icloud
--------------------------------------------------------------------------------
/framer-md-app.framer/framer/config 2.json:
--------------------------------------------------------------------------------
1 | {
2 | "orientation" : 0,
3 | "updateDelay" : 0,
4 | "designModeSelected" : 0,
5 | "cachedDeviceHeight" : 640,
6 | "contentScale" : 1,
7 | "cachedDeviceWidth" : 360,
8 | "fullScreen" : false,
9 | "deviceType" : "google-nexus-5x",
10 | "sharedPrototype" : true,
11 | "propertyPanelToggleStates" : {
12 |
13 | },
14 | "projectId" : "161AFC90-3E15-49FB-B518-BF8A8B6C4D4E",
15 | "deviceOrientation" : 0,
16 | "selectedHand" : "",
17 | "showBezel" : false,
18 | "foldedCodeRanges" : [
19 | "{181, 1369}",
20 | "{1599, 795}",
21 | "{2395, 2771}"
22 | ],
23 | "deviceScale" : "fit"
24 | }
--------------------------------------------------------------------------------
/framer-md-app.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":"google-nexus-5x","contentScale":1,"hideBezel":true,"orientation":0};
7 | }
8 | if (window.Framer) {window.Framer.Defaults.DeviceComponent = {"deviceScale":"fit","selectedHand":"","deviceType":"google-nexus-5x","contentScale":1,"hideBezel":true,"orientation":0};
9 | }
10 | window.FramerStudioInfo = {"deviceImagesUrl":"\/_server\/resources\/DeviceImages","documentTitle":"framer-md-app.framer"};
11 |
12 | Framer.Device = new Framer.DeviceView();
13 | Framer.Device.setupContext();
--------------------------------------------------------------------------------
/framer-md-app.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(callback) {
60 | CoffeeScript.load("app.coffee", callback)
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(function(){
94 | // CoffeeScript: Framer?.CurrentContext?.emit?("loaded:project")
95 | var context;
96 | if (typeof Framer !== "undefined" && Framer !== null) {
97 | if ((context = Framer.CurrentContext) != null) {
98 | if (typeof context.emit === "function") {
99 | context.emit("loaded:project");
100 | }
101 | }
102 | }
103 | })
104 | }
105 |
106 | init()
107 |
108 | })()
109 |
--------------------------------------------------------------------------------
/framer-md-app.framer/framer/images/cursor-active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/framer/images/cursor-active.png
--------------------------------------------------------------------------------
/framer-md-app.framer/framer/images/cursor-active@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/framer/images/cursor-active@2x.png
--------------------------------------------------------------------------------
/framer-md-app.framer/framer/images/cursor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/framer/images/cursor.png
--------------------------------------------------------------------------------
/framer-md-app.framer/framer/images/cursor@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/framer/images/cursor@2x.png
--------------------------------------------------------------------------------
/framer-md-app.framer/framer/images/icon-120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/framer/images/icon-120.png
--------------------------------------------------------------------------------
/framer-md-app.framer/framer/images/icon-152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/framer/images/icon-152.png
--------------------------------------------------------------------------------
/framer-md-app.framer/framer/images/icon-180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/framer/images/icon-180.png
--------------------------------------------------------------------------------
/framer-md-app.framer/framer/images/icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/framer/images/icon-192.png
--------------------------------------------------------------------------------
/framer-md-app.framer/framer/images/icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/framer/images/icon-76.png
--------------------------------------------------------------------------------
/framer-md-app.framer/framer/version:
--------------------------------------------------------------------------------
1 | 10
--------------------------------------------------------------------------------
/framer-md-app.framer/images/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/images/.gitkeep
--------------------------------------------------------------------------------
/framer-md-app.framer/images/.gitkeep 2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/images/.gitkeep 2
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/ActionButton.coffee:
--------------------------------------------------------------------------------
1 | # .d888888 dP oo 888888ba dP dP
2 | # d8' 88 88 88 `8b 88 88
3 | # 88aaaaa88a .d8888b. d8888P dP .d8888b. 88d888b. a88aaaa8P' dP dP d8888P d8888P .d8888b. 88d888b.
4 | # 88 88 88' `"" 88 88 88' `88 88' `88 88 `8b. 88 88 88 88 88' `88 88' `88
5 | # 88 88 88. ... 88 88 88. .88 88 88 88 .88 88. .88 88 88 88. .88 88 88
6 | # 88 88 `88888P' dP dP `88888P' dP dP 88888888P `88888P' dP dP `88888P' dP dP
7 |
8 | { Ripple } = require 'md-components/Ripple'
9 | { Icon } = require 'md-components/Icon'
10 | { Theme } = require 'md-components/Theme'
11 |
12 | exports.ActionButton = class ActionButton extends Layer
13 | constructor: (options = {}) ->
14 |
15 | @_action = options.action ? -> null
16 | @_icon = options.icon ? 'plus'
17 |
18 | { app } = require 'md-components/App'
19 |
20 | super _.defaults options,
21 | name: 'Action Button'
22 | x: Align.right(-16), y: Align.bottom(-17)
23 | width: 64, height: 64, borderRadius: 32
24 | backgroundColor: Theme.fab.backgroundColor
25 | shadowY: 2, shadowBlur: 3
26 | shadowColor: 'rgba(0,0,0,.25)'
27 | animationOptions: {time: .15}
28 |
29 | if app?
30 | @y = Align.bottom(-app.footer.height - 17)
31 | app.actionButton = @
32 |
33 | # icon
34 |
35 | @iconLayer = new Icon
36 | name: '.', parent: @
37 | x: Align.center, y: Align.center
38 | icon: @_icon,
39 | color: Theme.fab.color
40 |
41 | # mask
42 |
43 | @mask = new Layer
44 | parent: @
45 | size: @size
46 | backgroundColor: null
47 | borderRadius: @borderRadius
48 | clip: true
49 | opacity: 1
50 |
51 | @mask.placeBehind @iconLayer
52 | @ripple = new Ripple( @mask, null )
53 |
54 | # events
55 |
56 | @onTouchStart (event) ->
57 | @showTouched()
58 | Utils.delay 1, => @reset()
59 |
60 | @onTouchEnd (event) ->
61 | @_action()
62 | @reset()
63 |
64 | showTouched: ->
65 | @animate {shadowY: 3, shadowSpread: 1}
66 |
67 | reset: ->
68 | @animate
69 | shadowY: 2
70 | shadowSpread: 0
71 |
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/App.coffee:
--------------------------------------------------------------------------------
1 | # .d888888
2 | # d8' 88
3 | # 88aaaaa88a 88d888b. 88d888b.
4 | # 88 88 88' `88 88' `88
5 | # 88 88 88. .88 88. .88
6 | # 88 88 88Y888P' 88Y888P'
7 | # 88 88
8 | # dP dP
9 |
10 | { Header } = require 'md-components/Header'
11 | { BottomNav } = require 'md-components/BottomNav'
12 | { MenuOverlay } = require 'md-components/MenuOverlay'
13 | { Theme } = require 'md-components/Theme'
14 |
15 | exports.app # set by class
16 |
17 | class exports.App extends FlowComponent
18 | constructor: (options = {}) ->
19 | @__constructor = true
20 |
21 | exports.app = @
22 |
23 | @activeInput
24 | @header
25 | @keyboard
26 |
27 | @notifications = []
28 |
29 | super _.defaults options,
30 | name: 'App'
31 |
32 | # Header
33 |
34 | @header = new Header
35 | title: ''
36 | icon: ''
37 |
38 | # Keyboard
39 |
40 | @keyboard = new Layer
41 | name: 'Keyboard'
42 | y: @maxY, image: Theme.keyboard.image
43 | width: @width, height: 222
44 | index: 1000
45 | animationOptions:
46 | time: .25
47 |
48 | @keyboard.onTap @closeKeyboard
49 |
50 | # App Footer
51 |
52 | @footer = new Layer
53 | name: 'Footer'
54 | width: Screen.width, height: 48
55 | image: Theme.footer.image
56 | index: 999
57 | y: Align.bottom()
58 | clip: true
59 |
60 | flash = undefined
61 |
62 | @backButton = new Layer
63 | name: 'Back Button', parent: @footer
64 | x: 56
65 | width: 40, height: 40, borderRadius: 24
66 | opacity: 0, backgroundColor: 'rgba(255, 255, 255, .2)'
67 | animationOptions: {time: .15}
68 |
69 | @backButton.onTapStart =>
70 | flash?.destroy()
71 | flash = @backButton.copy()
72 | flash.ignoreEvents = true
73 | flash.parent = @footer
74 | flash.animate {x: 32, width: 100, y: 0, height: 48, opacity: 1}
75 |
76 | @backButton.onTap =>
77 | flash?.animateStop()
78 | flash?.animate {opacity: 0, options:{time: .5}}
79 | return if @current.constructor.name is 'View'
80 | @showPrevious()
81 |
82 | @menuOverlay = new MenuOverlay
83 | title: @name
84 |
85 | # Transition Events
86 |
87 | @onTransitionStart (prev, next, direction) =>
88 | Utils.delay 0, => @onChange(next)
89 |
90 | # On changing to a new page
91 |
92 | onChange: (next) ->
93 | return if typeof next is 'string'
94 | if !_.includes(['View', 'Page'], next.constructor?.name)
95 | throw 'App only words with Views and Pages.'
96 | return
97 |
98 | @setHeader(next.headerOptions)
99 | next.contentInset.top = @header.maxY + 16
100 |
101 | next.scrollY = 0
102 | next.onLoad()
103 |
104 | # Transitions
105 |
106 | showNextRight: (nav, layerA, layerB, overlay) ->
107 | options = {curve: "spring(300, 35, 0)"}
108 |
109 | transition =
110 | layerA:
111 | show: {options: options, x: 0, y: 0}
112 | hide: {options: options, x: 0 - layerA?.width / 2, y: 0}
113 | layerB:
114 | show: {options: options, x: 0, y: 0}
115 | hide: {options: options, x: layerB.width, y: 0}
116 |
117 | showNextLeft: (nav, layerA, layerB, overlay) ->
118 | options = {curve: "spring(300, 35, 0)"}
119 |
120 | transition =
121 | layerA:
122 | show: {options: options, x: 0, y: 0}
123 | hide: {options: options, x: 0 + layerA?.width / 2, y: 0}
124 | layerB:
125 | show: {options: options, x: 0, y: 0}
126 | hide: {options: options, x: -layerB.width, y: 0}
127 |
128 | # keyboard
129 |
130 | openKeyboard: () =>
131 | @footer.visible = false
132 | return if Utils.isMobile()
133 |
134 | @keyboard.bringToFront()
135 | @animate { y: -@keyboard.height }
136 | @keyboard.animate { y: Screen.height - @keyboard.height }
137 |
138 | closeKeyboard: =>
139 | @footer.visible = true
140 | @animate { y: 0 }
141 | @keyboard.animate { y: Screen.height }
142 |
143 | # menu
144 |
145 | showMenu: ->
146 | @menuOverlay.show()
147 |
148 | hideMenu: ->
149 | @menuOverlay.hide()
150 |
151 | # header
152 |
153 | setHeader: (options = {}) ->
154 | @header.setHeader(options)
155 |
156 | # add view
157 |
158 | addView: (options = {}) ->
159 | @menuOverlay.addLink(options)
160 |
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/BottomNav.coffee:
--------------------------------------------------------------------------------
1 | # 888888ba dP dP 888888ba
2 | # 88 `8b 88 88 88 `8b
3 | # a88aaaa8P' .d8888b. d8888P d8888P .d8888b. 88d8b.d8b. 88 88 .d8888b. dP .dP
4 | # 88 `8b. 88' `88 88 88 88' `88 88'`88'`88 88 88 88' `88 88 d8'
5 | # 88 .88 88. .88 88 88 88. .88 88 88 88 88 88 88. .88 88 .88'
6 | # 88888888P `88888P' dP dP `88888P' dP dP dP dP dP `88888P8 8888P'
7 |
8 | Type = require 'md-components/Type'
9 | { Ripple } = require 'md-components/Ripple'
10 | { Icon } = require 'md-components/Icon'
11 | { Theme } = require 'md-components/Theme'
12 |
13 | exports.BottomNav = class BottomNav extends Layer
14 | constructor: (options = {}) ->
15 |
16 | @_destinations = options.destinations ? throw 'Needs at least one destination.'
17 | @_items = []
18 | @_initialDestination = options.initialDestination ? undefined
19 | # destination should be: [{name: string, icon: iconString, action: function}]
20 | @_activeDestination = @_initialDestination ? @_items[0]
21 | @_app = options.app
22 | @view = options.view
23 |
24 | super _.defaults options,
25 | name: 'Bottom Nav'
26 | y: Align.bottom
27 | width: Screen.width, height: 56
28 | backgroundColor: Theme.bottomNav.backgroundColor
29 | shadowY: Theme.bottomNav.shadowY
30 | shadowBlur: Theme.bottomNav.shadowBlur
31 | shadowColor: Theme.bottomNav.shadowColor
32 | clip: true
33 |
34 | for destination, i in @_destinations
35 |
36 | item = new Layer
37 | name: '.', parent: @
38 | x: @width/@_destinations.length * i
39 | width: @width/@_destinations.length, height: @height
40 | color: Theme.primary
41 | backgroundColor: null
42 |
43 | nav = @
44 |
45 | do _.bind( ->
46 |
47 | @mask = new Layer
48 | parent: @
49 | x: Align.center, y: Align.center()
50 | height: @height * 1.72
51 | width: @height * 1.7
52 | borderRadius: @height
53 | backgroundColor: null
54 | clip: true
55 | opacity: 1
56 |
57 | @ripple = new Ripple( @mask , external = true, undefined, events = false)
58 |
59 | @iconLayer = new Icon
60 | name: '.', parent: @
61 | x: Align.center, y: Align.center(-8)
62 | icon: destination.icon
63 | animationOptions: {time: .15}
64 |
65 | @labelLayer = new Type.Caption
66 | name: '.', parent: @
67 | x: Align.center, y: Align.center(14)
68 | width: @width,
69 | textAlign: 'center'
70 | text: destination.title
71 | animationOptions: {time: .15}
72 |
73 | # set events on entire item
74 | @onTapStart ( event ) => @ripple.show( event.point )
75 | @onTapEnd @ripple.hide
76 | @onPanEnd @ripple.hide
77 |
78 | @view = destination.view
79 |
80 | @onTap -> nav._app.changeView(@view)
81 |
82 | , item)
83 |
84 | @_items.push(item)
85 |
86 | @showActive(@_items[0])
87 |
88 | @define "activeDestination",
89 | get: -> return @_activeDestination
90 | set: (destination) ->
91 | return if destination is @_activeDestination
92 | @_activeDestination = destination
93 |
94 | @showActive(@_activeDestination)
95 |
96 | @_app.changeView(@_activeDestination.view)
97 |
98 | showActive: (item) ->
99 | item.labelLayer.animate {color: Theme.primary, opacity: 1}
100 | item.iconLayer.color = Theme.primary
101 |
102 | for sib in item.siblings
103 | sib.labelLayer.animate {color: '#777'}
104 | sib.iconLayer.color = '#777'
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/Button.coffee:
--------------------------------------------------------------------------------
1 | # 888888ba dP dP
2 | # 88 `8b 88 88
3 | # a88aaaa8P' dP dP d8888P d8888P .d8888b. 88d888b.
4 | # 88 `8b. 88 88 88 88 88' `88 88' `88
5 | # 88 .88 88. .88 88 88 88. .88 88 88
6 | # 88888888P `88888P' dP dP `88888P' dP dP
7 |
8 |
9 | Type = require 'md-components/Type'
10 | { Ripple } = require 'md-components/Ripple'
11 | { Icon } = require 'md-components/Icon'
12 | { Theme } = require 'md-components/Theme'
13 |
14 | exports.Button = class Button extends Layer
15 | constructor: (options = {}) ->
16 | @__constructor = true
17 | showLayers = options.showLayers
18 |
19 | # if an icon is passed in, return an icon class and bail
20 | if options.icon
21 | options.action ?= -> null
22 | options.color ?= Theme.colors.primary.main
23 | return new Icon(options)
24 |
25 | @_disabled
26 | @_action
27 | @_raised
28 | @_type
29 | @_base
30 | @_labelText
31 |
32 | @_explicitWidth = options.width?
33 | @_startX = options.x
34 |
35 | @_type = options.type ? if options.raised then 'raised' else 'flat'
36 |
37 | # properties by type
38 | switch @_type
39 | when 'flat'
40 | @_base =
41 | name: 'Flat Button'
42 | height: 36
43 | width: 999
44 | borderRadius: 2
45 | backgroundColor: null
46 | color: Theme.colors.secondary.main
47 | shadowY: 0
48 | shadowColor: 'rgba(0,0,0,.26)'
49 | shadowBlur: 0
50 | animationOptions: {time: .15}
51 | when 'raised'
52 | @_base =
53 | name: 'Raised Button'
54 | height: 36
55 | width: 999
56 | borderRadius: 2
57 | backgroundColor: Theme.colors.secondary.main
58 | color: Theme.colors.secondary.text
59 | shadowY: 2
60 | shadowColor: 'rgba(0,0,0,.26)'
61 | shadowBlur: 4
62 | animationOptions: {time: .15}
63 |
64 | super _.defaults options, @_base
65 |
66 | # text label
67 | @labelLayer = new Type.Button
68 | name: if showLayers then 'Label' else '.'
69 | parent: @
70 | height: 36
71 | text: '{labelText}'
72 | textTransform: 'uppercase'
73 | textAlign: 'center'
74 | color: @color
75 | animationOptions: {time: .15}
76 | padding:
77 | left: 16.5, right: 16.5
78 | top: 9, bottom: 11
79 |
80 | # events
81 | @onTapStart ->
82 | @showRaised()
83 |
84 | @onTapEnd ->
85 | return if @_disabled
86 | @_action()
87 | @refresh()
88 |
89 | @labelLayer.on "change:width", =>
90 | return if @_explicitWidth
91 | @width = @labelLayer.width
92 | @_base.width = @labelLayer.width
93 | @setRipple()
94 |
95 | @on "change:width", =>
96 | return if @width is @labelLayer.width
97 | @labelLayer.width = @width
98 | @setRipple()
99 |
100 | # set props
101 | @action = options.action
102 | @disabled = options.disabled ? false
103 |
104 | delete @__constructor
105 |
106 | @text = options.text ? 'button'
107 |
108 | showRaised: =>
109 | return if @disabled
110 | return if @type isnt 'raised'
111 | @animate {shadowY: 5, shadowBlur: 8}
112 |
113 | setRipple: ->
114 | @mask?.destroy()
115 |
116 | @mask = new Layer
117 | parent: @
118 | size: @size
119 | backgroundColor: null
120 | borderRadius: 2
121 | clip: true
122 | opacity: 1
123 |
124 | @mask.placeBehind @labelLayer
125 |
126 | switch @type
127 | when 'flat'
128 | @ripple = new Ripple( @mask, null, colorOverride = 'rgba(0,0,0,.05)' )
129 | when 'raised'
130 | @ripple = new Ripple( @mask, null )
131 |
132 | refresh: =>
133 | @animateStop()
134 | if @disabled
135 | if @type is 'raised'
136 | @animate
137 | backgroundColor: 'rgba(0,0,0,.12)'
138 | shadowY: 0
139 | shadowBlur: 0
140 | @labelLayer.animate
141 | color: 'rgba(0,0,0,.26)'
142 | else
143 | @animate @_base
144 | @labelLayer.animate
145 | color: @_base.color
146 |
147 | @define "type",
148 | get: -> return @_type
149 |
150 | @define "disabled",
151 | get: -> return @_disabled
152 | set: (bool = false) ->
153 | return if bool is @_disabled
154 | @_disabled = bool
155 |
156 | @emit("change:disabled", @_disabled, @)
157 |
158 | return if @__constructor
159 | @refresh()
160 |
161 | @define "action",
162 | get: -> return @_action
163 | set: (func = -> null) ->
164 | return if func is @_action
165 | @_action = func
166 |
167 | @define "text",
168 | get: -> return @_labelText
169 | set: (text = '') ->
170 | return if @__constructor
171 | @_labelText = text
172 |
173 | @labelLayer.visible = text.length > 0
174 | @labelLayer.template = text
175 |
176 | @x = @_startX
177 | @refresh()
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/Card.coffee:
--------------------------------------------------------------------------------
1 | # a88888b. dP
2 | # d8' `88 88
3 | # 88 .d8888b. 88d888b. .d888b88
4 | # 88 88' `88 88' `88 88' `88
5 | # Y8. .88 88. .88 88 88. .88
6 | # Y88888P' `88888P8 dP `88888P8
7 |
8 | Type = require 'md-components/Type'
9 | { Ripple } = require 'md-components/Ripple'
10 | { Icon } = require 'md-components/Icon'
11 | { Theme } = require 'md-components/Theme'
12 | { Divider } = require 'md-components/Divider'
13 | { Button } = require 'md-components/Button'
14 | { Elevation } = require 'md-components/Elevation'
15 |
16 | exports.Card = class Card extends Layer
17 | constructor: (options = {}) ->
18 | showLayers = options.showLayers ? true
19 |
20 | @_stack = []
21 |
22 | @padding = options.padding ? {
23 | top: 16, right: 16,
24 | bottom: 16, left: 16
25 | stack: 16
26 | }
27 |
28 | @_elevation
29 | @_raised = undefined
30 |
31 | _initExpand = options.expanded
32 | options.expanded = undefined
33 |
34 | @_expanded = false
35 | @_expand = options.expand
36 |
37 | @_baseHeight = options.height ? 200
38 | @_baseFooterHeight = 0
39 |
40 | @_baseY = options.y ? 8
41 | @_expand = options.expand
42 | @_actions = options.actions ? [] # [{text: "", action: ->}]
43 | @_verticalActions = options.verticalActions ? false
44 |
45 | super _.defaults options,
46 | name: 'Card'
47 | y: 8
48 | width: Screen.width - 16
49 | borderRadius: 2
50 | backgroundColor: '#f9f9f9'
51 | shadowY: 2, shadowBlur: 3
52 | clip: true
53 | animationOptions: {time: .15}
54 |
55 | @footer = new Layer
56 | name: '.', parent: @
57 | height: 52, width: @width
58 | y: Align.bottom
59 | backgroundColor: @backgroundColor
60 | animationOptions: {time: .15}
61 |
62 | @divider = new Divider
63 | name: 'Divider', parent: @footer
64 | visible: false
65 |
66 | if @_expand?
67 |
68 | @divider.visible = true
69 | @footer.visible = true
70 |
71 | @expandIcon = new Icon
72 | name: 'Expand Icon', parent: @footer
73 | x: Align.right(-12), y: Align.bottom(-12)
74 | icon: 'chevron-down', color: '#000'
75 | animationOptions: {time: .15}
76 | action: => @expanded = !@expanded
77 |
78 | if @_actions.length > 0
79 |
80 | @divider.visible = true
81 | @footer.visible = true
82 |
83 | startX = 8; startY = 8
84 |
85 | for action in @_actions
86 | @actionButtons = []
87 |
88 | button = new Button
89 | name: "#{action.text} Button", parent: @footer
90 | x: startX, y: Align.bottom(-startY)
91 | action: _.bind(action.action, @)
92 | text: action.text
93 |
94 | if !@_verticalActions then startX = button.maxX + 4
95 | if @_verticalActions
96 | startY = @height - button.y + 4
97 | @footer.y = button.y - 8
98 | @footer.height += button.height + 8
99 |
100 | @actionButtons.push(button)
101 |
102 | @_baseFooterHeight = @footer.height
103 |
104 | # add a layer to the stack
105 | addToStack: (layers = [], position) =>
106 | if not _.isArray(layers) then layers = [layers]
107 | last = _.last(@stack)
108 |
109 | if last?
110 | startY = last.maxY + (@padding.stack ? 0)
111 | else
112 | startY = @padding.top ? 0
113 |
114 | for layer in layers
115 |
116 | if layer.constructor.name is 'Card' then position = 'full'
117 |
118 | layer.props =
119 | parent: @
120 | x: _.clamp(
121 | @padding.left + layer.x,
122 | @padding.left,
123 | @width - @padding.right - layer.width
124 | )
125 | y: startY
126 |
127 | switch position
128 | when 'full'
129 | layer.width = @width - ( @padding.left + @padding.right )
130 | when 'left'
131 | layer.props =
132 | width: (@width / 2) - @padding.left
133 | x: @padding.left
134 | when 'right'
135 | layer.props =
136 | width: (@width / 2) - @padding.right
137 | x: Align.right(-@padding.right)
138 | when 'center'
139 | layer.x = Align.center
140 |
141 | @stack.push(layer)
142 |
143 | layer.on "change:height", => @moveStack(@)
144 |
145 | @_setHeight()
146 |
147 | # pull a layer from the stack
148 | removeFromStack: (layer) =>
149 | _.pull(@stack, layer)
150 | @refresh()
151 |
152 | # stack layers in stack, with optional padding and animation
153 | _stackView: (
154 | animate = false,
155 | padding = @padding.stack,
156 | top = @padding.top,
157 | animationOptions = {time: .25}
158 | ) =>
159 |
160 | for layer, i in @stack
161 |
162 | if animate is true
163 | if i is 0 then layer.animate
164 | y: top
165 | options: animationOptions
166 |
167 | else layer.animate
168 | y: @stack[i - 1].maxY + padding
169 | options: animationOptions
170 | else
171 | if i is 0 then layer.y = top
172 | else layer.y = @stack[i - 1].maxY + padding
173 |
174 | @_setHeight()
175 |
176 | # move stack when layer height changes
177 | _moveStack: (layer) =>
178 | index = _.indexOf(@stack, layer)
179 | for layer, i in @stack
180 | if i > 0 and i > index
181 | layer.y = @stack[i - 1].maxY + @padding.stack
182 |
183 | @_setHeight()
184 |
185 | _setHeight: ->
186 | @height = _.last(@stack).maxY + (@padding.bottom ? 16)
187 |
188 | # build with page as bound object
189 | build: (func) -> do _.bind(func, @)
190 |
191 | # refresh page
192 | refresh: -> @_stackView()
193 |
194 | @define "stack",
195 | get: -> return @_stack
196 | set: (layers) ->
197 | layer.destroy() for layer in @stack
198 | @addToStack(layers)
199 |
200 | @define "expanded",
201 | get: -> return @_expanded
202 | set: (bool) ->
203 | return if bool is @_expanded
204 | @_expanded = bool
205 |
206 | if @_expanded
207 | @bringToFront()
208 | @expandIcon.animate {rotation: 180}
209 | @animate {height: @height + @_expand}
210 | @footer.animate {height: @_expand}
211 | else
212 | @expandIcon.animate {rotation: 0}
213 | @animate {height: @_baseHeight}
214 | @footer.animate {height: @_baseFooterHeight}
215 |
216 | @emit "change:expanded", @_expanded, @
217 |
218 | @define "raised",
219 | get: -> return @_raised
220 | set: (bool) ->
221 | return if bool is @_raised
222 | @_raised = bool
223 |
224 | if @_raised then @elevation = 8
225 | else @elevation = 2
226 |
227 | @define 'elevation',
228 | get: -> return @_elevation
229 | set: (number) ->
230 | Elevation(@, number)
231 |
232 |
233 |
234 |
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/Checkbox.coffee:
--------------------------------------------------------------------------------
1 | # a88888b. dP dP dP
2 | # d8' `88 88 88 88
3 | # 88 88d888b. .d8888b. .d8888b. 88 .dP 88d888b. .d8888b. dP. .dP
4 | # 88 88' `88 88ooood8 88' `"" 88888" 88' `88 88' `88 `8bd8'
5 | # Y8. .88 88 88 88. ... 88. ... 88 `8b. 88. .88 88. .88 .d88b.
6 | # Y88888P' dP dP `88888P' `88888P' dP `YP 88Y8888' `88888P' dP' `dP
7 |
8 | { Icon } = require 'md-components/Icon'
9 | { Theme } = require 'md-components/Theme'
10 |
11 | exports.Checkbox = CheckBox = class Checkbox extends Icon
12 | constructor: (options = {}) ->
13 |
14 | @_group = undefined
15 |
16 | super _.defaults options,
17 | name: '.'
18 | animationOptions: {time: .15}
19 | icon: 'checkbox-blank-outline'
20 | color: Theme.primary
21 | toggle: true
22 | action: -> null
23 |
24 | @on "change:isOn", @updateIcon
25 |
26 | updateIcon: =>
27 | @icon = if @isOn then 'checkbox-marked' else 'checkbox-blank-outline'
28 |
29 | @define "group",
30 | get: -> return @_group
31 | set: (array) ->
32 | return if array is @_group
33 | @_group = array
34 |
35 | # add this checkbox to the group array if not in it already
36 | if not _.includes(@_group, @) then @_group.push(@)
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/Dialog.coffee:
--------------------------------------------------------------------------------
1 | # 888888ba oo dP
2 | # 88 `8b 88
3 | # 88 88 dP .d8888b. 88 .d8888b. .d8888b.
4 | # 88 88 88 88' `88 88 88' `88 88' `88
5 | # 88 .8P 88 88. .88 88 88. .88 88. .88
6 | # 8888888P dP `88888P8 dP `88888P' `8888P88
7 | # .88
8 | # d8888P
9 |
10 | Type = require 'md-components/Type'
11 | { Icon } = require 'md-components/Icon'
12 | { Theme } = require 'md-components/Theme'
13 | { Button } = require 'md-components/Button'
14 |
15 | # simplify: create an actions array, with text, action, color?
16 | # this needs to be standardized across apis
17 |
18 | exports.Dialog = class Dialog extends Layer
19 | constructor: (options = {}) ->
20 |
21 | showLayers = options.showLayers ? false
22 |
23 | @_title = options.title ? 'Default Title'
24 | @_body = options.body ? 'Body text goes here.'
25 | @_acceptText = options.acceptText ? 'confirm'
26 | @_acceptAction = options.acceptAction ? -> null
27 | @_declineText = options.declineText ? ''
28 | @_declineAction = options.declineAction ? -> null
29 |
30 | super _.defaults options,
31 | name: if showLayers then 'Dialog' else '.'
32 | size: Screen.size
33 | backgroundColor: 'rgba(0, 0, 0, .5)'
34 | opacity: 0
35 |
36 | @on Events.Tap, (event) -> event.stopPropagation()
37 |
38 | @container = new Layer
39 | name: 'container', parent: @
40 | x: Align.center
41 | height: 128, width: Screen.width - 80
42 | backgroundColor: Theme.dialog.backgroundColor
43 | shadowX: 0, shadowY: 7, shadowBlur: 30
44 | opacity: 0
45 | shadowColor: 'rgba(0,0,0,.3)'
46 |
47 | @title = new Type.Title
48 | name: '.', parent: @container
49 | x: 24, y: 20
50 | fontSize: 16, fontWeight: 500, color: Theme.text.title
51 | text: @_title
52 |
53 | @body = new Type.Subhead
54 | name: 'body', parent: @container
55 | x: 24, y: 52
56 | width: @container.width - 42
57 | text: @_body
58 |
59 | buttonsY = if @_body is '' then 128 else @body.maxY + 16
60 |
61 | @accept = new Button
62 | name: '.', parent: @container
63 | x: Align.right(-16), y: buttonsY
64 | text: @_acceptText.toUpperCase()
65 | action: @_acceptAction
66 |
67 | if @_declineText isnt ''
68 | @decline = new Button
69 | name: '.', parent: @container
70 | x: 0, y: buttonsY
71 | text: @_declineText.toUpperCase()
72 | action: @_declineAction
73 |
74 | # set positions
75 | @container.height = @accept.maxY + 12
76 | @decline?.maxX = @accept.x - 16
77 | @container.y = Align.center(16)
78 |
79 | # add close actions to confirm and cancel
80 | for button in [@accept, @decline]
81 | button?.onTap => Utils.delay .25, @close
82 |
83 | # ON LOAD
84 | @open()
85 |
86 | open: =>
87 | @animate
88 | opacity: 1
89 | options:
90 | time: .25
91 |
92 | @container.animate
93 | opacity: 1
94 | options:
95 | time: .25
96 | delay: .15
97 |
98 | close: =>
99 | @container.animate
100 | opacity: 0
101 | options:
102 | time: .25
103 |
104 | @animate
105 | opacity: 0
106 | options:
107 | time: .25
108 |
109 | Utils.delay .5, => @destroy()
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/Divider.coffee:
--------------------------------------------------------------------------------
1 | # 888888ba oo oo dP
2 | # 88 `8b 88
3 | # 88 88 dP dP .dP dP .d888b88 .d8888b. 88d888b.
4 | # 88 88 88 88 d8' 88 88' `88 88ooood8 88' `88
5 | # 88 .8P 88 88 .88' 88 88. .88 88. ... 88
6 | # 8888888P dP 8888P' dP `88888P8 `88888P' dP
7 |
8 | Type = require 'md-components/Type'
9 | { Theme } = require 'md-components/Theme'
10 |
11 | class exports.Divider extends Layer
12 | constructor: (options = {}) ->
13 |
14 | width = 0 # check if parent is a View and adjust to padding
15 | showLayers = options.showLayers
16 |
17 | @_labelText = undefined
18 | @_backgroundColor = options.backgroundColor
19 |
20 | options.backgroundColor = Theme.divider.backgroundColor
21 |
22 | super _.defaults options,
23 | name: if showLayers then 'Divider' else '.'
24 | width: options.parent?.width ? 200, height: 1,
25 | backgroundColor: Theme.divider.backgroundColor
26 |
27 | @labelLayer = new Type.Caption
28 | name: if showLayers then 'Label' else '.'
29 | parent: @
30 | x: Align.center
31 | y: Align.center
32 | padding: {left: 16, right: 16}
33 | textAlign: 'center'
34 | textTransform: 'uppercase'
35 | text: '{labelText}'
36 | visible: false
37 | backgroundColor: @_backgroundColor
38 |
39 | @text = options.text
40 |
41 | @define "text",
42 | get: -> return @_labelText
43 | set: (text) ->
44 | if not text? then text = ''
45 | @_labelText = text
46 |
47 | @labelLayer?.visible = @text.length > 0
48 | @labelLayer?.template = @text
49 | @labelLayer?.x = Align.center
50 |
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/Elevation.coffee:
--------------------------------------------------------------------------------
1 | # 88888888b dP dP oo
2 | # 88 88 88
3 | # a88aaaa 88 .d8888b. dP .dP .d8888b. d8888P dP .d8888b. 88d888b.
4 | # 88 88 88ooood8 88 d8' 88' `88 88 88 88' `88 88' `88
5 | # 88 88 88. ... 88 .88' 88. .88 88 88 88. .88 88 88
6 | # 88888888P dP `88888P' 8888P' `88888P8 dP dP `88888P' dP dP
7 |
8 | # thanks to @ma_rylou
9 |
10 | exports.Elevation = (layer, elevationnumber = 0, animate = true, options = {time: .2, curve: 'ease'}) ->
11 |
12 | # Error handling
13 | if typeof elevationnumber isnt "number"
14 | throw Error "Elevation must be a number."
15 |
16 | # Clamp elevation number to between 0 and 24
17 | elevationnumber = _.clamp(elevationnumber, 0, 24)
18 |
19 | props =
20 | shadowSpread: 0
21 | shadowX: 0
22 | shadowY: elevationnumber
23 | shadowBlur: elevationnumber
24 | shadowColor:"rgba(0, 0, 0, 0.24)"
25 |
26 | animProps = _.merge(props, {options: options})
27 |
28 | #target layer
29 | if animate then layer.animate animProps
30 | else layer.props = props
31 |
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/GridList.coffee:
--------------------------------------------------------------------------------
1 |
2 | # .88888. oo dP dP oo dP
3 | # d8' `88 88 88 88
4 | # 88 88d888b. dP .d888b88 88 dP .d8888b. d8888P
5 | # 88 YP88 88' `88 88 88' `88 88 88 Y8ooooo. 88
6 | # Y8. .88 88 88 88. .88 88 88 88 88
7 | # `88888' dP dP `88888P8 88888888P dP `88888P' dP
8 |
9 | Type = require 'md-components/Type'
10 | { Ripple } = require 'md-components/Ripple'
11 | { Icon } = require 'md-components/Icon'
12 | { Theme } = require 'md-components/Theme'
13 |
14 | exports.GridList = class GridList extends Layer
15 | constructor: (options = {}) ->
16 |
17 | @_columns = options.columns ? 2
18 |
19 | super _.defaults options,
20 | name: '.'
21 | width: Screen.width
22 | backgroundColor: null
23 |
24 | @tiles = []
25 | @tileWidth = (@width - 24) / @_columns
26 | @tileHeight = options.tileHeight ? Screen.width / @_columns
27 |
28 | addTile: (tile) ->
29 | tile.i = @tiles.length
30 | tile.gridList = @
31 | @tiles.push(tile)
32 |
33 | tile.x = 8 + (@tileWidth + 8) * (tile.i % @_columns)
34 | tile.y = 8 + (@tileHeight + 8) * Math.floor(tile.i / @_columns)
35 |
36 | @height = _.last(@tiles).maxY
37 |
38 | if @parent?.parent?.content? then @parent.parent.updateContent()
39 |
40 | removeTile: (tile) ->
41 | _.pull(@tiles, tile)
42 | tile.destroy()
43 | @repositionTiles()
44 |
45 | repositionTiles: ->
46 | for tile, i in @tiles
47 | tile.i = i
48 | tile.animate
49 | x: 8 + (@tileWidth + 8) * (tile.i % @_columns)
50 | y: 8 + (@tileHeight + 8) * Math.floor(tile.i / @_columns)
51 | @height = _.last(@tiles).maxY
52 |
53 | if @parent?.parent?.content? then @parent.parent.updateContent()
54 |
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/Header.coffee:
--------------------------------------------------------------------------------
1 | # dP dP dP
2 | # 88 88 88
3 | # 88aaaaa88a .d8888b. .d8888b. .d888b88 .d8888b. 88d888b.
4 | # 88 88 88ooood8 88' `88 88' `88 88ooood8 88' `88
5 | # 88 88 88. ... 88. .88 88. .88 88. ... 88
6 | # dP dP `88888P' `88888P8 `88888P8 `88888P' dP
7 |
8 | Type = require 'md-components/Type'
9 | { Icon } = require 'md-components/Icon'
10 | { Theme } = require 'md-components/Theme'
11 | { modifyColor } = require 'md-components/Theme'
12 | { StatusBar } = require 'md-components/StatusBar'
13 |
14 | exports.Header = class Header extends Layer
15 | constructor: (options = {}) ->
16 | @__constructor = true
17 |
18 | # properties
19 |
20 | @_title
21 | options.title ?= 'Header'
22 |
23 | @_icon
24 | options.icon ?= 'menu'
25 |
26 | @_action
27 | options.action ?= -> null
28 |
29 | # assign forced options
30 | _.assign options,
31 | width: Screen.width
32 | height: 80
33 | shadowY: 2,
34 | shadowBlur: 3,
35 | shadowColor: 'rgba(0,0,0,.24)'
36 |
37 | # set default options
38 | super _.defaults options,
39 | name: options.title
40 | backgroundColor: Theme.header.backgroundColor ? '#777'
41 | color: Theme.header.title ? '#FFF'
42 |
43 | # title
44 |
45 | @titleLayer = new Type.Title
46 | name: '.', parent: @
47 | x: 72, y: Align.bottom(-14)
48 | color: @color
49 | text: ''
50 |
51 | # icon
52 |
53 | @iconLayer = new Icon
54 | name: '.', parent: @,
55 | x: 12, y: Align.center(12)
56 | icon: options.icon ? 'menu'
57 | color: @color
58 |
59 | # status bar
60 |
61 | @statusBar = new StatusBar
62 | name: '.', parent: @
63 |
64 | # events
65 |
66 | @iconLayer.onTapEnd => @_action()
67 |
68 | @on "change:color", =>
69 | @titleLayer.color = @color
70 | @iconLayer.color = @color
71 | @statusBar.color = @color
72 |
73 | @on "change:backgroundColor", =>
74 | @statusBar.backgroundColor = modifyColor(
75 | @backgroundColor, -1, -7, -12
76 | )
77 |
78 | delete @__constructor
79 |
80 | # set options that require layers
81 |
82 | @title = options.title
83 | @icon = options.icon
84 | @action = options.action
85 |
86 | setHeader: (options = {}) ->
87 |
88 | for layer in [@titleLayer, @iconLayer]
89 | layer.animate {opacity: 0, options: {time: .15}}
90 |
91 | Utils.delay .25, =>
92 |
93 | _.assign(@, options)
94 |
95 | for layer in [@titleLayer, @iconLayer]
96 | layer.animate {opacity: 1, options: {time: .15}}
97 |
98 | @define "title",
99 | get: -> return @_title
100 | set: (titleText) ->
101 | return if @__constructor
102 | @_title = titleText
103 | @titleLayer.text = titleText
104 |
105 | @define "icon",
106 | get: -> return @_icon
107 | set: (iconName) ->
108 | return if @__constructor
109 | @_icon = iconName
110 | @iconLayer.icon = iconName
111 |
112 | @define "action",
113 | get: -> return @_action
114 | set: (action) ->
115 | return if @__constructor
116 | @_action = action
117 |
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/MenuButton.coffee:
--------------------------------------------------------------------------------
1 | # 8888ba.88ba 888888ba dP dP
2 | # 88 `8b `8b 88 `8b 88 88
3 | # 88 88 88 .d8888b. 88d888b. dP dP a88aaaa8P' dP dP d8888P d8888P .d8888b. 88d888b.
4 | # 88 88 88 88ooood8 88' `88 88 88 88 `8b. 88 88 88 88 88' `88 88' `88
5 | # 88 88 88 88. ... 88 88 88. .88 88 .88 88. .88 88 88 88. .88 88 88
6 | # dP dP dP `88888P' dP dP `88888P' 88888888P `88888P' dP dP `88888P' dP dP
7 |
8 | Type = require 'md-components/Type'
9 | { Ripple } = require 'md-components/Ripple'
10 | { Icon } = require 'md-components/Icon'
11 | { Theme } = require 'md-components/Theme'
12 |
13 |
14 | exports.MenuButton = class MenuButton extends Layer
15 | constructor: (options = {}) ->
16 |
17 | { app } = require 'md-components/App'
18 |
19 | @_icon = options.icon ? 'home'
20 | @_text = options.text ? 'Default'
21 | @_action = options.action ? -> null
22 | @_view = options.view
23 | @_app = options.app
24 | @_i = options.i
25 |
26 | super _.defaults options,
27 | height: 48, width: 304
28 | backgroundColor: null
29 |
30 | @iconLayer = new Icon
31 | name: '.', parent: @
32 | y: Align.center
33 | icon: @_icon, color: Theme.menuOverlay.text
34 | action: -> null
35 |
36 | @labelLayer = new Type.Regular
37 | name: 'label', parent: @
38 | x: @iconLayer.maxX + 16
39 | y: Align.center()
40 | color: Theme.menuOverlay.text
41 | text: @_text
42 |
43 | @onTapEnd ->
44 | if @_view?
45 | if @_view.i > @_i
46 | app?.transition(@_view, app.showNextRight)
47 | else
48 | app?.transition(@_view, app.showNextLeft)
49 | Utils.delay .25, => @parent.hide()
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/MenuOverlay.coffee:
--------------------------------------------------------------------------------
1 | # 8888ba.88ba .88888. dP
2 | # 88 `8b `8b d8' `8b 88
3 | # 88 88 88 .d8888b. 88d888b. dP dP 88 88 dP .dP .d8888b. 88d888b. 88 .d8888b. dP dP
4 | # 88 88 88 88ooood8 88' `88 88 88 88 88 88 d8' 88ooood8 88' `88 88 88' `88 88 88
5 | # 88 88 88 88. ... 88 88 88. .88 Y8. .8P 88 .88' 88. ... 88 88 88. .88 88. .88
6 | # dP dP dP `88888P' dP dP `88888P' `8888P' 8888P' `88888P' dP dP `88888P8 `8888P88
7 | # .88
8 | # d8888P
9 |
10 | Type = require 'md-components/Type'
11 | { Ripple } = require 'md-components/Ripple'
12 | { Icon } = require 'md-components/Icon'
13 | { Theme } = require 'md-components/Theme'
14 | { MenuButton } = require 'md-components/MenuButton'
15 |
16 | exports.MenuOverlay = class MenuOverlay extends Layer
17 | constructor: (options = {}) ->
18 |
19 | @links = []
20 | @_title = options.title ? 'Menu'
21 | @_image = options.image ? null
22 | @_app = options.app
23 |
24 |
25 | super _.defaults options,
26 | height: Screen.height
27 | width: 304
28 | visible: false
29 | backgroundColor: Theme.menuOverlay.backgroundColor
30 | animationOptions: {curve: "spring(300, 35, 0)"}
31 |
32 |
33 | @scrim = new Layer
34 | name: '.',
35 | size: Screen.size
36 | backgroundColor: 'rgba(0,0,0,.6)'
37 | opacity: 0
38 | visible: false
39 | animationOptions:
40 | time: .25
41 |
42 | @scrim.onTap => @hide()
43 | @onSwipeLeftEnd => @hide()
44 |
45 | @header = new Layer
46 | name: '.', parent: @
47 | width: @width, height: 173
48 | image: Theme.user.image
49 | backgroundColor: Theme.menuOverlay.header.backgroundColor
50 |
51 | @titleIcon = new Layer
52 | name: '.', parent: @header
53 | x: 16, y: 40
54 | height: 64, width: 64
55 | borderRadius: 32
56 | backgroundColor: Theme.menuOverlay.header.icon
57 |
58 | @subheaderExpand = new Icon
59 | name: '.', parent: @header
60 | x: Align.right(-16)
61 | y: Align.bottom(-16)
62 | icon: 'menu-down'
63 | color: Theme.menuOverlay.subheader.icon
64 |
65 | @subheader = new Type.Body1
66 | name: '.', parent: @header
67 | width: @width
68 | x: 16, y: Align.bottom(-18)
69 | text: @_title
70 | color: Theme.menuOverlay.subheader.text
71 |
72 | show: ->
73 | @bringToFront()
74 | @visible = true
75 | @x = -Screen.width
76 | @animate
77 | x: 0
78 |
79 | @scrim.placeBehind(@)
80 | @scrim.visible = true
81 | @scrim.animate
82 | opacity: 1
83 |
84 | hide: ->
85 | @animate
86 | x: -Screen.width
87 |
88 | @scrim.animate
89 | opacity: 0
90 |
91 | Utils.delay .3, =>
92 | @visible = false
93 | @scrim.visible = false
94 | @sendToBack()
95 | @scrim.sendToBack()
96 |
97 | addLink: (options) ->
98 | lastY = _.last(@links)?.maxY ? 189
99 | @links.push new MenuButton
100 | name: '.', parent: @
101 | x: 16, y: lastY
102 | text: options.title
103 | icon: options.icon
104 | view: options.view
105 |
106 | options.view.i = @links.length
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/Notification.coffee:
--------------------------------------------------------------------------------
1 | # 888888ba dP oo .8888b oo dP oo
2 | # 88 `8b 88 88 " 88
3 | # 88 88 .d8888b. d8888P dP 88aaa dP .d8888b. .d8888b. d8888P dP .d8888b. 88d888b.
4 | # 88 88 88' `88 88 88 88 88 88' `"" 88' `88 88 88 88' `88 88' `88
5 | # 88 88 88. .88 88 88 88 88 88. ... 88. .88 88 88 88. .88 88 88
6 | # dP dP `88888P' dP dP dP dP `88888P' `88888P8 dP dP `88888P' dP dP
7 |
8 | # Notification does not require an app property, however if one is not set then notifications will not app around eachother.
9 |
10 | # TODO: replace action1 and action2 with array of actions.
11 |
12 | Type = require 'md-components/Type'
13 | { Icon } = require 'md-components/Icon'
14 | { Theme } = require 'md-components/Theme'
15 | { Divider } = require 'md-components/Divider'
16 |
17 | exports.Notification = Notification = class Notification extends Layer
18 | constructor: (options = {}) ->
19 |
20 | { app } = require 'md-components/App'
21 |
22 | @_title = options.title ? 'Notification'
23 | @_body = options.body ? 'This is a notification.'
24 | @_icon = options.icon ? undefined
25 | @_iconColor = options.iconColor ? Theme.text.secondary
26 | @_iconBackgroundColor = options.iconBackgroundColor ? Theme.secondary
27 |
28 | @_actions = options.actions ? []
29 |
30 | @_time = options.time ? new Date()
31 | @_timeout = options.timeout ? 5
32 | @_group = app?.notifications ? options.group ? []
33 |
34 | # actions should be:
35 | # {title: 'archive', icon: 'archive', color: '', backgroundColor: ''}
36 |
37 | super _.defaults options,
38 | name: options.name ? '.'
39 | width: Screen.width - 16, borderRadius: 2
40 | x: Align.center
41 | backgroundColor: Theme.dialog.backgroundColor
42 | shadowX: 0, shadowY: 2, shadowBlur: 3
43 | opacity: 0, shadowColor: 'rgba(0,0,0,.3)'
44 | animationOptions: {time: .25}
45 |
46 | @iconLayer = new Layer
47 | name: 'Icon Container'
48 | parent: @
49 | x: 12, y: 12
50 | height: 40, width: 40, borderRadius: 20
51 | backgroundColor: @_iconBackgroundColor
52 |
53 | if @_icon
54 | @icon = new Icon
55 | name: 'Icon'
56 | parent: @iconLayer
57 | x: Align.center, y: Align.center
58 | color: @_iconColor
59 | icon: @_icon
60 |
61 | @title = new Type.Subhead
62 | name: 'Title'
63 | parent: @
64 | x: 64, y: 8
65 | width: @width - 72
66 | color: 'rgba(0,0,0,.87)'
67 | text: @_title
68 |
69 | @body = new Type.Body1
70 | name: 'Body'
71 | parent: @
72 | x: 64, y: @title.maxY
73 | width: @width - 72
74 | text: @_body
75 |
76 | @date = new Type.Caption
77 | name: 'Date'
78 | parent: @
79 | x: Align.right(-9), y: 15
80 | text: @_time.toLocaleTimeString([], hour: "numeric", minute: "2-digit")
81 |
82 | @height = _.clamp(@body.maxY + 13, 64, Infinity)
83 |
84 | # actions
85 |
86 | if @_actions.length > 0
87 |
88 | divider = new Divider
89 | name: 'Divider'
90 | parent: @
91 | x: 64, y: @body.maxY + 11
92 | width: @width - 64
93 |
94 | @height = divider.maxY + 46
95 |
96 | startX = 64
97 | notification = @
98 |
99 | for action in @_actions
100 | actionButton = new Layer
101 | name: 'Action 1', parent: @
102 | x: startX, y: divider.maxY + 11
103 | width: 80, height: 24, backgroundColor: null
104 |
105 | do _.bind( -> # actionButton
106 |
107 | @icon = new Icon
108 | name: 'Icon', parent: @
109 | width: 18, height: 18
110 | color: 'rgba(0,0,0,.54)'
111 | icon: action.icon
112 |
113 | @label = new Type.Caption
114 | name: 'Label', parent: @
115 | x: @icon.maxX + 8
116 | fontSize: 13
117 | textTransform: 'uppercase'
118 | text: action.title
119 |
120 | @width = @label.maxX + 20
121 | startX += @width
122 |
123 | do (action) =>
124 | @onTap =>
125 | notification.close()
126 | if action.action?
127 | Utils.delay .25, _.bind(action.action, notification)
128 |
129 | actionButton)
130 |
131 | # swipes
132 |
133 | @onSwipeLeftEnd => @close('left')
134 | @onSwipeRightEnd => @close('right')
135 |
136 | @open()
137 |
138 | open: =>
139 | startY = _.last(@_group)?.maxY ? 24
140 | startY += 8
141 |
142 | @y = startY
143 |
144 | @animate {opacity: 1}
145 | @_group.push(@)
146 |
147 | Utils.delay @_timeout, => if not @closed then @close('right')
148 |
149 |
150 | close: (direction) =>
151 | _.pull(@_group, @)
152 |
153 | newY = 32
154 | for layer, i in @_group
155 | layer.animate { y: newY }
156 | newY += layer.height + 8
157 |
158 | @animate
159 | x: if direction is 'left' then -Screen.width else Screen.width
160 | opacity: 0
161 |
162 | @closed = true
163 |
164 | Utils.delay .5, => @destroy()
165 |
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/Page.coffee:
--------------------------------------------------------------------------------
1 |
2 | # 888888ba
3 | # 88 `8b
4 | # a88aaaa8P' .d8888b. .d8888b. .d8888b.
5 | # 88 88' `88 88' `88 88ooood8
6 | # 88 88. .88 88. .88 88. ...
7 | # dP `88888P8 `8888P88 `88888P'
8 | # .88
9 | # d8888P
10 |
11 | # simplify header controls
12 | # remove template(?)
13 |
14 | { Theme } = require 'md-components/Theme'
15 | { StackView } = require 'md-components/StackView'
16 |
17 | exports.Page = class Page extends StackView
18 | constructor: (options = {}) ->
19 | @__constructor = true
20 |
21 | { app } = require 'md-components/App'
22 |
23 | options.icon ?= 'arrow-left'
24 | options.action ?= -> app.showPrevious()
25 |
26 | # header
27 | @headerOptions = {
28 | title: options.title
29 | icon: options.icon
30 | action: options.action
31 | actions: options.actions
32 | }
33 |
34 | # on load
35 | @onLoad = options.onLoad ? -> null
36 |
37 | # refresh
38 | @refresh = options.refresh ? -> null
39 |
40 | super _.defaults options,
41 | name: options.title ? 'View'
42 | size: Screen.size
43 | scrollHorizontal: false
44 | backgroundColor: Theme.page.primary.backgroundColor
45 | shadowSpread: 1
46 | shadowColor: 'rgba(0,0,0,.16)'
47 | shadowBlur: 3
48 | contentInset: {top: app.header?.height, bottom: 241}
49 |
50 | @content.backgroundColor = null
51 |
52 | @sendToBack()
53 |
54 | delete @__constructor
55 |
56 | onLoad: -> null
57 | refresh: -> null
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/Radiobox.coffee:
--------------------------------------------------------------------------------
1 | # 888888ba dP oo dP
2 | # 88 `8b 88 88
3 | # a88aaaa8P' .d8888b. .d888b88 dP .d8888b. 88d888b. .d8888b. dP. .dP
4 | # 88 `8b. 88' `88 88' `88 88 88' `88 88' `88 88' `88 `8bd8'
5 | # 88 88 88. .88 88. .88 88 88. .88 88. .88 88. .88 .d88b.
6 | # dP dP `88888P8 `88888P8 dP `88888P' 88Y8888' `88888P' dP' `dP
7 |
8 |
9 | { Icon } = require 'md-components/Icon'
10 | { Theme } = require 'md-components/Theme'
11 |
12 | exports.Radiobox = Radiobox = class Radiobox extends Icon
13 | constructor: (options = {}) ->
14 |
15 | @_group = undefined
16 |
17 | super _.defaults options,
18 | name: '.'
19 | animationOptions: {time: .15}
20 | icon: 'radiobox-blank'
21 | color: Theme.primary
22 | toggle: true
23 | toggleLock: true
24 | action: -> null
25 |
26 | @on "change:isOn", ->
27 | @updateIcon()
28 | @updateSiblings()
29 |
30 | updateIcon: =>
31 | @icon = if @isOn then 'radiobox-marked' else 'radiobox-blank'
32 |
33 | updateSiblings: =>
34 | if @isOn then sib.isOn = false for sib in _.without(@_group, @)
35 |
36 | @define "group",
37 | get: -> return @_group
38 | set: (array) ->
39 | return if array is @_group
40 | @_group = array
41 |
42 | # add this checkbox to the group array if not in it already
43 | if not _.includes(@_group, @) then @_group.push(@)
44 |
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/Ripple.coffee:
--------------------------------------------------------------------------------
1 | # 888888ba oo dP
2 | # 88 `8b 88
3 | # a88aaaa8P' dP 88d888b. 88d888b. 88 .d8888b.
4 | # 88 `8b. 88 88' `88 88' `88 88 88ooood8
5 | # 88 88 88 88. .88 88. .88 88 88. ...
6 | # dP dP dP 88Y888P' 88Y888P' dP `88888P'
7 | # 88 88
8 | # dP dP
9 |
10 | # By default, shows an expanding circle over a layer, clipped to its frame.
11 | # On the layer's touchEnd event, the circle and its mask will disappear.
12 |
13 | # required:
14 | # layer (Layer), the layer over which to show the ripple effect
15 | # point (object), the ripple origin point, usually a onTouchStart's event.point
16 |
17 | # optional:
18 | # placeBehind (Layer), a child of layer behind which the ripple should appear
19 | # color (string or color object), a custom color for the ripple
20 |
21 | class exports.Ripple extends Layer
22 | constructor: (@mask, @external = false, @colorOverride = undefined, events = true) ->
23 |
24 | @mask ?= throw 'Ripple needs a mask layer'
25 |
26 | super
27 | name: 'Ripple', parent: @mask
28 | point: Align.center
29 | backgroundColor: @_color
30 | width: 8, height: 8
31 | opacity: 0
32 |
33 | fullWidth = if @mask.width > @mask.height then @mask.width else @mask.height
34 | @_fullWidth = fullWidth * 2
35 |
36 | if events
37 | @mask.onTapStart ( event ) => @show( event.point )
38 | @mask.onTapEnd @hide
39 | @mask.onPanEnd @hide
40 | @mask.onPan (event, layer) =>
41 | isTooFar = (num) -> Math.abs(num) >= 24
42 | @hide() if isTooFar(event.offset.x) or isTooFar(event.offset.y)
43 |
44 | show: (point = @point) =>
45 | return if @mask.parent?.disabled
46 |
47 | @animateStop()
48 |
49 | fullWidth = @_fullWidth
50 | parent = @mask.parent
51 | color = undefined
52 |
53 | if @colorOverride?
54 | color = @colorOverride
55 | else if @external
56 | color = new Color( parent.color )
57 | .alpha( .25 )
58 | else
59 | color = new Color( parent.backgroundColor )
60 | .alpha( .5 )
61 | .lighten( 15 )
62 | .saturate ( 15 )
63 |
64 | @props =
65 | x: point.x - 4
66 | y: point.y - 4
67 | height: 8
68 | width: 8
69 | borderRadius: 4
70 | backgroundColor: color
71 | opacity: 0
72 |
73 | @animate
74 | opacity: 1
75 | options: { time: .1 }
76 |
77 | @animate
78 | x: point.x - 4 - ( fullWidth )
79 | y: point.y - 4 - ( fullWidth )
80 | height: fullWidth * 2
81 | width: fullWidth * 2
82 | borderRadius: ( fullWidth )
83 | options: { time: .6 }
84 |
85 | hide: =>
86 | @animate
87 | opacity: 0
88 | options: { time: .45 , delay: .1 }
89 |
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/RowItem.coffee:
--------------------------------------------------------------------------------
1 | # 888888ba dP dP
2 | # 88 `8b 88 88
3 | # a88aaaa8P' .d8888b. dP dP dP 88 d8888P .d8888b. 88d8b.d8b.
4 | # 88 `8b. 88' `88 88 88 88 88 88 88ooood8 88'`88'`88
5 | # 88 88 88. .88 88.88b.88' 88 88 88. ... 88 88 88
6 | # dP dP `88888P' 8888P Y8P dP dP `88888P' dP dP dP
7 |
8 | Type = require 'md-components/Type'
9 | { Theme } = require 'md-components/Theme'
10 | { Divider } = require 'md-components/Divider'
11 |
12 |
13 | exports.RowItem = class RowItem extends Layer
14 | constructor: (options = {}) ->
15 |
16 | @_icon = options.icon
17 | @_iconBackgroundColor = options.iconBackgroundColor ? '#777'
18 | @_text = options.text ? 'Row item'
19 | @_row = options.row ? 0
20 | @_y = 32 + (@_row * 48)
21 |
22 | super _.defaults options,
23 | width: Screen.width
24 | y: @_y
25 | height: 48
26 | backgroundColor: null
27 |
28 | @icon = new Layer
29 | name: '.', parent: @
30 | x: 16, y: Align.center
31 | height: 32, width: 32, borderRadius: 16
32 | backgroundColor: @_iconBackgroundColor
33 | image: @_icon
34 |
35 | @labelLayer = new Type.Regular
36 | name: '.', parent: @
37 | x: @icon.maxX + 16, y: Align.center
38 | color: Theme.text.text
39 | text: @_text
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/Select.coffee:
--------------------------------------------------------------------------------
1 | Type = require 'md-components/Type'
2 | { Theme } = require 'md-components/Theme'
3 | { TextField } = require 'md-components/TextField'
4 | { Dropdown } = require 'md-components/Dropdown'
5 | { Icon } = require 'md-components/Icon'
6 |
7 |
8 | # .d88888b dP dP
9 | # 88. "' 88 88
10 | # `Y88888b. .d8888b. 88 .d8888b. .d8888b. d8888P
11 | # `8b 88ooood8 88 88ooood8 88' `"" 88
12 | # d8' .8P 88. ... 88 88. ... 88. ... 88
13 | # Y88888P `88888P' dP `88888P' `88888P' dP
14 | #
15 | #
16 |
17 |
18 | class exports.Select extends TextField
19 | constructor: (options = {}) ->
20 |
21 | @_options = options.options ? ['Select Menu']
22 |
23 | # TODO
24 | # add an explicit width prop to textfield and use this prop instead of useMenuWidth
25 |
26 | useMenuWidth = options.useMenuWidth ? false
27 |
28 | super _.defaults options,
29 | name: 'Downdown Select'
30 | type: 'dropdown'
31 | inputType: 'input'
32 | readOnly: true
33 | clip: false
34 |
35 | @dropdown = new Dropdown
36 | parent: @
37 | x: 0, y: 4
38 | width: if not useMenuWidth then @width
39 | options: @_options
40 |
41 | if useMenuWidth then @width = @dropdown.width
42 |
43 | @dropdown.on "change:selection", (selection) =>
44 | @_input.value = selection
45 | @setValue()
46 |
47 | @dropdown.on "change:isOpen", (isOpen) =>
48 | @focused = isOpen
49 |
50 | showFocused: =>
51 | return if @disabled
52 |
53 | baseY = 0
54 |
55 | if @focused
56 | @bringToFront()
57 |
58 | @animateStop()
59 |
60 | @_app?.focused = @
61 |
62 | if @screenFrame.y + @height > Screen.height - 222
63 | @scrollLayer?.scrollToLayer(@, 0, .45)
64 | else if @screenFrame.y < Screen.height * .15
65 | @scrollLayer?.scrollToLayer(@, 0, .15)
66 |
67 | @labelTextLayer?.animate
68 | y: baseY
69 | fontSize: 12
70 | color: @tint
71 |
72 | @inputLine?.animate
73 | height: 1
74 | backgroundColor: @tint
75 |
76 | else
77 | @animateStop()
78 |
79 | if this.hasTextContent()
80 | @labelTextLayer?.animate
81 | y: baseY
82 | fontSize: 12
83 | color: @labelTextColor
84 | else
85 | @labelTextLayer?.animate
86 | y: 22
87 | fontSize: 16
88 | color: @labelTextColor
89 |
90 | @inputLine?.animate
91 | height: 1
92 | backgroundColor: 'rgba(0, 0, 0, .42)'
93 |
94 | if @_app?.focused is @
95 | @_app?.focused = undefined
96 |
97 | @setPlaceholder()
98 |
99 | @define "focused",
100 | get: -> return @_focused
101 | set: (value) ->
102 | return if @_focused is value
103 | if typeof value isnt 'boolean' then throw 'Focused must be either true or false.'
104 |
105 | @_focused = value
106 |
107 | @emit("change:focused", value, @)
108 |
109 | @showFocused()
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/Slider.coffee:
--------------------------------------------------------------------------------
1 | # .d88888b dP oo dP
2 | # 88. "' 88 88
3 | # `Y88888b. 88 dP .d888b88 .d8888b. 88d888b.
4 | # `8b 88 88 88' `88 88ooood8 88' `88
5 | # d8' .8P 88 88 88. .88 88. ... 88
6 | # Y88888P dP dP `88888P8 `88888P' dP
7 |
8 | { Ripple } = require 'md-components/Ripple'
9 | { Icon } = require 'md-components/Icon'
10 | { Theme } = require 'md-components/Theme'
11 |
12 | exports.Slider = class Slider extends SliderComponent
13 | constructor: (options = {}) ->
14 |
15 | @_notched = options.notched ? false
16 | @_notches = options.notches ? 10
17 | @_notchWidth = undefined
18 |
19 | super _.defaults options,
20 | name: '.', height: 2
21 | backgroundColor: 'rgba(0,0,0,.26)'
22 | min: 0, max: 10
23 | animationOptions: {time: .15}
24 |
25 | @fill.backgroundColor = Theme.primary
26 | @knobSize = 44
27 |
28 | @knob.props =
29 | name: 'Knob'
30 | backgroundColor: null
31 | shadowX: 0
32 | shadowY: 0
33 | shadowBlur: 0
34 | color: Theme.primary
35 |
36 | @knob.draggable.propagateEvents = false
37 |
38 | @thumb = new Layer
39 | name: 'Thumb', parent: @knob
40 | x: Align.center, y: Align.center
41 | height: 12, width: 12, borderRadius: 12
42 | backgroundColor: Theme.primary
43 | animationOptions: {time: .15}
44 |
45 | if @_notched
46 |
47 | @_notchWidth = @width / @_notches
48 |
49 | for i in [0...@_notches]
50 | notch = new Layer
51 | name: '.', parent: @
52 | x: i * @_notchWidth
53 | width: 2, height: 2, borderRadius: 2,
54 | backgroundColor: Theme.colors.primary.text
55 |
56 | notch.placeBehind(@knob)
57 |
58 | @tip = new Layer
59 | name: 'Tip', parent: @knob
60 | x: Align.center, y: -24
61 | width: 26, height: 32
62 | html: ' '
63 | backgroundColor: null, opacity: 0
64 | animationOptions: {time: .15}
65 |
66 | @tipValue = new TextLayer
67 | name: 'Tip Value', parent: @tip
68 | y: 5, width: 26
69 | color: Theme.colors.primary.text
70 | fontSize: 12, fontFamily: 'Roboto', textAlign: 'center'
71 | text: "{value}"
72 |
73 | @tipValue.template = @value
74 |
75 | @onTouchStart @_showNotchedDragging
76 |
77 | @onValueChange ->
78 | @_setNotchedValue()
79 | @_setTipValue()
80 |
81 |
82 | else
83 | @knob.onTouchStart @_showDragging
84 |
85 |
86 | @knob.onTouchEnd @showDefault
87 | @knob.onDragEnd @showDefault
88 | @knob.onDrag @_setThumbColor
89 | @_setThumbColor()
90 |
91 | _roundValue: (number, nearest) ->
92 | return (Math.round(number / nearest) + 1) * nearest
93 |
94 | _setNotchedValue: (value) =>
95 | if @knob.midX % @_notchWidth > 0
96 | @knob.x = @_roundValue(@knob.x, @_notchWidth) - (@knob.width / 2)
97 |
98 | _setTipValue: =>
99 | @tipValue.template = Math.round(@value)
100 | @_setTipColor()
101 |
102 | _setTipColor: =>
103 | color = if @value is @min then 'rgba(190, 190, 190, 1)' else Theme.primary
104 | @tip.html = ' '
105 |
106 | _showNotchedDragging: =>
107 | @_setTipColor()
108 | @thumb.animate {opacity: 0}
109 | @tip.animate {opacity: 1}
110 |
111 | _showDragging: =>
112 | @_setThumbColor()
113 | @thumb.animate {width: 18, height: 18, x: 13, y: 13}
114 |
115 | _setThumbColor: =>
116 | @thumb.backgroundColor = if @value is @min then 'rgba(190, 190, 190, 1)' else Theme.primary
117 |
118 | showDefault: =>
119 | @animateStop()
120 | @_setThumbColor()
121 | @thumb.animate {opacity: 1, width: 12, height: 12, x: 15, y: 15}
122 | if @_notched
123 | @_setTipColor()
124 | @tip.animate {opacity: 0}
125 |
126 |
127 |
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/Snackbar.coffee:
--------------------------------------------------------------------------------
1 | # .d88888b dP dP
2 | # 88. "' 88 88
3 | # `Y88888b. 88d888b. .d8888b. .d8888b. 88 .dP 88d888b. .d8888b. 88d888b.
4 | # `8b 88' `88 88' `88 88' `"" 88888" 88' `88 88' `88 88' `88
5 | # d8' .8P 88 88 88. .88 88. ... 88 `8b. 88. .88 88. .88 88
6 | # Y88888P dP dP `88888P8 `88888P' dP `YP 88Y8888' `88888P8 dP
7 |
8 | Type = require 'md-components/Type'
9 | { Ripple } = require 'md-components/Ripple'
10 | { Theme } = require 'md-components/Theme'
11 | { Button } = require 'md-components/Button'
12 |
13 | class exports.Snackbar extends Layer
14 | constructor: (options = {}) ->
15 |
16 | { app } = require 'md-components/App'
17 | @_app = app
18 |
19 | @_title = options.title ? 'Snackbar'
20 | @_timeout = options.timeout ? 4
21 | @_action = options.action
22 |
23 | super _.defaults options,
24 | name: '.'
25 | y: Screen.maxY
26 | width: Screen.width
27 | clip: true
28 | backgroundColor: Theme.snackbar.backgroundColor
29 | animationOptions: {time: .25}
30 | visible: false
31 |
32 | titleWidth = @width - 48
33 |
34 | if @_action?
35 | @action = new Button
36 | parent: @
37 | x: Align.right(-8), y: 4
38 | color: @_action.color ? Theme.colors.primary.light
39 | text: @_action.title.toUpperCase()
40 | action: @_action.action
41 |
42 | @action.onTap @hide
43 | titleWidth = @action.x - 8 - 24
44 |
45 | @textLabel = new Type.Body1
46 | name: 'Title', parent: @
47 | x: 24, y: 14
48 | width: titleWidth
49 | text: @_title
50 | color: Theme.snackbar.color
51 |
52 | @height = @textLabel.maxY + 14
53 | @action?.y = Align.center
54 |
55 |
56 |
57 | Utils.delay @_timeout, @hide
58 |
59 | @show()
60 |
61 | show: =>
62 | if @_app?
63 | if @_app.snackbar?
64 | @_app.snackbar.hide()
65 | Utils.delay 1, @show
66 | return
67 | else
68 | @_app.snackbar = @
69 | @_app.actionButton?.animate {y: @_app.actionButton.y - @height, options: @animationOptions}
70 |
71 | height = @height
72 |
73 | @y = Screen.height - @_app.footer.height
74 | @height = 0
75 | @visible = true
76 | @animate
77 | y: @y - (height - 1)
78 | height: height
79 | else
80 | @visible = true
81 | @y = Screen.height
82 | @animate {y: Screen.height - @height}
83 |
84 | hide: =>
85 | if @_app?
86 | @_app.snackbar = undefined
87 | @_app.actionButton?.animate {y: @_app.actionButton.y + @height, options: @animationOptions}
88 |
89 | @animate {height: 0, y: @y + @height}
90 | Utils.delay .5, => @destroy()
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/StackView.coffee:
--------------------------------------------------------------------------------
1 | # add stackview to any layer
2 |
3 | class exports.StackView extends ScrollComponent
4 | constructor: (options = {}) ->
5 | showLayers = options.showLayers ? false
6 |
7 | # stack related
8 | @_stack = []
9 | @padding = options.padding ? {
10 | top: 16, right: 16,
11 | bottom: 0, left: 16
12 | stack: 16
13 | }
14 |
15 | super _.defaults options,
16 | name: 'StackView'
17 | size: Screen.size
18 | scrollHorizontal: false
19 | contentInset: { bottom: 16 }
20 |
21 | @content.clip = false
22 | @content.backgroundColor = Screen.backgroundColor
23 | @content.name = if options.showLayers then 'content' else '.'
24 |
25 | # add a layer to the stack
26 | addToStack: (layers = [], position) =>
27 | if not _.isArray(layers) then layers = [layers]
28 | last = _.last(@stack)
29 |
30 | if last?
31 | startY = last.maxY + (@padding.stack ? 0)
32 | else
33 | startY = @padding.top ? 0
34 |
35 | for layer in layers
36 |
37 | if layer.constructor.name is 'Card' then position = 'full'
38 |
39 | layer.props =
40 | parent: @content
41 | x: _.clamp(
42 | @padding.left + layer.x,
43 | @padding.left,
44 | @width - @padding.right - layer.width
45 | )
46 | y: startY
47 |
48 | switch position
49 | when 'full'
50 | layer.width = @width - ( @padding.left + @padding.right )
51 | when 'left'
52 | layer.props =
53 | width: (@width / 2) - @padding.left
54 | x: @padding.left
55 | when 'right'
56 | layer.props =
57 | width: (@width / 2) - @padding.right
58 | x: Align.right(-@padding.right)
59 | when 'center'
60 | layer.x = Align.center
61 |
62 | @stack.push(layer)
63 |
64 | layer.on "change:height", => @moveStack(@)
65 |
66 | @updateContent()
67 |
68 | # pull a layer from the stack
69 | removeFromStack: (layer) =>
70 | _.pull(@stack, layer)
71 |
72 | # stack layers in stack, with optional padding and animation
73 | stackView: (
74 | animate = false,
75 | padding = @padding.stack,
76 | top = @padding.top,
77 | animationOptions = {time: .25}
78 | ) =>
79 |
80 | for layer, i in @stack
81 |
82 | if animate is true
83 | if i is 0 then layer.animate
84 | y: top
85 | options: animationOptions
86 |
87 | else layer.animate
88 | y: @stack[i - 1].maxY + padding
89 | options: animationOptions
90 | else
91 | if i is 0 then layer.y = top
92 | else layer.y = @stack[i - 1].maxY + padding
93 |
94 | @updateContent()
95 |
96 | # move stack when layer height changes
97 | moveStack: (layer) =>
98 | index = _.indexOf(@stack, layer)
99 | for layer, i in @stack
100 | if i > 0 and i > index
101 | layer.y = @stack[i - 1].maxY + @padding.stack
102 |
103 |
104 | # build with page as bound object
105 | build: (func) -> do _.bind(func, @)
106 |
107 | # refresh page
108 | refresh: -> null
109 |
110 | @define "stack",
111 | get: -> return @_stack
112 | set: (layers) ->
113 | layer.destroy() for layer in @stack
114 | @addToStack(layers)
115 |
116 |
117 |
118 |
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/StatusBar.coffee:
--------------------------------------------------------------------------------
1 | # .d88888b dP dP 888888ba
2 | # 88. "' 88 88 88 `8b
3 | # `Y88888b. d8888P .d8888b. d8888P dP dP .d8888b. a88aaaa8P' .d8888b. 88d888b.
4 | # `8b 88 88' `88 88 88 88 Y8ooooo. 88 `8b. 88' `88 88' `88
5 | # d8' .8P 88 88. .88 88 88. .88 88 88 .88 88. .88 88
6 | # Y88888P dP `88888P8 dP `88888P' `88888P' 88888888P `88888P8 dP
7 |
8 | Type = require 'md-components/Type'
9 | { Ripple } = require 'md-components/Ripple'
10 | { Icon } = require 'md-components/Icon'
11 | { Theme } = require 'md-components/Theme'
12 |
13 | exports.StatusBar = class StatusBar extends Layer
14 | constructor: (options = {}) ->
15 |
16 | super _.defaults options,
17 | name: '.'
18 | width: Screen.width, height: 24
19 | backgroundColor: Theme.statusBar.backgroundColor
20 |
21 | @items = new Layer
22 | name: '.', parent: @
23 | width: 100
24 | height: 15
25 | x: Align.right(-8)
26 | y: 5
27 | backgroundColor: null
28 | style:
29 | lineHeight: 0
30 |
31 | @on "change:color", => @setSVG()
32 | @color = '#FFF'
33 |
34 | setSVG: ->
35 | @items.html = """
36 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | 12:30
84 |
85 |
86 |
87 |
88 | """
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/Switch.coffee:
--------------------------------------------------------------------------------
1 |
2 | # .d88888b oo dP dP
3 | # 88. "' 88 88
4 | # `Y88888b. dP dP dP dP d8888P .d8888b. 88d888b.
5 | # `8b 88 88 88 88 88 88' `"" 88' `88
6 | # d8' .8P 88.88b.88' 88 88 88. ... 88 88
7 | # Y88888P 8888P Y8P dP dP `88888P' dP dP
8 |
9 | Type = require 'md-components/Type'
10 | { Ripple } = require 'md-components/Ripple'
11 | { Icon } = require 'md-components/Icon'
12 | { Theme } = require 'md-components/Theme'
13 |
14 | exports.Switch = class Switch extends Layer
15 | constructor: (options = {}) ->
16 |
17 | @_isOn = false
18 |
19 | super _.defaults options,
20 | name: 'Switch'
21 | width: 34, height: 14, borderRadius: 7
22 | color: new Color(Theme.primary).desaturate(100).alpha(.84)
23 | backgroundColor: 'rgba(0,0,0,.54)'
24 | animationOptions: {time: .15}
25 |
26 | @mask = new Layer
27 | name: 'Mask', parent: @
28 | x: -12, y: Align.center
29 | width: 44, height: 44
30 | borderRadius: 20
31 | backgroundColor: null
32 | clip: true
33 | opacity: 1
34 | animationOptions: {time: .15}
35 |
36 | @ripple = new Ripple( @mask, external = true )
37 |
38 | @knob = new Layer
39 | name: 'Knob', parent: @mask
40 | x: Align.center, y: Align.center
41 | width: 20, height: 20, borderRadius: 10
42 | backgroundColor: 'rgba(250, 250, 250, 1)'
43 | shadowY: 2, shadowBlur: 3
44 | animationOptions: {time: .15}
45 |
46 | @onTap -> @isOn = !@isOn
47 |
48 | @define "isOn",
49 | get: -> return @_isOn
50 | set: (bool) ->
51 | return if bool is @_isOn
52 |
53 | @_isOn = bool
54 | @emit("change:isOn", @_isOn, @)
55 | @update()
56 |
57 | update: ->
58 | if @_isOn
59 | @mask.animate {x: Align.right(12)}
60 | @color = Theme.primary
61 | @knob.animate {backgroundColor: Theme.primary}
62 | @animate {backgroundColor: Theme.colors.primary.light}
63 | else
64 | @mask.animate {x: -12}
65 | @color = new Color(Theme.primary).desaturate(100).alpha(.84)
66 | @knob.animate {backgroundColor: 'rgba(250, 250, 250, 1)'}
67 | @animate {backgroundColor: 'rgba(0,0,0,.54)'}
68 |
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/TextArea.coffee:
--------------------------------------------------------------------------------
1 | Type = require 'md-components/Type'
2 | { Theme } = require 'md-components/Theme'
3 | { TextField } = require 'md-components/TextField'
4 |
5 |
6 | # d888888P dP .d888888
7 | # 88 88 d8' 88
8 | # 88 .d8888b. dP. .dP d8888P 88aaaaa88a 88d888b. .d8888b. .d8888b.
9 | # 88 88ooood8 `8bd8' 88 88 88 88' `88 88ooood8 88' `88
10 | # 88 88. ... .d88b. 88 88 88 88 88. ... 88. .88
11 | # dP `88888P' dP' `dP dP 88 88 dP `88888P' `88888P8
12 | #
13 | #
14 |
15 | exports.TextArea = class TextArea extends TextField
16 | constructor: (options = {}) ->
17 |
18 | @_rows = options.rows ? 4
19 |
20 | super _.defaults options,
21 | name: 'Text Area'
22 | width: 300
23 | borderRadius: 4
24 | borderWidth: 2, borderColor: options.tint
25 | padding: {top: 28, bottom: 16, right: 16, left: 16}
26 | clip: true
27 | inputType: 'textarea'
28 |
29 | # Label Text
30 |
31 | @labelTextLayer.props =
32 | x: 16, y: 16
33 |
34 | @helperTextLayer.visible = false
35 |
36 | # Input Line
37 |
38 | @inputLine.destroy()
39 |
40 | # Textarea Element
41 |
42 | @setInputAttribute('rows', @_rows)
43 | @setInputAttribute('resize', @_rows)
44 |
45 | @height = @_input.clientHeight
46 |
47 |
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/Theme.coffee:
--------------------------------------------------------------------------------
1 | # d888888P dP
2 | # 88 88
3 | # 88 88d888b. .d8888b. 88d8b.d8b. .d8888b.
4 | # 88 88' `88 88ooood8 88'`88'`88 88ooood8
5 | # 88 88 88 88. ... 88 88 88 88. ...
6 | # dP dP dP `88888P' dP dP dP `88888P'
7 |
8 |
9 | # When loaded, this module will attempt to create a new theme based on
10 | # the Design Mode template.
11 |
12 | Screen.backgroundColor = '#000'
13 |
14 | exports.modifyColor = modifyColor = (color, h, s, l) ->
15 | clip = _.replace(_.replace(color.toHslString().slice(4, -1), '%', ''), '%', '') .split(', ')
16 |
17 | newColor = new Color(
18 | h: _.parseInt(clip[0]) + h,
19 | s: (_.parseInt(clip[1]) + s)/100,
20 | l: (_.parseInt(clip[2]) + l)/100,
21 | a: 1)
22 |
23 | return newColor
24 |
25 | primaryColor = new Color('#0F6CC8')
26 | primaryTextColor = new Color('#FFFFFF')
27 |
28 | secondaryColor = new Color('#1B9DFF')
29 | secondaryTextColor = new Color('#FFFFFF')
30 |
31 | menuColor = new Color ('#CCCCCC')
32 | menuTextColor = new Color('#000000')
33 |
34 | pageColor = new Color('#FFFFFF')
35 | pageTextColor = new Color('#333333')
36 |
37 | exports.colors = colors =
38 | primary:
39 | main: primaryColor
40 | light: modifyColor(primaryColor, 13, -5, 15)
41 | dark: modifyColor(primaryColor, -1, -7, -12)
42 | text: primaryTextColor
43 |
44 | secondary:
45 | main: secondaryColor
46 | light: modifyColor(secondaryColor, 13, -5, 15)
47 | dark: modifyColor(secondaryColor, -1, -7, -12)
48 | text: secondaryTextColor
49 | menu:
50 | main: menuColor
51 | light: modifyColor(menuColor, 13, -5, 15)
52 | dark: modifyColor(menuColor, -1, -7, -12)
53 | text: menuTextColor
54 | page:
55 | main: pageColor
56 | light: modifyColor(pageColor, 13, -5, 15)
57 | dark: modifyColor(pageColor, -1, -7, -12)
58 | text: pageTextColor
59 |
60 | exports.Theme =
61 | tint: colors.secondary.main
62 | primary: colors.primary.main
63 | secondary: colors.secondary.main
64 | page: colors.page.main
65 | menu: colors.menu.light
66 | colors: colors
67 |
68 | user:
69 | image: undefined
70 |
71 | header:
72 | backgroundColor: colors.primary.main
73 | title: colors.primary.text
74 | icon:
75 | color: colors.primary.text
76 | tabs:
77 | backgroundColor: colors.primary.light
78 | color: colors.primary.text
79 | selector: colors.secondary.main
80 |
81 | statusBar:
82 | image: 'modules/md-images/status_bar.png'
83 | backgroundColor: colors.primary.dark
84 |
85 | bottomNav:
86 | backgroundColor: '#FFFFFF'
87 | shadowY: -2
88 | shadowBlur: 6
89 | shadowColor: 'rgba(0,0,0,.1)'
90 |
91 | navBar:
92 | backgroundColor: '#000000'
93 |
94 | keyboard:
95 | image: 'modules/md-images/keyboard.png'
96 |
97 | footer:
98 | image: 'modules/md-images/nav_bar.png'
99 |
100 | page:
101 | primary:
102 | backgroundColor: colors.page.main
103 | text: colors.page.text
104 | secondary:
105 | backgroundColor: '#F5F5F6'
106 |
107 | menuOverlay:
108 | header:
109 | backgroundColor: colors.secondary.main
110 | icon: colors.secondary.light
111 | text: colors.secondary.text
112 | subheader:
113 | color: colors.menu.text
114 | text: colors.secondary.text
115 | icon: colors.secondary.text
116 | backgroundColor: colors.menu.light
117 | text: colors.menu.text
118 | slider:
119 | knob: colors.secondary.light
120 | fill: colors.secondary.dark
121 |
122 | button:
123 | flat:
124 | backgroundColor: null
125 | color: colors.secondary.main
126 | shadowY: 0
127 | shadowColor: 'rgba(0,0,0,.18)'
128 | shadowBlur: 0
129 |
130 | raised:
131 | backgroundColor: colors.secondary.main
132 | color: colors.secondary.text
133 | shadowY: 2
134 | shadowColor: 'rgba(0,0,0,.18)'
135 | shadowBlur: 6
136 |
137 | fab:
138 | backgroundColor: colors.secondary.main
139 | color: colors.secondary.text
140 |
141 | dialog:
142 | backgroundColor:'#FAFAFA'
143 |
144 | divider:
145 | backgroundColor: 'rgba(0,0,0,.12)'
146 |
147 | text:
148 | primary: colors.primary.text
149 | secondary: colors.secondary.text
150 |
151 | table:
152 | backgroundColor: '#FFFFFF'
153 | text: colors.primary.text
154 | checkBox:
155 | backgroundColor: null
156 | borderColor: '#D3D3D3'
157 | selected:
158 | backgroundColor: colors.secondary.main
159 | text: colors.primary.text
160 | checkBox:
161 | backgroundColor: colors.secondary.dark
162 | borderColor: null
163 | snackbar:
164 | backgroundColor: 'rgba(51, 51, 51, 1)'
165 | color: 'rgba(255, 255, 255, 1)'
166 |
167 | toast:
168 | backgroundColor: 'rgba(51, 51, 51, 1)'
169 | color: 'rgba(255, 255, 255, 1)'
170 |
171 | slider:
172 | knob: colors.primary.light
173 | fill: colors.primary.dark
174 |
175 | card:
176 | header: colors.secondary.dark
177 |
178 | color_pallete?.destroy()
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/Tile.coffee:
--------------------------------------------------------------------------------
1 | # d888888P oo dP
2 | # 88 88
3 | # 88 dP 88 .d8888b.
4 | # 88 88 88 88ooood8
5 | # 88 88 88 88. ...
6 | # dP dP dP `88888P'
7 |
8 | Type = require 'md-components/Type'
9 | { Ripple } = require 'md-components/Ripple'
10 | { Icon } = require 'md-components/Icon'
11 | { Theme } = require 'md-components/Theme'
12 |
13 | exports.Tile = Tile = class Tile extends Layer
14 | constructor: (options = {}) ->
15 |
16 | @_header = options.header ? false
17 | @_footer = options.footer ? false
18 | @_action = options.action ? -> null
19 | @_headerAction = options.headerAction ? -> null
20 | @_footerAction = options.footerAction ? -> null
21 |
22 | if @_header and @_footer then throw 'Tile cannot have both a header and a footer.'
23 |
24 | @_icon = options.icon
25 | @gridList = options.gridList # ? throw 'Tile needs a grid property.'
26 |
27 | super _.defaults options,
28 | name: '.', parent: @gridList
29 | width: @gridList.tileWidth
30 | height: @gridList.tileHeight
31 | animationOptions: {time: .3}
32 |
33 | @onTouchStart (event) ->
34 | if @gridList.parent?.parent?.content and @gridList.parent?.parent?.isMoving is false
35 | Ripple(@, event.point, @header, options.RippleColor ? 'rgba(0,0,0,.1)')
36 |
37 | @onTap @_action
38 | @onTap (event) -> event.stopPropagation()
39 |
40 | if @_header or @_footer
41 | @header = new Layer
42 | name: '.', parent: @
43 | y: if @_footer then Align.bottom()
44 | width: @width
45 | height: if options.support then 68 else 48
46 | backgroundColor: options.backgroundColor ? 'rgba(0,0,0,.5)'
47 |
48 | @header.onTouchStart (event) -> Ripple(@, event.point, @title)
49 |
50 | if @_footer then @header.onTap @_footerAction
51 | else @header.onTap @_headerAction
52 |
53 | @header.onTap (event) -> event.stopPropagation()
54 |
55 | if options.title
56 | @header.title = new Type.Regular
57 | name: '.', parent: @header
58 | x: 8, y: if options.support then 12 else Align.center()
59 | color: @color
60 | text: options.title ? 'Two Line'
61 |
62 | if options.support
63 | @header.support = new TextLayer
64 | name: '.', parent: @header
65 | x: 8, y: 35
66 | fontSize: 12
67 | fontFamily: 'Roboto'
68 | color: @color
69 | text: options.support ? 'Support text'
70 |
71 | if options.icon
72 | @header.icon = new Icon
73 | name: '.', parent: @header
74 | x: Align.right(-12), y: if options.support then 20 else Align.center()
75 | icon: options.icon
76 | color: @color
77 |
78 | @i = undefined
79 | @gridList.addTile(@)
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/Toast.coffee:
--------------------------------------------------------------------------------
1 | # d888888P dP
2 | # 88 88
3 | # 88 .d8888b. .d8888b. .d8888b. d8888P
4 | # 88 88' `88 88' `88 Y8ooooo. 88
5 | # 88 88. .88 88. .88 88 88
6 | # dP `88888P' `88888P8 `88888P' dP
7 |
8 | Type = require 'md-components/Type'
9 | { Ripple } = require 'md-components/Ripple'
10 | { Theme } = require 'md-components/Theme'
11 | { Button } = require 'md-components/Button'
12 |
13 | # currently identical to snackbar
14 |
15 | class exports.Toast extends Layer
16 | constructor: (options = {}) ->
17 |
18 | { app } = require 'md-components/App'
19 | @_app = app
20 |
21 | @_title = options.title ? 'Toast'
22 | @_timeout = options.timeout ? 4
23 | @_action = options.action
24 |
25 | super _.defaults options,
26 | name: '.'
27 | y: Screen.maxY
28 | width: Screen.width
29 | clip: true
30 | backgroundColor: Theme.toast.backgroundColor
31 | animationOptions: {time: .25}
32 | visible: false
33 |
34 | titleWidth = @width - 48
35 |
36 | if @_action?
37 | @action = new Button
38 | parent: @
39 | x: Align.right(-8), y: 4
40 | color: @_action.color ? Theme.colors.primary.light
41 | text: @_action.title.toUpperCase()
42 | action: @_action.action
43 |
44 | @action.onTap @hide
45 | titleWidth = @action.x - 8 - 24
46 |
47 | @textLabel = new Type.Body1
48 | name: 'Title', parent: @
49 | x: 24, y: 14
50 | width: titleWidth
51 | text: @_title
52 | color: Theme.toast.color
53 |
54 | @height = @textLabel.maxY + 14
55 | @action?.y = Align.center
56 |
57 |
58 |
59 | Utils.delay @_timeout, @hide
60 |
61 | @show()
62 |
63 | show: =>
64 | if @_app?
65 | if @_app.toast?
66 | @_app.toast.hide()
67 | Utils.delay 1, @show
68 | return
69 | else
70 | @_app.toast = @
71 | @_app.actionButton?.animate {y: @_app.actionButton.y - @height, options: @animationOptions}
72 |
73 | height = @height
74 |
75 | @y = Screen.height - @_app.footer.height
76 | @height = 0
77 | @visible = true
78 | @animate
79 | y: @y - (height - 1)
80 | height: height
81 | else
82 | @visible = true
83 | @y = Screen.height
84 | @animate {y: Screen.height - @height}
85 |
86 | hide: =>
87 | if @_app?
88 | @_app.toast = undefined
89 | @_app.actionButton?.animate {y: @_app.actionButton.y + @height, options: @animationOptions}
90 |
91 | @animate {height: 0, y: @y + @height}
92 | Utils.delay .5, => @destroy()
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/Type.coffee:
--------------------------------------------------------------------------------
1 | Theme = require 'md-components/Theme'
2 |
3 | # d888888P dP
4 | # 88 88
5 | # 88 dP dP 88d888b. .d8888b. .d8888b. 88d888b. .d8888b. 88d888b. 88d888b. dP dP
6 | # 88 88 88 88' `88 88' `88 88' `88 88' `88 88' `88 88' `88 88' `88 88 88
7 | # 88 88. .88 88. .88 88. .88 88. .88 88 88. .88 88. .88 88 88 88. .88
8 | # dP `8888P88 88Y888P' `88888P' `8888P88 dP `88888P8 88Y888P' dP dP `8888P88
9 | # .88 88 .88 88 .88
10 | # d8888P dP d8888P dP d8888P
11 |
12 | Utils.insertCSS(
13 | """
14 | @font-face {
15 | font-family: "Roboto";
16 | src: url("modules/md-fonts/Roboto-Regular.ttf");
17 | """)
18 |
19 | class exports.Headline extends TextLayer
20 | constructor: (options) ->
21 | super _.defaults options,
22 | name: '.'
23 | fontFamily: 'Roboto'
24 | fontSize: 24
25 | fontWeight: 400
26 | lineHeight: 1.3
27 | color: 'rgba(0,0,0,.87)'
28 |
29 | class exports.Subhead extends TextLayer
30 | constructor: (options) ->
31 | super _.defaults options,
32 | name: '.'
33 | fontFamily: 'Roboto'
34 | fontSize: 16
35 | fontWeight: 400,
36 | lineHeight: 1.5,
37 | color: 'rgba(0,0,0,.54)'
38 |
39 | class exports.Title extends TextLayer
40 | constructor: (options) ->
41 | super _.defaults options,
42 | name: '.'
43 | fontFamily: 'Roboto'
44 | fontSize: 20
45 | fontWeight: 500
46 | lineHeight: 1.3
47 | color: 'rgba(0,0,0,.87)'
48 | class exports.Regular extends TextLayer
49 | constructor: (options) ->
50 | super _.defaults options,
51 | name: '.'
52 | fontFamily: 'Roboto'
53 | fontSize: 16
54 | fontWeight: 400
55 | lineHeight: 1.3
56 | color: 'rgba(0,0,0,.87)'
57 | class exports.Body2 extends TextLayer
58 | constructor: (options) ->
59 | super _.defaults options,
60 | name: '.'
61 | fontFamily: 'Roboto'
62 | fontSize: 14
63 | fontWeight: 500
64 | lineHeight: 1.3
65 | color: 'rgba(0,0,0,.87)'
66 | class exports.Menu extends TextLayer
67 | constructor: (options) ->
68 | super _.defaults options,
69 | name: '.'
70 | fontFamily: 'Roboto'
71 | fontSize: 14
72 | fontWeight: 500
73 | lineHeight: 1.7
74 | color: 'rgba(0,0,0,.87)'
75 | class exports.Body1 extends TextLayer
76 | constructor: (options) ->
77 | super _.defaults options,
78 | name: '.'
79 | fontFamily: 'Roboto'
80 | fontSize: 14
81 | fontWeight: 400
82 | lineHeight: 1.4
83 | color: 'rgba(0,0,0,.87)'
84 | class exports.Caption extends TextLayer
85 | constructor: (options) ->
86 | super _.defaults options,
87 | name: '.'
88 | fontFamily: 'Roboto'
89 | fontSize: 12
90 | fontWeight: 400
91 | lineHeight: 1.3
92 | color: 'rgba(0,0,0,.54)'
93 | class exports.Button extends TextLayer
94 | constructor: (options) ->
95 | super _.defaults options,
96 | name: '.'
97 | fontFamily: 'Roboto'
98 | fontSize: 14
99 | fontWeight: 500
100 | lineHeight: 1.3
101 | color: '#009688'
102 | letterSpacing: 0.5
103 | padding: {left: 4, right: 4, top: 8, bottom: 0},
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-components/View.coffee:
--------------------------------------------------------------------------------
1 | # dP dP oo
2 | # 88 88
3 | # 88 .8P dP .d8888b. dP dP dP
4 | # 88 d8' 88 88ooood8 88 88 88
5 | # 88 .d8P 88 88. ... 88.88b.88'
6 | # 888888' dP `88888P' 8888P Y8P
7 |
8 | # Works without an app, but will integrate with app if set with options.app.
9 |
10 | { Theme } = require 'md-components/Theme'
11 | { Page } = require 'md-components/Page'
12 |
13 | exports.View = class View extends Page
14 | constructor: (options = {}) ->
15 |
16 | { app } = require 'md-components/App'
17 |
18 | @_icon = options.icon ? 'open-in-new'
19 |
20 | options.title ?= 'New View'
21 | options.icon = 'menu'
22 | options.action = -> app.showMenu()
23 |
24 | super options
25 |
26 | app.addView
27 | title: options.title
28 | icon: @_icon
29 | view: @
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-fonts/Roboto-Black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/modules/md-fonts/Roboto-Black.ttf
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-fonts/Roboto-BlackItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/modules/md-fonts/Roboto-BlackItalic.ttf
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-fonts/Roboto-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/modules/md-fonts/Roboto-Bold.ttf
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-fonts/Roboto-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/modules/md-fonts/Roboto-BoldItalic.ttf
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-fonts/Roboto-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/modules/md-fonts/Roboto-Italic.ttf
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-fonts/Roboto-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/modules/md-fonts/Roboto-Light.ttf
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-fonts/Roboto-LightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/modules/md-fonts/Roboto-LightItalic.ttf
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-fonts/Roboto-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/modules/md-fonts/Roboto-Medium.ttf
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-fonts/Roboto-MediumItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/modules/md-fonts/Roboto-MediumItalic.ttf
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-fonts/Roboto-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/modules/md-fonts/Roboto-Regular.ttf
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-fonts/Roboto-Thin.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/modules/md-fonts/Roboto-Thin.ttf
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-fonts/Roboto-ThinItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/modules/md-fonts/Roboto-ThinItalic.ttf
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-images/Group.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Group
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 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | 12:30
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-images/keyboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/modules/md-images/keyboard.png
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-images/nav_bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/modules/md-images/nav_bar.png
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-images/status_bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-app.framer/modules/md-images/status_bar.png
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md-images/status_bar.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | time
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 | 12:30
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/framer-md-app.framer/modules/md.coffee:
--------------------------------------------------------------------------------
1 |
2 | Framer.Extras.Hints.disable()
3 |
4 |
5 | { ActionButton } = require 'md-components/ActionButton'
6 | { App } = require 'md-components/App'
7 | { BottomNav } = require 'md-components/BottomNav'
8 | { Button } = require 'md-components/Button'
9 | { Card } = require 'md-components/Card'
10 | { Checkbox } = require 'md-components/Checkbox'
11 | { Dialog } = require 'md-components/Dialog'
12 | { Divider } = require 'md-components/Divider'
13 | { Dropdown } = require 'md-components/Dropdown'
14 | { Elevation } = require 'md-components/Elevation'
15 | App = require 'md-components/App'
16 | { GridList } = require 'md-components/GridList'
17 | { Header } = require 'md-components/Header'
18 | { Icon } = require 'md-components/Icon'
19 | { MenuButton } = require 'md-components/MenuButton'
20 | { MenuOverlay } = require 'md-components/MenuOverlay'
21 | { Notification } = require 'md-components/Notification'
22 | { Page } = require 'md-components/Page'
23 | { Radiobox } = require 'md-components/Radiobox'
24 | { Ripple } = require 'md-components/Ripple'
25 | { RowItem } = require 'md-components/RowItem'
26 | { Select } = require 'md-components/Select'
27 | { Slider } = require 'md-components/Slider'
28 | { Snackbar } = require 'md-components/Snackbar'
29 | { StatusBar } = require 'md-components/StatusBar'
30 | { StackView } = require 'md-components/StackView'
31 | { Switch } = require 'md-components/Switch'
32 | { Table } = require 'md-components/Table'
33 | { TableCard } = require 'md-components/TableCard'
34 | { TextArea } = require 'md-components/TextArea'
35 | { TextField } = require 'md-components/TextField'
36 | { Theme } = require 'md-components/Theme'
37 | { Toast } = require 'md-components/Toast'
38 | Type = require 'md-components/Type'
39 | { Tile } = require 'md-components/Tile'
40 | { View } = require 'md-components/View'
41 |
42 | exports.ActionButton = ActionButton
43 | exports.App = App
44 | exports.Button = Button
45 | exports.Card = Card
46 | exports.Checkbox = Checkbox
47 | exports.Dialog = Dialog
48 | exports.Divider = Divider
49 | exports.Dropdown = Dropdown
50 | exports.Elevation = Elevation
51 | exports.App = App.App
52 | exports.app = App.app
53 | exports.GridList = GridList
54 | exports.Header = Header
55 | exports.Icon = Icon
56 | exports.MenuButton = MenuButton
57 | exports.MenuOverlay = MenuOverlay
58 | exports.Notification = Notification
59 | exports.Page = Page
60 | exports.Radiobox = Radiobox
61 | exports.Ripple = Ripple
62 | exports.RowItem = RowItem
63 | exports.Select = Select
64 | exports.Slider = Slider
65 | exports.Snackbar = Snackbar
66 | exports.StackView = StackView
67 | exports.StatusBar = StatusBar
68 | exports.Switch = Switch
69 | exports.Table = Table
70 | exports.TableCard = TableCard
71 | exports.TextArea = TextArea
72 | exports.TextField = TextField
73 | exports.Theme = Theme
74 | exports.Toast = Toast
75 | exports.Tile = Tile
76 | exports.Type = Type
77 | exports.View = View
78 |
79 | exports.Headline = Type.Headline
80 | exports.Subhead = Type.Subhead
81 | exports.Title = Type.Title
82 | exports.Regular = Type.Regular
83 | exports.Menu = Type.Menu
84 | exports.Body1 = Type.Body1
85 | exports.Body2 = Type.Body2
86 | exports.Caption = Type.Caption
87 |
88 | loading_screen?.destroy()
89 | color_pallette?.destroy()
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/framer-md-dev.framer/..social.html.icloud:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/..social.html.icloud
--------------------------------------------------------------------------------
/framer-md-dev.framer/..viewer 2.html.icloud:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/..viewer 2.html.icloud
--------------------------------------------------------------------------------
/framer-md-dev.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 | .app.js
33 | framer/*.old*
34 | framer/.*.hash
35 | framer/backup.coffee
36 | framer/backups/*
37 | framer/manifest.txt
38 | framer/preview.png
39 | framer/social-*x*.png
40 |
--------------------------------------------------------------------------------
/framer-md-dev.framer/app.coffee:
--------------------------------------------------------------------------------
1 | ### Notes / Todo
2 |
3 | REFERENCE:
4 | https://material.io/guidelines/
5 | https://materialdesignicons.com/
6 |
7 | ###
8 |
9 | md = require "md"
10 | Screen.backgroundColor = '#FFF'
11 |
12 | header = new md.Header
13 | icon: 'menu'
14 | title: 'Hello World!'
15 | action: -> print 'hello'
16 |
17 | header.icon = 'star'
18 |
19 | Utils.delay 3, =>
20 | header.setHeader
21 | title: 'whaddup world'
22 | action: -> print 'whaddup'
23 | backgroundColor: 'FF0077'
24 |
25 | # app = new md.App
26 | # name: 'Framer Introduction'
27 |
28 | # ###################################
29 | # Pages
30 |
31 | # refactored:
32 |
33 | # Button
34 | # Notification
35 | # StackView
36 | # Card
37 | # View
38 | # Snackbar
39 | # Toast
40 |
41 |
42 | # to do:
43 |
44 | # Text Inputs
45 | # combine into a single class - wrap everything in a container layer, so that I can adjus height depending on whether label or helpertext exists.
46 |
47 |
48 | # Home
49 |
50 | # home = new md.View
51 | # title: 'Refactoring!'
52 | # icon: 'home'
53 | # showLayers: true
54 | #
55 | # home.build ->
56 | # @addToStack new md.Button
57 | # action: -> new md.Toast
58 | #
59 | # app.showNext(home)
60 |
61 | # myView = new md.View
62 | #
63 | # app.showNext(myView)
64 |
--------------------------------------------------------------------------------
/framer-md-dev.framer/framer/.bookmark:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/framer/.bookmark
--------------------------------------------------------------------------------
/framer-md-dev.framer/framer/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "orientation" : 0,
3 | "updateDelay" : 0.3,
4 | "designModeSelected" : 0,
5 | "cachedDeviceHeight" : 640,
6 | "contentScale" : 1,
7 | "cachedDeviceWidth" : 360,
8 | "fullScreen" : false,
9 | "deviceType" : "google-nexus-5x",
10 | "sharedPrototype" : true,
11 | "propertyPanelToggleStates" : {
12 |
13 | },
14 | "projectId" : "21022926-504E-444C-B827-2ABD14EAC5FE",
15 | "deviceOrientation" : 0,
16 | "selectedHand" : "",
17 | "showBezel" : false,
18 | "foldedCodeRanges" : [
19 |
20 | ],
21 | "deviceScale" : "fit"
22 | }
--------------------------------------------------------------------------------
/framer-md-dev.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":"google-nexus-5x","contentScale":1,"hideBezel":true,"orientation":0};
7 | }
8 | if (window.Framer) {window.Framer.Defaults.DeviceComponent = {"deviceScale":"fit","selectedHand":"","deviceType":"google-nexus-5x","contentScale":1,"hideBezel":true,"orientation":0};
9 | }
10 | window.FramerStudioInfo = {"deviceImagesUrl":"\/_server\/resources\/DeviceImages","documentTitle":"framer-md-dev.framer"};
11 |
12 | Framer.Device = new Framer.DeviceView();
13 | Framer.Device.setupContext();
--------------------------------------------------------------------------------
/framer-md-dev.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(callback) {
60 | CoffeeScript.load("app.coffee", callback)
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(function(){
94 | // CoffeeScript: Framer?.CurrentContext?.emit?("loaded:project")
95 | var context;
96 | if (typeof Framer !== "undefined" && Framer !== null) {
97 | if ((context = Framer.CurrentContext) != null) {
98 | if (typeof context.emit === "function") {
99 | context.emit("loaded:project");
100 | }
101 | }
102 | }
103 | })
104 | }
105 |
106 | init()
107 |
108 | })()
109 |
--------------------------------------------------------------------------------
/framer-md-dev.framer/framer/images/cursor-active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/framer/images/cursor-active.png
--------------------------------------------------------------------------------
/framer-md-dev.framer/framer/images/cursor-active@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/framer/images/cursor-active@2x.png
--------------------------------------------------------------------------------
/framer-md-dev.framer/framer/images/cursor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/framer/images/cursor.png
--------------------------------------------------------------------------------
/framer-md-dev.framer/framer/images/cursor@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/framer/images/cursor@2x.png
--------------------------------------------------------------------------------
/framer-md-dev.framer/framer/images/icon-120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/framer/images/icon-120.png
--------------------------------------------------------------------------------
/framer-md-dev.framer/framer/images/icon-152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/framer/images/icon-152.png
--------------------------------------------------------------------------------
/framer-md-dev.framer/framer/images/icon-180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/framer/images/icon-180.png
--------------------------------------------------------------------------------
/framer-md-dev.framer/framer/images/icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/framer/images/icon-192.png
--------------------------------------------------------------------------------
/framer-md-dev.framer/framer/images/icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/framer/images/icon-76.png
--------------------------------------------------------------------------------
/framer-md-dev.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 | }
--------------------------------------------------------------------------------
/framer-md-dev.framer/framer/version:
--------------------------------------------------------------------------------
1 | 10
--------------------------------------------------------------------------------
/framer-md-dev.framer/images/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/images/.gitkeep
--------------------------------------------------------------------------------
/framer-md-dev.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 |
41 |
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/ActionButton.coffee:
--------------------------------------------------------------------------------
1 | # .d888888 dP oo 888888ba dP dP
2 | # d8' 88 88 88 `8b 88 88
3 | # 88aaaaa88a .d8888b. d8888P dP .d8888b. 88d888b. a88aaaa8P' dP dP d8888P d8888P .d8888b. 88d888b.
4 | # 88 88 88' `"" 88 88 88' `88 88' `88 88 `8b. 88 88 88 88 88' `88 88' `88
5 | # 88 88 88. ... 88 88 88. .88 88 88 88 .88 88. .88 88 88 88. .88 88 88
6 | # 88 88 `88888P' dP dP `88888P' dP dP 88888888P `88888P' dP dP `88888P' dP dP
7 |
8 | { Ripple } = require 'md-components/Ripple'
9 | { Icon } = require 'md-components/Icon'
10 | { Theme } = require 'md-components/Theme'
11 |
12 | exports.ActionButton = class ActionButton extends Layer
13 | constructor: (options = {}) ->
14 |
15 | @_action = options.action ? -> null
16 | @_icon = options.icon ? 'plus'
17 |
18 | { app } = require 'md-components/App'
19 |
20 | super _.defaults options,
21 | name: 'Action Button'
22 | x: Align.right(-16), y: Align.bottom(-17)
23 | width: 64, height: 64, borderRadius: 32
24 | backgroundColor: Theme.fab.backgroundColor
25 | shadowY: 2, shadowBlur: 3
26 | shadowColor: 'rgba(0,0,0,.25)'
27 | animationOptions: {time: .15}
28 |
29 | if app?
30 | @y = Align.bottom(-app.footer.height - 17)
31 | app.actionButton = @
32 |
33 | # icon
34 |
35 | @iconLayer = new Icon
36 | name: '.', parent: @
37 | x: Align.center, y: Align.center
38 | icon: @_icon,
39 | color: Theme.fab.color
40 |
41 | # mask
42 |
43 | @mask = new Layer
44 | parent: @
45 | size: @size
46 | backgroundColor: null
47 | borderRadius: @borderRadius
48 | clip: true
49 | opacity: 1
50 |
51 | @mask.placeBehind @iconLayer
52 | @ripple = new Ripple( @mask, null )
53 |
54 | # events
55 |
56 | @onTouchStart (event) ->
57 | @showTouched()
58 | Utils.delay 1, => @reset()
59 |
60 | @onTouchEnd (event) ->
61 | @_action()
62 | @reset()
63 |
64 | showTouched: ->
65 | @animate {shadowY: 3, shadowSpread: 1}
66 |
67 | reset: ->
68 | @animate
69 | shadowY: 2
70 | shadowSpread: 0
71 |
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/App.coffee:
--------------------------------------------------------------------------------
1 | # .d888888
2 | # d8' 88
3 | # 88aaaaa88a 88d888b. 88d888b.
4 | # 88 88 88' `88 88' `88
5 | # 88 88 88. .88 88. .88
6 | # 88 88 88Y888P' 88Y888P'
7 | # 88 88
8 | # dP dP
9 |
10 | { Header } = require 'md-components/Header'
11 | { BottomNav } = require 'md-components/BottomNav'
12 | { MenuOverlay } = require 'md-components/MenuOverlay'
13 | { Theme } = require 'md-components/Theme'
14 |
15 | exports.app # set by class
16 |
17 | class exports.App extends FlowComponent
18 | constructor: (options = {}) ->
19 | @__constructor = true
20 |
21 | exports.app = @
22 |
23 | @activeInput
24 | @header
25 | @keyboard
26 |
27 | @notifications = []
28 |
29 | super _.defaults options,
30 | name: 'App'
31 |
32 | # Header
33 |
34 | @header = new Header
35 | title: ''
36 | icon: ''
37 |
38 | # Keyboard
39 |
40 | @keyboard = new Layer
41 | name: 'Keyboard'
42 | y: @maxY, image: Theme.keyboard.image
43 | width: @width, height: 222
44 | index: 1000
45 | animationOptions:
46 | time: .25
47 |
48 | @keyboard.onTap @closeKeyboard
49 |
50 | # App Footer
51 |
52 | @footer = new Layer
53 | name: 'Footer'
54 | width: Screen.width, height: 48
55 | image: Theme.footer.image
56 | index: 999
57 | y: Align.bottom()
58 | clip: true
59 |
60 | flash = undefined
61 |
62 | @backButton = new Layer
63 | name: 'Back Button', parent: @footer
64 | x: 56
65 | width: 40, height: 40, borderRadius: 24
66 | opacity: 0, backgroundColor: 'rgba(255, 255, 255, .2)'
67 | animationOptions: {time: .15}
68 |
69 | @backButton.onTapStart =>
70 | flash?.destroy()
71 | flash = @backButton.copy()
72 | flash.ignoreEvents = true
73 | flash.parent = @footer
74 | flash.animate {x: 32, width: 100, y: 0, height: 48, opacity: 1}
75 |
76 | @backButton.onTap =>
77 | flash?.animateStop()
78 | flash?.animate {opacity: 0, options:{time: .5}}
79 | return if @current.constructor.name is 'View'
80 | @showPrevious()
81 |
82 | @menuOverlay = new MenuOverlay
83 | title: @name
84 |
85 | # Transition Events
86 |
87 | @onTransitionStart (prev, next, direction) =>
88 | Utils.delay 0, => @onChange(next)
89 |
90 | # On changing to a new page
91 |
92 | onChange: (next) ->
93 | return if typeof next is 'string'
94 | if !_.includes(['View', 'Page'], next.constructor?.name)
95 | throw 'App only words with Views and Pages.'
96 | return
97 |
98 | @setHeader(next.headerOptions)
99 | next.contentInset.top = @header.maxY + 16
100 |
101 | next.scrollY = 0
102 | next.onLoad()
103 |
104 | # Transitions
105 |
106 | showNextRight: (nav, layerA, layerB, overlay) ->
107 | options = {curve: "spring(300, 35, 0)"}
108 |
109 | transition =
110 | layerA:
111 | show: {options: options, x: 0, y: 0}
112 | hide: {options: options, x: 0 - layerA?.width / 2, y: 0}
113 | layerB:
114 | show: {options: options, x: 0, y: 0}
115 | hide: {options: options, x: layerB.width, y: 0}
116 |
117 | showNextLeft: (nav, layerA, layerB, overlay) ->
118 | options = {curve: "spring(300, 35, 0)"}
119 |
120 | transition =
121 | layerA:
122 | show: {options: options, x: 0, y: 0}
123 | hide: {options: options, x: 0 + layerA?.width / 2, y: 0}
124 | layerB:
125 | show: {options: options, x: 0, y: 0}
126 | hide: {options: options, x: -layerB.width, y: 0}
127 |
128 | # keyboard
129 |
130 | openKeyboard: () =>
131 | @footer.visible = false
132 | return if Utils.isMobile()
133 |
134 | @keyboard.bringToFront()
135 | @animate { y: -@keyboard.height }
136 | @keyboard.animate { y: Screen.height - @keyboard.height }
137 |
138 | closeKeyboard: =>
139 | @footer.visible = true
140 | @animate { y: 0 }
141 | @keyboard.animate { y: Screen.height }
142 |
143 | # menu
144 |
145 | showMenu: ->
146 | @menuOverlay.show()
147 |
148 | hideMenu: ->
149 | @menuOverlay.hide()
150 |
151 | # header
152 |
153 | setHeader: (options = {}) ->
154 | @header.setHeader(options)
155 |
156 | # add view
157 |
158 | addView: (options = {}) ->
159 | @menuOverlay.addLink(options)
160 |
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/BottomNav.coffee:
--------------------------------------------------------------------------------
1 | # 888888ba dP dP 888888ba
2 | # 88 `8b 88 88 88 `8b
3 | # a88aaaa8P' .d8888b. d8888P d8888P .d8888b. 88d8b.d8b. 88 88 .d8888b. dP .dP
4 | # 88 `8b. 88' `88 88 88 88' `88 88'`88'`88 88 88 88' `88 88 d8'
5 | # 88 .88 88. .88 88 88 88. .88 88 88 88 88 88 88. .88 88 .88'
6 | # 88888888P `88888P' dP dP `88888P' dP dP dP dP dP `88888P8 8888P'
7 |
8 | Type = require 'md-components/Type'
9 | { Ripple } = require 'md-components/Ripple'
10 | { Icon } = require 'md-components/Icon'
11 | { Theme } = require 'md-components/Theme'
12 |
13 | exports.BottomNav = class BottomNav extends Layer
14 | constructor: (options = {}) ->
15 |
16 | @_destinations = options.destinations ? throw 'Needs at least one destination.'
17 | @_items = []
18 | @_initialDestination = options.initialDestination ? undefined
19 | # destination should be: [{name: string, icon: iconString, action: function}]
20 | @_activeDestination = @_initialDestination ? @_items[0]
21 | @_app = options.app
22 | @view = options.view
23 |
24 | super _.defaults options,
25 | name: 'Bottom Nav'
26 | y: Align.bottom
27 | width: Screen.width, height: 56
28 | backgroundColor: Theme.bottomNav.backgroundColor
29 | shadowY: Theme.bottomNav.shadowY
30 | shadowBlur: Theme.bottomNav.shadowBlur
31 | shadowColor: Theme.bottomNav.shadowColor
32 | clip: true
33 |
34 | for destination, i in @_destinations
35 |
36 | item = new Layer
37 | name: '.', parent: @
38 | x: @width/@_destinations.length * i
39 | width: @width/@_destinations.length, height: @height
40 | color: Theme.primary
41 | backgroundColor: null
42 |
43 | nav = @
44 |
45 | do _.bind( ->
46 |
47 | @mask = new Layer
48 | parent: @
49 | x: Align.center, y: Align.center()
50 | height: @height * 1.72
51 | width: @height * 1.7
52 | borderRadius: @height
53 | backgroundColor: null
54 | clip: true
55 | opacity: 1
56 |
57 | @ripple = new Ripple( @mask , external = true, undefined, events = false)
58 |
59 | @iconLayer = new Icon
60 | name: '.', parent: @
61 | x: Align.center, y: Align.center(-8)
62 | icon: destination.icon
63 | animationOptions: {time: .15}
64 |
65 | @labelLayer = new Type.Caption
66 | name: '.', parent: @
67 | x: Align.center, y: Align.center(14)
68 | width: @width,
69 | textAlign: 'center'
70 | text: destination.title
71 | animationOptions: {time: .15}
72 |
73 | # set events on entire item
74 | @onTapStart ( event ) => @ripple.show( event.point )
75 | @onTapEnd @ripple.hide
76 | @onPanEnd @ripple.hide
77 |
78 | @view = destination.view
79 |
80 | @onTap -> nav._app.changeView(@view)
81 |
82 | , item)
83 |
84 | @_items.push(item)
85 |
86 | @showActive(@_items[0])
87 |
88 | @define "activeDestination",
89 | get: -> return @_activeDestination
90 | set: (destination) ->
91 | return if destination is @_activeDestination
92 | @_activeDestination = destination
93 |
94 | @showActive(@_activeDestination)
95 |
96 | @_app.changeView(@_activeDestination.view)
97 |
98 | showActive: (item) ->
99 | item.labelLayer.animate {color: Theme.primary, opacity: 1}
100 | item.iconLayer.color = Theme.primary
101 |
102 | for sib in item.siblings
103 | sib.labelLayer.animate {color: '#777'}
104 | sib.iconLayer.color = '#777'
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/Button.coffee:
--------------------------------------------------------------------------------
1 | # 888888ba dP dP
2 | # 88 `8b 88 88
3 | # a88aaaa8P' dP dP d8888P d8888P .d8888b. 88d888b.
4 | # 88 `8b. 88 88 88 88 88' `88 88' `88
5 | # 88 .88 88. .88 88 88 88. .88 88 88
6 | # 88888888P `88888P' dP dP `88888P' dP dP
7 |
8 |
9 | Type = require 'md-components/Type'
10 | { Ripple } = require 'md-components/Ripple'
11 | { Icon } = require 'md-components/Icon'
12 | { Theme } = require 'md-components/Theme'
13 |
14 | exports.Button = class Button extends Layer
15 | constructor: (options = {}) ->
16 | @__constructor = true
17 | showLayers = options.showLayers
18 |
19 | # if an icon is passed in, return an icon class and bail
20 | if options.icon
21 | options.action ?= -> null
22 | options.color ?= Theme.colors.primary.main
23 | return new Icon(options)
24 |
25 | @_disabled
26 | @_action
27 | @_raised
28 | @_type
29 | @_base
30 | @_labelText
31 |
32 | @_explicitWidth = options.width?
33 | @_startX = options.x
34 |
35 | @_type = options.type ? if options.raised then 'raised' else 'flat'
36 |
37 | # properties by type
38 | switch @_type
39 | when 'flat'
40 | @_base =
41 | name: 'Flat Button'
42 | height: 36
43 | width: 999
44 | borderRadius: 2
45 | backgroundColor: null
46 | color: Theme.colors.secondary.main
47 | shadowY: 0
48 | shadowColor: 'rgba(0,0,0,.26)'
49 | shadowBlur: 0
50 | animationOptions: {time: .15}
51 | when 'raised'
52 | @_base =
53 | name: 'Raised Button'
54 | height: 36
55 | width: 999
56 | borderRadius: 2
57 | backgroundColor: Theme.colors.secondary.main
58 | color: Theme.colors.secondary.text
59 | shadowY: 2
60 | shadowColor: 'rgba(0,0,0,.26)'
61 | shadowBlur: 4
62 | animationOptions: {time: .15}
63 |
64 | super _.defaults options, @_base
65 |
66 | # text label
67 | @labelLayer = new Type.Button
68 | name: if showLayers then 'Label' else '.'
69 | parent: @
70 | height: 36
71 | text: '{labelText}'
72 | textTransform: 'uppercase'
73 | textAlign: 'center'
74 | color: @color
75 | animationOptions: {time: .15}
76 | padding:
77 | left: 16.5, right: 16.5
78 | top: 9, bottom: 11
79 |
80 | # events
81 | @onTapStart ->
82 | @showRaised()
83 |
84 | @onTapEnd ->
85 | return if @_disabled
86 | @_action()
87 | @refresh()
88 |
89 | @labelLayer.on "change:width", =>
90 | return if @_explicitWidth
91 | @width = @labelLayer.width
92 | @_base.width = @labelLayer.width
93 | @setRipple()
94 |
95 | @on "change:width", =>
96 | return if @width is @labelLayer.width
97 | @labelLayer.width = @width
98 | @setRipple()
99 |
100 | # set props
101 | @action = options.action
102 | @disabled = options.disabled ? false
103 |
104 | delete @__constructor
105 |
106 | @text = options.text ? 'button'
107 |
108 | showRaised: =>
109 | return if @disabled
110 | return if @type isnt 'raised'
111 | @animate {shadowY: 5, shadowBlur: 8}
112 |
113 | setRipple: ->
114 | @mask?.destroy()
115 |
116 | @mask = new Layer
117 | parent: @
118 | size: @size
119 | backgroundColor: null
120 | borderRadius: 2
121 | clip: true
122 | opacity: 1
123 |
124 | @mask.placeBehind @labelLayer
125 |
126 | switch @type
127 | when 'flat'
128 | @ripple = new Ripple( @mask, null, colorOverride = 'rgba(0,0,0,.05)' )
129 | when 'raised'
130 | @ripple = new Ripple( @mask, null )
131 |
132 | refresh: =>
133 | @animateStop()
134 | if @disabled
135 | if @type is 'raised'
136 | @animate
137 | backgroundColor: 'rgba(0,0,0,.12)'
138 | shadowY: 0
139 | shadowBlur: 0
140 | @labelLayer.animate
141 | color: 'rgba(0,0,0,.26)'
142 | else
143 | @animate @_base
144 | @labelLayer.animate
145 | color: @_base.color
146 |
147 | @define "type",
148 | get: -> return @_type
149 |
150 | @define "disabled",
151 | get: -> return @_disabled
152 | set: (bool = false) ->
153 | return if bool is @_disabled
154 | @_disabled = bool
155 |
156 | @emit("change:disabled", @_disabled, @)
157 |
158 | return if @__constructor
159 | @refresh()
160 |
161 | @define "action",
162 | get: -> return @_action
163 | set: (func = -> null) ->
164 | return if func is @_action
165 | @_action = func
166 |
167 | @define "text",
168 | get: -> return @_labelText
169 | set: (text = '') ->
170 | return if @__constructor
171 | @_labelText = text
172 |
173 | @labelLayer.visible = text.length > 0
174 | @labelLayer.template = text
175 |
176 | @x = @_startX
177 | @refresh()
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/Checkbox.coffee:
--------------------------------------------------------------------------------
1 | # a88888b. dP dP dP
2 | # d8' `88 88 88 88
3 | # 88 88d888b. .d8888b. .d8888b. 88 .dP 88d888b. .d8888b. dP. .dP
4 | # 88 88' `88 88ooood8 88' `"" 88888" 88' `88 88' `88 `8bd8'
5 | # Y8. .88 88 88 88. ... 88. ... 88 `8b. 88. .88 88. .88 .d88b.
6 | # Y88888P' dP dP `88888P' `88888P' dP `YP 88Y8888' `88888P' dP' `dP
7 |
8 | { Icon } = require 'md-components/Icon'
9 | { Theme } = require 'md-components/Theme'
10 |
11 | exports.Checkbox = CheckBox = class Checkbox extends Icon
12 | constructor: (options = {}) ->
13 |
14 | @_group = undefined
15 |
16 | super _.defaults options,
17 | name: '.'
18 | animationOptions: {time: .15}
19 | icon: 'checkbox-blank-outline'
20 | color: Theme.primary
21 | toggle: true
22 | action: -> null
23 |
24 | @on "change:isOn", @updateIcon
25 |
26 | updateIcon: =>
27 | @icon = if @isOn then 'checkbox-marked' else 'checkbox-blank-outline'
28 |
29 | @define "group",
30 | get: -> return @_group
31 | set: (array) ->
32 | return if array is @_group
33 | @_group = array
34 |
35 | # add this checkbox to the group array if not in it already
36 | if not _.includes(@_group, @) then @_group.push(@)
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/Dialog.coffee:
--------------------------------------------------------------------------------
1 | # 888888ba oo dP
2 | # 88 `8b 88
3 | # 88 88 dP .d8888b. 88 .d8888b. .d8888b.
4 | # 88 88 88 88' `88 88 88' `88 88' `88
5 | # 88 .8P 88 88. .88 88 88. .88 88. .88
6 | # 8888888P dP `88888P8 dP `88888P' `8888P88
7 | # .88
8 | # d8888P
9 |
10 | Type = require 'md-components/Type'
11 | { Icon } = require 'md-components/Icon'
12 | { Theme } = require 'md-components/Theme'
13 | { Button } = require 'md-components/Button'
14 |
15 | # simplify: create an actions array, with text, action, color?
16 | # this needs to be standardized across apis
17 |
18 | exports.Dialog = class Dialog extends Layer
19 | constructor: (options = {}) ->
20 |
21 | showLayers = options.showLayers ? false
22 |
23 | @_title = options.title ? 'Default Title'
24 | @_body = options.body ? 'Body text goes here.'
25 | @_acceptText = options.acceptText ? 'confirm'
26 | @_acceptAction = options.acceptAction ? -> null
27 | @_declineText = options.declineText ? ''
28 | @_declineAction = options.declineAction ? -> null
29 |
30 | super _.defaults options,
31 | name: if showLayers then 'Dialog' else '.'
32 | size: Screen.size
33 | backgroundColor: 'rgba(0, 0, 0, .5)'
34 | opacity: 0
35 |
36 | @on Events.Tap, (event) -> event.stopPropagation()
37 |
38 | @container = new Layer
39 | name: 'container', parent: @
40 | x: Align.center
41 | height: 128, width: Screen.width - 80
42 | backgroundColor: Theme.dialog.backgroundColor
43 | shadowX: 0, shadowY: 7, shadowBlur: 30
44 | opacity: 0
45 | shadowColor: 'rgba(0,0,0,.3)'
46 |
47 | @title = new Type.Title
48 | name: '.', parent: @container
49 | x: 24, y: 20
50 | fontSize: 16, fontWeight: 500, color: Theme.text.title
51 | text: @_title
52 |
53 | @body = new Type.Subhead
54 | name: 'body', parent: @container
55 | x: 24, y: 52
56 | width: @container.width - 42
57 | text: @_body
58 |
59 | buttonsY = if @_body is '' then 128 else @body.maxY + 16
60 |
61 | @accept = new Button
62 | name: '.', parent: @container
63 | x: Align.right(-16), y: buttonsY
64 | text: @_acceptText.toUpperCase()
65 | action: @_acceptAction
66 |
67 | if @_declineText isnt ''
68 | @decline = new Button
69 | name: '.', parent: @container
70 | x: 0, y: buttonsY
71 | text: @_declineText.toUpperCase()
72 | action: @_declineAction
73 |
74 | # set positions
75 | @container.height = @accept.maxY + 12
76 | @decline?.maxX = @accept.x - 16
77 | @container.y = Align.center(16)
78 |
79 | # add close actions to confirm and cancel
80 | for button in [@accept, @decline]
81 | button?.onTap => Utils.delay .25, @close
82 |
83 | # ON LOAD
84 | @open()
85 |
86 | open: =>
87 | @animate
88 | opacity: 1
89 | options:
90 | time: .25
91 |
92 | @container.animate
93 | opacity: 1
94 | options:
95 | time: .25
96 | delay: .15
97 |
98 | close: =>
99 | @container.animate
100 | opacity: 0
101 | options:
102 | time: .25
103 |
104 | @animate
105 | opacity: 0
106 | options:
107 | time: .25
108 |
109 | Utils.delay .5, => @destroy()
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/Divider.coffee:
--------------------------------------------------------------------------------
1 | # 888888ba oo oo dP
2 | # 88 `8b 88
3 | # 88 88 dP dP .dP dP .d888b88 .d8888b. 88d888b.
4 | # 88 88 88 88 d8' 88 88' `88 88ooood8 88' `88
5 | # 88 .8P 88 88 .88' 88 88. .88 88. ... 88
6 | # 8888888P dP 8888P' dP `88888P8 `88888P' dP
7 |
8 | Type = require 'md-components/Type'
9 | { Theme } = require 'md-components/Theme'
10 |
11 | class exports.Divider extends Layer
12 | constructor: (options = {}) ->
13 |
14 | width = 0 # check if parent is a View and adjust to padding
15 | showLayers = options.showLayers
16 |
17 | @_labelText = undefined
18 | @_backgroundColor = options.backgroundColor
19 |
20 | options.backgroundColor = Theme.divider.backgroundColor
21 |
22 | super _.defaults options,
23 | name: if showLayers then 'Divider' else '.'
24 | width: options.parent?.width ? 200, height: 1,
25 | backgroundColor: Theme.divider.backgroundColor
26 |
27 | @labelLayer = new Type.Caption
28 | name: if showLayers then 'Label' else '.'
29 | parent: @
30 | x: Align.center
31 | y: Align.center
32 | padding: {left: 16, right: 16}
33 | textAlign: 'center'
34 | textTransform: 'uppercase'
35 | text: '{labelText}'
36 | visible: false
37 | backgroundColor: @_backgroundColor
38 |
39 | @text = options.text
40 |
41 | @define "text",
42 | get: -> return @_labelText
43 | set: (text) ->
44 | if not text? then text = ''
45 | @_labelText = text
46 |
47 | @labelLayer?.visible = @text.length > 0
48 | @labelLayer?.template = @text
49 | @labelLayer?.x = Align.center
50 |
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/Elevation.coffee:
--------------------------------------------------------------------------------
1 | # 88888888b dP dP oo
2 | # 88 88 88
3 | # a88aaaa 88 .d8888b. dP .dP .d8888b. d8888P dP .d8888b. 88d888b.
4 | # 88 88 88ooood8 88 d8' 88' `88 88 88 88' `88 88' `88
5 | # 88 88 88. ... 88 .88' 88. .88 88 88 88. .88 88 88
6 | # 88888888P dP `88888P' 8888P' `88888P8 dP dP `88888P' dP dP
7 |
8 | # thanks to @ma_rylou
9 |
10 | exports.Elevation = (layer, elevationnumber = 0, animate = true, options = {time: .2, curve: 'ease'}) ->
11 |
12 | # Error handling
13 | if typeof elevationnumber isnt "number"
14 | throw Error "Elevation must be a number."
15 |
16 | # Clamp elevation number to between 0 and 24
17 | elevationnumber = _.clamp(elevationnumber, 0, 24)
18 |
19 | props =
20 | shadowSpread: 0
21 | shadowX: 0
22 | shadowY: elevationnumber
23 | shadowBlur: elevationnumber
24 | shadowColor:"rgba(0, 0, 0, 0.24)"
25 |
26 | animProps = _.merge(props, {options: options})
27 |
28 | #target layer
29 | if animate then layer.animate animProps
30 | else layer.props = props
31 |
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/GridList.coffee:
--------------------------------------------------------------------------------
1 |
2 | # .88888. oo dP dP oo dP
3 | # d8' `88 88 88 88
4 | # 88 88d888b. dP .d888b88 88 dP .d8888b. d8888P
5 | # 88 YP88 88' `88 88 88' `88 88 88 Y8ooooo. 88
6 | # Y8. .88 88 88 88. .88 88 88 88 88
7 | # `88888' dP dP `88888P8 88888888P dP `88888P' dP
8 |
9 | Type = require 'md-components/Type'
10 | { Ripple } = require 'md-components/Ripple'
11 | { Icon } = require 'md-components/Icon'
12 | { Theme } = require 'md-components/Theme'
13 |
14 | exports.GridList = class GridList extends Layer
15 | constructor: (options = {}) ->
16 |
17 | @_columns = options.columns ? 2
18 |
19 | super _.defaults options,
20 | name: '.'
21 | width: Screen.width
22 | backgroundColor: null
23 |
24 | @tiles = []
25 | @tileWidth = (@width - 24) / @_columns
26 | @tileHeight = options.tileHeight ? Screen.width / @_columns
27 |
28 | addTile: (tile) ->
29 | tile.i = @tiles.length
30 | tile.gridList = @
31 | @tiles.push(tile)
32 |
33 | tile.x = 8 + (@tileWidth + 8) * (tile.i % @_columns)
34 | tile.y = 8 + (@tileHeight + 8) * Math.floor(tile.i / @_columns)
35 |
36 | @height = _.last(@tiles).maxY
37 |
38 | if @parent?.parent?.content? then @parent.parent.updateContent()
39 |
40 | removeTile: (tile) ->
41 | _.pull(@tiles, tile)
42 | tile.destroy()
43 | @repositionTiles()
44 |
45 | repositionTiles: ->
46 | for tile, i in @tiles
47 | tile.i = i
48 | tile.animate
49 | x: 8 + (@tileWidth + 8) * (tile.i % @_columns)
50 | y: 8 + (@tileHeight + 8) * Math.floor(tile.i / @_columns)
51 | @height = _.last(@tiles).maxY
52 |
53 | if @parent?.parent?.content? then @parent.parent.updateContent()
54 |
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/Header.coffee:
--------------------------------------------------------------------------------
1 | # dP dP dP
2 | # 88 88 88
3 | # 88aaaaa88a .d8888b. .d8888b. .d888b88 .d8888b. 88d888b.
4 | # 88 88 88ooood8 88' `88 88' `88 88ooood8 88' `88
5 | # 88 88 88. ... 88. .88 88. .88 88. ... 88
6 | # dP dP `88888P' `88888P8 `88888P8 `88888P' dP
7 |
8 | Type = require 'md-components/Type'
9 | { Icon } = require 'md-components/Icon'
10 | { Theme } = require 'md-components/Theme'
11 | { modifyColor } = require 'md-components/Theme'
12 | { StatusBar } = require 'md-components/StatusBar'
13 |
14 | exports.Header = class Header extends Layer
15 | constructor: (options = {}) ->
16 | @__constructor = true
17 |
18 | # properties
19 |
20 | @_title
21 | options.title ?= 'Header'
22 |
23 | @_icon
24 | options.icon ?= 'menu'
25 |
26 | @_action
27 | options.action ?= -> null
28 |
29 | # assign forced options
30 | _.assign options,
31 | width: Screen.width
32 | height: 80
33 | shadowY: 2,
34 | shadowBlur: 3,
35 | shadowColor: 'rgba(0,0,0,.24)'
36 |
37 | # set default options
38 | super _.defaults options,
39 | name: options.title
40 | backgroundColor: Theme.header.backgroundColor ? '#777'
41 | color: Theme.header.title ? '#FFF'
42 |
43 | # title
44 |
45 | @titleLayer = new Type.Title
46 | name: '.', parent: @
47 | x: 72, y: Align.bottom(-14)
48 | color: @color
49 | text: ''
50 |
51 | # icon
52 |
53 | @iconLayer = new Icon
54 | name: '.', parent: @,
55 | x: 12, y: Align.center(12)
56 | icon: options.icon ? 'menu'
57 | color: @color
58 |
59 | # status bar
60 |
61 | @statusBar = new StatusBar
62 | name: '.', parent: @
63 |
64 | # events
65 |
66 | @iconLayer.onTapEnd => @_action()
67 |
68 | @on "change:color", =>
69 | @titleLayer.color = @color
70 | @iconLayer.color = @color
71 | @statusBar.color = @color
72 |
73 | @on "change:backgroundColor", =>
74 | @statusBar.backgroundColor = modifyColor(
75 | @backgroundColor, -1, -7, -12
76 | )
77 |
78 | delete @__constructor
79 |
80 | # set options that require layers
81 |
82 | @title = options.title
83 | @icon = options.icon
84 | @action = options.action
85 |
86 | setHeader: (options = {}) ->
87 |
88 | for layer in [@titleLayer, @iconLayer]
89 | layer.animate {opacity: 0, options: {time: .15}}
90 |
91 | Utils.delay .25, =>
92 |
93 | _.assign(@, options)
94 |
95 | for layer in [@titleLayer, @iconLayer]
96 | layer.animate {opacity: 1, options: {time: .15}}
97 |
98 | @define "title",
99 | get: -> return @_title
100 | set: (titleText) ->
101 | return if @__constructor
102 | @_title = titleText
103 | @titleLayer.text = titleText
104 |
105 | @define "icon",
106 | get: -> return @_icon
107 | set: (iconName) ->
108 | return if @__constructor
109 | @_icon = iconName
110 | @iconLayer.icon = iconName
111 |
112 | @define "action",
113 | get: -> return @_action
114 | set: (action) ->
115 | return if @__constructor
116 | @_action = action
117 |
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/MenuButton.coffee:
--------------------------------------------------------------------------------
1 | # 8888ba.88ba 888888ba dP dP
2 | # 88 `8b `8b 88 `8b 88 88
3 | # 88 88 88 .d8888b. 88d888b. dP dP a88aaaa8P' dP dP d8888P d8888P .d8888b. 88d888b.
4 | # 88 88 88 88ooood8 88' `88 88 88 88 `8b. 88 88 88 88 88' `88 88' `88
5 | # 88 88 88 88. ... 88 88 88. .88 88 .88 88. .88 88 88 88. .88 88 88
6 | # dP dP dP `88888P' dP dP `88888P' 88888888P `88888P' dP dP `88888P' dP dP
7 |
8 | Type = require 'md-components/Type'
9 | { Ripple } = require 'md-components/Ripple'
10 | { Icon } = require 'md-components/Icon'
11 | { Theme } = require 'md-components/Theme'
12 |
13 |
14 | exports.MenuButton = class MenuButton extends Layer
15 | constructor: (options = {}) ->
16 |
17 | { app } = require 'md-components/App'
18 |
19 | @_icon = options.icon ? 'home'
20 | @_text = options.text ? 'Default'
21 | @_action = options.action ? -> null
22 | @_view = options.view
23 | @_app = options.app
24 | @_i = options.i
25 |
26 | super _.defaults options,
27 | height: 48, width: 304
28 | backgroundColor: null
29 |
30 | @iconLayer = new Icon
31 | name: '.', parent: @
32 | y: Align.center
33 | icon: @_icon, color: Theme.menuOverlay.text
34 | action: -> null
35 |
36 | @labelLayer = new Type.Regular
37 | name: 'label', parent: @
38 | x: @iconLayer.maxX + 16
39 | y: Align.center()
40 | color: Theme.menuOverlay.text
41 | text: @_text
42 |
43 | @onTapEnd ->
44 | if @_view?
45 | if @_view.i > @_i
46 | app?.transition(@_view, app.showNextRight)
47 | else
48 | app?.transition(@_view, app.showNextLeft)
49 | Utils.delay .25, => @parent.hide()
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/MenuOverlay.coffee:
--------------------------------------------------------------------------------
1 | # 8888ba.88ba .88888. dP
2 | # 88 `8b `8b d8' `8b 88
3 | # 88 88 88 .d8888b. 88d888b. dP dP 88 88 dP .dP .d8888b. 88d888b. 88 .d8888b. dP dP
4 | # 88 88 88 88ooood8 88' `88 88 88 88 88 88 d8' 88ooood8 88' `88 88 88' `88 88 88
5 | # 88 88 88 88. ... 88 88 88. .88 Y8. .8P 88 .88' 88. ... 88 88 88. .88 88. .88
6 | # dP dP dP `88888P' dP dP `88888P' `8888P' 8888P' `88888P' dP dP `88888P8 `8888P88
7 | # .88
8 | # d8888P
9 |
10 | Type = require 'md-components/Type'
11 | { Ripple } = require 'md-components/Ripple'
12 | { Icon } = require 'md-components/Icon'
13 | { Theme } = require 'md-components/Theme'
14 | { MenuButton } = require 'md-components/MenuButton'
15 |
16 | exports.MenuOverlay = class MenuOverlay extends Layer
17 | constructor: (options = {}) ->
18 |
19 | @links = []
20 | @_title = options.title ? 'Menu'
21 | @_image = options.image ? null
22 | @_app = options.app
23 |
24 |
25 | super _.defaults options,
26 | height: Screen.height
27 | width: 304
28 | visible: false
29 | backgroundColor: Theme.menuOverlay.backgroundColor
30 | animationOptions: {curve: "spring(300, 35, 0)"}
31 |
32 |
33 | @scrim = new Layer
34 | name: '.',
35 | size: Screen.size
36 | backgroundColor: 'rgba(0,0,0,.6)'
37 | opacity: 0
38 | visible: false
39 | animationOptions:
40 | time: .25
41 |
42 | @scrim.onTap => @hide()
43 | @onSwipeLeftEnd => @hide()
44 |
45 | @header = new Layer
46 | name: '.', parent: @
47 | width: @width, height: 173
48 | image: Theme.user.image
49 | backgroundColor: Theme.menuOverlay.header.backgroundColor
50 |
51 | @titleIcon = new Layer
52 | name: '.', parent: @header
53 | x: 16, y: 40
54 | height: 64, width: 64
55 | borderRadius: 32
56 | backgroundColor: Theme.menuOverlay.header.icon
57 |
58 | @subheaderExpand = new Icon
59 | name: '.', parent: @header
60 | x: Align.right(-16)
61 | y: Align.bottom(-16)
62 | icon: 'menu-down'
63 | color: Theme.menuOverlay.subheader.icon
64 |
65 | @subheader = new Type.Body1
66 | name: '.', parent: @header
67 | width: @width
68 | x: 16, y: Align.bottom(-18)
69 | text: @_title
70 | color: Theme.menuOverlay.subheader.text
71 |
72 | show: ->
73 | @bringToFront()
74 | @visible = true
75 | @x = -Screen.width
76 | @animate
77 | x: 0
78 |
79 | @scrim.placeBehind(@)
80 | @scrim.visible = true
81 | @scrim.animate
82 | opacity: 1
83 |
84 | hide: ->
85 | @animate
86 | x: -Screen.width
87 |
88 | @scrim.animate
89 | opacity: 0
90 |
91 | Utils.delay .3, =>
92 | @visible = false
93 | @scrim.visible = false
94 | @sendToBack()
95 | @scrim.sendToBack()
96 |
97 | addLink: (options) ->
98 | lastY = _.last(@links)?.maxY ? 189
99 | @links.push new MenuButton
100 | name: '.', parent: @
101 | x: 16, y: lastY
102 | text: options.title
103 | icon: options.icon
104 | view: options.view
105 |
106 | options.view.i = @links.length
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/Notification.coffee:
--------------------------------------------------------------------------------
1 | # 888888ba dP oo .8888b oo dP oo
2 | # 88 `8b 88 88 " 88
3 | # 88 88 .d8888b. d8888P dP 88aaa dP .d8888b. .d8888b. d8888P dP .d8888b. 88d888b.
4 | # 88 88 88' `88 88 88 88 88 88' `"" 88' `88 88 88 88' `88 88' `88
5 | # 88 88 88. .88 88 88 88 88 88. ... 88. .88 88 88 88. .88 88 88
6 | # dP dP `88888P' dP dP dP dP `88888P' `88888P8 dP dP `88888P' dP dP
7 |
8 | # Notification does not require an app property, however if one is not set then notifications will not app around eachother.
9 |
10 | # TODO: replace action1 and action2 with array of actions.
11 |
12 | Type = require 'md-components/Type'
13 | { Icon } = require 'md-components/Icon'
14 | { Theme } = require 'md-components/Theme'
15 | { Divider } = require 'md-components/Divider'
16 |
17 | exports.Notification = Notification = class Notification extends Layer
18 | constructor: (options = {}) ->
19 |
20 | { app } = require 'md-components/App'
21 |
22 | @_title = options.title ? 'Notification'
23 | @_body = options.body ? 'This is a notification.'
24 | @_icon = options.icon ? undefined
25 | @_iconColor = options.iconColor ? Theme.text.secondary
26 | @_iconBackgroundColor = options.iconBackgroundColor ? Theme.secondary
27 |
28 | @_actions = options.actions ? []
29 |
30 | @_time = options.time ? new Date()
31 | @_timeout = options.timeout ? 5
32 | @_group = app?.notifications ? options.group ? []
33 |
34 | # actions should be:
35 | # {title: 'archive', icon: 'archive', color: '', backgroundColor: ''}
36 |
37 | super _.defaults options,
38 | name: options.name ? '.'
39 | width: Screen.width - 16, borderRadius: 2
40 | x: Align.center
41 | backgroundColor: Theme.dialog.backgroundColor
42 | shadowX: 0, shadowY: 2, shadowBlur: 3
43 | opacity: 0, shadowColor: 'rgba(0,0,0,.3)'
44 | animationOptions: {time: .25}
45 |
46 | @iconLayer = new Layer
47 | name: 'Icon Container'
48 | parent: @
49 | x: 12, y: 12
50 | height: 40, width: 40, borderRadius: 20
51 | backgroundColor: @_iconBackgroundColor
52 |
53 | if @_icon
54 | @icon = new Icon
55 | name: 'Icon'
56 | parent: @iconLayer
57 | x: Align.center, y: Align.center
58 | color: @_iconColor
59 | icon: @_icon
60 |
61 | @title = new Type.Subhead
62 | name: 'Title'
63 | parent: @
64 | x: 64, y: 8
65 | width: @width - 72
66 | color: 'rgba(0,0,0,.87)'
67 | text: @_title
68 |
69 | @body = new Type.Body1
70 | name: 'Body'
71 | parent: @
72 | x: 64, y: @title.maxY
73 | width: @width - 72
74 | text: @_body
75 |
76 | @date = new Type.Caption
77 | name: 'Date'
78 | parent: @
79 | x: Align.right(-9), y: 15
80 | text: @_time.toLocaleTimeString([], hour: "numeric", minute: "2-digit")
81 |
82 | @height = _.clamp(@body.maxY + 13, 64, Infinity)
83 |
84 | # actions
85 |
86 | if @_actions.length > 0
87 |
88 | divider = new Divider
89 | name: 'Divider'
90 | parent: @
91 | x: 64, y: @body.maxY + 11
92 | width: @width - 64
93 |
94 | @height = divider.maxY + 46
95 |
96 | startX = 64
97 | notification = @
98 |
99 | for action in @_actions
100 | actionButton = new Layer
101 | name: 'Action 1', parent: @
102 | x: startX, y: divider.maxY + 11
103 | width: 80, height: 24, backgroundColor: null
104 |
105 | do _.bind( -> # actionButton
106 |
107 | @icon = new Icon
108 | name: 'Icon', parent: @
109 | width: 18, height: 18
110 | color: 'rgba(0,0,0,.54)'
111 | icon: action.icon
112 |
113 | @label = new Type.Caption
114 | name: 'Label', parent: @
115 | x: @icon.maxX + 8
116 | fontSize: 13
117 | textTransform: 'uppercase'
118 | text: action.title
119 |
120 | @width = @label.maxX + 20
121 | startX += @width
122 |
123 | do (action) =>
124 | @onTap =>
125 | notification.close()
126 | if action.action?
127 | Utils.delay .25, _.bind(action.action, notification)
128 |
129 | actionButton)
130 |
131 | # swipes
132 |
133 | @onSwipeLeftEnd => @close('left')
134 | @onSwipeRightEnd => @close('right')
135 |
136 | @open()
137 |
138 | open: =>
139 | startY = _.last(@_group)?.maxY ? 24
140 | startY += 8
141 |
142 | @y = startY
143 |
144 | @animate {opacity: 1}
145 | @_group.push(@)
146 |
147 | Utils.delay @_timeout, => if not @closed then @close('right')
148 |
149 |
150 | close: (direction) =>
151 | _.pull(@_group, @)
152 |
153 | newY = 32
154 | for layer, i in @_group
155 | layer.animate { y: newY }
156 | newY += layer.height + 8
157 |
158 | @animate
159 | x: if direction is 'left' then -Screen.width else Screen.width
160 | opacity: 0
161 |
162 | @closed = true
163 |
164 | Utils.delay .5, => @destroy()
165 |
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/Page.coffee:
--------------------------------------------------------------------------------
1 |
2 | # 888888ba
3 | # 88 `8b
4 | # a88aaaa8P' .d8888b. .d8888b. .d8888b.
5 | # 88 88' `88 88' `88 88ooood8
6 | # 88 88. .88 88. .88 88. ...
7 | # dP `88888P8 `8888P88 `88888P'
8 | # .88
9 | # d8888P
10 |
11 | # simplify header controls
12 | # remove template(?)
13 |
14 | { Theme } = require 'md-components/Theme'
15 | { StackView } = require 'md-components/StackView'
16 |
17 | exports.Page = class Page extends StackView
18 | constructor: (options = {}) ->
19 | @__constructor = true
20 |
21 | { app } = require 'md-components/App'
22 |
23 | options.icon ?= 'arrow-left'
24 | options.action ?= -> app.showPrevious()
25 |
26 | # header
27 | @headerOptions = {
28 | title: options.title
29 | icon: options.icon
30 | action: options.action
31 | actions: options.actions
32 | }
33 |
34 | # on load
35 | @onLoad = options.onLoad ? -> null
36 |
37 | # refresh
38 | @refresh = options.refresh ? -> null
39 |
40 | super _.defaults options,
41 | name: options.title ? 'View'
42 | size: Screen.size
43 | scrollHorizontal: false
44 | backgroundColor: Theme.page.primary.backgroundColor
45 | shadowSpread: 1
46 | shadowColor: 'rgba(0,0,0,.16)'
47 | shadowBlur: 3
48 | contentInset: {top: app.header?.height, bottom: 241}
49 |
50 | @content.backgroundColor = null
51 |
52 | @sendToBack()
53 |
54 | delete @__constructor
55 |
56 | onLoad: -> null
57 | refresh: -> null
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/Radiobox.coffee:
--------------------------------------------------------------------------------
1 | # 888888ba dP oo dP
2 | # 88 `8b 88 88
3 | # a88aaaa8P' .d8888b. .d888b88 dP .d8888b. 88d888b. .d8888b. dP. .dP
4 | # 88 `8b. 88' `88 88' `88 88 88' `88 88' `88 88' `88 `8bd8'
5 | # 88 88 88. .88 88. .88 88 88. .88 88. .88 88. .88 .d88b.
6 | # dP dP `88888P8 `88888P8 dP `88888P' 88Y8888' `88888P' dP' `dP
7 |
8 |
9 | { Icon } = require 'md-components/Icon'
10 | { Theme } = require 'md-components/Theme'
11 |
12 | exports.Radiobox = Radiobox = class Radiobox extends Icon
13 | constructor: (options = {}) ->
14 |
15 | @_group = undefined
16 |
17 | super _.defaults options,
18 | name: '.'
19 | animationOptions: {time: .15}
20 | icon: 'radiobox-blank'
21 | color: Theme.primary
22 | toggle: true
23 | toggleLock: true
24 | action: -> null
25 |
26 | @on "change:isOn", ->
27 | @updateIcon()
28 | @updateSiblings()
29 |
30 | updateIcon: =>
31 | @icon = if @isOn then 'radiobox-marked' else 'radiobox-blank'
32 |
33 | updateSiblings: =>
34 | if @isOn then sib.isOn = false for sib in _.without(@_group, @)
35 |
36 | @define "group",
37 | get: -> return @_group
38 | set: (array) ->
39 | return if array is @_group
40 | @_group = array
41 |
42 | # add this checkbox to the group array if not in it already
43 | if not _.includes(@_group, @) then @_group.push(@)
44 |
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/Ripple.coffee:
--------------------------------------------------------------------------------
1 | # 888888ba oo dP
2 | # 88 `8b 88
3 | # a88aaaa8P' dP 88d888b. 88d888b. 88 .d8888b.
4 | # 88 `8b. 88 88' `88 88' `88 88 88ooood8
5 | # 88 88 88 88. .88 88. .88 88 88. ...
6 | # dP dP dP 88Y888P' 88Y888P' dP `88888P'
7 | # 88 88
8 | # dP dP
9 |
10 | # By default, shows an expanding circle over a layer, clipped to its frame.
11 | # On the layer's touchEnd event, the circle and its mask will disappear.
12 |
13 | # required:
14 | # layer (Layer), the layer over which to show the ripple effect
15 | # point (object), the ripple origin point, usually a onTouchStart's event.point
16 |
17 | # optional:
18 | # placeBehind (Layer), a child of layer behind which the ripple should appear
19 | # color (string or color object), a custom color for the ripple
20 |
21 | class exports.Ripple extends Layer
22 | constructor: (@mask, @external = false, @colorOverride = undefined, events = true) ->
23 |
24 | @mask ?= throw 'Ripple needs a mask layer'
25 |
26 | super
27 | name: 'Ripple', parent: @mask
28 | point: Align.center
29 | backgroundColor: @_color
30 | width: 8, height: 8
31 | opacity: 0
32 |
33 | fullWidth = if @mask.width > @mask.height then @mask.width else @mask.height
34 | @_fullWidth = fullWidth * 2
35 |
36 | if events
37 | @mask.onTapStart ( event ) => @show( event.point )
38 | @mask.onTapEnd @hide
39 | @mask.onPanEnd @hide
40 | @mask.onPan (event, layer) =>
41 | isTooFar = (num) -> Math.abs(num) >= 24
42 | @hide() if isTooFar(event.offset.x) or isTooFar(event.offset.y)
43 |
44 | show: (point = @point) =>
45 | return if @mask.parent?.disabled
46 |
47 | @animateStop()
48 |
49 | fullWidth = @_fullWidth
50 | parent = @mask.parent
51 | color = undefined
52 |
53 | if @colorOverride?
54 | color = @colorOverride
55 | else if @external
56 | color = new Color( parent.color )
57 | .alpha( .25 )
58 | else
59 | color = new Color( parent.backgroundColor )
60 | .alpha( .5 )
61 | .lighten( 15 )
62 | .saturate ( 15 )
63 |
64 | @props =
65 | x: point.x - 4
66 | y: point.y - 4
67 | height: 8
68 | width: 8
69 | borderRadius: 4
70 | backgroundColor: color
71 | opacity: 0
72 |
73 | @animate
74 | opacity: 1
75 | options: { time: .1 }
76 |
77 | @animate
78 | x: point.x - 4 - ( fullWidth )
79 | y: point.y - 4 - ( fullWidth )
80 | height: fullWidth * 2
81 | width: fullWidth * 2
82 | borderRadius: ( fullWidth )
83 | options: { time: .6 }
84 |
85 | hide: =>
86 | @animate
87 | opacity: 0
88 | options: { time: .45 , delay: .1 }
89 |
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/RowItem.coffee:
--------------------------------------------------------------------------------
1 | # 888888ba dP dP
2 | # 88 `8b 88 88
3 | # a88aaaa8P' .d8888b. dP dP dP 88 d8888P .d8888b. 88d8b.d8b.
4 | # 88 `8b. 88' `88 88 88 88 88 88 88ooood8 88'`88'`88
5 | # 88 88 88. .88 88.88b.88' 88 88 88. ... 88 88 88
6 | # dP dP `88888P' 8888P Y8P dP dP `88888P' dP dP dP
7 |
8 | Type = require 'md-components/Type'
9 | { Theme } = require 'md-components/Theme'
10 | { Divider } = require 'md-components/Divider'
11 |
12 |
13 | exports.RowItem = class RowItem extends Layer
14 | constructor: (options = {}) ->
15 |
16 | @_icon = options.icon
17 | @_iconBackgroundColor = options.iconBackgroundColor ? '#777'
18 | @_text = options.text ? 'Row item'
19 | @_row = options.row ? 0
20 | @_y = 32 + (@_row * 48)
21 |
22 | super _.defaults options,
23 | width: Screen.width
24 | y: @_y
25 | height: 48
26 | backgroundColor: null
27 |
28 | @icon = new Layer
29 | name: '.', parent: @
30 | x: 16, y: Align.center
31 | height: 32, width: 32, borderRadius: 16
32 | backgroundColor: @_iconBackgroundColor
33 | image: @_icon
34 |
35 | @labelLayer = new Type.Regular
36 | name: '.', parent: @
37 | x: @icon.maxX + 16, y: Align.center
38 | color: Theme.text.text
39 | text: @_text
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/Select.coffee:
--------------------------------------------------------------------------------
1 | Type = require 'md-components/Type'
2 | { Theme } = require 'md-components/Theme'
3 | { TextField } = require 'md-components/TextField'
4 | { Dropdown } = require 'md-components/Dropdown'
5 | { Icon } = require 'md-components/Icon'
6 |
7 |
8 | # .d88888b dP dP
9 | # 88. "' 88 88
10 | # `Y88888b. .d8888b. 88 .d8888b. .d8888b. d8888P
11 | # `8b 88ooood8 88 88ooood8 88' `"" 88
12 | # d8' .8P 88. ... 88 88. ... 88. ... 88
13 | # Y88888P `88888P' dP `88888P' `88888P' dP
14 | #
15 | #
16 |
17 |
18 | class exports.Select extends TextField
19 | constructor: (options = {}) ->
20 |
21 | @_options = options.options ? ['Select Menu']
22 |
23 | # TODO
24 | # add an explicit width prop to textfield and use this prop instead of useMenuWidth
25 |
26 | useMenuWidth = options.useMenuWidth ? false
27 |
28 | super _.defaults options,
29 | name: 'Downdown Select'
30 | type: 'dropdown'
31 | inputType: 'input'
32 | readOnly: true
33 | clip: false
34 |
35 | @dropdown = new Dropdown
36 | parent: @
37 | x: 0, y: 4
38 | width: if not useMenuWidth then @width
39 | options: @_options
40 |
41 | if useMenuWidth then @width = @dropdown.width
42 |
43 | @dropdown.on "change:selection", (selection) =>
44 | @_input.value = selection
45 | @setValue()
46 |
47 | @dropdown.on "change:isOpen", (isOpen) =>
48 | @focused = isOpen
49 |
50 | showFocused: =>
51 | return if @disabled
52 |
53 | baseY = 0
54 |
55 | if @focused
56 | @bringToFront()
57 |
58 | @animateStop()
59 |
60 | @_app?.focused = @
61 |
62 | if @screenFrame.y + @height > Screen.height - 222
63 | @scrollLayer?.scrollToLayer(@, 0, .45)
64 | else if @screenFrame.y < Screen.height * .15
65 | @scrollLayer?.scrollToLayer(@, 0, .15)
66 |
67 | @labelTextLayer?.animate
68 | y: baseY
69 | fontSize: 12
70 | color: @tint
71 |
72 | @inputLine?.animate
73 | height: 1
74 | backgroundColor: @tint
75 |
76 | else
77 | @animateStop()
78 |
79 | if this.hasTextContent()
80 | @labelTextLayer?.animate
81 | y: baseY
82 | fontSize: 12
83 | color: @labelTextColor
84 | else
85 | @labelTextLayer?.animate
86 | y: 22
87 | fontSize: 16
88 | color: @labelTextColor
89 |
90 | @inputLine?.animate
91 | height: 1
92 | backgroundColor: 'rgba(0, 0, 0, .42)'
93 |
94 | if @_app?.focused is @
95 | @_app?.focused = undefined
96 |
97 | @setPlaceholder()
98 |
99 | @define "focused",
100 | get: -> return @_focused
101 | set: (value) ->
102 | return if @_focused is value
103 | if typeof value isnt 'boolean' then throw 'Focused must be either true or false.'
104 |
105 | @_focused = value
106 |
107 | @emit("change:focused", value, @)
108 |
109 | @showFocused()
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/Slider.coffee:
--------------------------------------------------------------------------------
1 | # .d88888b dP oo dP
2 | # 88. "' 88 88
3 | # `Y88888b. 88 dP .d888b88 .d8888b. 88d888b.
4 | # `8b 88 88 88' `88 88ooood8 88' `88
5 | # d8' .8P 88 88 88. .88 88. ... 88
6 | # Y88888P dP dP `88888P8 `88888P' dP
7 |
8 | { Ripple } = require 'md-components/Ripple'
9 | { Icon } = require 'md-components/Icon'
10 | { Theme } = require 'md-components/Theme'
11 |
12 | exports.Slider = class Slider extends SliderComponent
13 | constructor: (options = {}) ->
14 |
15 | @_notched = options.notched ? false
16 | @_notches = options.notches ? 10
17 | @_notchWidth = undefined
18 |
19 | super _.defaults options,
20 | name: '.', height: 2
21 | backgroundColor: 'rgba(0,0,0,.26)'
22 | min: 0, max: 10
23 | animationOptions: {time: .15}
24 |
25 | @fill.backgroundColor = Theme.primary
26 | @knobSize = 44
27 |
28 | @knob.props =
29 | name: 'Knob'
30 | backgroundColor: null
31 | shadowX: 0
32 | shadowY: 0
33 | shadowBlur: 0
34 | color: Theme.primary
35 |
36 | @knob.draggable.propagateEvents = false
37 |
38 | @thumb = new Layer
39 | name: 'Thumb', parent: @knob
40 | x: Align.center, y: Align.center
41 | height: 12, width: 12, borderRadius: 12
42 | backgroundColor: Theme.primary
43 | animationOptions: {time: .15}
44 |
45 | if @_notched
46 |
47 | @_notchWidth = @width / @_notches
48 |
49 | for i in [0...@_notches]
50 | notch = new Layer
51 | name: '.', parent: @
52 | x: i * @_notchWidth
53 | width: 2, height: 2, borderRadius: 2,
54 | backgroundColor: Theme.colors.primary.text
55 |
56 | notch.placeBehind(@knob)
57 |
58 | @tip = new Layer
59 | name: 'Tip', parent: @knob
60 | x: Align.center, y: -24
61 | width: 26, height: 32
62 | html: ' '
63 | backgroundColor: null, opacity: 0
64 | animationOptions: {time: .15}
65 |
66 | @tipValue = new TextLayer
67 | name: 'Tip Value', parent: @tip
68 | y: 5, width: 26
69 | color: Theme.colors.primary.text
70 | fontSize: 12, fontFamily: 'Roboto', textAlign: 'center'
71 | text: "{value}"
72 |
73 | @tipValue.template = @value
74 |
75 | @onTouchStart @_showNotchedDragging
76 |
77 | @onValueChange ->
78 | @_setNotchedValue()
79 | @_setTipValue()
80 |
81 |
82 | else
83 | @knob.onTouchStart @_showDragging
84 |
85 |
86 | @knob.onTouchEnd @showDefault
87 | @knob.onDragEnd @showDefault
88 | @knob.onDrag @_setThumbColor
89 | @_setThumbColor()
90 |
91 | _roundValue: (number, nearest) ->
92 | return (Math.round(number / nearest) + 1) * nearest
93 |
94 | _setNotchedValue: (value) =>
95 | if @knob.midX % @_notchWidth > 0
96 | @knob.x = @_roundValue(@knob.x, @_notchWidth) - (@knob.width / 2)
97 |
98 | _setTipValue: =>
99 | @tipValue.template = Math.round(@value)
100 | @_setTipColor()
101 |
102 | _setTipColor: =>
103 | color = if @value is @min then 'rgba(190, 190, 190, 1)' else Theme.primary
104 | @tip.html = ' '
105 |
106 | _showNotchedDragging: =>
107 | @_setTipColor()
108 | @thumb.animate {opacity: 0}
109 | @tip.animate {opacity: 1}
110 |
111 | _showDragging: =>
112 | @_setThumbColor()
113 | @thumb.animate {width: 18, height: 18, x: 13, y: 13}
114 |
115 | _setThumbColor: =>
116 | @thumb.backgroundColor = if @value is @min then 'rgba(190, 190, 190, 1)' else Theme.primary
117 |
118 | showDefault: =>
119 | @animateStop()
120 | @_setThumbColor()
121 | @thumb.animate {opacity: 1, width: 12, height: 12, x: 15, y: 15}
122 | if @_notched
123 | @_setTipColor()
124 | @tip.animate {opacity: 0}
125 |
126 |
127 |
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/Snackbar.coffee:
--------------------------------------------------------------------------------
1 | # .d88888b dP dP
2 | # 88. "' 88 88
3 | # `Y88888b. 88d888b. .d8888b. .d8888b. 88 .dP 88d888b. .d8888b. 88d888b.
4 | # `8b 88' `88 88' `88 88' `"" 88888" 88' `88 88' `88 88' `88
5 | # d8' .8P 88 88 88. .88 88. ... 88 `8b. 88. .88 88. .88 88
6 | # Y88888P dP dP `88888P8 `88888P' dP `YP 88Y8888' `88888P8 dP
7 |
8 | Type = require 'md-components/Type'
9 | { Ripple } = require 'md-components/Ripple'
10 | { Theme } = require 'md-components/Theme'
11 | { Button } = require 'md-components/Button'
12 |
13 | class exports.Snackbar extends Layer
14 | constructor: (options = {}) ->
15 |
16 | { app } = require 'md-components/App'
17 | @_app = app
18 |
19 | @_title = options.title ? 'Snackbar'
20 | @_timeout = options.timeout ? 4
21 | @_action = options.action
22 |
23 | super _.defaults options,
24 | name: '.'
25 | y: Screen.maxY
26 | width: Screen.width
27 | clip: true
28 | backgroundColor: Theme.snackbar.backgroundColor
29 | animationOptions: {time: .25}
30 | visible: false
31 |
32 | titleWidth = @width - 48
33 |
34 | if @_action?
35 | @action = new Button
36 | parent: @
37 | x: Align.right(-8), y: 4
38 | color: @_action.color ? Theme.colors.primary.light
39 | text: @_action.title.toUpperCase()
40 | action: @_action.action
41 |
42 | @action.onTap @hide
43 | titleWidth = @action.x - 8 - 24
44 |
45 | @textLabel = new Type.Body1
46 | name: 'Title', parent: @
47 | x: 24, y: 14
48 | width: titleWidth
49 | text: @_title
50 | color: Theme.snackbar.color
51 |
52 | @height = @textLabel.maxY + 14
53 | @action?.y = Align.center
54 |
55 |
56 |
57 | Utils.delay @_timeout, @hide
58 |
59 | @show()
60 |
61 | show: =>
62 | if @_app?
63 | if @_app.snackbar?
64 | @_app.snackbar.hide()
65 | Utils.delay 1, @show
66 | return
67 | else
68 | @_app.snackbar = @
69 | @_app.actionButton?.animate {y: @_app.actionButton.y - @height, options: @animationOptions}
70 |
71 | height = @height
72 |
73 | @y = Screen.height - @_app.footer.height
74 | @height = 0
75 | @visible = true
76 | @animate
77 | y: @y - (height - 1)
78 | height: height
79 | else
80 | @visible = true
81 | @y = Screen.height
82 | @animate {y: Screen.height - @height}
83 |
84 | hide: =>
85 | if @_app?
86 | @_app.snackbar = undefined
87 | @_app.actionButton?.animate {y: @_app.actionButton.y + @height, options: @animationOptions}
88 |
89 | @animate {height: 0, y: @y + @height}
90 | Utils.delay .5, => @destroy()
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/StackView.coffee:
--------------------------------------------------------------------------------
1 | # add stackview to any layer
2 |
3 | class exports.StackView extends ScrollComponent
4 | constructor: (options = {}) ->
5 | showLayers = options.showLayers ? false
6 |
7 | # stack related
8 | @_stack = []
9 | @padding = options.padding ? {
10 | top: 16, right: 16,
11 | bottom: 0, left: 16
12 | stack: 16
13 | }
14 |
15 | super _.defaults options,
16 | name: 'StackView'
17 | size: Screen.size
18 | scrollHorizontal: false
19 | contentInset: { bottom: 16 }
20 |
21 | @content.clip = false
22 | @content.backgroundColor = Screen.backgroundColor
23 | @content.name = if options.showLayers then 'content' else '.'
24 |
25 | # add a layer to the stack
26 | addToStack: (layers = [], position) =>
27 | if not _.isArray(layers) then layers = [layers]
28 | last = _.last(@stack)
29 |
30 | if last?
31 | startY = last.maxY + (@padding.stack ? 0)
32 | else
33 | startY = @padding.top ? 0
34 |
35 | for layer in layers
36 |
37 | if layer.constructor.name is 'Card' then position = 'full'
38 |
39 | layer.props =
40 | parent: @content
41 | x: _.clamp(
42 | @padding.left + layer.x,
43 | @padding.left,
44 | @width - @padding.right - layer.width
45 | )
46 | y: startY
47 |
48 | switch position
49 | when 'full'
50 | layer.width = @width - ( @padding.left + @padding.right )
51 | when 'left'
52 | layer.props =
53 | width: (@width / 2) - @padding.left
54 | x: @padding.left
55 | when 'right'
56 | layer.props =
57 | width: (@width / 2) - @padding.right
58 | x: Align.right(-@padding.right)
59 | when 'center'
60 | layer.x = Align.center
61 |
62 | @stack.push(layer)
63 |
64 | layer.on "change:height", => @moveStack(@)
65 |
66 | @updateContent()
67 |
68 | # pull a layer from the stack
69 | removeFromStack: (layer) =>
70 | _.pull(@stack, layer)
71 |
72 | # stack layers in stack, with optional padding and animation
73 | stackView: (
74 | animate = false,
75 | padding = @padding.stack,
76 | top = @padding.top,
77 | animationOptions = {time: .25}
78 | ) =>
79 |
80 | for layer, i in @stack
81 |
82 | if animate is true
83 | if i is 0 then layer.animate
84 | y: top
85 | options: animationOptions
86 |
87 | else layer.animate
88 | y: @stack[i - 1].maxY + padding
89 | options: animationOptions
90 | else
91 | if i is 0 then layer.y = top
92 | else layer.y = @stack[i - 1].maxY + padding
93 |
94 | @updateContent()
95 |
96 | # move stack when layer height changes
97 | moveStack: (layer) =>
98 | index = _.indexOf(@stack, layer)
99 | for layer, i in @stack
100 | if i > 0 and i > index
101 | layer.y = @stack[i - 1].maxY + @padding.stack
102 |
103 |
104 | # build with page as bound object
105 | build: (func) -> do _.bind(func, @)
106 |
107 | # refresh page
108 | refresh: -> null
109 |
110 | @define "stack",
111 | get: -> return @_stack
112 | set: (layers) ->
113 | layer.destroy() for layer in @stack
114 | @addToStack(layers)
115 |
116 |
117 |
118 |
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/StatusBar.coffee:
--------------------------------------------------------------------------------
1 | # .d88888b dP dP 888888ba
2 | # 88. "' 88 88 88 `8b
3 | # `Y88888b. d8888P .d8888b. d8888P dP dP .d8888b. a88aaaa8P' .d8888b. 88d888b.
4 | # `8b 88 88' `88 88 88 88 Y8ooooo. 88 `8b. 88' `88 88' `88
5 | # d8' .8P 88 88. .88 88 88. .88 88 88 .88 88. .88 88
6 | # Y88888P dP `88888P8 dP `88888P' `88888P' 88888888P `88888P8 dP
7 |
8 | Type = require 'md-components/Type'
9 | { Ripple } = require 'md-components/Ripple'
10 | { Icon } = require 'md-components/Icon'
11 | { Theme } = require 'md-components/Theme'
12 |
13 | exports.StatusBar = class StatusBar extends Layer
14 | constructor: (options = {}) ->
15 |
16 | super _.defaults options,
17 | name: '.'
18 | width: Screen.width, height: 24
19 | backgroundColor: Theme.statusBar.backgroundColor
20 |
21 | @items = new Layer
22 | name: '.', parent: @
23 | width: 100
24 | height: 15
25 | x: Align.right(-8)
26 | y: 5
27 | backgroundColor: null
28 | style:
29 | lineHeight: 0
30 |
31 | @on "change:color", => @setSVG()
32 | @color = '#FFF'
33 |
34 | setSVG: ->
35 | @items.html = """
36 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | 12:30
84 |
85 |
86 |
87 |
88 | """
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/Switch.coffee:
--------------------------------------------------------------------------------
1 |
2 | # .d88888b oo dP dP
3 | # 88. "' 88 88
4 | # `Y88888b. dP dP dP dP d8888P .d8888b. 88d888b.
5 | # `8b 88 88 88 88 88 88' `"" 88' `88
6 | # d8' .8P 88.88b.88' 88 88 88. ... 88 88
7 | # Y88888P 8888P Y8P dP dP `88888P' dP dP
8 |
9 | Type = require 'md-components/Type'
10 | { Ripple } = require 'md-components/Ripple'
11 | { Icon } = require 'md-components/Icon'
12 | { Theme } = require 'md-components/Theme'
13 |
14 | exports.Switch = class Switch extends Layer
15 | constructor: (options = {}) ->
16 |
17 | @_isOn = false
18 |
19 | super _.defaults options,
20 | name: 'Switch'
21 | width: 34, height: 14, borderRadius: 7
22 | color: new Color(Theme.primary).desaturate(100).alpha(.84)
23 | backgroundColor: 'rgba(0,0,0,.54)'
24 | animationOptions: {time: .15}
25 |
26 | @mask = new Layer
27 | name: 'Mask', parent: @
28 | x: -12, y: Align.center
29 | width: 44, height: 44
30 | borderRadius: 20
31 | backgroundColor: null
32 | clip: true
33 | opacity: 1
34 | animationOptions: {time: .15}
35 |
36 | @ripple = new Ripple( @mask, external = true )
37 |
38 | @knob = new Layer
39 | name: 'Knob', parent: @mask
40 | x: Align.center, y: Align.center
41 | width: 20, height: 20, borderRadius: 10
42 | backgroundColor: 'rgba(250, 250, 250, 1)'
43 | shadowY: 2, shadowBlur: 3
44 | animationOptions: {time: .15}
45 |
46 | @onTap -> @isOn = !@isOn
47 |
48 | @define "isOn",
49 | get: -> return @_isOn
50 | set: (bool) ->
51 | return if bool is @_isOn
52 |
53 | @_isOn = bool
54 | @emit("change:isOn", @_isOn, @)
55 | @update()
56 |
57 | update: ->
58 | if @_isOn
59 | @mask.animate {x: Align.right(12)}
60 | @color = Theme.primary
61 | @knob.animate {backgroundColor: Theme.primary}
62 | @animate {backgroundColor: Theme.colors.primary.light}
63 | else
64 | @mask.animate {x: -12}
65 | @color = new Color(Theme.primary).desaturate(100).alpha(.84)
66 | @knob.animate {backgroundColor: 'rgba(250, 250, 250, 1)'}
67 | @animate {backgroundColor: 'rgba(0,0,0,.54)'}
68 |
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/TextArea.coffee:
--------------------------------------------------------------------------------
1 | Type = require 'md-components/Type'
2 | { Theme } = require 'md-components/Theme'
3 | { TextField } = require 'md-components/TextField'
4 |
5 |
6 | # d888888P dP .d888888
7 | # 88 88 d8' 88
8 | # 88 .d8888b. dP. .dP d8888P 88aaaaa88a 88d888b. .d8888b. .d8888b.
9 | # 88 88ooood8 `8bd8' 88 88 88 88' `88 88ooood8 88' `88
10 | # 88 88. ... .d88b. 88 88 88 88 88. ... 88. .88
11 | # dP `88888P' dP' `dP dP 88 88 dP `88888P' `88888P8
12 | #
13 | #
14 |
15 | exports.TextArea = class TextArea extends TextField
16 | constructor: (options = {}) ->
17 |
18 | @_rows = options.rows ? 4
19 |
20 | super _.defaults options,
21 | name: 'Text Area'
22 | width: 300
23 | borderRadius: 4
24 | borderWidth: 2, borderColor: options.tint
25 | padding: {top: 28, bottom: 16, right: 16, left: 16}
26 | clip: true
27 | inputType: 'textarea'
28 |
29 | # Label Text
30 |
31 | @labelTextLayer.props =
32 | x: 16, y: 16
33 |
34 | @helperTextLayer.visible = false
35 |
36 | # Input Line
37 |
38 | @inputLine.destroy()
39 |
40 | # Textarea Element
41 |
42 | @setInputAttribute('rows', @_rows)
43 | @setInputAttribute('resize', @_rows)
44 |
45 | @height = @_input.clientHeight
46 |
47 |
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/Theme.coffee:
--------------------------------------------------------------------------------
1 | # d888888P dP
2 | # 88 88
3 | # 88 88d888b. .d8888b. 88d8b.d8b. .d8888b.
4 | # 88 88' `88 88ooood8 88'`88'`88 88ooood8
5 | # 88 88 88 88. ... 88 88 88 88. ...
6 | # dP dP dP `88888P' dP dP dP `88888P'
7 |
8 |
9 | # When loaded, this module will attempt to create a new theme based on
10 | # the Design Mode template.
11 |
12 | Screen.backgroundColor = '#000'
13 |
14 | exports.modifyColor = modifyColor = (color, h, s, l) ->
15 | clip = _.replace(_.replace(color.toHslString().slice(4, -1), '%', ''), '%', '') .split(', ')
16 |
17 | newColor = new Color(
18 | h: _.parseInt(clip[0]) + h,
19 | s: (_.parseInt(clip[1]) + s)/100,
20 | l: (_.parseInt(clip[2]) + l)/100,
21 | a: 1)
22 |
23 | return newColor
24 |
25 | primaryColor = new Color('#0F6CC8')
26 | primaryTextColor = new Color('#FFFFFF')
27 |
28 | secondaryColor = new Color('#1B9DFF')
29 | secondaryTextColor = new Color('#FFFFFF')
30 |
31 | menuColor = new Color ('#CCCCCC')
32 | menuTextColor = new Color('#000000')
33 |
34 | pageColor = new Color('#FFFFFF')
35 | pageTextColor = new Color('#333333')
36 |
37 | exports.colors = colors =
38 | primary:
39 | main: primaryColor
40 | light: modifyColor(primaryColor, 13, -5, 15)
41 | dark: modifyColor(primaryColor, -1, -7, -12)
42 | text: primaryTextColor
43 |
44 | secondary:
45 | main: secondaryColor
46 | light: modifyColor(secondaryColor, 13, -5, 15)
47 | dark: modifyColor(secondaryColor, -1, -7, -12)
48 | text: secondaryTextColor
49 | menu:
50 | main: menuColor
51 | light: modifyColor(menuColor, 13, -5, 15)
52 | dark: modifyColor(menuColor, -1, -7, -12)
53 | text: menuTextColor
54 | page:
55 | main: pageColor
56 | light: modifyColor(pageColor, 13, -5, 15)
57 | dark: modifyColor(pageColor, -1, -7, -12)
58 | text: pageTextColor
59 |
60 | exports.Theme =
61 | tint: colors.secondary.main
62 | primary: colors.primary.main
63 | secondary: colors.secondary.main
64 | page: colors.page.main
65 | menu: colors.menu.light
66 | colors: colors
67 |
68 | user:
69 | image: undefined
70 |
71 | header:
72 | backgroundColor: colors.primary.main
73 | title: colors.primary.text
74 | icon:
75 | color: colors.primary.text
76 | tabs:
77 | backgroundColor: colors.primary.light
78 | color: colors.primary.text
79 | selector: colors.secondary.main
80 |
81 | statusBar:
82 | image: 'modules/md-images/status_bar.png'
83 | backgroundColor: colors.primary.dark
84 |
85 | bottomNav:
86 | backgroundColor: '#FFFFFF'
87 | shadowY: -2
88 | shadowBlur: 6
89 | shadowColor: 'rgba(0,0,0,.1)'
90 |
91 | navBar:
92 | backgroundColor: '#000000'
93 |
94 | keyboard:
95 | image: 'modules/md-images/keyboard.png'
96 |
97 | footer:
98 | image: 'modules/md-images/nav_bar.png'
99 |
100 | page:
101 | primary:
102 | backgroundColor: colors.page.main
103 | text: colors.page.text
104 | secondary:
105 | backgroundColor: '#F5F5F6'
106 |
107 | menuOverlay:
108 | header:
109 | backgroundColor: colors.secondary.main
110 | icon: colors.secondary.light
111 | text: colors.secondary.text
112 | subheader:
113 | color: colors.menu.text
114 | text: colors.secondary.text
115 | icon: colors.secondary.text
116 | backgroundColor: colors.menu.light
117 | text: colors.menu.text
118 | slider:
119 | knob: colors.secondary.light
120 | fill: colors.secondary.dark
121 |
122 | button:
123 | flat:
124 | backgroundColor: null
125 | color: colors.secondary.main
126 | shadowY: 0
127 | shadowColor: 'rgba(0,0,0,.18)'
128 | shadowBlur: 0
129 |
130 | raised:
131 | backgroundColor: colors.secondary.main
132 | color: colors.secondary.text
133 | shadowY: 2
134 | shadowColor: 'rgba(0,0,0,.18)'
135 | shadowBlur: 6
136 |
137 | fab:
138 | backgroundColor: colors.secondary.main
139 | color: colors.secondary.text
140 |
141 | dialog:
142 | backgroundColor:'#FAFAFA'
143 |
144 | divider:
145 | backgroundColor: 'rgba(0,0,0,.12)'
146 |
147 | text:
148 | primary: colors.primary.text
149 | secondary: colors.secondary.text
150 |
151 | table:
152 | backgroundColor: '#FFFFFF'
153 | text: colors.primary.text
154 | checkBox:
155 | backgroundColor: null
156 | borderColor: '#D3D3D3'
157 | selected:
158 | backgroundColor: colors.secondary.main
159 | text: colors.primary.text
160 | checkBox:
161 | backgroundColor: colors.secondary.dark
162 | borderColor: null
163 | snackbar:
164 | backgroundColor: 'rgba(51, 51, 51, 1)'
165 | color: 'rgba(255, 255, 255, 1)'
166 |
167 | toast:
168 | backgroundColor: 'rgba(51, 51, 51, 1)'
169 | color: 'rgba(255, 255, 255, 1)'
170 |
171 | slider:
172 | knob: colors.primary.light
173 | fill: colors.primary.dark
174 |
175 | card:
176 | header: colors.secondary.dark
177 |
178 | color_pallete?.destroy()
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/Tile.coffee:
--------------------------------------------------------------------------------
1 | # d888888P oo dP
2 | # 88 88
3 | # 88 dP 88 .d8888b.
4 | # 88 88 88 88ooood8
5 | # 88 88 88 88. ...
6 | # dP dP dP `88888P'
7 |
8 | Type = require 'md-components/Type'
9 | { Ripple } = require 'md-components/Ripple'
10 | { Icon } = require 'md-components/Icon'
11 | { Theme } = require 'md-components/Theme'
12 |
13 | exports.Tile = Tile = class Tile extends Layer
14 | constructor: (options = {}) ->
15 |
16 | @_header = options.header ? false
17 | @_footer = options.footer ? false
18 | @_action = options.action ? -> null
19 | @_headerAction = options.headerAction ? -> null
20 | @_footerAction = options.footerAction ? -> null
21 |
22 | if @_header and @_footer then throw 'Tile cannot have both a header and a footer.'
23 |
24 | @_icon = options.icon
25 | @gridList = options.gridList # ? throw 'Tile needs a grid property.'
26 |
27 | super _.defaults options,
28 | name: '.', parent: @gridList
29 | width: @gridList.tileWidth
30 | height: @gridList.tileHeight
31 | animationOptions: {time: .3}
32 |
33 | @onTouchStart (event) ->
34 | if @gridList.parent?.parent?.content and @gridList.parent?.parent?.isMoving is false
35 | Ripple(@, event.point, @header, options.RippleColor ? 'rgba(0,0,0,.1)')
36 |
37 | @onTap @_action
38 | @onTap (event) -> event.stopPropagation()
39 |
40 | if @_header or @_footer
41 | @header = new Layer
42 | name: '.', parent: @
43 | y: if @_footer then Align.bottom()
44 | width: @width
45 | height: if options.support then 68 else 48
46 | backgroundColor: options.backgroundColor ? 'rgba(0,0,0,.5)'
47 |
48 | @header.onTouchStart (event) -> Ripple(@, event.point, @title)
49 |
50 | if @_footer then @header.onTap @_footerAction
51 | else @header.onTap @_headerAction
52 |
53 | @header.onTap (event) -> event.stopPropagation()
54 |
55 | if options.title
56 | @header.title = new Type.Regular
57 | name: '.', parent: @header
58 | x: 8, y: if options.support then 12 else Align.center()
59 | color: @color
60 | text: options.title ? 'Two Line'
61 |
62 | if options.support
63 | @header.support = new TextLayer
64 | name: '.', parent: @header
65 | x: 8, y: 35
66 | fontSize: 12
67 | fontFamily: 'Roboto'
68 | color: @color
69 | text: options.support ? 'Support text'
70 |
71 | if options.icon
72 | @header.icon = new Icon
73 | name: '.', parent: @header
74 | x: Align.right(-12), y: if options.support then 20 else Align.center()
75 | icon: options.icon
76 | color: @color
77 |
78 | @i = undefined
79 | @gridList.addTile(@)
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/Toast.coffee:
--------------------------------------------------------------------------------
1 | # d888888P dP
2 | # 88 88
3 | # 88 .d8888b. .d8888b. .d8888b. d8888P
4 | # 88 88' `88 88' `88 Y8ooooo. 88
5 | # 88 88. .88 88. .88 88 88
6 | # dP `88888P' `88888P8 `88888P' dP
7 |
8 | Type = require 'md-components/Type'
9 | { Ripple } = require 'md-components/Ripple'
10 | { Theme } = require 'md-components/Theme'
11 | { Button } = require 'md-components/Button'
12 |
13 | # currently identical to snackbar
14 |
15 | class exports.Toast extends Layer
16 | constructor: (options = {}) ->
17 |
18 | { app } = require 'md-components/App'
19 | @_app = app
20 |
21 | @_title = options.title ? 'Toast'
22 | @_timeout = options.timeout ? 4
23 | @_action = options.action
24 |
25 | super _.defaults options,
26 | name: '.'
27 | y: Screen.maxY
28 | width: Screen.width
29 | clip: true
30 | backgroundColor: Theme.toast.backgroundColor
31 | animationOptions: {time: .25}
32 | visible: false
33 |
34 | titleWidth = @width - 48
35 |
36 | if @_action?
37 | @action = new Button
38 | parent: @
39 | x: Align.right(-8), y: 4
40 | color: @_action.color ? Theme.colors.primary.light
41 | text: @_action.title.toUpperCase()
42 | action: @_action.action
43 |
44 | @action.onTap @hide
45 | titleWidth = @action.x - 8 - 24
46 |
47 | @textLabel = new Type.Body1
48 | name: 'Title', parent: @
49 | x: 24, y: 14
50 | width: titleWidth
51 | text: @_title
52 | color: Theme.toast.color
53 |
54 | @height = @textLabel.maxY + 14
55 | @action?.y = Align.center
56 |
57 |
58 |
59 | Utils.delay @_timeout, @hide
60 |
61 | @show()
62 |
63 | show: =>
64 | if @_app?
65 | if @_app.toast?
66 | @_app.toast.hide()
67 | Utils.delay 1, @show
68 | return
69 | else
70 | @_app.toast = @
71 | @_app.actionButton?.animate {y: @_app.actionButton.y - @height, options: @animationOptions}
72 |
73 | height = @height
74 |
75 | @y = Screen.height - @_app.footer.height
76 | @height = 0
77 | @visible = true
78 | @animate
79 | y: @y - (height - 1)
80 | height: height
81 | else
82 | @visible = true
83 | @y = Screen.height
84 | @animate {y: Screen.height - @height}
85 |
86 | hide: =>
87 | if @_app?
88 | @_app.toast = undefined
89 | @_app.actionButton?.animate {y: @_app.actionButton.y + @height, options: @animationOptions}
90 |
91 | @animate {height: 0, y: @y + @height}
92 | Utils.delay .5, => @destroy()
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/Type.coffee:
--------------------------------------------------------------------------------
1 | Theme = require 'md-components/Theme'
2 |
3 | # d888888P dP
4 | # 88 88
5 | # 88 dP dP 88d888b. .d8888b. .d8888b. 88d888b. .d8888b. 88d888b. 88d888b. dP dP
6 | # 88 88 88 88' `88 88' `88 88' `88 88' `88 88' `88 88' `88 88' `88 88 88
7 | # 88 88. .88 88. .88 88. .88 88. .88 88 88. .88 88. .88 88 88 88. .88
8 | # dP `8888P88 88Y888P' `88888P' `8888P88 dP `88888P8 88Y888P' dP dP `8888P88
9 | # .88 88 .88 88 .88
10 | # d8888P dP d8888P dP d8888P
11 |
12 | Utils.insertCSS(
13 | """
14 | @font-face {
15 | font-family: "Roboto";
16 | src: url("modules/md-fonts/Roboto-Regular.ttf");
17 | """)
18 |
19 | class exports.Headline extends TextLayer
20 | constructor: (options) ->
21 | super _.defaults options,
22 | name: '.'
23 | fontFamily: 'Roboto'
24 | fontSize: 24
25 | fontWeight: 400
26 | lineHeight: 1.3
27 | color: 'rgba(0,0,0,.87)'
28 |
29 | class exports.Subhead extends TextLayer
30 | constructor: (options) ->
31 | super _.defaults options,
32 | name: '.'
33 | fontFamily: 'Roboto'
34 | fontSize: 16
35 | fontWeight: 400,
36 | lineHeight: 1.5,
37 | color: 'rgba(0,0,0,.54)'
38 |
39 | class exports.Title extends TextLayer
40 | constructor: (options) ->
41 | super _.defaults options,
42 | name: '.'
43 | fontFamily: 'Roboto'
44 | fontSize: 20
45 | fontWeight: 500
46 | lineHeight: 1.3
47 | color: 'rgba(0,0,0,.87)'
48 | class exports.Regular extends TextLayer
49 | constructor: (options) ->
50 | super _.defaults options,
51 | name: '.'
52 | fontFamily: 'Roboto'
53 | fontSize: 16
54 | fontWeight: 400
55 | lineHeight: 1.3
56 | color: 'rgba(0,0,0,.87)'
57 | class exports.Body2 extends TextLayer
58 | constructor: (options) ->
59 | super _.defaults options,
60 | name: '.'
61 | fontFamily: 'Roboto'
62 | fontSize: 14
63 | fontWeight: 500
64 | lineHeight: 1.3
65 | color: 'rgba(0,0,0,.87)'
66 | class exports.Menu extends TextLayer
67 | constructor: (options) ->
68 | super _.defaults options,
69 | name: '.'
70 | fontFamily: 'Roboto'
71 | fontSize: 14
72 | fontWeight: 500
73 | lineHeight: 1.7
74 | color: 'rgba(0,0,0,.87)'
75 | class exports.Body1 extends TextLayer
76 | constructor: (options) ->
77 | super _.defaults options,
78 | name: '.'
79 | fontFamily: 'Roboto'
80 | fontSize: 14
81 | fontWeight: 400
82 | lineHeight: 1.4
83 | color: 'rgba(0,0,0,.87)'
84 | class exports.Caption extends TextLayer
85 | constructor: (options) ->
86 | super _.defaults options,
87 | name: '.'
88 | fontFamily: 'Roboto'
89 | fontSize: 12
90 | fontWeight: 400
91 | lineHeight: 1.3
92 | color: 'rgba(0,0,0,.54)'
93 | class exports.Button extends TextLayer
94 | constructor: (options) ->
95 | super _.defaults options,
96 | name: '.'
97 | fontFamily: 'Roboto'
98 | fontSize: 14
99 | fontWeight: 500
100 | lineHeight: 1.3
101 | color: '#009688'
102 | letterSpacing: 0.5
103 | padding: {left: 4, right: 4, top: 8, bottom: 0},
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-components/View.coffee:
--------------------------------------------------------------------------------
1 | # dP dP oo
2 | # 88 88
3 | # 88 .8P dP .d8888b. dP dP dP
4 | # 88 d8' 88 88ooood8 88 88 88
5 | # 88 .d8P 88 88. ... 88.88b.88'
6 | # 888888' dP `88888P' 8888P Y8P
7 |
8 | # Works without an app, but will integrate with app if set with options.app.
9 |
10 | { Theme } = require 'md-components/Theme'
11 | { Page } = require 'md-components/Page'
12 |
13 | exports.View = class View extends Page
14 | constructor: (options = {}) ->
15 |
16 | { app } = require 'md-components/App'
17 |
18 | @_icon = options.icon ? 'open-in-new'
19 |
20 | options.title ?= 'New View'
21 | options.icon = 'menu'
22 | options.action = -> app.showMenu()
23 |
24 | super options
25 |
26 | app.addView
27 | title: options.title
28 | icon: @_icon
29 | view: @
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-fonts/Roboto-Black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/modules/md-fonts/Roboto-Black.ttf
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-fonts/Roboto-BlackItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/modules/md-fonts/Roboto-BlackItalic.ttf
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-fonts/Roboto-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/modules/md-fonts/Roboto-Bold.ttf
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-fonts/Roboto-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/modules/md-fonts/Roboto-BoldItalic.ttf
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-fonts/Roboto-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/modules/md-fonts/Roboto-Italic.ttf
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-fonts/Roboto-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/modules/md-fonts/Roboto-Light.ttf
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-fonts/Roboto-LightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/modules/md-fonts/Roboto-LightItalic.ttf
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-fonts/Roboto-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/modules/md-fonts/Roboto-Medium.ttf
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-fonts/Roboto-MediumItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/modules/md-fonts/Roboto-MediumItalic.ttf
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-fonts/Roboto-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/modules/md-fonts/Roboto-Regular.ttf
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-fonts/Roboto-Thin.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/modules/md-fonts/Roboto-Thin.ttf
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-fonts/Roboto-ThinItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/modules/md-fonts/Roboto-ThinItalic.ttf
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-images/Group.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Group
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 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | 12:30
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-images/keyboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/modules/md-images/keyboard.png
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-images/nav_bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/modules/md-images/nav_bar.png
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-images/status_bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/steveruizok/framer-md/efc38d8d87ee5154f0d1ae4b30bb38416a0ac5fd/framer-md-dev.framer/modules/md-images/status_bar.png
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md-images/status_bar.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | time
5 | Created with Sketch.
6 |
7 |
8 |
9 |
10 | 12:30
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/framer-md-dev.framer/modules/md.coffee:
--------------------------------------------------------------------------------
1 |
2 | Framer.Extras.Hints.disable()
3 |
4 |
5 | { ActionButton } = require 'md-components/ActionButton'
6 | { App } = require 'md-components/App'
7 | { BottomNav } = require 'md-components/BottomNav'
8 | { Button } = require 'md-components/Button'
9 | { Card } = require 'md-components/Card'
10 | { Checkbox } = require 'md-components/Checkbox'
11 | { Dialog } = require 'md-components/Dialog'
12 | { Divider } = require 'md-components/Divider'
13 | { Dropdown } = require 'md-components/Dropdown'
14 | { Elevation } = require 'md-components/Elevation'
15 | App = require 'md-components/App'
16 | { GridList } = require 'md-components/GridList'
17 | { Header } = require 'md-components/Header'
18 | { Icon } = require 'md-components/Icon'
19 | { MenuButton } = require 'md-components/MenuButton'
20 | { MenuOverlay } = require 'md-components/MenuOverlay'
21 | { Notification } = require 'md-components/Notification'
22 | { Page } = require 'md-components/Page'
23 | { Radiobox } = require 'md-components/Radiobox'
24 | { Ripple } = require 'md-components/Ripple'
25 | { RowItem } = require 'md-components/RowItem'
26 | { Select } = require 'md-components/Select'
27 | { Slider } = require 'md-components/Slider'
28 | { Snackbar } = require 'md-components/Snackbar'
29 | { StatusBar } = require 'md-components/StatusBar'
30 | { StackView } = require 'md-components/StackView'
31 | { Switch } = require 'md-components/Switch'
32 | { Table } = require 'md-components/Table'
33 | { TableCard } = require 'md-components/TableCard'
34 | { TextArea } = require 'md-components/TextArea'
35 | { TextField } = require 'md-components/TextField'
36 | { Theme } = require 'md-components/Theme'
37 | { Toast } = require 'md-components/Toast'
38 | Type = require 'md-components/Type'
39 | { Tile } = require 'md-components/Tile'
40 | { View } = require 'md-components/View'
41 |
42 | exports.ActionButton = ActionButton
43 | exports.App = App
44 | exports.Button = Button
45 | exports.Card = Card
46 | exports.Checkbox = Checkbox
47 | exports.Dialog = Dialog
48 | exports.Divider = Divider
49 | exports.Dropdown = Dropdown
50 | exports.Elevation = Elevation
51 | exports.App = App.App
52 | exports.app = App.app
53 | exports.GridList = GridList
54 | exports.Header = Header
55 | exports.Icon = Icon
56 | exports.MenuButton = MenuButton
57 | exports.MenuOverlay = MenuOverlay
58 | exports.Notification = Notification
59 | exports.Page = Page
60 | exports.Radiobox = Radiobox
61 | exports.Ripple = Ripple
62 | exports.RowItem = RowItem
63 | exports.Select = Select
64 | exports.Slider = Slider
65 | exports.Snackbar = Snackbar
66 | exports.StackView = StackView
67 | exports.StatusBar = StatusBar
68 | exports.Switch = Switch
69 | exports.Table = Table
70 | exports.TableCard = TableCard
71 | exports.TextArea = TextArea
72 | exports.TextField = TextField
73 | exports.Theme = Theme
74 | exports.Toast = Toast
75 | exports.Tile = Tile
76 | exports.Type = Type
77 | exports.View = View
78 |
79 | exports.Headline = Type.Headline
80 | exports.Subhead = Type.Subhead
81 | exports.Title = Type.Title
82 | exports.Regular = Type.Regular
83 | exports.Menu = Type.Menu
84 | exports.Body1 = Type.Body1
85 | exports.Body2 = Type.Body2
86 | exports.Caption = Type.Caption
87 |
88 | loading_screen?.destroy()
89 | color_pallette?.destroy()
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------