bitwrench 2.0.32 → 2.1.1

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 (126) hide show
  1. package/README.md +211 -125
  2. package/dist/bitwrench-bccl.cjs.js +349 -188
  3. package/dist/bitwrench-bccl.cjs.min.js +2 -39
  4. package/dist/bitwrench-bccl.cjs.min.js.gz +0 -0
  5. package/dist/bitwrench-bccl.esm.js +349 -188
  6. package/dist/bitwrench-bccl.esm.min.js +2 -39
  7. package/dist/bitwrench-bccl.esm.min.js.gz +0 -0
  8. package/dist/bitwrench-bccl.umd.js +349 -188
  9. package/dist/bitwrench-bccl.umd.min.js +2 -39
  10. package/dist/bitwrench-bccl.umd.min.js.gz +0 -0
  11. package/dist/bitwrench-code-edit.cjs.js +17 -6
  12. package/dist/bitwrench-code-edit.cjs.min.js +2 -20
  13. package/dist/bitwrench-code-edit.es5.js +8 -3
  14. package/dist/bitwrench-code-edit.es5.min.js +2 -19
  15. package/dist/bitwrench-code-edit.esm.js +17 -6
  16. package/dist/bitwrench-code-edit.esm.min.js +2 -19
  17. package/dist/bitwrench-code-edit.umd.js +17 -6
  18. package/dist/bitwrench-code-edit.umd.min.js +2 -19
  19. package/dist/bitwrench-code-edit.umd.min.js.gz +0 -0
  20. package/dist/bitwrench-debug.js +1 -1
  21. package/dist/bitwrench-debug.min.js +1 -1
  22. package/dist/bitwrench-lean.cjs.js +2492 -1628
  23. package/dist/bitwrench-lean.cjs.min.js +2 -80
  24. package/dist/bitwrench-lean.cjs.min.js.gz +0 -0
  25. package/dist/bitwrench-lean.es5.js +2740 -1838
  26. package/dist/bitwrench-lean.es5.min.js +2 -49
  27. package/dist/bitwrench-lean.es5.min.js.gz +0 -0
  28. package/dist/bitwrench-lean.esm.js +2492 -1628
  29. package/dist/bitwrench-lean.esm.min.js +2 -80
  30. package/dist/bitwrench-lean.esm.min.js.gz +0 -0
  31. package/dist/bitwrench-lean.umd.js +2492 -1628
  32. package/dist/bitwrench-lean.umd.min.js +2 -80
  33. package/dist/bitwrench-lean.umd.min.js.gz +0 -0
  34. package/dist/bitwrench-util-color.cjs.js +251 -0
  35. package/dist/bitwrench-util-color.cjs.min.js +3 -0
  36. package/dist/bitwrench-util-color.es5.js +256 -0
  37. package/dist/bitwrench-util-color.es5.min.js +3 -0
  38. package/dist/bitwrench-util-color.esm.js +241 -0
  39. package/dist/bitwrench-util-color.esm.min.js +3 -0
  40. package/dist/bitwrench-util-color.umd.js +257 -0
  41. package/dist/bitwrench-util-color.umd.min.js +3 -0
  42. package/dist/bitwrench-util-css.cjs.js +2 -1
  43. package/dist/bitwrench-util-css.cjs.min.js +2 -21
  44. package/dist/bitwrench-util-css.es5.js +2 -1
  45. package/dist/bitwrench-util-css.es5.min.js +2 -20
  46. package/dist/bitwrench-util-css.esm.js +2 -1
  47. package/dist/bitwrench-util-css.esm.min.js +1 -19
  48. package/dist/bitwrench-util-css.umd.js +2 -1
  49. package/dist/bitwrench-util-css.umd.min.js +2 -20
  50. package/dist/bitwrench-util-css.umd.min.js.gz +0 -0
  51. package/dist/bitwrench.cjs.js +2826 -1801
  52. package/dist/bitwrench.cjs.min.js +2 -99
  53. package/dist/bitwrench.cjs.min.js.gz +0 -0
  54. package/dist/bitwrench.css +403 -479
  55. package/dist/bitwrench.d.ts +70 -73
  56. package/dist/bitwrench.es5.js +3106 -2020
  57. package/dist/bitwrench.es5.min.js +2 -67
  58. package/dist/bitwrench.es5.min.js.gz +0 -0
  59. package/dist/bitwrench.esm.js +2826 -1801
  60. package/dist/bitwrench.esm.min.js +2 -99
  61. package/dist/bitwrench.esm.min.js.gz +0 -0
  62. package/dist/bitwrench.min.css +1 -1
  63. package/dist/bitwrench.umd.js +2826 -1801
  64. package/dist/bitwrench.umd.min.js +2 -99
  65. package/dist/bitwrench.umd.min.js.gz +0 -0
  66. package/dist/builds.json +222 -134
  67. package/dist/bwserve.cjs.js +289 -282
  68. package/dist/bwserve.d.ts +157 -0
  69. package/dist/bwserve.esm.js +290 -283
  70. package/dist/sri.json +54 -46
  71. package/docs/README.md +6 -3
  72. package/docs/app-patterns.md +7 -6
  73. package/docs/bitwrench-for-wasm.md +53 -54
  74. package/docs/bitwrench-mcp.md +2 -2
  75. package/docs/bitwrench-northstar-principles.md +406 -0
  76. package/docs/bitwrench-taco-schema-discussion.md +2 -2
  77. package/docs/bitwrench_api.md +191 -106
  78. package/docs/bitwrench_typescript_usage.md +5 -5
  79. package/docs/bw-attach.md +29 -75
  80. package/docs/bwserve.md +200 -168
  81. package/docs/cli.md +36 -12
  82. package/docs/component-cheatsheet.md +2 -2
  83. package/docs/component-library.md +4 -4
  84. package/docs/component-lifecycle.md +234 -0
  85. package/docs/drift-lint.md +268 -0
  86. package/docs/framework-translation-table.md +4 -4
  87. package/docs/llm-bitwrench-guide.md +60 -50
  88. package/docs/routing.md +11 -13
  89. package/docs/state-management.md +110 -109
  90. package/docs/taco-format.md +13 -14
  91. package/docs/theming.md +13 -3
  92. package/docs/thinking-in-bitwrench.md +858 -983
  93. package/docs/tutorial-bwserve.md +37 -36
  94. package/docs/tutorial-embedded.md +10 -21
  95. package/docs/tutorial-website.md +2 -2
  96. package/package.json +38 -7
  97. package/readme.html +262 -161
  98. package/src/bitwrench-bccl-entry.js +2 -2
  99. package/src/bitwrench-bccl.js +346 -185
  100. package/src/bitwrench-code-edit.js +16 -5
  101. package/src/bitwrench-color-utils.js +117 -181
  102. package/src/bitwrench-file-ops.js +2 -2
  103. package/src/bitwrench-lean.js +4 -3
  104. package/src/bitwrench-router.js +5 -2
  105. package/src/bitwrench-styles.js +420 -504
  106. package/src/bitwrench-util-color.js +240 -0
  107. package/src/bitwrench-util-css.js +1 -0
  108. package/src/bitwrench-utils.js +4 -0
  109. package/src/bitwrench.d.ts +70 -73
  110. package/src/bitwrench.h +5 -0
  111. package/src/bitwrench.js +1939 -933
  112. package/src/bwserve/attach.js +0 -1
  113. package/src/bwserve/bwclient.js +172 -32
  114. package/src/bwserve/bwshell.js +0 -4
  115. package/src/bwserve/client.js +59 -220
  116. package/src/bwserve/index.js +59 -26
  117. package/src/bwserve.d.ts +157 -0
  118. package/src/bwserve.h +5 -0
  119. package/src/cli/attach.js +12 -75
  120. package/src/cli/convert.js +2 -2
  121. package/src/cli/serve.js +37 -35
  122. package/src/generate-css.js +1 -1
  123. package/src/mcp/knowledge.js +4 -4
  124. package/src/mcp/live.js +21 -13
  125. package/src/mcp/tools.js +0 -1
  126. package/src/version.js +3 -7
@@ -44,7 +44,7 @@ export function variantClass(v) {
44
44
  // Handle outline variants: 'outline_primary' or 'outline-primary'
45
45
  if (v.indexOf('outline') === 0) {
46
46
  var base = v.replace(/^outline[_-]/, '');
47
- return 'bw_btn_outline bw_' + base;
47
+ return 'bw_bccl_btn_outline bw_' + base;
48
48
  }
49
49
  return 'bw_' + v;
50
50
  }
@@ -114,48 +114,48 @@ export function makeCard(props = {}) {
114
114
  };
115
115
 
116
116
  const cardClasses = [
117
- 'bw_card',
117
+ 'bw_bccl_card',
118
118
  variantClass(variant),
119
119
  shadow ? (shadowClasses[shadow] || '') : '',
120
120
  !bordered ? 'bw_border_0' : '',
121
- hoverable ? 'bw_card_hoverable' : '',
121
+ hoverable ? 'bw_bccl_card_hoverable' : '',
122
122
  className
123
123
  ].filter(Boolean).join(' ').trim();
124
124
 
125
125
  const cardContent = [
126
126
  header && {
127
127
  t: 'div',
128
- a: { class: `bw_card_header ${headerClass}`.trim() },
128
+ a: { class: `bw_bccl_card_header ${headerClass}`.trim() },
129
129
  c: header
130
130
  },
131
131
  image && (imagePosition === 'top' || imagePosition === 'left') && {
132
132
  t: 'img',
133
133
  a: {
134
- class: `bw_card_img_${imagePosition}`,
134
+ class: `bw_bccl_card_img_${imagePosition}`,
135
135
  src: image.src,
136
136
  alt: image.alt || ''
137
137
  }
138
138
  },
139
139
  {
140
140
  t: 'div',
141
- a: { class: `bw_card_body ${bodyClass}`.trim() },
141
+ a: { class: `bw_bccl_card_body ${bodyClass}`.trim() },
142
142
  c: [
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 },
143
+ title && { t: 'h5', a: { class: 'bw_bccl_card_title' }, c: title },
144
+ subtitle && { t: 'h6', a: { class: 'bw_bccl_card_subtitle bw_mb_2 bw_text_muted' }, c: subtitle },
145
145
  content && (Array.isArray(content) ? content : [content])
146
146
  ].flat().filter(Boolean)
147
147
  },
148
148
  image && (imagePosition === 'bottom' || imagePosition === 'right') && {
149
149
  t: 'img',
150
150
  a: {
151
- class: `bw_card_img_${imagePosition}`,
151
+ class: `bw_bccl_card_img_${imagePosition}`,
152
152
  src: image.src,
153
153
  alt: image.alt || ''
154
154
  }
155
155
  },
156
156
  footer && {
157
157
  t: 'div',
158
- a: { class: `bw_card_footer ${footerClass}`.trim() },
158
+ a: { class: `bw_bccl_card_footer ${footerClass}`.trim() },
159
159
  c: footer
160
160
  }
161
161
  ].filter(Boolean);
@@ -174,9 +174,9 @@ export function makeCard(props = {}) {
174
174
  type: 'card',
175
175
  state: props.state || {},
176
176
  slots: {
177
- title: '.bw_card_title',
178
- content: '.bw_card_body',
179
- footer: '.bw_card_footer'
177
+ title: '.bw_bccl_card_title',
178
+ content: '.bw_bccl_card_body',
179
+ footer: '.bw_bccl_card_footer'
180
180
  }
181
181
  }
182
182
  };
@@ -190,9 +190,9 @@ export function makeCard(props = {}) {
190
190
  type: 'card',
191
191
  state: props.state || {},
192
192
  slots: {
193
- title: '.bw_card_title',
194
- content: '.bw_card_body',
195
- footer: '.bw_card_footer'
193
+ title: '.bw_bccl_card_title',
194
+ content: '.bw_bccl_card_body',
195
+ footer: '.bw_bccl_card_footer'
196
196
  }
197
197
  }
198
198
  };
@@ -229,6 +229,7 @@ export function makeButton(props = {}) {
229
229
  size,
230
230
  disabled = false,
231
231
  onclick,
232
+ action,
232
233
  type = 'button',
233
234
  className = '',
234
235
  style
@@ -239,9 +240,10 @@ export function makeButton(props = {}) {
239
240
  a: {
240
241
  type,
241
242
  class: [
242
- 'bw_btn',
243
+ 'bw_bccl_btn',
243
244
  variantClass(variant),
244
- size && `bw_btn_${size}`,
245
+ size && `bw_bccl_btn_${size}`,
246
+ action && ('bw_act_' + action),
245
247
  className
246
248
  ].filter(Boolean).join(' '),
247
249
  disabled,
@@ -275,7 +277,7 @@ export function makeContainer(props = {}) {
275
277
 
276
278
  return {
277
279
  t: 'div',
278
- a: { class: `bw_container${fluid ? '-fluid' : ''} ${className}`.trim() },
280
+ a: { class: `bw_bccl_container${fluid ? '-fluid' : ''} ${className}`.trim() },
279
281
  c: children
280
282
  };
281
283
  }
@@ -301,7 +303,7 @@ export function makeRow(props = {}) {
301
303
  return {
302
304
  t: 'div',
303
305
  a: {
304
- class: `bw_row ${gap ? `bw_g_${gap}` : ''} ${className}`.trim()
306
+ class: `bw_bccl_row bw_row ${gap ? `bw_g_${gap}` : ''} ${className}`.trim()
305
307
  },
306
308
  c: children
307
309
  };
@@ -352,7 +354,7 @@ export function makeCol(props = {}) {
352
354
 
353
355
  return {
354
356
  t: 'div',
355
- a: { class: `${classes.join(' ')} ${className}`.trim() },
357
+ a: { class: `bw_bccl_col ${classes.join(' ')} ${className}`.trim() },
356
358
  c: content || children
357
359
  };
358
360
  }
@@ -391,7 +393,7 @@ export function makeNav(props = {}) {
391
393
  return {
392
394
  t: 'ul',
393
395
  a: {
394
- class: `bw_nav ${pills ? 'bw_nav_pills' : 'bw_nav_tabs'} ${vertical ? 'bw_nav_vertical' : ''} ${className}`.trim()
396
+ class: `bw_bccl_nav bw_nav ${pills ? 'bw_nav_pills' : 'bw_nav_tabs'} ${vertical ? 'bw_nav_vertical' : ''} ${className}`.trim()
395
397
  },
396
398
  c: items.map(item => ({
397
399
  t: 'li',
@@ -444,7 +446,7 @@ export function makeNavbar(props = {}) {
444
446
  return {
445
447
  t: 'nav',
446
448
  a: {
447
- class: `bw_navbar ${dark ? 'bw_navbar_dark' : 'bw_navbar_light'} ${className}`.trim()
449
+ class: `bw_bccl_navbar ${dark ? 'bw_bccl_navbar_dark' : 'bw_bccl_navbar_light'} ${className}`.trim()
448
450
  },
449
451
  c: {
450
452
  t: 'div',
@@ -452,12 +454,12 @@ export function makeNavbar(props = {}) {
452
454
  c: [
453
455
  brand && {
454
456
  t: 'a',
455
- a: { href: brandHref, class: 'bw_navbar_brand' },
457
+ a: { href: brandHref, class: 'bw_bccl_navbar_brand' },
456
458
  c: brand
457
459
  },
458
460
  items.length > 0 && {
459
461
  t: 'div',
460
- a: { class: 'bw_navbar_nav' },
462
+ a: { class: 'bw_bccl_navbar_nav' },
461
463
  c: items.map(item => ({
462
464
  t: 'a',
463
465
  a: {
@@ -514,7 +516,7 @@ export function makeTabs(props = {}) {
514
516
  // Shared tab switching logic
515
517
  function switchTab(el, index) {
516
518
  var allTabs = el.querySelectorAll('.bw_nav_link');
517
- var allPanes = el.querySelectorAll('.bw_tab_pane');
519
+ var allPanes = el.querySelectorAll('.bw_bccl_tab_pane');
518
520
  if (index < 0 || index >= allTabs.length) return;
519
521
  allTabs.forEach(function(t) {
520
522
  t.classList.remove('active');
@@ -531,7 +533,7 @@ export function makeTabs(props = {}) {
531
533
 
532
534
  return {
533
535
  t: 'div',
534
- a: { class: 'bw_tabs' },
536
+ a: { class: 'bw_bccl_tabs' },
535
537
  c: [
536
538
  {
537
539
  t: 'ul',
@@ -548,7 +550,7 @@ export function makeTabs(props = {}) {
548
550
  tabindex: index === actualActiveIndex ? '0' : '-1',
549
551
  'aria-selected': index === actualActiveIndex ? 'true' : 'false',
550
552
  onclick: (e) => {
551
- switchTab(e.target.closest('.bw_tabs'), index);
553
+ switchTab(e.target.closest('.bw_bccl_tabs'), index);
552
554
  }
553
555
  },
554
556
  c: tab.label
@@ -557,11 +559,11 @@ export function makeTabs(props = {}) {
557
559
  },
558
560
  {
559
561
  t: 'div',
560
- a: { class: 'bw_tab_content' },
562
+ a: { class: 'bw_bccl_tab_content' },
561
563
  c: tabs.map((tab, index) => ({
562
564
  t: 'div',
563
565
  a: {
564
- class: `bw_tab_pane ${index === actualActiveIndex ? 'active' : ''}`,
566
+ class: `bw_bccl_tab_pane ${index === actualActiveIndex ? 'active' : ''}`,
565
567
  role: 'tabpanel'
566
568
  },
567
569
  c: tab.content
@@ -642,7 +644,7 @@ export function makeAlert(props = {}) {
642
644
  return {
643
645
  t: 'div',
644
646
  a: {
645
- class: `bw_alert ${variantClass(variant)} ${dismissible ? 'bw_alert_dismissible' : ''} ${className}`.trim(),
647
+ class: `bw_bccl_alert ${variantClass(variant)} ${dismissible ? 'bw_bccl_alert_dismissible' : ''} ${className}`.trim(),
646
648
  role: 'alert'
647
649
  },
648
650
  c: [
@@ -654,7 +656,7 @@ export function makeAlert(props = {}) {
654
656
  class: 'bw_close',
655
657
  'aria-label': 'Close',
656
658
  onclick: function(e) {
657
- var alert = e.target.closest('.bw_alert');
659
+ var alert = e.target.closest('.bw_bccl_alert');
658
660
  if (alert) { alert.remove(); }
659
661
  }
660
662
  },
@@ -697,12 +699,12 @@ export function makeBadge(props = {}) {
697
699
  className = ''
698
700
  } = props;
699
701
 
700
- const sizeClass = size === 'sm' ? ' bw_badge_sm' : size === 'lg' ? ' bw_badge_lg' : '';
702
+ const sizeClass = size === 'sm' ? ' bw_bccl_badge_sm' : size === 'lg' ? ' bw_bccl_badge_lg' : '';
701
703
 
702
704
  return {
703
705
  t: 'span',
704
706
  a: {
705
- class: `bw_badge ${variantClass(variant)}${sizeClass} ${pill ? 'bw_badge_pill' : ''} ${className}`.trim()
707
+ class: `bw_bccl_badge ${variantClass(variant)}${sizeClass} ${pill ? 'bw_bccl_badge_pill' : ''} ${className}`.trim()
706
708
  },
707
709
  c: text
708
710
  };
@@ -745,17 +747,17 @@ export function makeProgress(props = {}) {
745
747
  return {
746
748
  t: 'div',
747
749
  a: {
748
- class: 'bw_progress',
750
+ class: 'bw_bccl_progress',
749
751
  style: height ? { height: `${height}px` } : undefined
750
752
  },
751
753
  c: {
752
754
  t: 'div',
753
755
  a: {
754
756
  class: [
755
- 'bw_progress_bar',
757
+ 'bw_bccl_progress_bar',
756
758
  variantClass(variant),
757
- striped && 'bw_progress_bar_striped',
758
- animated && 'bw_progress_bar_animated'
759
+ striped && 'bw_bccl_progress_bar_striped',
760
+ animated && 'bw_bccl_progress_bar_animated'
759
761
  ].filter(Boolean).join(' '),
760
762
  role: 'progressbar',
761
763
  style: { width: `${percentage}%` },
@@ -769,7 +771,7 @@ export function makeProgress(props = {}) {
769
771
  type: 'progress',
770
772
  handle: {
771
773
  setValue: function(el, n) {
772
- var bar = el.querySelector('.bw_progress_bar');
774
+ var bar = el.querySelector('.bw_bccl_progress_bar');
773
775
  if (!bar) return;
774
776
  var maxVal = parseInt(bar.getAttribute('aria-valuemax')) || 100;
775
777
  var pct = Math.round((n / maxVal) * 100);
@@ -778,7 +780,7 @@ export function makeProgress(props = {}) {
778
780
  bar.textContent = pct + '%';
779
781
  },
780
782
  getValue: function(el) {
781
- var bar = el.querySelector('.bw_progress_bar');
783
+ var bar = el.querySelector('.bw_bccl_progress_bar');
782
784
  return bar ? parseInt(bar.getAttribute('aria-valuenow')) || 0 : 0;
783
785
  }
784
786
  }
@@ -819,7 +821,7 @@ export function makeListGroup(props = {}) {
819
821
 
820
822
  return {
821
823
  t: 'div',
822
- a: { class: `bw_list_group ${flush ? 'bw_list_group_flush' : ''}`.trim() },
824
+ a: { class: `bw_bccl_listGroup bw_list_group ${flush ? 'bw_list_group_flush' : ''}`.trim() },
823
825
  c: items.map(item => {
824
826
  const isObject = typeof item === 'object';
825
827
  const text = isObject ? item.text : item;
@@ -891,11 +893,11 @@ export function makeBreadcrumb(props = {}) {
891
893
 
892
894
  return {
893
895
  t: 'nav',
894
- a: { 'aria-label': 'breadcrumb' },
896
+ a: { 'aria-label': 'breadcrumb', class: 'bw_bccl_breadcrumb' },
895
897
  c: {
896
898
  t: 'ol',
897
899
  a: { class: 'bw_breadcrumb' },
898
- c: items.map((item, index) => ({
900
+ c: items.map((item, _index) => ({
899
901
  t: 'li',
900
902
  a: {
901
903
  class: `bw_breadcrumb_item ${item.active ? 'active' : ''}`,
@@ -930,15 +932,138 @@ export function makeBreadcrumb(props = {}) {
930
932
  * });
931
933
  */
932
934
  export function makeForm(props = {}) {
933
- const { children, onsubmit, className = '' } = props;
935
+ const { children, fields, onsubmit, className = '' } = props;
936
+
937
+ // Legacy API: just wraps children
938
+ if (!fields) {
939
+ return {
940
+ t: 'form',
941
+ a: {
942
+ class: `bw_bccl_form ${className}`.trim(),
943
+ onsubmit: onsubmit || ((e) => e.preventDefault())
944
+ },
945
+ c: children
946
+ };
947
+ }
948
+
949
+ // New fields-based API with label association, getValues/setValues/validate
950
+ var fieldIds = {};
951
+ var fieldItems = fields.map(function(field) {
952
+ var fieldId = 'bw_field_' + Math.random().toString(36).substr(2, 9);
953
+ fieldIds[field.name] = fieldId;
954
+
955
+ var inputTag = field.type === 'textarea' ? 'textarea' : (field.type === 'select' ? 'select' : 'input');
956
+ var inputAttrs = {
957
+ id: fieldId,
958
+ name: field.name,
959
+ class: 'bw_bccl_form_control'
960
+ };
961
+ if (inputTag === 'input') {
962
+ inputAttrs.type = field.type || 'text';
963
+ }
964
+ if (field.required) {
965
+ inputAttrs.required = true;
966
+ }
967
+ if (field.placeholder) {
968
+ inputAttrs.placeholder = field.placeholder;
969
+ }
970
+
971
+ return {
972
+ t: 'div',
973
+ a: { class: 'bw_bccl_form_group' },
974
+ c: [
975
+ field.label && {
976
+ t: 'label',
977
+ a: { for: fieldId, class: 'bw_bccl_form_label' },
978
+ c: field.required ? [field.label, { t: 'span', a: { class: 'bw_text_danger bw_ms_1' }, c: '*' }] : field.label
979
+ },
980
+ {
981
+ t: inputTag,
982
+ a: inputAttrs
983
+ }
984
+ ].filter(Boolean)
985
+ };
986
+ });
934
987
 
935
988
  return {
936
989
  t: 'form',
937
990
  a: {
938
- class: className,
991
+ class: `bw_bccl_form ${className}`.trim(),
939
992
  onsubmit: onsubmit || ((e) => e.preventDefault())
940
993
  },
941
- c: children
994
+ c: fieldItems,
995
+ o: {
996
+ type: 'form',
997
+ handle: {
998
+ getValues: function(el) {
999
+ var values = {};
1000
+ fields.forEach(function(field) {
1001
+ var input = el.querySelector('[name="' + field.name + '"]');
1002
+ if (input) {
1003
+ var val = input.value;
1004
+ if (field.type === 'number' && val !== '' && val !== undefined) {
1005
+ val = Number(val);
1006
+ }
1007
+ values[field.name] = val;
1008
+ }
1009
+ });
1010
+ return values;
1011
+ },
1012
+ setValues: function(el, vals) {
1013
+ if (typeof vals !== 'object') return;
1014
+ Object.keys(vals).forEach(function(name) {
1015
+ var input = el.querySelector('[name="' + name + '"]');
1016
+ if (input) {
1017
+ input.value = vals[name];
1018
+ }
1019
+ });
1020
+ },
1021
+ validate: function(el) {
1022
+ var valid = true;
1023
+ fields.forEach(function(field) {
1024
+ var input = el.querySelector('[name="' + field.name + '"]');
1025
+ if (!input) return;
1026
+ // Clear previous error state
1027
+ input.removeAttribute('aria-invalid');
1028
+ input.removeAttribute('aria-describedby');
1029
+ var existingErr = input.parentNode.querySelector('.bw_bccl_form_error');
1030
+ if (existingErr) existingErr.parentNode.removeChild(existingErr);
1031
+
1032
+ var isValid = true;
1033
+ if (field.required && (!input.value || input.value.trim() === '')) {
1034
+ isValid = false;
1035
+ }
1036
+ if (!isValid) {
1037
+ valid = false;
1038
+ input.setAttribute('aria-invalid', 'true');
1039
+ var errId = 'bw_err_' + field.name + '_' + Math.random().toString(36).substr(2, 6);
1040
+ input.setAttribute('aria-describedby', errId);
1041
+ var errEl = document.createElement('div');
1042
+ errEl.id = errId;
1043
+ errEl.className = 'bw_bccl_form_error bw_invalid_feedback';
1044
+ errEl.textContent = (field.label || field.name) + ' is required';
1045
+ input.parentNode.appendChild(errEl);
1046
+ }
1047
+ });
1048
+ return { valid: valid };
1049
+ },
1050
+ setErrors: function(el, errors) {
1051
+ if (typeof errors !== 'object') return;
1052
+ Object.keys(errors).forEach(function(name) {
1053
+ var input = el.querySelector('[name="' + name + '"]');
1054
+ if (!input) return;
1055
+ input.setAttribute('aria-invalid', 'true');
1056
+ var errId = 'bw_err_' + name + '_' + Math.random().toString(36).substr(2, 6);
1057
+ input.setAttribute('aria-describedby', errId);
1058
+ var errEl = document.createElement('div');
1059
+ errEl.id = errId;
1060
+ errEl.className = 'bw_bccl_form_error bw_invalid_feedback';
1061
+ errEl.textContent = errors[name];
1062
+ input.parentNode.appendChild(errEl);
1063
+ });
1064
+ }
1065
+ }
1066
+ }
942
1067
  };
943
1068
  }
944
1069
 
@@ -979,11 +1104,11 @@ export function makeFormGroup(props = {}) {
979
1104
 
980
1105
  return {
981
1106
  t: 'div',
982
- a: { class: 'bw_form_group' },
1107
+ a: { class: 'bw_bccl_form_group' },
983
1108
  c: [
984
1109
  label && {
985
1110
  t: 'label',
986
- a: { for: id, class: 'bw_form_label' },
1111
+ a: { for: id, class: 'bw_bccl_form_label' },
987
1112
  c: required ? [label, { t: 'span', a: { class: 'bw_text_danger bw_ms_1' }, c: '*' }] : label
988
1113
  },
989
1114
  styledInput,
@@ -994,7 +1119,7 @@ export function makeFormGroup(props = {}) {
994
1119
  },
995
1120
  help && {
996
1121
  t: 'small',
997
- a: { class: 'bw_form_text bw_text_muted' },
1122
+ a: { class: 'bw_bccl_form_text bw_text_muted' },
998
1123
  c: help
999
1124
  }
1000
1125
  ].filter(Boolean)
@@ -1047,7 +1172,7 @@ export function makeInput(props = {}) {
1047
1172
  t: 'input',
1048
1173
  a: {
1049
1174
  type,
1050
- class: `bw_form_control ${className}`.trim(),
1175
+ class: `bw_bccl_form_control ${className}`.trim(),
1051
1176
  placeholder,
1052
1177
  value,
1053
1178
  id,
@@ -1100,7 +1225,7 @@ export function makeTextarea(props = {}) {
1100
1225
  return {
1101
1226
  t: 'textarea',
1102
1227
  a: {
1103
- class: `bw_form_control ${className}`.trim(),
1228
+ class: `bw_bccl_form_control ${className}`.trim(),
1104
1229
  placeholder,
1105
1230
  rows,
1106
1231
  id,
@@ -1154,7 +1279,7 @@ export function makeSelect(props = {}) {
1154
1279
  return {
1155
1280
  t: 'select',
1156
1281
  a: {
1157
- class: `bw_form_control ${className}`.trim(),
1282
+ class: `bw_bccl_form_control ${className}`.trim(),
1158
1283
  id,
1159
1284
  name,
1160
1285
  disabled,
@@ -1205,13 +1330,13 @@ export function makeCheckbox(props = {}) {
1205
1330
 
1206
1331
  return {
1207
1332
  t: 'div',
1208
- a: { class: `bw_form_check ${className}`.trim() },
1333
+ a: { class: `bw_bccl_form_check ${className}`.trim() },
1209
1334
  c: [
1210
1335
  {
1211
1336
  t: 'input',
1212
1337
  a: {
1213
1338
  type: 'checkbox',
1214
- class: 'bw_form_check_input',
1339
+ class: 'bw_bccl_form_check_input',
1215
1340
  checked,
1216
1341
  id,
1217
1342
  name,
@@ -1222,7 +1347,7 @@ export function makeCheckbox(props = {}) {
1222
1347
  },
1223
1348
  label && {
1224
1349
  t: 'label',
1225
- a: { class: 'bw_form_check_label', for: id },
1350
+ a: { class: 'bw_bccl_form_check_label', for: id },
1226
1351
  c: label
1227
1352
  }
1228
1353
  ].filter(Boolean)
@@ -1260,7 +1385,7 @@ export function makeStack(props = {}) {
1260
1385
  return {
1261
1386
  t: 'div',
1262
1387
  a: {
1263
- class: `bw_${direction === 'vertical' ? 'vstack' : 'hstack'} bw_gap_${gap} ${className}`.trim()
1388
+ class: `bw_bccl_stack bw_${direction === 'vertical' ? 'vstack' : 'hstack'} bw_gap_${gap} ${className}`.trim()
1264
1389
  },
1265
1390
  c: children
1266
1391
  };
@@ -1288,7 +1413,7 @@ export function makeSpinner(props = {}) {
1288
1413
  return {
1289
1414
  t: 'div',
1290
1415
  a: {
1291
- class: `bw_spinner_${type} bw_spinner_${type}-${size} ${variantClass(variant)}`,
1416
+ class: `bw_bccl_spinner bw_spinner_${type} bw_spinner_${type}-${size} ${variantClass(variant)}`,
1292
1417
  role: 'status'
1293
1418
  },
1294
1419
  c: {
@@ -1325,7 +1450,7 @@ export function makeSpinner(props = {}) {
1325
1450
  * variant: "dark",
1326
1451
  * actions: [
1327
1452
  * makeButton({ text: "Get Started", variant: "primary", size: "lg" }),
1328
- * makeButton({ text: "Learn More", variant: "outline-light", size: "lg" })
1453
+ * makeButton({ text: "Learn More", variant: "outline_light", size: "lg" })
1329
1454
  * ]
1330
1455
  * });
1331
1456
  */
@@ -1353,35 +1478,35 @@ export function makeHero(props = {}) {
1353
1478
  return {
1354
1479
  t: 'section',
1355
1480
  a: {
1356
- class: `bw_hero ${variantClass(variant)} ${sizeClasses[size] || sizeClasses.lg} ${centered ? 'bw_text_center' : ''} ${className}`.trim(),
1481
+ class: `bw_bccl_hero ${variantClass(variant)} ${sizeClasses[size] || sizeClasses.lg} ${centered ? 'bw_text_center' : ''} ${className}`.trim(),
1357
1482
  style: backgroundImage ? `background-image: url('${backgroundImage}'); background-size: cover; background-position: center;` : undefined
1358
1483
  },
1359
1484
  c: [
1360
1485
  overlay && {
1361
1486
  t: 'div',
1362
- a: { class: 'bw_hero_overlay' }
1487
+ a: { class: 'bw_bccl_hero_overlay' }
1363
1488
  },
1364
1489
  {
1365
1490
  t: 'div',
1366
1491
  a: { class: 'bw_container' },
1367
1492
  c: {
1368
1493
  t: 'div',
1369
- a: { class: 'bw_hero_content' },
1494
+ a: { class: 'bw_bccl_hero_content' },
1370
1495
  c: [
1371
1496
  title && {
1372
1497
  t: 'h1',
1373
- a: { class: 'bw_hero_title bw_display_4 bw_mb_3' },
1498
+ a: { class: 'bw_bccl_hero_title bw_display_4 bw_mb_3' },
1374
1499
  c: title
1375
1500
  },
1376
1501
  subtitle && {
1377
1502
  t: 'p',
1378
- a: { class: 'bw_hero_subtitle bw_lead bw_mb_4' },
1503
+ a: { class: 'bw_bccl_hero_subtitle bw_lead bw_mb_4' },
1379
1504
  c: subtitle
1380
1505
  },
1381
1506
  content,
1382
1507
  actions && {
1383
1508
  t: 'div',
1384
- a: { class: 'bw_hero_actions bw_mt_4' },
1509
+ a: { class: 'bw_bccl_hero_actions bw_mt_4' },
1385
1510
  c: actions
1386
1511
  }
1387
1512
  ].filter(Boolean)
@@ -1431,7 +1556,7 @@ export function makeFeatureGrid(props = {}) {
1431
1556
 
1432
1557
  return {
1433
1558
  t: 'div',
1434
- a: { class: `bw_feature_grid ${className}`.trim() },
1559
+ a: { class: `bw_bccl_featureGrid bw_feature_grid ${className}`.trim() },
1435
1560
  c: {
1436
1561
  t: 'div',
1437
1562
  a: { class: 'bw_row bw_g_4' },
@@ -1501,7 +1626,7 @@ export function makeCTA(props = {}) {
1501
1626
 
1502
1627
  return {
1503
1628
  t: 'section',
1504
- a: { class: `bw_cta bw_bg_${variant} bw_py_5 ${className}`.trim() },
1629
+ a: { class: `bw_bccl_cta bw_cta bw_bg_${variant} bw_py_5 ${className}`.trim() },
1505
1630
  c: {
1506
1631
  t: 'div',
1507
1632
  a: { class: 'bw_container' },
@@ -1562,7 +1687,7 @@ export function makeSection(props = {}) {
1562
1687
  return {
1563
1688
  t: 'section',
1564
1689
  a: {
1565
- class: `bw_section ${spacingClasses[spacing] || spacingClasses.md} ${variant !== 'default' ? `bw_bg_${variant}` : ''} ${className}`.trim()
1690
+ class: `bw_bccl_section bw_section ${spacingClasses[spacing] || spacingClasses.md} ${variant !== 'default' ? `bw_bg_${variant}` : ''} ${className}`.trim()
1566
1691
  },
1567
1692
  c: {
1568
1693
  t: 'div',
@@ -1663,6 +1788,7 @@ export function makeCodeDemo(props = {}) {
1663
1788
  },
1664
1789
  c: 'Copy'
1665
1790
  },
1791
+ /* c8 ignore next 2 -- codeEditor ternary; requires globalThis.bw.codeEditor setup */
1666
1792
  (typeof globalThis !== 'undefined' && typeof globalThis.bw !== 'undefined' && typeof globalThis.bw.codeEditor === 'function')
1667
1793
  ? globalThis.bw.codeEditor({ code: code, lang: language === 'javascript' ? 'js' : language, readOnly: true, height: 'auto' })
1668
1794
  : {
@@ -1691,7 +1817,7 @@ export function makeCodeDemo(props = {}) {
1691
1817
 
1692
1818
  return {
1693
1819
  t: 'div',
1694
- a: { class: 'bw_code_demo' },
1820
+ a: { class: 'bw_bccl_codeDemo bw_code_demo' },
1695
1821
  c: content
1696
1822
  };
1697
1823
  }
@@ -1788,7 +1914,7 @@ export function makePagination(props = {}) {
1788
1914
  c: {
1789
1915
  t: 'ul',
1790
1916
  a: {
1791
- class: `bw_pagination ${size ? 'bw_pagination_' + size : ''} ${className}`.trim()
1917
+ class: `bw_bccl_pagination ${size ? 'bw_bccl_pagination_' + size : ''} ${className}`.trim()
1792
1918
  },
1793
1919
  c: items
1794
1920
  },
@@ -1850,13 +1976,13 @@ export function makeRadio(props = {}) {
1850
1976
 
1851
1977
  return {
1852
1978
  t: 'div',
1853
- a: { class: `bw_form_check ${className}`.trim() },
1979
+ a: { class: `bw_bccl_form_check ${className}`.trim() },
1854
1980
  c: [
1855
1981
  {
1856
1982
  t: 'input',
1857
1983
  a: {
1858
1984
  type: 'radio',
1859
- class: 'bw_form_check_input',
1985
+ class: 'bw_bccl_form_check_input',
1860
1986
  name,
1861
1987
  value,
1862
1988
  checked,
@@ -1867,7 +1993,7 @@ export function makeRadio(props = {}) {
1867
1993
  },
1868
1994
  label && {
1869
1995
  t: 'label',
1870
- a: { class: 'bw_form_check_label', for: id },
1996
+ a: { class: 'bw_bccl_form_check_label', for: id },
1871
1997
  c: label
1872
1998
  }
1873
1999
  ].filter(Boolean)
@@ -1904,7 +2030,7 @@ export function makeButtonGroup(props = {}) {
1904
2030
  return {
1905
2031
  t: 'div',
1906
2032
  a: {
1907
- class: `${vertical ? 'bw_btn_group_vertical' : 'bw_btn_group'} ${size ? 'bw_btn_group_' + size : ''} ${className}`.trim(),
2033
+ class: `${vertical ? 'bw_bccl_btn_group_vertical' : 'bw_bccl_btn_group'} ${size ? 'bw_bccl_btn_group_' + size : ''} ${className}`.trim(),
1908
2034
  role: 'group'
1909
2035
  },
1910
2036
  c: children
@@ -1944,35 +2070,37 @@ export function makeAccordion(props = {}) {
1944
2070
 
1945
2071
  return {
1946
2072
  t: 'div',
1947
- a: { class: `bw_accordion ${className}`.trim() },
2073
+ a: { class: `bw_bccl_accordion ${className}`.trim() },
1948
2074
  c: items.map(function(item, index) {
2075
+ var panelId = 'bw_acc_panel_' + Math.random().toString(36).substr(2, 9) + '_' + index;
1949
2076
  return {
1950
2077
  t: 'div',
1951
- a: { class: 'bw_accordion_item' },
2078
+ a: { class: 'bw_bccl_accordion_item' },
1952
2079
  c: [
1953
2080
  {
1954
2081
  t: 'h2',
1955
- a: { class: 'bw_accordion_header' },
2082
+ a: { class: 'bw_bccl_accordion_header' },
1956
2083
  c: {
1957
2084
  t: 'button',
1958
2085
  a: {
1959
- class: `bw_accordion_button ${item.open ? '' : 'bw_collapsed'}`.trim(),
2086
+ class: `bw_bccl_accordion_button ${item.open ? '' : 'bw_collapsed'}`.trim(),
1960
2087
  type: 'button',
1961
2088
  'aria-expanded': item.open ? 'true' : 'false',
2089
+ 'aria-controls': panelId,
1962
2090
  onclick: function(e) {
1963
- var btn = e.target.closest('.bw_accordion_button');
1964
- var accordionEl = btn.closest('.bw_accordion');
1965
- var accordionItem = btn.closest('.bw_accordion_item');
1966
- var collapse = accordionItem.querySelector('.bw_accordion_collapse');
2091
+ var btn = e.target.closest('.bw_bccl_accordion_button');
2092
+ var accordionEl = btn.closest('.bw_bccl_accordion');
2093
+ var accordionItem = btn.closest('.bw_bccl_accordion_item');
2094
+ var collapse = accordionItem.querySelector('.bw_bccl_accordion_collapse');
1967
2095
  var isOpen = collapse.classList.contains('bw_collapse_show');
1968
2096
 
1969
2097
  if (!multiOpen) {
1970
2098
  // Animate-close all other open siblings
1971
- var allItems = accordionEl.querySelectorAll('.bw_accordion_item');
2099
+ var allItems = accordionEl.querySelectorAll('.bw_bccl_accordion_item');
1972
2100
  for (var j = 0; j < allItems.length; j++) {
1973
2101
  if (allItems[j] === accordionItem) continue;
1974
- var sibCollapse = allItems[j].querySelector('.bw_accordion_collapse');
1975
- var sibBtn = allItems[j].querySelector('.bw_accordion_button');
2102
+ var sibCollapse = allItems[j].querySelector('.bw_bccl_accordion_collapse');
2103
+ var sibBtn = allItems[j].querySelector('.bw_bccl_accordion_button');
1976
2104
  if (sibCollapse.classList.contains('bw_collapse_show')) {
1977
2105
  sibCollapse.style.maxHeight = sibCollapse.scrollHeight + 'px';
1978
2106
  sibCollapse.offsetHeight; // force reflow
@@ -2016,10 +2144,10 @@ export function makeAccordion(props = {}) {
2016
2144
  },
2017
2145
  {
2018
2146
  t: 'div',
2019
- a: { class: `bw_accordion_collapse ${item.open ? 'bw_collapse_show' : ''}`.trim() },
2147
+ a: { id: panelId, class: `bw_bccl_accordion_collapse ${item.open ? 'bw_collapse_show' : ''}`.trim() },
2020
2148
  c: {
2021
2149
  t: 'div',
2022
- a: { class: 'bw_accordion_body' },
2150
+ a: { class: 'bw_bccl_accordion_body' },
2023
2151
  c: item.content
2024
2152
  },
2025
2153
  o: item.open ? {
@@ -2036,16 +2164,16 @@ export function makeAccordion(props = {}) {
2036
2164
  state: { multiOpen: multiOpen },
2037
2165
  handle: {
2038
2166
  toggle: function(el, index) {
2039
- var items = el.querySelectorAll('.bw_accordion_item');
2167
+ var items = el.querySelectorAll('.bw_bccl_accordion_item');
2040
2168
  if (index < 0 || index >= items.length) return;
2041
- var btn = items[index].querySelector('.bw_accordion_button');
2169
+ var btn = items[index].querySelector('.bw_bccl_accordion_button');
2042
2170
  if (btn) btn.click();
2043
2171
  },
2044
2172
  openAll: function(el) {
2045
- var items = el.querySelectorAll('.bw_accordion_item');
2173
+ var items = el.querySelectorAll('.bw_bccl_accordion_item');
2046
2174
  for (var i = 0; i < items.length; i++) {
2047
- var collapse = items[i].querySelector('.bw_accordion_collapse');
2048
- var btn = items[i].querySelector('.bw_accordion_button');
2175
+ var collapse = items[i].querySelector('.bw_bccl_accordion_collapse');
2176
+ var btn = items[i].querySelector('.bw_bccl_accordion_button');
2049
2177
  if (!collapse.classList.contains('bw_collapse_show')) {
2050
2178
  collapse.classList.add('bw_collapse_show');
2051
2179
  collapse.style.maxHeight = 'none';
@@ -2055,10 +2183,10 @@ export function makeAccordion(props = {}) {
2055
2183
  }
2056
2184
  },
2057
2185
  closeAll: function(el) {
2058
- var items = el.querySelectorAll('.bw_accordion_item');
2186
+ var items = el.querySelectorAll('.bw_bccl_accordion_item');
2059
2187
  for (var i = 0; i < items.length; i++) {
2060
- var collapse = items[i].querySelector('.bw_accordion_collapse');
2061
- var btn = items[i].querySelector('.bw_accordion_button');
2188
+ var collapse = items[i].querySelector('.bw_bccl_accordion_collapse');
2189
+ var btn = items[i].querySelector('.bw_bccl_accordion_button');
2062
2190
  if (collapse.classList.contains('bw_collapse_show')) {
2063
2191
  collapse.style.maxHeight = collapse.scrollHeight + 'px';
2064
2192
  collapse.offsetHeight;
@@ -2104,40 +2232,56 @@ export function makeModal(props = {}) {
2104
2232
  footer,
2105
2233
  size,
2106
2234
  closeButton = true,
2235
+ closeLabel = 'Close',
2107
2236
  onClose,
2237
+ open = false,
2108
2238
  className = ''
2109
2239
  } = props;
2110
2240
 
2111
2241
  function closeModal(el) {
2112
- var backdrop = el.closest('.bw_modal');
2113
- if (backdrop) {
2114
- backdrop.classList.remove('bw_modal_show');
2115
- document.body.style.overflow = '';
2116
- }
2242
+ var backdrop = el.closest('.bw_bccl_modal');
2243
+ /* c8 ignore next -- defensive; closeModal always called from within modal */
2244
+ if (!backdrop) backdrop = el;
2245
+ // Restore focus to the element that was focused when the modal opened
2246
+ var opener = backdrop._bw_opener || null;
2247
+ backdrop.classList.remove('bw_bccl_modal_show');
2248
+ backdrop.style.display = 'none';
2249
+ document.body.style.overflow = '';
2250
+ // Remove aria-modal when closed
2251
+ var dialog = backdrop.querySelector('[aria-modal]');
2252
+ if (dialog) dialog.removeAttribute('aria-modal');
2253
+ if (opener && typeof opener.focus === 'function') opener.focus();
2117
2254
  if (onClose) onClose();
2118
2255
  }
2119
2256
 
2120
2257
  return {
2121
2258
  t: 'div',
2122
- a: { class: `bw_modal ${className}`.trim() },
2259
+ a: {
2260
+ class: `bw_bccl_modal ${open ? 'bw_bccl_modal_show' : ''} ${className}`.trim(),
2261
+ style: open ? 'display:flex' : undefined
2262
+ },
2123
2263
  c: {
2124
2264
  t: 'div',
2125
- a: { class: `bw_modal_dialog ${size ? 'bw_modal_' + size : ''}`.trim() },
2265
+ a: {
2266
+ class: `bw_bccl_modal_dialog ${size ? 'bw_bccl_modal_' + size : ''}`.trim(),
2267
+ role: 'dialog',
2268
+ 'aria-modal': 'true'
2269
+ },
2126
2270
  c: {
2127
2271
  t: 'div',
2128
- a: { class: 'bw_modal_content' },
2272
+ a: { class: 'bw_bccl_modal_content' },
2129
2273
  c: [
2130
2274
  (title || closeButton) && {
2131
2275
  t: 'div',
2132
- a: { class: 'bw_modal_header' },
2276
+ a: { class: 'bw_bccl_modal_header' },
2133
2277
  c: [
2134
- title && { t: 'h5', a: { class: 'bw_modal_title' }, c: title },
2278
+ title && { t: 'h5', a: { class: 'bw_bccl_modal_title' }, c: title },
2135
2279
  closeButton && {
2136
2280
  t: 'button',
2137
2281
  a: {
2138
2282
  type: 'button',
2139
2283
  class: 'bw_close',
2140
- 'aria-label': 'Close',
2284
+ 'aria-label': closeLabel,
2141
2285
  onclick: function(e) { closeModal(e.target); }
2142
2286
  },
2143
2287
  c: '\u00D7'
@@ -2146,12 +2290,12 @@ export function makeModal(props = {}) {
2146
2290
  },
2147
2291
  content && {
2148
2292
  t: 'div',
2149
- a: { class: 'bw_modal_body' },
2293
+ a: { class: 'bw_bccl_modal_body' },
2150
2294
  c: content
2151
2295
  },
2152
2296
  footer && {
2153
2297
  t: 'div',
2154
- a: { class: 'bw_modal_footer' },
2298
+ a: { class: 'bw_bccl_modal_footer' },
2155
2299
  c: footer
2156
2300
  }
2157
2301
  ].filter(Boolean)
@@ -2161,25 +2305,36 @@ export function makeModal(props = {}) {
2161
2305
  type: 'modal',
2162
2306
  handle: {
2163
2307
  open: function(el) {
2164
- el.classList.add('bw_modal_show');
2308
+ el._bw_opener = document.activeElement;
2309
+ el.classList.add('bw_bccl_modal_show');
2165
2310
  el.style.display = 'flex';
2311
+ var dialog = el.querySelector('[role="dialog"]');
2312
+ if (dialog) dialog.setAttribute('aria-modal', 'true');
2166
2313
  document.body.style.overflow = 'hidden';
2167
2314
  },
2168
2315
  close: function(el) { closeModal(el); }
2169
2316
  },
2170
2317
  mounted: function(el) {
2318
+ // Record the opener (the element that had focus when modal was mounted)
2319
+ el._bw_opener = document.activeElement;
2171
2320
  // Click backdrop to close
2172
2321
  el.addEventListener('click', function(e) {
2173
2322
  if (e.target === el) closeModal(el);
2174
2323
  });
2175
- // Escape key to close
2324
+ // Escape key to close — listen on the element and on the document
2176
2325
  var escHandler = function(e) {
2177
- if (e.key === 'Escape' && el.classList.contains('bw_modal_show')) {
2326
+ if (e.key === 'Escape') {
2327
+ closeModal(el);
2328
+ }
2329
+ };
2330
+ el.addEventListener('keydown', escHandler);
2331
+ var docEscHandler = function(e) {
2332
+ if (e.key === 'Escape' && (el.classList.contains('bw_bccl_modal_show') || el.style.display === 'flex')) {
2178
2333
  closeModal(el);
2179
2334
  }
2180
2335
  };
2181
- document.addEventListener('keydown', escHandler);
2182
- el._bw_escHandler = escHandler;
2336
+ document.addEventListener('keydown', docEscHandler);
2337
+ el._bw_escHandler = docEscHandler;
2183
2338
  },
2184
2339
  unmount: function(el) {
2185
2340
  if (el._bw_escHandler) {
@@ -2225,13 +2380,13 @@ export function makeToast(props = {}) {
2225
2380
  return {
2226
2381
  t: 'div',
2227
2382
  a: {
2228
- class: `bw_toast ${variantClass(variant)} bw_toast_${position.replace(/-/g, '_')} ${className}`.trim(),
2383
+ class: `bw_bccl_toast ${variantClass(variant)} bw_bccl_toast_${position.replace(/-/g, '_')} ${className}`.trim(),
2229
2384
  role: 'alert'
2230
2385
  },
2231
2386
  c: [
2232
2387
  (title) && {
2233
2388
  t: 'div',
2234
- a: { class: 'bw_toast_header' },
2389
+ a: { class: 'bw_bccl_toast_header' },
2235
2390
  c: [
2236
2391
  { t: 'strong', c: title },
2237
2392
  {
@@ -2241,9 +2396,9 @@ export function makeToast(props = {}) {
2241
2396
  class: 'bw_close',
2242
2397
  'aria-label': 'Close',
2243
2398
  onclick: function(e) {
2244
- var toast = e.target.closest('.bw_toast');
2399
+ var toast = e.target.closest('.bw_bccl_toast');
2245
2400
  if (toast) {
2246
- toast.classList.add('bw_toast_hiding');
2401
+ toast.classList.add('bw_bccl_toast_hiding');
2247
2402
  setTimeout(function() { if (toast.parentNode) toast.parentNode.removeChild(toast); }, 300);
2248
2403
  }
2249
2404
  }
@@ -2254,7 +2409,7 @@ export function makeToast(props = {}) {
2254
2409
  },
2255
2410
  content && {
2256
2411
  t: 'div',
2257
- a: { class: 'bw_toast_body' },
2412
+ a: { class: 'bw_bccl_toast_body' },
2258
2413
  c: content
2259
2414
  }
2260
2415
  ].filter(Boolean),
@@ -2262,19 +2417,20 @@ export function makeToast(props = {}) {
2262
2417
  type: 'toast',
2263
2418
  handle: {
2264
2419
  dismiss: function(el) {
2265
- el.classList.add('bw_toast_hiding');
2420
+ el.classList.add('bw_bccl_toast_hiding');
2421
+ /* c8 ignore next -- setTimeout callback; requires real timer advancement */
2266
2422
  setTimeout(function() { if (el.parentNode) el.parentNode.removeChild(el); }, 300);
2267
2423
  }
2268
2424
  },
2269
2425
  mounted: function(el) {
2270
2426
  // Trigger show animation
2271
2427
  requestAnimationFrame(function() {
2272
- el.classList.add('bw_toast_show');
2428
+ el.classList.add('bw_bccl_toast_show');
2273
2429
  });
2274
2430
  // Auto-dismiss
2275
2431
  if (autoDismiss) {
2276
2432
  setTimeout(function() {
2277
- el.classList.add('bw_toast_hiding');
2433
+ el.classList.add('bw_bccl_toast_hiding');
2278
2434
  setTimeout(function() { if (el.parentNode) el.parentNode.removeChild(el); }, 300);
2279
2435
  }, delay);
2280
2436
  }
@@ -2327,12 +2483,12 @@ export function makeDropdown(props = {}) {
2327
2483
  triggerTaco = {
2328
2484
  t: 'button',
2329
2485
  a: {
2330
- class: `bw_btn ${variantClass(variant)} bw_dropdown_toggle`,
2486
+ class: `bw_bccl_btn ${variantClass(variant)} bw_bccl_dropdown_toggle`,
2331
2487
  type: 'button',
2332
2488
  onclick: function(e) {
2333
- var dropdown = e.target.closest('.bw_dropdown');
2334
- var menu = dropdown.querySelector('.bw_dropdown_menu');
2335
- menu.classList.toggle('bw_dropdown_show');
2489
+ var dropdown = e.target.closest('.bw_bccl_dropdown');
2490
+ var menu = dropdown.querySelector('.bw_bccl_dropdown_menu');
2491
+ menu.classList.toggle('bw_bccl_dropdown_show');
2336
2492
  }
2337
2493
  },
2338
2494
  c: trigger || 'Dropdown'
@@ -2343,26 +2499,26 @@ export function makeDropdown(props = {}) {
2343
2499
 
2344
2500
  return {
2345
2501
  t: 'div',
2346
- a: { class: `bw_dropdown ${className}`.trim() },
2502
+ a: { class: `bw_bccl_dropdown ${className}`.trim() },
2347
2503
  c: [
2348
2504
  triggerTaco,
2349
2505
  {
2350
2506
  t: 'div',
2351
- a: { class: `bw_dropdown_menu ${align === 'end' ? 'bw_dropdown_menu_end' : ''}`.trim() },
2507
+ a: { class: `bw_bccl_dropdown_menu ${align === 'end' ? 'bw_bccl_dropdown_menu_end' : ''}`.trim() },
2352
2508
  c: items.map(function(item) {
2353
2509
  if (item.divider) {
2354
- return { t: 'hr', a: { class: 'bw_dropdown_divider' } };
2510
+ return { t: 'hr', a: { class: 'bw_bccl_dropdown_divider' } };
2355
2511
  }
2356
2512
  return {
2357
2513
  t: 'a',
2358
2514
  a: {
2359
- class: `bw_dropdown_item ${item.disabled ? 'disabled' : ''}`.trim(),
2515
+ class: `bw_bccl_dropdown_item ${item.disabled ? 'disabled' : ''}`.trim(),
2360
2516
  href: item.href || '#',
2361
2517
  onclick: item.disabled ? undefined : function(e) {
2362
2518
  if (!item.href) e.preventDefault();
2363
- var dropdown = e.target.closest('.bw_dropdown');
2364
- var menu = dropdown.querySelector('.bw_dropdown_menu');
2365
- menu.classList.remove('bw_dropdown_show');
2519
+ var dropdown = e.target.closest('.bw_bccl_dropdown');
2520
+ var menu = dropdown.querySelector('.bw_bccl_dropdown_menu');
2521
+ menu.classList.remove('bw_bccl_dropdown_show');
2366
2522
  if (item.onclick) item.onclick(e);
2367
2523
  }
2368
2524
  },
@@ -2377,8 +2533,8 @@ export function makeDropdown(props = {}) {
2377
2533
  // Click outside to close
2378
2534
  var outsideHandler = function(e) {
2379
2535
  if (!el.contains(e.target)) {
2380
- var menu = el.querySelector('.bw_dropdown_menu');
2381
- if (menu) menu.classList.remove('bw_dropdown_show');
2536
+ var menu = el.querySelector('.bw_bccl_dropdown_menu');
2537
+ if (menu) menu.classList.remove('bw_bccl_dropdown_show');
2382
2538
  }
2383
2539
  };
2384
2540
  document.addEventListener('click', outsideHandler);
@@ -2425,13 +2581,13 @@ export function makeSwitch(props = {}) {
2425
2581
 
2426
2582
  return {
2427
2583
  t: 'div',
2428
- a: { class: `bw_form_check bw_form_switch ${className}`.trim() },
2584
+ a: { class: `bw_bccl_form_check bw_bccl_form_switch ${className}`.trim() },
2429
2585
  c: [
2430
2586
  {
2431
2587
  t: 'input',
2432
2588
  a: {
2433
2589
  type: 'checkbox',
2434
- class: 'bw_form_check_input bw_switch_input',
2590
+ class: 'bw_bccl_form_check_input bw_switch_input',
2435
2591
  role: 'switch',
2436
2592
  checked,
2437
2593
  id,
@@ -2442,7 +2598,7 @@ export function makeSwitch(props = {}) {
2442
2598
  },
2443
2599
  label && {
2444
2600
  t: 'label',
2445
- a: { class: 'bw_form_check_label', for: id },
2601
+ a: { class: 'bw_bccl_form_check_label', for: id },
2446
2602
  c: label
2447
2603
  }
2448
2604
  ].filter(Boolean)
@@ -2477,7 +2633,7 @@ export function makeSkeleton(props = {}) {
2477
2633
  return {
2478
2634
  t: 'div',
2479
2635
  a: {
2480
- class: `bw_skeleton bw_skeleton_circle ${className}`.trim(),
2636
+ class: `bw_bccl_skeleton bw_skeleton bw_skeleton_circle ${className}`.trim(),
2481
2637
  style: { width: circleSize, height: circleSize }
2482
2638
  }
2483
2639
  };
@@ -2487,7 +2643,7 @@ export function makeSkeleton(props = {}) {
2487
2643
  return {
2488
2644
  t: 'div',
2489
2645
  a: {
2490
- class: `bw_skeleton bw_skeleton_rect ${className}`.trim(),
2646
+ class: `bw_bccl_skeleton bw_skeleton bw_skeleton_rect ${className}`.trim(),
2491
2647
  style: {
2492
2648
  width: width || '100%',
2493
2649
  height: height || '120px'
@@ -2501,7 +2657,7 @@ export function makeSkeleton(props = {}) {
2501
2657
  return {
2502
2658
  t: 'div',
2503
2659
  a: {
2504
- class: `bw_skeleton bw_skeleton_text ${className}`.trim(),
2660
+ class: `bw_bccl_skeleton bw_skeleton bw_skeleton_text ${className}`.trim(),
2505
2661
  style: {
2506
2662
  width: width || '100%',
2507
2663
  height: height || '1em'
@@ -2526,7 +2682,7 @@ export function makeSkeleton(props = {}) {
2526
2682
 
2527
2683
  return {
2528
2684
  t: 'div',
2529
- a: { class: `bw_skeleton_group ${className}`.trim() },
2685
+ a: { class: `bw_bccl_skeleton bw_skeleton_group ${className}`.trim() },
2530
2686
  c: lines
2531
2687
  };
2532
2688
  }
@@ -2561,7 +2717,7 @@ export function makeAvatar(props = {}) {
2561
2717
  return {
2562
2718
  t: 'img',
2563
2719
  a: {
2564
- class: `bw_avatar bw_avatar_${size} ${className}`.trim(),
2720
+ class: `bw_bccl_avatar bw_avatar bw_avatar_${size} ${className}`.trim(),
2565
2721
  src: src,
2566
2722
  alt: alt
2567
2723
  }
@@ -2571,7 +2727,7 @@ export function makeAvatar(props = {}) {
2571
2727
  return {
2572
2728
  t: 'div',
2573
2729
  a: {
2574
- class: `bw_avatar bw_avatar_${size} ${variantClass(variant)} ${className}`.trim()
2730
+ class: `bw_bccl_avatar bw_avatar bw_avatar_${size} ${variantClass(variant)} ${className}`.trim()
2575
2731
  },
2576
2732
  c: initials || ''
2577
2733
  };
@@ -2615,19 +2771,21 @@ export function makeCarousel(props = {}) {
2615
2771
  interval = 5000,
2616
2772
  height = '300px',
2617
2773
  startIndex = 0,
2774
+ prevLabel = 'Previous slide',
2775
+ nextLabel = 'Next slide',
2618
2776
  className = ''
2619
2777
  } = props;
2620
2778
 
2621
2779
  // Shared navigation logic
2622
2780
  function goToSlide(carouselEl, index) {
2623
- var total = carouselEl.querySelectorAll('.bw_carousel_slide').length;
2781
+ var total = carouselEl.querySelectorAll('.bw_bccl_carousel_slide').length;
2624
2782
  if (index < 0) index = total - 1;
2625
2783
  if (index >= total) index = 0;
2626
2784
  carouselEl._bw_carouselIndex = index;
2627
- var track = carouselEl.querySelector('.bw_carousel_track');
2785
+ var track = carouselEl.querySelector('.bw_bccl_carousel_track');
2628
2786
  track.style.transform = 'translateX(-' + (index * 100) + '%)';
2629
2787
  // Update indicators
2630
- var indicators = carouselEl.querySelectorAll('.bw_carousel_indicator');
2788
+ var indicators = carouselEl.querySelectorAll('.bw_bccl_carousel_indicator');
2631
2789
  for (var i = 0; i < indicators.length; i++) {
2632
2790
  if (i === index) {
2633
2791
  indicators[i].classList.add('active');
@@ -2646,14 +2804,14 @@ export function makeCarousel(props = {}) {
2646
2804
  item.content,
2647
2805
  item.caption && {
2648
2806
  t: 'div',
2649
- a: { class: 'bw_carousel_caption' },
2807
+ a: { class: 'bw_bccl_carousel_caption' },
2650
2808
  c: item.caption
2651
2809
  }
2652
2810
  ].filter(Boolean);
2653
2811
 
2654
2812
  return {
2655
2813
  t: 'div',
2656
- a: { class: 'bw_carousel_slide' },
2814
+ a: { class: 'bw_bccl_carousel_slide' },
2657
2815
  c: slideContent.length === 1 ? slideContent[0] : slideContent
2658
2816
  };
2659
2817
  });
@@ -2663,7 +2821,7 @@ export function makeCarousel(props = {}) {
2663
2821
  {
2664
2822
  t: 'div',
2665
2823
  a: {
2666
- class: 'bw_carousel_track',
2824
+ class: 'bw_bccl_carousel_track',
2667
2825
  style: 'transform: translateX(-' + (startIndex * 100) + '%)'
2668
2826
  },
2669
2827
  c: slides
@@ -2675,30 +2833,31 @@ export function makeCarousel(props = {}) {
2675
2833
  children.push({
2676
2834
  t: 'button',
2677
2835
  a: {
2678
- class: 'bw_carousel_control bw_carousel_control_prev',
2836
+ class: 'bw_bccl_carousel_control bw_bccl_carousel_control_prev',
2679
2837
  type: 'button',
2680
- 'aria-label': 'Previous slide',
2838
+ 'aria-label': prevLabel,
2681
2839
  onclick: function(e) {
2682
- var carousel = e.target.closest('.bw_carousel');
2840
+ var carousel = e.target.closest('.bw_bccl_carousel');
2841
+ /* c8 ignore next -- carousel index fallback; default 0 */
2683
2842
  var idx = carousel._bw_carouselIndex || 0;
2684
2843
  goToSlide(carousel, idx - 1);
2685
2844
  }
2686
2845
  },
2687
- c: { t: 'img', a: { src: prevArrow, alt: '', role: 'presentation' } }
2846
+ c: [{ t: 'img', a: { src: prevArrow, alt: '', role: 'presentation' } }, { t: 'span', a: { class: 'bw_visually_hidden' }, c: prevLabel }]
2688
2847
  });
2689
2848
  children.push({
2690
2849
  t: 'button',
2691
2850
  a: {
2692
- class: 'bw_carousel_control bw_carousel_control_next',
2851
+ class: 'bw_bccl_carousel_control bw_bccl_carousel_control_next',
2693
2852
  type: 'button',
2694
- 'aria-label': 'Next slide',
2853
+ 'aria-label': nextLabel,
2695
2854
  onclick: function(e) {
2696
- var carousel = e.target.closest('.bw_carousel');
2855
+ var carousel = e.target.closest('.bw_bccl_carousel');
2697
2856
  var idx = carousel._bw_carouselIndex || 0;
2698
2857
  goToSlide(carousel, idx + 1);
2699
2858
  }
2700
2859
  },
2701
- c: { t: 'img', a: { src: nextArrow, alt: '', role: 'presentation' } }
2860
+ c: [{ t: 'img', a: { src: nextArrow, alt: '', role: 'presentation' } }, { t: 'span', a: { class: 'bw_visually_hidden' }, c: nextLabel }]
2702
2861
  });
2703
2862
  }
2704
2863
 
@@ -2706,16 +2865,16 @@ export function makeCarousel(props = {}) {
2706
2865
  if (showIndicators && items.length > 1) {
2707
2866
  children.push({
2708
2867
  t: 'div',
2709
- a: { class: 'bw_carousel_indicators' },
2868
+ a: { class: 'bw_bccl_carousel_indicators' },
2710
2869
  c: items.map(function(_, i) {
2711
2870
  return {
2712
2871
  t: 'button',
2713
2872
  a: {
2714
- class: 'bw_carousel_indicator' + (i === startIndex ? ' active' : ''),
2873
+ class: 'bw_bccl_carousel_indicator' + (i === startIndex ? ' active' : ''),
2715
2874
  type: 'button',
2716
2875
  'aria-label': 'Go to slide ' + (i + 1),
2717
2876
  onclick: function(e) {
2718
- var carousel = e.target.closest('.bw_carousel');
2877
+ var carousel = e.target.closest('.bw_bccl_carousel');
2719
2878
  goToSlide(carousel, i);
2720
2879
  }
2721
2880
  }
@@ -2727,7 +2886,7 @@ export function makeCarousel(props = {}) {
2727
2886
  return {
2728
2887
  t: 'div',
2729
2888
  a: {
2730
- class: ('bw_carousel ' + className).trim(),
2889
+ class: ('bw_bccl_carousel ' + className).trim(),
2731
2890
  style: 'height: ' + height,
2732
2891
  tabindex: '0',
2733
2892
  'aria-roledescription': 'carousel'
@@ -2739,6 +2898,7 @@ export function makeCarousel(props = {}) {
2739
2898
  handle: {
2740
2899
  goToSlide: function(el, index) { goToSlide(el, index); },
2741
2900
  next: function(el) { goToSlide(el, (el._bw_carouselIndex || 0) + 1); },
2901
+ /* c8 ignore next -- carousel index fallback */
2742
2902
  prev: function(el) { goToSlide(el, (el._bw_carouselIndex || 0) - 1); },
2743
2903
  getActiveIndex: function(el) { return el._bw_carouselIndex || 0; },
2744
2904
  pause: function(el) {
@@ -2749,6 +2909,7 @@ export function makeCarousel(props = {}) {
2749
2909
  },
2750
2910
  play: function(el) {
2751
2911
  if (!el._bw_carouselInterval && el._bw_state) {
2912
+ /* c8 ignore next -- interval fallback to default 5000ms */
2752
2913
  var ms = el._bw_state.interval || 5000;
2753
2914
  el._bw_carouselInterval = setInterval(function() {
2754
2915
  goToSlide(el, (el._bw_carouselIndex || 0) + 1);
@@ -2855,7 +3016,7 @@ export function makeStatCard(props = {}) {
2855
3016
  }
2856
3017
 
2857
3018
  var classes = [
2858
- 'bw_stat_card',
3019
+ 'bw_bccl_statCard bw_stat_card',
2859
3020
  variantClass(variant),
2860
3021
  className
2861
3022
  ].filter(Boolean).join(' ').trim();
@@ -2943,13 +3104,13 @@ export function makeTooltip(props = {}) {
2943
3104
 
2944
3105
  return {
2945
3106
  t: 'span',
2946
- a: { class: ('bw_tooltip_wrapper ' + className).trim() },
3107
+ a: { class: ('bw_bccl_tooltip_wrapper ' + className).trim() },
2947
3108
  c: [
2948
3109
  content,
2949
3110
  {
2950
3111
  t: 'span',
2951
3112
  a: {
2952
- class: 'bw_tooltip bw_tooltip_' + placement,
3113
+ class: 'bw_bccl_tooltip bw_bccl_tooltip_' + placement,
2953
3114
  role: 'tooltip'
2954
3115
  },
2955
3116
  c: text
@@ -2958,18 +3119,18 @@ export function makeTooltip(props = {}) {
2958
3119
  o: {
2959
3120
  type: 'tooltip',
2960
3121
  mounted: function(el) {
2961
- var tip = el.querySelector('.bw_tooltip');
3122
+ var tip = el.querySelector('.bw_bccl_tooltip');
2962
3123
  el.addEventListener('mouseenter', function() {
2963
- tip.classList.add('bw_tooltip_show');
3124
+ tip.classList.add('bw_bccl_tooltip_show');
2964
3125
  });
2965
3126
  el.addEventListener('mouseleave', function() {
2966
- tip.classList.remove('bw_tooltip_show');
3127
+ tip.classList.remove('bw_bccl_tooltip_show');
2967
3128
  });
2968
3129
  el.addEventListener('focusin', function() {
2969
- tip.classList.add('bw_tooltip_show');
3130
+ tip.classList.add('bw_bccl_tooltip_show');
2970
3131
  });
2971
3132
  el.addEventListener('focusout', function() {
2972
- tip.classList.remove('bw_tooltip_show');
3133
+ tip.classList.remove('bw_bccl_tooltip_show');
2973
3134
  });
2974
3135
  }
2975
3136
  }
@@ -3022,7 +3183,7 @@ export function makePopover(props = {}) {
3022
3183
 
3023
3184
  return {
3024
3185
  t: 'span',
3025
- a: { class: ('bw_popover_wrapper ' + className).trim() },
3186
+ a: { class: ('bw_bccl_popover bw_popover_wrapper ' + className).trim() },
3026
3187
  c: [
3027
3188
  {
3028
3189
  t: 'span',
@@ -3106,13 +3267,13 @@ export function makeSearchInput(props = {}) {
3106
3267
 
3107
3268
  return {
3108
3269
  t: 'div',
3109
- a: { class: ('bw_search_input ' + className).trim() },
3270
+ a: { class: ('bw_bccl_searchInput bw_search_input ' + className).trim() },
3110
3271
  c: [
3111
3272
  {
3112
3273
  t: 'input',
3113
3274
  a: {
3114
3275
  type: 'search',
3115
- class: 'bw_form_control bw_search_field',
3276
+ class: 'bw_bccl_form_control bw_search_field',
3116
3277
  placeholder: placeholder,
3117
3278
  value: value,
3118
3279
  id: id,
@@ -3249,7 +3410,7 @@ export function makeRange(props = {}) {
3249
3410
 
3250
3411
  return {
3251
3412
  t: 'div',
3252
- a: { class: ('bw_range_wrapper ' + className).trim() },
3413
+ a: { class: ('bw_bccl_range bw_range_wrapper ' + className).trim() },
3253
3414
  c: children,
3254
3415
  o: { type: 'range' }
3255
3416
  };
@@ -3310,7 +3471,7 @@ export function makeMediaObject(props = {}) {
3310
3471
 
3311
3472
  return {
3312
3473
  t: 'div',
3313
- a: { class: ('bw_media ' + (reverse ? 'bw_media_reverse ' : '') + className).trim() },
3474
+ a: { class: ('bw_bccl_mediaObject bw_media ' + (reverse ? 'bw_media_reverse ' : '') + className).trim() },
3314
3475
  c: reverse
3315
3476
  ? [bodyEl, imgEl].filter(Boolean)
3316
3477
  : [imgEl, bodyEl].filter(Boolean),
@@ -3353,7 +3514,7 @@ export function makeFileUpload(props = {}) {
3353
3514
  return {
3354
3515
  t: 'div',
3355
3516
  a: {
3356
- class: ('bw_file_upload ' + className).trim(),
3517
+ class: ('bw_bccl_fileUpload bw_file_upload ' + className).trim(),
3357
3518
  tabindex: '0',
3358
3519
  role: 'button',
3359
3520
  'aria-label': text
@@ -3447,32 +3608,32 @@ export function makeTimeline(props = {}) {
3447
3608
 
3448
3609
  return {
3449
3610
  t: 'div',
3450
- a: { class: ('bw_timeline ' + className).trim() },
3611
+ a: { class: ('bw_bccl_timeline ' + className).trim() },
3451
3612
  c: items.map(function(item) {
3452
3613
  return {
3453
3614
  t: 'div',
3454
- a: { class: 'bw_timeline_item' },
3615
+ a: { class: 'bw_bccl_timeline_item' },
3455
3616
  c: [
3456
3617
  {
3457
3618
  t: 'div',
3458
- a: { class: 'bw_timeline_marker ' + variantClass(item.variant || 'primary') }
3619
+ a: { class: 'bw_bccl_timeline_marker ' + variantClass(item.variant || 'primary') }
3459
3620
  },
3460
3621
  {
3461
3622
  t: 'div',
3462
- a: { class: 'bw_timeline_content' },
3623
+ a: { class: 'bw_bccl_timeline_content' },
3463
3624
  c: [
3464
3625
  item.date && {
3465
3626
  t: 'div',
3466
- a: { class: 'bw_timeline_date' },
3627
+ a: { class: 'bw_bccl_timeline_date' },
3467
3628
  c: item.date
3468
3629
  },
3469
3630
  item.title && {
3470
3631
  t: 'h5',
3471
- a: { class: 'bw_timeline_title' },
3632
+ a: { class: 'bw_bccl_timeline_title' },
3472
3633
  c: item.title
3473
3634
  },
3474
3635
  item.content && (typeof item.content === 'string'
3475
- ? { t: 'p', a: { class: 'bw_timeline_text' }, c: item.content }
3636
+ ? { t: 'p', a: { class: 'bw_bccl_timeline_text' }, c: item.content }
3476
3637
  : item.content)
3477
3638
  ].filter(Boolean)
3478
3639
  }
@@ -3517,7 +3678,7 @@ export function makeStepper(props = {}) {
3517
3678
 
3518
3679
  return {
3519
3680
  t: 'div',
3520
- a: { class: ('bw_stepper ' + className).trim(), role: 'list' },
3681
+ a: { class: ('bw_bccl_stepper bw_stepper ' + className).trim(), role: 'list' },
3521
3682
  c: steps.map(function(step, index) {
3522
3683
  var state = index < currentStep ? 'completed' : index === currentStep ? 'active' : 'pending';
3523
3684
  return {
@@ -3606,7 +3767,7 @@ export function makeChipInput(props = {}) {
3606
3767
 
3607
3768
  return {
3608
3769
  t: 'div',
3609
- a: { class: ('bw_chip_input ' + className).trim() },
3770
+ a: { class: ('bw_bccl_chipInput bw_chip_input ' + className).trim() },
3610
3771
  c: [
3611
3772
  ...chips.map(makeChipEl),
3612
3773
  {
@@ -3642,8 +3803,8 @@ export function makeChipInput(props = {}) {
3642
3803
  }
3643
3804
  // Backspace on empty input removes last chip
3644
3805
  if (e.key === 'Backspace' && !e.target.value) {
3645
- var wrapper = e.target.closest('.bw_chip_input');
3646
- var chipEls = wrapper.querySelectorAll('.bw_chip');
3806
+ var chipWrapper = e.target.closest('.bw_chip_input');
3807
+ var chipEls = chipWrapper.querySelectorAll('.bw_chip');
3647
3808
  if (chipEls.length) {
3648
3809
  var last = chipEls[chipEls.length - 1];
3649
3810
  var removedVal = last._bw_chipValue || last.firstChild.textContent;