browser-extension-manager 1.0.13 → 1.1.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 (242) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/CLAUDE.md +672 -0
  3. package/TODO.md +3 -0
  4. package/dist/assets/css/browser-extension-manager.scss +18 -0
  5. package/dist/assets/css/components/content/index.scss +5 -0
  6. package/dist/assets/css/components/options/index.scss +5 -0
  7. package/dist/assets/css/components/pages/index.scss +5 -0
  8. package/dist/assets/css/components/popup/index.scss +5 -0
  9. package/dist/assets/css/core/_animations.scss +64 -0
  10. package/dist/assets/css/core/_initialize.scss +23 -0
  11. package/dist/assets/css/core/_utilities.scss +80 -0
  12. package/dist/assets/themes/_template/_theme.js +5 -0
  13. package/dist/assets/themes/_template/_theme.scss +5 -0
  14. package/dist/assets/themes/bootstrap/_theme.js +16 -0
  15. package/dist/assets/themes/bootstrap/_theme.scss +232 -0
  16. package/dist/assets/themes/bootstrap/js/index.esm.js +19 -0
  17. package/dist/assets/themes/bootstrap/js/index.umd.js +34 -0
  18. package/dist/assets/themes/bootstrap/js/src/alert.js +87 -0
  19. package/dist/assets/themes/bootstrap/js/src/base-component.js +86 -0
  20. package/dist/assets/themes/bootstrap/js/src/button.js +72 -0
  21. package/dist/assets/themes/bootstrap/js/src/carousel.js +474 -0
  22. package/dist/assets/themes/bootstrap/js/src/collapse.js +297 -0
  23. package/dist/assets/themes/bootstrap/js/src/dom/data.js +55 -0
  24. package/dist/assets/themes/bootstrap/js/src/dom/event-handler.js +317 -0
  25. package/dist/assets/themes/bootstrap/js/src/dom/manipulator.js +71 -0
  26. package/dist/assets/themes/bootstrap/js/src/dom/selector-engine.js +126 -0
  27. package/dist/assets/themes/bootstrap/js/src/dropdown.js +458 -0
  28. package/dist/assets/themes/bootstrap/js/src/modal.js +378 -0
  29. package/dist/assets/themes/bootstrap/js/src/offcanvas.js +282 -0
  30. package/dist/assets/themes/bootstrap/js/src/popover.js +97 -0
  31. package/dist/assets/themes/bootstrap/js/src/scrollspy.js +296 -0
  32. package/dist/assets/themes/bootstrap/js/src/tab.js +315 -0
  33. package/dist/assets/themes/bootstrap/js/src/toast.js +224 -0
  34. package/dist/assets/themes/bootstrap/js/src/tooltip.js +632 -0
  35. package/dist/assets/themes/bootstrap/js/src/util/backdrop.js +151 -0
  36. package/dist/assets/themes/bootstrap/js/src/util/component-functions.js +35 -0
  37. package/dist/assets/themes/bootstrap/js/src/util/config.js +65 -0
  38. package/dist/assets/themes/bootstrap/js/src/util/focustrap.js +115 -0
  39. package/dist/assets/themes/bootstrap/js/src/util/index.js +306 -0
  40. package/dist/assets/themes/bootstrap/js/src/util/sanitizer.js +117 -0
  41. package/dist/assets/themes/bootstrap/js/src/util/scrollbar.js +114 -0
  42. package/dist/assets/themes/bootstrap/js/src/util/swipe.js +146 -0
  43. package/dist/assets/themes/bootstrap/js/src/util/template-factory.js +160 -0
  44. package/dist/assets/themes/bootstrap/scss/_accordion.scss +153 -0
  45. package/dist/assets/themes/bootstrap/scss/_alert.scss +68 -0
  46. package/dist/assets/themes/bootstrap/scss/_badge.scss +38 -0
  47. package/dist/assets/themes/bootstrap/scss/_breadcrumb.scss +40 -0
  48. package/dist/assets/themes/bootstrap/scss/_button-group.scss +147 -0
  49. package/dist/assets/themes/bootstrap/scss/_buttons.scss +216 -0
  50. package/dist/assets/themes/bootstrap/scss/_card.scss +238 -0
  51. package/dist/assets/themes/bootstrap/scss/_carousel.scss +226 -0
  52. package/dist/assets/themes/bootstrap/scss/_close.scss +66 -0
  53. package/dist/assets/themes/bootstrap/scss/_containers.scss +41 -0
  54. package/dist/assets/themes/bootstrap/scss/_dropdown.scss +250 -0
  55. package/dist/assets/themes/bootstrap/scss/_forms.scss +9 -0
  56. package/dist/assets/themes/bootstrap/scss/_functions.scss +302 -0
  57. package/dist/assets/themes/bootstrap/scss/_grid.scss +39 -0
  58. package/dist/assets/themes/bootstrap/scss/_helpers.scss +12 -0
  59. package/dist/assets/themes/bootstrap/scss/_images.scss +42 -0
  60. package/dist/assets/themes/bootstrap/scss/_list-group.scss +199 -0
  61. package/dist/assets/themes/bootstrap/scss/_maps.scss +174 -0
  62. package/dist/assets/themes/bootstrap/scss/_mixins.scss +42 -0
  63. package/dist/assets/themes/bootstrap/scss/_modal.scss +240 -0
  64. package/dist/assets/themes/bootstrap/scss/_nav.scss +197 -0
  65. package/dist/assets/themes/bootstrap/scss/_navbar.scss +289 -0
  66. package/dist/assets/themes/bootstrap/scss/_offcanvas.scss +147 -0
  67. package/dist/assets/themes/bootstrap/scss/_pagination.scss +109 -0
  68. package/dist/assets/themes/bootstrap/scss/_placeholders.scss +51 -0
  69. package/dist/assets/themes/bootstrap/scss/_popover.scss +196 -0
  70. package/dist/assets/themes/bootstrap/scss/_progress.scss +68 -0
  71. package/dist/assets/themes/bootstrap/scss/_reboot.scss +611 -0
  72. package/dist/assets/themes/bootstrap/scss/_root.scss +187 -0
  73. package/dist/assets/themes/bootstrap/scss/_spinners.scss +85 -0
  74. package/dist/assets/themes/bootstrap/scss/_tables.scss +171 -0
  75. package/dist/assets/themes/bootstrap/scss/_toasts.scss +73 -0
  76. package/dist/assets/themes/bootstrap/scss/_tooltip.scss +119 -0
  77. package/dist/assets/themes/bootstrap/scss/_transitions.scss +27 -0
  78. package/dist/assets/themes/bootstrap/scss/_type.scss +106 -0
  79. package/dist/assets/themes/bootstrap/scss/_utilities.scss +806 -0
  80. package/dist/assets/themes/bootstrap/scss/_variables-dark.scss +102 -0
  81. package/dist/assets/themes/bootstrap/scss/_variables.scss +1753 -0
  82. package/dist/assets/themes/bootstrap/scss/bootstrap-grid.scss +62 -0
  83. package/dist/assets/themes/bootstrap/scss/bootstrap-reboot.scss +10 -0
  84. package/dist/assets/themes/bootstrap/scss/bootstrap-utilities.scss +19 -0
  85. package/dist/assets/themes/bootstrap/scss/bootstrap.scss +52 -0
  86. package/dist/assets/themes/bootstrap/scss/forms/_floating-labels.scss +97 -0
  87. package/dist/assets/themes/bootstrap/scss/forms/_form-check.scss +189 -0
  88. package/dist/assets/themes/bootstrap/scss/forms/_form-control.scss +214 -0
  89. package/dist/assets/themes/bootstrap/scss/forms/_form-range.scss +91 -0
  90. package/dist/assets/themes/bootstrap/scss/forms/_form-select.scss +80 -0
  91. package/dist/assets/themes/bootstrap/scss/forms/_form-text.scss +11 -0
  92. package/dist/assets/themes/bootstrap/scss/forms/_input-group.scss +132 -0
  93. package/dist/assets/themes/bootstrap/scss/forms/_labels.scss +36 -0
  94. package/dist/assets/themes/bootstrap/scss/forms/_validation.scss +12 -0
  95. package/dist/assets/themes/bootstrap/scss/helpers/_clearfix.scss +3 -0
  96. package/dist/assets/themes/bootstrap/scss/helpers/_color-bg.scss +7 -0
  97. package/dist/assets/themes/bootstrap/scss/helpers/_colored-links.scss +30 -0
  98. package/dist/assets/themes/bootstrap/scss/helpers/_focus-ring.scss +5 -0
  99. package/dist/assets/themes/bootstrap/scss/helpers/_icon-link.scss +25 -0
  100. package/dist/assets/themes/bootstrap/scss/helpers/_position.scss +36 -0
  101. package/dist/assets/themes/bootstrap/scss/helpers/_ratio.scss +26 -0
  102. package/dist/assets/themes/bootstrap/scss/helpers/_stacks.scss +15 -0
  103. package/dist/assets/themes/bootstrap/scss/helpers/_stretched-link.scss +15 -0
  104. package/dist/assets/themes/bootstrap/scss/helpers/_text-truncation.scss +7 -0
  105. package/dist/assets/themes/bootstrap/scss/helpers/_visually-hidden.scss +8 -0
  106. package/dist/assets/themes/bootstrap/scss/helpers/_vr.scss +8 -0
  107. package/dist/assets/themes/bootstrap/scss/mixins/_alert.scss +18 -0
  108. package/dist/assets/themes/bootstrap/scss/mixins/_backdrop.scss +14 -0
  109. package/dist/assets/themes/bootstrap/scss/mixins/_banner.scss +7 -0
  110. package/dist/assets/themes/bootstrap/scss/mixins/_border-radius.scss +78 -0
  111. package/dist/assets/themes/bootstrap/scss/mixins/_box-shadow.scss +18 -0
  112. package/dist/assets/themes/bootstrap/scss/mixins/_breakpoints.scss +127 -0
  113. package/dist/assets/themes/bootstrap/scss/mixins/_buttons.scss +70 -0
  114. package/dist/assets/themes/bootstrap/scss/mixins/_caret.scss +69 -0
  115. package/dist/assets/themes/bootstrap/scss/mixins/_clearfix.scss +9 -0
  116. package/dist/assets/themes/bootstrap/scss/mixins/_color-mode.scss +21 -0
  117. package/dist/assets/themes/bootstrap/scss/mixins/_color-scheme.scss +7 -0
  118. package/dist/assets/themes/bootstrap/scss/mixins/_container.scss +11 -0
  119. package/dist/assets/themes/bootstrap/scss/mixins/_deprecate.scss +10 -0
  120. package/dist/assets/themes/bootstrap/scss/mixins/_forms.scss +163 -0
  121. package/dist/assets/themes/bootstrap/scss/mixins/_gradients.scss +47 -0
  122. package/dist/assets/themes/bootstrap/scss/mixins/_grid.scss +151 -0
  123. package/dist/assets/themes/bootstrap/scss/mixins/_image.scss +16 -0
  124. package/dist/assets/themes/bootstrap/scss/mixins/_list-group.scss +26 -0
  125. package/dist/assets/themes/bootstrap/scss/mixins/_lists.scss +7 -0
  126. package/dist/assets/themes/bootstrap/scss/mixins/_pagination.scss +10 -0
  127. package/dist/assets/themes/bootstrap/scss/mixins/_reset-text.scss +17 -0
  128. package/dist/assets/themes/bootstrap/scss/mixins/_resize.scss +6 -0
  129. package/dist/assets/themes/bootstrap/scss/mixins/_table-variants.scss +24 -0
  130. package/dist/assets/themes/bootstrap/scss/mixins/_text-truncate.scss +8 -0
  131. package/dist/assets/themes/bootstrap/scss/mixins/_transition.scss +26 -0
  132. package/dist/assets/themes/bootstrap/scss/mixins/_utilities.scss +97 -0
  133. package/dist/assets/themes/bootstrap/scss/mixins/_visually-hidden.scss +38 -0
  134. package/dist/assets/themes/bootstrap/scss/tests/jasmine.js +16 -0
  135. package/dist/assets/themes/bootstrap/scss/tests/mixins/_auto-import-of-variables-dark.test.scss +7 -0
  136. package/dist/assets/themes/bootstrap/scss/tests/mixins/_color-modes.test.scss +69 -0
  137. package/dist/assets/themes/bootstrap/scss/tests/mixins/_media-query-color-mode-full.test.scss +8 -0
  138. package/dist/assets/themes/bootstrap/scss/tests/mixins/_utilities.test.scss +393 -0
  139. package/dist/assets/themes/bootstrap/scss/tests/sass-true/register.js +14 -0
  140. package/dist/assets/themes/bootstrap/scss/tests/sass-true/runner.js +17 -0
  141. package/dist/assets/themes/bootstrap/scss/tests/utilities/_api.test.scss +75 -0
  142. package/dist/assets/themes/bootstrap/scss/utilities/_api.scss +47 -0
  143. package/dist/assets/themes/bootstrap/scss/vendor/_rfs.scss +348 -0
  144. package/dist/assets/themes/classy/README.md +75 -0
  145. package/dist/assets/themes/classy/_config.scss +185 -0
  146. package/dist/assets/themes/classy/_theme.js +29 -0
  147. package/dist/assets/themes/classy/_theme.scss +34 -0
  148. package/dist/assets/themes/classy/css/base/_animations.scss +27 -0
  149. package/dist/assets/themes/classy/css/base/_backgrounds.scss +191 -0
  150. package/dist/assets/themes/classy/css/base/_borders.scss +65 -0
  151. package/dist/assets/themes/classy/css/base/_root.scss +58 -0
  152. package/dist/assets/themes/classy/css/base/_soft-colors.scss +92 -0
  153. package/dist/assets/themes/classy/css/base/_spacing.scss +64 -0
  154. package/dist/assets/themes/classy/css/base/_typography.scss +179 -0
  155. package/dist/assets/themes/classy/css/base/_utilities.scss +77 -0
  156. package/dist/assets/themes/classy/css/components/_accordion.scss +33 -0
  157. package/dist/assets/themes/classy/css/components/_avatars.scss +32 -0
  158. package/dist/assets/themes/classy/css/components/_badges.scss +25 -0
  159. package/dist/assets/themes/classy/css/components/_buttons.scss +397 -0
  160. package/dist/assets/themes/classy/css/components/_cards.scss +33 -0
  161. package/dist/assets/themes/classy/css/components/_carousel.scss +41 -0
  162. package/dist/assets/themes/classy/css/components/_forms.scss +115 -0
  163. package/dist/assets/themes/classy/css/components/_links.scss +19 -0
  164. package/dist/assets/themes/classy/css/components/_logo-scroll.scss +57 -0
  165. package/dist/assets/themes/classy/css/components/_spinners.scss +19 -0
  166. package/dist/assets/themes/classy/css/components/_text.scss +41 -0
  167. package/dist/assets/themes/classy/css/layout/_blog.scss +42 -0
  168. package/dist/assets/themes/classy/css/layout/_general.scss +139 -0
  169. package/dist/assets/themes/classy/css/layout/_navigation.scss +576 -0
  170. package/dist/assets/themes/classy/css/layout/_team.scss +18 -0
  171. package/dist/assets/themes/classy/js/logo-scroll.js +83 -0
  172. package/dist/assets/themes/classy/js/navbar-scroll.js +65 -0
  173. package/dist/background.js +236 -260
  174. package/dist/build.js +93 -4
  175. package/dist/commands/setup.js +0 -268
  176. package/dist/config/manifest.json +11 -3
  177. package/dist/config/page-template.html +21 -0
  178. package/dist/defaults/.nvmrc +1 -1
  179. package/dist/defaults/CLAUDE.md +8 -0
  180. package/dist/defaults/config/browser-extension-manager.json +37 -0
  181. package/dist/defaults/src/assets/css/components/content/index.scss +11 -0
  182. package/dist/defaults/src/assets/css/components/options/index.scss +14 -0
  183. package/dist/defaults/src/assets/css/components/pages/index.scss +10 -0
  184. package/dist/defaults/src/assets/css/components/popup/index.scss +10 -0
  185. package/dist/defaults/src/assets/css/components/sidepanel/index.scss +6 -0
  186. package/dist/defaults/src/assets/css/main.scss +32 -0
  187. package/dist/defaults/src/assets/js/components/background/index.js +22 -0
  188. package/dist/defaults/src/assets/js/components/content/index.js +22 -0
  189. package/dist/defaults/src/assets/js/components/options/index.js +22 -0
  190. package/dist/defaults/src/assets/js/components/pages/index.js +22 -0
  191. package/dist/defaults/src/assets/js/components/popup/index.js +22 -0
  192. package/dist/defaults/src/assets/js/components/sidepanel/index.js +20 -0
  193. package/dist/defaults/src/assets/vendor/.gitkeep +0 -0
  194. package/dist/defaults/src/manifest.json +11 -6
  195. package/dist/defaults/src/views/options/index.html +8 -0
  196. package/dist/defaults/src/views/pages/index.html +10 -0
  197. package/dist/defaults/src/views/popup/index.html +4 -0
  198. package/dist/defaults/src/views/sidepanel/index.html +4 -0
  199. package/dist/gulp/main.js +11 -5
  200. package/dist/gulp/plugins/webpack/strip-dev-blocks.js +53 -0
  201. package/dist/gulp/tasks/{_package.js → BU/_package.js} +1 -1
  202. package/dist/gulp/tasks/{developmentRebuild.js → BU/developmentRebuild.js} +1 -1
  203. package/dist/gulp/tasks/{themes.js → BU/themes.js} +3 -2
  204. package/dist/gulp/tasks/{test.js → _.js} +3 -3
  205. package/dist/gulp/tasks/audit.js +154 -0
  206. package/dist/gulp/tasks/defaults.js +308 -0
  207. package/dist/gulp/tasks/distribute.js +87 -92
  208. package/dist/gulp/tasks/html.js +150 -0
  209. package/dist/gulp/tasks/icons.js +3 -2
  210. package/dist/gulp/tasks/package.js +216 -27
  211. package/dist/gulp/tasks/sass.js +188 -43
  212. package/dist/gulp/tasks/serve.js +1 -0
  213. package/dist/gulp/tasks/utils/template-transform.js +50 -0
  214. package/dist/gulp/tasks/webpack.js +338 -134
  215. package/dist/index.js +34 -34
  216. package/dist/options.js +40 -0
  217. package/dist/page.js +40 -0
  218. package/dist/popup.js +40 -0
  219. package/dist/sidepanel.js +40 -0
  220. package/firebase-debug.log +322 -0
  221. package/package.json +25 -18
  222. package/dist/assets/css/main.scss +0 -3
  223. package/dist/assets/themes/bootstrap/5.3.3/css/bootstrap.css +0 -12057
  224. package/dist/assets/themes/bootstrap/5.3.3/css/bootstrap.css.map +0 -1
  225. package/dist/assets/themes/bootstrap/5.3.3/js/bootstrap.bundle.js +0 -6314
  226. package/dist/assets/themes/bootstrap/5.3.3/js/bootstrap.bundle.js.map +0 -1
  227. package/dist/assets/themes/bootstrap/5.3.3/js/bootstrap.js +0 -4494
  228. package/dist/assets/themes/bootstrap/5.3.3/js/bootstrap.js.map +0 -1
  229. package/dist/defaults/src/assets/css/content.scss +0 -2
  230. package/dist/defaults/src/assets/css/options.scss +0 -11
  231. package/dist/defaults/src/assets/css/popup.scss +0 -14
  232. package/dist/defaults/src/assets/js/background.js +0 -18
  233. package/dist/defaults/src/assets/js/content.js +0 -15
  234. package/dist/defaults/src/assets/js/options.js +0 -17
  235. package/dist/defaults/src/assets/js/popup.js +0 -17
  236. package/dist/defaults/src/pages/options.html +0 -26
  237. package/dist/defaults/src/pages/popup.html +0 -26
  238. /package/dist/{defaults/src/assets/images/_ → assets/css/bundles/.gitkeep} +0 -0
  239. /package/dist/assets/css/{fontawesome.scss → core/_fontawesome.scss} +0 -0
  240. /package/dist/defaults/src/assets/{vendor/_ → images/.gitkeep} +0 -0
  241. /package/dist/gulp/tasks/{_importer.js → BU/_importer.js} +0 -0
  242. /package/dist/gulp/tasks/{_vendor.js → BU/_vendor.js} +0 -0
@@ -0,0 +1,71 @@
1
+ /**
2
+ * --------------------------------------------------------------------------
3
+ * Bootstrap dom/manipulator.js
4
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
+ * --------------------------------------------------------------------------
6
+ */
7
+
8
+ function normalizeData(value) {
9
+ if (value === 'true') {
10
+ return true
11
+ }
12
+
13
+ if (value === 'false') {
14
+ return false
15
+ }
16
+
17
+ if (value === Number(value).toString()) {
18
+ return Number(value)
19
+ }
20
+
21
+ if (value === '' || value === 'null') {
22
+ return null
23
+ }
24
+
25
+ if (typeof value !== 'string') {
26
+ return value
27
+ }
28
+
29
+ try {
30
+ return JSON.parse(decodeURIComponent(value))
31
+ } catch {
32
+ return value
33
+ }
34
+ }
35
+
36
+ function normalizeDataKey(key) {
37
+ return key.replace(/[A-Z]/g, chr => `-${chr.toLowerCase()}`)
38
+ }
39
+
40
+ const Manipulator = {
41
+ setDataAttribute(element, key, value) {
42
+ element.setAttribute(`data-bs-${normalizeDataKey(key)}`, value)
43
+ },
44
+
45
+ removeDataAttribute(element, key) {
46
+ element.removeAttribute(`data-bs-${normalizeDataKey(key)}`)
47
+ },
48
+
49
+ getDataAttributes(element) {
50
+ if (!element) {
51
+ return {}
52
+ }
53
+
54
+ const attributes = {}
55
+ const bsKeys = Object.keys(element.dataset).filter(key => key.startsWith('bs') && !key.startsWith('bsConfig'))
56
+
57
+ for (const key of bsKeys) {
58
+ let pureKey = key.replace(/^bs/, '')
59
+ pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1)
60
+ attributes[pureKey] = normalizeData(element.dataset[key])
61
+ }
62
+
63
+ return attributes
64
+ },
65
+
66
+ getDataAttribute(element, key) {
67
+ return normalizeData(element.getAttribute(`data-bs-${normalizeDataKey(key)}`))
68
+ }
69
+ }
70
+
71
+ export default Manipulator
@@ -0,0 +1,126 @@
1
+ /**
2
+ * --------------------------------------------------------------------------
3
+ * Bootstrap dom/selector-engine.js
4
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
+ * --------------------------------------------------------------------------
6
+ */
7
+
8
+ import { isDisabled, isVisible, parseSelector } from '../util/index.js'
9
+
10
+ const getSelector = element => {
11
+ let selector = element.getAttribute('data-bs-target')
12
+
13
+ if (!selector || selector === '#') {
14
+ let hrefAttribute = element.getAttribute('href')
15
+
16
+ // The only valid content that could double as a selector are IDs or classes,
17
+ // so everything starting with `#` or `.`. If a "real" URL is used as the selector,
18
+ // `document.querySelector` will rightfully complain it is invalid.
19
+ // See https://github.com/twbs/bootstrap/issues/32273
20
+ if (!hrefAttribute || (!hrefAttribute.includes('#') && !hrefAttribute.startsWith('.'))) {
21
+ return null
22
+ }
23
+
24
+ // Just in case some CMS puts out a full URL with the anchor appended
25
+ if (hrefAttribute.includes('#') && !hrefAttribute.startsWith('#')) {
26
+ hrefAttribute = `#${hrefAttribute.split('#')[1]}`
27
+ }
28
+
29
+ selector = hrefAttribute && hrefAttribute !== '#' ? hrefAttribute.trim() : null
30
+ }
31
+
32
+ return selector ? selector.split(',').map(sel => parseSelector(sel)).join(',') : null
33
+ }
34
+
35
+ const SelectorEngine = {
36
+ find(selector, element = document.documentElement) {
37
+ return [].concat(...Element.prototype.querySelectorAll.call(element, selector))
38
+ },
39
+
40
+ findOne(selector, element = document.documentElement) {
41
+ return Element.prototype.querySelector.call(element, selector)
42
+ },
43
+
44
+ children(element, selector) {
45
+ return [].concat(...element.children).filter(child => child.matches(selector))
46
+ },
47
+
48
+ parents(element, selector) {
49
+ const parents = []
50
+ let ancestor = element.parentNode.closest(selector)
51
+
52
+ while (ancestor) {
53
+ parents.push(ancestor)
54
+ ancestor = ancestor.parentNode.closest(selector)
55
+ }
56
+
57
+ return parents
58
+ },
59
+
60
+ prev(element, selector) {
61
+ let previous = element.previousElementSibling
62
+
63
+ while (previous) {
64
+ if (previous.matches(selector)) {
65
+ return [previous]
66
+ }
67
+
68
+ previous = previous.previousElementSibling
69
+ }
70
+
71
+ return []
72
+ },
73
+ // TODO: this is now unused; remove later along with prev()
74
+ next(element, selector) {
75
+ let next = element.nextElementSibling
76
+
77
+ while (next) {
78
+ if (next.matches(selector)) {
79
+ return [next]
80
+ }
81
+
82
+ next = next.nextElementSibling
83
+ }
84
+
85
+ return []
86
+ },
87
+
88
+ focusableChildren(element) {
89
+ const focusables = [
90
+ 'a',
91
+ 'button',
92
+ 'input',
93
+ 'textarea',
94
+ 'select',
95
+ 'details',
96
+ '[tabindex]',
97
+ '[contenteditable="true"]'
98
+ ].map(selector => `${selector}:not([tabindex^="-"])`).join(',')
99
+
100
+ return this.find(focusables, element).filter(el => !isDisabled(el) && isVisible(el))
101
+ },
102
+
103
+ getSelectorFromElement(element) {
104
+ const selector = getSelector(element)
105
+
106
+ if (selector) {
107
+ return SelectorEngine.findOne(selector) ? selector : null
108
+ }
109
+
110
+ return null
111
+ },
112
+
113
+ getElementFromSelector(element) {
114
+ const selector = getSelector(element)
115
+
116
+ return selector ? SelectorEngine.findOne(selector) : null
117
+ },
118
+
119
+ getMultipleElementsFromSelector(element) {
120
+ const selector = getSelector(element)
121
+
122
+ return selector ? SelectorEngine.find(selector) : []
123
+ }
124
+ }
125
+
126
+ export default SelectorEngine
@@ -0,0 +1,458 @@
1
+ /**
2
+ * --------------------------------------------------------------------------
3
+ * Bootstrap dropdown.js
4
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
+ * --------------------------------------------------------------------------
6
+ */
7
+
8
+ import * as Popper from '@popperjs/core'
9
+ import BaseComponent from './base-component.js'
10
+ import EventHandler from './dom/event-handler.js'
11
+ import Manipulator from './dom/manipulator.js'
12
+ import SelectorEngine from './dom/selector-engine.js'
13
+ import {
14
+ defineJQueryPlugin,
15
+ execute,
16
+ getElement,
17
+ getNextActiveElement,
18
+ isDisabled,
19
+ isElement,
20
+ isRTL,
21
+ isVisible,
22
+ noop
23
+ } from './util/index.js'
24
+
25
+ /**
26
+ * Constants
27
+ */
28
+
29
+ const NAME = 'dropdown'
30
+ const DATA_KEY = 'bs.dropdown'
31
+ const EVENT_KEY = `.${DATA_KEY}`
32
+ const DATA_API_KEY = '.data-api'
33
+
34
+ const ESCAPE_KEY = 'Escape'
35
+ const TAB_KEY = 'Tab'
36
+ const ARROW_UP_KEY = 'ArrowUp'
37
+ const ARROW_DOWN_KEY = 'ArrowDown'
38
+ const RIGHT_MOUSE_BUTTON = 2 // MouseEvent.button value for the secondary button, usually the right button
39
+
40
+ const EVENT_HIDE = `hide${EVENT_KEY}`
41
+ const EVENT_HIDDEN = `hidden${EVENT_KEY}`
42
+ const EVENT_SHOW = `show${EVENT_KEY}`
43
+ const EVENT_SHOWN = `shown${EVENT_KEY}`
44
+ const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
45
+ const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY}${DATA_API_KEY}`
46
+ const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}`
47
+
48
+ const CLASS_NAME_SHOW = 'show'
49
+ const CLASS_NAME_DROPUP = 'dropup'
50
+ const CLASS_NAME_DROPEND = 'dropend'
51
+ const CLASS_NAME_DROPSTART = 'dropstart'
52
+ const CLASS_NAME_DROPUP_CENTER = 'dropup-center'
53
+ const CLASS_NAME_DROPDOWN_CENTER = 'dropdown-center'
54
+
55
+ const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="dropdown"]:not(.disabled):not(:disabled)'
56
+ const SELECTOR_DATA_TOGGLE_SHOWN = `${SELECTOR_DATA_TOGGLE}.${CLASS_NAME_SHOW}`
57
+ const SELECTOR_MENU = '.dropdown-menu'
58
+ const SELECTOR_NAVBAR = '.navbar'
59
+ const SELECTOR_NAVBAR_NAV = '.navbar-nav'
60
+ const SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)'
61
+
62
+ const PLACEMENT_TOP = isRTL() ? 'top-end' : 'top-start'
63
+ const PLACEMENT_TOPEND = isRTL() ? 'top-start' : 'top-end'
64
+ const PLACEMENT_BOTTOM = isRTL() ? 'bottom-end' : 'bottom-start'
65
+ const PLACEMENT_BOTTOMEND = isRTL() ? 'bottom-start' : 'bottom-end'
66
+ const PLACEMENT_RIGHT = isRTL() ? 'left-start' : 'right-start'
67
+ const PLACEMENT_LEFT = isRTL() ? 'right-start' : 'left-start'
68
+ const PLACEMENT_TOPCENTER = 'top'
69
+ const PLACEMENT_BOTTOMCENTER = 'bottom'
70
+
71
+ const Default = {
72
+ autoClose: true,
73
+ boundary: 'clippingParents',
74
+ display: 'dynamic',
75
+ offset: [0, 2],
76
+ popperConfig: null,
77
+ reference: 'toggle'
78
+ }
79
+
80
+ const DefaultType = {
81
+ autoClose: '(boolean|string)',
82
+ boundary: '(string|element)',
83
+ display: 'string',
84
+ offset: '(array|string|function)',
85
+ popperConfig: '(null|object|function)',
86
+ reference: '(string|element|object)'
87
+ }
88
+
89
+ /**
90
+ * Class definition
91
+ */
92
+
93
+ class Dropdown extends BaseComponent {
94
+ constructor(element, config) {
95
+ super(element, config)
96
+
97
+ this._popper = null
98
+ this._parent = this._element.parentNode // dropdown wrapper
99
+ // TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/
100
+ this._menu = SelectorEngine.next(this._element, SELECTOR_MENU)[0] ||
101
+ SelectorEngine.prev(this._element, SELECTOR_MENU)[0] ||
102
+ SelectorEngine.findOne(SELECTOR_MENU, this._parent)
103
+ this._inNavbar = this._detectNavbar()
104
+ }
105
+
106
+ // Getters
107
+ static get Default() {
108
+ return Default
109
+ }
110
+
111
+ static get DefaultType() {
112
+ return DefaultType
113
+ }
114
+
115
+ static get NAME() {
116
+ return NAME
117
+ }
118
+
119
+ // Public
120
+ toggle() {
121
+ return this._isShown() ? this.hide() : this.show()
122
+ }
123
+
124
+ show() {
125
+ if (isDisabled(this._element) || this._isShown()) {
126
+ return
127
+ }
128
+
129
+ const relatedTarget = {
130
+ relatedTarget: this._element
131
+ }
132
+
133
+ const showEvent = EventHandler.trigger(this._element, EVENT_SHOW, relatedTarget)
134
+
135
+ if (showEvent.defaultPrevented) {
136
+ return
137
+ }
138
+
139
+ this._createPopper()
140
+
141
+ // If this is a touch-enabled device we add extra
142
+ // empty mouseover listeners to the body's immediate children;
143
+ // only needed because of broken event delegation on iOS
144
+ // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
145
+ if ('ontouchstart' in document.documentElement && !this._parent.closest(SELECTOR_NAVBAR_NAV)) {
146
+ for (const element of [].concat(...document.body.children)) {
147
+ EventHandler.on(element, 'mouseover', noop)
148
+ }
149
+ }
150
+
151
+ this._element.focus()
152
+ this._element.setAttribute('aria-expanded', true)
153
+
154
+ this._menu.classList.add(CLASS_NAME_SHOW)
155
+ this._element.classList.add(CLASS_NAME_SHOW)
156
+ EventHandler.trigger(this._element, EVENT_SHOWN, relatedTarget)
157
+ }
158
+
159
+ hide() {
160
+ if (isDisabled(this._element) || !this._isShown()) {
161
+ return
162
+ }
163
+
164
+ const relatedTarget = {
165
+ relatedTarget: this._element
166
+ }
167
+
168
+ this._completeHide(relatedTarget)
169
+ }
170
+
171
+ dispose() {
172
+ if (this._popper) {
173
+ this._popper.destroy()
174
+ }
175
+
176
+ super.dispose()
177
+ }
178
+
179
+ update() {
180
+ this._inNavbar = this._detectNavbar()
181
+ if (this._popper) {
182
+ this._popper.update()
183
+ }
184
+ }
185
+
186
+ // Private
187
+ _completeHide(relatedTarget) {
188
+ const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE, relatedTarget)
189
+ if (hideEvent.defaultPrevented) {
190
+ return
191
+ }
192
+
193
+ // If this is a touch-enabled device we remove the extra
194
+ // empty mouseover listeners we added for iOS support
195
+ if ('ontouchstart' in document.documentElement) {
196
+ for (const element of [].concat(...document.body.children)) {
197
+ EventHandler.off(element, 'mouseover', noop)
198
+ }
199
+ }
200
+
201
+ if (this._popper) {
202
+ this._popper.destroy()
203
+ }
204
+
205
+ this._menu.classList.remove(CLASS_NAME_SHOW)
206
+ this._element.classList.remove(CLASS_NAME_SHOW)
207
+ this._element.setAttribute('aria-expanded', 'false')
208
+ Manipulator.removeDataAttribute(this._menu, 'popper')
209
+ EventHandler.trigger(this._element, EVENT_HIDDEN, relatedTarget)
210
+
211
+ // Explicitly return focus to the trigger element
212
+ this._element.focus()
213
+ }
214
+
215
+ _getConfig(config) {
216
+ config = super._getConfig(config)
217
+
218
+ if (typeof config.reference === 'object' && !isElement(config.reference) &&
219
+ typeof config.reference.getBoundingClientRect !== 'function'
220
+ ) {
221
+ // Popper virtual elements require a getBoundingClientRect method
222
+ throw new TypeError(`${NAME.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`)
223
+ }
224
+
225
+ return config
226
+ }
227
+
228
+ _createPopper() {
229
+ if (typeof Popper === 'undefined') {
230
+ throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org/docs/v2/)')
231
+ }
232
+
233
+ let referenceElement = this._element
234
+
235
+ if (this._config.reference === 'parent') {
236
+ referenceElement = this._parent
237
+ } else if (isElement(this._config.reference)) {
238
+ referenceElement = getElement(this._config.reference)
239
+ } else if (typeof this._config.reference === 'object') {
240
+ referenceElement = this._config.reference
241
+ }
242
+
243
+ const popperConfig = this._getPopperConfig()
244
+ this._popper = Popper.createPopper(referenceElement, this._menu, popperConfig)
245
+ }
246
+
247
+ _isShown() {
248
+ return this._menu.classList.contains(CLASS_NAME_SHOW)
249
+ }
250
+
251
+ _getPlacement() {
252
+ const parentDropdown = this._parent
253
+
254
+ if (parentDropdown.classList.contains(CLASS_NAME_DROPEND)) {
255
+ return PLACEMENT_RIGHT
256
+ }
257
+
258
+ if (parentDropdown.classList.contains(CLASS_NAME_DROPSTART)) {
259
+ return PLACEMENT_LEFT
260
+ }
261
+
262
+ if (parentDropdown.classList.contains(CLASS_NAME_DROPUP_CENTER)) {
263
+ return PLACEMENT_TOPCENTER
264
+ }
265
+
266
+ if (parentDropdown.classList.contains(CLASS_NAME_DROPDOWN_CENTER)) {
267
+ return PLACEMENT_BOTTOMCENTER
268
+ }
269
+
270
+ // We need to trim the value because custom properties can also include spaces
271
+ const isEnd = getComputedStyle(this._menu).getPropertyValue('--bs-position').trim() === 'end'
272
+
273
+ if (parentDropdown.classList.contains(CLASS_NAME_DROPUP)) {
274
+ return isEnd ? PLACEMENT_TOPEND : PLACEMENT_TOP
275
+ }
276
+
277
+ return isEnd ? PLACEMENT_BOTTOMEND : PLACEMENT_BOTTOM
278
+ }
279
+
280
+ _detectNavbar() {
281
+ return this._element.closest(SELECTOR_NAVBAR) !== null
282
+ }
283
+
284
+ _getOffset() {
285
+ const { offset } = this._config
286
+
287
+ if (typeof offset === 'string') {
288
+ return offset.split(',').map(value => Number.parseInt(value, 10))
289
+ }
290
+
291
+ if (typeof offset === 'function') {
292
+ return popperData => offset(popperData, this._element)
293
+ }
294
+
295
+ return offset
296
+ }
297
+
298
+ _getPopperConfig() {
299
+ const defaultBsPopperConfig = {
300
+ placement: this._getPlacement(),
301
+ modifiers: [{
302
+ name: 'preventOverflow',
303
+ options: {
304
+ boundary: this._config.boundary
305
+ }
306
+ },
307
+ {
308
+ name: 'offset',
309
+ options: {
310
+ offset: this._getOffset()
311
+ }
312
+ }]
313
+ }
314
+
315
+ // Disable Popper if we have a static display or Dropdown is in Navbar
316
+ if (this._inNavbar || this._config.display === 'static') {
317
+ Manipulator.setDataAttribute(this._menu, 'popper', 'static') // TODO: v6 remove
318
+ defaultBsPopperConfig.modifiers = [{
319
+ name: 'applyStyles',
320
+ enabled: false
321
+ }]
322
+ }
323
+
324
+ return {
325
+ ...defaultBsPopperConfig,
326
+ ...execute(this._config.popperConfig, [undefined, defaultBsPopperConfig])
327
+ }
328
+ }
329
+
330
+ _selectMenuItem({ key, target }) {
331
+ const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(element => isVisible(element))
332
+
333
+ if (!items.length) {
334
+ return
335
+ }
336
+
337
+ // if target isn't included in items (e.g. when expanding the dropdown)
338
+ // allow cycling to get the last item in case key equals ARROW_UP_KEY
339
+ getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus()
340
+ }
341
+
342
+ // Static
343
+ static jQueryInterface(config) {
344
+ return this.each(function () {
345
+ const data = Dropdown.getOrCreateInstance(this, config)
346
+
347
+ if (typeof config !== 'string') {
348
+ return
349
+ }
350
+
351
+ if (typeof data[config] === 'undefined') {
352
+ throw new TypeError(`No method named "${config}"`)
353
+ }
354
+
355
+ data[config]()
356
+ })
357
+ }
358
+
359
+ static clearMenus(event) {
360
+ if (event.button === RIGHT_MOUSE_BUTTON || (event.type === 'keyup' && event.key !== TAB_KEY)) {
361
+ return
362
+ }
363
+
364
+ const openToggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE_SHOWN)
365
+
366
+ for (const toggle of openToggles) {
367
+ const context = Dropdown.getInstance(toggle)
368
+ if (!context || context._config.autoClose === false) {
369
+ continue
370
+ }
371
+
372
+ const composedPath = event.composedPath()
373
+ const isMenuTarget = composedPath.includes(context._menu)
374
+ if (
375
+ composedPath.includes(context._element) ||
376
+ (context._config.autoClose === 'inside' && !isMenuTarget) ||
377
+ (context._config.autoClose === 'outside' && isMenuTarget)
378
+ ) {
379
+ continue
380
+ }
381
+
382
+ // Tab navigation through the dropdown menu or events from contained inputs shouldn't close the menu
383
+ if (context._menu.contains(event.target) && ((event.type === 'keyup' && event.key === TAB_KEY) || /input|select|option|textarea|form/i.test(event.target.tagName))) {
384
+ continue
385
+ }
386
+
387
+ const relatedTarget = { relatedTarget: context._element }
388
+
389
+ if (event.type === 'click') {
390
+ relatedTarget.clickEvent = event
391
+ }
392
+
393
+ context._completeHide(relatedTarget)
394
+ }
395
+ }
396
+
397
+ static dataApiKeydownHandler(event) {
398
+ // If not an UP | DOWN | ESCAPE key => not a dropdown command
399
+ // If input/textarea && if key is other than ESCAPE => not a dropdown command
400
+
401
+ const isInput = /input|textarea/i.test(event.target.tagName)
402
+ const isEscapeEvent = event.key === ESCAPE_KEY
403
+ const isUpOrDownEvent = [ARROW_UP_KEY, ARROW_DOWN_KEY].includes(event.key)
404
+
405
+ if (!isUpOrDownEvent && !isEscapeEvent) {
406
+ return
407
+ }
408
+
409
+ if (isInput && !isEscapeEvent) {
410
+ return
411
+ }
412
+
413
+ event.preventDefault()
414
+
415
+ // TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/
416
+ const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE) ?
417
+ this :
418
+ (SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE)[0] ||
419
+ SelectorEngine.next(this, SELECTOR_DATA_TOGGLE)[0] ||
420
+ SelectorEngine.findOne(SELECTOR_DATA_TOGGLE, event.delegateTarget.parentNode))
421
+
422
+ const instance = Dropdown.getOrCreateInstance(getToggleButton)
423
+
424
+ if (isUpOrDownEvent) {
425
+ event.stopPropagation()
426
+ instance.show()
427
+ instance._selectMenuItem(event)
428
+ return
429
+ }
430
+
431
+ if (instance._isShown()) { // else is escape and we check if it is shown
432
+ event.stopPropagation()
433
+ instance.hide()
434
+ getToggleButton.focus()
435
+ }
436
+ }
437
+ }
438
+
439
+ /**
440
+ * Data API implementation
441
+ */
442
+
443
+ EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE, Dropdown.dataApiKeydownHandler)
444
+ EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler)
445
+ EventHandler.on(document, EVENT_CLICK_DATA_API, Dropdown.clearMenus)
446
+ EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus)
447
+ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
448
+ event.preventDefault()
449
+ Dropdown.getOrCreateInstance(this).toggle()
450
+ })
451
+
452
+ /**
453
+ * jQuery
454
+ */
455
+
456
+ defineJQueryPlugin(Dropdown)
457
+
458
+ export default Dropdown