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
@@ -1,4 +1,4 @@
1
- /*! bitwrench-bccl v2.0.32 | BSD-2-Clause | https://deftio.github.com/bitwrench/pages */
1
+ /*! bitwrench-bccl v2.1.1 | BSD-2-Clause | https://deftio.github.io/bitwrench/pages */
2
2
  'use strict';
3
3
 
4
4
  /**
@@ -47,7 +47,7 @@ function variantClass(v) {
47
47
  // Handle outline variants: 'outline_primary' or 'outline-primary'
48
48
  if (v.indexOf('outline') === 0) {
49
49
  var base = v.replace(/^outline[_-]/, '');
50
- return 'bw_btn_outline bw_' + base;
50
+ return 'bw_bccl_btn_outline bw_' + base;
51
51
  }
52
52
  return 'bw_' + v;
53
53
  }
@@ -117,48 +117,48 @@ function makeCard(props = {}) {
117
117
  };
118
118
 
119
119
  const cardClasses = [
120
- 'bw_card',
120
+ 'bw_bccl_card',
121
121
  variantClass(variant),
122
122
  shadow ? (shadowClasses[shadow] || '') : '',
123
123
  !bordered ? 'bw_border_0' : '',
124
- hoverable ? 'bw_card_hoverable' : '',
124
+ hoverable ? 'bw_bccl_card_hoverable' : '',
125
125
  className
126
126
  ].filter(Boolean).join(' ').trim();
127
127
 
128
128
  const cardContent = [
129
129
  header && {
130
130
  t: 'div',
131
- a: { class: `bw_card_header ${headerClass}`.trim() },
131
+ a: { class: `bw_bccl_card_header ${headerClass}`.trim() },
132
132
  c: header
133
133
  },
134
134
  image && (imagePosition === 'top' || imagePosition === 'left') && {
135
135
  t: 'img',
136
136
  a: {
137
- class: `bw_card_img_${imagePosition}`,
137
+ class: `bw_bccl_card_img_${imagePosition}`,
138
138
  src: image.src,
139
139
  alt: image.alt || ''
140
140
  }
141
141
  },
142
142
  {
143
143
  t: 'div',
144
- a: { class: `bw_card_body ${bodyClass}`.trim() },
144
+ a: { class: `bw_bccl_card_body ${bodyClass}`.trim() },
145
145
  c: [
146
- title && { t: 'h5', a: { class: 'bw_card_title' }, c: title },
147
- subtitle && { t: 'h6', a: { class: 'bw_card_subtitle bw_mb_2 bw_text_muted' }, c: subtitle },
146
+ title && { t: 'h5', a: { class: 'bw_bccl_card_title' }, c: title },
147
+ subtitle && { t: 'h6', a: { class: 'bw_bccl_card_subtitle bw_mb_2 bw_text_muted' }, c: subtitle },
148
148
  content && (Array.isArray(content) ? content : [content])
149
149
  ].flat().filter(Boolean)
150
150
  },
151
151
  image && (imagePosition === 'bottom' || imagePosition === 'right') && {
152
152
  t: 'img',
153
153
  a: {
154
- class: `bw_card_img_${imagePosition}`,
154
+ class: `bw_bccl_card_img_${imagePosition}`,
155
155
  src: image.src,
156
156
  alt: image.alt || ''
157
157
  }
158
158
  },
159
159
  footer && {
160
160
  t: 'div',
161
- a: { class: `bw_card_footer ${footerClass}`.trim() },
161
+ a: { class: `bw_bccl_card_footer ${footerClass}`.trim() },
162
162
  c: footer
163
163
  }
164
164
  ].filter(Boolean);
@@ -177,9 +177,9 @@ function makeCard(props = {}) {
177
177
  type: 'card',
178
178
  state: props.state || {},
179
179
  slots: {
180
- title: '.bw_card_title',
181
- content: '.bw_card_body',
182
- footer: '.bw_card_footer'
180
+ title: '.bw_bccl_card_title',
181
+ content: '.bw_bccl_card_body',
182
+ footer: '.bw_bccl_card_footer'
183
183
  }
184
184
  }
185
185
  };
@@ -193,9 +193,9 @@ function makeCard(props = {}) {
193
193
  type: 'card',
194
194
  state: props.state || {},
195
195
  slots: {
196
- title: '.bw_card_title',
197
- content: '.bw_card_body',
198
- footer: '.bw_card_footer'
196
+ title: '.bw_bccl_card_title',
197
+ content: '.bw_bccl_card_body',
198
+ footer: '.bw_bccl_card_footer'
199
199
  }
200
200
  }
201
201
  };
@@ -232,6 +232,7 @@ function makeButton(props = {}) {
232
232
  size,
233
233
  disabled = false,
234
234
  onclick,
235
+ action,
235
236
  type = 'button',
236
237
  className = '',
237
238
  style
@@ -242,9 +243,10 @@ function makeButton(props = {}) {
242
243
  a: {
243
244
  type,
244
245
  class: [
245
- 'bw_btn',
246
+ 'bw_bccl_btn',
246
247
  variantClass(variant),
247
- size && `bw_btn_${size}`,
248
+ size && `bw_bccl_btn_${size}`,
249
+ action && ('bw_act_' + action),
248
250
  className
249
251
  ].filter(Boolean).join(' '),
250
252
  disabled,
@@ -278,7 +280,7 @@ function makeContainer(props = {}) {
278
280
 
279
281
  return {
280
282
  t: 'div',
281
- a: { class: `bw_container${fluid ? '-fluid' : ''} ${className}`.trim() },
283
+ a: { class: `bw_bccl_container${fluid ? '-fluid' : ''} ${className}`.trim() },
282
284
  c: children
283
285
  };
284
286
  }
@@ -304,7 +306,7 @@ function makeRow(props = {}) {
304
306
  return {
305
307
  t: 'div',
306
308
  a: {
307
- class: `bw_row ${gap ? `bw_g_${gap}` : ''} ${className}`.trim()
309
+ class: `bw_bccl_row bw_row ${gap ? `bw_g_${gap}` : ''} ${className}`.trim()
308
310
  },
309
311
  c: children
310
312
  };
@@ -355,7 +357,7 @@ function makeCol(props = {}) {
355
357
 
356
358
  return {
357
359
  t: 'div',
358
- a: { class: `${classes.join(' ')} ${className}`.trim() },
360
+ a: { class: `bw_bccl_col ${classes.join(' ')} ${className}`.trim() },
359
361
  c: content || children
360
362
  };
361
363
  }
@@ -394,7 +396,7 @@ function makeNav(props = {}) {
394
396
  return {
395
397
  t: 'ul',
396
398
  a: {
397
- class: `bw_nav ${pills ? 'bw_nav_pills' : 'bw_nav_tabs'} ${vertical ? 'bw_nav_vertical' : ''} ${className}`.trim()
399
+ class: `bw_bccl_nav bw_nav ${pills ? 'bw_nav_pills' : 'bw_nav_tabs'} ${vertical ? 'bw_nav_vertical' : ''} ${className}`.trim()
398
400
  },
399
401
  c: items.map(item => ({
400
402
  t: 'li',
@@ -447,7 +449,7 @@ function makeNavbar(props = {}) {
447
449
  return {
448
450
  t: 'nav',
449
451
  a: {
450
- class: `bw_navbar ${dark ? 'bw_navbar_dark' : 'bw_navbar_light'} ${className}`.trim()
452
+ class: `bw_bccl_navbar ${dark ? 'bw_bccl_navbar_dark' : 'bw_bccl_navbar_light'} ${className}`.trim()
451
453
  },
452
454
  c: {
453
455
  t: 'div',
@@ -455,12 +457,12 @@ function makeNavbar(props = {}) {
455
457
  c: [
456
458
  brand && {
457
459
  t: 'a',
458
- a: { href: brandHref, class: 'bw_navbar_brand' },
460
+ a: { href: brandHref, class: 'bw_bccl_navbar_brand' },
459
461
  c: brand
460
462
  },
461
463
  items.length > 0 && {
462
464
  t: 'div',
463
- a: { class: 'bw_navbar_nav' },
465
+ a: { class: 'bw_bccl_navbar_nav' },
464
466
  c: items.map(item => ({
465
467
  t: 'a',
466
468
  a: {
@@ -517,7 +519,7 @@ function makeTabs(props = {}) {
517
519
  // Shared tab switching logic
518
520
  function switchTab(el, index) {
519
521
  var allTabs = el.querySelectorAll('.bw_nav_link');
520
- var allPanes = el.querySelectorAll('.bw_tab_pane');
522
+ var allPanes = el.querySelectorAll('.bw_bccl_tab_pane');
521
523
  if (index < 0 || index >= allTabs.length) return;
522
524
  allTabs.forEach(function(t) {
523
525
  t.classList.remove('active');
@@ -534,7 +536,7 @@ function makeTabs(props = {}) {
534
536
 
535
537
  return {
536
538
  t: 'div',
537
- a: { class: 'bw_tabs' },
539
+ a: { class: 'bw_bccl_tabs' },
538
540
  c: [
539
541
  {
540
542
  t: 'ul',
@@ -551,7 +553,7 @@ function makeTabs(props = {}) {
551
553
  tabindex: index === actualActiveIndex ? '0' : '-1',
552
554
  'aria-selected': index === actualActiveIndex ? 'true' : 'false',
553
555
  onclick: (e) => {
554
- switchTab(e.target.closest('.bw_tabs'), index);
556
+ switchTab(e.target.closest('.bw_bccl_tabs'), index);
555
557
  }
556
558
  },
557
559
  c: tab.label
@@ -560,11 +562,11 @@ function makeTabs(props = {}) {
560
562
  },
561
563
  {
562
564
  t: 'div',
563
- a: { class: 'bw_tab_content' },
565
+ a: { class: 'bw_bccl_tab_content' },
564
566
  c: tabs.map((tab, index) => ({
565
567
  t: 'div',
566
568
  a: {
567
- class: `bw_tab_pane ${index === actualActiveIndex ? 'active' : ''}`,
569
+ class: `bw_bccl_tab_pane ${index === actualActiveIndex ? 'active' : ''}`,
568
570
  role: 'tabpanel'
569
571
  },
570
572
  c: tab.content
@@ -645,7 +647,7 @@ function makeAlert(props = {}) {
645
647
  return {
646
648
  t: 'div',
647
649
  a: {
648
- class: `bw_alert ${variantClass(variant)} ${dismissible ? 'bw_alert_dismissible' : ''} ${className}`.trim(),
650
+ class: `bw_bccl_alert ${variantClass(variant)} ${dismissible ? 'bw_bccl_alert_dismissible' : ''} ${className}`.trim(),
649
651
  role: 'alert'
650
652
  },
651
653
  c: [
@@ -657,7 +659,7 @@ function makeAlert(props = {}) {
657
659
  class: 'bw_close',
658
660
  'aria-label': 'Close',
659
661
  onclick: function(e) {
660
- var alert = e.target.closest('.bw_alert');
662
+ var alert = e.target.closest('.bw_bccl_alert');
661
663
  if (alert) { alert.remove(); }
662
664
  }
663
665
  },
@@ -700,12 +702,12 @@ function makeBadge(props = {}) {
700
702
  className = ''
701
703
  } = props;
702
704
 
703
- const sizeClass = size === 'sm' ? ' bw_badge_sm' : size === 'lg' ? ' bw_badge_lg' : '';
705
+ const sizeClass = size === 'sm' ? ' bw_bccl_badge_sm' : size === 'lg' ? ' bw_bccl_badge_lg' : '';
704
706
 
705
707
  return {
706
708
  t: 'span',
707
709
  a: {
708
- class: `bw_badge ${variantClass(variant)}${sizeClass} ${pill ? 'bw_badge_pill' : ''} ${className}`.trim()
710
+ class: `bw_bccl_badge ${variantClass(variant)}${sizeClass} ${pill ? 'bw_bccl_badge_pill' : ''} ${className}`.trim()
709
711
  },
710
712
  c: text
711
713
  };
@@ -748,17 +750,17 @@ function makeProgress(props = {}) {
748
750
  return {
749
751
  t: 'div',
750
752
  a: {
751
- class: 'bw_progress',
753
+ class: 'bw_bccl_progress',
752
754
  style: height ? { height: `${height}px` } : undefined
753
755
  },
754
756
  c: {
755
757
  t: 'div',
756
758
  a: {
757
759
  class: [
758
- 'bw_progress_bar',
760
+ 'bw_bccl_progress_bar',
759
761
  variantClass(variant),
760
- striped && 'bw_progress_bar_striped',
761
- animated && 'bw_progress_bar_animated'
762
+ striped && 'bw_bccl_progress_bar_striped',
763
+ animated && 'bw_bccl_progress_bar_animated'
762
764
  ].filter(Boolean).join(' '),
763
765
  role: 'progressbar',
764
766
  style: { width: `${percentage}%` },
@@ -772,7 +774,7 @@ function makeProgress(props = {}) {
772
774
  type: 'progress',
773
775
  handle: {
774
776
  setValue: function(el, n) {
775
- var bar = el.querySelector('.bw_progress_bar');
777
+ var bar = el.querySelector('.bw_bccl_progress_bar');
776
778
  if (!bar) return;
777
779
  var maxVal = parseInt(bar.getAttribute('aria-valuemax')) || 100;
778
780
  var pct = Math.round((n / maxVal) * 100);
@@ -781,7 +783,7 @@ function makeProgress(props = {}) {
781
783
  bar.textContent = pct + '%';
782
784
  },
783
785
  getValue: function(el) {
784
- var bar = el.querySelector('.bw_progress_bar');
786
+ var bar = el.querySelector('.bw_bccl_progress_bar');
785
787
  return bar ? parseInt(bar.getAttribute('aria-valuenow')) || 0 : 0;
786
788
  }
787
789
  }
@@ -822,7 +824,7 @@ function makeListGroup(props = {}) {
822
824
 
823
825
  return {
824
826
  t: 'div',
825
- a: { class: `bw_list_group ${flush ? 'bw_list_group_flush' : ''}`.trim() },
827
+ a: { class: `bw_bccl_listGroup bw_list_group ${flush ? 'bw_list_group_flush' : ''}`.trim() },
826
828
  c: items.map(item => {
827
829
  const isObject = typeof item === 'object';
828
830
  const text = isObject ? item.text : item;
@@ -894,11 +896,11 @@ function makeBreadcrumb(props = {}) {
894
896
 
895
897
  return {
896
898
  t: 'nav',
897
- a: { 'aria-label': 'breadcrumb' },
899
+ a: { 'aria-label': 'breadcrumb', class: 'bw_bccl_breadcrumb' },
898
900
  c: {
899
901
  t: 'ol',
900
902
  a: { class: 'bw_breadcrumb' },
901
- c: items.map((item, index) => ({
903
+ c: items.map((item, _index) => ({
902
904
  t: 'li',
903
905
  a: {
904
906
  class: `bw_breadcrumb_item ${item.active ? 'active' : ''}`,
@@ -933,15 +935,138 @@ function makeBreadcrumb(props = {}) {
933
935
  * });
934
936
  */
935
937
  function makeForm(props = {}) {
936
- const { children, onsubmit, className = '' } = props;
938
+ const { children, fields, onsubmit, className = '' } = props;
939
+
940
+ // Legacy API: just wraps children
941
+ if (!fields) {
942
+ return {
943
+ t: 'form',
944
+ a: {
945
+ class: `bw_bccl_form ${className}`.trim(),
946
+ onsubmit: onsubmit || ((e) => e.preventDefault())
947
+ },
948
+ c: children
949
+ };
950
+ }
951
+
952
+ // New fields-based API with label association, getValues/setValues/validate
953
+ var fieldIds = {};
954
+ var fieldItems = fields.map(function(field) {
955
+ var fieldId = 'bw_field_' + Math.random().toString(36).substr(2, 9);
956
+ fieldIds[field.name] = fieldId;
957
+
958
+ var inputTag = field.type === 'textarea' ? 'textarea' : (field.type === 'select' ? 'select' : 'input');
959
+ var inputAttrs = {
960
+ id: fieldId,
961
+ name: field.name,
962
+ class: 'bw_bccl_form_control'
963
+ };
964
+ if (inputTag === 'input') {
965
+ inputAttrs.type = field.type || 'text';
966
+ }
967
+ if (field.required) {
968
+ inputAttrs.required = true;
969
+ }
970
+ if (field.placeholder) {
971
+ inputAttrs.placeholder = field.placeholder;
972
+ }
973
+
974
+ return {
975
+ t: 'div',
976
+ a: { class: 'bw_bccl_form_group' },
977
+ c: [
978
+ field.label && {
979
+ t: 'label',
980
+ a: { for: fieldId, class: 'bw_bccl_form_label' },
981
+ c: field.required ? [field.label, { t: 'span', a: { class: 'bw_text_danger bw_ms_1' }, c: '*' }] : field.label
982
+ },
983
+ {
984
+ t: inputTag,
985
+ a: inputAttrs
986
+ }
987
+ ].filter(Boolean)
988
+ };
989
+ });
937
990
 
938
991
  return {
939
992
  t: 'form',
940
993
  a: {
941
- class: className,
994
+ class: `bw_bccl_form ${className}`.trim(),
942
995
  onsubmit: onsubmit || ((e) => e.preventDefault())
943
996
  },
944
- c: children
997
+ c: fieldItems,
998
+ o: {
999
+ type: 'form',
1000
+ handle: {
1001
+ getValues: function(el) {
1002
+ var values = {};
1003
+ fields.forEach(function(field) {
1004
+ var input = el.querySelector('[name="' + field.name + '"]');
1005
+ if (input) {
1006
+ var val = input.value;
1007
+ if (field.type === 'number' && val !== '' && val !== undefined) {
1008
+ val = Number(val);
1009
+ }
1010
+ values[field.name] = val;
1011
+ }
1012
+ });
1013
+ return values;
1014
+ },
1015
+ setValues: function(el, vals) {
1016
+ if (typeof vals !== 'object') return;
1017
+ Object.keys(vals).forEach(function(name) {
1018
+ var input = el.querySelector('[name="' + name + '"]');
1019
+ if (input) {
1020
+ input.value = vals[name];
1021
+ }
1022
+ });
1023
+ },
1024
+ validate: function(el) {
1025
+ var valid = true;
1026
+ fields.forEach(function(field) {
1027
+ var input = el.querySelector('[name="' + field.name + '"]');
1028
+ if (!input) return;
1029
+ // Clear previous error state
1030
+ input.removeAttribute('aria-invalid');
1031
+ input.removeAttribute('aria-describedby');
1032
+ var existingErr = input.parentNode.querySelector('.bw_bccl_form_error');
1033
+ if (existingErr) existingErr.parentNode.removeChild(existingErr);
1034
+
1035
+ var isValid = true;
1036
+ if (field.required && (!input.value || input.value.trim() === '')) {
1037
+ isValid = false;
1038
+ }
1039
+ if (!isValid) {
1040
+ valid = false;
1041
+ input.setAttribute('aria-invalid', 'true');
1042
+ var errId = 'bw_err_' + field.name + '_' + Math.random().toString(36).substr(2, 6);
1043
+ input.setAttribute('aria-describedby', errId);
1044
+ var errEl = document.createElement('div');
1045
+ errEl.id = errId;
1046
+ errEl.className = 'bw_bccl_form_error bw_invalid_feedback';
1047
+ errEl.textContent = (field.label || field.name) + ' is required';
1048
+ input.parentNode.appendChild(errEl);
1049
+ }
1050
+ });
1051
+ return { valid: valid };
1052
+ },
1053
+ setErrors: function(el, errors) {
1054
+ if (typeof errors !== 'object') return;
1055
+ Object.keys(errors).forEach(function(name) {
1056
+ var input = el.querySelector('[name="' + name + '"]');
1057
+ if (!input) return;
1058
+ input.setAttribute('aria-invalid', 'true');
1059
+ var errId = 'bw_err_' + name + '_' + Math.random().toString(36).substr(2, 6);
1060
+ input.setAttribute('aria-describedby', errId);
1061
+ var errEl = document.createElement('div');
1062
+ errEl.id = errId;
1063
+ errEl.className = 'bw_bccl_form_error bw_invalid_feedback';
1064
+ errEl.textContent = errors[name];
1065
+ input.parentNode.appendChild(errEl);
1066
+ });
1067
+ }
1068
+ }
1069
+ }
945
1070
  };
946
1071
  }
947
1072
 
@@ -982,11 +1107,11 @@ function makeFormGroup(props = {}) {
982
1107
 
983
1108
  return {
984
1109
  t: 'div',
985
- a: { class: 'bw_form_group' },
1110
+ a: { class: 'bw_bccl_form_group' },
986
1111
  c: [
987
1112
  label && {
988
1113
  t: 'label',
989
- a: { for: id, class: 'bw_form_label' },
1114
+ a: { for: id, class: 'bw_bccl_form_label' },
990
1115
  c: required ? [label, { t: 'span', a: { class: 'bw_text_danger bw_ms_1' }, c: '*' }] : label
991
1116
  },
992
1117
  styledInput,
@@ -997,7 +1122,7 @@ function makeFormGroup(props = {}) {
997
1122
  },
998
1123
  help && {
999
1124
  t: 'small',
1000
- a: { class: 'bw_form_text bw_text_muted' },
1125
+ a: { class: 'bw_bccl_form_text bw_text_muted' },
1001
1126
  c: help
1002
1127
  }
1003
1128
  ].filter(Boolean)
@@ -1050,7 +1175,7 @@ function makeInput(props = {}) {
1050
1175
  t: 'input',
1051
1176
  a: {
1052
1177
  type,
1053
- class: `bw_form_control ${className}`.trim(),
1178
+ class: `bw_bccl_form_control ${className}`.trim(),
1054
1179
  placeholder,
1055
1180
  value,
1056
1181
  id,
@@ -1103,7 +1228,7 @@ function makeTextarea(props = {}) {
1103
1228
  return {
1104
1229
  t: 'textarea',
1105
1230
  a: {
1106
- class: `bw_form_control ${className}`.trim(),
1231
+ class: `bw_bccl_form_control ${className}`.trim(),
1107
1232
  placeholder,
1108
1233
  rows,
1109
1234
  id,
@@ -1157,7 +1282,7 @@ function makeSelect(props = {}) {
1157
1282
  return {
1158
1283
  t: 'select',
1159
1284
  a: {
1160
- class: `bw_form_control ${className}`.trim(),
1285
+ class: `bw_bccl_form_control ${className}`.trim(),
1161
1286
  id,
1162
1287
  name,
1163
1288
  disabled,
@@ -1208,13 +1333,13 @@ function makeCheckbox(props = {}) {
1208
1333
 
1209
1334
  return {
1210
1335
  t: 'div',
1211
- a: { class: `bw_form_check ${className}`.trim() },
1336
+ a: { class: `bw_bccl_form_check ${className}`.trim() },
1212
1337
  c: [
1213
1338
  {
1214
1339
  t: 'input',
1215
1340
  a: {
1216
1341
  type: 'checkbox',
1217
- class: 'bw_form_check_input',
1342
+ class: 'bw_bccl_form_check_input',
1218
1343
  checked,
1219
1344
  id,
1220
1345
  name,
@@ -1225,7 +1350,7 @@ function makeCheckbox(props = {}) {
1225
1350
  },
1226
1351
  label && {
1227
1352
  t: 'label',
1228
- a: { class: 'bw_form_check_label', for: id },
1353
+ a: { class: 'bw_bccl_form_check_label', for: id },
1229
1354
  c: label
1230
1355
  }
1231
1356
  ].filter(Boolean)
@@ -1263,7 +1388,7 @@ function makeStack(props = {}) {
1263
1388
  return {
1264
1389
  t: 'div',
1265
1390
  a: {
1266
- class: `bw_${direction === 'vertical' ? 'vstack' : 'hstack'} bw_gap_${gap} ${className}`.trim()
1391
+ class: `bw_bccl_stack bw_${direction === 'vertical' ? 'vstack' : 'hstack'} bw_gap_${gap} ${className}`.trim()
1267
1392
  },
1268
1393
  c: children
1269
1394
  };
@@ -1291,7 +1416,7 @@ function makeSpinner(props = {}) {
1291
1416
  return {
1292
1417
  t: 'div',
1293
1418
  a: {
1294
- class: `bw_spinner_${type} bw_spinner_${type}-${size} ${variantClass(variant)}`,
1419
+ class: `bw_bccl_spinner bw_spinner_${type} bw_spinner_${type}-${size} ${variantClass(variant)}`,
1295
1420
  role: 'status'
1296
1421
  },
1297
1422
  c: {
@@ -1328,7 +1453,7 @@ function makeSpinner(props = {}) {
1328
1453
  * variant: "dark",
1329
1454
  * actions: [
1330
1455
  * makeButton({ text: "Get Started", variant: "primary", size: "lg" }),
1331
- * makeButton({ text: "Learn More", variant: "outline-light", size: "lg" })
1456
+ * makeButton({ text: "Learn More", variant: "outline_light", size: "lg" })
1332
1457
  * ]
1333
1458
  * });
1334
1459
  */
@@ -1356,35 +1481,35 @@ function makeHero(props = {}) {
1356
1481
  return {
1357
1482
  t: 'section',
1358
1483
  a: {
1359
- class: `bw_hero ${variantClass(variant)} ${sizeClasses[size] || sizeClasses.lg} ${centered ? 'bw_text_center' : ''} ${className}`.trim(),
1484
+ class: `bw_bccl_hero ${variantClass(variant)} ${sizeClasses[size] || sizeClasses.lg} ${centered ? 'bw_text_center' : ''} ${className}`.trim(),
1360
1485
  style: backgroundImage ? `background-image: url('${backgroundImage}'); background-size: cover; background-position: center;` : undefined
1361
1486
  },
1362
1487
  c: [
1363
1488
  overlay && {
1364
1489
  t: 'div',
1365
- a: { class: 'bw_hero_overlay' }
1490
+ a: { class: 'bw_bccl_hero_overlay' }
1366
1491
  },
1367
1492
  {
1368
1493
  t: 'div',
1369
1494
  a: { class: 'bw_container' },
1370
1495
  c: {
1371
1496
  t: 'div',
1372
- a: { class: 'bw_hero_content' },
1497
+ a: { class: 'bw_bccl_hero_content' },
1373
1498
  c: [
1374
1499
  title && {
1375
1500
  t: 'h1',
1376
- a: { class: 'bw_hero_title bw_display_4 bw_mb_3' },
1501
+ a: { class: 'bw_bccl_hero_title bw_display_4 bw_mb_3' },
1377
1502
  c: title
1378
1503
  },
1379
1504
  subtitle && {
1380
1505
  t: 'p',
1381
- a: { class: 'bw_hero_subtitle bw_lead bw_mb_4' },
1506
+ a: { class: 'bw_bccl_hero_subtitle bw_lead bw_mb_4' },
1382
1507
  c: subtitle
1383
1508
  },
1384
1509
  content,
1385
1510
  actions && {
1386
1511
  t: 'div',
1387
- a: { class: 'bw_hero_actions bw_mt_4' },
1512
+ a: { class: 'bw_bccl_hero_actions bw_mt_4' },
1388
1513
  c: actions
1389
1514
  }
1390
1515
  ].filter(Boolean)
@@ -1434,7 +1559,7 @@ function makeFeatureGrid(props = {}) {
1434
1559
 
1435
1560
  return {
1436
1561
  t: 'div',
1437
- a: { class: `bw_feature_grid ${className}`.trim() },
1562
+ a: { class: `bw_bccl_featureGrid bw_feature_grid ${className}`.trim() },
1438
1563
  c: {
1439
1564
  t: 'div',
1440
1565
  a: { class: 'bw_row bw_g_4' },
@@ -1504,7 +1629,7 @@ function makeCTA(props = {}) {
1504
1629
 
1505
1630
  return {
1506
1631
  t: 'section',
1507
- a: { class: `bw_cta bw_bg_${variant} bw_py_5 ${className}`.trim() },
1632
+ a: { class: `bw_bccl_cta bw_cta bw_bg_${variant} bw_py_5 ${className}`.trim() },
1508
1633
  c: {
1509
1634
  t: 'div',
1510
1635
  a: { class: 'bw_container' },
@@ -1565,7 +1690,7 @@ function makeSection(props = {}) {
1565
1690
  return {
1566
1691
  t: 'section',
1567
1692
  a: {
1568
- class: `bw_section ${spacingClasses[spacing] || spacingClasses.md} ${variant !== 'default' ? `bw_bg_${variant}` : ''} ${className}`.trim()
1693
+ class: `bw_bccl_section bw_section ${spacingClasses[spacing] || spacingClasses.md} ${variant !== 'default' ? `bw_bg_${variant}` : ''} ${className}`.trim()
1569
1694
  },
1570
1695
  c: {
1571
1696
  t: 'div',
@@ -1666,6 +1791,7 @@ function makeCodeDemo(props = {}) {
1666
1791
  },
1667
1792
  c: 'Copy'
1668
1793
  },
1794
+ /* c8 ignore next 2 -- codeEditor ternary; requires globalThis.bw.codeEditor setup */
1669
1795
  (typeof globalThis !== 'undefined' && typeof globalThis.bw !== 'undefined' && typeof globalThis.bw.codeEditor === 'function')
1670
1796
  ? globalThis.bw.codeEditor({ code: code, lang: language === 'javascript' ? 'js' : language, readOnly: true, height: 'auto' })
1671
1797
  : {
@@ -1694,7 +1820,7 @@ function makeCodeDemo(props = {}) {
1694
1820
 
1695
1821
  return {
1696
1822
  t: 'div',
1697
- a: { class: 'bw_code_demo' },
1823
+ a: { class: 'bw_bccl_codeDemo bw_code_demo' },
1698
1824
  c: content
1699
1825
  };
1700
1826
  }
@@ -1791,7 +1917,7 @@ function makePagination(props = {}) {
1791
1917
  c: {
1792
1918
  t: 'ul',
1793
1919
  a: {
1794
- class: `bw_pagination ${size ? 'bw_pagination_' + size : ''} ${className}`.trim()
1920
+ class: `bw_bccl_pagination ${size ? 'bw_bccl_pagination_' + size : ''} ${className}`.trim()
1795
1921
  },
1796
1922
  c: items
1797
1923
  },
@@ -1853,13 +1979,13 @@ function makeRadio(props = {}) {
1853
1979
 
1854
1980
  return {
1855
1981
  t: 'div',
1856
- a: { class: `bw_form_check ${className}`.trim() },
1982
+ a: { class: `bw_bccl_form_check ${className}`.trim() },
1857
1983
  c: [
1858
1984
  {
1859
1985
  t: 'input',
1860
1986
  a: {
1861
1987
  type: 'radio',
1862
- class: 'bw_form_check_input',
1988
+ class: 'bw_bccl_form_check_input',
1863
1989
  name,
1864
1990
  value,
1865
1991
  checked,
@@ -1870,7 +1996,7 @@ function makeRadio(props = {}) {
1870
1996
  },
1871
1997
  label && {
1872
1998
  t: 'label',
1873
- a: { class: 'bw_form_check_label', for: id },
1999
+ a: { class: 'bw_bccl_form_check_label', for: id },
1874
2000
  c: label
1875
2001
  }
1876
2002
  ].filter(Boolean)
@@ -1907,7 +2033,7 @@ function makeButtonGroup(props = {}) {
1907
2033
  return {
1908
2034
  t: 'div',
1909
2035
  a: {
1910
- class: `${vertical ? 'bw_btn_group_vertical' : 'bw_btn_group'} ${size ? 'bw_btn_group_' + size : ''} ${className}`.trim(),
2036
+ class: `${vertical ? 'bw_bccl_btn_group_vertical' : 'bw_bccl_btn_group'} ${size ? 'bw_bccl_btn_group_' + size : ''} ${className}`.trim(),
1911
2037
  role: 'group'
1912
2038
  },
1913
2039
  c: children
@@ -1947,35 +2073,37 @@ function makeAccordion(props = {}) {
1947
2073
 
1948
2074
  return {
1949
2075
  t: 'div',
1950
- a: { class: `bw_accordion ${className}`.trim() },
2076
+ a: { class: `bw_bccl_accordion ${className}`.trim() },
1951
2077
  c: items.map(function(item, index) {
2078
+ var panelId = 'bw_acc_panel_' + Math.random().toString(36).substr(2, 9) + '_' + index;
1952
2079
  return {
1953
2080
  t: 'div',
1954
- a: { class: 'bw_accordion_item' },
2081
+ a: { class: 'bw_bccl_accordion_item' },
1955
2082
  c: [
1956
2083
  {
1957
2084
  t: 'h2',
1958
- a: { class: 'bw_accordion_header' },
2085
+ a: { class: 'bw_bccl_accordion_header' },
1959
2086
  c: {
1960
2087
  t: 'button',
1961
2088
  a: {
1962
- class: `bw_accordion_button ${item.open ? '' : 'bw_collapsed'}`.trim(),
2089
+ class: `bw_bccl_accordion_button ${item.open ? '' : 'bw_collapsed'}`.trim(),
1963
2090
  type: 'button',
1964
2091
  'aria-expanded': item.open ? 'true' : 'false',
2092
+ 'aria-controls': panelId,
1965
2093
  onclick: function(e) {
1966
- var btn = e.target.closest('.bw_accordion_button');
1967
- var accordionEl = btn.closest('.bw_accordion');
1968
- var accordionItem = btn.closest('.bw_accordion_item');
1969
- var collapse = accordionItem.querySelector('.bw_accordion_collapse');
2094
+ var btn = e.target.closest('.bw_bccl_accordion_button');
2095
+ var accordionEl = btn.closest('.bw_bccl_accordion');
2096
+ var accordionItem = btn.closest('.bw_bccl_accordion_item');
2097
+ var collapse = accordionItem.querySelector('.bw_bccl_accordion_collapse');
1970
2098
  var isOpen = collapse.classList.contains('bw_collapse_show');
1971
2099
 
1972
2100
  if (!multiOpen) {
1973
2101
  // Animate-close all other open siblings
1974
- var allItems = accordionEl.querySelectorAll('.bw_accordion_item');
2102
+ var allItems = accordionEl.querySelectorAll('.bw_bccl_accordion_item');
1975
2103
  for (var j = 0; j < allItems.length; j++) {
1976
2104
  if (allItems[j] === accordionItem) continue;
1977
- var sibCollapse = allItems[j].querySelector('.bw_accordion_collapse');
1978
- var sibBtn = allItems[j].querySelector('.bw_accordion_button');
2105
+ var sibCollapse = allItems[j].querySelector('.bw_bccl_accordion_collapse');
2106
+ var sibBtn = allItems[j].querySelector('.bw_bccl_accordion_button');
1979
2107
  if (sibCollapse.classList.contains('bw_collapse_show')) {
1980
2108
  sibCollapse.style.maxHeight = sibCollapse.scrollHeight + 'px';
1981
2109
  sibCollapse.offsetHeight; // force reflow
@@ -2019,10 +2147,10 @@ function makeAccordion(props = {}) {
2019
2147
  },
2020
2148
  {
2021
2149
  t: 'div',
2022
- a: { class: `bw_accordion_collapse ${item.open ? 'bw_collapse_show' : ''}`.trim() },
2150
+ a: { id: panelId, class: `bw_bccl_accordion_collapse ${item.open ? 'bw_collapse_show' : ''}`.trim() },
2023
2151
  c: {
2024
2152
  t: 'div',
2025
- a: { class: 'bw_accordion_body' },
2153
+ a: { class: 'bw_bccl_accordion_body' },
2026
2154
  c: item.content
2027
2155
  },
2028
2156
  o: item.open ? {
@@ -2039,16 +2167,16 @@ function makeAccordion(props = {}) {
2039
2167
  state: { multiOpen: multiOpen },
2040
2168
  handle: {
2041
2169
  toggle: function(el, index) {
2042
- var items = el.querySelectorAll('.bw_accordion_item');
2170
+ var items = el.querySelectorAll('.bw_bccl_accordion_item');
2043
2171
  if (index < 0 || index >= items.length) return;
2044
- var btn = items[index].querySelector('.bw_accordion_button');
2172
+ var btn = items[index].querySelector('.bw_bccl_accordion_button');
2045
2173
  if (btn) btn.click();
2046
2174
  },
2047
2175
  openAll: function(el) {
2048
- var items = el.querySelectorAll('.bw_accordion_item');
2176
+ var items = el.querySelectorAll('.bw_bccl_accordion_item');
2049
2177
  for (var i = 0; i < items.length; i++) {
2050
- var collapse = items[i].querySelector('.bw_accordion_collapse');
2051
- var btn = items[i].querySelector('.bw_accordion_button');
2178
+ var collapse = items[i].querySelector('.bw_bccl_accordion_collapse');
2179
+ var btn = items[i].querySelector('.bw_bccl_accordion_button');
2052
2180
  if (!collapse.classList.contains('bw_collapse_show')) {
2053
2181
  collapse.classList.add('bw_collapse_show');
2054
2182
  collapse.style.maxHeight = 'none';
@@ -2058,10 +2186,10 @@ function makeAccordion(props = {}) {
2058
2186
  }
2059
2187
  },
2060
2188
  closeAll: function(el) {
2061
- var items = el.querySelectorAll('.bw_accordion_item');
2189
+ var items = el.querySelectorAll('.bw_bccl_accordion_item');
2062
2190
  for (var i = 0; i < items.length; i++) {
2063
- var collapse = items[i].querySelector('.bw_accordion_collapse');
2064
- var btn = items[i].querySelector('.bw_accordion_button');
2191
+ var collapse = items[i].querySelector('.bw_bccl_accordion_collapse');
2192
+ var btn = items[i].querySelector('.bw_bccl_accordion_button');
2065
2193
  if (collapse.classList.contains('bw_collapse_show')) {
2066
2194
  collapse.style.maxHeight = collapse.scrollHeight + 'px';
2067
2195
  collapse.offsetHeight;
@@ -2107,40 +2235,56 @@ function makeModal(props = {}) {
2107
2235
  footer,
2108
2236
  size,
2109
2237
  closeButton = true,
2238
+ closeLabel = 'Close',
2110
2239
  onClose,
2240
+ open = false,
2111
2241
  className = ''
2112
2242
  } = props;
2113
2243
 
2114
2244
  function closeModal(el) {
2115
- var backdrop = el.closest('.bw_modal');
2116
- if (backdrop) {
2117
- backdrop.classList.remove('bw_modal_show');
2118
- document.body.style.overflow = '';
2119
- }
2245
+ var backdrop = el.closest('.bw_bccl_modal');
2246
+ /* c8 ignore next -- defensive; closeModal always called from within modal */
2247
+ if (!backdrop) backdrop = el;
2248
+ // Restore focus to the element that was focused when the modal opened
2249
+ var opener = backdrop._bw_opener || null;
2250
+ backdrop.classList.remove('bw_bccl_modal_show');
2251
+ backdrop.style.display = 'none';
2252
+ document.body.style.overflow = '';
2253
+ // Remove aria-modal when closed
2254
+ var dialog = backdrop.querySelector('[aria-modal]');
2255
+ if (dialog) dialog.removeAttribute('aria-modal');
2256
+ if (opener && typeof opener.focus === 'function') opener.focus();
2120
2257
  if (onClose) onClose();
2121
2258
  }
2122
2259
 
2123
2260
  return {
2124
2261
  t: 'div',
2125
- a: { class: `bw_modal ${className}`.trim() },
2262
+ a: {
2263
+ class: `bw_bccl_modal ${open ? 'bw_bccl_modal_show' : ''} ${className}`.trim(),
2264
+ style: open ? 'display:flex' : undefined
2265
+ },
2126
2266
  c: {
2127
2267
  t: 'div',
2128
- a: { class: `bw_modal_dialog ${size ? 'bw_modal_' + size : ''}`.trim() },
2268
+ a: {
2269
+ class: `bw_bccl_modal_dialog ${size ? 'bw_bccl_modal_' + size : ''}`.trim(),
2270
+ role: 'dialog',
2271
+ 'aria-modal': 'true'
2272
+ },
2129
2273
  c: {
2130
2274
  t: 'div',
2131
- a: { class: 'bw_modal_content' },
2275
+ a: { class: 'bw_bccl_modal_content' },
2132
2276
  c: [
2133
2277
  (title || closeButton) && {
2134
2278
  t: 'div',
2135
- a: { class: 'bw_modal_header' },
2279
+ a: { class: 'bw_bccl_modal_header' },
2136
2280
  c: [
2137
- title && { t: 'h5', a: { class: 'bw_modal_title' }, c: title },
2281
+ title && { t: 'h5', a: { class: 'bw_bccl_modal_title' }, c: title },
2138
2282
  closeButton && {
2139
2283
  t: 'button',
2140
2284
  a: {
2141
2285
  type: 'button',
2142
2286
  class: 'bw_close',
2143
- 'aria-label': 'Close',
2287
+ 'aria-label': closeLabel,
2144
2288
  onclick: function(e) { closeModal(e.target); }
2145
2289
  },
2146
2290
  c: '\u00D7'
@@ -2149,12 +2293,12 @@ function makeModal(props = {}) {
2149
2293
  },
2150
2294
  content && {
2151
2295
  t: 'div',
2152
- a: { class: 'bw_modal_body' },
2296
+ a: { class: 'bw_bccl_modal_body' },
2153
2297
  c: content
2154
2298
  },
2155
2299
  footer && {
2156
2300
  t: 'div',
2157
- a: { class: 'bw_modal_footer' },
2301
+ a: { class: 'bw_bccl_modal_footer' },
2158
2302
  c: footer
2159
2303
  }
2160
2304
  ].filter(Boolean)
@@ -2164,25 +2308,36 @@ function makeModal(props = {}) {
2164
2308
  type: 'modal',
2165
2309
  handle: {
2166
2310
  open: function(el) {
2167
- el.classList.add('bw_modal_show');
2311
+ el._bw_opener = document.activeElement;
2312
+ el.classList.add('bw_bccl_modal_show');
2168
2313
  el.style.display = 'flex';
2314
+ var dialog = el.querySelector('[role="dialog"]');
2315
+ if (dialog) dialog.setAttribute('aria-modal', 'true');
2169
2316
  document.body.style.overflow = 'hidden';
2170
2317
  },
2171
2318
  close: function(el) { closeModal(el); }
2172
2319
  },
2173
2320
  mounted: function(el) {
2321
+ // Record the opener (the element that had focus when modal was mounted)
2322
+ el._bw_opener = document.activeElement;
2174
2323
  // Click backdrop to close
2175
2324
  el.addEventListener('click', function(e) {
2176
2325
  if (e.target === el) closeModal(el);
2177
2326
  });
2178
- // Escape key to close
2327
+ // Escape key to close — listen on the element and on the document
2179
2328
  var escHandler = function(e) {
2180
- if (e.key === 'Escape' && el.classList.contains('bw_modal_show')) {
2329
+ if (e.key === 'Escape') {
2330
+ closeModal(el);
2331
+ }
2332
+ };
2333
+ el.addEventListener('keydown', escHandler);
2334
+ var docEscHandler = function(e) {
2335
+ if (e.key === 'Escape' && (el.classList.contains('bw_bccl_modal_show') || el.style.display === 'flex')) {
2181
2336
  closeModal(el);
2182
2337
  }
2183
2338
  };
2184
- document.addEventListener('keydown', escHandler);
2185
- el._bw_escHandler = escHandler;
2339
+ document.addEventListener('keydown', docEscHandler);
2340
+ el._bw_escHandler = docEscHandler;
2186
2341
  },
2187
2342
  unmount: function(el) {
2188
2343
  if (el._bw_escHandler) {
@@ -2228,13 +2383,13 @@ function makeToast(props = {}) {
2228
2383
  return {
2229
2384
  t: 'div',
2230
2385
  a: {
2231
- class: `bw_toast ${variantClass(variant)} bw_toast_${position.replace(/-/g, '_')} ${className}`.trim(),
2386
+ class: `bw_bccl_toast ${variantClass(variant)} bw_bccl_toast_${position.replace(/-/g, '_')} ${className}`.trim(),
2232
2387
  role: 'alert'
2233
2388
  },
2234
2389
  c: [
2235
2390
  (title) && {
2236
2391
  t: 'div',
2237
- a: { class: 'bw_toast_header' },
2392
+ a: { class: 'bw_bccl_toast_header' },
2238
2393
  c: [
2239
2394
  { t: 'strong', c: title },
2240
2395
  {
@@ -2244,9 +2399,9 @@ function makeToast(props = {}) {
2244
2399
  class: 'bw_close',
2245
2400
  'aria-label': 'Close',
2246
2401
  onclick: function(e) {
2247
- var toast = e.target.closest('.bw_toast');
2402
+ var toast = e.target.closest('.bw_bccl_toast');
2248
2403
  if (toast) {
2249
- toast.classList.add('bw_toast_hiding');
2404
+ toast.classList.add('bw_bccl_toast_hiding');
2250
2405
  setTimeout(function() { if (toast.parentNode) toast.parentNode.removeChild(toast); }, 300);
2251
2406
  }
2252
2407
  }
@@ -2257,7 +2412,7 @@ function makeToast(props = {}) {
2257
2412
  },
2258
2413
  content && {
2259
2414
  t: 'div',
2260
- a: { class: 'bw_toast_body' },
2415
+ a: { class: 'bw_bccl_toast_body' },
2261
2416
  c: content
2262
2417
  }
2263
2418
  ].filter(Boolean),
@@ -2265,19 +2420,20 @@ function makeToast(props = {}) {
2265
2420
  type: 'toast',
2266
2421
  handle: {
2267
2422
  dismiss: function(el) {
2268
- el.classList.add('bw_toast_hiding');
2423
+ el.classList.add('bw_bccl_toast_hiding');
2424
+ /* c8 ignore next -- setTimeout callback; requires real timer advancement */
2269
2425
  setTimeout(function() { if (el.parentNode) el.parentNode.removeChild(el); }, 300);
2270
2426
  }
2271
2427
  },
2272
2428
  mounted: function(el) {
2273
2429
  // Trigger show animation
2274
2430
  requestAnimationFrame(function() {
2275
- el.classList.add('bw_toast_show');
2431
+ el.classList.add('bw_bccl_toast_show');
2276
2432
  });
2277
2433
  // Auto-dismiss
2278
2434
  if (autoDismiss) {
2279
2435
  setTimeout(function() {
2280
- el.classList.add('bw_toast_hiding');
2436
+ el.classList.add('bw_bccl_toast_hiding');
2281
2437
  setTimeout(function() { if (el.parentNode) el.parentNode.removeChild(el); }, 300);
2282
2438
  }, delay);
2283
2439
  }
@@ -2330,12 +2486,12 @@ function makeDropdown(props = {}) {
2330
2486
  triggerTaco = {
2331
2487
  t: 'button',
2332
2488
  a: {
2333
- class: `bw_btn ${variantClass(variant)} bw_dropdown_toggle`,
2489
+ class: `bw_bccl_btn ${variantClass(variant)} bw_bccl_dropdown_toggle`,
2334
2490
  type: 'button',
2335
2491
  onclick: function(e) {
2336
- var dropdown = e.target.closest('.bw_dropdown');
2337
- var menu = dropdown.querySelector('.bw_dropdown_menu');
2338
- menu.classList.toggle('bw_dropdown_show');
2492
+ var dropdown = e.target.closest('.bw_bccl_dropdown');
2493
+ var menu = dropdown.querySelector('.bw_bccl_dropdown_menu');
2494
+ menu.classList.toggle('bw_bccl_dropdown_show');
2339
2495
  }
2340
2496
  },
2341
2497
  c: trigger || 'Dropdown'
@@ -2346,26 +2502,26 @@ function makeDropdown(props = {}) {
2346
2502
 
2347
2503
  return {
2348
2504
  t: 'div',
2349
- a: { class: `bw_dropdown ${className}`.trim() },
2505
+ a: { class: `bw_bccl_dropdown ${className}`.trim() },
2350
2506
  c: [
2351
2507
  triggerTaco,
2352
2508
  {
2353
2509
  t: 'div',
2354
- a: { class: `bw_dropdown_menu ${align === 'end' ? 'bw_dropdown_menu_end' : ''}`.trim() },
2510
+ a: { class: `bw_bccl_dropdown_menu ${align === 'end' ? 'bw_bccl_dropdown_menu_end' : ''}`.trim() },
2355
2511
  c: items.map(function(item) {
2356
2512
  if (item.divider) {
2357
- return { t: 'hr', a: { class: 'bw_dropdown_divider' } };
2513
+ return { t: 'hr', a: { class: 'bw_bccl_dropdown_divider' } };
2358
2514
  }
2359
2515
  return {
2360
2516
  t: 'a',
2361
2517
  a: {
2362
- class: `bw_dropdown_item ${item.disabled ? 'disabled' : ''}`.trim(),
2518
+ class: `bw_bccl_dropdown_item ${item.disabled ? 'disabled' : ''}`.trim(),
2363
2519
  href: item.href || '#',
2364
2520
  onclick: item.disabled ? undefined : function(e) {
2365
2521
  if (!item.href) e.preventDefault();
2366
- var dropdown = e.target.closest('.bw_dropdown');
2367
- var menu = dropdown.querySelector('.bw_dropdown_menu');
2368
- menu.classList.remove('bw_dropdown_show');
2522
+ var dropdown = e.target.closest('.bw_bccl_dropdown');
2523
+ var menu = dropdown.querySelector('.bw_bccl_dropdown_menu');
2524
+ menu.classList.remove('bw_bccl_dropdown_show');
2369
2525
  if (item.onclick) item.onclick(e);
2370
2526
  }
2371
2527
  },
@@ -2380,8 +2536,8 @@ function makeDropdown(props = {}) {
2380
2536
  // Click outside to close
2381
2537
  var outsideHandler = function(e) {
2382
2538
  if (!el.contains(e.target)) {
2383
- var menu = el.querySelector('.bw_dropdown_menu');
2384
- if (menu) menu.classList.remove('bw_dropdown_show');
2539
+ var menu = el.querySelector('.bw_bccl_dropdown_menu');
2540
+ if (menu) menu.classList.remove('bw_bccl_dropdown_show');
2385
2541
  }
2386
2542
  };
2387
2543
  document.addEventListener('click', outsideHandler);
@@ -2428,13 +2584,13 @@ function makeSwitch(props = {}) {
2428
2584
 
2429
2585
  return {
2430
2586
  t: 'div',
2431
- a: { class: `bw_form_check bw_form_switch ${className}`.trim() },
2587
+ a: { class: `bw_bccl_form_check bw_bccl_form_switch ${className}`.trim() },
2432
2588
  c: [
2433
2589
  {
2434
2590
  t: 'input',
2435
2591
  a: {
2436
2592
  type: 'checkbox',
2437
- class: 'bw_form_check_input bw_switch_input',
2593
+ class: 'bw_bccl_form_check_input bw_switch_input',
2438
2594
  role: 'switch',
2439
2595
  checked,
2440
2596
  id,
@@ -2445,7 +2601,7 @@ function makeSwitch(props = {}) {
2445
2601
  },
2446
2602
  label && {
2447
2603
  t: 'label',
2448
- a: { class: 'bw_form_check_label', for: id },
2604
+ a: { class: 'bw_bccl_form_check_label', for: id },
2449
2605
  c: label
2450
2606
  }
2451
2607
  ].filter(Boolean)
@@ -2480,7 +2636,7 @@ function makeSkeleton(props = {}) {
2480
2636
  return {
2481
2637
  t: 'div',
2482
2638
  a: {
2483
- class: `bw_skeleton bw_skeleton_circle ${className}`.trim(),
2639
+ class: `bw_bccl_skeleton bw_skeleton bw_skeleton_circle ${className}`.trim(),
2484
2640
  style: { width: circleSize, height: circleSize }
2485
2641
  }
2486
2642
  };
@@ -2490,7 +2646,7 @@ function makeSkeleton(props = {}) {
2490
2646
  return {
2491
2647
  t: 'div',
2492
2648
  a: {
2493
- class: `bw_skeleton bw_skeleton_rect ${className}`.trim(),
2649
+ class: `bw_bccl_skeleton bw_skeleton bw_skeleton_rect ${className}`.trim(),
2494
2650
  style: {
2495
2651
  width: width || '100%',
2496
2652
  height: height || '120px'
@@ -2504,7 +2660,7 @@ function makeSkeleton(props = {}) {
2504
2660
  return {
2505
2661
  t: 'div',
2506
2662
  a: {
2507
- class: `bw_skeleton bw_skeleton_text ${className}`.trim(),
2663
+ class: `bw_bccl_skeleton bw_skeleton bw_skeleton_text ${className}`.trim(),
2508
2664
  style: {
2509
2665
  width: width || '100%',
2510
2666
  height: height || '1em'
@@ -2529,7 +2685,7 @@ function makeSkeleton(props = {}) {
2529
2685
 
2530
2686
  return {
2531
2687
  t: 'div',
2532
- a: { class: `bw_skeleton_group ${className}`.trim() },
2688
+ a: { class: `bw_bccl_skeleton bw_skeleton_group ${className}`.trim() },
2533
2689
  c: lines
2534
2690
  };
2535
2691
  }
@@ -2564,7 +2720,7 @@ function makeAvatar(props = {}) {
2564
2720
  return {
2565
2721
  t: 'img',
2566
2722
  a: {
2567
- class: `bw_avatar bw_avatar_${size} ${className}`.trim(),
2723
+ class: `bw_bccl_avatar bw_avatar bw_avatar_${size} ${className}`.trim(),
2568
2724
  src: src,
2569
2725
  alt: alt
2570
2726
  }
@@ -2574,7 +2730,7 @@ function makeAvatar(props = {}) {
2574
2730
  return {
2575
2731
  t: 'div',
2576
2732
  a: {
2577
- class: `bw_avatar bw_avatar_${size} ${variantClass(variant)} ${className}`.trim()
2733
+ class: `bw_bccl_avatar bw_avatar bw_avatar_${size} ${variantClass(variant)} ${className}`.trim()
2578
2734
  },
2579
2735
  c: initials || ''
2580
2736
  };
@@ -2618,19 +2774,21 @@ function makeCarousel(props = {}) {
2618
2774
  interval = 5000,
2619
2775
  height = '300px',
2620
2776
  startIndex = 0,
2777
+ prevLabel = 'Previous slide',
2778
+ nextLabel = 'Next slide',
2621
2779
  className = ''
2622
2780
  } = props;
2623
2781
 
2624
2782
  // Shared navigation logic
2625
2783
  function goToSlide(carouselEl, index) {
2626
- var total = carouselEl.querySelectorAll('.bw_carousel_slide').length;
2784
+ var total = carouselEl.querySelectorAll('.bw_bccl_carousel_slide').length;
2627
2785
  if (index < 0) index = total - 1;
2628
2786
  if (index >= total) index = 0;
2629
2787
  carouselEl._bw_carouselIndex = index;
2630
- var track = carouselEl.querySelector('.bw_carousel_track');
2788
+ var track = carouselEl.querySelector('.bw_bccl_carousel_track');
2631
2789
  track.style.transform = 'translateX(-' + (index * 100) + '%)';
2632
2790
  // Update indicators
2633
- var indicators = carouselEl.querySelectorAll('.bw_carousel_indicator');
2791
+ var indicators = carouselEl.querySelectorAll('.bw_bccl_carousel_indicator');
2634
2792
  for (var i = 0; i < indicators.length; i++) {
2635
2793
  if (i === index) {
2636
2794
  indicators[i].classList.add('active');
@@ -2649,14 +2807,14 @@ function makeCarousel(props = {}) {
2649
2807
  item.content,
2650
2808
  item.caption && {
2651
2809
  t: 'div',
2652
- a: { class: 'bw_carousel_caption' },
2810
+ a: { class: 'bw_bccl_carousel_caption' },
2653
2811
  c: item.caption
2654
2812
  }
2655
2813
  ].filter(Boolean);
2656
2814
 
2657
2815
  return {
2658
2816
  t: 'div',
2659
- a: { class: 'bw_carousel_slide' },
2817
+ a: { class: 'bw_bccl_carousel_slide' },
2660
2818
  c: slideContent.length === 1 ? slideContent[0] : slideContent
2661
2819
  };
2662
2820
  });
@@ -2666,7 +2824,7 @@ function makeCarousel(props = {}) {
2666
2824
  {
2667
2825
  t: 'div',
2668
2826
  a: {
2669
- class: 'bw_carousel_track',
2827
+ class: 'bw_bccl_carousel_track',
2670
2828
  style: 'transform: translateX(-' + (startIndex * 100) + '%)'
2671
2829
  },
2672
2830
  c: slides
@@ -2678,30 +2836,31 @@ function makeCarousel(props = {}) {
2678
2836
  children.push({
2679
2837
  t: 'button',
2680
2838
  a: {
2681
- class: 'bw_carousel_control bw_carousel_control_prev',
2839
+ class: 'bw_bccl_carousel_control bw_bccl_carousel_control_prev',
2682
2840
  type: 'button',
2683
- 'aria-label': 'Previous slide',
2841
+ 'aria-label': prevLabel,
2684
2842
  onclick: function(e) {
2685
- var carousel = e.target.closest('.bw_carousel');
2843
+ var carousel = e.target.closest('.bw_bccl_carousel');
2844
+ /* c8 ignore next -- carousel index fallback; default 0 */
2686
2845
  var idx = carousel._bw_carouselIndex || 0;
2687
2846
  goToSlide(carousel, idx - 1);
2688
2847
  }
2689
2848
  },
2690
- c: { t: 'img', a: { src: prevArrow, alt: '', role: 'presentation' } }
2849
+ c: [{ t: 'img', a: { src: prevArrow, alt: '', role: 'presentation' } }, { t: 'span', a: { class: 'bw_visually_hidden' }, c: prevLabel }]
2691
2850
  });
2692
2851
  children.push({
2693
2852
  t: 'button',
2694
2853
  a: {
2695
- class: 'bw_carousel_control bw_carousel_control_next',
2854
+ class: 'bw_bccl_carousel_control bw_bccl_carousel_control_next',
2696
2855
  type: 'button',
2697
- 'aria-label': 'Next slide',
2856
+ 'aria-label': nextLabel,
2698
2857
  onclick: function(e) {
2699
- var carousel = e.target.closest('.bw_carousel');
2858
+ var carousel = e.target.closest('.bw_bccl_carousel');
2700
2859
  var idx = carousel._bw_carouselIndex || 0;
2701
2860
  goToSlide(carousel, idx + 1);
2702
2861
  }
2703
2862
  },
2704
- c: { t: 'img', a: { src: nextArrow, alt: '', role: 'presentation' } }
2863
+ c: [{ t: 'img', a: { src: nextArrow, alt: '', role: 'presentation' } }, { t: 'span', a: { class: 'bw_visually_hidden' }, c: nextLabel }]
2705
2864
  });
2706
2865
  }
2707
2866
 
@@ -2709,16 +2868,16 @@ function makeCarousel(props = {}) {
2709
2868
  if (showIndicators && items.length > 1) {
2710
2869
  children.push({
2711
2870
  t: 'div',
2712
- a: { class: 'bw_carousel_indicators' },
2871
+ a: { class: 'bw_bccl_carousel_indicators' },
2713
2872
  c: items.map(function(_, i) {
2714
2873
  return {
2715
2874
  t: 'button',
2716
2875
  a: {
2717
- class: 'bw_carousel_indicator' + (i === startIndex ? ' active' : ''),
2876
+ class: 'bw_bccl_carousel_indicator' + (i === startIndex ? ' active' : ''),
2718
2877
  type: 'button',
2719
2878
  'aria-label': 'Go to slide ' + (i + 1),
2720
2879
  onclick: function(e) {
2721
- var carousel = e.target.closest('.bw_carousel');
2880
+ var carousel = e.target.closest('.bw_bccl_carousel');
2722
2881
  goToSlide(carousel, i);
2723
2882
  }
2724
2883
  }
@@ -2730,7 +2889,7 @@ function makeCarousel(props = {}) {
2730
2889
  return {
2731
2890
  t: 'div',
2732
2891
  a: {
2733
- class: ('bw_carousel ' + className).trim(),
2892
+ class: ('bw_bccl_carousel ' + className).trim(),
2734
2893
  style: 'height: ' + height,
2735
2894
  tabindex: '0',
2736
2895
  'aria-roledescription': 'carousel'
@@ -2742,6 +2901,7 @@ function makeCarousel(props = {}) {
2742
2901
  handle: {
2743
2902
  goToSlide: function(el, index) { goToSlide(el, index); },
2744
2903
  next: function(el) { goToSlide(el, (el._bw_carouselIndex || 0) + 1); },
2904
+ /* c8 ignore next -- carousel index fallback */
2745
2905
  prev: function(el) { goToSlide(el, (el._bw_carouselIndex || 0) - 1); },
2746
2906
  getActiveIndex: function(el) { return el._bw_carouselIndex || 0; },
2747
2907
  pause: function(el) {
@@ -2752,6 +2912,7 @@ function makeCarousel(props = {}) {
2752
2912
  },
2753
2913
  play: function(el) {
2754
2914
  if (!el._bw_carouselInterval && el._bw_state) {
2915
+ /* c8 ignore next -- interval fallback to default 5000ms */
2755
2916
  var ms = el._bw_state.interval || 5000;
2756
2917
  el._bw_carouselInterval = setInterval(function() {
2757
2918
  goToSlide(el, (el._bw_carouselIndex || 0) + 1);
@@ -2858,7 +3019,7 @@ function makeStatCard(props = {}) {
2858
3019
  }
2859
3020
 
2860
3021
  var classes = [
2861
- 'bw_stat_card',
3022
+ 'bw_bccl_statCard bw_stat_card',
2862
3023
  variantClass(variant),
2863
3024
  className
2864
3025
  ].filter(Boolean).join(' ').trim();
@@ -2946,13 +3107,13 @@ function makeTooltip(props = {}) {
2946
3107
 
2947
3108
  return {
2948
3109
  t: 'span',
2949
- a: { class: ('bw_tooltip_wrapper ' + className).trim() },
3110
+ a: { class: ('bw_bccl_tooltip_wrapper ' + className).trim() },
2950
3111
  c: [
2951
3112
  content,
2952
3113
  {
2953
3114
  t: 'span',
2954
3115
  a: {
2955
- class: 'bw_tooltip bw_tooltip_' + placement,
3116
+ class: 'bw_bccl_tooltip bw_bccl_tooltip_' + placement,
2956
3117
  role: 'tooltip'
2957
3118
  },
2958
3119
  c: text
@@ -2961,18 +3122,18 @@ function makeTooltip(props = {}) {
2961
3122
  o: {
2962
3123
  type: 'tooltip',
2963
3124
  mounted: function(el) {
2964
- var tip = el.querySelector('.bw_tooltip');
3125
+ var tip = el.querySelector('.bw_bccl_tooltip');
2965
3126
  el.addEventListener('mouseenter', function() {
2966
- tip.classList.add('bw_tooltip_show');
3127
+ tip.classList.add('bw_bccl_tooltip_show');
2967
3128
  });
2968
3129
  el.addEventListener('mouseleave', function() {
2969
- tip.classList.remove('bw_tooltip_show');
3130
+ tip.classList.remove('bw_bccl_tooltip_show');
2970
3131
  });
2971
3132
  el.addEventListener('focusin', function() {
2972
- tip.classList.add('bw_tooltip_show');
3133
+ tip.classList.add('bw_bccl_tooltip_show');
2973
3134
  });
2974
3135
  el.addEventListener('focusout', function() {
2975
- tip.classList.remove('bw_tooltip_show');
3136
+ tip.classList.remove('bw_bccl_tooltip_show');
2976
3137
  });
2977
3138
  }
2978
3139
  }
@@ -3025,7 +3186,7 @@ function makePopover(props = {}) {
3025
3186
 
3026
3187
  return {
3027
3188
  t: 'span',
3028
- a: { class: ('bw_popover_wrapper ' + className).trim() },
3189
+ a: { class: ('bw_bccl_popover bw_popover_wrapper ' + className).trim() },
3029
3190
  c: [
3030
3191
  {
3031
3192
  t: 'span',
@@ -3109,13 +3270,13 @@ function makeSearchInput(props = {}) {
3109
3270
 
3110
3271
  return {
3111
3272
  t: 'div',
3112
- a: { class: ('bw_search_input ' + className).trim() },
3273
+ a: { class: ('bw_bccl_searchInput bw_search_input ' + className).trim() },
3113
3274
  c: [
3114
3275
  {
3115
3276
  t: 'input',
3116
3277
  a: {
3117
3278
  type: 'search',
3118
- class: 'bw_form_control bw_search_field',
3279
+ class: 'bw_bccl_form_control bw_search_field',
3119
3280
  placeholder: placeholder,
3120
3281
  value: value,
3121
3282
  id: id,
@@ -3252,7 +3413,7 @@ function makeRange(props = {}) {
3252
3413
 
3253
3414
  return {
3254
3415
  t: 'div',
3255
- a: { class: ('bw_range_wrapper ' + className).trim() },
3416
+ a: { class: ('bw_bccl_range bw_range_wrapper ' + className).trim() },
3256
3417
  c: children,
3257
3418
  o: { type: 'range' }
3258
3419
  };
@@ -3313,7 +3474,7 @@ function makeMediaObject(props = {}) {
3313
3474
 
3314
3475
  return {
3315
3476
  t: 'div',
3316
- a: { class: ('bw_media ' + (reverse ? 'bw_media_reverse ' : '') + className).trim() },
3477
+ a: { class: ('bw_bccl_mediaObject bw_media ' + (reverse ? 'bw_media_reverse ' : '') + className).trim() },
3317
3478
  c: reverse
3318
3479
  ? [bodyEl, imgEl].filter(Boolean)
3319
3480
  : [imgEl, bodyEl].filter(Boolean),
@@ -3356,7 +3517,7 @@ function makeFileUpload(props = {}) {
3356
3517
  return {
3357
3518
  t: 'div',
3358
3519
  a: {
3359
- class: ('bw_file_upload ' + className).trim(),
3520
+ class: ('bw_bccl_fileUpload bw_file_upload ' + className).trim(),
3360
3521
  tabindex: '0',
3361
3522
  role: 'button',
3362
3523
  'aria-label': text
@@ -3450,32 +3611,32 @@ function makeTimeline(props = {}) {
3450
3611
 
3451
3612
  return {
3452
3613
  t: 'div',
3453
- a: { class: ('bw_timeline ' + className).trim() },
3614
+ a: { class: ('bw_bccl_timeline ' + className).trim() },
3454
3615
  c: items.map(function(item) {
3455
3616
  return {
3456
3617
  t: 'div',
3457
- a: { class: 'bw_timeline_item' },
3618
+ a: { class: 'bw_bccl_timeline_item' },
3458
3619
  c: [
3459
3620
  {
3460
3621
  t: 'div',
3461
- a: { class: 'bw_timeline_marker ' + variantClass(item.variant || 'primary') }
3622
+ a: { class: 'bw_bccl_timeline_marker ' + variantClass(item.variant || 'primary') }
3462
3623
  },
3463
3624
  {
3464
3625
  t: 'div',
3465
- a: { class: 'bw_timeline_content' },
3626
+ a: { class: 'bw_bccl_timeline_content' },
3466
3627
  c: [
3467
3628
  item.date && {
3468
3629
  t: 'div',
3469
- a: { class: 'bw_timeline_date' },
3630
+ a: { class: 'bw_bccl_timeline_date' },
3470
3631
  c: item.date
3471
3632
  },
3472
3633
  item.title && {
3473
3634
  t: 'h5',
3474
- a: { class: 'bw_timeline_title' },
3635
+ a: { class: 'bw_bccl_timeline_title' },
3475
3636
  c: item.title
3476
3637
  },
3477
3638
  item.content && (typeof item.content === 'string'
3478
- ? { t: 'p', a: { class: 'bw_timeline_text' }, c: item.content }
3639
+ ? { t: 'p', a: { class: 'bw_bccl_timeline_text' }, c: item.content }
3479
3640
  : item.content)
3480
3641
  ].filter(Boolean)
3481
3642
  }
@@ -3520,7 +3681,7 @@ function makeStepper(props = {}) {
3520
3681
 
3521
3682
  return {
3522
3683
  t: 'div',
3523
- a: { class: ('bw_stepper ' + className).trim(), role: 'list' },
3684
+ a: { class: ('bw_bccl_stepper bw_stepper ' + className).trim(), role: 'list' },
3524
3685
  c: steps.map(function(step, index) {
3525
3686
  var state = index < currentStep ? 'completed' : index === currentStep ? 'active' : 'pending';
3526
3687
  return {
@@ -3609,7 +3770,7 @@ function makeChipInput(props = {}) {
3609
3770
 
3610
3771
  return {
3611
3772
  t: 'div',
3612
- a: { class: ('bw_chip_input ' + className).trim() },
3773
+ a: { class: ('bw_bccl_chipInput bw_chip_input ' + className).trim() },
3613
3774
  c: [
3614
3775
  ...chips.map(makeChipEl),
3615
3776
  {
@@ -3645,8 +3806,8 @@ function makeChipInput(props = {}) {
3645
3806
  }
3646
3807
  // Backspace on empty input removes last chip
3647
3808
  if (e.key === 'Backspace' && !e.target.value) {
3648
- var wrapper = e.target.closest('.bw_chip_input');
3649
- var chipEls = wrapper.querySelectorAll('.bw_chip');
3809
+ var chipWrapper = e.target.closest('.bw_chip_input');
3810
+ var chipEls = chipWrapper.querySelectorAll('.bw_chip');
3650
3811
  if (chipEls.length) {
3651
3812
  var last = chipEls[chipEls.length - 1];
3652
3813
  var removedVal = last._bw_chipValue || last.firstChild.textContent;
@@ -3896,13 +4057,13 @@ function registerBCCL(bw) {
3896
4057
  bw.variantClass = variantClass;
3897
4058
 
3898
4059
  // Create functions that return DOM elements
3899
- if (typeof bw.createDOM === 'function') {
4060
+ if (typeof bw.create === 'function') {
3900
4061
  Object.entries(components).forEach(function(entry) {
3901
4062
  var name = entry[0], fn = entry[1];
3902
4063
  if (name.indexOf('make') === 0) {
3903
4064
  var createName = 'create' + name.substring(4);
3904
4065
  bw[createName] = function(props) {
3905
- return bw.createDOM(fn(props));
4066
+ return bw.create(fn(props));
3906
4067
  };
3907
4068
  }
3908
4069
  });