@natachah/vanilla-frontend 0.0.2

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 (104) hide show
  1. package/.gitlab-ci.yml +40 -0
  2. package/LICENSE.md +7 -0
  3. package/README.md +11 -0
  4. package/docs/index.html +36 -0
  5. package/docs/main.js +32 -0
  6. package/docs/pages/components/badge.html +154 -0
  7. package/docs/pages/components/button.html +186 -0
  8. package/docs/pages/components/card.html +184 -0
  9. package/docs/pages/components/dialog.html +334 -0
  10. package/docs/pages/components/disclosure.html +310 -0
  11. package/docs/pages/components/dropdown.html +255 -0
  12. package/docs/pages/components/form.html +331 -0
  13. package/docs/pages/components/list.html +140 -0
  14. package/docs/pages/components/loading.html +58 -0
  15. package/docs/pages/components/media.html +130 -0
  16. package/docs/pages/components/nav.html +119 -0
  17. package/docs/pages/components/progress.html +47 -0
  18. package/docs/pages/components/slider.html +311 -0
  19. package/docs/pages/components/table.html +168 -0
  20. package/docs/pages/javascript/autofill.html +170 -0
  21. package/docs/pages/javascript/checkall.html +59 -0
  22. package/docs/pages/javascript/comfort.html +134 -0
  23. package/docs/pages/javascript/consent.html +112 -0
  24. package/docs/pages/javascript/cookie.html +81 -0
  25. package/docs/pages/javascript/form.html +199 -0
  26. package/docs/pages/javascript/scroll.html +209 -0
  27. package/docs/pages/javascript/sidebar.html +53 -0
  28. package/docs/pages/javascript/sortable.html +148 -0
  29. package/docs/pages/javascript/toggle.html +191 -0
  30. package/docs/pages/javascript/tree.html +221 -0
  31. package/docs/pages/layout/grid.html +201 -0
  32. package/docs/pages/layout/reset.html +53 -0
  33. package/docs/pages/layout/typography.html +324 -0
  34. package/docs/pages/quick-start/conventions.html +112 -0
  35. package/docs/pages/quick-start/customization.html +187 -0
  36. package/docs/pages/quick-start/installation.html +95 -0
  37. package/docs/pages/quick-start/mixins.html +228 -0
  38. package/docs/pages/test.html +15 -0
  39. package/docs/src/js/demo.js +98 -0
  40. package/docs/src/js/doc-code.js +102 -0
  41. package/docs/src/js/doc-demo.js +14 -0
  42. package/docs/src/js/doc-layout.js +108 -0
  43. package/docs/src/scss/demo.scss +77 -0
  44. package/docs/src/scss/layout.scss +160 -0
  45. package/docs/src/scss/style.scss +278 -0
  46. package/docs/vite.config.mjs +23 -0
  47. package/esbuild.mjs +25 -0
  48. package/js/_autofill.js +131 -0
  49. package/js/_check-all.js +77 -0
  50. package/js/_comfort.js +174 -0
  51. package/js/_consent.js +84 -0
  52. package/js/_dialog.js +164 -0
  53. package/js/_dropdown.js +101 -0
  54. package/js/_scroll.js +184 -0
  55. package/js/_sidebar.js +97 -0
  56. package/js/_slider.js +249 -0
  57. package/js/_sortable.js +143 -0
  58. package/js/_tabpanel.js +88 -0
  59. package/js/_toggle.js +123 -0
  60. package/js/_tree.js +85 -0
  61. package/js/tests/autofill.test.js +157 -0
  62. package/js/tests/base-component.test.js +108 -0
  63. package/js/tests/check-all.test.js +88 -0
  64. package/js/tests/comfort.test.js +219 -0
  65. package/js/tests/consent.test.js +84 -0
  66. package/js/tests/cookie.test.js +102 -0
  67. package/js/tests/dialog.test.js +189 -0
  68. package/js/tests/dropdown.test.js +115 -0
  69. package/js/tests/form-helper.test.js +155 -0
  70. package/js/tests/scroll.test.js +203 -0
  71. package/js/tests/sidebar.test.js +99 -0
  72. package/js/tests/slider.test.js +307 -0
  73. package/js/tests/sortable.test.js +124 -0
  74. package/js/tests/tabpanel.test.js +114 -0
  75. package/js/tests/toggle.test.js +190 -0
  76. package/js/tests/tree.test.js +165 -0
  77. package/js/utilities/_base-component.js +101 -0
  78. package/js/utilities/_cookie.js +98 -0
  79. package/js/utilities/_error.js +80 -0
  80. package/js/utilities/_form-helper.js +101 -0
  81. package/package.json +42 -0
  82. package/scss/_badge.scss +37 -0
  83. package/scss/_button.scss +34 -0
  84. package/scss/_card.scss +122 -0
  85. package/scss/_dialog.scss +116 -0
  86. package/scss/_disclosure.scss +101 -0
  87. package/scss/_dropdown.scss +68 -0
  88. package/scss/_form.scss +197 -0
  89. package/scss/_grid.scss +40 -0
  90. package/scss/_group.scss +57 -0
  91. package/scss/_list.scss +18 -0
  92. package/scss/_loading.scss +49 -0
  93. package/scss/_media.scss +37 -0
  94. package/scss/_nav.scss +72 -0
  95. package/scss/_progress.scss +40 -0
  96. package/scss/_slider.scss +35 -0
  97. package/scss/_table.scss +36 -0
  98. package/scss/utilities/_mixin.scss +322 -0
  99. package/scss/utilities/_reset.scss +145 -0
  100. package/scss/utilities/_typography.scss +107 -0
  101. package/scss/vanilla-frontend.scss +23 -0
  102. package/scss/variables/_root.scss +70 -0
  103. package/scss/variables/_setting.scss +63 -0
  104. package/vitest.config.js +7 -0
@@ -0,0 +1,131 @@
1
+ /**
2
+ * ------------------------------------------------------------------
3
+ * Auto fill
4
+ * ------------------------------------------------------------------
5
+ * This class enable the functionality to automatic filling some fields from another
6
+ *
7
+ * @author Natacha Herth
8
+ * @version 0.0.1
9
+ * @copyright Natacha Herth, design & web development
10
+ */
11
+
12
+ import BaseComponent from './utilities/_base-component'
13
+ import ErrorMessage from "./utilities/_error"
14
+
15
+ export default class Autofill extends BaseComponent {
16
+
17
+ /**
18
+ * Creates an instance
19
+ *
20
+ * @param {HTMLElement} el - The HTML element
21
+ * @param {object} options - The custom options
22
+ * @constructor
23
+ */
24
+ constructor(el, options = {}) {
25
+
26
+ // Run the SUPER constructor from BaseComponent
27
+ super(el, options)
28
+
29
+ // Check for errors
30
+ if (el.tagName !== 'SELECT' && el.tagName !== 'INPUT') throw new Error(ErrorMessage.typeOf('el', 'input|select'))
31
+ if (!el.hasAttribute('aria-controls')) throw new Error(ErrorMessage.withAttribute('el', 'aria-controls'))
32
+ if (el.tagName === 'INPUT') {
33
+ if (el.type !== 'text' && el.type !== 'file') throw new Error(ErrorMessage.typeOf('type', 'text|file'))
34
+ if (el.type === 'text' && !el.hasAttribute('list')) throw new Error(ErrorMessage.withAttribute('input', 'list'))
35
+ }
36
+
37
+ // Define the properties
38
+ this._type = el.tagName === 'SELECT' ? 'select' : el.type === 'file' ? 'file' : 'datalist'
39
+
40
+ this._fields = el.hasAttribute('aria-controls') ? el.getAttribute('aria-controls').split(' ').filter(id => document.getElementById(id)).map(id => document.getElementById(id)) : []
41
+
42
+ // Init the event listener
43
+ this.#init()
44
+
45
+ }
46
+
47
+ /**
48
+ * Init the event listener
49
+ *
50
+ * @private
51
+ */
52
+ #init() {
53
+
54
+ // CHANGE the element
55
+ this._element.addEventListener('change', () => {
56
+
57
+ switch (this._type) {
58
+ case 'select':
59
+ this.#byOption(this._element.options[this._element.selectedIndex])
60
+ break
61
+ case 'datalist':
62
+ this.#byOption(document.querySelector(`#${this._element.getAttribute('list')} [value="${this._element.value}"]`))
63
+ break
64
+ case 'file':
65
+ this.#byFile(this._element.files[0])
66
+ break
67
+ }
68
+
69
+ })
70
+
71
+ }
72
+
73
+ /**
74
+ * Set value from a <option>
75
+ *
76
+ * @param {string} option - Current option selected
77
+ * @private
78
+ */
79
+ #byOption(option) {
80
+
81
+ this._fields.forEach(field => {
82
+ const attribute = `data-${field.getAttribute('data-autofill')}`
83
+ field.value = option && option.hasAttribute(attribute) ? option.getAttribute(attribute) : ''
84
+ })
85
+
86
+ // Emmit event
87
+ this.emmitEvent('changed', { current: option })
88
+
89
+ }
90
+
91
+ /**
92
+ * Set value from an uploaded file
93
+ *
94
+ * @param {File} file - Current file selected
95
+ * @private
96
+ */
97
+ #byFile(file) {
98
+
99
+ // Clean data
100
+ const extension = file.name.split('.').pop()
101
+ const name = file.name.replace(`.${extension}`, '')
102
+
103
+ this._fields.forEach(field => {
104
+
105
+ // Define attribute
106
+ const attribute = field.getAttribute('data-autofill')
107
+
108
+ // Define the value
109
+ let value
110
+ switch (attribute) {
111
+ case 'filename':
112
+ value = name
113
+ break
114
+ case 'extension':
115
+ value = extension
116
+ break
117
+ default:
118
+ value = file[attribute] ?? ''
119
+ }
120
+
121
+ // Set the value
122
+ field.value = value
123
+
124
+ })
125
+
126
+ // Emmit event
127
+ this.emmitEvent('changed', { current: file })
128
+
129
+ }
130
+
131
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * ------------------------------------------------------------------
3
+ * Check all
4
+ * ------------------------------------------------------------------
5
+ * This class enable the functionality to un/check a list of checkboxes
6
+ *
7
+ * @author Natacha Herth
8
+ * @version 0.0.1
9
+ * @copyright Natacha Herth, design & web development
10
+ */
11
+
12
+ import BaseComponent from './utilities/_base-component'
13
+
14
+ export default class CheckAll extends BaseComponent {
15
+
16
+ /**
17
+ * Creates an instance
18
+ *
19
+ * @param {HTMLElement} el - The HTML element
20
+ * @param {object} options - The custom options
21
+ * @constructor
22
+ */
23
+ constructor(el, options = {}) {
24
+
25
+ // Run the SUPER constructor from BaseComponent
26
+ super(el, options)
27
+
28
+ // Define the properties
29
+ this._checkboxes = document.querySelectorAll(`input[type="checkbox"][name="${this._element.value}"]`)
30
+
31
+ // Init the event listener
32
+ this.#init()
33
+
34
+ }
35
+
36
+ /**
37
+ * Init the event listener
38
+ *
39
+ * @private
40
+ */
41
+ #init() {
42
+
43
+ // Check the "check all" checkbox by default is needed
44
+ this._element.checked = this.number.total === this.number.checked
45
+
46
+ // CLICK on "check all"
47
+ this._element.addEventListener('change', () => {
48
+ this._checkboxes.forEach((checkbox) => checkbox.checked = this._element.checked)
49
+ })
50
+
51
+ // CLICK on "checkboxes"
52
+ this._checkboxes.forEach(checkbox => {
53
+ checkbox.addEventListener('change', () => this._element.checked = this.number.total === this.number.checked)
54
+ })
55
+
56
+ }
57
+
58
+ /**
59
+ * Get the number of checkboxes as total, checked and unchecked
60
+ *
61
+ * @returns {object}
62
+ */
63
+ get number() {
64
+
65
+ let checkboxes = {
66
+ total: this._checkboxes.length,
67
+ checked: 0,
68
+ unchecked: 0
69
+ }
70
+
71
+ this._checkboxes.forEach((checkbox) => checkbox.checked ? checkboxes.checked++ : checkboxes.unchecked++)
72
+
73
+ return checkboxes
74
+
75
+ }
76
+
77
+ }
package/js/_comfort.js ADDED
@@ -0,0 +1,174 @@
1
+ /**
2
+ * ------------------------------------------------------------------
3
+ * Comfort
4
+ * ------------------------------------------------------------------
5
+ * This class create and manage the cookies for saving theme and style changes for visual comfort
6
+ *
7
+ * @author Natacha Herth
8
+ * @version 0.0.1
9
+ * @copyright Natacha Herth, design & web development
10
+ */
11
+
12
+ import Cookie from "./utilities/_cookie"
13
+ import ErrorMessage from "./utilities/_error"
14
+
15
+ export default class Comfort extends Cookie {
16
+
17
+ /**
18
+ * Creates an instance
19
+ *
20
+ * @param {string} name - The name of the cookie
21
+ * @constructor
22
+ */
23
+ constructor(name = '_comfort') {
24
+
25
+ // Run the SUPER constructor from Cookie
26
+ super(name)
27
+
28
+ // Define the properties
29
+ this._buttons = {
30
+ theme: document.querySelectorAll('body [data-theme]'),
31
+ style: document.querySelectorAll('body [data-style]'),
32
+ }
33
+
34
+ // Init the cookie
35
+ this.#init()
36
+
37
+ }
38
+
39
+ /**
40
+ * Init the event listener
41
+ *
42
+ * @private
43
+ */
44
+ #init() {
45
+
46
+ // If the cookie is NOT empty, toggle the attributes on <html> <body> and <button>
47
+ if (Object.keys(this.value).length !== 0) {
48
+ this.#toggleTheme()
49
+ this.#toggleStyle()
50
+ }
51
+
52
+ // CLICK on theme buttons
53
+ this._buttons.theme.forEach((button) => button.addEventListener('click', () => this.setTheme(button.value)))
54
+
55
+ // CLICK on style buttons
56
+ this._buttons.style.forEach((button) => button.addEventListener('click', () => this.setStyle(button.getAttribute('data-style'), button.value)))
57
+
58
+ }
59
+
60
+ /**
61
+ * Toggle the [data-theme] attribute on the <html>
62
+ * and the [aria-pressed] attribute on the <button>
63
+ *
64
+ * @private
65
+ */
66
+ #toggleTheme() {
67
+
68
+ // Do nothing if there is no theme in the cookie
69
+ if (!this.has('theme')) return
70
+
71
+ // Set the [data-theme] attribute on the <html>
72
+ document.documentElement.setAttribute('data-theme', this.get('theme'))
73
+
74
+ // Set the [aria-pressed] attribute on the <button>
75
+ this._buttons.theme.forEach(button => button.setAttribute('aria-pressed', button.value === this.get('theme')))
76
+
77
+ }
78
+
79
+ /**
80
+ * Toggle the [style] attribute on the <body>
81
+ * and the [aria-pressed] attribute on the <button>
82
+ *
83
+ * @private
84
+ */
85
+ #toggleStyle() {
86
+
87
+ // Get the style object stored in cookie
88
+ const style = this.get('style')
89
+
90
+ // Do nothing if there is no style in the cookie
91
+ if (!style || style.length === 0) return
92
+
93
+ // Set the [style] attribute on the <body>
94
+ const styleAsString = Object.entries(style).map(([k, v]) => `${k}:${v}`).join(';')
95
+ document.body.setAttribute('style', styleAsString)
96
+
97
+ // Set the [aria-pressed] attribute on the <button>
98
+ this._buttons.style.forEach(button => {
99
+ const attribute = button.getAttribute('data-style')
100
+ button.setAttribute('aria-pressed', style.hasOwnProperty(attribute) && style[attribute] === button.value)
101
+ })
102
+
103
+ }
104
+
105
+ /**
106
+ * Save the theme inside the cookie
107
+ *
108
+ * @param {string} value - Name of the theme
109
+ */
110
+ setTheme(value) {
111
+
112
+ // Check for errors
113
+ if (typeof value !== 'string') throw new Error(ErrorMessage.typeOf('value', 'string'))
114
+
115
+ // Do nothing if it's already the current theme
116
+ if (this.get('theme') === value) return
117
+
118
+ // Save the cookie
119
+ this.set({ ...this.value, theme: value })
120
+
121
+ // Then toggle theme
122
+ this.#toggleTheme()
123
+
124
+ }
125
+
126
+ /**
127
+ * Save the style inside the cookie
128
+ *
129
+ * @param {string} name - Name of the CSS property
130
+ * @param {string} value - Value of the CSS property
131
+ */
132
+ setStyle(name, value) {
133
+
134
+ // Check for errors
135
+ if (typeof name !== 'string') throw new Error(ErrorMessage.typeOf('name', 'string'))
136
+ if (typeof value !== 'string') throw new Error(ErrorMessage.typeOf('value', 'string'))
137
+
138
+ // Get the style inside the cookie
139
+ const style = this.get('style')
140
+
141
+ // Do nothing if it's already the current style
142
+ if (style && style.hasOwnProperty(name) && style[name] === value) return
143
+
144
+ // Save the cookie
145
+ this.set({
146
+ ...this.value,
147
+ style: { ...this.value.style, ...{ [name]: value } }
148
+ })
149
+
150
+ // Then toggle style
151
+ this.#toggleStyle()
152
+
153
+ }
154
+
155
+ /**
156
+ * Reset the comfort cookie
157
+ *
158
+ */
159
+ reset() {
160
+
161
+ // Delete the cookie
162
+ this.delete()
163
+
164
+ // Remove the attributes on <html> <body> and <button>
165
+ document.documentElement.removeAttribute('data-theme')
166
+ document.body.removeAttribute('style');
167
+
168
+ [...this._buttons.theme, ...this._buttons.style].forEach(button => {
169
+ button.removeAttribute('aria-pressed')
170
+ })
171
+
172
+ }
173
+
174
+ }
package/js/_consent.js ADDED
@@ -0,0 +1,84 @@
1
+ /**
2
+ * ------------------------------------------------------------------
3
+ * Consent
4
+ * ------------------------------------------------------------------
5
+ * This class create and manage the cookies for saving the consent to comply the GDPR
6
+ *
7
+ * @author Natacha Herth
8
+ * @version 0.0.1
9
+ * @copyright Natacha Herth, design & web development
10
+ */
11
+
12
+ import Cookie from "./utilities/_cookie"
13
+ import Dialog from "./_dialog"
14
+ import ErrorMessage from "./utilities/_error"
15
+
16
+ export default class Consent extends Cookie {
17
+
18
+ static DEFAULT = { necessary: true }
19
+
20
+ /**
21
+ * Creates an instance
22
+ *
23
+ * @param {string} name - The name of the cookie
24
+ * @param {string} dialogID - The id of the cookies dialog
25
+ * @constructor
26
+ */
27
+ constructor(name = '_consent', dialogID = 'cookies') {
28
+
29
+ // Check for errors
30
+ if (typeof dialogID !== 'string') throw new Error(ErrorMessage.typeOf('dialogID', 'string'))
31
+ if (!document.getElementById(dialogID)) throw new Error(ErrorMessage.existById('dialog', dialogID))
32
+
33
+ // Run the SUPER constructor from Cookie
34
+ super(name)
35
+
36
+ // Define the properties
37
+ this._dialog = new Dialog(document.getElementById(dialogID))
38
+
39
+ // Init the cookie
40
+ this.#init()
41
+
42
+ }
43
+
44
+ /**
45
+ * Init the event listener
46
+ *
47
+ * @private
48
+ */
49
+ #init() {
50
+
51
+ // If the cookie is empty, open the dialog
52
+ if (Object.keys(this.value).length === 0) this._dialog.open()
53
+
54
+ // Set the cookie via the dialog:closed event
55
+ this._dialog._element.addEventListener('dialog:closed', () => this.set(Consent.DEFAULT))
56
+
57
+ // Set the cookie via the dialog:submiting event
58
+ this._dialog._element.addEventListener('dialog:submiting', (e) => this.#setByForm(e.detail.form))
59
+
60
+ }
61
+
62
+ /**
63
+ * Save the consent cookie via a form with input of type checkbox
64
+ *
65
+ * @param {HTMLElement} form
66
+ * @private
67
+ */
68
+ #setByForm(form) {
69
+
70
+ // Check for errors
71
+ if (!(form instanceof HTMLElement)) throw new Error('Whoops, the form parameter must be an HTML Element !')
72
+
73
+ // Get all the input of type checkbox with name cookies_consent[]
74
+ const fields = form.querySelectorAll('input[type="checkbox"][name="cookies_consent[]"]')
75
+
76
+ // If there is some fields, add each to the variable preferences and save it
77
+ if (fields.length) {
78
+ const preferences = [...fields].reduce((obj, field) => { return { ...obj, ...Consent.DEFAULT, [field.value]: field.checked } }, {})
79
+ this.set(preferences)
80
+ }
81
+
82
+ }
83
+
84
+ }
package/js/_dialog.js ADDED
@@ -0,0 +1,164 @@
1
+ /**
2
+ * ------------------------------------------------------------------
3
+ * Dialog
4
+ * ------------------------------------------------------------------
5
+ * This class enable the functionalities for open/close/submit an HTML dialog
6
+ *
7
+ * @author Natacha Herth
8
+ * @version 0.0.1
9
+ * @copyright Natacha Herth, design & web development
10
+ */
11
+
12
+ import BaseComponent from './utilities/_base-component'
13
+ import ErrorMessage from './utilities/_error'
14
+
15
+ export default class Dialog extends BaseComponent {
16
+
17
+ /**
18
+ * Creates an instance
19
+ *
20
+ * @param {HTMLElement} el - The HTML element
21
+ * @param {object} options - The custom options
22
+ * @constructor
23
+ */
24
+ constructor(el, options = {}) {
25
+
26
+ // Run the SUPER constructor from BaseComponent
27
+ super(el, options)
28
+
29
+ // Define the properties
30
+ this._isModal = Boolean(this._element.getAttribute('aria-modal'))
31
+
32
+ this._buttons = {
33
+ open: document.querySelectorAll(`[aria-controls=${this._element.id}]`) ?? [],
34
+ close: this._element.querySelectorAll('[data-dialog-close]') ?? [],
35
+ submit: this._element.querySelectorAll('[type=submit]') ?? [],
36
+ }
37
+
38
+ this._form = this._element.querySelector('form') ?? {}
39
+
40
+ // Init the event listener
41
+ this.#init()
42
+
43
+ }
44
+
45
+ /**
46
+ * Init the event listener
47
+ *
48
+ * @private
49
+ */
50
+ #init() {
51
+
52
+ // OPEN
53
+ this._buttons.open.forEach((button) => button.addEventListener('click', () => this.open()))
54
+
55
+ // CLOSE
56
+ this._buttons.close.forEach((button) => button.addEventListener('click', () => this.close()))
57
+
58
+ // SUBMIT
59
+ this._buttons.submit.forEach((button) => {
60
+ button.addEventListener('click', (e) => {
61
+ e.preventDefault()
62
+ this.submit()
63
+ })
64
+ })
65
+
66
+ }
67
+
68
+ /**
69
+ * Remove the [inert] attribute from the body if the dialog a modal
70
+ *
71
+ * @private
72
+ */
73
+ #toggleBodyAttribute() {
74
+ if (!this._isModal) return
75
+ const numberOfDialogOpen = document.querySelectorAll('dialog[open][aria-modal=true]').length
76
+ numberOfDialogOpen ? document.body.setAttribute('inert', true) : document.body.removeAttribute('inert')
77
+ }
78
+
79
+ /**
80
+ * Open the dialog
81
+ *
82
+ */
83
+ open() {
84
+
85
+ // Run event before opening, and stop if e.preventDefault()
86
+ const callback = this.emmitEvent('opening')
87
+ if (callback.defaultPrevented) return
88
+
89
+ // Open the dialog (the methode changed if it's a modal)
90
+ this._isModal ? this._element.showModal() : this._element.show()
91
+
92
+ // Toggle the [inert] attribute on the body
93
+ this.#toggleBodyAttribute()
94
+
95
+ // Run event after opened
96
+ this.emmitEvent('opened')
97
+
98
+ }
99
+
100
+ /**
101
+ * Close the dialog
102
+ *
103
+ */
104
+ close() {
105
+
106
+ // Run event before closing, and stop if e.preventDefault()
107
+ const callback = this.emmitEvent('closing')
108
+ if (callback.defaultPrevented) return
109
+
110
+ // Close the dialog
111
+ this._element.close()
112
+
113
+ // Toggle the [inert] attribute on the body
114
+ this.#toggleBodyAttribute()
115
+
116
+ // Run event after closed
117
+ this.emmitEvent('closed')
118
+
119
+ }
120
+
121
+ /**
122
+ * Submit the form in the dialog as default
123
+ *
124
+ */
125
+ submit() {
126
+
127
+ // Check for errors
128
+ if (!this._form.length) throw new Error(ErrorMessage.exist('form'))
129
+
130
+ // Stop if the form is invalid (Default required fields)
131
+ if (!this._form.reportValidity()) return
132
+
133
+ // Add [aria-busy] attribute on each submit button
134
+ this._buttons.submit.forEach((button) => button.setAttribute('aria-busy', true))
135
+
136
+ // Run event before submitting, and stop if e.preventDefault()
137
+ const callback = this.emmitEvent('submiting', { form: this._form })
138
+ if (callback.defaultPrevented) return
139
+
140
+ // Define if the form is submited by Javascript or default
141
+ if (this._form.getAttribute('method') == 'dialog') {
142
+
143
+ // Remove [aria-busy] attribute on each submit button
144
+ this._buttons.submit.forEach((button) => button.removeAttribute('aria-busy', true))
145
+
146
+ // Close the dialog element
147
+ this._element.close()
148
+
149
+ // Toggle the [inert] attribute on the body
150
+ this.#toggleBodyAttribute()
151
+
152
+ // Run event after submited
153
+ this.emmitEvent('submited', { form: this._form })
154
+
155
+ } else {
156
+
157
+ // Default <form> submit
158
+ this._form.submit()
159
+
160
+ }
161
+
162
+ }
163
+
164
+ }