@rhavenside/baseline 2.0.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 (80) hide show
  1. package/README.md +472 -0
  2. package/dist/base-line.css +5 -0
  3. package/dist/base-line.css.map +1 -0
  4. package/dist/fonts/GoogleSansCode-Bold.ttf +0 -0
  5. package/dist/fonts/GoogleSansCode-BoldItalic.ttf +0 -0
  6. package/dist/fonts/GoogleSansCode-ExtraBold.ttf +0 -0
  7. package/dist/fonts/GoogleSansCode-ExtraBoldItalic.ttf +0 -0
  8. package/dist/fonts/GoogleSansCode-Italic-VariableFont_wght.ttf +0 -0
  9. package/dist/fonts/GoogleSansCode-Italic.ttf +0 -0
  10. package/dist/fonts/GoogleSansCode-Light.ttf +0 -0
  11. package/dist/fonts/GoogleSansCode-LightItalic.ttf +0 -0
  12. package/dist/fonts/GoogleSansCode-Medium.ttf +0 -0
  13. package/dist/fonts/GoogleSansCode-MediumItalic.ttf +0 -0
  14. package/dist/fonts/GoogleSansCode-Regular.ttf +0 -0
  15. package/dist/fonts/GoogleSansCode-SemiBold.ttf +0 -0
  16. package/dist/fonts/GoogleSansCode-SemiBoldItalic.ttf +0 -0
  17. package/dist/fonts/GoogleSansCode-VariableFont_wght.ttf +0 -0
  18. package/dist/fonts/RobotoCondensed-Black.ttf +0 -0
  19. package/dist/fonts/RobotoCondensed-BlackItalic.ttf +0 -0
  20. package/dist/fonts/RobotoCondensed-Bold.ttf +0 -0
  21. package/dist/fonts/RobotoCondensed-BoldItalic.ttf +0 -0
  22. package/dist/fonts/RobotoCondensed-ExtraBold.ttf +0 -0
  23. package/dist/fonts/RobotoCondensed-ExtraBoldItalic.ttf +0 -0
  24. package/dist/fonts/RobotoCondensed-ExtraLight.ttf +0 -0
  25. package/dist/fonts/RobotoCondensed-ExtraLightItalic.ttf +0 -0
  26. package/dist/fonts/RobotoCondensed-Italic-VariableFont_wght.ttf +0 -0
  27. package/dist/fonts/RobotoCondensed-Italic.ttf +0 -0
  28. package/dist/fonts/RobotoCondensed-Light.ttf +0 -0
  29. package/dist/fonts/RobotoCondensed-LightItalic.ttf +0 -0
  30. package/dist/fonts/RobotoCondensed-Medium.ttf +0 -0
  31. package/dist/fonts/RobotoCondensed-MediumItalic.ttf +0 -0
  32. package/dist/fonts/RobotoCondensed-Regular.ttf +0 -0
  33. package/dist/fonts/RobotoCondensed-SemiBold.ttf +0 -0
  34. package/dist/fonts/RobotoCondensed-SemiBoldItalic.ttf +0 -0
  35. package/dist/fonts/RobotoCondensed-Thin.ttf +0 -0
  36. package/dist/fonts/RobotoCondensed-ThinItalic.ttf +0 -0
  37. package/dist/fonts/RobotoCondensed-VariableFont_wght.ttf +0 -0
  38. package/dist/fonts/ZalandoSansExpanded-Black.ttf +0 -0
  39. package/dist/fonts/ZalandoSansExpanded-BlackItalic.ttf +0 -0
  40. package/dist/fonts/ZalandoSansExpanded-Bold.ttf +0 -0
  41. package/dist/fonts/ZalandoSansExpanded-BoldItalic.ttf +0 -0
  42. package/dist/fonts/ZalandoSansExpanded-ExtraBold.ttf +0 -0
  43. package/dist/fonts/ZalandoSansExpanded-ExtraBoldItalic.ttf +0 -0
  44. package/dist/fonts/ZalandoSansExpanded-ExtraLight.ttf +0 -0
  45. package/dist/fonts/ZalandoSansExpanded-ExtraLightItalic.ttf +0 -0
  46. package/dist/fonts/ZalandoSansExpanded-Italic-VariableFont_wght.ttf +0 -0
  47. package/dist/fonts/ZalandoSansExpanded-Italic.ttf +0 -0
  48. package/dist/fonts/ZalandoSansExpanded-Light.ttf +0 -0
  49. package/dist/fonts/ZalandoSansExpanded-LightItalic.ttf +0 -0
  50. package/dist/fonts/ZalandoSansExpanded-Medium.ttf +0 -0
  51. package/dist/fonts/ZalandoSansExpanded-MediumItalic.ttf +0 -0
  52. package/dist/fonts/ZalandoSansExpanded-Regular.ttf +0 -0
  53. package/dist/fonts/ZalandoSansExpanded-SemiBold.ttf +0 -0
  54. package/dist/fonts/ZalandoSansExpanded-SemiBoldItalic.ttf +0 -0
  55. package/dist/fonts/ZalandoSansExpanded-VariableFont_wght.ttf +0 -0
  56. package/dist/fonts/baseline-icons.woff +0 -0
  57. package/dist/fonts/baseline-icons.woff2 +0 -0
  58. package/dist/js/accordion.js +103 -0
  59. package/dist/js/alert.js +91 -0
  60. package/dist/js/base.js +146 -0
  61. package/dist/js/button.js +80 -0
  62. package/dist/js/carousel.js +427 -0
  63. package/dist/js/collapse.js +233 -0
  64. package/dist/js/color-modes.js +70 -0
  65. package/dist/js/component.js +114 -0
  66. package/dist/js/dropdown.js +348 -0
  67. package/dist/js/index.js +108 -0
  68. package/dist/js/modal.js +440 -0
  69. package/dist/js/offcanvas.js +356 -0
  70. package/dist/js/popover.js +241 -0
  71. package/dist/js/swipe.js +143 -0
  72. package/dist/js/tab.js +285 -0
  73. package/dist/js/toast.js +228 -0
  74. package/dist/js/tooltip.js +716 -0
  75. package/dist/js/util/backdrop.js +133 -0
  76. package/dist/js/util/component-functions.js +111 -0
  77. package/dist/js/util/focustrap.js +101 -0
  78. package/dist/js/util/scrollbar.js +111 -0
  79. package/dist/js/util.js +564 -0
  80. package/package.json +47 -0
@@ -0,0 +1,70 @@
1
+ /*!
2
+ * Color mode toggler for Base-Line
3
+ * Based on Baseline's color-modes.js
4
+ */
5
+
6
+ (() => {
7
+ 'use strict'
8
+
9
+ const getStoredTheme = () => localStorage.getItem('theme')
10
+ const setStoredTheme = theme => localStorage.setItem('theme', theme)
11
+
12
+ const getPreferredTheme = () => {
13
+ const storedTheme = getStoredTheme()
14
+ if (storedTheme) {
15
+ return storedTheme
16
+ }
17
+
18
+ return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
19
+ }
20
+
21
+ const setTheme = theme => {
22
+ if (theme === 'auto') {
23
+ document.documentElement.setAttribute('data-bl-theme', (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'))
24
+ } else {
25
+ document.documentElement.setAttribute('data-bl-theme', theme)
26
+ }
27
+
28
+ // Also set class for backward compatibility
29
+ if (theme === 'auto') {
30
+ const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
31
+ if (systemTheme === 'dark') {
32
+ document.documentElement.classList.add('theme-dark')
33
+ document.documentElement.classList.remove('theme-light')
34
+ } else {
35
+ document.documentElement.classList.remove('theme-dark')
36
+ document.documentElement.classList.add('theme-light')
37
+ }
38
+ } else {
39
+ if (theme === 'dark') {
40
+ document.documentElement.classList.add('theme-dark')
41
+ document.documentElement.classList.remove('theme-light')
42
+ } else {
43
+ document.documentElement.classList.remove('theme-dark')
44
+ document.documentElement.classList.add('theme-light')
45
+ }
46
+ }
47
+ }
48
+
49
+ // Set theme immediately, before React renders
50
+ setTheme(getPreferredTheme())
51
+
52
+ // Listen for system theme changes
53
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
54
+ const storedTheme = getStoredTheme()
55
+ if (!storedTheme || storedTheme === 'auto') {
56
+ setTheme(getPreferredTheme())
57
+ }
58
+ })
59
+
60
+ // Expose functions globally for React to use
61
+ window.__setTheme = (theme) => {
62
+ setStoredTheme(theme)
63
+ setTheme(theme)
64
+ }
65
+
66
+ window.__getTheme = () => {
67
+ return getPreferredTheme()
68
+ }
69
+ })()
70
+
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Base-Line Component Factory
3
+ * Helper to create components with consistent interface
4
+ */
5
+
6
+ import { BaseComponent } from './base.js'
7
+ import { getElement, getElements, executeAfterTransition, reflow } from './util.js'
8
+
9
+ /**
10
+ * Component Factory
11
+ */
12
+ export function createComponent(name, ComponentClass) {
13
+ // Register with Data API
14
+ if (typeof window !== 'undefined' && window.BaseLine && window.BaseLine.dataAPI) {
15
+ window.BaseLine.dataAPI.register(name, ComponentClass)
16
+ }
17
+
18
+ // Auto-initialize on DOM ready
19
+ if (typeof document !== 'undefined') {
20
+ const initComponents = () => {
21
+ const selector = `[data-c-${name}]`
22
+ const elements = document.querySelectorAll(selector)
23
+
24
+ elements.forEach(element => {
25
+ if (!element._baseLineComponent) {
26
+ const instance = new ComponentClass(element)
27
+ element._baseLineComponent = instance
28
+ }
29
+ })
30
+ }
31
+
32
+ if (document.readyState === 'loading') {
33
+ document.addEventListener('DOMContentLoaded', initComponents)
34
+ } else {
35
+ initComponents()
36
+ }
37
+ }
38
+
39
+ return ComponentClass
40
+ }
41
+
42
+ /**
43
+ * Event handler helpers
44
+ */
45
+ export function on(element, event, handler) {
46
+ element.addEventListener(event, handler)
47
+ }
48
+
49
+ export function off(element, event, handler) {
50
+ element.removeEventListener(event, handler)
51
+ }
52
+
53
+ export function one(element, event, handler) {
54
+ const onceHandler = (e) => {
55
+ handler(e)
56
+ off(element, event, onceHandler)
57
+ }
58
+ on(element, event, onceHandler)
59
+ }
60
+
61
+ /**
62
+ * Class manipulation helpers
63
+ */
64
+ export function addClass(element, className) {
65
+ if (element && className) {
66
+ element.classList.add(className)
67
+ }
68
+ }
69
+
70
+ export function removeClass(element, className) {
71
+ if (element && className) {
72
+ element.classList.remove(className)
73
+ }
74
+ }
75
+
76
+ export function toggleClass(element, className) {
77
+ if (element && className) {
78
+ element.classList.toggle(className)
79
+ }
80
+ }
81
+
82
+ export function hasClass(element, className) {
83
+ return element && element.classList.contains(className)
84
+ }
85
+
86
+ /**
87
+ * Show/hide helpers
88
+ */
89
+ export function show(element) {
90
+ if (element) {
91
+ element.style.display = ''
92
+ element.removeAttribute('hidden')
93
+ }
94
+ }
95
+
96
+ export function hide(element) {
97
+ if (element) {
98
+ element.style.display = 'none'
99
+ element.setAttribute('hidden', '')
100
+ }
101
+ }
102
+
103
+ export function toggle(element) {
104
+ if (element) {
105
+ if (element.style.display === 'none' || element.hasAttribute('hidden')) {
106
+ show(element)
107
+ } else {
108
+ hide(element)
109
+ }
110
+ }
111
+ }
112
+
113
+
114
+
@@ -0,0 +1,348 @@
1
+ /**
2
+ * Base-Line Dropdown Component
3
+ * Baseline 2.0 compatible dropdown with Base-Line naming
4
+ */
5
+
6
+ import { BaseComponent } from './base.js'
7
+ import { getElement, getElements, on, off, isElement, isDisabled, isRTL, SelectorEngine } from './util.js'
8
+ import { addClass, removeClass, hasClass } from './component.js'
9
+
10
+ // Import Popper.js
11
+ import * as Popper from '@popperjs/core'
12
+
13
+ const NAME = 'dropdown'
14
+ const DATA_KEY = `c.${NAME}`
15
+ const EVENT_KEY = `.${DATA_KEY}`
16
+ const DATA_API_KEY = `[data-c-${NAME}]`
17
+
18
+ const EVENT_HIDE = `hide${EVENT_KEY}`
19
+ const EVENT_HIDDEN = `hidden${EVENT_KEY}`
20
+ const EVENT_SHOW = `show${EVENT_KEY}`
21
+ const EVENT_SHOWN = `shown${EVENT_KEY}`
22
+ const EVENT_CLICK = `click${EVENT_KEY}`
23
+ const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
24
+
25
+ const CLASS_NAME_SHOW = 'is-show'
26
+ const CLASS_NAME_DROPUP = 'c-dropup'
27
+ const CLASS_NAME_DROPEND = 'c-dropend'
28
+ const CLASS_NAME_DROPSTART = 'c-dropstart'
29
+ const SELECTOR_DATA_TOGGLE = '[data-c-toggle="dropdown"]'
30
+ const SELECTOR_MENU = '.c-dropdown-menu'
31
+ const SELECTOR_DROPDOWN_ITEM = '.c-dropdown-item'
32
+ const SELECTOR_NAVBAR_NAV = '.c-navbar-nav'
33
+ const SELECTOR_NAVBAR = '.c-navbar'
34
+
35
+ // Placement constants (for Popper.js) with RTL support
36
+ const PLACEMENT_TOP = isRTL() ? 'top-end' : 'top-start'
37
+ const PLACEMENT_TOPEND = isRTL() ? 'top-start' : 'top-end'
38
+ const PLACEMENT_BOTTOM = isRTL() ? 'bottom-end' : 'bottom-start'
39
+ const PLACEMENT_BOTTOMEND = isRTL() ? 'bottom-start' : 'bottom-end'
40
+ const PLACEMENT_RIGHT = isRTL() ? 'left-start' : 'right-start'
41
+ const PLACEMENT_LEFT = isRTL() ? 'right-start' : 'left-start'
42
+
43
+ class Dropdown extends BaseComponent {
44
+ constructor(element, config) {
45
+ super(element, config)
46
+ this._popper = null
47
+ this._parent = this._element.parentNode // dropdown wrapper
48
+ // Find menu using multiple strategies (like Baseline)
49
+ this._menu = SelectorEngine.next(this._element, SELECTOR_MENU)[0] ||
50
+ SelectorEngine.prev(this._element, SELECTOR_MENU)[0] ||
51
+ SelectorEngine.findOne(SELECTOR_MENU, this._parent)
52
+ this._isShown = false
53
+ this._inNavbar = this._detectNavbar()
54
+ this._init()
55
+ }
56
+
57
+ static get NAME() {
58
+ return NAME
59
+ }
60
+
61
+ static get Default() {
62
+ return {
63
+ offset: [0, 2],
64
+ boundary: 'clippingParents',
65
+ reference: 'toggle',
66
+ display: 'dynamic',
67
+ popperConfig: null,
68
+ autoClose: true
69
+ }
70
+ }
71
+
72
+ _init() {
73
+ this._bindEvents()
74
+ }
75
+
76
+ _bindEvents() {
77
+ const toggle = getElement(SELECTOR_DATA_TOGGLE, this._element) || this._element
78
+
79
+ on(toggle, 'click', (e) => {
80
+ e.preventDefault()
81
+ e.stopPropagation()
82
+ this.toggle()
83
+ })
84
+
85
+ // Close on dropdown item click
86
+ if (this._menu) {
87
+ on(this._menu, 'click', SELECTOR_DROPDOWN_ITEM, (e) => {
88
+ // Only close if autoClose is enabled (default: true)
89
+ if (this._config.autoClose !== false) {
90
+ // Check if the item is disabled
91
+ const item = e.target.closest(SELECTOR_DROPDOWN_ITEM)
92
+ if (item && !item.classList.contains('is-disabled') && !item.hasAttribute('disabled')) {
93
+ this.hide()
94
+ }
95
+ }
96
+ })
97
+ }
98
+
99
+ // Close on outside click
100
+ on(document, 'click', (e) => {
101
+ if (this._isShown && !this._parent.contains(e.target)) {
102
+ this.hide()
103
+ }
104
+ })
105
+
106
+ // Close on escape
107
+ on(document, 'keydown', (e) => {
108
+ if (e.key === 'Escape' && this._isShown) {
109
+ this.hide()
110
+ }
111
+ })
112
+ }
113
+
114
+ _detectNavbar() {
115
+ return this._element.closest(SELECTOR_NAVBAR) !== null
116
+ }
117
+
118
+ _getPlacement() {
119
+ const parentDropdown = this._parent
120
+
121
+ if (parentDropdown.classList.contains(CLASS_NAME_DROPEND)) {
122
+ return PLACEMENT_RIGHT
123
+ }
124
+
125
+ if (parentDropdown.classList.contains(CLASS_NAME_DROPSTART)) {
126
+ return PLACEMENT_LEFT
127
+ }
128
+
129
+ // We need to trim the value because custom properties can also include spaces
130
+ const isEnd = this._menu && window.getComputedStyle(this._menu).getPropertyValue('--bl-position').trim() === 'end'
131
+
132
+ if (parentDropdown.classList.contains(CLASS_NAME_DROPUP)) {
133
+ return isEnd ? PLACEMENT_TOPEND : PLACEMENT_TOP
134
+ }
135
+
136
+ return isEnd ? PLACEMENT_BOTTOMEND : PLACEMENT_BOTTOM
137
+ }
138
+
139
+ _getOffset() {
140
+ const { offset } = this._config
141
+
142
+ if (typeof offset === 'string') {
143
+ return offset.split(',').map(value => Number.parseInt(value, 10))
144
+ }
145
+
146
+ if (typeof offset === 'function') {
147
+ return popperData => offset(popperData, this._element)
148
+ }
149
+
150
+ return offset
151
+ }
152
+
153
+ _getPopperConfig() {
154
+ if (typeof Popper === 'undefined') {
155
+ throw new TypeError('Base-Line\'s dropdowns require Popper (https://popper.js.org/docs/v2/)')
156
+ }
157
+
158
+ const defaultBsPopperConfig = {
159
+ placement: this._getPlacement(),
160
+ modifiers: [{
161
+ name: 'preventOverflow',
162
+ options: {
163
+ boundary: this._config.boundary
164
+ }
165
+ },
166
+ {
167
+ name: 'offset',
168
+ options: {
169
+ offset: this._getOffset()
170
+ }
171
+ }]
172
+ }
173
+
174
+ // Disable Popper if we have a static display or Dropdown is in Navbar
175
+ if (this._inNavbar || this._config.display === 'static') {
176
+ if (this._menu) {
177
+ this._menu.setAttribute('data-bl-popper', 'static')
178
+ }
179
+ defaultBsPopperConfig.modifiers = [{
180
+ name: 'applyStyles',
181
+ enabled: false
182
+ }]
183
+ }
184
+
185
+ return {
186
+ ...defaultBsPopperConfig,
187
+ ...(typeof this._config.popperConfig === 'function'
188
+ ? this._config.popperConfig(undefined, defaultBsPopperConfig)
189
+ : this._config.popperConfig || {})
190
+ }
191
+ }
192
+
193
+ _createPopper() {
194
+ if (typeof Popper === 'undefined') {
195
+ throw new TypeError('Base-Line\'s dropdowns require Popper (https://popper.js.org/docs/v2/)')
196
+ }
197
+
198
+ if (!this._menu) {
199
+ return
200
+ }
201
+
202
+ let referenceElement = this._element
203
+
204
+ if (this._config.reference === 'parent') {
205
+ referenceElement = this._parent
206
+ } else if (isElement(this._config.reference)) {
207
+ referenceElement = getElement(this._config.reference)
208
+ } else if (typeof this._config.reference === 'object') {
209
+ referenceElement = this._config.reference
210
+ }
211
+
212
+ const popperConfig = this._getPopperConfig()
213
+ this._popper = Popper.createPopper(referenceElement, this._menu, popperConfig)
214
+
215
+ // Set data-bl-popper attribute to enable CSS positioning (always set, even with Popper)
216
+ // This is needed for CSS positioning rules to work
217
+ this._menu.setAttribute('data-bl-popper', '')
218
+ }
219
+
220
+ show() {
221
+ if (this._isShown || isDisabled(this._element)) {
222
+ return
223
+ }
224
+
225
+ const showEvent = new CustomEvent(EVENT_SHOW, {
226
+ bubbles: true,
227
+ cancelable: true
228
+ })
229
+
230
+ this._parent.dispatchEvent(showEvent)
231
+
232
+ if (showEvent.defaultPrevented) {
233
+ return
234
+ }
235
+
236
+ // Close all other open dropdowns before showing this one
237
+ // Find all dropdown menus that are currently shown
238
+ const openMenus = document.querySelectorAll(`${SELECTOR_MENU}.${CLASS_NAME_SHOW}`)
239
+ openMenus.forEach(menu => {
240
+ if (menu !== this._menu) {
241
+ // Find the parent dropdown container
242
+ const parent = menu.closest('.c-dropdown')
243
+ if (parent && parent !== this._parent) {
244
+ // Find the toggle element for this dropdown
245
+ const toggle = SelectorEngine.findOne(SELECTOR_DATA_TOGGLE, parent) ||
246
+ parent.querySelector(SELECTOR_DATA_TOGGLE)
247
+ if (toggle) {
248
+ // Get or create the dropdown instance
249
+ const otherDropdown = Dropdown.getOrCreateInstance(toggle)
250
+ if (otherDropdown && otherDropdown._isShown) {
251
+ otherDropdown.hide()
252
+ }
253
+ }
254
+ }
255
+ }
256
+ })
257
+
258
+ this._createPopper()
259
+
260
+ this._isShown = true
261
+
262
+ if (this._menu) {
263
+ addClass(this._menu, CLASS_NAME_SHOW)
264
+ addClass(this._parent, CLASS_NAME_SHOW)
265
+ }
266
+
267
+ this._element.setAttribute('aria-expanded', 'true')
268
+
269
+ const shownEvent = new CustomEvent(EVENT_SHOWN, { bubbles: true })
270
+ this._parent.dispatchEvent(shownEvent)
271
+ }
272
+
273
+ hide() {
274
+ if (!this._isShown) {
275
+ return
276
+ }
277
+
278
+ const hideEvent = new CustomEvent(EVENT_HIDE, {
279
+ bubbles: true,
280
+ cancelable: true
281
+ })
282
+
283
+ this._parent.dispatchEvent(hideEvent)
284
+
285
+ if (hideEvent.defaultPrevented) {
286
+ return
287
+ }
288
+
289
+ this._isShown = false
290
+
291
+ if (this._popper) {
292
+ this._popper.destroy()
293
+ this._popper = null
294
+ }
295
+
296
+ if (this._menu) {
297
+ removeClass(this._menu, CLASS_NAME_SHOW)
298
+ removeClass(this._parent, CLASS_NAME_SHOW)
299
+ this._menu.removeAttribute('data-bl-popper')
300
+ }
301
+
302
+ this._element.setAttribute('aria-expanded', 'false')
303
+
304
+ const hiddenEvent = new CustomEvent(EVENT_HIDDEN, { bubbles: true })
305
+ this._parent.dispatchEvent(hiddenEvent)
306
+ }
307
+
308
+ toggle() {
309
+ if (this._isShown) {
310
+ this.hide()
311
+ } else {
312
+ this.show()
313
+ }
314
+ }
315
+
316
+ dispose() {
317
+ if (this._popper) {
318
+ this._popper.destroy()
319
+ this._popper = null
320
+ }
321
+ super.dispose()
322
+ }
323
+
324
+ update() {
325
+ this._inNavbar = this._detectNavbar()
326
+ if (this._popper) {
327
+ this._popper.update()
328
+ }
329
+ }
330
+
331
+ static getOrCreateInstance(element, config = {}) {
332
+ return element._baseLineComponent || new Dropdown(element, config)
333
+ }
334
+ }
335
+
336
+ // Data API
337
+ on(document, 'click', SELECTOR_DATA_TOGGLE, function (event) {
338
+ event.preventDefault()
339
+ event.stopPropagation()
340
+
341
+ // Use the toggle element directly (like Baseline)
342
+ const dropdown = Dropdown.getOrCreateInstance(this)
343
+ dropdown.toggle()
344
+ })
345
+
346
+ export default Dropdown
347
+
348
+
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Base-Line JavaScript Components
3
+ * Main entry point for all components
4
+ */
5
+
6
+ import { dataAPI, BaseComponent } from './base.js'
7
+ import { onDOMContentLoaded } from './util.js'
8
+
9
+ // Import all components
10
+ import Alert from './alert.js'
11
+ import Button from './button.js'
12
+ import Carousel from './carousel.js'
13
+ import Collapse from './collapse.js'
14
+ import Dropdown from './dropdown.js'
15
+ import Modal from './modal.js'
16
+ import Offcanvas from './offcanvas.js'
17
+ import Popover from './popover.js'
18
+ import Tab from './tab.js'
19
+ import Toast from './toast.js'
20
+ import Tooltip from './tooltip.js'
21
+ import Accordion from './accordion.js'
22
+
23
+ // Register all components with Data API
24
+ const components = {
25
+ Alert,
26
+ Button,
27
+ Carousel,
28
+ Collapse,
29
+ Dropdown,
30
+ Modal,
31
+ Offcanvas,
32
+ Popover,
33
+ Tab,
34
+ Toast,
35
+ Tooltip,
36
+ Accordion
37
+ }
38
+
39
+ // Register components
40
+ Object.keys(components).forEach(name => {
41
+ const ComponentClass = components[name]
42
+ if (ComponentClass && ComponentClass.NAME) {
43
+ dataAPI.register(ComponentClass.NAME, ComponentClass)
44
+ }
45
+ })
46
+
47
+ // Initialize on DOM ready
48
+ onDOMContentLoaded(() => {
49
+ dataAPI.init()
50
+
51
+ // Trigger load event for components that need it (e.g., Tab)
52
+ const loadEvent = new Event('load.c.tab')
53
+ window.dispatchEvent(loadEvent)
54
+ })
55
+
56
+ // Export for global access
57
+ if (typeof window !== 'undefined') {
58
+ window.BaseLine = window.BaseLine || {}
59
+ window.BaseLine.components = components
60
+ window.BaseLine.dataAPI = dataAPI
61
+ window.BaseLine.BaseComponent = BaseComponent
62
+ // Export individual components for direct access
63
+ window.BaseLine.Alert = Alert
64
+ window.BaseLine.Button = Button
65
+ window.BaseLine.Carousel = Carousel
66
+ window.BaseLine.Collapse = Collapse
67
+ window.BaseLine.Dropdown = Dropdown
68
+ window.BaseLine.Modal = Modal
69
+ window.BaseLine.Offcanvas = Offcanvas
70
+ window.BaseLine.Popover = Popover
71
+ window.BaseLine.Tab = Tab
72
+ window.BaseLine.Toast = Toast
73
+ window.BaseLine.Tooltip = Tooltip
74
+ window.BaseLine.Accordion = Accordion
75
+ }
76
+
77
+ // Export individual components
78
+ export {
79
+ Alert,
80
+ Button,
81
+ Carousel,
82
+ Collapse,
83
+ Dropdown,
84
+ Modal,
85
+ Offcanvas,
86
+ Popover,
87
+ Tab,
88
+ Toast,
89
+ Tooltip,
90
+ Accordion,
91
+ dataAPI,
92
+ BaseComponent
93
+ }
94
+
95
+ export default {
96
+ Alert,
97
+ Button,
98
+ Carousel,
99
+ Collapse,
100
+ Dropdown,
101
+ Modal,
102
+ Offcanvas,
103
+ Popover,
104
+ Tab,
105
+ Toast,
106
+ Tooltip,
107
+ Accordion
108
+ }