alchemy-widget 0.1.6 → 0.2.1

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 (37) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/assets/stylesheets/{alchemy-widgets.scss → alchemy_widgets.scss} +169 -54
  3. package/bootstrap.js +101 -2
  4. package/controller/alchemy_widgets_controller.js +64 -0
  5. package/element/00-widget_base_element.js +105 -4
  6. package/element/05-widget_element.js +33 -21
  7. package/element/10-container_elements.js +27 -32
  8. package/element/11-alchemy_widgets_list_element.js +2 -2
  9. package/element/20-add_area_element.js +22 -22
  10. package/element/table_of_contents_element.js +144 -11
  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 +295 -50
  14. package/helper/widget_action.js +10 -10
  15. package/helper/widgets/00-widget.js +244 -27
  16. package/helper/widgets/01-container.js +29 -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 +193 -0
  22. package/helper/widgets/hawkejs_template.js +60 -0
  23. package/helper/widgets/header.js +8 -10
  24. package/helper/widgets/html.js +52 -3
  25. package/helper/widgets/markdown.js +18 -13
  26. package/helper/widgets/partial.js +1 -3
  27. package/helper/widgets/sourcecode.js +5 -7
  28. package/helper/widgets/table_of_contents.js +2 -4
  29. package/helper/widgets/text.js +15 -15
  30. package/helper/widgets_helper.js +26 -0
  31. package/package.json +3 -2
  32. package/view/elements/table_of_contents.hwk +33 -9
  33. package/view/form/inputs/edit/widget.hwk +2 -2
  34. package/view/form/inputs/edit/widgets.hwk +2 -2
  35. package/view/widget/elements/al_widget_toolbar.hwk +49 -0
  36. package/view/widget/widget_config.hwk +7 -4
  37. package/assets/stylesheets/alchemy-widget-symbols.scss +0 -191
@@ -14,7 +14,16 @@ let Base = Function.inherits('Alchemy.Element', 'Alchemy.Element.Widget', 'Base'
14
14
  * @since 0.1.0
15
15
  * @version 0.1.0
16
16
  */
17
- Base.setStylesheetFile('alchemy-widgets');
17
+ Base.setStylesheetFile('alchemy_widgets');
18
+
19
+ /**
20
+ * Set the custom element prefix
21
+ *
22
+ * @author Jelle De Loecker <jelle@elevenways.be>
23
+ * @since 0.1.0
24
+ * @version 0.2.0
25
+ */
26
+ Base.setStatic('custom_element_prefix', 'al');
18
27
 
19
28
  /**
20
29
  * Don't register this as a custom element
@@ -22,9 +31,9 @@ Base.setStylesheetFile('alchemy-widgets');
22
31
  *
23
32
  * @author Jelle De Loecker <jelle@elevenways.be>
24
33
  * @since 0.1.0
25
- * @version 0.1.0
34
+ * @version 0.2.0
26
35
  */
27
- Base.setStatic('is_abstract_class', true, false);
36
+ Base.makeAbstractClass();
28
37
 
29
38
  /**
30
39
  * The Widget class instance belonging to this element
@@ -183,7 +192,7 @@ Base.setMethod(function getSiblingContainer(type) {
183
192
  return next;
184
193
  }
185
194
 
186
- if (next.tagName != 'ALCHEMY-WIDGET-ADD-AREA') {
195
+ if (next.tagName != 'AL-WIDGET-ADD-AREA') {
187
196
  return false;
188
197
  }
189
198
  }
@@ -348,4 +357,96 @@ Base.setMethod(async function save() {
348
357
  };
349
358
 
350
359
  let result = await alchemy.fetch(config);
360
+ });
361
+
362
+ /**
363
+ * Copy this widget's configuration to the clipboard
364
+ *
365
+ * @author Jelle De Loecker <jelle@elevenways.be>
366
+ * @since 0.2.0
367
+ * @version 0.2.1
368
+ */
369
+ Base.setMethod(async function copyConfigToClipboard() {
370
+
371
+ let value = this.value;
372
+
373
+ if (!value) {
374
+ return;
375
+ }
376
+
377
+ value._altype = 'widget';
378
+ value.type = this.type;
379
+
380
+ let dried = JSON.dry(value, null, '\t');
381
+
382
+ try {
383
+ await navigator.clipboard.writeText(dried);
384
+ } catch (err) {
385
+ console.error('Failed to copy:', err);
386
+ }
387
+
388
+ localStorage._copied_widget_config = dried;
389
+ });
390
+
391
+ /**
392
+ * Get configuration from the clipboard and return it if it's valid
393
+ *
394
+ * @author Jelle De Loecker <jelle@elevenways.be>
395
+ * @since 0.2.0
396
+ * @version 0.2.1
397
+ */
398
+ Base.setMethod(async function getConfigFromClipboard() {
399
+
400
+ let result;
401
+
402
+ try {
403
+ result = await navigator.clipboard.readText();
404
+ } catch (err) {
405
+
406
+ if (!localStorage._copied_widget_config) {
407
+ return false;
408
+ } else {
409
+ result = localStorage._copied_widget_config;
410
+ }
411
+ }
412
+
413
+ if (result) {
414
+ result = result.trim();
415
+ }
416
+
417
+ if (!result || result[0] != '{') {
418
+ return false;
419
+ }
420
+
421
+ try {
422
+ result = JSON.undry(result);
423
+ } catch (err) {
424
+ return false;
425
+ }
426
+
427
+ if (result._altype != 'widget') {
428
+ return false;
429
+ }
430
+
431
+ if (result.type != this.type && !this.can_be_removed) {
432
+ return false;
433
+ }
434
+
435
+ return result;
436
+ });
437
+
438
+ /**
439
+ * Read the configuration from the clipboard & apply
440
+ *
441
+ * @author Jelle De Loecker <jelle@elevenways.be>
442
+ * @since 0.2.0
443
+ * @version 0.2.0
444
+ */
445
+ Base.setMethod(async function pasteConfigFromClipboard() {
446
+
447
+ let result = await this.getConfigFromClipboard();
448
+
449
+ if (result) {
450
+ this.value = result;
451
+ }
351
452
  });
@@ -1,5 +1,5 @@
1
1
  /**
2
- * The alchemy-widget element
2
+ * The al-widget element
3
3
  *
4
4
  * @author Jelle De Loecker <jelle@elevenways.be>
5
5
  * @since 0.1.0
@@ -7,15 +7,6 @@
7
7
  */
8
8
  let Widget = Function.inherits('Alchemy.Element.Widget.Base', 'Widget');
9
9
 
10
- /**
11
- * Set the custom element prefix
12
- *
13
- * @author Jelle De Loecker <jelle@elevenways.be>
14
- * @since 0.1.0
15
- * @version 0.1.0
16
- */
17
- Widget.setStatic('custom_element_prefix', 'alchemy');
18
-
19
10
  /**
20
11
  * The type of widget
21
12
  *
@@ -88,6 +79,15 @@ Widget.setAssignedProperty('filter_value');
88
79
  */
89
80
  Widget.setAttribute('child-class');
90
81
 
82
+ /**
83
+ * A role to give to each child widgets
84
+ *
85
+ * @author Jelle De Loecker <jelle@elevenways.be>
86
+ * @since 0.2.1
87
+ * @version 0.2.1
88
+ */
89
+ Widget.setAttribute('child-role');
90
+
91
91
  /**
92
92
  * Is this widget being edited?
93
93
  *
@@ -278,13 +278,11 @@ Widget.setMethod(function syncConfig() {
278
278
  *
279
279
  * @author Jelle De Loecker <jelle@elevenways.be>
280
280
  * @since 0.1.0
281
- * @version 0.1.0
281
+ * @version 0.2.1
282
282
  */
283
283
  Widget.setMethod(function startEditor() {
284
284
 
285
- if (!this.instance) {
286
- throw new Error('Unable to start the editor: this widget element has no accompanying instance');
287
- }
285
+ this.assertWidgetInstance();
288
286
 
289
287
  this.instance.startEditor();
290
288
  this.addEditEventListeners();
@@ -295,19 +293,33 @@ Widget.setMethod(function startEditor() {
295
293
  *
296
294
  * @author Jelle De Loecker <jelle@elevenways.be>
297
295
  * @since 0.1.0
298
- * @version 0.1.5
296
+ * @version 0.2.1
299
297
  */
300
298
  Widget.setMethod(function stopEditor() {
301
299
 
302
- if (!this.instance) {
303
- throw new Error('Unable to stop the editor: this widget element has no accompanying instance');
304
- }
300
+ this.assertWidgetInstance();
305
301
 
306
302
  this.unselectWidget();
307
303
  this.instance.stopEditor();
308
304
  this.removeEditEventListeners();
309
305
  });
310
306
 
307
+ /**
308
+ * Make sure there is an instance
309
+ *
310
+ * @author Jelle De Loecker <jelle@elevenways.be>
311
+ * @since 0.2.1
312
+ * @version 0.2.1
313
+ */
314
+ Widget.setMethod(function assertWidgetInstance() {
315
+
316
+ if (!this.instance) {
317
+ console.error('Problem with widget element:', this);
318
+ throw new Error('Unable to stop the editor: this ' + this.tagName + ' element has no accompanying instance');
319
+ }
320
+
321
+ });
322
+
311
323
  /**
312
324
  * Mouse click
313
325
  *
@@ -363,14 +375,14 @@ Widget.setMethod(function removeEditEventListeners() {
363
375
  *
364
376
  * @author Jelle De Loecker <jelle@elevenways.be>
365
377
  * @since 0.1.0
366
- * @version 0.1.0
378
+ * @version 0.2.0
367
379
  */
368
380
  Widget.setMethod(function getContextButton() {
369
381
 
370
- let button = document.querySelector('alchemy-widget-context');
382
+ let button = document.querySelector('al-widget-context');
371
383
 
372
384
  if (!button) {
373
- button = this.createElement('alchemy-widget-context');
385
+ button = this.createElement('al-widget-context');
374
386
  document.body.append(button);
375
387
  }
376
388
 
@@ -1,13 +1,13 @@
1
1
  /**
2
- * The alchemy-widgets element is the base "container" for all other widgets.
2
+ * The al-widgets element is the base "container" for all other widgets.
3
3
  * It should never be nested, though
4
4
  *
5
5
  * @author Jelle De Loecker <jelle@elevenways.be>
6
6
  * @since 0.1.0
7
7
  * @version 0.1.0
8
8
  */
9
- let AlchemyWidgets = Function.inherits('Alchemy.Element.Widget', function AlchemyWidgets() {
10
- AlchemyWidgets.super.call(this);
9
+ let AlchemyWidgets = Function.inherits('Alchemy.Element.Widget', function AlWidgets() {
10
+ AlWidgets.super.call(this);
11
11
 
12
12
  // Always create this dummy instance just in case?
13
13
  this.instance = new Classes.Alchemy.Widget.Container();
@@ -19,9 +19,9 @@ let AlchemyWidgets = Function.inherits('Alchemy.Element.Widget', function Alchem
19
19
  *
20
20
  * @author Jelle De Loecker <jelle@elevenways.be>
21
21
  * @since 0.1.0
22
- * @version 0.1.0
22
+ * @version 0.2.0
23
23
  */
24
- AlchemyWidgets.setStatic('custom_element_prefix', 'alchemy-widgets');
24
+ AlchemyWidgets.setStatic('custom_element_prefix', 'al-widgets');
25
25
 
26
26
  /**
27
27
  * Don't add the edit event listeners
@@ -62,21 +62,22 @@ AlchemyWidgets.setAssignedProperty('context_variables', function getContextData(
62
62
  *
63
63
  * @author Jelle De Loecker <jelle@elevenways.be>
64
64
  * @since 0.1.0
65
- * @version 0.1.0
65
+ * @version 0.2.1
66
66
  */
67
67
  AlchemyWidgets.setProperty(function value() {
68
68
 
69
- let widgets = this.getWidgetsConfig(),
69
+ let config = this.instance.config,
70
+ widgets = this.getWidgetsConfig(),
70
71
  result;
72
+
73
+ config = Object.assign({}, config, {widgets});
71
74
 
72
- if (this.nodeName == 'ALCHEMY-WIDGETS') {
73
- result = {widgets};
75
+ if (this.nodeName == 'AL-WIDGETS') {
76
+ result = config;
74
77
  } else {
75
78
  result = {
76
79
  type : this.instance.constructor.type_name,
77
- config : {
78
- widgets : widgets
79
- }
80
+ config : config,
80
81
  };
81
82
  }
82
83
 
@@ -91,7 +92,7 @@ AlchemyWidgets.setProperty(function value() {
91
92
  *
92
93
  * @author Jelle De Loecker <jelle@elevenways.be>
93
94
  * @since 0.1.5
94
- * @version 0.1.5
95
+ * @version 0.2.1
95
96
  */
96
97
  AlchemyWidgets.setMethod(function applyValue(value) {
97
98
 
@@ -119,24 +120,18 @@ AlchemyWidgets.setMethod(function applyValue(value) {
119
120
  if (config.class_names) {
120
121
  Hawkejs.addClasses(this, config.class_names);
121
122
  }
123
+ } else {
124
+ config = this.instance?.config || {};
122
125
  }
123
126
 
124
127
  if (!this.instance) {
125
128
  return;
126
129
  }
127
130
 
131
+ config.widgets = widgets;
132
+
128
133
  this.instance.config = config;
129
134
  this.instance.initContainer();
130
-
131
- if (!widgets || !widgets.length) {
132
- return;
133
- }
134
-
135
- let widget;
136
-
137
- for (widget of widgets) {
138
- this.addWidget(widget.type, widget.config);
139
- }
140
135
  });
141
136
 
142
137
  /**
@@ -186,7 +181,7 @@ AlchemyWidgets.setMethod(function clear() {
186
181
  for (i = 0; i < children.length; i++) {
187
182
  child = children[i];
188
183
 
189
- if (child.nodeName == 'ALCHEMY-WIDGET-ADD-AREA') {
184
+ if (child.nodeName == 'AL-WIDGET-ADD-AREA') {
190
185
  continue;
191
186
  }
192
187
 
@@ -240,7 +235,7 @@ AlchemyWidgets.setMethod(function addWidget(type, config) {
240
235
  *
241
236
  * @author Jelle De Loecker <jelle@elevenways.be>
242
237
  * @since 0.1.0
243
- * @version 0.1.0
238
+ * @version 0.2.0
244
239
  *
245
240
  * @param {Element} element
246
241
  */
@@ -249,7 +244,7 @@ AlchemyWidgets.setMethod(function _appendWidgetElement(element) {
249
244
  let add_area;
250
245
 
251
246
  if (this.editing) {
252
- add_area = this.querySelector(':scope > alchemy-widget-add-area');
247
+ add_area = this.querySelector(':scope > al-widget-add-area');
253
248
  }
254
249
 
255
250
  if (add_area) {
@@ -270,19 +265,19 @@ AlchemyWidgets.setMethod(function _appendWidgetElement(element) {
270
265
  AlchemyWidgets.setMethod(function initEventListeners() {});
271
266
 
272
267
  /**
273
- * The alchemy-widgets-column element
268
+ * The al-widgets-column element
274
269
  *
275
270
  * @author Jelle De Loecker <jelle@elevenways.be>
276
271
  * @since 0.1.0
277
- * @version 0.1.0
272
+ * @version 0.2.0
278
273
  */
279
- Function.inherits('Alchemy.Element.Widget.AlchemyWidgets', 'Column');
274
+ Function.inherits('Alchemy.Element.Widget.AlWidgets', 'Column');
280
275
 
281
276
  /**
282
- * The alchemy-widgets-row element
277
+ * The al-widgets-row element
283
278
  *
284
279
  * @author Jelle De Loecker <jelle@elevenways.be>
285
280
  * @since 0.1.0
286
- * @version 0.1.0
281
+ * @version 0.2.0
287
282
  */
288
- Function.inherits('Alchemy.Element.Widget.AlchemyWidgets', 'Row');
283
+ Function.inherits('Alchemy.Element.Widget.AlWidgets', 'Row');
@@ -1,11 +1,11 @@
1
1
  /**
2
- * The alchemy-widgets-list element
2
+ * The al-widgets-list element
3
3
  *
4
4
  * @author Jelle De Loecker <jelle@elevenways.be>
5
5
  * @since 0.1.0
6
6
  * @version 0.1.0
7
7
  */
8
- const List = Function.inherits('Alchemy.Element.Widget.AlchemyWidgets', 'List');
8
+ const List = Function.inherits('Alchemy.Element.Widget.AlWidgets', 'List');
9
9
 
10
10
  /**
11
11
  * Get the list element
@@ -1,17 +1,17 @@
1
1
  /**
2
- * The alchemy-widgets element
2
+ * The al-widgets element
3
3
  *
4
4
  * @author Jelle De Loecker <jelle@elevenways.be>
5
5
  * @since 0.1.0
6
- * @version 0.1.0
6
+ * @version 0.2.0
7
7
  */
8
- let AddArea = Function.inherits('Alchemy.Element.Widget.Base', function AlchemyWidgetAddArea() {
9
- AlchemyWidgetAddArea.super.call(this);
8
+ let AddArea = Function.inherits('Alchemy.Element.Widget.Base', function WidgetAddArea() {
9
+ WidgetAddArea.super.call(this);
10
10
 
11
11
  this.innerHTML = `
12
12
  <div class="main-button">
13
- <button class="add-button widget-button" title="Add"><i class="gg-math-plus"></i></button>
14
- <button class="menu-button widget-button" title="Menu"><i class="gg-menu-grid-o"></i></button>
13
+ <button class="add-button widget-button" title="Add"><al-icon icon-name="plus"></al-icon></button>
14
+ <button class="menu-button widget-button" title="Menu"><al-icon icon-name="grid"></al-icon></button>
15
15
  </div>
16
16
  <div class="widget-types">
17
17
  TYPES
@@ -24,16 +24,16 @@ let AddArea = Function.inherits('Alchemy.Element.Widget.Base', function AlchemyW
24
24
  *
25
25
  * @author Jelle De Loecker <jelle@elevenways.be>
26
26
  * @since 0.1.0
27
- * @version 0.1.6
27
+ * @version 0.2.0
28
28
  */
29
29
  AddArea.setMethod(function showTypes(event) {
30
30
 
31
31
  let that = this;
32
32
 
33
- let context_button = document.querySelector('alchemy-widget-context');
33
+ let context_button = document.querySelector('al-widget-context');
34
34
 
35
- if (context_button && context_button.active_widget) {
36
- context_button.unselectedWidget();
35
+ if (context_button) {
36
+ context_button.forceUnselection();
37
37
  }
38
38
 
39
39
  let context = this.createElement('he-context-menu');
@@ -58,27 +58,27 @@ AddArea.setMethod(function showTypes(event) {
58
58
  });
59
59
 
60
60
  /**
61
- * Show the toolbar
61
+ * Show the actionbar
62
62
  *
63
63
  * @author Jelle De Loecker <jelle@elevenways.be>
64
64
  * @since 0.1.0
65
- * @version 0.1.0
65
+ * @version 0.2.0
66
66
  */
67
- AddArea.setMethod(function showToolbar() {
67
+ AddArea.setMethod(function showActionbar() {
68
68
 
69
- if (!this.toolbar) {
70
- this.toolbar = document.createElement('alchemy-widget-toolbar');
71
- this.append(this.toolbar);
69
+ if (!this.actionbar) {
70
+ this.actionbar = document.createElement('al-widget-actionbar');
71
+ this.append(this.actionbar);
72
72
  }
73
73
 
74
- if (this.toolbar.context_element == this && !this.toolbar.hidden) {
75
- this.toolbar.close();
74
+ if (this.actionbar.context_element == this && !this.actionbar.hidden) {
75
+ this.actionbar.close();
76
76
  return;
77
77
  }
78
78
 
79
- this.toolbar.hidden = false;
80
- this.toolbar.context_element = this;
81
- this.toolbar.showWidgetActions(this.parentElement);
79
+ this.actionbar.hidden = false;
80
+ this.actionbar.context_element = this;
81
+ this.actionbar.showWidgetActions(this.parentElement);
82
82
 
83
83
  });
84
84
 
@@ -106,6 +106,6 @@ AddArea.setMethod(function introduced() {
106
106
 
107
107
  context_button.addEventListener('click', function onClick(e) {
108
108
  e.preventDefault();
109
- that.showToolbar();
109
+ that.showActionbar();
110
110
  });
111
111
  });