]> BookStack Code Mirror - bookstack/commitdiff
Updated a whole load more js components
authorDan Brown <redacted>
Tue, 15 Nov 2022 16:04:46 +0000 (16:04 +0000)
committerDan Brown <redacted>
Tue, 15 Nov 2022 16:04:46 +0000 (16:04 +0000)
25 files changed:
resources/js/components/collapsible.js
resources/js/components/dropdown-search.js
resources/js/components/expand-toggle.js
resources/js/components/header-mobile-toggle.js
resources/js/components/image-picker.js
resources/js/components/index.js
resources/js/components/list-sort-control.js
resources/js/components/new-user-password.js
resources/js/components/optional-input.js
resources/js/components/page-display.js
resources/js/components/shelf-sort.js
resources/js/components/sidebar.js [deleted file]
resources/js/components/submit-on-change.js
resources/js/components/tri-layout.js
resources/js/components/user-select.js
resources/js/components/webhook-events.js
resources/sass/_forms.scss
resources/views/books/parts/form.blade.php
resources/views/chapters/parts/form.blade.php
resources/views/form/image-picker.blade.php
resources/views/home/parts/expand-toggle.blade.php
resources/views/home/specific-page.blade.php
resources/views/pages/show.blade.php
resources/views/shelves/parts/form.blade.php
resources/views/users/parts/form.blade.php

index 544f91008c7d13eaeec88a9f119ebfb47e839a85..bb8ed477ffe9f600769dace8ba6d7f2af32d5fb7 100644 (file)
@@ -1,35 +1,37 @@
 import {slideDown, slideUp} from "../services/animations";
 import {slideDown, slideUp} from "../services/animations";
+import {Component} from "./component";
 
 /**
  * Collapsible
  * Provides some simple logic to allow collapsible sections.
  */
 
 /**
  * Collapsible
  * Provides some simple logic to allow collapsible sections.
  */
-class Collapsible {
+export class Collapsible extends Component {
 
 
-    constructor(elem) {
-        this.elem = elem;
-        this.trigger = elem.querySelector('[collapsible-trigger]');
-        this.content = elem.querySelector('[collapsible-content]');
+    setup() {
+        this.container = this.$el;
+        this.trigger = this.$refs.trigger;
+        this.content = this.$refs.content;
 
 
-        if (!this.trigger) return;
-        this.trigger.addEventListener('click', this.toggle.bind(this));
-        this.openIfContainsError();
+        if (this.trigger) {
+            this.trigger.addEventListener('click', this.toggle.bind(this));
+            this.openIfContainsError();
+        }
     }
 
     open() {
     }
 
     open() {
-        this.elem.classList.add('open');
+        this.container.classList.add('open');
         this.trigger.setAttribute('aria-expanded', 'true');
         slideDown(this.content, 300);
     }
 
     close() {
         this.trigger.setAttribute('aria-expanded', 'true');
         slideDown(this.content, 300);
     }
 
     close() {
-        this.elem.classList.remove('open');
+        this.container.classList.remove('open');
         this.trigger.setAttribute('aria-expanded', 'false');
         slideUp(this.content, 300);
     }
 
     toggle() {
         this.trigger.setAttribute('aria-expanded', 'false');
         slideUp(this.content, 300);
     }
 
     toggle() {
-        if (this.elem.classList.contains('open')) {
+        if (this.container.classList.contains('open')) {
             this.close();
         } else {
             this.open();
             this.close();
         } else {
             this.open();
@@ -43,6 +45,4 @@ class Collapsible {
         }
     }
 
         }
     }
 
-}
-
-export default Collapsible;
\ No newline at end of file
+}
\ No newline at end of file
index 81fa940c24ca7cf4a38ba66fe7b55e300d746100..30a2aadc1467ddd97a1a3ccb30efea591383f07b 100644 (file)
@@ -1,7 +1,8 @@
 import {debounce} from "../services/util";
 import {transitionHeight} from "../services/animations";
 import {debounce} from "../services/util";
 import {transitionHeight} from "../services/animations";
+import {Component} from "./component";
 
 
-class DropdownSearch {
+export class DropdownSearch extends Component {
 
     setup() {
         this.elem = this.$el;
 
     setup() {
         this.elem = this.$el;
@@ -78,6 +79,4 @@ class DropdownSearch {
         this.loadingElem.style.display = show ? 'block' : 'none';
     }
 
         this.loadingElem.style.display = show ? 'block' : 'none';
     }
 
-}
-
-export default DropdownSearch;
\ No newline at end of file
+}
\ No newline at end of file
index cce1b215c9378f30659befc189424f76145f4c6c..ab4d38ab1df2224270a27aab2f1fca6ae3786e10 100644 (file)
@@ -1,17 +1,15 @@
 import {slideUp, slideDown} from "../services/animations";
 import {slideUp, slideDown} from "../services/animations";
+import {Component} from "./component";
 
 
-class ExpandToggle {
+export class ExpandToggle extends Component {
 
 
-    constructor(elem) {
-        this.elem = elem;
-
-        // Component state
-        this.isOpen = elem.getAttribute('expand-toggle-is-open') === 'yes';
-        this.updateEndpoint = elem.getAttribute('expand-toggle-update-endpoint');
-        this.selector = elem.getAttribute('expand-toggle');
+    setup(elem) {
+        this.targetSelector = this.$opts.targetSelector;
+        this.isOpen = this.$opts.isOpen === 'true';
+        this.updateEndpoint = this.$opts.updateEndpoint;
 
         // Listener setup
 
         // Listener setup
-        elem.addEventListener('click', this.click.bind(this));
+        this.$el.addEventListener('click', this.click.bind(this));
     }
 
     open(elemToToggle) {
     }
 
     open(elemToToggle) {
@@ -25,7 +23,7 @@ class ExpandToggle {
     click(event) {
         event.preventDefault();
 
     click(event) {
         event.preventDefault();
 
-        const matchingElems = document.querySelectorAll(this.selector);
+        const matchingElems = document.querySelectorAll(this.targetSelector);
         for (let match of matchingElems) {
             this.isOpen ?  this.close(match) : this.open(match);
         }
         for (let match of matchingElems) {
             this.isOpen ?  this.close(match) : this.open(match);
         }
@@ -40,6 +38,4 @@ class ExpandToggle {
         });
     }
 
         });
     }
 
-}
-
-export default ExpandToggle;
\ No newline at end of file
+}
\ No newline at end of file
index 99737bfb8b0fb741564a5c854d566fd3f774067a..11b23cca6cc06f833d8d3146ceb6c0bb0ddf6bdf 100644 (file)
@@ -1,5 +1,6 @@
+import {Component} from "./component";
 
 
-class HeaderMobileToggle {
+export class HeaderMobileToggle extends Component {
 
     setup() {
         this.elem = this.$el;
 
     setup() {
         this.elem = this.$el;
@@ -36,6 +37,4 @@ class HeaderMobileToggle {
         this.onToggle(event);
     }
 
         this.onToggle(event);
     }
 
-}
-
-export default HeaderMobileToggle;
\ No newline at end of file
+}
\ No newline at end of file
index 7455fa622379a798ae102dd65dc7c72aed28417e..03d9567d22e331c82a04c75bc1840e207c5d1eec 100644 (file)
@@ -1,21 +1,25 @@
+import {Component} from "./component";
 
 
-class ImagePicker {
+export class ImagePicker extends Component {
 
 
-    constructor(elem) {
-        this.elem = elem;
-        this.imageElem = elem.querySelector('img');
-        this.imageInput = elem.querySelector('input[type=file]');
-        this.resetInput = elem.querySelector('input[data-reset-input]');
-        this.removeInput = elem.querySelector('input[data-remove-input]');
+    setup() {
+        this.imageElem = this.$refs.image;
+        this.imageInput = this.$refs.imageInput;
+        this.resetInput = this.$refs.resetInput;
+        this.removeInput = this.$refs.removeInput;
+        this.resetButton = this.$refs.resetButton;
+        this.removeButton = this.$refs.removeButton || null;
 
 
-        this.defaultImage = elem.getAttribute('data-default-image');
+        this.defaultImage = this.$opts.defaultImage;
 
 
-        const resetButton = elem.querySelector('button[data-action="reset-image"]');
-        resetButton.addEventListener('click', this.reset.bind(this));
+        this.setupListeners();
+    }
+
+    setupListeners() {
+        this.resetButton.addEventListener('click', this.reset.bind(this));
 
 
-        const removeButton = elem.querySelector('button[data-action="remove-image"]');
-        if (removeButton) {
-            removeButton.addEventListener('click', this.removeImage.bind(this));
+        if (this.removeButton) {
+            this.removeButton.addEventListener('click', this.removeImage.bind(this));
         }
 
         this.imageInput.addEventListener('change', this.fileInputChange.bind(this));
         }
 
         this.imageInput.addEventListener('change', this.fileInputChange.bind(this));
@@ -50,6 +54,4 @@ class ImagePicker {
         this.resetInput.setAttribute('disabled', 'disabled');
     }
 
         this.resetInput.setAttribute('disabled', 'disabled');
     }
 
-}
-
-export default ImagePicker;
\ No newline at end of file
+}
\ No newline at end of file
index 6b5967031bb489a83c40673fe8275ad59f2ca2f8..0106e82d4fdea7a779716de28a6ec2727ef94730 100644 (file)
@@ -11,12 +11,12 @@ export {ChapterContents} from "./chapter-contents.js"
 // export {CodeEditor} from "./code-editor.js"
 export {CodeHighlighter} from "./code-highlighter.js"
 export {CodeTextarea} from "./code-textarea.js"
 // export {CodeEditor} from "./code-editor.js"
 export {CodeHighlighter} from "./code-highlighter.js"
 export {CodeTextarea} from "./code-textarea.js"
-// export {Collapsible} from "./collapsible.js"
+export {Collapsible} from "./collapsible.js"
 // export {ConfirmDialog} from "./confirm-dialog"
 export {CustomCheckbox} from "./custom-checkbox.js"
 export {DetailsHighlighter} from "./details-highlighter.js"
 export {Dropdown} from "./dropdown.js"
 // export {ConfirmDialog} from "./confirm-dialog"
 export {CustomCheckbox} from "./custom-checkbox.js"
 export {DetailsHighlighter} from "./details-highlighter.js"
 export {Dropdown} from "./dropdown.js"
-// export {DropdownSearch} from "./dropdown-search.js"
+export {DropdownSearch} from "./dropdown-search.js"
 // export {Dropzone} from "./dropzone.js"
 // export {EditorToolbox} from "./editor-toolbox.js"
 export {EntityPermissions} from "./entity-permissions"
 // export {Dropzone} from "./dropzone.js"
 // export {EditorToolbox} from "./editor-toolbox.js"
 export {EntityPermissions} from "./entity-permissions"
@@ -24,17 +24,17 @@ export {EntityPermissions} from "./entity-permissions"
 export {EntitySelector} from "./entity-selector.js"
 export {EntitySelectorPopup} from "./entity-selector-popup.js"
 // export {EventEmitSelect} from "./event-emit-select.js"
 export {EntitySelector} from "./entity-selector.js"
 export {EntitySelectorPopup} from "./entity-selector-popup.js"
 // export {EventEmitSelect} from "./event-emit-select.js"
-// export {ExpandToggle} from "./expand-toggle.js"
-// export {HeaderMobileToggle} from "./header-mobile-toggle.js"
+export {ExpandToggle} from "./expand-toggle.js"
+export {HeaderMobileToggle} from "./header-mobile-toggle.js"
 // export {ImageManager} from "./image-manager.js"
 // export {ImageManager} from "./image-manager.js"
-// export {ImagePicker} from "./image-picker.js"
-// export {ListSortControl} from "./list-sort-control.js"
+export {ImagePicker} from "./image-picker.js"
+export {ListSortControl} from "./list-sort-control.js"
 // export {MarkdownEditor} from "./markdown-editor.js"
 // export {MarkdownEditor} from "./markdown-editor.js"
-// export {NewUserPassword} from "./new-user-password.js"
+export {NewUserPassword} from "./new-user-password.js"
 export {Notification} from "./notification.js"
 export {Notification} from "./notification.js"
-// export {OptionalInput} from "./optional-input.js"
+export {OptionalInput} from "./optional-input.js"
 export {PageComments} from "./page-comments.js"
 export {PageComments} from "./page-comments.js"
-// export {PageDisplay} from "./page-display.js"
+export {PageDisplay} from "./page-display.js"
 // export {PageEditor} from "./page-editor.js"
 export {PagePicker} from "./page-picker.js"
 export {PermissionsTable} from "./permissions-table.js"
 // export {PageEditor} from "./page-editor.js"
 export {PagePicker} from "./page-picker.js"
 export {PermissionsTable} from "./permissions-table.js"
@@ -43,17 +43,16 @@ export {Popup} from "./popup.js"
 export {SettingAppColorPicker} from "./setting-app-color-picker.js"
 export {SettingColorPicker} from "./setting-color-picker.js"
 export {SettingHomepageControl} from "./setting-homepage-control.js"
 export {SettingAppColorPicker} from "./setting-app-color-picker.js"
 export {SettingColorPicker} from "./setting-color-picker.js"
 export {SettingHomepageControl} from "./setting-homepage-control.js"
-// export {ShelfSort} from "./shelf-sort.js"
+export {ShelfSort} from "./shelf-sort.js"
 export {Shortcuts} from "./shortcuts"
 export {ShortcutInput} from "./shortcut-input"
 export {Shortcuts} from "./shortcuts"
 export {ShortcutInput} from "./shortcut-input"
-// export {Sidebar} from "./sidebar.js"
 // export {SortableList} from "./sortable-list.js"
 // export {SortableList} from "./sortable-list.js"
-// export {SubmitOnChange} from "./submit-on-change.js"
+export {SubmitOnChange} from "./submit-on-change.js"
 // export {Tabs} from "./tabs.js"
 // export {TagManager} from "./tag-manager.js"
 // export {TemplateManager} from "./template-manager.js"
 export {ToggleSwitch} from "./toggle-switch.js"
 // export {Tabs} from "./tabs.js"
 // export {TagManager} from "./tag-manager.js"
 // export {TemplateManager} from "./template-manager.js"
 export {ToggleSwitch} from "./toggle-switch.js"
-// export {TriLayout} from "./tri-layout.js"
-// export {UserSelect} from "./user-select.js"
-// export {WebhookEvents} from "./webhook-events";
+export {TriLayout} from "./tri-layout.js"
+export {UserSelect} from "./user-select.js"
+export {WebhookEvents} from "./webhook-events";
 // export {WysiwygEditor} from "./wysiwyg-editor.js"
\ No newline at end of file
 // export {WysiwygEditor} from "./wysiwyg-editor.js"
\ No newline at end of file
index 3b642dbde09604485d78f81b87f280c42f2daceb..b8d4de73a0e7b8cd3326ca9e30679366043af7be 100644 (file)
@@ -1,9 +1,10 @@
 /**
  * ListSortControl
  * Manages the logic for the control which provides list sorting options.
 /**
  * ListSortControl
  * Manages the logic for the control which provides list sorting options.
- * @extends {Component}
  */
  */
-class ListSortControl {
+import {Component} from "./component";
+
+export class ListSortControl extends Component {
 
     setup() {
         this.elem = this.$el;
 
     setup() {
         this.elem = this.$el;
@@ -44,6 +45,4 @@ class ListSortControl {
         this.form.submit();
     }
 
         this.form.submit();
     }
 
-}
-
-export default ListSortControl;
\ No newline at end of file
+}
\ No newline at end of file
index 9c4c21c14cc0bae368f8bf9be2fd5abd546b8482..a4ed4d15b300c5e255e86ef43eee9f8c7b31d014 100644 (file)
@@ -1,9 +1,11 @@
+import {Component} from "./component";
 
 
-class NewUserPassword {
+export class NewUserPassword extends Component {
 
 
-    constructor(elem) {
-        this.elem = elem;
-        this.inviteOption = elem.querySelector('input[name=send_invite]');
+    setup() {
+        this.container = this.$el;
+        this.inputContainer = this.$refs.inputContainer;
+        this.inviteOption = this.container.querySelector('input[name=send_invite]');
 
         if (this.inviteOption) {
             this.inviteOption.addEventListener('change', this.inviteOptionChange.bind(this));
 
         if (this.inviteOption) {
             this.inviteOption.addEventListener('change', this.inviteOptionChange.bind(this));
@@ -13,16 +15,12 @@ class NewUserPassword {
 
     inviteOptionChange() {
         const inviting = (this.inviteOption.value === 'true');
 
     inviteOptionChange() {
         const inviting = (this.inviteOption.value === 'true');
-        const passwordBoxes = this.elem.querySelectorAll('input[type=password]');
+        const passwordBoxes = this.container.querySelectorAll('input[type=password]');
         for (const input of passwordBoxes) {
             input.disabled = inviting;
         }
         for (const input of passwordBoxes) {
             input.disabled = inviting;
         }
-        const container = this.elem.querySelector('#password-input-container');
-        if (container) {
-            container.style.display = inviting ? 'none' : 'block';
-        }
-    }
 
 
-}
+        this.inputContainer.style.display = inviting ? 'none' : 'block';
+    }
 
 
-export default NewUserPassword;
\ No newline at end of file
+}
\ No newline at end of file
index eab58e42a584a53c18a1727a3fe497789c23c381..cc429c991522bcd9b51a5fc811127e7775a4a066 100644 (file)
@@ -1,6 +1,7 @@
 import {onSelect} from "../services/dom";
 import {onSelect} from "../services/dom";
+import {Component} from "./component";
 
 
-class OptionalInput {
+export class OptionalInput extends Component {
     setup() {
         this.removeButton = this.$refs.remove;
         this.showButton = this.$refs.show;
     setup() {
         this.removeButton = this.$refs.remove;
         this.showButton = this.$refs.show;
@@ -23,6 +24,4 @@ class OptionalInput {
         });
     }
 
         });
     }
 
-}
-
-export default OptionalInput;
\ No newline at end of file
+}
\ No newline at end of file
index f8377130c1f8615958c2eaf2ad34eca07f15c17f..c06c3310dee2c44c221b331c8a78b8d3eee9d3f3 100644 (file)
@@ -1,11 +1,12 @@
 import * as DOM from "../services/dom";
 import {scrollAndHighlightElement} from "../services/util";
 import * as DOM from "../services/dom";
 import {scrollAndHighlightElement} from "../services/util";
+import {Component} from "./component";
 
 
-class PageDisplay {
+export class PageDisplay extends Component {
 
 
-    constructor(elem) {
-        this.elem = elem;
-        this.pageId = elem.getAttribute('page-display');
+    setup() {
+        this.container = this.$el;
+        this.pageId = this.$opts.pageId;
 
         window.importVersioned('code').then(Code => Code.highlight());
         this.setupNavHighlighting();
 
         window.importVersioned('code').then(Code => Code.highlight());
         this.setupNavHighlighting();
@@ -13,7 +14,7 @@ class PageDisplay {
 
         // Check the hash on load
         if (window.location.hash) {
 
         // Check the hash on load
         if (window.location.hash) {
-            let text = window.location.hash.replace(/\%20/g, ' ').substr(1);
+            const text = window.location.hash.replace(/%20/g, ' ').substring(1);
             this.goToText(text);
         }
 
             this.goToText(text);
         }
 
@@ -49,17 +50,10 @@ class PageDisplay {
     }
 
     setupNavHighlighting() {
     }
 
     setupNavHighlighting() {
-        // Check if support is present for IntersectionObserver
-        if (!('IntersectionObserver' in window) ||
-            !('IntersectionObserverEntry' in window) ||
-            !('intersectionRatio' in window.IntersectionObserverEntry.prototype)) {
-            return;
-        }
-
-        let pageNav = document.querySelector('.sidebar-page-nav');
+        const pageNav = document.querySelector('.sidebar-page-nav');
 
         // fetch all the headings.
 
         // fetch all the headings.
-        let headings = document.querySelector('.page-content').querySelectorAll('h1, h2, h3, h4, h5, h6');
+        const headings = document.querySelector('.page-content').querySelectorAll('h1, h2, h3, h4, h5, h6');
         // if headings are present, add observers.
         if (headings.length > 0 && pageNav !== null) {
             addNavObserver(headings);
         // if headings are present, add observers.
         if (headings.length > 0 && pageNav !== null) {
             addNavObserver(headings);
@@ -67,21 +61,21 @@ class PageDisplay {
 
         function addNavObserver(headings) {
             // Setup the intersection observer.
 
         function addNavObserver(headings) {
             // Setup the intersection observer.
-            let intersectOpts = {
+            const intersectOpts = {
                 rootMargin: '0px 0px 0px 0px',
                 threshold: 1.0
             };
                 rootMargin: '0px 0px 0px 0px',
                 threshold: 1.0
             };
-            let pageNavObserver = new IntersectionObserver(headingVisibilityChange, intersectOpts);
+            const pageNavObserver = new IntersectionObserver(headingVisibilityChange, intersectOpts);
 
             // observe each heading
 
             // observe each heading
-            for (let heading of headings) {
+            for (const heading of headings) {
                 pageNavObserver.observe(heading);
             }
         }
 
         function headingVisibilityChange(entries, observer) {
                 pageNavObserver.observe(heading);
             }
         }
 
         function headingVisibilityChange(entries, observer) {
-            for (let entry of entries) {
-                let isVisible = (entry.intersectionRatio === 1);
+            for (const entry of entries) {
+                const isVisible = (entry.intersectionRatio === 1);
                 toggleAnchorHighlighting(entry.target.id, isVisible);
             }
         }
                 toggleAnchorHighlighting(entry.target.id, isVisible);
             }
         }
@@ -99,9 +93,7 @@ class PageDisplay {
             codeMirrors.forEach(cm => cm.CodeMirror && cm.CodeMirror.refresh());
         };
 
             codeMirrors.forEach(cm => cm.CodeMirror && cm.CodeMirror.refresh());
         };
 
-        const details = [...this.elem.querySelectorAll('details')];
+        const details = [...this.container.querySelectorAll('details')];
         details.forEach(detail => detail.addEventListener('toggle', onToggle));
     }
         details.forEach(detail => detail.addEventListener('toggle', onToggle));
     }
-}
-
-export default PageDisplay;
+}
\ No newline at end of file
index 30eda5a21f7cf920fc99f254ac051b3e36b79408..aa244086e88a173878c3dcf2c8aacd272ae4a1a6 100644 (file)
@@ -1,6 +1,7 @@
 import Sortable from "sortablejs";
 import Sortable from "sortablejs";
+import {Component} from "./component";
 
 
-class ShelfSort {
+export class ShelfSort extends Component {
 
     setup() {
         this.elem = this.$el;
 
     setup() {
         this.elem = this.$el;
@@ -15,7 +16,7 @@ class ShelfSort {
 
     initSortable() {
         const scrollBoxes = this.elem.querySelectorAll('.scroll-box');
 
     initSortable() {
         const scrollBoxes = this.elem.querySelectorAll('.scroll-box');
-        for (let scrollBox of scrollBoxes) {
+        for (const scrollBox of scrollBoxes) {
             new Sortable(scrollBox, {
                 group: 'shelf-books',
                 ghostClass: 'primary-background-light',
             new Sortable(scrollBox, {
                 group: 'shelf-books',
                 ghostClass: 'primary-background-light',
diff --git a/resources/js/components/sidebar.js b/resources/js/components/sidebar.js
deleted file mode 100644 (file)
index 0fecc5e..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-
-class Sidebar {
-
-    constructor(elem) {
-        this.elem = elem;
-        this.toggleElem = elem.querySelector('.sidebar-toggle');
-        this.toggleElem.addEventListener('click', this.toggle.bind(this));
-    }
-
-    toggle(show = true) {
-        this.elem.classList.toggle('open');
-    }
-
-}
-
-export default Sidebar;
\ No newline at end of file
index aeacae23213bd96b94290ed9ab6a4e9e131a4b78..da4ac699608f21a11a5392dfd272a3492ae178a9 100644 (file)
@@ -1,9 +1,10 @@
+import {Component} from "./component";
+
 /**
  * Submit on change
  * Simply submits a parent form when this input is changed.
 /**
  * Submit on change
  * Simply submits a parent form when this input is changed.
- * @extends {Component}
  */
  */
-class SubmitOnChange {
+export class SubmitOnChange extends Component {
 
     setup() {
         this.filter = this.$opts.filter;
 
     setup() {
         this.filter = this.$opts.filter;
@@ -21,6 +22,4 @@ class SubmitOnChange {
         });
     }
 
         });
     }
 
-}
-
-export default SubmitOnChange;
\ No newline at end of file
+}
\ No newline at end of file
index f801e52a193715fdea427fa4eac03c2372ca9abf..ead2ac3d0dae85d4f865cd191d6ff768307eaa76 100644 (file)
@@ -1,5 +1,6 @@
+import {Component} from "./component";
 
 
-class TriLayout {
+export class TriLayout extends Component {
 
     setup() {
         this.container = this.$refs.container;
 
     setup() {
         this.container = this.$refs.container;
@@ -108,6 +109,4 @@ class TriLayout {
         this.lastTabShown = tabName;
     }
 
         this.lastTabShown = tabName;
     }
 
-}
-
-export default TriLayout;
\ No newline at end of file
+}
\ No newline at end of file
index aba43e0a920a5c66b0cdb8097061cec9c039d211..549963eed4193e6e5fc72ea46eadd73f77010e7a 100644 (file)
@@ -1,6 +1,7 @@
 import {onChildEvent} from "../services/dom";
 import {onChildEvent} from "../services/dom";
+import {Component} from "./component";
 
 
-class UserSelect {
+export class UserSelect extends Component {
 
     setup() {
         this.input = this.$refs.input;
 
     setup() {
         this.input = this.$refs.input;
@@ -13,13 +14,10 @@ class UserSelect {
 
     selectUser(event, userEl) {
         event.preventDefault();
 
     selectUser(event, userEl) {
         event.preventDefault();
-        const id = userEl.getAttribute('data-id');
-        this.input.value = id;
+        this.input.value = userEl.getAttribute('data-id');
         this.userInfoContainer.innerHTML = userEl.innerHTML;
         this.input.dispatchEvent(new Event('change', {bubbles: true}));
         this.hide();
     }
 
         this.userInfoContainer.innerHTML = userEl.innerHTML;
         this.input.dispatchEvent(new Event('change', {bubbles: true}));
         this.hide();
     }
 
-}
-
-export default UserSelect;
\ No newline at end of file
+}
\ No newline at end of file
index aa50aa9d883f1541cbf08eed3d9865b65c252789..ad8c59ac2abd7c73a1857602f1f465b754f016e9 100644 (file)
@@ -1,10 +1,10 @@
-
 /**
  * Webhook Events
  * Manages dynamic selection control in the webhook form interface.
 /**
  * Webhook Events
  * Manages dynamic selection control in the webhook form interface.
- * @extends {Component}
  */
  */
-class WebhookEvents {
+import {Component} from "./component";
+
+export class WebhookEvents extends Component {
 
     setup() {
         this.checkboxes = this.$el.querySelectorAll('input[type="checkbox"]');
 
     setup() {
         this.checkboxes = this.$el.querySelectorAll('input[type="checkbox"]');
@@ -27,6 +27,4 @@ class WebhookEvents {
         }
     }
 
         }
     }
 
-}
-
-export default WebhookEvents;
\ No newline at end of file
+}
\ No newline at end of file
index 7de8a9d7dc53782f47f07c00087769c8e08ecd63..f341ce48683f8cc90cc01288ef61a36d2a548aa5 100644 (file)
@@ -328,7 +328,7 @@ input[type=color] {
   }
 }
 
   }
 }
 
-.form-group[collapsible] {
+.form-group.collapsible {
   padding: 0 $-m;
   border: 1px solid;
   @include lightDark(border-color, #DDD, #000);
   padding: 0 $-m;
   border: 1px solid;
   @include lightDark(border-color, #DDD, #000);
index bb87089b272ac3a30e62f5846c7611c67ca8bb4a..e893bceadc55e10acf2a5b986cf9fcdceb6fe98f 100644 (file)
     @include('form.textarea', ['name' => 'description'])
 </div>
 
     @include('form.textarea', ['name' => 'description'])
 </div>
 
-<div class="form-group" collapsible id="logo-control">
-    <button type="button" class="collapse-title text-primary" collapsible-trigger aria-expanded="false">
+<div class="form-group collapsible" component="collapsible" id="logo-control">
+    <button refs="collapsible@trigger" type="button" class="collapse-title text-primary" aria-expanded="false">
         <label>{{ trans('common.cover_image') }}</label>
     </button>
         <label>{{ trans('common.cover_image') }}</label>
     </button>
-    <div class="collapse-content" collapsible-content>
+    <div refs="collapsible@content" class="collapse-content">
         <p class="small">{{ trans('common.cover_image_description') }}</p>
 
         @include('form.image-picker', [
         <p class="small">{{ trans('common.cover_image_description') }}</p>
 
         @include('form.image-picker', [
     </div>
 </div>
 
     </div>
 </div>
 
-<div class="form-group" collapsible id="tags-control">
-    <button type="button" class="collapse-title text-primary" collapsible-trigger aria-expanded="false">
+<div class="form-group collapsible" component="collapsible" id="tags-control">
+    <button refs="collapsible@trigger" type="button" class="collapse-title text-primary" aria-expanded="false">
         <label for="tag-manager">{{ trans('entities.book_tags') }}</label>
     </button>
         <label for="tag-manager">{{ trans('entities.book_tags') }}</label>
     </button>
-    <div class="collapse-content" collapsible-content>
+    <div refs="collapsible@content" class="collapse-content">
         @include('entities.tag-manager', ['entity' => $book ?? null])
     </div>
 </div>
         @include('entities.tag-manager', ['entity' => $book ?? null])
     </div>
 </div>
index 3908d0693fb7a3ec635be5d609dfb61f579c3d7c..068c033ab90fb67864b56955e8b6f445b12bd109 100644 (file)
     @include('form.textarea', ['name' => 'description'])
 </div>
 
     @include('form.textarea', ['name' => 'description'])
 </div>
 
-<div class="form-group" collapsible id="logo-control">
-    <button type="button" class="collapse-title text-primary" collapsible-trigger aria-expanded="false">
+<div class="form-group collapsible" component="collapsible" id="logo-control">
+    <button refs="collapsible@trigger" type="button" class="collapse-title text-primary" aria-expanded="false">
         <label for="tags">{{ trans('entities.chapter_tags') }}</label>
     </button>
         <label for="tags">{{ trans('entities.chapter_tags') }}</label>
     </button>
-    <div class="collapse-content" collapsible-content>
+    <div refs="collapsible@content" class="collapse-content">
         @include('entities.tag-manager', ['entity' => $chapter ?? null])
     </div>
 </div>
         @include('entities.tag-manager', ['entity' => $chapter ?? null])
     </div>
 </div>
index 9c2661cccbd3d19c412a39af93837ad0be8ab205..f7e2c6bb97bd321a6f2b892f8044f05aab81006b 100644 (file)
@@ -1,26 +1,27 @@
-<div class="image-picker @if($errors->has($name)) has-error @endif"
-     image-picker="{{$name}}"
-     data-default-image="{{ $defaultImage }}">
+<div component="image-picker"
+     option:image-picker:default-image="{{ $defaultImage }}"
+     class="image-picker @if($errors->has($name)) has-error @endif">
 
     <div class="grid half">
         <div class="text-center">
 
     <div class="grid half">
         <div class="text-center">
-            <img @if($currentImage && $currentImage !== 'none') src="{{$currentImage}}" @else src="{{$defaultImage}}" @endif  class="{{$imageClass}} @if($currentImage=== 'none') none @endif" alt="{{ trans('components.image_preview') }}">
+            <img refs="image-picker@image"
+                @if($currentImage && $currentImage !== 'none') src="{{$currentImage}}" @else src="{{$defaultImage}}" @endif
+                class="{{$imageClass}} @if($currentImage=== 'none') none @endif" alt="{{ trans('components.image_preview') }}">
         </div>
         <div class="text-center">
         </div>
         <div class="text-center">
-
-            <input type="file" class="custom-file-input" accept="image/*" name="{{ $name }}" id="{{ $name }}">
+            <input refs="image-picker@image-input" type="file" class="custom-file-input" accept="image/*" name="{{ $name }}" id="{{ $name }}">
             <label for="{{ $name }}" class="button outline">{{ trans('components.image_select_image') }}</label>
             <label for="{{ $name }}" class="button outline">{{ trans('components.image_select_image') }}</label>
-            <input type="hidden" data-reset-input name="{{ $name }}_reset" value="true" disabled="disabled">
+            <input refs="image-picker@reset-input" type="hidden" name="{{ $name }}_reset" value="true" disabled="disabled">
             @if(isset($removeName))
             @if(isset($removeName))
-                <input type="hidden" data-remove-input name="{{ $removeName }}" value="{{ $removeValue }}" disabled="disabled">
+                <input refs="image-picker@remove-input" type="hidden" name="{{ $removeName }}" value="{{ $removeValue }}" disabled="disabled">
             @endif
 
             <br>
             @endif
 
             <br>
-            <button class="text-button text-muted" data-action="reset-image" type="button">{{ trans('common.reset') }}</button>
+            <button refs="image-picker@reset-button" class="text-button text-muted" type="button">{{ trans('common.reset') }}</button>
 
             @if(isset($removeName))
                 <span class="sep">|</span>
 
             @if(isset($removeName))
                 <span class="sep">|</span>
-                <button class="text-button text-muted" data-action="remove-image" type="button">{{ trans('common.remove') }}</button>
+                <button refs="image-picker@remove-button" class="text-button text-muted" type="button">{{ trans('common.remove') }}</button>
             @endif
         </div>
     </div>
             @endif
         </div>
     </div>
index 291e5db344114d1cfe060e141099ad040c1b6d5c..73d21f5f7b9e1e4d4be38d44471973d2577e8b8a 100644 (file)
@@ -3,10 +3,12 @@ $target - CSS selector of items to expand
 $key - Unique key for checking existing stored state.
 --}}
 <?php $isOpen = setting()->getForCurrentUser('section_expansion#'. $key); ?>
 $key - Unique key for checking existing stored state.
 --}}
 <?php $isOpen = setting()->getForCurrentUser('section_expansion#'. $key); ?>
-<button type="button" expand-toggle="{{ $target }}"
-   expand-toggle-update-endpoint="{{ url('/preferences/change-expansion/' . $key) }}"
-   expand-toggle-is-open="{{ $isOpen ? 'yes' : 'no' }}"
-   class="icon-list-item {{ $classes ?? '' }}">
+<button component="expand-toggle"
+        option:expand-toggle:target-selector="{{ $target }}"
+        option:expand-toggle:update-endpoint="{{ url('/preferences/change-expansion/' . $key) }}"
+        option:expand-toggle:is-open="{{ $isOpen ? 'true' : 'false' }}"
+        type="button"
+        class="icon-list-item {{ $classes ?? '' }}">
     <span>@icon('expand-text')</span>
     <span>{{ trans('common.toggle_details') }}</span>
 </button>
     <span>@icon('expand-text')</span>
     <span>{{ trans('common.toggle_details') }}</span>
 </button>
index 936433b276adb445df7a3713396b645d7728d04f..cc8ff22fa0a22f73a87c9220b9c73ddabd606aa8 100644 (file)
@@ -3,7 +3,9 @@
 @section('body')
     <div class="mt-m">
         <main class="content-wrap card">
 @section('body')
     <div class="mt-m">
         <main class="content-wrap card">
-            <div class="page-content" page-display="{{ $customHomepage->id }}">
+            <div component="page-display"
+                 option:page-display:page-id="{{ $page->id }}"
+                 class="page-content">
                 @include('pages.parts.page-display', ['page' => $customHomepage])
             </div>
         </main>
                 @include('pages.parts.page-display', ['page' => $customHomepage])
             </div>
         </main>
index 32718b7f1e47873b98483fa9b0d5bbebebb55662..e05d9d7393fce09b93662b498a77290562dc7642 100644 (file)
@@ -17,7 +17,9 @@
     </div>
 
     <main class="content-wrap card">
     </div>
 
     <main class="content-wrap card">
-        <div class="page-content clearfix" page-display="{{ $page->id }}">
+        <div component="page-display"
+             option:page-display:page-id="{{ $page->id }}"
+             class="page-content clearfix">
             @include('pages.parts.page-display')
         </div>
         @include('pages.parts.pointer', ['page' => $page])
             @include('pages.parts.page-display')
         </div>
         @include('pages.parts.pointer', ['page' => $page])
index 1dcc4192f04acaddfd1e51198defee4e5be4f294..a5445270314ea0b3df2351a4f3e36f54fc3aa198 100644 (file)
 
 
 
 
 
 
-<div class="form-group" collapsible id="logo-control">
-    <button type="button" class="collapse-title text-primary" collapsible-trigger aria-expanded="false">
+<div class="form-group collapsible" component="collapsible" id="logo-control">
+    <button refs="collapsible@trigger" type="button" class="collapse-title text-primary" aria-expanded="false">
         <label>{{ trans('common.cover_image') }}</label>
     </button>
         <label>{{ trans('common.cover_image') }}</label>
     </button>
-    <div class="collapse-content" collapsible-content>
+    <div refs="collapsible@content" class="collapse-content">
         <p class="small">{{ trans('common.cover_image_description') }}</p>
 
         @include('form.image-picker', [
         <p class="small">{{ trans('common.cover_image_description') }}</p>
 
         @include('form.image-picker', [
     </div>
 </div>
 
     </div>
 </div>
 
-<div class="form-group" collapsible id="tags-control">
-    <button type="button" class="collapse-title text-primary" collapsible-trigger aria-expanded="false">
+<div class="form-group collapsible" component="collapsible" id="tags-control">
+    <button refs="collapsible@trigger" type="button" class="collapse-title text-primary" aria-expanded="false">
         <label for="tag-manager">{{ trans('entities.shelf_tags') }}</label>
     </button>
         <label for="tag-manager">{{ trans('entities.shelf_tags') }}</label>
     </button>
-    <div class="collapse-content" collapsible-content>
+    <div refs="collapsible@content" class="collapse-content">
         @include('entities.tag-manager', ['entity' => $shelf ?? null])
     </div>
 </div>
         @include('entities.tag-manager', ['entity' => $shelf ?? null])
     </div>
 </div>
index 2a5002c3b766c34cc97494336130268c448b499d..7ff48a83dd881b9a96f6c1c9f0438dddc844ba40 100644 (file)
@@ -48,7 +48,7 @@
 @endif
 
 @if($authMethod === 'standard')
 @endif
 
 @if($authMethod === 'standard')
-    <div new-user-password>
+    <div component="new-user-password">
         <label class="setting-list-label">{{ trans('settings.users_password') }}</label>
 
         @if(!isset($model))
         <label class="setting-list-label">{{ trans('settings.users_password') }}</label>
 
         @if(!isset($model))
                 'value' => old('send_invite', 'true') === 'true',
                 'label' => trans('settings.users_send_invite_option')
             ])
                 'value' => old('send_invite', 'true') === 'true',
                 'label' => trans('settings.users_send_invite_option')
             ])
-
         @endif
 
         @endif
 
-        <div id="password-input-container" @if(!isset($model)) style="display: none;" @endif>
+        <div refs="new-user-password@input-container" @if(!isset($model)) style="display: none;" @endif>
             <p class="small">{{ trans('settings.users_password_desc') }}</p>
             @if(isset($model))
                 <p class="small">
             <p class="small">{{ trans('settings.users_password_desc') }}</p>
             @if(isset($model))
                 <p class="small">