alchemy-widget 0.1.5 → 0.2.0

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.
Files changed (36) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/assets/stylesheets/alchemy_widgets.scss +426 -0
  3. package/bootstrap.js +6 -0
  4. package/controller/alchemy_widgets_controller.js +85 -9
  5. package/element/00-widget_base_element.js +154 -6
  6. package/element/05-widget_element.js +112 -19
  7. package/element/10-container_elements.js +15 -15
  8. package/element/11-alchemy_widgets_list_element.js +2 -2
  9. package/element/20-add_area_element.js +23 -23
  10. package/element/table_of_contents_element.js +104 -8
  11. package/element/widget_actionbar_element.js +92 -0
  12. package/element/widget_context_element.js +39 -23
  13. package/element/widget_toolbar_element.js +300 -38
  14. package/helper/widget_action.js +19 -18
  15. package/helper/widgets/00-widget.js +160 -37
  16. package/helper/widgets/01-container.js +12 -7
  17. package/helper/widgets/05-list.js +1 -1
  18. package/helper/widgets/alchemy_field_widget.js +112 -0
  19. package/helper/widgets/alchemy_form_widget.js +183 -0
  20. package/helper/widgets/alchemy_table_widget.js +71 -0
  21. package/helper/widgets/alchemy_tabs_widget.js +195 -0
  22. package/helper/widgets/header.js +4 -4
  23. package/helper/widgets/markdown.js +17 -10
  24. package/helper/widgets/partial.js +215 -0
  25. package/helper/widgets/sourcecode.js +4 -4
  26. package/helper/widgets/table_of_contents.js +2 -2
  27. package/helper/widgets/text.js +14 -4
  28. package/helper/widgets_helper.js +26 -0
  29. package/package.json +4 -3
  30. package/view/elements/table_of_contents.hwk +23 -9
  31. package/view/form/inputs/edit/widget.hwk +2 -2
  32. package/view/form/inputs/edit/widgets.hwk +2 -2
  33. package/view/widget/elements/al_widget_toolbar.hwk +49 -0
  34. package/view/widget/widget_config.hwk +7 -4
  35. package/assets/stylesheets/alchemy-widget-symbols.scss +0 -191
  36. package/assets/stylesheets/alchemy-widgets.scss +0 -258
@@ -77,14 +77,20 @@ Widget.setProperty(function element() {
77
77
  *
78
78
  * @author Jelle De Loecker <jelle@elevenways.be>
79
79
  * @since 0.1.0
80
- * @version 0.1.0
80
+ * @version 0.1.6
81
81
  *
82
82
  * @type {Hawkejs.Renderer}
83
83
  */
84
84
  Widget.enforceProperty(function hawkejs_renderer(new_value) {
85
85
 
86
- if (!new_value && Blast.isBrowser) {
87
- new_value = hawkejs.scene.general_renderer;
86
+ if (!new_value) {
87
+ if (this.parent_instance && this.parent_instance.hawkejs_renderer) {
88
+ new_value = this.parent_instance.hawkejs_renderer;
89
+ } else if (this.widget && this.widget.hawkejs_renderer) {
90
+ new_value = this.widget.hawkejs_renderer;
91
+ } else if (Blast.isBrowser) {
92
+ new_value = hawkejs.scene.general_renderer;
93
+ }
88
94
  }
89
95
 
90
96
  return new_value;
@@ -95,7 +101,7 @@ Widget.enforceProperty(function hawkejs_renderer(new_value) {
95
101
  *
96
102
  * @author Jelle De Loecker <jelle@elevenways.be>
97
103
  * @since 0.1.0
98
- * @version 0.1.5
104
+ * @version 0.2.0
99
105
  */
100
106
  Widget.constitute(function prepareSchema() {
101
107
 
@@ -108,7 +114,7 @@ Widget.constitute(function prepareSchema() {
108
114
  // Extra classnames for the wrapper
109
115
  this.schema.addField('wrapper_class_names', 'String', {
110
116
  title : 'Wrapper CSS classes',
111
- description : 'Configure extra CSS classes to the wrapper `alchemy-widget` element',
117
+ description : 'Configure extra CSS classes to the wrapper `al-widget` element',
112
118
  array: true,
113
119
  widget_config_editable: true,
114
120
  });
@@ -120,6 +126,34 @@ Widget.constitute(function prepareSchema() {
120
126
  array: true,
121
127
  });
122
128
 
129
+ // Add the "copy to clipboard" action
130
+ let copy = this.createAction('copy', 'Copy to clipboard');
131
+
132
+ copy.setHandler(function copyAction(widget_el, handle) {
133
+ return widget_el.copyConfigToClipboard();
134
+ });
135
+
136
+ copy.setTester(function copyAction(widget_el, handle) {
137
+ return true;
138
+ });
139
+
140
+ copy.setIcon('clipboard');
141
+ copy.close_actionbar = true;
142
+
143
+ // Add the "paste from clipboard" action
144
+ let paste = this.createAction('paste', 'Replace from clipboard');
145
+
146
+ paste.setHandler(function pasteAction(widget_el, handle) {
147
+ return widget_el.pasteConfigFromClipboard();
148
+ });
149
+
150
+ paste.setTester(function pasteAction(widget_el, handle) {
151
+ return widget_el.getConfigFromClipboard();
152
+ });
153
+
154
+ paste.setIcon('paste');
155
+ paste.close_actionbar = true;
156
+
123
157
  // Add the "save" action
124
158
  let save = this.createAction('save', 'Save');
125
159
 
@@ -131,26 +165,28 @@ Widget.constitute(function prepareSchema() {
131
165
  return widget_el.can_be_saved;
132
166
  });
133
167
 
168
+ save.setIcon('floppy-disk');
169
+
134
170
  // Add the remove action
135
171
  let remove = this.createAction('remove', 'Remove');
136
172
 
137
- remove.close_toolbar = true;
173
+ remove.close_actionbar = true;
138
174
 
139
175
  remove.setHandler(function removeAction(widget_el, handle) {
140
176
  handle.remove();
141
177
  });
142
178
 
143
179
  remove.setTester(function removeTester(widget_el, handle) {
144
- // The root alchemy-widgets element should not be removed
145
- return widget_el.tagName !== 'ALCHEMY-WIDGETS';
180
+ return widget_el.can_be_removed;
146
181
  });
147
182
 
148
- remove.setIcon('gg-trash');
183
+ remove.setIcon('trash');
149
184
 
150
185
  // Add the config action
151
186
  let config = this.createAction('config', 'Config');
152
187
 
153
- config.close_toolbar = true;
188
+ config.close_actionbar = true;
189
+ config.setIcon('gears');
154
190
 
155
191
  config.setHandler(function configAction(widget_el, handle) {
156
192
  widget_el.instance.showConfig();
@@ -159,7 +195,7 @@ Widget.constitute(function prepareSchema() {
159
195
  // The move-left action
160
196
  let move_left = this.createAction('move-left', 'Move left');
161
197
 
162
- move_left.close_toolbar = true;
198
+ move_left.close_actionbar = true;
163
199
 
164
200
  move_left.setHandler(function moveLeftAction(widget_el, handle) {
165
201
  // Hawkejs custom element method!
@@ -167,14 +203,19 @@ Widget.constitute(function prepareSchema() {
167
203
  });
168
204
 
169
205
  move_left.setTester(function moveLeftTest(widget_el, handle) {
206
+
207
+ if (!widget_el.can_be_moved) {
208
+ return false;
209
+ }
210
+
170
211
  return !!handle.previousElementSibling;
171
212
  });
172
213
 
173
- move_left.setIcon('gg-arrow-left');
214
+ move_left.setIcon('arrow-left');
174
215
 
175
216
  let move_right = this.createAction('move-right', 'Move right');
176
217
 
177
- move_right.close_toolbar = true;
218
+ move_right.close_actionbar = true;
178
219
 
179
220
  move_right.setHandler(function moveRightAction(widget_el, handle) {
180
221
  // Hawkejs custom element method!
@@ -183,21 +224,25 @@ Widget.constitute(function prepareSchema() {
183
224
 
184
225
  move_right.setTester(function moveRightTest(widget_el, handle) {
185
226
 
227
+ if (!widget_el.can_be_moved) {
228
+ return false;
229
+ }
230
+
186
231
  let next = handle.nextElementSibling;
187
232
 
188
- if (!next || next.tagName == 'ALCHEMY-WIDGET-ADD-AREA') {
233
+ if (!next || next.tagName == 'AL-WIDGET-ADD-AREA') {
189
234
  return false;
190
235
  }
191
236
 
192
237
  return true;
193
238
  });
194
239
 
195
- move_right.setIcon('gg-arrow-right');
240
+ move_right.setIcon('arrow-right');
196
241
 
197
242
  // The move-in-left action
198
243
  let move_in_left = this.createAction('move-in-left', 'Move in left');
199
244
 
200
- move_in_left.close_toolbar = true;
245
+ move_in_left.close_actionbar = true;
201
246
 
202
247
  move_in_left.setHandler(function moveLeftAction(widget_el, handle) {
203
248
  // Hawkejs custom element method!
@@ -209,15 +254,20 @@ Widget.constitute(function prepareSchema() {
209
254
  });
210
255
 
211
256
  move_in_left.setTester(function moveLeftTest(widget_el, handle) {
257
+
258
+ if (!widget_el.can_be_moved) {
259
+ return false;
260
+ }
261
+
212
262
  return !!handle.previous_container;
213
263
  });
214
264
 
215
- move_in_left.setIcon('gg-arrow-left');
265
+ move_in_left.setIcon('arrow-left');
216
266
 
217
267
  // The move-in-right action
218
268
  let move_in_right = this.createAction('move-in-right', 'Move in right');
219
269
 
220
- move_in_right.close_toolbar = true;
270
+ move_in_right.close_actionbar = true;
221
271
 
222
272
  move_in_right.setHandler(function moveRightAction(widget_el, handle) {
223
273
  // Hawkejs custom element method!
@@ -229,17 +279,23 @@ Widget.constitute(function prepareSchema() {
229
279
  });
230
280
 
231
281
  move_in_right.setTester(function moveRightTest(widget_el, handle) {
232
- console.log('Right test of:', handle)
282
+
283
+ if (!widget_el.can_be_moved) {
284
+ return false;
285
+ }
286
+
233
287
  return !!handle.next_container;
234
288
  });
235
289
 
236
- move_in_right.setIcon('gg-arrow-right');
290
+ move_in_right.setIcon('arrow-right');
237
291
 
238
292
  let css_class = this.createAction('css-class', 'CSS Class');
239
293
 
240
294
  css_class.setHandler(function setCssClass(widget_el, handle) {
241
295
  widget_el.instance.showConfig(['main_class_names']);
242
296
  });
297
+
298
+ css_class.setIcon('tags');
243
299
  });
244
300
 
245
301
  /**
@@ -279,6 +335,43 @@ Widget.setStatic(function createAction(name, title) {
279
335
  return action;
280
336
  });
281
337
 
338
+ /**
339
+ * Add a check to see if the widget can be added to the current location
340
+ *
341
+ * @author Jelle De Loecker <jelle@elevenways.be>
342
+ * @since 0.1.6
343
+ * @version 0.1.6
344
+ *
345
+ * @param {Boolean|Function} checker
346
+ */
347
+ Widget.setStatic(function setAddChecker(checker) {
348
+ this.add_checker = checker;
349
+ });
350
+
351
+ /**
352
+ * Actually perform the add-check
353
+ *
354
+ * @author Jelle De Loecker <jelle@elevenways.be>
355
+ * @since 0.1.6
356
+ * @version 0.1.6
357
+ *
358
+ * @param {Alchemy.Element.Widget.Base} widget_element
359
+ */
360
+ Widget.setStatic(function canBeAdded(widget_element) {
361
+
362
+ if (this.add_checker != null) {
363
+ const type = typeof this.add_checker;
364
+
365
+ if (type == 'function') {
366
+ return this.add_checker(widget_element);
367
+ } else if (type == 'boolean') {
368
+ return this.add_checker;
369
+ }
370
+ }
371
+
372
+ return true;
373
+ });
374
+
282
375
  /**
283
376
  * unDry an object
284
377
  *
@@ -356,22 +449,29 @@ Widget.setMethod(function toDry() {
356
449
  });
357
450
 
358
451
  /**
359
- * Get an array of toolbar actions
452
+ * Get an array of actionbar actions
360
453
  *
361
454
  * @author Jelle De Loecker <jelle@elevenways.be>
362
455
  * @since 0.1.0
363
- * @version 0.1.0
456
+ * @version 0.2.0
364
457
  *
365
458
  * @return {Array}
366
459
  */
367
- Widget.setMethod(function getToolbarActions() {
460
+ Widget.setMethod(async function getActionbarActions() {
368
461
 
369
462
  let sorted = this.constructor.actions.getSorted(),
370
463
  result = [],
371
464
  action;
372
465
 
373
466
  for (action of sorted) {
374
- if (action.test(this.widget)) {
467
+
468
+ let tester = action.test(this.widget);
469
+
470
+ if (Pledge.isThenable(tester)) {
471
+ tester = await tester;
472
+ }
473
+
474
+ if (tester) {
375
475
  result.push(action);
376
476
  }
377
477
  }
@@ -411,17 +511,17 @@ Widget.setMethod(function createElement(tag_name) {
411
511
 
412
512
  /**
413
513
  * Create an instance of the HTML element representing this widget
414
- * This will probably be just <alchemy-widget>
514
+ * This will probably be just <al-widget>
415
515
  *
416
516
  * @author Jelle De Loecker <jelle@elevenways.be>
417
517
  * @since 0.1.0
418
- * @version 0.1.0
518
+ * @version 0.2.0
419
519
  *
420
520
  * @return {HTMLElement}
421
521
  */
422
522
  Widget.setMethod(function _createWidgetElement() {
423
523
 
424
- let element = this.createElement('alchemy-widget');
524
+ let element = this.createElement('al-widget');
425
525
 
426
526
  // Set the type of the widget to our type
427
527
  element.type = this.constructor.type_name;
@@ -460,11 +560,11 @@ Widget.setMethod(function _createPopulatedWidgetElement() {
460
560
  });
461
561
 
462
562
  /**
463
- * Dummy populate method
563
+ * Populate the contents of the widget
464
564
  *
465
565
  * @author Jelle De Loecker <jelle@elevenways.be>
466
566
  * @since 0.1.0
467
- * @version 0.1.2
567
+ * @version 0.1.6
468
568
  */
469
569
  Widget.setMethod(function populateWidget() {
470
570
 
@@ -480,6 +580,16 @@ Widget.setMethod(function populateWidget() {
480
580
  }
481
581
  }
482
582
 
583
+ let child_classes = this.widget.child_class;
584
+
585
+ if (child_classes) {
586
+ let children = this.widget.children,
587
+ i;
588
+
589
+ for (i = 0; i < children.length; i++) {
590
+ Hawkejs.addClasses(children[i], child_classes);
591
+ }
592
+ }
483
593
  });
484
594
 
485
595
  /**
@@ -487,16 +597,23 @@ Widget.setMethod(function populateWidget() {
487
597
  *
488
598
  * @author Jelle De Loecker <jelle@elevenways.be>
489
599
  * @since 0.1.0
490
- * @version 0.1.0
600
+ * @version 0.1.6
491
601
  */
492
- Widget.setMethod(function startEditor() {
602
+ Widget.setMethod(async function startEditor() {
493
603
 
494
604
  // Show this is being edited
495
605
  this.editing = true;
496
606
 
607
+ // Make sure the icon font is loaded
608
+ if (this.hawkejs_renderer?.helpers?.Media) {
609
+ this.hawkejs_renderer.helpers.Media.loadIconFont();
610
+ }
611
+
497
612
  // Add the appropriate class to the current widget wrapper
498
613
  this.widget.classList.add('aw-editing');
499
614
 
615
+ await this.widget.waitForTasks();
616
+
500
617
  if (typeof this._startEditor == 'function') {
501
618
  this._startEditor();
502
619
  }
@@ -529,13 +646,13 @@ Widget.setMethod(function stopEditor() {
529
646
  *
530
647
  * @author Jelle De Loecker <jelle@elevenways.be>
531
648
  * @since 0.1.0
532
- * @version 0.1.0
649
+ * @version 0.1.6
533
650
  */
534
- Widget.setMethod(function rerender() {
651
+ Widget.setMethod(async function rerender() {
535
652
 
536
653
  Hawkejs.removeChildren(this.widget);
537
654
 
538
- this.populateWidget();
655
+ await this.populateWidget();
539
656
 
540
657
  if (this.editing) {
541
658
  this.startEditor();
@@ -560,7 +677,7 @@ Widget.setMethod(function syncConfig() {
560
677
  *
561
678
  * @author Jelle De Loecker <jelle@elevenways.be>
562
679
  * @since 0.1.0
563
- * @version 0.1.0
680
+ * @version 0.2.0
564
681
  */
565
682
  Widget.setMethod(async function showConfig(fields) {
566
683
 
@@ -590,9 +707,12 @@ Widget.setMethod(async function showConfig(fields) {
590
707
  }
591
708
  }
592
709
 
710
+ let widget_settings = Object.assign({}, this.syncConfig());
711
+
593
712
  let variables = {
713
+ title : this.constructor.title,
594
714
  schema : this.schema,
595
- widget_settings : this.syncConfig(),
715
+ widget_settings,
596
716
  fields : fields
597
717
  };
598
718
 
@@ -607,10 +727,13 @@ Widget.setMethod(async function showConfig(fields) {
607
727
  let dialog = dialog_contents.queryParents('he-dialog'),
608
728
  button = dialog_contents.querySelector('.btn-apply');
609
729
 
730
+ dialog_contents.classList.add('default-form-editor');
731
+ hawkejs.scene.enableStyle('chimera/chimera');
732
+
610
733
  button.addEventListener('click', e => {
611
734
  e.preventDefault();
612
735
 
613
- let form = dialog.querySelector('alchemy-form');
736
+ let form = dialog.querySelector('al-form');
614
737
 
615
738
  Object.assign(this.config, form.value);
616
739
 
@@ -11,6 +11,11 @@
11
11
  */
12
12
  const Container = Function.inherits('Alchemy.Widget', 'Container');
13
13
 
14
+ /**
15
+ * Make this an abstract class
16
+ */
17
+ Container.makeAbstractClass();
18
+
14
19
  /**
15
20
  * Prepare the schema
16
21
  *
@@ -46,13 +51,13 @@ Container.setMethod(function initContainer() {
46
51
  *
47
52
  * @author Jelle De Loecker <jelle@elevenways.be>
48
53
  * @since 0.1.0
49
- * @version 0.1.0
54
+ * @version 0.2.0
50
55
  *
51
56
  * @return {HTMLElement}
52
57
  */
53
58
  Container.setMethod(function _createWidgetElement() {
54
59
 
55
- let tag_name = 'alchemy-widgets-' + this.constructor.type_name;
60
+ let tag_name = 'al-widgets-' + this.constructor.type_name;
56
61
 
57
62
  let element = this.createElement(tag_name);
58
63
 
@@ -67,14 +72,14 @@ Container.setMethod(function _createWidgetElement() {
67
72
  *
68
73
  * @author Jelle De Loecker <jelle@elevenways.be>
69
74
  * @since 0.1.0
70
- * @version 0.1.0
75
+ * @version 0.2.0
71
76
  */
72
77
  Container.setMethod(function _startEditor() {
73
78
 
74
- let add_area = this.widget.querySelector(':scope > alchemy-widget-add-area');
79
+ let add_area = this.widget.querySelector(':scope > al-widget-add-area');
75
80
 
76
81
  if (!add_area) {
77
- add_area = this.createElement('alchemy-widget-add-area');
82
+ add_area = this.createElement('al-widget-add-area');
78
83
  this.widget.append(add_area);
79
84
  }
80
85
 
@@ -95,11 +100,11 @@ Container.setMethod(function _startEditor() {
95
100
  *
96
101
  * @author Jelle De Loecker <jelle@elevenways.be>
97
102
  * @since 0.1.0
98
- * @version 0.1.0
103
+ * @version 0.2.0
99
104
  */
100
105
  Container.setMethod(function _stopEditor() {
101
106
 
102
- let add_area = this.widget.querySelector(':scope > alchemy-widget-add-area');
107
+ let add_area = this.widget.querySelector(':scope > al-widget-add-area');
103
108
 
104
109
  if (add_area) {
105
110
  add_area.remove();
@@ -22,7 +22,7 @@ List.setMethod(function initContainer() {
22
22
 
23
23
  let ul = this.createElement('ul');
24
24
 
25
- Classes.Alchemy.Element.Widget.AlchemyWidgets.prototype._appendWidgetElement.call(this.widget, ul);
25
+ Classes.Alchemy.Element.Widget.AlWidgets.prototype._appendWidgetElement.call(this.widget, ul);
26
26
 
27
27
  this.widget.list_element = ul;
28
28
 
@@ -0,0 +1,112 @@
1
+ /**
2
+ * The Field Widget class
3
+ *
4
+ * @constructor
5
+ *
6
+ * @author Jelle De Loecker <jelle@elevenways.be>
7
+ * @since 0.1.0
8
+ * @version 0.1.0
9
+ *
10
+ * @param {Object} data
11
+ */
12
+ const AlchemyField = Function.inherits('Alchemy.Widget', 'AlchemyField');
13
+
14
+ /**
15
+ * Prepare the schema
16
+ *
17
+ * @author Jelle De Loecker <jelle@elevenways.be>
18
+ * @since 0.1.0
19
+ * @version 0.1.12
20
+ */
21
+ AlchemyField.constitute(function prepareSchema() {
22
+
23
+ this.setAddChecker(function(widget_element) {
24
+ return false;
25
+ });
26
+ });
27
+
28
+ /**
29
+ * Find the al-form parent
30
+ *
31
+ * @author Jelle De Loecker <jelle@elevenways.be>
32
+ * @since 0.1.4
33
+ * @version 0.2.0
34
+ */
35
+ AlchemyField.enforceProperty(function alchemy_form(new_value) {
36
+
37
+ if (!new_value && this.config && this.config.alchemy_form) {
38
+ new_value = this.config.alchemy_form;
39
+ }
40
+
41
+ if (!new_value) {
42
+
43
+ let parent = this.parent_instance;
44
+
45
+ while (parent) {
46
+
47
+ new_value = parent.alchemy_form;
48
+
49
+ if (new_value) {
50
+ break;
51
+ }
52
+
53
+ if (parent.element) {
54
+ new_value = parent.element.querySelector('al-form');
55
+
56
+ if (new_value) {
57
+ break;
58
+ }
59
+ }
60
+
61
+ parent = parent.parent_instance;
62
+ }
63
+ }
64
+
65
+ return new_value;
66
+ });
67
+
68
+ /**
69
+ * Populate the widget
70
+ *
71
+ * @author Jelle De Loecker <jelle@elevenways.be>
72
+ * @since 0.1.0
73
+ * @version 0.2.0
74
+ */
75
+ AlchemyField.setMethod(function populateWidget() {
76
+
77
+ let config = this.config;
78
+
79
+ let alchemy_form = this.alchemy_form;
80
+
81
+ let field_el = this.createElement('al-field');
82
+
83
+ if (alchemy_form) {
84
+ field_el.alchemy_form = alchemy_form;
85
+ }
86
+
87
+ field_el.field_name = config.field;
88
+
89
+ field_el.applyOptions(config);
90
+
91
+ this.element.append(field_el);
92
+ });
93
+
94
+ /**
95
+ * Get the config of this widget
96
+ *
97
+ * @author Jelle De Loecker <jelle@elevenways.be>
98
+ * @since 0.1.0
99
+ * @version 0.1.0
100
+ *
101
+ * @return {Object}
102
+ */
103
+ AlchemyField.setMethod(function syncConfig() {
104
+
105
+ let config = this.config;
106
+
107
+ if (!config) {
108
+ config = this.config = {};
109
+ }
110
+
111
+ return this.config;
112
+ });