loft 0.1.2 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d229fb260b365c12ff3b3ea01d22d46127a2ef0f
4
- data.tar.gz: 2d134163274e9e5c1c2613e9f436a93cd6eea9a2
3
+ metadata.gz: 7f204fc64713eb740598cd03d4cd32aa11313719
4
+ data.tar.gz: 39d010891c3e501c7321690cdcfe81b4e4ba26f9
5
5
  SHA512:
6
- metadata.gz: 8888002fc78aa83f97d4a848bcc5f37745317070a3bead5d5d7d48992f37695de3fa735fd042f5a5369d53b85e230a50ca82746f5f8d88f30778da83181ede2d
7
- data.tar.gz: 8629e3a75d48bb5bff41e699f13f30b01aaed2193590a1bbdfadb31a38df182171957fc6868ef8e1351e9f50cd39c937c559246f60affe03e227e808f4267d15
6
+ metadata.gz: 8bbe85ed20e0221a0d4776100bfa2a8648816b6ce960d5aeb590990fbcb2586ed29efdef9822c46f811b3a97fb5e6d2aa353e02c7273ecdb6691891e58fccbfc
7
+ data.tar.gz: b612bcbf8a16792e2231b79e250be6ea4c6cf3bfee97c465fda6f8825317a65ed3fa862797747c1a25c5135fe1230aab3eb2130a4904bae35d9981ef7eaee6a1
data/.gitignore CHANGED
@@ -1,2 +1,4 @@
1
1
  *.gem
2
- .DS_Store
2
+ .DS_Store
3
+
4
+ node_modules/
data/Gruntfile.coffee ADDED
@@ -0,0 +1,41 @@
1
+ module.exports = (grunt) ->
2
+ # Project configuration
3
+ grunt.initConfig
4
+ pkg: grunt.file.readJSON('package.json')
5
+ coffee:
6
+ compileBare:
7
+ options:
8
+ bare: true
9
+ files:
10
+ 'build/loft.js': [
11
+ # core
12
+ 'app/assets/javascripts/loft/group-actions.coffee'
13
+ 'app/assets/javascripts/loft/asset-item.coffee'
14
+ 'app/assets/javascripts/loft/module.coffee'
15
+ # redactor
16
+ 'app/assets/javascripts/loft/redactor-loft.coffee'
17
+ # inputs
18
+ 'app/assets/javascripts/loft/input-loft-asset.coffee'
19
+ 'app/assets/javascripts/loft/input-loft-image.coffee'
20
+ ]
21
+
22
+ concat:
23
+ loft:
24
+ src: [
25
+ 'build/loft.js'
26
+ ]
27
+ dest: 'dist/loft.js'
28
+
29
+ clean: [
30
+ 'build'
31
+ ]
32
+
33
+ grunt.loadNpmTasks('grunt-contrib-coffee')
34
+ grunt.loadNpmTasks('grunt-contrib-concat')
35
+ grunt.loadNpmTasks('grunt-contrib-clean')
36
+
37
+ grunt.registerTask('default', ['coffee', 'concat', 'clean'])
38
+
39
+
40
+
41
+
data/README.md CHANGED
@@ -45,10 +45,14 @@ Add to ```admin.scss```:
45
45
  Add to ```admin.coffee``` character configuration object:
46
46
 
47
47
  ```coffee
48
- assets: new Loft('Library', 'asset', '/admin/assets')
48
+ loft: new Loft('Files', 'asset', '/admin/assets')
49
49
  ```
50
50
 
51
51
 
52
+ ## Notes
53
+
54
+ 1. Check out [kraken.io](https://github.com/kraken-io/kraken-ruby) for image optimization.
55
+
52
56
  ## Loft family
53
57
 
54
58
  - [Character](https://github.com/slate-studio/chr): Powerful javascript CMS for apps
@@ -1,10 +1,10 @@
1
1
  #= require loft/group-actions
2
2
  #= require loft/asset-item
3
- #= require loft/type-item
4
3
  #= require loft/module
5
4
 
6
- #= require redactor-loft
7
- #= require input-loft-image
5
+ #= require loft/redactor-loft
6
+ #= require loft/input-loft-asset
7
+ #= require loft/input-loft-image
8
8
 
9
9
  # TODOs:
10
- # - refactor group remove action
10
+ # - refactor group remove action: delete a bunch first, then reload the page
@@ -11,10 +11,44 @@
11
11
  # -----------------------------------------------------------------------------
12
12
  class @LoftAssetItem extends Item
13
13
  constructor: (@module, @path, @object, @config) ->
14
- @$el =$ "<div class='item asset asset-#{ @object.type }' data-id='#{ @object._id }' data-title=''></div>"
14
+ @$el =$ "<div class='item asset asset-#{ @object.type }' data-id='#{ @object._id }'></div>"
15
15
  @render()
16
16
 
17
17
 
18
+ # PRIVATE ===============================================
19
+
20
+ _bind_name_input: ->
21
+ @$nameInput.on 'blur', (e) => @_update_name_if_changed()
22
+ @$nameInput.on 'keyup', (e) =>
23
+ if e.keyCode == 13 then $(e.target).blur()
24
+ if e.keyCode == 27 then @_cancel_name_change()
25
+
26
+
27
+ _edit_name: (e) ->
28
+ @$el.addClass('edit-name')
29
+ @$nameInput.focus().select()
30
+
31
+
32
+ _cancel_name_change: ->
33
+ @$el.removeClass('edit-name')
34
+ name = @$title.html()
35
+ @$nameInput.val(name)
36
+
37
+
38
+ _update_name_if_changed: ->
39
+ @$el.removeClass('edit-name')
40
+ name = @$nameInput.val()
41
+
42
+ if name == @$title.html() then return
43
+ @$title.html(name)
44
+
45
+ @config.arrayStore.update @object._id, { '[name]': name },
46
+ onSuccess: (object) =>
47
+ onError: (errors) => # process errors
48
+
49
+
50
+ # PUBLIC ================================================
51
+
18
52
  render: ->
19
53
  @$el.html('').removeClass('item-folder has-subtitle has-thumbnail')
20
54
 
@@ -40,7 +74,7 @@ class @LoftAssetItem extends Item
40
74
 
41
75
 
42
76
  # input for assets name
43
- name = @$el.attr('data-title')
77
+ name = @$title.text()
44
78
  @$name =$ "<div class='asset-name'></div>"
45
79
  @$nameInput =$ "<input type='text' value='#{ name }' />"
46
80
  @$name.append @$nameInput
@@ -51,36 +85,5 @@ class @LoftAssetItem extends Item
51
85
  @$title.on 'click', (e) => @_edit_name(e)
52
86
 
53
87
 
54
- _bind_name_input: ->
55
- @$nameInput.on 'blur', (e) => @_update_name_if_changed()
56
- @$nameInput.on 'keyup', (e) =>
57
- if e.keyCode == 13 then $(e.target).blur()
58
- if e.keyCode == 27 then @_cancel_name_change()
59
-
60
-
61
- _edit_name: (e) ->
62
- @$el.addClass('edit-name')
63
- @$nameInput.focus().select()
64
-
65
-
66
- _cancel_name_change: ->
67
- @$el.removeClass('edit-name')
68
- name = @$title.html()
69
- @$nameInput.val(name)
70
-
71
-
72
- _update_name_if_changed: ->
73
- @$el.removeClass('edit-name')
74
- name = @$nameInput.val()
75
-
76
- if name == @$title.html() then return
77
- @$title.html(name)
78
-
79
- @config.arrayStore.update @object._id, { '[name]': name },
80
- onSuccess: (object) =>
81
- onError: (errors) => # process errors
82
-
83
-
84
-
85
88
 
86
89
 
@@ -15,6 +15,8 @@ class @LoftGroupActions
15
15
  @_bind_checkboxes()
16
16
 
17
17
 
18
+ # PRIVATE ===============================================
19
+
18
20
  _render: ->
19
21
  @$el =$ "<div class='assets-group-actions' style='display:none;'></div>"
20
22
  @list.$header.append @$el
@@ -95,6 +97,8 @@ class @LoftGroupActions
95
97
  @$el.show()
96
98
 
97
99
 
100
+ # PUBLIC ================================================
101
+
98
102
  hide: ->
99
103
  @$el.hide()
100
104
 
@@ -0,0 +1,11 @@
1
+ # -----------------------------------------------------------------------------
2
+ # Author: Alexander Kravets <alex@slatestudio.com>,
3
+ # Slate Studio (http://www.slatestudio.com)
4
+ #
5
+ # Coding Guide:
6
+ # https://github.com/thoughtbot/guides/tree/master/style/coffeescript
7
+ # -----------------------------------------------------------------------------
8
+
9
+ # -----------------------------------------------------------------------------
10
+ # INPUT LOFT ASSET
11
+ # -----------------------------------------------------------------------------
@@ -41,7 +41,7 @@ class @InputLoftImage extends InputString
41
41
 
42
42
  @$chooseBtn.on 'click', (e) =>
43
43
  e.preventDefault()
44
- chr.modules.assets.showModal 'images', false, (objects) =>
44
+ chr.modules.loft.showModal 'images', false, (objects) =>
45
45
  asset = objects[0]
46
46
  @updateValue(asset.file.url)
47
47
 
@@ -8,32 +8,40 @@
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
  # Loft
11
+ # -----------------------------------------------------------------------------
11
12
  #
12
13
  # Public methods:
13
- # new Loft(title, @resource, @resourcePath)
14
+ # new Loft(title, resource, resourcePath, @arrayStoreClass, @arrayStoreConfig)
14
15
  # showModal(assetType, @selectMultipleAssets, @onAcceptCallback)
15
16
  # closeModal()
16
17
  #
17
18
  # -----------------------------------------------------------------------------
18
19
  class @Loft
19
- constructor: (title, @resource, @resourcePath) ->
20
+ constructor: (title, resource, resourcePath, @arrayStoreClass, @arrayStoreConfig) ->
20
21
  @module = {}
21
22
  @store = {}
22
23
 
24
+ @arrayStoreClass ?= RailsArrayStore
25
+ @arrayStoreConfig ?=
26
+ resource: resource
27
+ path: resourcePath
28
+ sortBy: 'created_at'
29
+ sortReverse: true
30
+ searchable: true
31
+
23
32
  @_uploadsCounter = 0
24
33
 
25
34
  moduleConfig =
26
35
  title: title
27
36
  showNestedListsAside: true
28
- itemClass: LoftTypeItem
29
37
  items:
30
- assets_all: @_nested_list_config 'All'
31
- assets_images: @_nested_list_config 'Images', 'image'
32
- assets_text: @_nested_list_config 'Text', 'text'
33
- assets_archives: @_nested_list_config 'Archives', 'archive'
34
- assets_audio: @_nested_list_config 'Audio', 'audio'
35
- assets_video: @_nested_list_config 'Video', 'video'
36
- assets_other: @_nested_list_config 'Other', 'other'
38
+ loft_all: @_nested_list_config 'All'
39
+ loft_images: @_nested_list_config 'Images', 'image'
40
+ loft_text: @_nested_list_config 'Text', 'text'
41
+ loft_archives: @_nested_list_config 'Archives', 'archive'
42
+ loft_audio: @_nested_list_config 'Audio', 'audio'
43
+ loft_video: @_nested_list_config 'Video', 'video'
44
+ loft_other: @_nested_list_config 'Other', 'other'
37
45
 
38
46
  onModuleInit: (module) =>
39
47
  @_initialize_module(module)
@@ -41,9 +49,11 @@ class @Loft
41
49
  return moduleConfig
42
50
 
43
51
 
52
+ # PRIVATE ===============================================
53
+
44
54
  _initialize_module: (module) ->
45
55
  @module = module
46
- @store = @module.nestedLists.assets_all.config.arrayStore
56
+ @store = @module.nestedLists.loft_all.config.arrayStore
47
57
 
48
58
  # API method
49
59
  @module.showModal = (assetType, selectMultipleAssets, callback) =>
@@ -55,28 +65,40 @@ class @Loft
55
65
  @module.rootList.$header.prepend @module.rootList.$modalCloseBtn
56
66
  @module.rootList.$modalCloseBtn.on 'click', (e) => e.preventDefault() ; @closeModal()
57
67
 
68
+ # modal types navigation
69
+ @module.rootList.$items.on 'click', 'a', (e) =>
70
+ if @module.$el.hasClass 'module-modal'
71
+ e.preventDefault()
72
+
73
+ $item = $(e.currentTarget)
74
+ listName = $item.attr('href').split('/')[2]
75
+
76
+ @module.activeList.hide()
77
+ @module.showList(listName)
78
+ @module.activeList.updateItems()
79
+
80
+ $item.parent().children('.active').removeClass('active')
81
+ $item.addClass('active')
82
+
58
83
  # enable grid mode as default on desktop/tablet
59
84
  if ! chr.isMobile()
60
85
  @module.$el.addClass('grid-mode')
61
86
 
62
87
 
63
88
  _nested_list_config: (moduleName, assetType) ->
64
- arrayStoreConfig =
65
- resource: @resource
66
- path: @resourcePath
67
- searchable: true
68
- sortBy: 'created_at'
69
- sortReverse: true
89
+ storeConfig = {}
90
+ $.extend(storeConfig, @arrayStoreConfig)
70
91
 
71
92
  if assetType
72
- $.extend(arrayStoreConfig, { urlParams: { by_type: assetType } })
93
+ $.extend(storeConfig, { urlParams: { by_type: assetType } })
73
94
 
74
95
  config =
75
96
  title: moduleName
76
97
  itemTitleField: 'name'
77
98
  itemSubtitleField: 'created_ago'
99
+ showWithParent: true
78
100
  itemClass: LoftAssetItem
79
- arrayStore: new MongosteenArrayStore(arrayStoreConfig)
101
+ arrayStore: new @arrayStoreClass(storeConfig)
80
102
  onListInit: (list) => @_inititialize_list(list)
81
103
  onListShow: (list) => @_clear_assets_selection()
82
104
 
@@ -102,6 +124,12 @@ class @Loft
102
124
  list.$backBtn.after list.$switchMode
103
125
  list.$switchMode.on 'click', (e) => e.preventDefault() ; @module.$el.toggleClass('grid-mode')
104
126
 
127
+ # modal back for mobiles
128
+ list.$header.on 'click', '.back', (e) =>
129
+ if @module.$el.hasClass 'module-modal'
130
+ e.preventDefault()
131
+ @module.showList()
132
+
105
133
 
106
134
  _upload: (file, list) ->
107
135
  obj = {}
@@ -125,11 +153,10 @@ class @Loft
125
153
  if @_uploadsCounter == 0
126
154
  @module.$el.removeClass('assets-uploading')
127
155
 
128
- # update data in list if it's not assets_all,
129
- # in assets_all new objects are added automatically
130
- visibleList = @module.visibleNestedListShownWithParent()
131
- if visibleList.name != 'assets_all'
132
- visibleList.updateItems()
156
+ # update data in list if it's not loft_all,
157
+ # in loft_all new objects are added automatically
158
+ if @module.activeList.name != 'loft_all'
159
+ @module.activeList.updateItems()
133
160
 
134
161
 
135
162
  _clear_assets_selection: ->
@@ -138,6 +165,8 @@ class @Loft
138
165
  list.$items.find('.asset-checkbox').prop('checked', false)
139
166
 
140
167
 
168
+ # PUBLIC ================================================
169
+
141
170
  closeModal: ->
142
171
  @selectMultipleAssets = true
143
172
  @_clear_assets_selection()
@@ -149,13 +178,14 @@ class @Loft
149
178
  showModal: (assetType='all', @selectMultipleAssets=false, @onAcceptCallback=$.noop) ->
150
179
  # modal mode
151
180
  @module.$el.addClass('module-modal')
181
+ # show module
182
+ @module.show()
152
183
  # show nested list
153
- @module.showNestedList("assets_#{ assetType }")
184
+ @module.showList("loft_#{ assetType }")
185
+ @module.activeList.updateItems()
154
186
  # select active item
155
187
  @module.rootList.$items.children().removeClass('active')
156
- @module.rootList.$items.children("[href='#/assets/assets_#{ assetType }']").addClass('active')
157
- # show module
158
- @module.show()
188
+ @module.rootList.$items.children("[href='#/loft/loft_#{ assetType }']").addClass('active')
159
189
 
160
190
 
161
191
 
@@ -23,13 +23,13 @@ RedactorPlugins.loft = ->
23
23
 
24
24
 
25
25
  showImagesModal: ->
26
- chr.modules.assets.showModal 'images', true, (objects) => @loft.insertImages(objects)
26
+ chr.modules.loft.showModal 'images', true, (objects) => @loft.insertImages(objects)
27
27
 
28
28
 
29
29
  # allow multiple assets when no text is selected
30
30
  showAllModal: ->
31
31
  multipleAssets = this.selection.getText() == ''
32
- chr.modules.assets.showModal 'all', multipleAssets, (objects) => @loft.insertFiles(objects)
32
+ chr.modules.loft.showModal 'all', multipleAssets, (objects) => @loft.insertFiles(objects)
33
33
 
34
34
 
35
35
  # if text is selected replace text with <a>{{ text }}</a>
@@ -7,11 +7,6 @@
7
7
 
8
8
  // MIXINS
9
9
 
10
- @mixin iconBase($bgSize, $width, $height) {
11
- background-image: image-url('loft/library@3x.png'); background-size: $bgSize;
12
- display: block; width: $width; height: $height;
13
- }
14
-
15
10
  @mixin iconLabel($title) {
16
11
  &:before {
17
12
  display: block; margin-top: 2.6em;
@@ -21,13 +16,17 @@
21
16
  }
22
17
  }
23
18
 
19
+ @mixin iconBase($bgSize, $width, $height) {
20
+ display: block; background-size: $bgSize; width: $width; height: $height;
21
+ background-image: image-url("loft/library@3x.png");
22
+ }
24
23
 
25
24
  // ASSET TYPE ICONS
26
25
 
27
- .module.assets .list:first-child .items {
26
+ .loft .list:first-child .items {
28
27
  .item {
29
28
  .item-title { margin-left: 2.05em; }
30
- &:before { @include absolutePosition(inherit inherit inherit 1em); content: ''; display: block; }
29
+ &:before { @include position(absolute, null null null 1em); content: ''; display: block; }
31
30
  }
32
31
 
33
32
  .item {
@@ -63,24 +62,24 @@
63
62
 
64
63
  // LIST MODE
65
64
 
66
- .module.assets .list:not(:first-child) .items .item.asset {
65
+ .loft .list:not(:first-child) .items .item.asset {
67
66
  padding-left: 6.25em; // 100px;
68
67
 
69
68
  // checkbox
70
69
  .asset-checkbox {
71
- @include absolutePosition(1.3em inherit inherit 1em); z-index: 1;
72
- input { @include absolutePosition(0px inherit inherit 0px); }
70
+ @include position(absolute, 1.3em null null 1em); z-index: 1;
71
+ input { @include position(absolute, 0px null null 0px); }
73
72
  }
74
73
 
75
74
  // type icon
76
75
  .asset-icon {
77
76
  @include iconBase(64px 224px, 32px, 32px);
78
- @include absolutePosition(12px inherit inherit 3.05em);
77
+ @include position(absolute, 12px null null 3.05em);
79
78
  }
80
79
 
81
80
  // image thumbnail
82
81
  &.asset-image .asset-icon {
83
- @include absolutePosition(8px inherit inherit 2.8em);
82
+ @include position(absolute, 8px null null 2.8em);
84
83
  overflow: hidden; width: 40px; height: 40px; border-radius: 20px;
85
84
  img { height: 100%; }
86
85
  }
@@ -99,8 +98,8 @@
99
98
  .item-title { cursor: pointer; }
100
99
  .asset-name {
101
100
  display: none; z-index: 1;
102
- @include absolutePosition(7px .5em inherit 94px);
103
- input { width: 100%; padding: .1em .3em .3em .3em; @include noFocus();
101
+ @include position(absolute, 7px .5em null 94px);
102
+ input { width: 100%; padding: .1em .3em .3em .3em; @include no-focus-outline;
104
103
  border: 1px solid $stableColor; box-shadow: 0 0 10px $lightColor; border-radius: 3px; }
105
104
  }
106
105
  &.edit-name .asset-name { display: block; }
@@ -115,10 +114,10 @@
115
114
  // GROUP ACTIONS
116
115
 
117
116
  .assets-group-actions {
118
- @include absolutePosition(0 0 0 0); background: $white;
119
- .accept { @include headerButton($positiveColor); float: right; margin-right: 1em; }
120
- .delete { @include headerButton($assertiveColor); float: right; margin-right: 1em; }
121
- .unselect { @include headerButton($stableColor); float: left; margin-left: 1em; }
117
+ @include position(absolute, 0 0 0 0); background: $white;
118
+ .accept { @include header-button($positiveColor); float: right; margin-right: 1em; }
119
+ .delete { @include header-button($assertiveColor); float: right; margin-right: 1em; }
120
+ .unselect { @include header-button($stableColor); float: left; margin-left: 1em; }
122
121
  }
123
122
 
124
123
  .assets-group-actions .accept { display: none; }
@@ -129,28 +128,24 @@
129
128
  // UPLOAD BUTTON
130
129
 
131
130
  .asset-upload {
132
- @include absolutePosition(0 -40px inherit inherit);
133
- @extend .icon-plus; @include noFocus;
131
+ @include position(absolute, 0 -40px null null);
132
+ @extend .icon-plus; @include no-focus-outline;
134
133
  cursor: pointer; padding-left: 80px;
135
134
  }
136
135
 
137
- .list header .asset-upload + .search { @include absolutePosition(0 40px inherit inherit); }
138
- .list.list-search header .asset-upload + .search { @include absolutePosition(0 0 inherit 0); }
139
- .module.assets.assets-uploading .list:not(:first-child) header .spinner { display: inline-block; }
136
+ .list header .asset-upload + .search { @include position(absolute, 0 40px null null); }
137
+ .list.list-search header .asset-upload + .search { @include position(absolute, 0 0 null 0); }
138
+ .loft.assets-uploading .list:not(:first-child) header .spinner { display: inline-block; }
140
139
 
141
140
 
142
141
  // MODAL MODE
143
142
 
144
- .module.assets {
145
- .modal-close {
146
- display: none;
147
- @include headerButton();
148
- @include absolutePosition(null null null 1em );
149
- }
143
+ .loft {
144
+ .modal-close { @include hide(); }
150
145
  &.module-modal {
151
- @include absolutePosition(.5em .5em 0em .5em); z-index: 1100;
146
+ @include position(absolute, 0 .5em 0 .5em); z-index: 1100;
152
147
 
153
- &:after { display: none; }
148
+ &:after { @include hide(); }
154
149
 
155
150
  // dark background
156
151
  &:before {
@@ -158,53 +153,53 @@
158
153
  content: ''; display: block; background: rgba(0,0,0,.25);
159
154
  }
160
155
 
161
- .modal-close { display: inline; }
156
+ .modal-close { @include header-button(); @include position(absolute, null null null 1em ); }
157
+ .header { top: 0; left: .5em; right: .5em; width: auto; }
158
+
162
159
  .list:first-child .back { display: none }
163
160
  }
164
161
  }
165
162
 
166
163
 
167
- /* TABLET LAYOUT */
168
-
169
- @media #{ $tablet } {
170
- .module.assets .list:not(:first-child) .items { font-size: 1em; }
171
-
172
- // ITEM
173
- .module.assets .list:not(:first-child) .items .item.asset {
164
+ /* Tablet ------------------------------------------------------------------ */
165
+ @media #{$tablet} {
166
+ // ITEMS
167
+ .loft .list:not(:first-child) .items { font-size: 1em; }
168
+ .loft .list:not(:first-child) .items .item.asset {
174
169
  padding-top: 19px; padding-bottom: 19px;
175
170
  .item-title {
176
171
  display: inline; cursor: pointer;
177
172
  &:hover { color: $positiveColor; text-decoration: underline; }
178
173
  }
179
- .item-subtitle { @include absolutePosition(1.55em 1em inherit inherit); }
174
+ .item-subtitle { @include position(absolute, 1.55em 1em null null); }
180
175
  .asset-name { top: 16px; }
181
176
  }
182
177
 
183
178
  // MODAL MODE
184
- .module.assets.module-modal { @include absolutePosition(1.5em 1.5em 0em 1.5em) }
179
+ .loft.module-modal { @include position(absolute, 1.5em 1.5em 0em 1.5em) }
180
+ .loft.module-modal .header { top: 0; left: 0; right: 0; width: auto; }
185
181
 
186
182
 
187
183
  // GRID MODE
188
184
  .assets-switch-mode {
189
- @include absolutePosition(inherit inherit inherit 1em);
190
- display: inline;
191
- font-size: .9em;
185
+ @include position(absolute, null null null 1em);
186
+ display: inline; font-size: .9em; line-height: 2.9; left: 3em;
192
187
  &:before { content: 'Grid'; color: $lightColor; margin-right: .25em; }
193
188
  &:after { content: 'List'; color: $stableColor; }
194
189
  }
195
- .module.assets.grid-mode .assets-switch-mode {
190
+ .loft.grid-mode .assets-switch-mode {
196
191
  &:before { color: $stableColor; }
197
192
  &:after { color: $lightColor; }
198
193
  }
199
194
 
200
- .module.assets.grid-mode {
195
+ .loft.grid-mode {
201
196
  .list:not(:first-child) .items {
202
197
  padding: .25em .25em 5em .75em;
203
198
  .item.asset { margin: 0 .75em 1.5em; float: left; display: inline-block; }
204
199
 
205
200
  .item.asset {
206
201
  padding-left: 1em; width: 222px; height: 222px;
207
- @include noBorder(); border: 1px solid $contrastColor; border-radius: 4px;
202
+ @include no-bottom-border; border: 1px solid $contrastColor; border-radius: 4px;
208
203
 
209
204
  // checkbox: position + decoration
210
205
  .asset-checkbox {
@@ -214,9 +209,9 @@
214
209
 
215
210
  // thumbnail
216
211
  .asset-icon {
217
- @include absolutePosition(10px inherit inherit 10px);
212
+ @include position(absolute, 10px null null 10px);
218
213
  width: 200px; height: 150px; background: $white; border-radius: 0;
219
- &:after { @include absolutePosition(0px 0px 0px 0px); box-shadow: 0 0 1px rgba(0,0,0,0.2) inset; content: ''; display: block; }
214
+ &:after { @include position(absolute, 0px 0px 0px 0px); box-shadow: 0 0 1px rgba(0,0,0,0.2) inset; content: ''; display: block; }
220
215
  }
221
216
 
222
217
  .asset-thumbnail-small { display: none; }
@@ -239,6 +234,15 @@
239
234
  }
240
235
 
241
236
 
237
+ /* Desktop ----------------------------------------------------------------- */
238
+ @media #{$desktop} {
239
+ // BACK
240
+ .loft .list:not(:first-child) .back { @include hide; }
241
+
242
+ // GRID MODE
243
+ .assets-switch-mode { left: 1em; }
244
+ }
245
+
242
246
 
243
247
 
244
248