bitwrench 2.0.32 → 2.1.0

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