alchemy-media 0.6.2 → 0.6.4

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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## 0.6.4 (2022-10-13)
2
+
3
+ * Add the `Media#loadIconFont()` helper method
4
+ * Make the `image` route serve up filetype thumbnails for non-images
5
+ * Add file preview image to the chimera edit view of MediaFile
6
+ * Add thumbnail column to MediaFile chimera index view
7
+ * Add `prefix` parameter to the `MediaFile#data` route
8
+
9
+ ## 0.6.3 (2022-07-23)
10
+
11
+ * Fix `al-file` element showing wrong buttons on load
12
+ * Always add `role="presentation"` to images that get a simple placeholder
13
+ * Add support for Fontawesome Pro with the `media.fontawesome_pro` setting
14
+
1
15
  ## 0.6.2 (2022-07-06)
2
16
 
3
17
  * Upgrade to Fontawesome 6
@@ -1,66 +1,10 @@
1
- @import "fontawesome6/fontawesome.scss";
2
- @import "fontawesome6/solid.scss";
3
- @import "fontawesome6/brands.scss";
4
-
5
1
  al-ico {
6
- --fa-display: inline-flex;
7
- @extend %fa-icon;
2
+ // inline-flex breaks certain (duotone) icons
3
+ //--fa-display: inline-flex;
8
4
  flex-flow: column;
9
- justify-content: center;
10
- align-content: center;
11
- text-align: center;
12
-
13
- &[type="arrow-left"] {
14
- @extend .fas, .fa-angle-left;
15
- }
16
-
17
- &[type="arrow-left-double"] {
18
- @extend .fas, .fa-angle-double-left;
19
- }
20
-
21
- &[type="arrow-right"] {
22
- @extend .fas, .fa-angle-right;
23
- }
24
-
25
- &[type="arrow-right-double"] {
26
- @extend .fas, .fa-angle-double-right;
27
- }
28
-
29
- &[type="sorting-arrow"] {
30
- @extend .fas;
31
-
32
- &.down {
33
- @extend .fa-sort-alpha-up;
34
- }
35
-
36
- &.up {
37
- @extend .fa-sort-alpha-down;
38
- }
39
- }
40
-
41
- &[type="menu"] {
42
- @extend .fas, .fa-bars;
43
- }
44
-
45
- &[type="edit"] {
46
- @extend .fas, .fa-pencil-alt;
47
- }
48
-
49
- &[type="zoom-in"] {
50
- @extend .fas, .fa-search-plus;
51
- }
52
-
53
- &[type="microphone"] {
54
- @extend .fas, .fa-microphone-alt;
55
- }
56
-
57
- &[type="video"] {
58
- @extend .fas, .fa-video;
59
- }
60
-
61
- &[type="plus"] {
62
- @extend .fas, .fa-plus;
63
- }
5
+ justify-content: center;
6
+ align-content: center;
7
+ text-align: center;
64
8
 
65
9
  &[hidden] {
66
10
  display: none !important;
@@ -0,0 +1,59 @@
1
+ @use "fontawesome6/fontawesome.scss";
2
+ @use "fontawesome6/solid.scss";
3
+ @use "fontawesome6/brands.scss";
4
+
5
+ al-ico {
6
+ @extend %fa-icon;
7
+
8
+ &[type="arrow-left"] {
9
+ @extend .fas, .fa-angle-left;
10
+ }
11
+
12
+ &[type="arrow-left-double"] {
13
+ @extend .fas, .fa-angle-double-left;
14
+ }
15
+
16
+ &[type="arrow-right"] {
17
+ @extend .fas, .fa-angle-right;
18
+ }
19
+
20
+ &[type="arrow-right-double"] {
21
+ @extend .fas, .fa-angle-double-right;
22
+ }
23
+
24
+ &[type="sorting-arrow"] {
25
+ @extend .fas;
26
+
27
+ &.down {
28
+ @extend .fa-sort-alpha-up;
29
+ }
30
+
31
+ &.up {
32
+ @extend .fa-sort-alpha-down;
33
+ }
34
+ }
35
+
36
+ &[type="menu"] {
37
+ @extend .fas, .fa-bars;
38
+ }
39
+
40
+ &[type="edit"] {
41
+ @extend .fas, .fa-pencil-alt;
42
+ }
43
+
44
+ &[type="zoom-in"] {
45
+ @extend .fas, .fa-search-plus;
46
+ }
47
+
48
+ &[type="microphone"] {
49
+ @extend .fas, .fa-microphone-alt;
50
+ }
51
+
52
+ &[type="video"] {
53
+ @extend .fas, .fa-video;
54
+ }
55
+
56
+ &[type="plus"] {
57
+ @extend .fas, .fa-plus;
58
+ }
59
+ }
@@ -92,4 +92,30 @@ al-file {
92
92
  button {
93
93
  min-height: 2rem;
94
94
  }
95
+ }
96
+
97
+ alchemy-field[field-view="file_preview"] {
98
+ [data-he-name="field"] .field {
99
+ padding: 0;
100
+
101
+ img {
102
+ max-height: 25rem;
103
+ object-fit: contain;
104
+ }
105
+ }
106
+ }
107
+
108
+ alchemy-field[field-view="file_preview"],
109
+ alchemy-field[field-view="file"],
110
+ alchemy-field[field-type="file"] {
111
+
112
+ &[mode="inline"] {
113
+ .field img {
114
+ object-fit: contain;
115
+ width: 100px;
116
+ height: 100px;
117
+ display: block;
118
+ margin: auto;
119
+ }
120
+ }
95
121
  }
package/bootstrap.js CHANGED
@@ -21,7 +21,10 @@ var options = {
21
21
  scratch: path.resolve(PATH_TEMP, 'scratch'),
22
22
 
23
23
  // The cache map for resized images & thumbnails
24
- cache: path.resolve(PATH_TEMP, 'imagecache')
24
+ cache: path.resolve(PATH_TEMP, 'imagecache'),
25
+
26
+ // Path to fontawesome pro
27
+ fontawesome_pro: null,
25
28
  };
26
29
 
27
30
  // Inject the user-overridden options
@@ -40,7 +43,9 @@ alchemy.createDir(options.cache);
40
43
  Router.get('Media::static', /\/media\/static\/(.*)*/, 'MediaFile#serveStatic');
41
44
  Router.get('Media::image', options.url + '/{id}', 'MediaFile#image');
42
45
 
43
- Router.get('MediaFile#data', '/media/data/{[MediaFile._id]id}', 'MediaFile#data');
46
+ // The prefix is added at the end of the route so it does not
47
+ // change the user's active_prefix
48
+ Router.get('MediaFile#data', '/media/data/{prefix}/{id}', 'MediaFile#data');
44
49
  Router.get('MediaFile#info', '/media/info', 'MediaFile#info');
45
50
 
46
51
  // Allow dummy extensions
@@ -66,6 +71,10 @@ options.veronica = new Veronica({
66
71
 
67
72
  alchemy.hawkejs.addRawHtml(`<script>document.cookie = 'mediaResolution=' + encodeURIComponent(JSON.stringify({width:Math.max(screen.availWidth||0, window.outerWidth||0) || 1024,height:Math.max(screen.availHeight||0, window.outerHeight||0) || 768,dpr:window.devicePixelRatio}))</script>`);
68
73
 
74
+ if (options.fontawesome_pro) {
75
+ alchemy.exposeStatic('fontawesome_pro', options.fontawesome_pro);
76
+ }
77
+
69
78
  /**
70
79
  * Register a profile under the given name
71
80
  *
@@ -13,16 +13,14 @@ var fs = require('fs'),
13
13
  * @since 0.0.1
14
14
  * @version 0.3.0
15
15
  */
16
- var MediaFiles = Function.inherits('Alchemy.Controller', function MediaFile(conduit, options) {
17
- MediaFile.super.call(this, conduit, options);
18
- });
16
+ const MediaFiles = Function.inherits('Alchemy.Controller', 'MediaFile');
19
17
 
20
18
  /**
21
19
  * Serve a thumbnail
22
20
  *
23
21
  * @author Jelle De Loecker <jelle@develry.be>
24
22
  * @since 0.0.1
25
- * @version 0.4.1
23
+ * @version 0.6.4
26
24
  *
27
25
  * @param {Conduit} conduit
28
26
  */
@@ -35,21 +33,15 @@ MediaFiles.setAction(function thumbnail(conduit, id) {
35
33
  // Get the requested file
36
34
  this.getModel('MediaFile').getFile(id, function gotFile(err, record) {
37
35
 
38
- var Type;
39
-
40
36
  if (err) {
41
37
  return conduit.notFound(err);
42
38
  }
43
39
 
44
- Type = MediaTypes[record.type];
45
-
46
- if (!Type) {
47
- Type = Classes.Alchemy.MediaType;
48
- }
40
+ const Type = MediaTypes[record.type] || Classes.Alchemy.MediaType;
49
41
 
50
42
  if (Type) {
51
- Type = new Type();
52
- Type.thumbnail(conduit, record);
43
+ let instance = new Type();
44
+ instance.thumbnail(conduit, record);
53
45
  } else {
54
46
  conduit.error('Error generating thumbnail of ' + record.type);
55
47
  }
@@ -100,7 +92,7 @@ MediaFiles.setAction(function serveStatic(conduit, path) {
100
92
  *
101
93
  * @author Jelle De Loecker <jelle@develry.be>
102
94
  * @since 0.0.1
103
- * @version 0.4.1
95
+ * @version 0.6.4
104
96
  *
105
97
  * @param {Conduit} conduit
106
98
  */
@@ -112,12 +104,22 @@ MediaFiles.setAction(function image(conduit, id) {
112
104
 
113
105
  this.getModel('MediaFile').getFile(id, function gotFile(err, record) {
114
106
 
115
- var Image = new MediaTypes.image;
107
+ if (err) {
108
+ return conduit.error(err);
109
+ }
110
+
111
+ const Image = new MediaTypes.image;
116
112
 
117
113
  if (!record) {
118
114
  return Image.placeholder(conduit, {text: 404, status: 404});
119
115
  }
120
116
 
117
+ if (record.type != 'image') {
118
+ const Type = MediaTypes[record.type] || Classes.Alchemy.MediaType;
119
+ let instance = new Type();
120
+ return instance.thumbnail(conduit, record);
121
+ }
122
+
121
123
  Image.serve(conduit, record);
122
124
  });
123
125
  });
@@ -315,14 +317,23 @@ MediaFiles.setAction(function uploadsingle(conduit) {
315
317
  /**
316
318
  * Get the file data
317
319
  *
318
- * @author Jelle De Loecker <jelle@develry.be>
320
+ * @author Jelle De Loecker <jelle@elevenways.be>
319
321
  * @since 0.5.1
320
- * @version 0.5.1
322
+ * @version 0.6.4
321
323
  *
322
- * @param {Conduit} conduit
323
- * @param {Document.MediaFile} media_file
324
+ * @param {Conduit} conduit
325
+ * @param {ObjectId} media_file_id
324
326
  */
325
- MediaFiles.setAction(function data(conduit, media_file) {
327
+ MediaFiles.setAction(async function data(conduit, prefix, media_file_id) {
328
+
329
+ conduit.prefix = prefix;
330
+
331
+ let media_file = await this.model.findById(media_file_id);
332
+
333
+ if (!media_file) {
334
+ return conduit.notFound();
335
+ }
336
+
326
337
  conduit.setHeader('cache-control', 'public, max-age=3600, must-revalidate');
327
338
 
328
339
  conduit.end({
@@ -14,4 +14,133 @@ const Icon = Function.inherits('Alchemy.Element', 'AlIco');
14
14
  * @since 0.6.0
15
15
  * @version 0.6.0
16
16
  */
17
- Icon.setStylesheetFile('alchemy_icons');
17
+ Icon.setStylesheetFile('alchemy_icons');
18
+
19
+ /**
20
+ * The source to use
21
+ * (Will default to Fontawesome)
22
+ *
23
+ * @author Jelle De Loecker <jelle@elevenways.be>
24
+ * @since 0.6.3
25
+ * @version 0.6.3
26
+ */
27
+ Icon.setAttribute('source');
28
+
29
+ /**
30
+ * The icon-style to use
31
+ * (Will default to regular for fontawesome)
32
+ *
33
+ * @author Jelle De Loecker <jelle@elevenways.be>
34
+ * @since 0.6.3
35
+ * @version 0.6.3
36
+ */
37
+ Icon.setAttribute('icon-style');
38
+
39
+ /**
40
+ * The actual icon name to use
41
+ *
42
+ * @author Jelle De Loecker <jelle@elevenways.be>
43
+ * @since 0.6.3
44
+ * @version 0.6.3
45
+ */
46
+ Icon.setAttribute('icon-name');
47
+
48
+ /**
49
+ * The element is being retained
50
+ *
51
+ * @author Jelle De Loecker <jelle@elevenways.be>
52
+ * @since 0.6.3
53
+ * @version 0.6.3
54
+ */
55
+ Icon.setMethod(function retained() {
56
+ this.setCssClasses();
57
+ });
58
+
59
+ /**
60
+ * The element has been introduced to the DOM for the first time
61
+ *
62
+ * @author Jelle De Loecker <jelle@elevenways.be>
63
+ * @since 0.6.3
64
+ * @version 0.6.3
65
+ */
66
+ Icon.setMethod(function introduced() {
67
+ this.setCssClasses();
68
+ });
69
+
70
+ /**
71
+ * Try to set the correct icon
72
+ *
73
+ * @author Jelle De Loecker <jelle@elevenways.be>
74
+ * @since 0.6.3
75
+ * @version 0.6.3
76
+ */
77
+ Icon.setMethod(function setIcon(info) {
78
+
79
+ if (!info) {
80
+ return;
81
+ }
82
+
83
+ if (typeof info == 'string') {
84
+ info = info.split(' ');
85
+
86
+ if (info.length == 2) {
87
+ this.icon_style = info[0];
88
+ this.icon_name = info[1];
89
+ } else {
90
+ this.icon_name = info[0];
91
+ }
92
+ } else if (typeof info == 'object') {
93
+ let style = info.style || info.icon_style,
94
+ name = info.name || info.icon_name;
95
+
96
+ if (style) {
97
+ this.icon_style = style;
98
+ }
99
+
100
+ if (name) {
101
+ this.icon_name = name;
102
+ }
103
+ }
104
+
105
+ if (!this.icon_style) {
106
+ this.icon_style = 'duotone';
107
+ }
108
+ });
109
+
110
+ /**
111
+ * Set the CSS classes
112
+ *
113
+ * @author Jelle De Loecker <jelle@elevenways.be>
114
+ * @since 0.6.3
115
+ * @version 0.6.4
116
+ */
117
+ Icon.setMethod(function setCssClasses() {
118
+
119
+ if (this.source && this.source != 'fontawesome') {
120
+ return;
121
+ }
122
+
123
+ // Load the appropriate font style
124
+ this.hawkejs_renderer.helpers.Media.loadIconFont();
125
+
126
+ let fa_pro = this.hawkejs_renderer.expose('fontawesome_pro'),
127
+ style = this.icon_style || 'regular';
128
+
129
+ if (!fa_pro) {
130
+ if (style == 'duotone' || style == 'light' || style == 'thin' || style == 'regular') {
131
+ style = 'solid';
132
+ }
133
+ }
134
+
135
+ let existing_classes = Array.cast(this.classList);
136
+
137
+ // Remove existing fontawesome classes
138
+ for (let entry of existing_classes) {
139
+ if (entry.startsWith('fa')) {
140
+ this.classList.remove(entry);
141
+ }
142
+ }
143
+
144
+ this.classList.add('fa-' + (this.icon_style || 'solid'));
145
+ this.classList.add('fa-' + this.icon_name);
146
+ });
@@ -1,3 +1,5 @@
1
+ const PLACEHOLDER = Symbol('placeholder');
2
+
1
3
  /**
2
4
  * The Media helper
3
5
  *
@@ -7,9 +9,7 @@
7
9
  *
8
10
  * @param {ViewRender} view
9
11
  */
10
- var Media = Function.inherits('Alchemy.Helper', function Media(view) {
11
- Media.super.call(this, view);
12
- });
12
+ const Media = Function.inherits('Alchemy.Helper', 'Media');
13
13
 
14
14
  /**
15
15
  * Function to execute on the client side, when the scene is made
@@ -88,6 +88,28 @@ Media.setStatic(function loadImagesBasedOnSize() {
88
88
  }
89
89
  });
90
90
 
91
+ /**
92
+ * Load the icon font
93
+ *
94
+ * @author Jelle De Loecker <jelle@elevenways.be>
95
+ * @since 0.6.4
96
+ * @version 0.6.4
97
+ *
98
+ * @return {string}
99
+ */
100
+ Media.setMethod(function loadIconFont() {
101
+
102
+ let font_style = this.hawkejs_renderer.expose('fontawesome_pro');
103
+
104
+ if (!font_style) {
105
+ font_style = 'alchemy_icons_fafree';
106
+ }
107
+
108
+ this.hawkejs_renderer.style(font_style);
109
+
110
+ return font_style;
111
+ });
112
+
91
113
  /**
92
114
  * Apply directive to an element
93
115
  *
@@ -159,6 +181,11 @@ Media.setMethod(function applyDirective(element, image, options) {
159
181
  return;
160
182
  }
161
183
 
184
+ if (options[PLACEHOLDER]) {
185
+ element.setAttribute('alt', '');
186
+ element.setAttribute('role', 'presentation');
187
+ }
188
+
162
189
  if (!String(image).isHex()) {
163
190
  return;
164
191
  }
@@ -168,7 +195,8 @@ Media.setMethod(function applyDirective(element, image, options) {
168
195
  this.view.helpers.Alchemy.getResource({
169
196
  name: 'MediaFile#data',
170
197
  params: {
171
- id: image
198
+ id : image,
199
+ prefix : this.view.expose('active_prefix') || '__',
172
200
  }
173
201
  }, function gotResult(err, data) {
174
202
 
@@ -275,9 +303,9 @@ Media.setMethod(function imageUrl(image_id, options) {
275
303
  /**
276
304
  * Create a base placeholder image url
277
305
  *
278
- * @author Jelle De Loecker <jelle@develry.be>
306
+ * @author Jelle De Loecker <jelle@elevenways.be>
279
307
  * @since 0.2.0
280
- * @version 0.2.0
308
+ * @version 0.6.2
281
309
  *
282
310
  * @param {Object} options
283
311
  *
@@ -306,6 +334,8 @@ Media.setMethod(function placeholderUrl(options) {
306
334
  if (options.text) {
307
335
  url.addQuery('text', options.text);
308
336
  }
337
+
338
+ options[PLACEHOLDER] = true;
309
339
  }
310
340
 
311
341
  return url;
@@ -4,8 +4,8 @@
4
4
  * @constructor
5
5
  *
6
6
  * @author Jelle De Loecker <jelle@elevenways.be>
7
- * @since 0.1.0
8
- * @version 0.1.0
7
+ * @since 0.6.0
8
+ * @version 0.6.0
9
9
  *
10
10
  * @param {Object} data
11
11
  */
@@ -15,8 +15,8 @@ const Image = Function.inherits('Alchemy.Widget', 'Image');
15
15
  * Prepare the schema
16
16
  *
17
17
  * @author Jelle De Loecker <jelle@elevenways.be>
18
- * @since 0.1.0
19
- * @version 0.1.0
18
+ * @since 0.6.0
19
+ * @version 0.6.0
20
20
  */
21
21
  Image.constitute(function prepareSchema() {
22
22
 
@@ -29,8 +29,8 @@ Image.constitute(function prepareSchema() {
29
29
  * Populate the widget
30
30
  *
31
31
  * @author Jelle De Loecker <jelle@elevenways.be>
32
- * @since 0.1.0
33
- * @version 0.1.0
32
+ * @since 0.6.0
33
+ * @version 0.6.4
34
34
  *
35
35
  * @param {HTMLElement} widget
36
36
  */
@@ -40,7 +40,7 @@ Image.setMethod(function populateWidget() {
40
40
 
41
41
  this.hawkejs_renderer.helpers.Media.applyDirective(img, this.config.image);
42
42
 
43
- populateWidget.super.call(this);
44
-
45
43
  this.widget.append(img);
44
+
45
+ return populateWidget.super.call(this);
46
46
  });
@@ -14,10 +14,10 @@ var exiv2 = alchemy.use('@11ways/exiv2'),
14
14
  * @author Jelle De Loecker <jelle@develry.be>
15
15
  * @since 0.0.1
16
16
  * @version 0.2.0
17
+ *
18
+ * @param {Object} options
17
19
  */
18
- var ImageMedia = Function.inherits('Alchemy.MediaType', function ImageMediaType(options) {
19
- ImageMediaType.super.call(this, options);
20
- });
20
+ const ImageMedia = Function.inherits('Alchemy.MediaType', 'ImageMediaType');
21
21
 
22
22
  ImageMedia.setProperty('exivPath', alchemy.plugins.media.exiv2);
23
23
  ImageMedia.setProperty('hashType', alchemy.plugins.media.hash);
@@ -19,32 +19,48 @@ var MediaFile = Function.inherits('Alchemy.Model', function MediaFile(options) {
19
19
 
20
20
  MediaFile.setProperty('types', alchemy.shared('Media.types'));
21
21
 
22
+ /**
23
+ * The default sort options
24
+ *
25
+ * @type {Object}
26
+ */
27
+ MediaFile.prepareProperty('sort', function sort() {
28
+ return {created: -1};
29
+ });
30
+
22
31
  /**
23
32
  * Constitute the class wide schema
24
33
  *
25
- * @author Jelle De Loecker <jelle@develry.be>
34
+ * @author Jelle De Loecker <jelle@elevenways.be>
26
35
  * @since 0.2.0
27
- * @version 0.5.1
36
+ * @version 0.6.4
28
37
  */
29
38
  MediaFile.constitute(function addFields() {
30
39
 
31
- this.addField('name', 'String');
32
- this.addField('filename', 'String');
40
+ this.addField('name', 'String', {
41
+ description: 'The name of the file',
42
+ });
43
+
44
+ this.addField('filename', 'String', {
45
+ description : 'The actual filename',
46
+ });
33
47
 
34
48
  this.addField('type', 'Enum', {
35
- values: alchemy.getClassGroup('media_type')
49
+ values: alchemy.getClassGroup('media_type'),
50
+ description: 'The type of file',
36
51
  });
37
52
 
38
53
  this.addField('extra', 'Object');
39
54
 
40
- let options = {};
41
-
42
- if (alchemy.plugins.media.translatable) {
43
- options.translatable = true;
44
- }
55
+ this.addField('title', 'String', {
56
+ translatable : alchemy.plugins.media.translatable,
57
+ description : 'The title of the file (will be used in the title attribute)',
58
+ });
45
59
 
46
- this.addField('title', 'String', options);
47
- this.addField('alt', 'String', options);
60
+ this.addField('alt', 'String', {
61
+ translatable : alchemy.plugins.media.translatable,
62
+ description : 'The alternative information of the file (will be used in the alt attribute)',
63
+ });
48
64
 
49
65
  this.belongsTo('MediaRaw');
50
66
  });
@@ -54,7 +70,7 @@ MediaFile.constitute(function addFields() {
54
70
  *
55
71
  * @author Jelle De Loecker <jelle@develry.be>
56
72
  * @since 0.2.0
57
- * @version 0.5.1
73
+ * @version 0.6.4
58
74
  */
59
75
  MediaFile.constitute(function chimeraConfig() {
60
76
 
@@ -69,6 +85,15 @@ MediaFile.constitute(function chimeraConfig() {
69
85
  // Get the list group
70
86
  list = this.chimera.getActionFields('list');
71
87
 
88
+ list.addField('_id', {
89
+ view : 'file_preview',
90
+ wrapper : 'file_preview',
91
+ title : 'Thumbnail',
92
+ filter : false,
93
+ sortable : false,
94
+ });
95
+
96
+ list.addField('created');
72
97
  list.addField('name');
73
98
  list.addField('filename');
74
99
  list.addField('type');
@@ -78,6 +103,12 @@ MediaFile.constitute(function chimeraConfig() {
78
103
  // Get the edit group
79
104
  edit = this.chimera.getActionFields('edit');
80
105
 
106
+ edit.addField('_id', {
107
+ view : 'file_preview',
108
+ wrapper : 'file_preview',
109
+ title : 'Preview',
110
+ });
111
+
81
112
  edit.addField('name');
82
113
  edit.addField('filename');
83
114
  edit.addField('type');
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "alchemy-media",
3
3
  "description": "The media plugin for Alchemy",
4
- "version": "0.6.2",
4
+ "version": "0.6.4",
5
5
  "repository": {
6
6
  "type" : "git",
7
7
  "url" : "https://github.com/skerit/alchemy-media.git"
@@ -1,7 +1,7 @@
1
1
  <label class="al-file-drop-target">
2
2
  <div class="al-file-preview"></div>
3
3
  <al-ico class="uploading-icon fa-solid fa-spinner fa-spin-pulse"></al-ico>
4
- <al-ico class="empty-icon fa-solid fa-file-arrow-up" hidden></al-ico>
4
+ <al-ico class="empty-icon fa-solid fa-file-arrow-up"><% if (self.value) $0.hidden = true %></al-ico>
5
5
  <input type="file" tabindex="-1" class="al-file-input" hidden>
6
6
  </label>
7
7
 
@@ -12,6 +12,7 @@
12
12
  </button>
13
13
 
14
14
  <button class="al-file-remove">
15
+ <% if (!self.value) $0.hidden = true %>
15
16
  <al-ico class="fa-solid fa-trash-can"></al-ico>
16
17
  {%t "remove-current-file" %}
17
18
  </button>
@@ -0,0 +1,5 @@
1
+ <% style('element/alchemy_file') %>
2
+
3
+ <img
4
+ !Media={% value %}
5
+ >
@@ -0,0 +1,8 @@
1
+ <% style('element/alchemy_file') %>
2
+
3
+ {% if value %}
4
+ <img
5
+ !Media={% value %}
6
+ +media-route="Media::thumb"
7
+ >
8
+ {% /if %}
@@ -0,0 +1,8 @@
1
+ <% style('element/alchemy_file') %>
2
+
3
+ {% if value %}
4
+ <img
5
+ !Media={% value %}
6
+ +media-route="Media::thumb"
7
+ >
8
+ {% /if %}
@@ -0,0 +1,13 @@
1
+ <div class="form-field-info">
2
+ <alchemy-label>
3
+ <span
4
+ data-he-name="field-title"
5
+ data-he-slot="field-title"
6
+ ><%= alchemy_field.field_title %></span>
7
+ <small
8
+ data-he-name="field-description"
9
+ data-he-slot="field-description"
10
+ ><%= alchemy_field.field_description %></small>
11
+ </alchemy-label>
12
+ </div>
13
+ <div data-he-name="field"></div>