bitwrench 2.0.17 → 2.0.19

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 (72) hide show
  1. package/README.md +169 -75
  2. package/dist/bitwrench-bccl.cjs.js +228 -55
  3. package/dist/bitwrench-bccl.cjs.min.js +3 -3
  4. package/dist/bitwrench-bccl.esm.js +228 -55
  5. package/dist/bitwrench-bccl.esm.min.js +3 -3
  6. package/dist/bitwrench-bccl.umd.js +228 -55
  7. package/dist/bitwrench-bccl.umd.min.js +3 -3
  8. package/dist/bitwrench-code-edit.cjs.js +7 -9
  9. package/dist/bitwrench-code-edit.cjs.min.js +5 -7
  10. package/dist/bitwrench-code-edit.es5.js +6 -8
  11. package/dist/bitwrench-code-edit.es5.min.js +5 -7
  12. package/dist/bitwrench-code-edit.esm.js +7 -9
  13. package/dist/bitwrench-code-edit.esm.min.js +5 -7
  14. package/dist/bitwrench-code-edit.umd.js +7 -9
  15. package/dist/bitwrench-code-edit.umd.min.js +5 -7
  16. package/dist/bitwrench-debug.js +268 -0
  17. package/dist/bitwrench-debug.min.js +3 -0
  18. package/dist/bitwrench-lean.cjs.js +1190 -2348
  19. package/dist/bitwrench-lean.cjs.min.js +20 -20
  20. package/dist/bitwrench-lean.es5.js +1285 -2551
  21. package/dist/bitwrench-lean.es5.min.js +18 -18
  22. package/dist/bitwrench-lean.esm.js +1190 -2348
  23. package/dist/bitwrench-lean.esm.min.js +20 -20
  24. package/dist/bitwrench-lean.umd.js +1190 -2348
  25. package/dist/bitwrench-lean.umd.min.js +20 -20
  26. package/dist/bitwrench-util-css.cjs.js +236 -0
  27. package/dist/bitwrench-util-css.cjs.min.js +22 -0
  28. package/dist/bitwrench-util-css.es5.js +414 -0
  29. package/dist/bitwrench-util-css.es5.min.js +21 -0
  30. package/dist/bitwrench-util-css.esm.js +230 -0
  31. package/dist/bitwrench-util-css.esm.min.js +21 -0
  32. package/dist/bitwrench-util-css.umd.js +242 -0
  33. package/dist/bitwrench-util-css.umd.min.js +21 -0
  34. package/dist/bitwrench.cjs.js +1404 -2388
  35. package/dist/bitwrench.cjs.min.js +21 -21
  36. package/dist/bitwrench.css +503 -132
  37. package/dist/bitwrench.es5.js +1588 -2659
  38. package/dist/bitwrench.es5.min.js +19 -19
  39. package/dist/bitwrench.esm.js +1405 -2389
  40. package/dist/bitwrench.esm.min.js +21 -21
  41. package/dist/bitwrench.min.css +1 -1
  42. package/dist/bitwrench.umd.js +1404 -2388
  43. package/dist/bitwrench.umd.min.js +21 -21
  44. package/dist/builds.json +214 -104
  45. package/dist/bwserve.cjs.js +514 -68
  46. package/dist/bwserve.esm.js +513 -69
  47. package/dist/sri.json +46 -36
  48. package/package.json +6 -3
  49. package/readme.html +183 -85
  50. package/src/bitwrench-bccl-entry.js +3 -4
  51. package/src/bitwrench-bccl.js +224 -50
  52. package/src/bitwrench-code-edit.js +6 -8
  53. package/src/bitwrench-color-utils.js +31 -9
  54. package/src/bitwrench-debug.js +245 -0
  55. package/src/bitwrench-esm-entry.js +11 -0
  56. package/src/bitwrench-styles.js +474 -240
  57. package/src/bitwrench-util-css.js +229 -0
  58. package/src/bitwrench.js +689 -2042
  59. package/src/bwserve/attach.js +57 -0
  60. package/src/bwserve/bwclient.js +141 -0
  61. package/src/bwserve/bwshell.js +102 -0
  62. package/src/bwserve/client.js +151 -1
  63. package/src/bwserve/index.js +127 -28
  64. package/src/cli/attach.js +587 -0
  65. package/src/cli/convert.js +2 -5
  66. package/src/cli/index.js +7 -0
  67. package/src/cli/inject.js +1 -1
  68. package/src/cli/serve.js +185 -5
  69. package/src/generate-css.js +11 -4
  70. package/src/vendor/html2canvas.min.js +20 -0
  71. package/src/version.js +3 -3
  72. package/src/bwserve/shell.js +0 -106
@@ -1,4 +1,4 @@
1
- /*! bitwrench-bccl v2.0.17 | BSD-2-Clause | https://deftio.github.com/bitwrench/pages */
1
+ /*! bitwrench-bccl v2.0.19 | BSD-2-Clause | https://deftio.github.com/bitwrench/pages */
2
2
  /**
3
3
  * Bitwrench v2 Components
4
4
  *
@@ -173,7 +173,12 @@ function makeCard(props = {}) {
173
173
  },
174
174
  o: {
175
175
  type: 'card',
176
- state: props.state || {}
176
+ state: props.state || {},
177
+ slots: {
178
+ title: '.bw_card_title',
179
+ content: '.bw_card_body',
180
+ footer: '.bw_card_footer'
181
+ }
177
182
  }
178
183
  };
179
184
  }
@@ -184,7 +189,12 @@ function makeCard(props = {}) {
184
189
  c: cardContent,
185
190
  o: {
186
191
  type: 'card',
187
- state: props.state || {}
192
+ state: props.state || {},
193
+ slots: {
194
+ title: '.bw_card_title',
195
+ content: '.bw_card_body',
196
+ footer: '.bw_card_footer'
197
+ }
188
198
  }
189
199
  };
190
200
  }
@@ -328,7 +338,7 @@ function makeCol(props = {}) {
328
338
  if (breakpoint === 'xs') {
329
339
  classes.push(`bw_col_${value}`);
330
340
  } else {
331
- classes.push(`bw_col_${breakpoint}-${value}`);
341
+ classes.push(`bw_col_${breakpoint}_${value}`);
332
342
  }
333
343
  });
334
344
  } else if (size) {
@@ -502,6 +512,24 @@ function makeTabs(props = {}) {
502
512
  }
503
513
  });
504
514
 
515
+ // Shared tab switching logic
516
+ function switchTab(el, index) {
517
+ var allTabs = el.querySelectorAll('.bw_nav_link');
518
+ var allPanes = el.querySelectorAll('.bw_tab_pane');
519
+ if (index < 0 || index >= allTabs.length) return;
520
+ allTabs.forEach(function(t) {
521
+ t.classList.remove('active');
522
+ t.setAttribute('aria-selected', 'false');
523
+ t.setAttribute('tabindex', '-1');
524
+ });
525
+ allPanes.forEach(function(p) { p.classList.remove('active'); });
526
+ allTabs[index].classList.add('active');
527
+ allTabs[index].setAttribute('aria-selected', 'true');
528
+ allTabs[index].setAttribute('tabindex', '0');
529
+ allPanes[index].classList.add('active');
530
+ if (el._bw_state) el._bw_state.activeIndex = index;
531
+ }
532
+
505
533
  return {
506
534
  t: 'div',
507
535
  a: { class: 'bw_tabs' },
@@ -520,24 +548,8 @@ function makeTabs(props = {}) {
520
548
  role: 'tab',
521
549
  tabindex: index === actualActiveIndex ? '0' : '-1',
522
550
  'aria-selected': index === actualActiveIndex ? 'true' : 'false',
523
- 'data-tab-index': index,
524
551
  onclick: (e) => {
525
- const tabsContainer = e.target.closest('.bw_tabs');
526
- const allTabs = tabsContainer.querySelectorAll('.bw_nav_link');
527
- const allPanes = tabsContainer.querySelectorAll('.bw_tab_pane');
528
-
529
- allTabs.forEach(t => {
530
- t.classList.remove('active');
531
- t.setAttribute('aria-selected', 'false');
532
- t.setAttribute('tabindex', '-1');
533
- });
534
- allPanes.forEach(p => p.classList.remove('active'));
535
-
536
- e.target.classList.add('active');
537
- e.target.setAttribute('aria-selected', 'true');
538
- e.target.setAttribute('tabindex', '0');
539
- const targetIndex = parseInt(e.target.getAttribute('data-tab-index'));
540
- allPanes[targetIndex].classList.add('active');
552
+ switchTab(e.target.closest('.bw_tabs'), index);
541
553
  }
542
554
  },
543
555
  c: tab.label
@@ -560,6 +572,10 @@ function makeTabs(props = {}) {
560
572
  o: {
561
573
  type: 'tabs',
562
574
  state: { activeIndex: actualActiveIndex },
575
+ handle: {
576
+ setActiveTab: switchTab,
577
+ getActiveTab: function(el) { return (el._bw_state && el._bw_state.activeIndex) || 0; }
578
+ },
563
579
  mounted: function(el) {
564
580
  var tablist = el.querySelector('[role="tablist"]');
565
581
  if (!tablist) return;
@@ -645,7 +661,13 @@ function makeAlert(props = {}) {
645
661
  },
646
662
  c: '×'
647
663
  }
648
- ].filter(Boolean)
664
+ ].filter(Boolean),
665
+ o: {
666
+ type: 'alert',
667
+ handle: {
668
+ dismiss: function(el) { if (el && el.parentNode) el.parentNode.removeChild(el); }
669
+ }
670
+ }
649
671
  };
650
672
  }
651
673
 
@@ -743,6 +765,24 @@ function makeProgress(props = {}) {
743
765
  'aria-valuemax': max
744
766
  },
745
767
  c: label || `${percentage}%`
768
+ },
769
+ o: {
770
+ type: 'progress',
771
+ handle: {
772
+ setValue: function(el, n) {
773
+ var bar = el.querySelector('.bw_progress_bar');
774
+ if (!bar) return;
775
+ var maxVal = parseInt(bar.getAttribute('aria-valuemax')) || 100;
776
+ var pct = Math.round((n / maxVal) * 100);
777
+ bar.style.width = pct + '%';
778
+ bar.setAttribute('aria-valuenow', n);
779
+ bar.textContent = pct + '%';
780
+ },
781
+ getValue: function(el) {
782
+ var bar = el.querySelector('.bw_progress_bar');
783
+ return bar ? parseInt(bar.getAttribute('aria-valuenow')) || 0 : 0;
784
+ }
785
+ }
746
786
  }
747
787
  };
748
788
  }
@@ -1711,8 +1751,8 @@ function makePagination(props = {}) {
1711
1751
  t: 'li',
1712
1752
  a: { class: `bw_page_item ${currentPage <= 1 ? 'bw_disabled' : ''}`.trim() },
1713
1753
  c: {
1714
- t: 'a',
1715
- a: { class: 'bw_page_link', href: '#', onclick: handleClick(currentPage - 1), 'aria-label': 'Previous' },
1754
+ t: 'button',
1755
+ a: { class: 'bw_page_link', type: 'button', onclick: handleClick(currentPage - 1), 'aria-label': 'Previous', disabled: currentPage <= 1 ? true : undefined },
1716
1756
  c: '\u2039'
1717
1757
  }
1718
1758
  });
@@ -1724,8 +1764,8 @@ function makePagination(props = {}) {
1724
1764
  t: 'li',
1725
1765
  a: { class: `bw_page_item ${pageNum === currentPage ? 'bw_active' : ''}`.trim() },
1726
1766
  c: {
1727
- t: 'a',
1728
- a: { class: 'bw_page_link', href: '#', onclick: handleClick(pageNum) },
1767
+ t: 'button',
1768
+ a: { class: 'bw_page_link', type: 'button', onclick: handleClick(pageNum), 'aria-current': pageNum === currentPage ? 'page' : undefined },
1729
1769
  c: '' + pageNum
1730
1770
  }
1731
1771
  });
@@ -1737,8 +1777,8 @@ function makePagination(props = {}) {
1737
1777
  t: 'li',
1738
1778
  a: { class: `bw_page_item ${currentPage >= pages ? 'bw_disabled' : ''}`.trim() },
1739
1779
  c: {
1740
- t: 'a',
1741
- a: { class: 'bw_page_link', href: '#', onclick: handleClick(currentPage + 1), 'aria-label': 'Next' },
1780
+ t: 'button',
1781
+ a: { class: 'bw_page_link', type: 'button', onclick: handleClick(currentPage + 1), 'aria-label': 'Next', disabled: currentPage >= pages ? true : undefined },
1742
1782
  c: '\u203A'
1743
1783
  }
1744
1784
  });
@@ -1752,6 +1792,26 @@ function makePagination(props = {}) {
1752
1792
  class: `bw_pagination ${size ? 'bw_pagination_' + size : ''} ${className}`.trim()
1753
1793
  },
1754
1794
  c: items
1795
+ },
1796
+ o: {
1797
+ type: 'pagination',
1798
+ state: { currentPage: currentPage, pages: pages },
1799
+ handle: {
1800
+ setPage: function(el, n) {
1801
+ if (n < 1 || n > pages) return;
1802
+ var allItems = el.querySelectorAll('.bw_page_item');
1803
+ for (var i = 0; i < allItems.length; i++) {
1804
+ allItems[i].classList.remove('bw_active');
1805
+ }
1806
+ // +1 offset: first item is prev arrow
1807
+ if (allItems[n]) allItems[n].classList.add('bw_active');
1808
+ if (el._bw_state) el._bw_state.currentPage = n;
1809
+ if (onPageChange) onPageChange(n);
1810
+ },
1811
+ getPage: function(el) {
1812
+ return (el._bw_state && el._bw_state.currentPage) || 1;
1813
+ }
1814
+ }
1755
1815
  }
1756
1816
  };
1757
1817
  }
@@ -1900,7 +1960,6 @@ function makeAccordion(props = {}) {
1900
1960
  class: `bw_accordion_button ${item.open ? '' : 'bw_collapsed'}`.trim(),
1901
1961
  type: 'button',
1902
1962
  'aria-expanded': item.open ? 'true' : 'false',
1903
- 'data-accordion-index': index,
1904
1963
  onclick: function(e) {
1905
1964
  var btn = e.target.closest('.bw_accordion_button');
1906
1965
  var accordionEl = btn.closest('.bw_accordion');
@@ -1975,7 +2034,43 @@ function makeAccordion(props = {}) {
1975
2034
  }),
1976
2035
  o: {
1977
2036
  type: 'accordion',
1978
- state: { multiOpen: multiOpen }
2037
+ state: { multiOpen: multiOpen },
2038
+ handle: {
2039
+ toggle: function(el, index) {
2040
+ var items = el.querySelectorAll('.bw_accordion_item');
2041
+ if (index < 0 || index >= items.length) return;
2042
+ var btn = items[index].querySelector('.bw_accordion_button');
2043
+ if (btn) btn.click();
2044
+ },
2045
+ openAll: function(el) {
2046
+ var items = el.querySelectorAll('.bw_accordion_item');
2047
+ 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');
2050
+ if (!collapse.classList.contains('bw_collapse_show')) {
2051
+ collapse.classList.add('bw_collapse_show');
2052
+ collapse.style.maxHeight = 'none';
2053
+ btn.classList.remove('bw_collapsed');
2054
+ btn.setAttribute('aria-expanded', 'true');
2055
+ }
2056
+ }
2057
+ },
2058
+ closeAll: function(el) {
2059
+ var items = el.querySelectorAll('.bw_accordion_item');
2060
+ 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');
2063
+ if (collapse.classList.contains('bw_collapse_show')) {
2064
+ collapse.style.maxHeight = collapse.scrollHeight + 'px';
2065
+ collapse.offsetHeight;
2066
+ collapse.style.maxHeight = '0px';
2067
+ collapse.classList.remove('bw_collapse_show');
2068
+ btn.classList.add('bw_collapsed');
2069
+ btn.setAttribute('aria-expanded', 'false');
2070
+ }
2071
+ }
2072
+ }
2073
+ }
1979
2074
  }
1980
2075
  };
1981
2076
  }
@@ -2065,6 +2160,14 @@ function makeModal(props = {}) {
2065
2160
  },
2066
2161
  o: {
2067
2162
  type: 'modal',
2163
+ handle: {
2164
+ open: function(el) {
2165
+ el.classList.add('bw_modal_show');
2166
+ el.style.display = 'flex';
2167
+ document.body.style.overflow = 'hidden';
2168
+ },
2169
+ close: function(el) { closeModal(el); }
2170
+ },
2068
2171
  mounted: function(el) {
2069
2172
  // Click backdrop to close
2070
2173
  el.addEventListener('click', function(e) {
@@ -2123,9 +2226,8 @@ function makeToast(props = {}) {
2123
2226
  return {
2124
2227
  t: 'div',
2125
2228
  a: {
2126
- class: `bw_toast ${variantClass(variant)} ${className}`.trim(),
2127
- role: 'alert',
2128
- 'data-position': position
2229
+ class: `bw_toast ${variantClass(variant)} bw_toast_${position.replace(/-/g, '_')} ${className}`.trim(),
2230
+ role: 'alert'
2129
2231
  },
2130
2232
  c: [
2131
2233
  (title) && {
@@ -2159,6 +2261,12 @@ function makeToast(props = {}) {
2159
2261
  ].filter(Boolean),
2160
2262
  o: {
2161
2263
  type: 'toast',
2264
+ handle: {
2265
+ dismiss: function(el) {
2266
+ el.classList.add('bw_toast_hiding');
2267
+ setTimeout(function() { if (el.parentNode) el.parentNode.removeChild(el); }, 300);
2268
+ }
2269
+ },
2162
2270
  mounted: function(el) {
2163
2271
  // Trigger show animation
2164
2272
  requestAnimationFrame(function() {
@@ -2516,7 +2624,7 @@ function makeCarousel(props = {}) {
2516
2624
  var total = carouselEl.querySelectorAll('.bw_carousel_slide').length;
2517
2625
  if (index < 0) index = total - 1;
2518
2626
  if (index >= total) index = 0;
2519
- carouselEl.setAttribute('data-carousel-index', index);
2627
+ carouselEl._bw_carouselIndex = index;
2520
2628
  var track = carouselEl.querySelector('.bw_carousel_track');
2521
2629
  track.style.transform = 'translateX(-' + (index * 100) + '%)';
2522
2630
  // Update indicators
@@ -2573,7 +2681,7 @@ function makeCarousel(props = {}) {
2573
2681
  'aria-label': 'Previous slide',
2574
2682
  onclick: function(e) {
2575
2683
  var carousel = e.target.closest('.bw_carousel');
2576
- var idx = parseInt(carousel.getAttribute('data-carousel-index') || '0');
2684
+ var idx = carousel._bw_carouselIndex || 0;
2577
2685
  goToSlide(carousel, idx - 1);
2578
2686
  }
2579
2687
  },
@@ -2587,7 +2695,7 @@ function makeCarousel(props = {}) {
2587
2695
  'aria-label': 'Next slide',
2588
2696
  onclick: function(e) {
2589
2697
  var carousel = e.target.closest('.bw_carousel');
2590
- var idx = parseInt(carousel.getAttribute('data-carousel-index') || '0');
2698
+ var idx = carousel._bw_carouselIndex || 0;
2591
2699
  goToSlide(carousel, idx + 1);
2592
2700
  }
2593
2701
  },
@@ -2607,11 +2715,9 @@ function makeCarousel(props = {}) {
2607
2715
  class: 'bw_carousel_indicator' + (i === startIndex ? ' active' : ''),
2608
2716
  type: 'button',
2609
2717
  'aria-label': 'Go to slide ' + (i + 1),
2610
- 'data-slide-index': i,
2611
2718
  onclick: function(e) {
2612
2719
  var carousel = e.target.closest('.bw_carousel');
2613
- var idx = parseInt(e.target.getAttribute('data-slide-index'));
2614
- goToSlide(carousel, idx);
2720
+ goToSlide(carousel, i);
2615
2721
  }
2616
2722
  }
2617
2723
  };
@@ -2625,17 +2731,37 @@ function makeCarousel(props = {}) {
2625
2731
  class: ('bw_carousel ' + className).trim(),
2626
2732
  style: 'height: ' + height,
2627
2733
  tabindex: '0',
2628
- 'aria-roledescription': 'carousel',
2629
- 'data-carousel-index': startIndex
2734
+ 'aria-roledescription': 'carousel'
2630
2735
  },
2631
2736
  c: children,
2632
2737
  o: {
2633
2738
  type: 'carousel',
2634
2739
  state: { activeIndex: startIndex, autoPlay: autoPlay, interval: interval },
2740
+ handle: {
2741
+ goToSlide: function(el, index) { goToSlide(el, index); },
2742
+ next: function(el) { goToSlide(el, (el._bw_carouselIndex || 0) + 1); },
2743
+ prev: function(el) { goToSlide(el, (el._bw_carouselIndex || 0) - 1); },
2744
+ getActiveIndex: function(el) { return el._bw_carouselIndex || 0; },
2745
+ pause: function(el) {
2746
+ if (el._bw_carouselInterval) {
2747
+ clearInterval(el._bw_carouselInterval);
2748
+ el._bw_carouselInterval = null;
2749
+ }
2750
+ },
2751
+ play: function(el) {
2752
+ if (!el._bw_carouselInterval && el._bw_state) {
2753
+ var ms = el._bw_state.interval || 5000;
2754
+ el._bw_carouselInterval = setInterval(function() {
2755
+ goToSlide(el, (el._bw_carouselIndex || 0) + 1);
2756
+ }, ms);
2757
+ }
2758
+ }
2759
+ },
2635
2760
  mounted: function(el) {
2761
+ el._bw_carouselIndex = startIndex;
2636
2762
  // Keyboard navigation
2637
2763
  el.addEventListener('keydown', function(e) {
2638
- var idx = parseInt(el.getAttribute('data-carousel-index') || '0');
2764
+ var idx = el._bw_carouselIndex || 0;
2639
2765
  if (e.key === 'ArrowLeft') {
2640
2766
  e.preventDefault();
2641
2767
  goToSlide(el, idx - 1);
@@ -2647,7 +2773,7 @@ function makeCarousel(props = {}) {
2647
2773
  // Auto-play
2648
2774
  if (autoPlay) {
2649
2775
  var intervalId = setInterval(function() {
2650
- var idx = parseInt(el.getAttribute('data-carousel-index') || '0');
2776
+ var idx = el._bw_carouselIndex || 0;
2651
2777
  goToSlide(el, idx + 1);
2652
2778
  }, interval);
2653
2779
  el._bw_carouselInterval = intervalId;
@@ -2657,7 +2783,7 @@ function makeCarousel(props = {}) {
2657
2783
  });
2658
2784
  el.addEventListener('mouseleave', function() {
2659
2785
  el._bw_carouselInterval = setInterval(function() {
2660
- var idx = parseInt(el.getAttribute('data-carousel-index') || '0');
2786
+ var idx = el._bw_carouselIndex || 0;
2661
2787
  goToSlide(el, idx + 1);
2662
2788
  }, interval);
2663
2789
  });
@@ -2773,7 +2899,13 @@ function makeStatCard(props = {}) {
2773
2899
  t: 'div',
2774
2900
  a: { class: classes, style: style },
2775
2901
  c: children,
2776
- o: { type: 'stat-card' }
2902
+ o: {
2903
+ type: 'stat-card',
2904
+ slots: {
2905
+ value: '.bw_stat_value',
2906
+ label: '.bw_stat_label'
2907
+ }
2908
+ }
2777
2909
  };
2778
2910
  }
2779
2911
 
@@ -3452,7 +3584,7 @@ function makeChipInput(props = {}) {
3452
3584
  function makeChipEl(text) {
3453
3585
  return {
3454
3586
  t: 'span',
3455
- a: { class: 'bw_chip', 'data-chip-value': text },
3587
+ a: { class: 'bw_chip' },
3456
3588
  c: [
3457
3589
  text,
3458
3590
  {
@@ -3463,9 +3595,8 @@ function makeChipInput(props = {}) {
3463
3595
  'aria-label': 'Remove ' + text,
3464
3596
  onclick: function(e) {
3465
3597
  var chip = e.target.closest('.bw_chip');
3466
- var val = chip.getAttribute('data-chip-value');
3467
3598
  chip.parentNode.removeChild(chip);
3468
- if (onRemove) onRemove(val);
3599
+ if (onRemove) onRemove(text);
3469
3600
  }
3470
3601
  },
3471
3602
  c: '\u00D7'
@@ -3493,7 +3624,7 @@ function makeChipInput(props = {}) {
3493
3624
  // Insert chip before the input
3494
3625
  var chipEl = document.createElement('span');
3495
3626
  chipEl.className = 'bw_chip';
3496
- chipEl.setAttribute('data-chip-value', val);
3627
+ chipEl._bw_chipValue = val;
3497
3628
  chipEl.innerHTML = '';
3498
3629
  chipEl.textContent = val;
3499
3630
  var removeBtn = document.createElement('button');
@@ -3516,7 +3647,7 @@ function makeChipInput(props = {}) {
3516
3647
  var chipEls = wrapper.querySelectorAll('.bw_chip');
3517
3648
  if (chipEls.length) {
3518
3649
  var last = chipEls[chipEls.length - 1];
3519
- var removedVal = last.getAttribute('data-chip-value');
3650
+ var removedVal = last._bw_chipValue || last.firstChild.textContent;
3520
3651
  last.parentNode.removeChild(last);
3521
3652
  if (onRemove) onRemove(removedVal);
3522
3653
  }
@@ -3525,7 +3656,50 @@ function makeChipInput(props = {}) {
3525
3656
  }
3526
3657
  }
3527
3658
  ],
3528
- o: { type: 'chip-input' }
3659
+ o: {
3660
+ type: 'chip-input',
3661
+ handle: {
3662
+ addChip: function(el, text) {
3663
+ if (!text) return;
3664
+ var input = el.querySelector('.bw_chip_field');
3665
+ var chipEl = document.createElement('span');
3666
+ chipEl.className = 'bw_chip';
3667
+ chipEl._bw_chipValue = text;
3668
+ chipEl.textContent = text;
3669
+ var removeBtn = document.createElement('button');
3670
+ removeBtn.type = 'button';
3671
+ removeBtn.className = 'bw_chip_remove';
3672
+ removeBtn.setAttribute('aria-label', 'Remove ' + text);
3673
+ removeBtn.textContent = '\u00D7';
3674
+ removeBtn.onclick = function() { chipEl.parentNode.removeChild(chipEl); };
3675
+ chipEl.appendChild(removeBtn);
3676
+ el.insertBefore(chipEl, input);
3677
+ },
3678
+ removeChip: function(el, text) {
3679
+ var chips = el.querySelectorAll('.bw_chip');
3680
+ for (var i = 0; i < chips.length; i++) {
3681
+ if ((chips[i]._bw_chipValue || chips[i].firstChild.textContent) === text) {
3682
+ chips[i].parentNode.removeChild(chips[i]);
3683
+ return;
3684
+ }
3685
+ }
3686
+ },
3687
+ getChips: function(el) {
3688
+ var chips = el.querySelectorAll('.bw_chip');
3689
+ var values = [];
3690
+ for (var i = 0; i < chips.length; i++) {
3691
+ values.push(chips[i]._bw_chipValue || chips[i].firstChild.textContent);
3692
+ }
3693
+ return values;
3694
+ },
3695
+ clear: function(el) {
3696
+ var chips = el.querySelectorAll('.bw_chip');
3697
+ for (var i = chips.length - 1; i >= 0; i--) {
3698
+ chips[i].parentNode.removeChild(chips[i]);
3699
+ }
3700
+ }
3701
+ }
3702
+ }
3529
3703
  };
3530
3704
  }
3531
3705
 
@@ -3719,15 +3893,14 @@ function registerBCCL(bw) {
3719
3893
  // Variant class helper
3720
3894
  bw.variantClass = variantClass;
3721
3895
 
3722
- // Create functions that return handles
3723
- if (typeof bw.renderComponent === 'function') {
3896
+ // Create functions that return DOM elements
3897
+ if (typeof bw.createDOM === 'function') {
3724
3898
  Object.entries(components).forEach(function(entry) {
3725
3899
  var name = entry[0], fn = entry[1];
3726
3900
  if (name.indexOf('make') === 0) {
3727
3901
  var createName = 'create' + name.substring(4);
3728
3902
  bw[createName] = function(props) {
3729
- var taco = fn(props);
3730
- return bw.renderComponent(taco);
3903
+ return bw.createDOM(fn(props));
3731
3904
  };
3732
3905
  }
3733
3906
  });