bitwrench 2.0.14 → 2.0.16
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.
- package/README.md +57 -21
- package/dist/bitwrench-bccl.cjs.js +3746 -0
- package/dist/bitwrench-bccl.cjs.min.js +40 -0
- package/dist/bitwrench-bccl.esm.js +3741 -0
- package/dist/bitwrench-bccl.esm.min.js +40 -0
- package/dist/bitwrench-bccl.umd.js +3752 -0
- package/dist/bitwrench-bccl.umd.min.js +40 -0
- package/dist/bitwrench-code-edit.cjs.js +99 -49
- package/dist/bitwrench-code-edit.cjs.min.js +23 -0
- package/dist/bitwrench-code-edit.es5.js +79 -16
- package/dist/bitwrench-code-edit.es5.min.js +9 -2
- package/dist/bitwrench-code-edit.esm.js +99 -49
- package/dist/bitwrench-code-edit.esm.min.js +9 -2
- package/dist/bitwrench-code-edit.umd.js +99 -49
- package/dist/bitwrench-code-edit.umd.min.js +9 -2
- package/dist/bitwrench-lean.cjs.js +4923 -3248
- package/dist/bitwrench-lean.cjs.min.js +35 -6
- package/dist/bitwrench-lean.es5.js +6325 -4580
- package/dist/bitwrench-lean.es5.min.js +32 -3
- package/dist/bitwrench-lean.esm.js +4923 -3248
- package/dist/bitwrench-lean.esm.min.js +35 -6
- package/dist/bitwrench-lean.umd.js +4923 -3248
- package/dist/bitwrench-lean.umd.min.js +35 -6
- package/dist/bitwrench.cjs.js +5082 -3667
- package/dist/bitwrench.cjs.min.js +38 -8
- package/dist/bitwrench.css +2289 -6034
- package/dist/bitwrench.es5.js +6862 -5346
- package/dist/bitwrench.es5.min.js +34 -5
- package/dist/bitwrench.esm.js +5082 -3667
- package/dist/bitwrench.esm.min.js +38 -8
- package/dist/bitwrench.min.css +1 -0
- package/dist/bitwrench.umd.js +5082 -3667
- package/dist/bitwrench.umd.min.js +38 -8
- package/dist/builds.json +184 -74
- package/dist/bwserve.cjs.js +646 -0
- package/dist/bwserve.esm.js +638 -0
- package/dist/sri.json +36 -26
- package/package.json +23 -6
- package/readme.html +71 -32
- package/src/bitwrench-bccl-entry.js +72 -0
- package/src/{bitwrench-components-v2.js → bitwrench-bccl.js} +396 -647
- package/src/bitwrench-code-edit.js +98 -48
- package/src/bitwrench-color-utils.js +24 -18
- package/src/bitwrench-components-stub.js +4 -1
- package/src/bitwrench-file-ops.js +180 -0
- package/src/bitwrench-lean.js +2 -2
- package/src/bitwrench-styles.js +1287 -4029
- package/src/bitwrench-utils.js +458 -0
- package/src/bitwrench.js +2070 -1292
- package/src/bwserve/client.js +182 -0
- package/src/bwserve/index.js +352 -0
- package/src/bwserve/shell.js +103 -0
- package/src/cli/index.js +36 -15
- package/src/cli/layout-default.js +18 -18
- package/src/cli/serve.js +325 -0
- package/src/generate-css.js +73 -53
- package/src/version.js +3 -3
- package/src/bitwrench-component-base.js +0 -736
- package/src/bitwrench-components-inline.js +0 -374
- package/src/bitwrench-components.js +0 -610
- /package/bin/{bitwrench.js → bwcli.js} +0 -0
|
@@ -12,11 +12,43 @@
|
|
|
12
12
|
* Handle classes (CardHandle, TableHandle, NavbarHandle, TabsHandle)
|
|
13
13
|
* provide imperative DOM manipulation for rendered components.
|
|
14
14
|
*
|
|
15
|
-
* @module bitwrench-
|
|
15
|
+
* @module bitwrench-bccl
|
|
16
16
|
* @license BSD-2-Clause
|
|
17
17
|
* @author M A Chatterjee <deftio [at] deftio [dot] com>
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
+
// =========================================================================
|
|
21
|
+
// Variant → Utility Class Mapping
|
|
22
|
+
//
|
|
23
|
+
// Components compose these shared utility classes instead of owning
|
|
24
|
+
// their own variant selectors. The CSS is generated once by
|
|
25
|
+
// generatePaletteUtilities() + generateInteractionRules().
|
|
26
|
+
// =========================================================================
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Maps component type to a function that returns utility classes for a variant.
|
|
30
|
+
* Each function takes a variant name (e.g. 'primary') and returns a class string.
|
|
31
|
+
* @type {Object.<string, function(string): string>}
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* Convert a variant name to a single palette class.
|
|
35
|
+
* All BCCL components use this: variant='primary' → class includes 'bw_primary'.
|
|
36
|
+
* The CSS palette class (.bw-primary) sets bg/color/border; component-specific
|
|
37
|
+
* overrides in generatePaletteClasses() adjust per component type.
|
|
38
|
+
*
|
|
39
|
+
* @param {string} v - Variant name (e.g. 'primary', 'danger', 'outline_primary')
|
|
40
|
+
* @returns {string} CSS class string
|
|
41
|
+
*/
|
|
42
|
+
export function variantClass(v) {
|
|
43
|
+
if (!v) return '';
|
|
44
|
+
// Handle outline variants: 'outline_primary' or 'outline-primary'
|
|
45
|
+
if (v.indexOf('outline') === 0) {
|
|
46
|
+
var base = v.replace(/^outline[_-]/, '');
|
|
47
|
+
return 'bw_btn_outline bw_' + base;
|
|
48
|
+
}
|
|
49
|
+
return 'bw_' + v;
|
|
50
|
+
}
|
|
51
|
+
|
|
20
52
|
/**
|
|
21
53
|
* Create a card component with optional header, body, footer, and image support
|
|
22
54
|
*
|
|
@@ -76,54 +108,54 @@ export function makeCard(props = {}) {
|
|
|
76
108
|
|
|
77
109
|
const shadowClasses = {
|
|
78
110
|
none: '',
|
|
79
|
-
sm: '
|
|
80
|
-
md: '
|
|
81
|
-
lg: '
|
|
111
|
+
sm: 'bw_shadow_sm',
|
|
112
|
+
md: 'bw_shadow',
|
|
113
|
+
lg: 'bw_shadow_lg'
|
|
82
114
|
};
|
|
83
115
|
|
|
84
116
|
const cardClasses = [
|
|
85
|
-
'
|
|
86
|
-
variant
|
|
117
|
+
'bw_card',
|
|
118
|
+
variantClass(variant),
|
|
87
119
|
shadow ? (shadowClasses[shadow] || '') : '',
|
|
88
|
-
!bordered ? '
|
|
89
|
-
hoverable ? '
|
|
120
|
+
!bordered ? 'bw_border_0' : '',
|
|
121
|
+
hoverable ? 'bw_card_hoverable' : '',
|
|
90
122
|
className
|
|
91
123
|
].filter(Boolean).join(' ').trim();
|
|
92
124
|
|
|
93
125
|
const cardContent = [
|
|
94
126
|
header && {
|
|
95
127
|
t: 'div',
|
|
96
|
-
a: { class: `
|
|
128
|
+
a: { class: `bw_card_header ${headerClass}`.trim() },
|
|
97
129
|
c: header
|
|
98
130
|
},
|
|
99
131
|
image && (imagePosition === 'top' || imagePosition === 'left') && {
|
|
100
132
|
t: 'img',
|
|
101
133
|
a: {
|
|
102
|
-
class: `
|
|
134
|
+
class: `bw_card_img_${imagePosition}`,
|
|
103
135
|
src: image.src,
|
|
104
136
|
alt: image.alt || ''
|
|
105
137
|
}
|
|
106
138
|
},
|
|
107
139
|
{
|
|
108
140
|
t: 'div',
|
|
109
|
-
a: { class: `
|
|
141
|
+
a: { class: `bw_card_body ${bodyClass}`.trim() },
|
|
110
142
|
c: [
|
|
111
|
-
title && { t: 'h5', a: { class: '
|
|
112
|
-
subtitle && { t: 'h6', a: { class: '
|
|
143
|
+
title && { t: 'h5', a: { class: 'bw_card_title' }, c: title },
|
|
144
|
+
subtitle && { t: 'h6', a: { class: 'bw_card_subtitle bw_mb_2 bw_text_muted' }, c: subtitle },
|
|
113
145
|
content && (Array.isArray(content) ? content : [content])
|
|
114
146
|
].flat().filter(Boolean)
|
|
115
147
|
},
|
|
116
148
|
image && (imagePosition === 'bottom' || imagePosition === 'right') && {
|
|
117
149
|
t: 'img',
|
|
118
150
|
a: {
|
|
119
|
-
class: `
|
|
151
|
+
class: `bw_card_img_${imagePosition}`,
|
|
120
152
|
src: image.src,
|
|
121
153
|
alt: image.alt || ''
|
|
122
154
|
}
|
|
123
155
|
},
|
|
124
156
|
footer && {
|
|
125
157
|
t: 'div',
|
|
126
|
-
a: { class: `
|
|
158
|
+
a: { class: `bw_card_footer ${footerClass}`.trim() },
|
|
127
159
|
c: footer
|
|
128
160
|
}
|
|
129
161
|
].filter(Boolean);
|
|
@@ -135,7 +167,7 @@ export function makeCard(props = {}) {
|
|
|
135
167
|
a: { class: cardClasses, style },
|
|
136
168
|
c: {
|
|
137
169
|
t: 'div',
|
|
138
|
-
a: { class: '
|
|
170
|
+
a: { class: 'bw_row bw_g_0' },
|
|
139
171
|
c: cardContent
|
|
140
172
|
},
|
|
141
173
|
o: {
|
|
@@ -197,9 +229,9 @@ export function makeButton(props = {}) {
|
|
|
197
229
|
a: {
|
|
198
230
|
type,
|
|
199
231
|
class: [
|
|
200
|
-
'
|
|
201
|
-
|
|
202
|
-
size && `
|
|
232
|
+
'bw_btn',
|
|
233
|
+
variantClass(variant),
|
|
234
|
+
size && `bw_btn_${size}`,
|
|
203
235
|
className
|
|
204
236
|
].filter(Boolean).join(' '),
|
|
205
237
|
disabled,
|
|
@@ -233,7 +265,7 @@ export function makeContainer(props = {}) {
|
|
|
233
265
|
|
|
234
266
|
return {
|
|
235
267
|
t: 'div',
|
|
236
|
-
a: { class: `
|
|
268
|
+
a: { class: `bw_container${fluid ? '-fluid' : ''} ${className}`.trim() },
|
|
237
269
|
c: children
|
|
238
270
|
};
|
|
239
271
|
}
|
|
@@ -244,7 +276,7 @@ export function makeContainer(props = {}) {
|
|
|
244
276
|
* @param {Object} [props] - Row configuration
|
|
245
277
|
* @param {Array|Object|string} [props.children] - Child columns
|
|
246
278
|
* @param {string} [props.className] - Additional CSS classes
|
|
247
|
-
* @param {number} [props.gap] - Gap size (1-5) applied via
|
|
279
|
+
* @param {number} [props.gap] - Gap size (1-5) applied via bw_g_{gap} class
|
|
248
280
|
* @returns {Object} TACO object representing a grid row
|
|
249
281
|
* @category Component Builders
|
|
250
282
|
* @example
|
|
@@ -259,7 +291,7 @@ export function makeRow(props = {}) {
|
|
|
259
291
|
return {
|
|
260
292
|
t: 'div',
|
|
261
293
|
a: {
|
|
262
|
-
class: `
|
|
294
|
+
class: `bw_row ${gap ? `bw_g_${gap}` : ''} ${className}`.trim()
|
|
263
295
|
},
|
|
264
296
|
c: children
|
|
265
297
|
};
|
|
@@ -293,20 +325,20 @@ export function makeCol(props = {}) {
|
|
|
293
325
|
// Responsive sizes
|
|
294
326
|
Object.entries(size).forEach(([breakpoint, value]) => {
|
|
295
327
|
if (breakpoint === 'xs') {
|
|
296
|
-
classes.push(`
|
|
328
|
+
classes.push(`bw_col_${value}`);
|
|
297
329
|
} else {
|
|
298
|
-
classes.push(`
|
|
330
|
+
classes.push(`bw_col_${breakpoint}-${value}`);
|
|
299
331
|
}
|
|
300
332
|
});
|
|
301
333
|
} else if (size) {
|
|
302
|
-
classes.push(`
|
|
334
|
+
classes.push(`bw_col_${size}`);
|
|
303
335
|
} else {
|
|
304
|
-
classes.push('
|
|
336
|
+
classes.push('bw_col');
|
|
305
337
|
}
|
|
306
338
|
|
|
307
|
-
if (offset) classes.push(`
|
|
308
|
-
if (push) classes.push(`
|
|
309
|
-
if (pull) classes.push(`
|
|
339
|
+
if (offset) classes.push(`bw_offset_${offset}`);
|
|
340
|
+
if (push) classes.push(`bw_push_${push}`);
|
|
341
|
+
if (pull) classes.push(`bw_pull_${pull}`);
|
|
310
342
|
|
|
311
343
|
return {
|
|
312
344
|
t: 'div',
|
|
@@ -349,16 +381,16 @@ export function makeNav(props = {}) {
|
|
|
349
381
|
return {
|
|
350
382
|
t: 'ul',
|
|
351
383
|
a: {
|
|
352
|
-
class: `
|
|
384
|
+
class: `bw_nav ${pills ? 'bw_nav_pills' : 'bw_nav_tabs'} ${vertical ? 'bw_nav_vertical' : ''} ${className}`.trim()
|
|
353
385
|
},
|
|
354
386
|
c: items.map(item => ({
|
|
355
387
|
t: 'li',
|
|
356
|
-
a: { class: '
|
|
388
|
+
a: { class: 'bw_nav_item' },
|
|
357
389
|
c: {
|
|
358
390
|
t: 'a',
|
|
359
391
|
a: {
|
|
360
392
|
href: item.href || '#',
|
|
361
|
-
class: `
|
|
393
|
+
class: `bw_nav_link ${item.active ? 'active' : ''} ${item.disabled ? 'disabled' : ''}`.trim()
|
|
362
394
|
},
|
|
363
395
|
c: item.text
|
|
364
396
|
}
|
|
@@ -402,25 +434,25 @@ export function makeNavbar(props = {}) {
|
|
|
402
434
|
return {
|
|
403
435
|
t: 'nav',
|
|
404
436
|
a: {
|
|
405
|
-
class: `
|
|
437
|
+
class: `bw_navbar ${dark ? 'bw_navbar_dark' : 'bw_navbar_light'} ${className}`.trim()
|
|
406
438
|
},
|
|
407
439
|
c: {
|
|
408
440
|
t: 'div',
|
|
409
|
-
a: { class: '
|
|
441
|
+
a: { class: 'bw_container' },
|
|
410
442
|
c: [
|
|
411
443
|
brand && {
|
|
412
444
|
t: 'a',
|
|
413
|
-
a: { href: brandHref, class: '
|
|
445
|
+
a: { href: brandHref, class: 'bw_navbar_brand' },
|
|
414
446
|
c: brand
|
|
415
447
|
},
|
|
416
448
|
items.length > 0 && {
|
|
417
449
|
t: 'div',
|
|
418
|
-
a: { class: '
|
|
450
|
+
a: { class: 'bw_navbar_nav' },
|
|
419
451
|
c: items.map(item => ({
|
|
420
452
|
t: 'a',
|
|
421
453
|
a: {
|
|
422
454
|
href: item.href || '#',
|
|
423
|
-
class: `
|
|
455
|
+
class: `bw_nav_link ${item.active ? 'active' : ''}`
|
|
424
456
|
},
|
|
425
457
|
c: item.text
|
|
426
458
|
}))
|
|
@@ -471,27 +503,27 @@ export function makeTabs(props = {}) {
|
|
|
471
503
|
|
|
472
504
|
return {
|
|
473
505
|
t: 'div',
|
|
474
|
-
a: { class: '
|
|
506
|
+
a: { class: 'bw_tabs' },
|
|
475
507
|
c: [
|
|
476
508
|
{
|
|
477
509
|
t: 'ul',
|
|
478
|
-
a: { class: '
|
|
510
|
+
a: { class: 'bw_nav bw_nav_tabs', role: 'tablist' },
|
|
479
511
|
c: tabs.map((tab, index) => ({
|
|
480
512
|
t: 'li',
|
|
481
|
-
a: { class: '
|
|
513
|
+
a: { class: 'bw_nav_item', role: 'presentation' },
|
|
482
514
|
c: {
|
|
483
515
|
t: 'button',
|
|
484
516
|
a: {
|
|
485
|
-
class: `
|
|
517
|
+
class: `bw_nav_link ${index === actualActiveIndex ? 'active' : ''}`,
|
|
486
518
|
type: 'button',
|
|
487
519
|
role: 'tab',
|
|
488
520
|
tabindex: index === actualActiveIndex ? '0' : '-1',
|
|
489
521
|
'aria-selected': index === actualActiveIndex ? 'true' : 'false',
|
|
490
522
|
'data-tab-index': index,
|
|
491
523
|
onclick: (e) => {
|
|
492
|
-
const tabsContainer = e.target.closest('.
|
|
493
|
-
const allTabs = tabsContainer.querySelectorAll('.
|
|
494
|
-
const allPanes = tabsContainer.querySelectorAll('.
|
|
524
|
+
const tabsContainer = e.target.closest('.bw_tabs');
|
|
525
|
+
const allTabs = tabsContainer.querySelectorAll('.bw_nav_link');
|
|
526
|
+
const allPanes = tabsContainer.querySelectorAll('.bw_tab_pane');
|
|
495
527
|
|
|
496
528
|
allTabs.forEach(t => {
|
|
497
529
|
t.classList.remove('active');
|
|
@@ -513,11 +545,11 @@ export function makeTabs(props = {}) {
|
|
|
513
545
|
},
|
|
514
546
|
{
|
|
515
547
|
t: 'div',
|
|
516
|
-
a: { class: '
|
|
548
|
+
a: { class: 'bw_tab_content' },
|
|
517
549
|
c: tabs.map((tab, index) => ({
|
|
518
550
|
t: 'div',
|
|
519
551
|
a: {
|
|
520
|
-
class: `
|
|
552
|
+
class: `bw_tab_pane ${index === actualActiveIndex ? 'active' : ''}`,
|
|
521
553
|
role: 'tabpanel'
|
|
522
554
|
},
|
|
523
555
|
c: tab.content
|
|
@@ -594,7 +626,7 @@ export function makeAlert(props = {}) {
|
|
|
594
626
|
return {
|
|
595
627
|
t: 'div',
|
|
596
628
|
a: {
|
|
597
|
-
class: `
|
|
629
|
+
class: `bw_alert ${variantClass(variant)} ${dismissible ? 'bw_alert_dismissible' : ''} ${className}`.trim(),
|
|
598
630
|
role: 'alert'
|
|
599
631
|
},
|
|
600
632
|
c: [
|
|
@@ -603,10 +635,10 @@ export function makeAlert(props = {}) {
|
|
|
603
635
|
t: 'button',
|
|
604
636
|
a: {
|
|
605
637
|
type: 'button',
|
|
606
|
-
class: '
|
|
638
|
+
class: 'bw_close',
|
|
607
639
|
'aria-label': 'Close',
|
|
608
640
|
onclick: function(e) {
|
|
609
|
-
var alert = e.target.closest('.
|
|
641
|
+
var alert = e.target.closest('.bw_alert');
|
|
610
642
|
if (alert) { alert.remove(); }
|
|
611
643
|
}
|
|
612
644
|
},
|
|
@@ -643,12 +675,12 @@ export function makeBadge(props = {}) {
|
|
|
643
675
|
className = ''
|
|
644
676
|
} = props;
|
|
645
677
|
|
|
646
|
-
const sizeClass = size === 'sm' ? '
|
|
678
|
+
const sizeClass = size === 'sm' ? ' bw_badge_sm' : size === 'lg' ? ' bw_badge_lg' : '';
|
|
647
679
|
|
|
648
680
|
return {
|
|
649
681
|
t: 'span',
|
|
650
682
|
a: {
|
|
651
|
-
class: `
|
|
683
|
+
class: `bw_badge ${variantClass(variant)}${sizeClass} ${pill ? 'bw_badge_pill' : ''} ${className}`.trim()
|
|
652
684
|
},
|
|
653
685
|
c: text
|
|
654
686
|
};
|
|
@@ -691,17 +723,17 @@ export function makeProgress(props = {}) {
|
|
|
691
723
|
return {
|
|
692
724
|
t: 'div',
|
|
693
725
|
a: {
|
|
694
|
-
class: '
|
|
726
|
+
class: 'bw_progress',
|
|
695
727
|
style: height ? { height: `${height}px` } : undefined
|
|
696
728
|
},
|
|
697
729
|
c: {
|
|
698
730
|
t: 'div',
|
|
699
731
|
a: {
|
|
700
732
|
class: [
|
|
701
|
-
'
|
|
702
|
-
|
|
703
|
-
striped && '
|
|
704
|
-
animated && '
|
|
733
|
+
'bw_progress_bar',
|
|
734
|
+
variantClass(variant),
|
|
735
|
+
striped && 'bw_progress_bar_striped',
|
|
736
|
+
animated && 'bw_progress_bar_animated'
|
|
705
737
|
].filter(Boolean).join(' '),
|
|
706
738
|
role: 'progressbar',
|
|
707
739
|
style: { width: `${percentage}%` },
|
|
@@ -747,7 +779,7 @@ export function makeListGroup(props = {}) {
|
|
|
747
779
|
|
|
748
780
|
return {
|
|
749
781
|
t: 'div',
|
|
750
|
-
a: { class: `
|
|
782
|
+
a: { class: `bw_list_group ${flush ? 'bw_list_group_flush' : ''}`.trim() },
|
|
751
783
|
c: items.map(item => {
|
|
752
784
|
const isObject = typeof item === 'object';
|
|
753
785
|
const text = isObject ? item.text : item;
|
|
@@ -762,7 +794,7 @@ export function makeListGroup(props = {}) {
|
|
|
762
794
|
t: 'a',
|
|
763
795
|
a: {
|
|
764
796
|
class: [
|
|
765
|
-
'
|
|
797
|
+
'bw_list_group_item',
|
|
766
798
|
active && 'active',
|
|
767
799
|
disabled && 'disabled'
|
|
768
800
|
].filter(Boolean).join(' '),
|
|
@@ -781,7 +813,7 @@ export function makeListGroup(props = {}) {
|
|
|
781
813
|
t: 'div',
|
|
782
814
|
a: {
|
|
783
815
|
class: [
|
|
784
|
-
'
|
|
816
|
+
'bw_list_group_item',
|
|
785
817
|
active && 'active',
|
|
786
818
|
disabled && 'disabled'
|
|
787
819
|
].filter(Boolean).join(' ')
|
|
@@ -822,11 +854,11 @@ export function makeBreadcrumb(props = {}) {
|
|
|
822
854
|
a: { 'aria-label': 'breadcrumb' },
|
|
823
855
|
c: {
|
|
824
856
|
t: 'ol',
|
|
825
|
-
a: { class: '
|
|
857
|
+
a: { class: 'bw_breadcrumb' },
|
|
826
858
|
c: items.map((item, index) => ({
|
|
827
859
|
t: 'li',
|
|
828
860
|
a: {
|
|
829
|
-
class: `
|
|
861
|
+
class: `bw_breadcrumb_item ${item.active ? 'active' : ''}`,
|
|
830
862
|
'aria-current': item.active ? 'page' : undefined
|
|
831
863
|
},
|
|
832
864
|
c: item.active ? item.text : {
|
|
@@ -899,7 +931,7 @@ export function makeFormGroup(props = {}) {
|
|
|
899
931
|
var styledInput = input;
|
|
900
932
|
if (validation && input && input.a) {
|
|
901
933
|
styledInput = { t: input.t, a: Object.assign({}, input.a), c: input.c, o: input.o };
|
|
902
|
-
var validClass = validation === 'valid' ? '
|
|
934
|
+
var validClass = validation === 'valid' ? 'bw_is_valid' : validation === 'invalid' ? 'bw_is_invalid' : '';
|
|
903
935
|
if (validClass) {
|
|
904
936
|
styledInput.a.class = ((styledInput.a.class || '') + ' ' + validClass).trim();
|
|
905
937
|
}
|
|
@@ -907,22 +939,22 @@ export function makeFormGroup(props = {}) {
|
|
|
907
939
|
|
|
908
940
|
return {
|
|
909
941
|
t: 'div',
|
|
910
|
-
a: { class: '
|
|
942
|
+
a: { class: 'bw_form_group' },
|
|
911
943
|
c: [
|
|
912
944
|
label && {
|
|
913
945
|
t: 'label',
|
|
914
|
-
a: { for: id, class: '
|
|
915
|
-
c: required ? [label, { t: 'span', a: { class: '
|
|
946
|
+
a: { for: id, class: 'bw_form_label' },
|
|
947
|
+
c: required ? [label, { t: 'span', a: { class: 'bw_text_danger bw_ms_1' }, c: '*' }] : label
|
|
916
948
|
},
|
|
917
949
|
styledInput,
|
|
918
950
|
feedback && validation && {
|
|
919
951
|
t: 'div',
|
|
920
|
-
a: { class: validation === 'valid' ? '
|
|
952
|
+
a: { class: validation === 'valid' ? 'bw_valid_feedback' : 'bw_invalid_feedback' },
|
|
921
953
|
c: feedback
|
|
922
954
|
},
|
|
923
955
|
help && {
|
|
924
956
|
t: 'small',
|
|
925
|
-
a: { class: '
|
|
957
|
+
a: { class: 'bw_form_text bw_text_muted' },
|
|
926
958
|
c: help
|
|
927
959
|
}
|
|
928
960
|
].filter(Boolean)
|
|
@@ -975,7 +1007,7 @@ export function makeInput(props = {}) {
|
|
|
975
1007
|
t: 'input',
|
|
976
1008
|
a: {
|
|
977
1009
|
type,
|
|
978
|
-
class: `
|
|
1010
|
+
class: `bw_form_control ${className}`.trim(),
|
|
979
1011
|
placeholder,
|
|
980
1012
|
value,
|
|
981
1013
|
id,
|
|
@@ -1028,7 +1060,7 @@ export function makeTextarea(props = {}) {
|
|
|
1028
1060
|
return {
|
|
1029
1061
|
t: 'textarea',
|
|
1030
1062
|
a: {
|
|
1031
|
-
class: `
|
|
1063
|
+
class: `bw_form_control ${className}`.trim(),
|
|
1032
1064
|
placeholder,
|
|
1033
1065
|
rows,
|
|
1034
1066
|
id,
|
|
@@ -1082,7 +1114,7 @@ export function makeSelect(props = {}) {
|
|
|
1082
1114
|
return {
|
|
1083
1115
|
t: 'select',
|
|
1084
1116
|
a: {
|
|
1085
|
-
class: `
|
|
1117
|
+
class: `bw_form_control ${className}`.trim(),
|
|
1086
1118
|
id,
|
|
1087
1119
|
name,
|
|
1088
1120
|
disabled,
|
|
@@ -1133,13 +1165,13 @@ export function makeCheckbox(props = {}) {
|
|
|
1133
1165
|
|
|
1134
1166
|
return {
|
|
1135
1167
|
t: 'div',
|
|
1136
|
-
a: { class: `
|
|
1168
|
+
a: { class: `bw_form_check ${className}`.trim() },
|
|
1137
1169
|
c: [
|
|
1138
1170
|
{
|
|
1139
1171
|
t: 'input',
|
|
1140
1172
|
a: {
|
|
1141
1173
|
type: 'checkbox',
|
|
1142
|
-
class: '
|
|
1174
|
+
class: 'bw_form_check_input',
|
|
1143
1175
|
checked,
|
|
1144
1176
|
id,
|
|
1145
1177
|
name,
|
|
@@ -1150,7 +1182,7 @@ export function makeCheckbox(props = {}) {
|
|
|
1150
1182
|
},
|
|
1151
1183
|
label && {
|
|
1152
1184
|
t: 'label',
|
|
1153
|
-
a: { class: '
|
|
1185
|
+
a: { class: 'bw_form_check_label', for: id },
|
|
1154
1186
|
c: label
|
|
1155
1187
|
}
|
|
1156
1188
|
].filter(Boolean)
|
|
@@ -1188,7 +1220,7 @@ export function makeStack(props = {}) {
|
|
|
1188
1220
|
return {
|
|
1189
1221
|
t: 'div',
|
|
1190
1222
|
a: {
|
|
1191
|
-
class: `
|
|
1223
|
+
class: `bw_${direction === 'vertical' ? 'vstack' : 'hstack'} bw_gap_${gap} ${className}`.trim()
|
|
1192
1224
|
},
|
|
1193
1225
|
c: children
|
|
1194
1226
|
};
|
|
@@ -1216,12 +1248,12 @@ export function makeSpinner(props = {}) {
|
|
|
1216
1248
|
return {
|
|
1217
1249
|
t: 'div',
|
|
1218
1250
|
a: {
|
|
1219
|
-
class: `
|
|
1251
|
+
class: `bw_spinner_${type} bw_spinner_${type}-${size} ${variantClass(variant)}`,
|
|
1220
1252
|
role: 'status'
|
|
1221
1253
|
},
|
|
1222
1254
|
c: {
|
|
1223
1255
|
t: 'span',
|
|
1224
|
-
a: { class: '
|
|
1256
|
+
a: { class: 'bw_visually_hidden' },
|
|
1225
1257
|
c: 'Loading...'
|
|
1226
1258
|
}
|
|
1227
1259
|
};
|
|
@@ -1272,44 +1304,44 @@ export function makeHero(props = {}) {
|
|
|
1272
1304
|
} = props;
|
|
1273
1305
|
|
|
1274
1306
|
const sizeClasses = {
|
|
1275
|
-
sm: '
|
|
1276
|
-
md: '
|
|
1277
|
-
lg: '
|
|
1278
|
-
xl: '
|
|
1307
|
+
sm: 'bw_py_3',
|
|
1308
|
+
md: 'bw_py_4',
|
|
1309
|
+
lg: 'bw_py_5',
|
|
1310
|
+
xl: 'bw_py_6'
|
|
1279
1311
|
};
|
|
1280
1312
|
|
|
1281
1313
|
return {
|
|
1282
1314
|
t: 'section',
|
|
1283
1315
|
a: {
|
|
1284
|
-
class: `
|
|
1316
|
+
class: `bw_hero ${variantClass(variant)} ${sizeClasses[size] || sizeClasses.lg} ${centered ? 'bw_text_center' : ''} ${className}`.trim(),
|
|
1285
1317
|
style: backgroundImage ? `background-image: url('${backgroundImage}'); background-size: cover; background-position: center;` : undefined
|
|
1286
1318
|
},
|
|
1287
1319
|
c: [
|
|
1288
1320
|
overlay && {
|
|
1289
1321
|
t: 'div',
|
|
1290
|
-
a: { class: '
|
|
1322
|
+
a: { class: 'bw_hero_overlay' }
|
|
1291
1323
|
},
|
|
1292
1324
|
{
|
|
1293
1325
|
t: 'div',
|
|
1294
|
-
a: { class: '
|
|
1326
|
+
a: { class: 'bw_container' },
|
|
1295
1327
|
c: {
|
|
1296
1328
|
t: 'div',
|
|
1297
|
-
a: { class: '
|
|
1329
|
+
a: { class: 'bw_hero_content' },
|
|
1298
1330
|
c: [
|
|
1299
1331
|
title && {
|
|
1300
1332
|
t: 'h1',
|
|
1301
|
-
a: { class: '
|
|
1333
|
+
a: { class: 'bw_hero_title bw_display_4 bw_mb_3' },
|
|
1302
1334
|
c: title
|
|
1303
1335
|
},
|
|
1304
1336
|
subtitle && {
|
|
1305
1337
|
t: 'p',
|
|
1306
|
-
a: { class: '
|
|
1338
|
+
a: { class: 'bw_hero_subtitle bw_lead bw_mb_4' },
|
|
1307
1339
|
c: subtitle
|
|
1308
1340
|
},
|
|
1309
1341
|
content,
|
|
1310
1342
|
actions && {
|
|
1311
1343
|
t: 'div',
|
|
1312
|
-
a: { class: '
|
|
1344
|
+
a: { class: 'bw_hero_actions bw_mt_4' },
|
|
1313
1345
|
c: actions
|
|
1314
1346
|
}
|
|
1315
1347
|
].filter(Boolean)
|
|
@@ -1355,37 +1387,37 @@ export function makeFeatureGrid(props = {}) {
|
|
|
1355
1387
|
className = ''
|
|
1356
1388
|
} = props;
|
|
1357
1389
|
|
|
1358
|
-
const colClass = `
|
|
1390
|
+
const colClass = `bw_col_md_${12/columns}`;
|
|
1359
1391
|
|
|
1360
1392
|
return {
|
|
1361
1393
|
t: 'div',
|
|
1362
|
-
a: { class: `
|
|
1394
|
+
a: { class: `bw_feature_grid ${className}`.trim() },
|
|
1363
1395
|
c: {
|
|
1364
1396
|
t: 'div',
|
|
1365
|
-
a: { class: '
|
|
1397
|
+
a: { class: 'bw_row bw_g_4' },
|
|
1366
1398
|
c: features.map(feature => ({
|
|
1367
1399
|
t: 'div',
|
|
1368
1400
|
a: { class: colClass },
|
|
1369
1401
|
c: {
|
|
1370
1402
|
t: 'div',
|
|
1371
|
-
a: { class: `
|
|
1403
|
+
a: { class: `bw_feature ${centered ? 'bw_text_center' : ''}` },
|
|
1372
1404
|
c: [
|
|
1373
1405
|
feature.icon && {
|
|
1374
1406
|
t: 'div',
|
|
1375
1407
|
a: {
|
|
1376
|
-
class: '
|
|
1408
|
+
class: 'bw_feature_icon bw_mb_3 bw_text_primary',
|
|
1377
1409
|
style: `font-size: ${iconSize};`
|
|
1378
1410
|
},
|
|
1379
1411
|
c: feature.icon
|
|
1380
1412
|
},
|
|
1381
1413
|
feature.title && {
|
|
1382
1414
|
t: 'h3',
|
|
1383
|
-
a: { class: '
|
|
1415
|
+
a: { class: 'bw_feature_title bw_h5 bw_mb_2' },
|
|
1384
1416
|
c: feature.title
|
|
1385
1417
|
},
|
|
1386
1418
|
feature.description && {
|
|
1387
1419
|
t: 'p',
|
|
1388
|
-
a: { class: '
|
|
1420
|
+
a: { class: 'bw_feature_description bw_text_muted' },
|
|
1389
1421
|
c: feature.description
|
|
1390
1422
|
}
|
|
1391
1423
|
].filter(Boolean)
|
|
@@ -1429,19 +1461,19 @@ export function makeCTA(props = {}) {
|
|
|
1429
1461
|
|
|
1430
1462
|
return {
|
|
1431
1463
|
t: 'section',
|
|
1432
|
-
a: { class: `
|
|
1464
|
+
a: { class: `bw_cta bw_bg_${variant} bw_py_5 ${className}`.trim() },
|
|
1433
1465
|
c: {
|
|
1434
1466
|
t: 'div',
|
|
1435
|
-
a: { class: '
|
|
1467
|
+
a: { class: 'bw_container' },
|
|
1436
1468
|
c: {
|
|
1437
1469
|
t: 'div',
|
|
1438
|
-
a: { class: `
|
|
1470
|
+
a: { class: `bw_cta_content ${centered ? 'bw_text_center' : ''}` },
|
|
1439
1471
|
c: [
|
|
1440
|
-
title && { t: 'h2', a: { class: '
|
|
1441
|
-
description && { t: 'p', a: { class: '
|
|
1472
|
+
title && { t: 'h2', a: { class: 'bw_cta_title bw_mb_3' }, c: title },
|
|
1473
|
+
description && { t: 'p', a: { class: 'bw_cta_description bw_lead bw_mb_4' }, c: description },
|
|
1442
1474
|
actions && {
|
|
1443
1475
|
t: 'div',
|
|
1444
|
-
a: { class: '
|
|
1476
|
+
a: { class: 'bw_cta_actions' },
|
|
1445
1477
|
c: actions
|
|
1446
1478
|
}
|
|
1447
1479
|
].filter(Boolean)
|
|
@@ -1481,27 +1513,27 @@ export function makeSection(props = {}) {
|
|
|
1481
1513
|
} = props;
|
|
1482
1514
|
|
|
1483
1515
|
const spacingClasses = {
|
|
1484
|
-
sm: '
|
|
1485
|
-
md: '
|
|
1486
|
-
lg: '
|
|
1487
|
-
xl: '
|
|
1516
|
+
sm: 'bw_py_3',
|
|
1517
|
+
md: 'bw_py_4',
|
|
1518
|
+
lg: 'bw_py_5',
|
|
1519
|
+
xl: 'bw_py_6'
|
|
1488
1520
|
};
|
|
1489
1521
|
|
|
1490
1522
|
return {
|
|
1491
1523
|
t: 'section',
|
|
1492
1524
|
a: {
|
|
1493
|
-
class: `
|
|
1525
|
+
class: `bw_section ${spacingClasses[spacing] || spacingClasses.md} ${variant !== 'default' ? `bw_bg_${variant}` : ''} ${className}`.trim()
|
|
1494
1526
|
},
|
|
1495
1527
|
c: {
|
|
1496
1528
|
t: 'div',
|
|
1497
|
-
a: { class: '
|
|
1529
|
+
a: { class: 'bw_container' },
|
|
1498
1530
|
c: [
|
|
1499
1531
|
(title || subtitle) && {
|
|
1500
1532
|
t: 'div',
|
|
1501
|
-
a: { class: '
|
|
1533
|
+
a: { class: 'bw_section_header bw_text_center bw_mb_5' },
|
|
1502
1534
|
c: [
|
|
1503
|
-
title && { t: 'h2', a: { class: '
|
|
1504
|
-
subtitle && { t: 'p', a: { class: '
|
|
1535
|
+
title && { t: 'h2', a: { class: 'bw_section_title' }, c: title },
|
|
1536
|
+
subtitle && { t: 'p', a: { class: 'bw_section_subtitle bw_text_muted' }, c: subtitle }
|
|
1505
1537
|
].filter(Boolean)
|
|
1506
1538
|
},
|
|
1507
1539
|
content
|
|
@@ -1518,317 +1550,9 @@ export function makeSection(props = {}) {
|
|
|
1518
1550
|
// full re-renders. Used by bw.createCard(), bw.createTable(), etc.
|
|
1519
1551
|
// =========================================================================
|
|
1520
1552
|
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
* Provides methods to update card title, content, and CSS classes
|
|
1525
|
-
* without re-rendering the entire component. Created automatically
|
|
1526
|
-
* when using bw.createCard().
|
|
1527
|
-
*
|
|
1528
|
-
* @category Component Handles
|
|
1529
|
-
*/
|
|
1530
|
-
export class CardHandle {
|
|
1531
|
-
/**
|
|
1532
|
-
* @param {Element} element - The card's root DOM element
|
|
1533
|
-
* @param {Object} taco - The original TACO object used to create the card
|
|
1534
|
-
*/
|
|
1535
|
-
constructor(element, taco) {
|
|
1536
|
-
this.element = element;
|
|
1537
|
-
this._taco = taco;
|
|
1538
|
-
this.state = taco.o?.state || {};
|
|
1539
|
-
|
|
1540
|
-
// Cache child elements
|
|
1541
|
-
this.children = {
|
|
1542
|
-
header: element.querySelector('.bw-card-header'),
|
|
1543
|
-
title: element.querySelector('.bw-card-title'),
|
|
1544
|
-
body: element.querySelector('.bw-card-body'),
|
|
1545
|
-
footer: element.querySelector('.bw-card-footer')
|
|
1546
|
-
};
|
|
1547
|
-
}
|
|
1548
|
-
|
|
1549
|
-
/**
|
|
1550
|
-
* Update the card title text
|
|
1551
|
-
*
|
|
1552
|
-
* @param {string} title - New title text
|
|
1553
|
-
* @returns {CardHandle} this (for chaining)
|
|
1554
|
-
*/
|
|
1555
|
-
setTitle(title) {
|
|
1556
|
-
if (this.children.title) {
|
|
1557
|
-
this.children.title.textContent = title;
|
|
1558
|
-
}
|
|
1559
|
-
return this;
|
|
1560
|
-
}
|
|
1561
|
-
|
|
1562
|
-
/**
|
|
1563
|
-
* Replace the card body content
|
|
1564
|
-
*
|
|
1565
|
-
* @param {string|Object} content - New content (string or TACO object)
|
|
1566
|
-
* @returns {CardHandle} this (for chaining)
|
|
1567
|
-
*/
|
|
1568
|
-
setContent(content) {
|
|
1569
|
-
if (this.children.body) {
|
|
1570
|
-
if (typeof content === 'string') {
|
|
1571
|
-
this.children.body.textContent = content;
|
|
1572
|
-
} else {
|
|
1573
|
-
// Re-render content
|
|
1574
|
-
this.children.body.innerHTML = '';
|
|
1575
|
-
const newContent = window.bw.taco.toDOM(content);
|
|
1576
|
-
this.children.body.appendChild(newContent);
|
|
1577
|
-
}
|
|
1578
|
-
}
|
|
1579
|
-
return this;
|
|
1580
|
-
}
|
|
1581
|
-
|
|
1582
|
-
/**
|
|
1583
|
-
* Add a CSS class to the card root element
|
|
1584
|
-
*
|
|
1585
|
-
* @param {string} className - Class to add
|
|
1586
|
-
* @returns {CardHandle} this (for chaining)
|
|
1587
|
-
*/
|
|
1588
|
-
addClass(className) {
|
|
1589
|
-
this.element.classList.add(className);
|
|
1590
|
-
return this;
|
|
1591
|
-
}
|
|
1592
|
-
|
|
1593
|
-
/**
|
|
1594
|
-
* Remove a CSS class from the card root element
|
|
1595
|
-
*
|
|
1596
|
-
* @param {string} className - Class to remove
|
|
1597
|
-
* @returns {CardHandle} this (for chaining)
|
|
1598
|
-
*/
|
|
1599
|
-
removeClass(className) {
|
|
1600
|
-
this.element.classList.remove(className);
|
|
1601
|
-
return this;
|
|
1602
|
-
}
|
|
1603
|
-
|
|
1604
|
-
/**
|
|
1605
|
-
* Query a child element within the card
|
|
1606
|
-
*
|
|
1607
|
-
* @param {string} selector - CSS selector
|
|
1608
|
-
* @returns {Element|null} Matching element or null
|
|
1609
|
-
*/
|
|
1610
|
-
select(selector) {
|
|
1611
|
-
return this.element.querySelector(selector);
|
|
1612
|
-
}
|
|
1613
|
-
}
|
|
1614
|
-
|
|
1615
|
-
/**
|
|
1616
|
-
* Imperative handle for a rendered table component
|
|
1617
|
-
*
|
|
1618
|
-
* Provides methods for data updates and column sorting. Caches
|
|
1619
|
-
* thead/tbody/header references for efficient DOM updates.
|
|
1620
|
-
* Created automatically when using bw.createTable().
|
|
1621
|
-
*
|
|
1622
|
-
* @category Component Handles
|
|
1623
|
-
*/
|
|
1624
|
-
export class TableHandle {
|
|
1625
|
-
/**
|
|
1626
|
-
* @param {Element} element - The table's root DOM element
|
|
1627
|
-
* @param {Object} taco - The original TACO object used to create the table
|
|
1628
|
-
*/
|
|
1629
|
-
constructor(element, taco) {
|
|
1630
|
-
this.element = element;
|
|
1631
|
-
this._taco = taco;
|
|
1632
|
-
this.state = taco.o?.state || {};
|
|
1633
|
-
this._data = this.state.data || [];
|
|
1634
|
-
this._sortColumn = null;
|
|
1635
|
-
this._sortDirection = 'asc';
|
|
1636
|
-
|
|
1637
|
-
// Cache elements
|
|
1638
|
-
this.children = {
|
|
1639
|
-
thead: element.querySelector('thead'),
|
|
1640
|
-
tbody: element.querySelector('tbody'),
|
|
1641
|
-
headers: element.querySelectorAll('th')
|
|
1642
|
-
};
|
|
1643
|
-
|
|
1644
|
-
// Set up sorting if enabled
|
|
1645
|
-
if (this.state.sortable) {
|
|
1646
|
-
this._setupSorting();
|
|
1647
|
-
}
|
|
1648
|
-
}
|
|
1649
|
-
|
|
1650
|
-
/**
|
|
1651
|
-
* Attach click-to-sort handlers on all column headers
|
|
1652
|
-
* @private
|
|
1653
|
-
*/
|
|
1654
|
-
_setupSorting() {
|
|
1655
|
-
this.children.headers.forEach((th, index) => {
|
|
1656
|
-
th.style.cursor = 'pointer';
|
|
1657
|
-
th.onclick = () => this.sortBy(th.textContent);
|
|
1658
|
-
});
|
|
1659
|
-
}
|
|
1660
|
-
|
|
1661
|
-
/**
|
|
1662
|
-
* Replace the table data and re-render the body
|
|
1663
|
-
*
|
|
1664
|
-
* @param {Array<Object>} data - Array of row objects
|
|
1665
|
-
* @returns {TableHandle} this (for chaining)
|
|
1666
|
-
*/
|
|
1667
|
-
setData(data) {
|
|
1668
|
-
this._data = data;
|
|
1669
|
-
this._renderBody();
|
|
1670
|
-
return this;
|
|
1671
|
-
}
|
|
1672
|
-
|
|
1673
|
-
/**
|
|
1674
|
-
* Sort the table by a column name
|
|
1675
|
-
*
|
|
1676
|
-
* Toggles direction if the same column is sorted again.
|
|
1677
|
-
*
|
|
1678
|
-
* @param {string} column - Column header text to sort by
|
|
1679
|
-
* @param {string} [direction] - Sort direction ("asc" or "desc"); toggles if omitted
|
|
1680
|
-
* @returns {TableHandle} this (for chaining)
|
|
1681
|
-
*/
|
|
1682
|
-
sortBy(column, direction) {
|
|
1683
|
-
if (column === this._sortColumn && !direction) {
|
|
1684
|
-
this._sortDirection = this._sortDirection === 'asc' ? 'desc' : 'asc';
|
|
1685
|
-
} else {
|
|
1686
|
-
this._sortColumn = column;
|
|
1687
|
-
this._sortDirection = direction || 'asc';
|
|
1688
|
-
}
|
|
1689
|
-
|
|
1690
|
-
const columnKey = Object.keys(this._data[0])[
|
|
1691
|
-
Array.from(this.children.headers).findIndex(th => th.textContent === column)
|
|
1692
|
-
];
|
|
1693
|
-
|
|
1694
|
-
this._data.sort((a, b) => {
|
|
1695
|
-
const aVal = a[columnKey];
|
|
1696
|
-
const bVal = b[columnKey];
|
|
1697
|
-
const result = aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
|
|
1698
|
-
return this._sortDirection === 'asc' ? result : -result;
|
|
1699
|
-
});
|
|
1700
|
-
|
|
1701
|
-
this._renderBody();
|
|
1702
|
-
return this;
|
|
1703
|
-
}
|
|
1704
|
-
|
|
1705
|
-
/**
|
|
1706
|
-
* Re-render the tbody from current _data
|
|
1707
|
-
* @private
|
|
1708
|
-
*/
|
|
1709
|
-
_renderBody() {
|
|
1710
|
-
this.children.tbody.innerHTML = '';
|
|
1711
|
-
this._data.forEach(row => {
|
|
1712
|
-
const tr = document.createElement('tr');
|
|
1713
|
-
Object.values(row).forEach(value => {
|
|
1714
|
-
const td = document.createElement('td');
|
|
1715
|
-
td.textContent = value;
|
|
1716
|
-
tr.appendChild(td);
|
|
1717
|
-
});
|
|
1718
|
-
this.children.tbody.appendChild(tr);
|
|
1719
|
-
});
|
|
1720
|
-
}
|
|
1721
|
-
}
|
|
1722
|
-
|
|
1723
|
-
/**
|
|
1724
|
-
* Imperative handle for a rendered navbar component
|
|
1725
|
-
*
|
|
1726
|
-
* Provides methods to update the active navigation link.
|
|
1727
|
-
* Created automatically when using bw.createNavbar().
|
|
1728
|
-
*
|
|
1729
|
-
* @category Component Handles
|
|
1730
|
-
*/
|
|
1731
|
-
export class NavbarHandle {
|
|
1732
|
-
/**
|
|
1733
|
-
* @param {Element} element - The navbar's root DOM element
|
|
1734
|
-
* @param {Object} taco - The original TACO object used to create the navbar
|
|
1735
|
-
*/
|
|
1736
|
-
constructor(element, taco) {
|
|
1737
|
-
this.element = element;
|
|
1738
|
-
this._taco = taco;
|
|
1739
|
-
this.state = taco.o?.state || {};
|
|
1740
|
-
|
|
1741
|
-
this.children = {
|
|
1742
|
-
brand: element.querySelector('.bw-navbar-brand'),
|
|
1743
|
-
links: element.querySelectorAll('.bw-nav-link')
|
|
1744
|
-
};
|
|
1745
|
-
}
|
|
1746
|
-
|
|
1747
|
-
/**
|
|
1748
|
-
* Set the active navigation link by href
|
|
1749
|
-
*
|
|
1750
|
-
* @param {string} href - The href value of the link to activate
|
|
1751
|
-
* @returns {NavbarHandle} this (for chaining)
|
|
1752
|
-
*/
|
|
1753
|
-
setActive(href) {
|
|
1754
|
-
this.children.links.forEach(link => {
|
|
1755
|
-
if (link.getAttribute('href') === href) {
|
|
1756
|
-
link.classList.add('active');
|
|
1757
|
-
} else {
|
|
1758
|
-
link.classList.remove('active');
|
|
1759
|
-
}
|
|
1760
|
-
});
|
|
1761
|
-
return this;
|
|
1762
|
-
}
|
|
1763
|
-
}
|
|
1764
|
-
|
|
1765
|
-
/**
|
|
1766
|
-
* Imperative handle for a rendered tabs component
|
|
1767
|
-
*
|
|
1768
|
-
* Provides programmatic tab switching. Sets up click handlers
|
|
1769
|
-
* on tab buttons and manages active states on both buttons and panes.
|
|
1770
|
-
* Created automatically when using bw.createTabs().
|
|
1771
|
-
*
|
|
1772
|
-
* @category Component Handles
|
|
1773
|
-
*/
|
|
1774
|
-
export class TabsHandle {
|
|
1775
|
-
/**
|
|
1776
|
-
* @param {Element} element - The tabs container DOM element
|
|
1777
|
-
* @param {Object} taco - The original TACO object used to create the tabs
|
|
1778
|
-
*/
|
|
1779
|
-
constructor(element, taco) {
|
|
1780
|
-
this.element = element;
|
|
1781
|
-
this._taco = taco;
|
|
1782
|
-
this.state = taco.o?.state || {};
|
|
1783
|
-
|
|
1784
|
-
this.children = {
|
|
1785
|
-
navItems: element.querySelectorAll('.bw-nav-link'),
|
|
1786
|
-
tabPanes: element.querySelectorAll('.bw-tab-pane')
|
|
1787
|
-
};
|
|
1788
|
-
|
|
1789
|
-
this._setupTabs();
|
|
1790
|
-
}
|
|
1791
|
-
|
|
1792
|
-
/**
|
|
1793
|
-
* Attach click handlers to tab navigation buttons
|
|
1794
|
-
* @private
|
|
1795
|
-
*/
|
|
1796
|
-
_setupTabs() {
|
|
1797
|
-
this.children.navItems.forEach((navItem, index) => {
|
|
1798
|
-
navItem.onclick = (e) => {
|
|
1799
|
-
e.preventDefault();
|
|
1800
|
-
this.switchTo(index);
|
|
1801
|
-
};
|
|
1802
|
-
});
|
|
1803
|
-
}
|
|
1804
|
-
|
|
1805
|
-
/**
|
|
1806
|
-
* Programmatically switch to a tab by index
|
|
1807
|
-
*
|
|
1808
|
-
* @param {number} index - Zero-based tab index to activate
|
|
1809
|
-
* @returns {TabsHandle} this (for chaining)
|
|
1810
|
-
*/
|
|
1811
|
-
switchTo(index) {
|
|
1812
|
-
this.children.navItems.forEach((item, i) => {
|
|
1813
|
-
if (i === index) {
|
|
1814
|
-
item.classList.add('active');
|
|
1815
|
-
} else {
|
|
1816
|
-
item.classList.remove('active');
|
|
1817
|
-
}
|
|
1818
|
-
});
|
|
1819
|
-
|
|
1820
|
-
this.children.tabPanes.forEach((pane, i) => {
|
|
1821
|
-
if (i === index) {
|
|
1822
|
-
pane.classList.add('active');
|
|
1823
|
-
} else {
|
|
1824
|
-
pane.classList.remove('active');
|
|
1825
|
-
}
|
|
1826
|
-
});
|
|
1827
|
-
|
|
1828
|
-
this.state.activeIndex = index;
|
|
1829
|
-
return this;
|
|
1830
|
-
}
|
|
1831
|
-
}
|
|
1553
|
+
// Handle classes (CardHandle, TableHandle, NavbarHandle, TabsHandle)
|
|
1554
|
+
// removed in v2.0.15 — superseded by ComponentHandle.
|
|
1555
|
+
// See dev/dead-code-elimination-v2.0.15.md for recovery.
|
|
1832
1556
|
|
|
1833
1557
|
/**
|
|
1834
1558
|
* Create a code demo component for documentation pages
|
|
@@ -1883,16 +1607,16 @@ export function makeCodeDemo(props = {}) {
|
|
|
1883
1607
|
{
|
|
1884
1608
|
t: 'button',
|
|
1885
1609
|
a: {
|
|
1886
|
-
class: '
|
|
1610
|
+
class: 'bw_copy_btn bw_code_copy_btn',
|
|
1887
1611
|
onclick: function(e) {
|
|
1888
1612
|
navigator.clipboard.writeText(code).then(function() {
|
|
1889
1613
|
var btn = e.target;
|
|
1890
1614
|
var originalText = btn.textContent;
|
|
1891
1615
|
btn.textContent = 'Copied!';
|
|
1892
|
-
btn.classList.add('
|
|
1616
|
+
btn.classList.add('bw_code_copy_btn_copied');
|
|
1893
1617
|
setTimeout(function() {
|
|
1894
1618
|
btn.textContent = originalText;
|
|
1895
|
-
btn.classList.remove('
|
|
1619
|
+
btn.classList.remove('bw_code_copy_btn_copied');
|
|
1896
1620
|
}, 2000);
|
|
1897
1621
|
});
|
|
1898
1622
|
}
|
|
@@ -1903,10 +1627,10 @@ export function makeCodeDemo(props = {}) {
|
|
|
1903
1627
|
? globalThis.bw.codeEditor({ code: code, lang: language === 'javascript' ? 'js' : language, readOnly: true, height: 'auto' })
|
|
1904
1628
|
: {
|
|
1905
1629
|
t: 'pre',
|
|
1906
|
-
a: { class: '
|
|
1630
|
+
a: { class: 'bw_code_pre' },
|
|
1907
1631
|
c: {
|
|
1908
1632
|
t: 'code',
|
|
1909
|
-
a: { class: `
|
|
1633
|
+
a: { class: `bw_code_block language-${language}` },
|
|
1910
1634
|
c: code
|
|
1911
1635
|
}
|
|
1912
1636
|
}
|
|
@@ -1919,7 +1643,7 @@ export function makeCodeDemo(props = {}) {
|
|
|
1919
1643
|
title && { t: 'h3', c: title },
|
|
1920
1644
|
description && {
|
|
1921
1645
|
t: 'p',
|
|
1922
|
-
a: { class: '
|
|
1646
|
+
a: { class: 'bw_text_muted bw_mb_3' },
|
|
1923
1647
|
c: description
|
|
1924
1648
|
},
|
|
1925
1649
|
makeTabs({ tabs, id: demoId })
|
|
@@ -1927,7 +1651,7 @@ export function makeCodeDemo(props = {}) {
|
|
|
1927
1651
|
|
|
1928
1652
|
return {
|
|
1929
1653
|
t: 'div',
|
|
1930
|
-
a: { class: '
|
|
1654
|
+
a: { class: 'bw_code_demo' },
|
|
1931
1655
|
c: content
|
|
1932
1656
|
};
|
|
1933
1657
|
}
|
|
@@ -1984,10 +1708,10 @@ export function makePagination(props = {}) {
|
|
|
1984
1708
|
// Previous arrow
|
|
1985
1709
|
items.push({
|
|
1986
1710
|
t: 'li',
|
|
1987
|
-
a: { class: `
|
|
1711
|
+
a: { class: `bw_page_item ${currentPage <= 1 ? 'bw_disabled' : ''}`.trim() },
|
|
1988
1712
|
c: {
|
|
1989
1713
|
t: 'a',
|
|
1990
|
-
a: { class: '
|
|
1714
|
+
a: { class: 'bw_page_link', href: '#', onclick: handleClick(currentPage - 1), 'aria-label': 'Previous' },
|
|
1991
1715
|
c: '\u2039'
|
|
1992
1716
|
}
|
|
1993
1717
|
});
|
|
@@ -1997,10 +1721,10 @@ export function makePagination(props = {}) {
|
|
|
1997
1721
|
(function(pageNum) {
|
|
1998
1722
|
items.push({
|
|
1999
1723
|
t: 'li',
|
|
2000
|
-
a: { class: `
|
|
1724
|
+
a: { class: `bw_page_item ${pageNum === currentPage ? 'bw_active' : ''}`.trim() },
|
|
2001
1725
|
c: {
|
|
2002
1726
|
t: 'a',
|
|
2003
|
-
a: { class: '
|
|
1727
|
+
a: { class: 'bw_page_link', href: '#', onclick: handleClick(pageNum) },
|
|
2004
1728
|
c: '' + pageNum
|
|
2005
1729
|
}
|
|
2006
1730
|
});
|
|
@@ -2010,10 +1734,10 @@ export function makePagination(props = {}) {
|
|
|
2010
1734
|
// Next arrow
|
|
2011
1735
|
items.push({
|
|
2012
1736
|
t: 'li',
|
|
2013
|
-
a: { class: `
|
|
1737
|
+
a: { class: `bw_page_item ${currentPage >= pages ? 'bw_disabled' : ''}`.trim() },
|
|
2014
1738
|
c: {
|
|
2015
1739
|
t: 'a',
|
|
2016
|
-
a: { class: '
|
|
1740
|
+
a: { class: 'bw_page_link', href: '#', onclick: handleClick(currentPage + 1), 'aria-label': 'Next' },
|
|
2017
1741
|
c: '\u203A'
|
|
2018
1742
|
}
|
|
2019
1743
|
});
|
|
@@ -2024,7 +1748,7 @@ export function makePagination(props = {}) {
|
|
|
2024
1748
|
c: {
|
|
2025
1749
|
t: 'ul',
|
|
2026
1750
|
a: {
|
|
2027
|
-
class: `
|
|
1751
|
+
class: `bw_pagination ${size ? 'bw_pagination_' + size : ''} ${className}`.trim()
|
|
2028
1752
|
},
|
|
2029
1753
|
c: items
|
|
2030
1754
|
}
|
|
@@ -2066,13 +1790,13 @@ export function makeRadio(props = {}) {
|
|
|
2066
1790
|
|
|
2067
1791
|
return {
|
|
2068
1792
|
t: 'div',
|
|
2069
|
-
a: { class: `
|
|
1793
|
+
a: { class: `bw_form_check ${className}`.trim() },
|
|
2070
1794
|
c: [
|
|
2071
1795
|
{
|
|
2072
1796
|
t: 'input',
|
|
2073
1797
|
a: {
|
|
2074
1798
|
type: 'radio',
|
|
2075
|
-
class: '
|
|
1799
|
+
class: 'bw_form_check_input',
|
|
2076
1800
|
name,
|
|
2077
1801
|
value,
|
|
2078
1802
|
checked,
|
|
@@ -2083,7 +1807,7 @@ export function makeRadio(props = {}) {
|
|
|
2083
1807
|
},
|
|
2084
1808
|
label && {
|
|
2085
1809
|
t: 'label',
|
|
2086
|
-
a: { class: '
|
|
1810
|
+
a: { class: 'bw_form_check_label', for: id },
|
|
2087
1811
|
c: label
|
|
2088
1812
|
}
|
|
2089
1813
|
].filter(Boolean)
|
|
@@ -2120,7 +1844,7 @@ export function makeButtonGroup(props = {}) {
|
|
|
2120
1844
|
return {
|
|
2121
1845
|
t: 'div',
|
|
2122
1846
|
a: {
|
|
2123
|
-
class: `${vertical ? '
|
|
1847
|
+
class: `${vertical ? 'bw_btn_group_vertical' : 'bw_btn_group'} ${size ? 'bw_btn_group_' + size : ''} ${className}`.trim(),
|
|
2124
1848
|
role: 'group'
|
|
2125
1849
|
},
|
|
2126
1850
|
c: children
|
|
@@ -2160,42 +1884,42 @@ export function makeAccordion(props = {}) {
|
|
|
2160
1884
|
|
|
2161
1885
|
return {
|
|
2162
1886
|
t: 'div',
|
|
2163
|
-
a: { class: `
|
|
1887
|
+
a: { class: `bw_accordion ${className}`.trim() },
|
|
2164
1888
|
c: items.map(function(item, index) {
|
|
2165
1889
|
return {
|
|
2166
1890
|
t: 'div',
|
|
2167
|
-
a: { class: '
|
|
1891
|
+
a: { class: 'bw_accordion_item' },
|
|
2168
1892
|
c: [
|
|
2169
1893
|
{
|
|
2170
1894
|
t: 'h2',
|
|
2171
|
-
a: { class: '
|
|
1895
|
+
a: { class: 'bw_accordion_header' },
|
|
2172
1896
|
c: {
|
|
2173
1897
|
t: 'button',
|
|
2174
1898
|
a: {
|
|
2175
|
-
class: `
|
|
1899
|
+
class: `bw_accordion_button ${item.open ? '' : 'bw_collapsed'}`.trim(),
|
|
2176
1900
|
type: 'button',
|
|
2177
1901
|
'aria-expanded': item.open ? 'true' : 'false',
|
|
2178
1902
|
'data-accordion-index': index,
|
|
2179
1903
|
onclick: function(e) {
|
|
2180
|
-
var btn = e.target.closest('.
|
|
2181
|
-
var accordionEl = btn.closest('.
|
|
2182
|
-
var accordionItem = btn.closest('.
|
|
2183
|
-
var collapse = accordionItem.querySelector('.
|
|
2184
|
-
var isOpen = collapse.classList.contains('
|
|
1904
|
+
var btn = e.target.closest('.bw_accordion_button');
|
|
1905
|
+
var accordionEl = btn.closest('.bw_accordion');
|
|
1906
|
+
var accordionItem = btn.closest('.bw_accordion_item');
|
|
1907
|
+
var collapse = accordionItem.querySelector('.bw_accordion_collapse');
|
|
1908
|
+
var isOpen = collapse.classList.contains('bw_collapse_show');
|
|
2185
1909
|
|
|
2186
1910
|
if (!multiOpen) {
|
|
2187
1911
|
// Animate-close all other open siblings
|
|
2188
|
-
var allItems = accordionEl.querySelectorAll('.
|
|
1912
|
+
var allItems = accordionEl.querySelectorAll('.bw_accordion_item');
|
|
2189
1913
|
for (var j = 0; j < allItems.length; j++) {
|
|
2190
1914
|
if (allItems[j] === accordionItem) continue;
|
|
2191
|
-
var sibCollapse = allItems[j].querySelector('.
|
|
2192
|
-
var sibBtn = allItems[j].querySelector('.
|
|
2193
|
-
if (sibCollapse.classList.contains('
|
|
1915
|
+
var sibCollapse = allItems[j].querySelector('.bw_accordion_collapse');
|
|
1916
|
+
var sibBtn = allItems[j].querySelector('.bw_accordion_button');
|
|
1917
|
+
if (sibCollapse.classList.contains('bw_collapse_show')) {
|
|
2194
1918
|
sibCollapse.style.maxHeight = sibCollapse.scrollHeight + 'px';
|
|
2195
1919
|
sibCollapse.offsetHeight; // force reflow
|
|
2196
1920
|
sibCollapse.style.maxHeight = '0px';
|
|
2197
|
-
sibCollapse.classList.remove('
|
|
2198
|
-
sibBtn.classList.add('
|
|
1921
|
+
sibCollapse.classList.remove('bw_collapse_show');
|
|
1922
|
+
sibBtn.classList.add('bw_collapsed');
|
|
2199
1923
|
sibBtn.setAttribute('aria-expanded', 'false');
|
|
2200
1924
|
}
|
|
2201
1925
|
}
|
|
@@ -2206,20 +1930,20 @@ export function makeAccordion(props = {}) {
|
|
|
2206
1930
|
collapse.style.maxHeight = collapse.scrollHeight + 'px';
|
|
2207
1931
|
collapse.offsetHeight; // force reflow
|
|
2208
1932
|
collapse.style.maxHeight = '0px';
|
|
2209
|
-
collapse.classList.remove('
|
|
2210
|
-
btn.classList.add('
|
|
1933
|
+
collapse.classList.remove('bw_collapse_show');
|
|
1934
|
+
btn.classList.add('bw_collapsed');
|
|
2211
1935
|
btn.setAttribute('aria-expanded', 'false');
|
|
2212
1936
|
} else {
|
|
2213
1937
|
// Animate open
|
|
2214
|
-
collapse.classList.add('
|
|
1938
|
+
collapse.classList.add('bw_collapse_show');
|
|
2215
1939
|
collapse.style.maxHeight = '0px';
|
|
2216
1940
|
collapse.offsetHeight; // force reflow
|
|
2217
1941
|
collapse.style.maxHeight = collapse.scrollHeight + 'px';
|
|
2218
|
-
btn.classList.remove('
|
|
1942
|
+
btn.classList.remove('bw_collapsed');
|
|
2219
1943
|
btn.setAttribute('aria-expanded', 'true');
|
|
2220
1944
|
// After transition, allow dynamic content sizing
|
|
2221
1945
|
var onEnd = function(ev) {
|
|
2222
|
-
if (ev.propertyName === 'max-height' && collapse.classList.contains('
|
|
1946
|
+
if (ev.propertyName === 'max-height' && collapse.classList.contains('bw_collapse_show')) {
|
|
2223
1947
|
collapse.style.maxHeight = 'none';
|
|
2224
1948
|
}
|
|
2225
1949
|
collapse.removeEventListener('transitionend', onEnd);
|
|
@@ -2233,10 +1957,10 @@ export function makeAccordion(props = {}) {
|
|
|
2233
1957
|
},
|
|
2234
1958
|
{
|
|
2235
1959
|
t: 'div',
|
|
2236
|
-
a: { class: `
|
|
1960
|
+
a: { class: `bw_accordion_collapse ${item.open ? 'bw_collapse_show' : ''}`.trim() },
|
|
2237
1961
|
c: {
|
|
2238
1962
|
t: 'div',
|
|
2239
|
-
a: { class: '
|
|
1963
|
+
a: { class: 'bw_accordion_body' },
|
|
2240
1964
|
c: item.content
|
|
2241
1965
|
},
|
|
2242
1966
|
o: item.open ? {
|
|
@@ -2255,60 +1979,8 @@ export function makeAccordion(props = {}) {
|
|
|
2255
1979
|
};
|
|
2256
1980
|
}
|
|
2257
1981
|
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
*
|
|
2261
|
-
* Provides `.show()`, `.hide()`, `.toggle()`, and `.destroy()` methods
|
|
2262
|
-
* for controlling the modal programmatically.
|
|
2263
|
-
*
|
|
2264
|
-
* @category Component Handles
|
|
2265
|
-
*/
|
|
2266
|
-
export class ModalHandle {
|
|
2267
|
-
/**
|
|
2268
|
-
* @param {Element} element - The modal backdrop DOM element
|
|
2269
|
-
* @param {Object} taco - The original TACO object
|
|
2270
|
-
*/
|
|
2271
|
-
constructor(element, taco) {
|
|
2272
|
-
this.element = element;
|
|
2273
|
-
this._taco = taco;
|
|
2274
|
-
this._escHandler = null;
|
|
2275
|
-
}
|
|
2276
|
-
|
|
2277
|
-
/** Show the modal */
|
|
2278
|
-
show() {
|
|
2279
|
-
this.element.classList.add('bw-modal-show');
|
|
2280
|
-
document.body.style.overflow = 'hidden';
|
|
2281
|
-
return this;
|
|
2282
|
-
}
|
|
2283
|
-
|
|
2284
|
-
/** Hide the modal */
|
|
2285
|
-
hide() {
|
|
2286
|
-
this.element.classList.remove('bw-modal-show');
|
|
2287
|
-
document.body.style.overflow = '';
|
|
2288
|
-
return this;
|
|
2289
|
-
}
|
|
2290
|
-
|
|
2291
|
-
/** Toggle modal visibility */
|
|
2292
|
-
toggle() {
|
|
2293
|
-
if (this.element.classList.contains('bw-modal-show')) {
|
|
2294
|
-
this.hide();
|
|
2295
|
-
} else {
|
|
2296
|
-
this.show();
|
|
2297
|
-
}
|
|
2298
|
-
return this;
|
|
2299
|
-
}
|
|
2300
|
-
|
|
2301
|
-
/** Remove the modal from DOM and clean up */
|
|
2302
|
-
destroy() {
|
|
2303
|
-
this.hide();
|
|
2304
|
-
if (this._escHandler) {
|
|
2305
|
-
document.removeEventListener('keydown', this._escHandler);
|
|
2306
|
-
}
|
|
2307
|
-
if (this.element.parentNode) {
|
|
2308
|
-
this.element.parentNode.removeChild(this.element);
|
|
2309
|
-
}
|
|
2310
|
-
}
|
|
2311
|
-
}
|
|
1982
|
+
// ModalHandle removed in v2.0.15 — superseded by ComponentHandle.
|
|
1983
|
+
// See dev/dead-code-elimination-v2.0.15.md for recovery.
|
|
2312
1984
|
|
|
2313
1985
|
/**
|
|
2314
1986
|
* Create a modal dialog overlay
|
|
@@ -2342,9 +2014,9 @@ export function makeModal(props = {}) {
|
|
|
2342
2014
|
} = props;
|
|
2343
2015
|
|
|
2344
2016
|
function closeModal(el) {
|
|
2345
|
-
var backdrop = el.closest('.
|
|
2017
|
+
var backdrop = el.closest('.bw_modal');
|
|
2346
2018
|
if (backdrop) {
|
|
2347
|
-
backdrop.classList.remove('
|
|
2019
|
+
backdrop.classList.remove('bw_modal_show');
|
|
2348
2020
|
document.body.style.overflow = '';
|
|
2349
2021
|
}
|
|
2350
2022
|
if (onClose) onClose();
|
|
@@ -2352,24 +2024,24 @@ export function makeModal(props = {}) {
|
|
|
2352
2024
|
|
|
2353
2025
|
return {
|
|
2354
2026
|
t: 'div',
|
|
2355
|
-
a: { class: `
|
|
2027
|
+
a: { class: `bw_modal ${className}`.trim() },
|
|
2356
2028
|
c: {
|
|
2357
2029
|
t: 'div',
|
|
2358
|
-
a: { class: `
|
|
2030
|
+
a: { class: `bw_modal_dialog ${size ? 'bw_modal_' + size : ''}`.trim() },
|
|
2359
2031
|
c: {
|
|
2360
2032
|
t: 'div',
|
|
2361
|
-
a: { class: '
|
|
2033
|
+
a: { class: 'bw_modal_content' },
|
|
2362
2034
|
c: [
|
|
2363
2035
|
(title || closeButton) && {
|
|
2364
2036
|
t: 'div',
|
|
2365
|
-
a: { class: '
|
|
2037
|
+
a: { class: 'bw_modal_header' },
|
|
2366
2038
|
c: [
|
|
2367
|
-
title && { t: 'h5', a: { class: '
|
|
2039
|
+
title && { t: 'h5', a: { class: 'bw_modal_title' }, c: title },
|
|
2368
2040
|
closeButton && {
|
|
2369
2041
|
t: 'button',
|
|
2370
2042
|
a: {
|
|
2371
2043
|
type: 'button',
|
|
2372
|
-
class: '
|
|
2044
|
+
class: 'bw_close',
|
|
2373
2045
|
'aria-label': 'Close',
|
|
2374
2046
|
onclick: function(e) { closeModal(e.target); }
|
|
2375
2047
|
},
|
|
@@ -2379,12 +2051,12 @@ export function makeModal(props = {}) {
|
|
|
2379
2051
|
},
|
|
2380
2052
|
content && {
|
|
2381
2053
|
t: 'div',
|
|
2382
|
-
a: { class: '
|
|
2054
|
+
a: { class: 'bw_modal_body' },
|
|
2383
2055
|
c: content
|
|
2384
2056
|
},
|
|
2385
2057
|
footer && {
|
|
2386
2058
|
t: 'div',
|
|
2387
|
-
a: { class: '
|
|
2059
|
+
a: { class: 'bw_modal_footer' },
|
|
2388
2060
|
c: footer
|
|
2389
2061
|
}
|
|
2390
2062
|
].filter(Boolean)
|
|
@@ -2399,7 +2071,7 @@ export function makeModal(props = {}) {
|
|
|
2399
2071
|
});
|
|
2400
2072
|
// Escape key to close
|
|
2401
2073
|
var escHandler = function(e) {
|
|
2402
|
-
if (e.key === 'Escape' && el.classList.contains('
|
|
2074
|
+
if (e.key === 'Escape' && el.classList.contains('bw_modal_show')) {
|
|
2403
2075
|
closeModal(el);
|
|
2404
2076
|
}
|
|
2405
2077
|
};
|
|
@@ -2450,26 +2122,26 @@ export function makeToast(props = {}) {
|
|
|
2450
2122
|
return {
|
|
2451
2123
|
t: 'div',
|
|
2452
2124
|
a: {
|
|
2453
|
-
class: `
|
|
2125
|
+
class: `bw_toast ${variantClass(variant)} ${className}`.trim(),
|
|
2454
2126
|
role: 'alert',
|
|
2455
2127
|
'data-position': position
|
|
2456
2128
|
},
|
|
2457
2129
|
c: [
|
|
2458
2130
|
(title) && {
|
|
2459
2131
|
t: 'div',
|
|
2460
|
-
a: { class: '
|
|
2132
|
+
a: { class: 'bw_toast_header' },
|
|
2461
2133
|
c: [
|
|
2462
2134
|
{ t: 'strong', c: title },
|
|
2463
2135
|
{
|
|
2464
2136
|
t: 'button',
|
|
2465
2137
|
a: {
|
|
2466
2138
|
type: 'button',
|
|
2467
|
-
class: '
|
|
2139
|
+
class: 'bw_close',
|
|
2468
2140
|
'aria-label': 'Close',
|
|
2469
2141
|
onclick: function(e) {
|
|
2470
|
-
var toast = e.target.closest('.
|
|
2142
|
+
var toast = e.target.closest('.bw_toast');
|
|
2471
2143
|
if (toast) {
|
|
2472
|
-
toast.classList.add('
|
|
2144
|
+
toast.classList.add('bw_toast_hiding');
|
|
2473
2145
|
setTimeout(function() { if (toast.parentNode) toast.parentNode.removeChild(toast); }, 300);
|
|
2474
2146
|
}
|
|
2475
2147
|
}
|
|
@@ -2480,7 +2152,7 @@ export function makeToast(props = {}) {
|
|
|
2480
2152
|
},
|
|
2481
2153
|
content && {
|
|
2482
2154
|
t: 'div',
|
|
2483
|
-
a: { class: '
|
|
2155
|
+
a: { class: 'bw_toast_body' },
|
|
2484
2156
|
c: content
|
|
2485
2157
|
}
|
|
2486
2158
|
].filter(Boolean),
|
|
@@ -2489,12 +2161,12 @@ export function makeToast(props = {}) {
|
|
|
2489
2161
|
mounted: function(el) {
|
|
2490
2162
|
// Trigger show animation
|
|
2491
2163
|
requestAnimationFrame(function() {
|
|
2492
|
-
el.classList.add('
|
|
2164
|
+
el.classList.add('bw_toast_show');
|
|
2493
2165
|
});
|
|
2494
2166
|
// Auto-dismiss
|
|
2495
2167
|
if (autoDismiss) {
|
|
2496
2168
|
setTimeout(function() {
|
|
2497
|
-
el.classList.add('
|
|
2169
|
+
el.classList.add('bw_toast_hiding');
|
|
2498
2170
|
setTimeout(function() { if (el.parentNode) el.parentNode.removeChild(el); }, 300);
|
|
2499
2171
|
}, delay);
|
|
2500
2172
|
}
|
|
@@ -2547,12 +2219,12 @@ export function makeDropdown(props = {}) {
|
|
|
2547
2219
|
triggerTaco = {
|
|
2548
2220
|
t: 'button',
|
|
2549
2221
|
a: {
|
|
2550
|
-
class: `
|
|
2222
|
+
class: `bw_btn ${variantClass(variant)} bw_dropdown_toggle`,
|
|
2551
2223
|
type: 'button',
|
|
2552
2224
|
onclick: function(e) {
|
|
2553
|
-
var dropdown = e.target.closest('.
|
|
2554
|
-
var menu = dropdown.querySelector('.
|
|
2555
|
-
menu.classList.toggle('
|
|
2225
|
+
var dropdown = e.target.closest('.bw_dropdown');
|
|
2226
|
+
var menu = dropdown.querySelector('.bw_dropdown_menu');
|
|
2227
|
+
menu.classList.toggle('bw_dropdown_show');
|
|
2556
2228
|
}
|
|
2557
2229
|
},
|
|
2558
2230
|
c: trigger || 'Dropdown'
|
|
@@ -2563,26 +2235,26 @@ export function makeDropdown(props = {}) {
|
|
|
2563
2235
|
|
|
2564
2236
|
return {
|
|
2565
2237
|
t: 'div',
|
|
2566
|
-
a: { class: `
|
|
2238
|
+
a: { class: `bw_dropdown ${className}`.trim() },
|
|
2567
2239
|
c: [
|
|
2568
2240
|
triggerTaco,
|
|
2569
2241
|
{
|
|
2570
2242
|
t: 'div',
|
|
2571
|
-
a: { class: `
|
|
2243
|
+
a: { class: `bw_dropdown_menu ${align === 'end' ? 'bw_dropdown_menu_end' : ''}`.trim() },
|
|
2572
2244
|
c: items.map(function(item) {
|
|
2573
2245
|
if (item.divider) {
|
|
2574
|
-
return { t: 'hr', a: { class: '
|
|
2246
|
+
return { t: 'hr', a: { class: 'bw_dropdown_divider' } };
|
|
2575
2247
|
}
|
|
2576
2248
|
return {
|
|
2577
2249
|
t: 'a',
|
|
2578
2250
|
a: {
|
|
2579
|
-
class: `
|
|
2251
|
+
class: `bw_dropdown_item ${item.disabled ? 'disabled' : ''}`.trim(),
|
|
2580
2252
|
href: item.href || '#',
|
|
2581
2253
|
onclick: item.disabled ? undefined : function(e) {
|
|
2582
2254
|
if (!item.href) e.preventDefault();
|
|
2583
|
-
var dropdown = e.target.closest('.
|
|
2584
|
-
var menu = dropdown.querySelector('.
|
|
2585
|
-
menu.classList.remove('
|
|
2255
|
+
var dropdown = e.target.closest('.bw_dropdown');
|
|
2256
|
+
var menu = dropdown.querySelector('.bw_dropdown_menu');
|
|
2257
|
+
menu.classList.remove('bw_dropdown_show');
|
|
2586
2258
|
if (item.onclick) item.onclick(e);
|
|
2587
2259
|
}
|
|
2588
2260
|
},
|
|
@@ -2597,8 +2269,8 @@ export function makeDropdown(props = {}) {
|
|
|
2597
2269
|
// Click outside to close
|
|
2598
2270
|
var outsideHandler = function(e) {
|
|
2599
2271
|
if (!el.contains(e.target)) {
|
|
2600
|
-
var menu = el.querySelector('.
|
|
2601
|
-
if (menu) menu.classList.remove('
|
|
2272
|
+
var menu = el.querySelector('.bw_dropdown_menu');
|
|
2273
|
+
if (menu) menu.classList.remove('bw_dropdown_show');
|
|
2602
2274
|
}
|
|
2603
2275
|
};
|
|
2604
2276
|
document.addEventListener('click', outsideHandler);
|
|
@@ -2645,13 +2317,13 @@ export function makeSwitch(props = {}) {
|
|
|
2645
2317
|
|
|
2646
2318
|
return {
|
|
2647
2319
|
t: 'div',
|
|
2648
|
-
a: { class: `
|
|
2320
|
+
a: { class: `bw_form_check bw_form_switch ${className}`.trim() },
|
|
2649
2321
|
c: [
|
|
2650
2322
|
{
|
|
2651
2323
|
t: 'input',
|
|
2652
2324
|
a: {
|
|
2653
2325
|
type: 'checkbox',
|
|
2654
|
-
class: '
|
|
2326
|
+
class: 'bw_form_check_input bw_switch_input',
|
|
2655
2327
|
role: 'switch',
|
|
2656
2328
|
checked,
|
|
2657
2329
|
id,
|
|
@@ -2662,7 +2334,7 @@ export function makeSwitch(props = {}) {
|
|
|
2662
2334
|
},
|
|
2663
2335
|
label && {
|
|
2664
2336
|
t: 'label',
|
|
2665
|
-
a: { class: '
|
|
2337
|
+
a: { class: 'bw_form_check_label', for: id },
|
|
2666
2338
|
c: label
|
|
2667
2339
|
}
|
|
2668
2340
|
].filter(Boolean)
|
|
@@ -2697,7 +2369,7 @@ export function makeSkeleton(props = {}) {
|
|
|
2697
2369
|
return {
|
|
2698
2370
|
t: 'div',
|
|
2699
2371
|
a: {
|
|
2700
|
-
class: `
|
|
2372
|
+
class: `bw_skeleton bw_skeleton_circle ${className}`.trim(),
|
|
2701
2373
|
style: { width: circleSize, height: circleSize }
|
|
2702
2374
|
}
|
|
2703
2375
|
};
|
|
@@ -2707,7 +2379,7 @@ export function makeSkeleton(props = {}) {
|
|
|
2707
2379
|
return {
|
|
2708
2380
|
t: 'div',
|
|
2709
2381
|
a: {
|
|
2710
|
-
class: `
|
|
2382
|
+
class: `bw_skeleton bw_skeleton_rect ${className}`.trim(),
|
|
2711
2383
|
style: {
|
|
2712
2384
|
width: width || '100%',
|
|
2713
2385
|
height: height || '120px'
|
|
@@ -2721,7 +2393,7 @@ export function makeSkeleton(props = {}) {
|
|
|
2721
2393
|
return {
|
|
2722
2394
|
t: 'div',
|
|
2723
2395
|
a: {
|
|
2724
|
-
class: `
|
|
2396
|
+
class: `bw_skeleton bw_skeleton_text ${className}`.trim(),
|
|
2725
2397
|
style: {
|
|
2726
2398
|
width: width || '100%',
|
|
2727
2399
|
height: height || '1em'
|
|
@@ -2735,7 +2407,7 @@ export function makeSkeleton(props = {}) {
|
|
|
2735
2407
|
lines.push({
|
|
2736
2408
|
t: 'div',
|
|
2737
2409
|
a: {
|
|
2738
|
-
class: '
|
|
2410
|
+
class: 'bw_skeleton bw_skeleton_text',
|
|
2739
2411
|
style: {
|
|
2740
2412
|
width: i === count - 1 ? '75%' : (width || '100%'),
|
|
2741
2413
|
height: height || '1em'
|
|
@@ -2746,7 +2418,7 @@ export function makeSkeleton(props = {}) {
|
|
|
2746
2418
|
|
|
2747
2419
|
return {
|
|
2748
2420
|
t: 'div',
|
|
2749
|
-
a: { class: `
|
|
2421
|
+
a: { class: `bw_skeleton_group ${className}`.trim() },
|
|
2750
2422
|
c: lines
|
|
2751
2423
|
};
|
|
2752
2424
|
}
|
|
@@ -2781,7 +2453,7 @@ export function makeAvatar(props = {}) {
|
|
|
2781
2453
|
return {
|
|
2782
2454
|
t: 'img',
|
|
2783
2455
|
a: {
|
|
2784
|
-
class: `
|
|
2456
|
+
class: `bw_avatar bw_avatar_${size} ${className}`.trim(),
|
|
2785
2457
|
src: src,
|
|
2786
2458
|
alt: alt
|
|
2787
2459
|
}
|
|
@@ -2791,7 +2463,7 @@ export function makeAvatar(props = {}) {
|
|
|
2791
2463
|
return {
|
|
2792
2464
|
t: 'div',
|
|
2793
2465
|
a: {
|
|
2794
|
-
class: `
|
|
2466
|
+
class: `bw_avatar bw_avatar_${size} ${variantClass(variant)} ${className}`.trim()
|
|
2795
2467
|
},
|
|
2796
2468
|
c: initials || ''
|
|
2797
2469
|
};
|
|
@@ -2840,14 +2512,14 @@ export function makeCarousel(props = {}) {
|
|
|
2840
2512
|
|
|
2841
2513
|
// Shared navigation logic
|
|
2842
2514
|
function goToSlide(carouselEl, index) {
|
|
2843
|
-
var total = carouselEl.querySelectorAll('.
|
|
2515
|
+
var total = carouselEl.querySelectorAll('.bw_carousel_slide').length;
|
|
2844
2516
|
if (index < 0) index = total - 1;
|
|
2845
2517
|
if (index >= total) index = 0;
|
|
2846
2518
|
carouselEl.setAttribute('data-carousel-index', index);
|
|
2847
|
-
var track = carouselEl.querySelector('.
|
|
2519
|
+
var track = carouselEl.querySelector('.bw_carousel_track');
|
|
2848
2520
|
track.style.transform = 'translateX(-' + (index * 100) + '%)';
|
|
2849
2521
|
// Update indicators
|
|
2850
|
-
var indicators = carouselEl.querySelectorAll('.
|
|
2522
|
+
var indicators = carouselEl.querySelectorAll('.bw_carousel_indicator');
|
|
2851
2523
|
for (var i = 0; i < indicators.length; i++) {
|
|
2852
2524
|
if (i === index) {
|
|
2853
2525
|
indicators[i].classList.add('active');
|
|
@@ -2866,14 +2538,14 @@ export function makeCarousel(props = {}) {
|
|
|
2866
2538
|
item.content,
|
|
2867
2539
|
item.caption && {
|
|
2868
2540
|
t: 'div',
|
|
2869
|
-
a: { class: '
|
|
2541
|
+
a: { class: 'bw_carousel_caption' },
|
|
2870
2542
|
c: item.caption
|
|
2871
2543
|
}
|
|
2872
2544
|
].filter(Boolean);
|
|
2873
2545
|
|
|
2874
2546
|
return {
|
|
2875
2547
|
t: 'div',
|
|
2876
|
-
a: { class: '
|
|
2548
|
+
a: { class: 'bw_carousel_slide' },
|
|
2877
2549
|
c: slideContent.length === 1 ? slideContent[0] : slideContent
|
|
2878
2550
|
};
|
|
2879
2551
|
});
|
|
@@ -2883,7 +2555,7 @@ export function makeCarousel(props = {}) {
|
|
|
2883
2555
|
{
|
|
2884
2556
|
t: 'div',
|
|
2885
2557
|
a: {
|
|
2886
|
-
class: '
|
|
2558
|
+
class: 'bw_carousel_track',
|
|
2887
2559
|
style: 'transform: translateX(-' + (startIndex * 100) + '%)'
|
|
2888
2560
|
},
|
|
2889
2561
|
c: slides
|
|
@@ -2895,11 +2567,11 @@ export function makeCarousel(props = {}) {
|
|
|
2895
2567
|
children.push({
|
|
2896
2568
|
t: 'button',
|
|
2897
2569
|
a: {
|
|
2898
|
-
class: '
|
|
2570
|
+
class: 'bw_carousel_control bw_carousel_control_prev',
|
|
2899
2571
|
type: 'button',
|
|
2900
2572
|
'aria-label': 'Previous slide',
|
|
2901
2573
|
onclick: function(e) {
|
|
2902
|
-
var carousel = e.target.closest('.
|
|
2574
|
+
var carousel = e.target.closest('.bw_carousel');
|
|
2903
2575
|
var idx = parseInt(carousel.getAttribute('data-carousel-index') || '0');
|
|
2904
2576
|
goToSlide(carousel, idx - 1);
|
|
2905
2577
|
}
|
|
@@ -2909,11 +2581,11 @@ export function makeCarousel(props = {}) {
|
|
|
2909
2581
|
children.push({
|
|
2910
2582
|
t: 'button',
|
|
2911
2583
|
a: {
|
|
2912
|
-
class: '
|
|
2584
|
+
class: 'bw_carousel_control bw_carousel_control_next',
|
|
2913
2585
|
type: 'button',
|
|
2914
2586
|
'aria-label': 'Next slide',
|
|
2915
2587
|
onclick: function(e) {
|
|
2916
|
-
var carousel = e.target.closest('.
|
|
2588
|
+
var carousel = e.target.closest('.bw_carousel');
|
|
2917
2589
|
var idx = parseInt(carousel.getAttribute('data-carousel-index') || '0');
|
|
2918
2590
|
goToSlide(carousel, idx + 1);
|
|
2919
2591
|
}
|
|
@@ -2926,17 +2598,17 @@ export function makeCarousel(props = {}) {
|
|
|
2926
2598
|
if (showIndicators && items.length > 1) {
|
|
2927
2599
|
children.push({
|
|
2928
2600
|
t: 'div',
|
|
2929
|
-
a: { class: '
|
|
2601
|
+
a: { class: 'bw_carousel_indicators' },
|
|
2930
2602
|
c: items.map(function(_, i) {
|
|
2931
2603
|
return {
|
|
2932
2604
|
t: 'button',
|
|
2933
2605
|
a: {
|
|
2934
|
-
class: '
|
|
2606
|
+
class: 'bw_carousel_indicator' + (i === startIndex ? ' active' : ''),
|
|
2935
2607
|
type: 'button',
|
|
2936
2608
|
'aria-label': 'Go to slide ' + (i + 1),
|
|
2937
2609
|
'data-slide-index': i,
|
|
2938
2610
|
onclick: function(e) {
|
|
2939
|
-
var carousel = e.target.closest('.
|
|
2611
|
+
var carousel = e.target.closest('.bw_carousel');
|
|
2940
2612
|
var idx = parseInt(e.target.getAttribute('data-slide-index'));
|
|
2941
2613
|
goToSlide(carousel, idx);
|
|
2942
2614
|
}
|
|
@@ -2949,7 +2621,7 @@ export function makeCarousel(props = {}) {
|
|
|
2949
2621
|
return {
|
|
2950
2622
|
t: 'div',
|
|
2951
2623
|
a: {
|
|
2952
|
-
class: ('
|
|
2624
|
+
class: ('bw_carousel ' + className).trim(),
|
|
2953
2625
|
style: 'height: ' + height,
|
|
2954
2626
|
tabindex: '0',
|
|
2955
2627
|
'aria-roledescription': 'carousel',
|
|
@@ -3057,8 +2729,8 @@ export function makeStatCard(props = {}) {
|
|
|
3057
2729
|
}
|
|
3058
2730
|
|
|
3059
2731
|
var classes = [
|
|
3060
|
-
'
|
|
3061
|
-
variant
|
|
2732
|
+
'bw_stat_card',
|
|
2733
|
+
variantClass(variant),
|
|
3062
2734
|
className
|
|
3063
2735
|
].filter(Boolean).join(' ').trim();
|
|
3064
2736
|
|
|
@@ -3067,21 +2739,21 @@ export function makeStatCard(props = {}) {
|
|
|
3067
2739
|
if (icon) {
|
|
3068
2740
|
children.push({
|
|
3069
2741
|
t: 'div',
|
|
3070
|
-
a: { class: '
|
|
2742
|
+
a: { class: 'bw_stat_icon' },
|
|
3071
2743
|
c: icon
|
|
3072
2744
|
});
|
|
3073
2745
|
}
|
|
3074
2746
|
|
|
3075
2747
|
children.push({
|
|
3076
2748
|
t: 'div',
|
|
3077
|
-
a: { class: '
|
|
2749
|
+
a: { class: 'bw_stat_value' },
|
|
3078
2750
|
c: formatValue(value, format)
|
|
3079
2751
|
});
|
|
3080
2752
|
|
|
3081
2753
|
if (label) {
|
|
3082
2754
|
children.push({
|
|
3083
2755
|
t: 'div',
|
|
3084
|
-
a: { class: '
|
|
2756
|
+
a: { class: 'bw_stat_label' },
|
|
3085
2757
|
c: label
|
|
3086
2758
|
});
|
|
3087
2759
|
}
|
|
@@ -3090,7 +2762,7 @@ export function makeStatCard(props = {}) {
|
|
|
3090
2762
|
children.push({
|
|
3091
2763
|
t: 'div',
|
|
3092
2764
|
a: {
|
|
3093
|
-
class: '
|
|
2765
|
+
class: 'bw_stat_change ' + (change >= 0 ? 'bw_stat_change_up' : 'bw_stat_change_down')
|
|
3094
2766
|
},
|
|
3095
2767
|
c: (change >= 0 ? '\u2191 +' : '\u2193 ') + change + '%'
|
|
3096
2768
|
});
|
|
@@ -3139,13 +2811,13 @@ export function makeTooltip(props = {}) {
|
|
|
3139
2811
|
|
|
3140
2812
|
return {
|
|
3141
2813
|
t: 'span',
|
|
3142
|
-
a: { class: ('
|
|
2814
|
+
a: { class: ('bw_tooltip_wrapper ' + className).trim() },
|
|
3143
2815
|
c: [
|
|
3144
2816
|
content,
|
|
3145
2817
|
{
|
|
3146
2818
|
t: 'span',
|
|
3147
2819
|
a: {
|
|
3148
|
-
class: '
|
|
2820
|
+
class: 'bw_tooltip bw_tooltip_' + placement,
|
|
3149
2821
|
role: 'tooltip'
|
|
3150
2822
|
},
|
|
3151
2823
|
c: text
|
|
@@ -3154,18 +2826,18 @@ export function makeTooltip(props = {}) {
|
|
|
3154
2826
|
o: {
|
|
3155
2827
|
type: 'tooltip',
|
|
3156
2828
|
mounted: function(el) {
|
|
3157
|
-
var tip = el.querySelector('.
|
|
2829
|
+
var tip = el.querySelector('.bw_tooltip');
|
|
3158
2830
|
el.addEventListener('mouseenter', function() {
|
|
3159
|
-
tip.classList.add('
|
|
2831
|
+
tip.classList.add('bw_tooltip_show');
|
|
3160
2832
|
});
|
|
3161
2833
|
el.addEventListener('mouseleave', function() {
|
|
3162
|
-
tip.classList.remove('
|
|
2834
|
+
tip.classList.remove('bw_tooltip_show');
|
|
3163
2835
|
});
|
|
3164
2836
|
el.addEventListener('focusin', function() {
|
|
3165
|
-
tip.classList.add('
|
|
2837
|
+
tip.classList.add('bw_tooltip_show');
|
|
3166
2838
|
});
|
|
3167
2839
|
el.addEventListener('focusout', function() {
|
|
3168
|
-
tip.classList.remove('
|
|
2840
|
+
tip.classList.remove('bw_tooltip_show');
|
|
3169
2841
|
});
|
|
3170
2842
|
}
|
|
3171
2843
|
}
|
|
@@ -3206,28 +2878,28 @@ export function makePopover(props = {}) {
|
|
|
3206
2878
|
var popoverContent = [
|
|
3207
2879
|
title && {
|
|
3208
2880
|
t: 'div',
|
|
3209
|
-
a: { class: '
|
|
2881
|
+
a: { class: 'bw_popover_header' },
|
|
3210
2882
|
c: title
|
|
3211
2883
|
},
|
|
3212
2884
|
content && {
|
|
3213
2885
|
t: 'div',
|
|
3214
|
-
a: { class: '
|
|
2886
|
+
a: { class: 'bw_popover_body' },
|
|
3215
2887
|
c: content
|
|
3216
2888
|
}
|
|
3217
2889
|
].filter(Boolean);
|
|
3218
2890
|
|
|
3219
2891
|
return {
|
|
3220
2892
|
t: 'span',
|
|
3221
|
-
a: { class: ('
|
|
2893
|
+
a: { class: ('bw_popover_wrapper ' + className).trim() },
|
|
3222
2894
|
c: [
|
|
3223
2895
|
{
|
|
3224
2896
|
t: 'span',
|
|
3225
2897
|
a: {
|
|
3226
|
-
class: '
|
|
2898
|
+
class: 'bw_popover_trigger',
|
|
3227
2899
|
onclick: function(e) {
|
|
3228
|
-
var wrapper = e.target.closest('.
|
|
3229
|
-
var pop = wrapper.querySelector('.
|
|
3230
|
-
pop.classList.toggle('
|
|
2900
|
+
var wrapper = e.target.closest('.bw_popover_wrapper');
|
|
2901
|
+
var pop = wrapper.querySelector('.bw_popover');
|
|
2902
|
+
pop.classList.toggle('bw_popover_show');
|
|
3231
2903
|
}
|
|
3232
2904
|
},
|
|
3233
2905
|
c: trigger
|
|
@@ -3235,7 +2907,7 @@ export function makePopover(props = {}) {
|
|
|
3235
2907
|
{
|
|
3236
2908
|
t: 'div',
|
|
3237
2909
|
a: {
|
|
3238
|
-
class: '
|
|
2910
|
+
class: 'bw_popover bw_popover_' + placement
|
|
3239
2911
|
},
|
|
3240
2912
|
c: popoverContent
|
|
3241
2913
|
}
|
|
@@ -3246,8 +2918,8 @@ export function makePopover(props = {}) {
|
|
|
3246
2918
|
// Click outside to close
|
|
3247
2919
|
var outsideHandler = function(e) {
|
|
3248
2920
|
if (!el.contains(e.target)) {
|
|
3249
|
-
var pop = el.querySelector('.
|
|
3250
|
-
if (pop) pop.classList.remove('
|
|
2921
|
+
var pop = el.querySelector('.bw_popover');
|
|
2922
|
+
if (pop) pop.classList.remove('bw_popover_show');
|
|
3251
2923
|
}
|
|
3252
2924
|
};
|
|
3253
2925
|
document.addEventListener('click', outsideHandler);
|
|
@@ -3302,13 +2974,13 @@ export function makeSearchInput(props = {}) {
|
|
|
3302
2974
|
|
|
3303
2975
|
return {
|
|
3304
2976
|
t: 'div',
|
|
3305
|
-
a: { class: ('
|
|
2977
|
+
a: { class: ('bw_search_input ' + className).trim() },
|
|
3306
2978
|
c: [
|
|
3307
2979
|
{
|
|
3308
2980
|
t: 'input',
|
|
3309
2981
|
a: {
|
|
3310
2982
|
type: 'search',
|
|
3311
|
-
class: '
|
|
2983
|
+
class: 'bw_form_control bw_search_field',
|
|
3312
2984
|
placeholder: placeholder,
|
|
3313
2985
|
value: value,
|
|
3314
2986
|
id: id,
|
|
@@ -3320,8 +2992,8 @@ export function makeSearchInput(props = {}) {
|
|
|
3320
2992
|
}
|
|
3321
2993
|
},
|
|
3322
2994
|
oninput: function(e) {
|
|
3323
|
-
var wrapper = e.target.closest('.
|
|
3324
|
-
var clearBtn = wrapper.querySelector('.
|
|
2995
|
+
var wrapper = e.target.closest('.bw_search_input');
|
|
2996
|
+
var clearBtn = wrapper.querySelector('.bw_search_clear');
|
|
3325
2997
|
if (clearBtn) {
|
|
3326
2998
|
clearBtn.style.display = e.target.value ? 'flex' : 'none';
|
|
3327
2999
|
}
|
|
@@ -3333,12 +3005,12 @@ export function makeSearchInput(props = {}) {
|
|
|
3333
3005
|
t: 'button',
|
|
3334
3006
|
a: {
|
|
3335
3007
|
type: 'button',
|
|
3336
|
-
class: '
|
|
3008
|
+
class: 'bw_search_clear',
|
|
3337
3009
|
'aria-label': 'Clear search',
|
|
3338
3010
|
style: value ? undefined : 'display: none',
|
|
3339
3011
|
onclick: function(e) {
|
|
3340
|
-
var wrapper = e.target.closest('.
|
|
3341
|
-
var input = wrapper.querySelector('.
|
|
3012
|
+
var wrapper = e.target.closest('.bw_search_input');
|
|
3013
|
+
var input = wrapper.querySelector('.bw_search_field');
|
|
3342
3014
|
input.value = '';
|
|
3343
3015
|
e.target.style.display = 'none';
|
|
3344
3016
|
input.focus();
|
|
@@ -3405,13 +3077,13 @@ export function makeRange(props = {}) {
|
|
|
3405
3077
|
if (showValue) {
|
|
3406
3078
|
labelContent.push({
|
|
3407
3079
|
t: 'span',
|
|
3408
|
-
a: { class: '
|
|
3080
|
+
a: { class: 'bw_range_value' },
|
|
3409
3081
|
c: '' + value
|
|
3410
3082
|
});
|
|
3411
3083
|
}
|
|
3412
3084
|
children.push({
|
|
3413
3085
|
t: 'div',
|
|
3414
|
-
a: { class: '
|
|
3086
|
+
a: { class: 'bw_range_label' },
|
|
3415
3087
|
c: labelContent
|
|
3416
3088
|
});
|
|
3417
3089
|
}
|
|
@@ -3420,8 +3092,8 @@ export function makeRange(props = {}) {
|
|
|
3420
3092
|
var userOnInput = eventHandlers.oninput;
|
|
3421
3093
|
if (showValue) {
|
|
3422
3094
|
eventHandlers.oninput = function(e) {
|
|
3423
|
-
var wrapper = e.target.closest('.
|
|
3424
|
-
var valDisplay = wrapper.querySelector('.
|
|
3095
|
+
var wrapper = e.target.closest('.bw_range_wrapper');
|
|
3096
|
+
var valDisplay = wrapper.querySelector('.bw_range_value');
|
|
3425
3097
|
if (valDisplay) valDisplay.textContent = e.target.value;
|
|
3426
3098
|
if (userOnInput) userOnInput(e);
|
|
3427
3099
|
};
|
|
@@ -3431,7 +3103,7 @@ export function makeRange(props = {}) {
|
|
|
3431
3103
|
t: 'input',
|
|
3432
3104
|
a: {
|
|
3433
3105
|
type: 'range',
|
|
3434
|
-
class: '
|
|
3106
|
+
class: 'bw_range',
|
|
3435
3107
|
min: min,
|
|
3436
3108
|
max: max,
|
|
3437
3109
|
step: step,
|
|
@@ -3445,7 +3117,7 @@ export function makeRange(props = {}) {
|
|
|
3445
3117
|
|
|
3446
3118
|
return {
|
|
3447
3119
|
t: 'div',
|
|
3448
|
-
a: { class: ('
|
|
3120
|
+
a: { class: ('bw_range_wrapper ' + className).trim() },
|
|
3449
3121
|
c: children,
|
|
3450
3122
|
o: { type: 'range' }
|
|
3451
3123
|
};
|
|
@@ -3488,7 +3160,7 @@ export function makeMediaObject(props = {}) {
|
|
|
3488
3160
|
var imgEl = src ? {
|
|
3489
3161
|
t: 'img',
|
|
3490
3162
|
a: {
|
|
3491
|
-
class: '
|
|
3163
|
+
class: 'bw_media_img',
|
|
3492
3164
|
src: src,
|
|
3493
3165
|
alt: alt,
|
|
3494
3166
|
style: 'width:' + imageSize + ';height:' + imageSize
|
|
@@ -3497,16 +3169,16 @@ export function makeMediaObject(props = {}) {
|
|
|
3497
3169
|
|
|
3498
3170
|
var bodyEl = {
|
|
3499
3171
|
t: 'div',
|
|
3500
|
-
a: { class: '
|
|
3172
|
+
a: { class: 'bw_media_body' },
|
|
3501
3173
|
c: [
|
|
3502
|
-
title && { t: 'h5', a: { class: '
|
|
3174
|
+
title && { t: 'h5', a: { class: 'bw_media_title' }, c: title },
|
|
3503
3175
|
content
|
|
3504
3176
|
].filter(Boolean)
|
|
3505
3177
|
};
|
|
3506
3178
|
|
|
3507
3179
|
return {
|
|
3508
3180
|
t: 'div',
|
|
3509
|
-
a: { class: ('
|
|
3181
|
+
a: { class: ('bw_media ' + (reverse ? 'bw_media_reverse ' : '') + className).trim() },
|
|
3510
3182
|
c: reverse
|
|
3511
3183
|
? [bodyEl, imgEl].filter(Boolean)
|
|
3512
3184
|
: [imgEl, bodyEl].filter(Boolean),
|
|
@@ -3549,19 +3221,19 @@ export function makeFileUpload(props = {}) {
|
|
|
3549
3221
|
return {
|
|
3550
3222
|
t: 'div',
|
|
3551
3223
|
a: {
|
|
3552
|
-
class: ('
|
|
3224
|
+
class: ('bw_file_upload ' + className).trim(),
|
|
3553
3225
|
tabindex: '0',
|
|
3554
3226
|
role: 'button',
|
|
3555
3227
|
'aria-label': text
|
|
3556
3228
|
},
|
|
3557
3229
|
c: [
|
|
3558
|
-
{ t: 'div', a: { class: '
|
|
3559
|
-
{ t: 'div', a: { class: '
|
|
3230
|
+
{ t: 'div', a: { class: 'bw_file_upload_icon' }, c: '\uD83D\uDCC1' },
|
|
3231
|
+
{ t: 'div', a: { class: 'bw_file_upload_text' }, c: text },
|
|
3560
3232
|
{
|
|
3561
3233
|
t: 'input',
|
|
3562
3234
|
a: {
|
|
3563
3235
|
type: 'file',
|
|
3564
|
-
class: '
|
|
3236
|
+
class: 'bw_file_upload_input',
|
|
3565
3237
|
accept: accept,
|
|
3566
3238
|
multiple: multiple,
|
|
3567
3239
|
id: id,
|
|
@@ -3574,7 +3246,7 @@ export function makeFileUpload(props = {}) {
|
|
|
3574
3246
|
o: {
|
|
3575
3247
|
type: 'file-upload',
|
|
3576
3248
|
mounted: function(el) {
|
|
3577
|
-
var input = el.querySelector('.
|
|
3249
|
+
var input = el.querySelector('.bw_file_upload_input');
|
|
3578
3250
|
|
|
3579
3251
|
// Click zone to trigger file input
|
|
3580
3252
|
el.addEventListener('click', function(e) {
|
|
@@ -3592,14 +3264,14 @@ export function makeFileUpload(props = {}) {
|
|
|
3592
3264
|
// Drag-and-drop visuals
|
|
3593
3265
|
el.addEventListener('dragover', function(e) {
|
|
3594
3266
|
e.preventDefault();
|
|
3595
|
-
el.classList.add('
|
|
3267
|
+
el.classList.add('bw_file_upload_active');
|
|
3596
3268
|
});
|
|
3597
3269
|
el.addEventListener('dragleave', function() {
|
|
3598
|
-
el.classList.remove('
|
|
3270
|
+
el.classList.remove('bw_file_upload_active');
|
|
3599
3271
|
});
|
|
3600
3272
|
el.addEventListener('drop', function(e) {
|
|
3601
3273
|
e.preventDefault();
|
|
3602
|
-
el.classList.remove('
|
|
3274
|
+
el.classList.remove('bw_file_upload_active');
|
|
3603
3275
|
if (onFiles && e.dataTransfer.files.length) onFiles(e.dataTransfer.files);
|
|
3604
3276
|
});
|
|
3605
3277
|
}
|
|
@@ -3643,32 +3315,32 @@ export function makeTimeline(props = {}) {
|
|
|
3643
3315
|
|
|
3644
3316
|
return {
|
|
3645
3317
|
t: 'div',
|
|
3646
|
-
a: { class: ('
|
|
3318
|
+
a: { class: ('bw_timeline ' + className).trim() },
|
|
3647
3319
|
c: items.map(function(item) {
|
|
3648
3320
|
return {
|
|
3649
3321
|
t: 'div',
|
|
3650
|
-
a: { class: '
|
|
3322
|
+
a: { class: 'bw_timeline_item' },
|
|
3651
3323
|
c: [
|
|
3652
3324
|
{
|
|
3653
3325
|
t: 'div',
|
|
3654
|
-
a: { class: '
|
|
3326
|
+
a: { class: 'bw_timeline_marker ' + variantClass(item.variant || 'primary') }
|
|
3655
3327
|
},
|
|
3656
3328
|
{
|
|
3657
3329
|
t: 'div',
|
|
3658
|
-
a: { class: '
|
|
3330
|
+
a: { class: 'bw_timeline_content' },
|
|
3659
3331
|
c: [
|
|
3660
3332
|
item.date && {
|
|
3661
3333
|
t: 'div',
|
|
3662
|
-
a: { class: '
|
|
3334
|
+
a: { class: 'bw_timeline_date' },
|
|
3663
3335
|
c: item.date
|
|
3664
3336
|
},
|
|
3665
3337
|
item.title && {
|
|
3666
3338
|
t: 'h5',
|
|
3667
|
-
a: { class: '
|
|
3339
|
+
a: { class: 'bw_timeline_title' },
|
|
3668
3340
|
c: item.title
|
|
3669
3341
|
},
|
|
3670
3342
|
item.content && (typeof item.content === 'string'
|
|
3671
|
-
? { t: 'p', a: { class: '
|
|
3343
|
+
? { t: 'p', a: { class: 'bw_timeline_text' }, c: item.content }
|
|
3672
3344
|
: item.content)
|
|
3673
3345
|
].filter(Boolean)
|
|
3674
3346
|
}
|
|
@@ -3713,28 +3385,28 @@ export function makeStepper(props = {}) {
|
|
|
3713
3385
|
|
|
3714
3386
|
return {
|
|
3715
3387
|
t: 'div',
|
|
3716
|
-
a: { class: ('
|
|
3388
|
+
a: { class: ('bw_stepper ' + className).trim(), role: 'list' },
|
|
3717
3389
|
c: steps.map(function(step, index) {
|
|
3718
3390
|
var state = index < currentStep ? 'completed' : index === currentStep ? 'active' : 'pending';
|
|
3719
3391
|
return {
|
|
3720
3392
|
t: 'div',
|
|
3721
3393
|
a: {
|
|
3722
|
-
class: '
|
|
3394
|
+
class: 'bw_step bw_step_' + state,
|
|
3723
3395
|
role: 'listitem',
|
|
3724
3396
|
'aria-current': state === 'active' ? 'step' : undefined
|
|
3725
3397
|
},
|
|
3726
3398
|
c: [
|
|
3727
3399
|
{
|
|
3728
3400
|
t: 'div',
|
|
3729
|
-
a: { class: '
|
|
3401
|
+
a: { class: 'bw_step_indicator' },
|
|
3730
3402
|
c: state === 'completed' ? '\u2713' : '' + (index + 1)
|
|
3731
3403
|
},
|
|
3732
3404
|
{
|
|
3733
3405
|
t: 'div',
|
|
3734
|
-
a: { class: '
|
|
3406
|
+
a: { class: 'bw_step_body' },
|
|
3735
3407
|
c: [
|
|
3736
|
-
{ t: 'div', a: { class: '
|
|
3737
|
-
step.description && { t: 'div', a: { class: '
|
|
3408
|
+
{ t: 'div', a: { class: 'bw_step_label' }, c: step.label },
|
|
3409
|
+
step.description && { t: 'div', a: { class: 'bw_step_description' }, c: step.description }
|
|
3738
3410
|
].filter(Boolean)
|
|
3739
3411
|
}
|
|
3740
3412
|
]
|
|
@@ -3779,17 +3451,17 @@ export function makeChipInput(props = {}) {
|
|
|
3779
3451
|
function makeChipEl(text) {
|
|
3780
3452
|
return {
|
|
3781
3453
|
t: 'span',
|
|
3782
|
-
a: { class: '
|
|
3454
|
+
a: { class: 'bw_chip', 'data-chip-value': text },
|
|
3783
3455
|
c: [
|
|
3784
3456
|
text,
|
|
3785
3457
|
{
|
|
3786
3458
|
t: 'button',
|
|
3787
3459
|
a: {
|
|
3788
3460
|
type: 'button',
|
|
3789
|
-
class: '
|
|
3461
|
+
class: 'bw_chip_remove',
|
|
3790
3462
|
'aria-label': 'Remove ' + text,
|
|
3791
3463
|
onclick: function(e) {
|
|
3792
|
-
var chip = e.target.closest('.
|
|
3464
|
+
var chip = e.target.closest('.bw_chip');
|
|
3793
3465
|
var val = chip.getAttribute('data-chip-value');
|
|
3794
3466
|
chip.parentNode.removeChild(chip);
|
|
3795
3467
|
if (onRemove) onRemove(val);
|
|
@@ -3803,29 +3475,29 @@ export function makeChipInput(props = {}) {
|
|
|
3803
3475
|
|
|
3804
3476
|
return {
|
|
3805
3477
|
t: 'div',
|
|
3806
|
-
a: { class: ('
|
|
3478
|
+
a: { class: ('bw_chip_input ' + className).trim() },
|
|
3807
3479
|
c: [
|
|
3808
3480
|
...chips.map(makeChipEl),
|
|
3809
3481
|
{
|
|
3810
3482
|
t: 'input',
|
|
3811
3483
|
a: {
|
|
3812
3484
|
type: 'text',
|
|
3813
|
-
class: '
|
|
3485
|
+
class: 'bw_chip_field',
|
|
3814
3486
|
placeholder: placeholder,
|
|
3815
3487
|
onkeydown: function(e) {
|
|
3816
3488
|
if (e.key === 'Enter' && e.target.value.trim()) {
|
|
3817
3489
|
e.preventDefault();
|
|
3818
3490
|
var val = e.target.value.trim();
|
|
3819
|
-
var wrapper = e.target.closest('.
|
|
3491
|
+
var wrapper = e.target.closest('.bw_chip_input');
|
|
3820
3492
|
// Insert chip before the input
|
|
3821
3493
|
var chipEl = document.createElement('span');
|
|
3822
|
-
chipEl.className = '
|
|
3494
|
+
chipEl.className = 'bw_chip';
|
|
3823
3495
|
chipEl.setAttribute('data-chip-value', val);
|
|
3824
3496
|
chipEl.innerHTML = '';
|
|
3825
3497
|
chipEl.textContent = val;
|
|
3826
3498
|
var removeBtn = document.createElement('button');
|
|
3827
3499
|
removeBtn.type = 'button';
|
|
3828
|
-
removeBtn.className = '
|
|
3500
|
+
removeBtn.className = 'bw_chip_remove';
|
|
3829
3501
|
removeBtn.setAttribute('aria-label', 'Remove ' + val);
|
|
3830
3502
|
removeBtn.textContent = '\u00D7';
|
|
3831
3503
|
removeBtn.onclick = function() {
|
|
@@ -3839,8 +3511,8 @@ export function makeChipInput(props = {}) {
|
|
|
3839
3511
|
}
|
|
3840
3512
|
// Backspace on empty input removes last chip
|
|
3841
3513
|
if (e.key === 'Backspace' && !e.target.value) {
|
|
3842
|
-
var wrapper = e.target.closest('.
|
|
3843
|
-
var chipEls = wrapper.querySelectorAll('.
|
|
3514
|
+
var wrapper = e.target.closest('.bw_chip_input');
|
|
3515
|
+
var chipEls = wrapper.querySelectorAll('.bw_chip');
|
|
3844
3516
|
if (chipEls.length) {
|
|
3845
3517
|
var last = chipEls[chipEls.length - 1];
|
|
3846
3518
|
var removedVal = last.getAttribute('data-chip-value');
|
|
@@ -3856,10 +3528,87 @@ export function makeChipInput(props = {}) {
|
|
|
3856
3528
|
};
|
|
3857
3529
|
}
|
|
3858
3530
|
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3531
|
+
// componentHandles registry removed in v2.0.15.
|
|
3532
|
+
// See dev/dead-code-elimination-v2.0.15.md for recovery.
|
|
3533
|
+
|
|
3534
|
+
// =========================================================================
|
|
3535
|
+
// BCCL Component Registry
|
|
3536
|
+
//
|
|
3537
|
+
// Single registry mapping type names to their factory functions.
|
|
3538
|
+
// Enables bw.make('card', props) dispatch and introspection via
|
|
3539
|
+
// Object.keys(BCCL).
|
|
3540
|
+
// =========================================================================
|
|
3541
|
+
|
|
3542
|
+
/**
|
|
3543
|
+
* BCCL component registry — maps component type names to factory functions.
|
|
3544
|
+
* Each entry's `make` function is the corresponding exported makeXxx().
|
|
3545
|
+
*
|
|
3546
|
+
* @type {Object.<string, {make: Function}>}
|
|
3547
|
+
*/
|
|
3548
|
+
export var BCCL = {
|
|
3549
|
+
card: { make: makeCard },
|
|
3550
|
+
button: { make: makeButton },
|
|
3551
|
+
container: { make: makeContainer },
|
|
3552
|
+
row: { make: makeRow },
|
|
3553
|
+
col: { make: makeCol },
|
|
3554
|
+
nav: { make: makeNav },
|
|
3555
|
+
navbar: { make: makeNavbar },
|
|
3556
|
+
tabs: { make: makeTabs },
|
|
3557
|
+
alert: { make: makeAlert },
|
|
3558
|
+
badge: { make: makeBadge },
|
|
3559
|
+
progress: { make: makeProgress },
|
|
3560
|
+
listGroup: { make: makeListGroup },
|
|
3561
|
+
breadcrumb: { make: makeBreadcrumb },
|
|
3562
|
+
form: { make: makeForm },
|
|
3563
|
+
formGroup: { make: makeFormGroup },
|
|
3564
|
+
input: { make: makeInput },
|
|
3565
|
+
textarea: { make: makeTextarea },
|
|
3566
|
+
select: { make: makeSelect },
|
|
3567
|
+
checkbox: { make: makeCheckbox },
|
|
3568
|
+
stack: { make: makeStack },
|
|
3569
|
+
spinner: { make: makeSpinner },
|
|
3570
|
+
hero: { make: makeHero },
|
|
3571
|
+
featureGrid: { make: makeFeatureGrid },
|
|
3572
|
+
cta: { make: makeCTA },
|
|
3573
|
+
section: { make: makeSection },
|
|
3574
|
+
codeDemo: { make: makeCodeDemo },
|
|
3575
|
+
pagination: { make: makePagination },
|
|
3576
|
+
radio: { make: makeRadio },
|
|
3577
|
+
buttonGroup: { make: makeButtonGroup },
|
|
3578
|
+
accordion: { make: makeAccordion },
|
|
3579
|
+
modal: { make: makeModal },
|
|
3580
|
+
toast: { make: makeToast },
|
|
3581
|
+
dropdown: { make: makeDropdown },
|
|
3582
|
+
switch: { make: makeSwitch },
|
|
3583
|
+
skeleton: { make: makeSkeleton },
|
|
3584
|
+
avatar: { make: makeAvatar },
|
|
3585
|
+
carousel: { make: makeCarousel },
|
|
3586
|
+
statCard: { make: makeStatCard },
|
|
3587
|
+
tooltip: { make: makeTooltip },
|
|
3588
|
+
popover: { make: makePopover },
|
|
3589
|
+
searchInput: { make: makeSearchInput },
|
|
3590
|
+
range: { make: makeRange },
|
|
3591
|
+
mediaObject: { make: makeMediaObject },
|
|
3592
|
+
fileUpload: { make: makeFileUpload },
|
|
3593
|
+
timeline: { make: makeTimeline },
|
|
3594
|
+
stepper: { make: makeStepper },
|
|
3595
|
+
chipInput: { make: makeChipInput }
|
|
3865
3596
|
};
|
|
3597
|
+
|
|
3598
|
+
/**
|
|
3599
|
+
* Factory function — create any BCCL component by type name.
|
|
3600
|
+
*
|
|
3601
|
+
* @param {string} type - Component type (e.g. 'card', 'button', 'alert')
|
|
3602
|
+
* @param {Object} [props] - Component properties
|
|
3603
|
+
* @returns {Object} TACO object
|
|
3604
|
+
* @throws {Error} If type is not found in the registry
|
|
3605
|
+
* @example
|
|
3606
|
+
* var card = make('card', { title: 'Hello', variant: 'primary' });
|
|
3607
|
+
* var btn = make('button', { text: 'Click', variant: 'success' });
|
|
3608
|
+
* var types = Object.keys(BCCL); // list all available types
|
|
3609
|
+
*/
|
|
3610
|
+
export function make(type, props) {
|
|
3611
|
+
var def = BCCL[type];
|
|
3612
|
+
if (!def) throw new Error('bw.make: unknown component type "' + type + '". Available: ' + Object.keys(BCCL).join(', '));
|
|
3613
|
+
return def.make(props || {});
|
|
3614
|
+
}
|