bitwrench 2.0.11 → 2.0.12

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.
@@ -1,4 +1,4 @@
1
- /*! bitwrench-lean v2.0.11 | BSD-2-Clause | https://deftio.github.com/bitwrench/pages */
1
+ /*! bitwrench-lean v2.0.12 | BSD-2-Clause | https://deftio.github.com/bitwrench/pages */
2
2
  (function (global, factory) {
3
3
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
4
4
  typeof define === 'function' && define.amd ? define(factory) :
@@ -11,14 +11,14 @@
11
11
  */
12
12
 
13
13
  const VERSION_INFO = {
14
- version: '2.0.11',
14
+ version: '2.0.12',
15
15
  name: 'bitwrench',
16
16
  description: 'A library for javascript UI functions.',
17
17
  license: 'BSD-2-Clause',
18
18
  homepage: 'https://deftio.github.com/bitwrench/pages',
19
19
  repository: 'git+https://github.com/deftio/bitwrench.git',
20
20
  author: 'manu a. chatterjee <deftio@deftio.com> (https://deftio.com/)',
21
- buildDate: '2026-03-07T11:05:08.522Z'
21
+ buildDate: '2026-03-07T22:31:35.755Z'
22
22
  };
23
23
 
24
24
  /**
@@ -893,15 +893,36 @@
893
893
  rules[scopeSelector(scope, '.bw-accordion-button')] = {
894
894
  'color': palette.dark.base
895
895
  };
896
+ rules[scopeSelector(scope, '.bw-accordion-button:not(.bw-collapsed)')] = {
897
+ 'color': palette.primary.darkText,
898
+ 'background-color': palette.primary.light
899
+ };
896
900
  rules[scopeSelector(scope, '.bw-accordion-button:hover')] = {
897
901
  'background-color': palette.light.light
898
902
  };
903
+ rules[scopeSelector(scope, '.bw-accordion-button:not(.bw-collapsed):hover')] = {
904
+ 'background-color': palette.primary.hover
905
+ };
906
+ rules[scopeSelector(scope, '.bw-accordion-button:focus-visible')] = {
907
+ 'box-shadow': '0 0 0 0.2rem ' + palette.primary.focus
908
+ };
899
909
  rules[scopeSelector(scope, '.bw-accordion-body')] = {
900
910
  'border-top': '1px solid ' + palette.light.border
901
911
  };
902
912
  return rules;
903
913
  }
904
914
 
915
+ function generateCarouselThemed(scope, palette) {
916
+ var rules = {};
917
+ rules[scopeSelector(scope, '.bw-carousel')] = {
918
+ 'background-color': palette.light.light
919
+ };
920
+ rules[scopeSelector(scope, '.bw-carousel-indicator.active')] = {
921
+ 'background-color': palette.primary.base
922
+ };
923
+ return rules;
924
+ }
925
+
905
926
  function generateModalThemed(scope, palette) {
906
927
  var rules = {};
907
928
  rules[scopeSelector(scope, '.bw-modal-content')] = {
@@ -982,7 +1003,7 @@
982
1003
  function generateSkeletonThemed(scope, palette) {
983
1004
  var rules = {};
984
1005
  rules[scopeSelector(scope, '.bw-skeleton')] = {
985
- 'background-color': palette.light.border
1006
+ 'background': 'linear-gradient(90deg, ' + palette.light.border + ' 25%, ' + palette.light.light + ' 37%, ' + palette.light.border + ' 63%)'
986
1007
  };
987
1008
  return rules;
988
1009
  }
@@ -1029,6 +1050,7 @@
1029
1050
  generateCloseButtonThemed(scopeName, palette),
1030
1051
  generateSectionsThemed(scopeName, palette),
1031
1052
  generateAccordionThemed(scopeName, palette),
1053
+ generateCarouselThemed(scopeName, palette),
1032
1054
  generateModalThemed(scopeName, palette),
1033
1055
  generateToastThemed(scopeName, palette),
1034
1056
  generateDropdownThemed(scopeName, palette),
@@ -1388,6 +1410,8 @@
1388
1410
  rules['.bw-tab-content'] = { 'padding': '1.25rem 0' };
1389
1411
  rules['.bw-tab-pane'] = { 'display': 'none' };
1390
1412
  rules['.bw-tab-pane.active'] = { 'display': 'block' };
1413
+ rules['.bw-nav-scrollable'] = { 'flex-wrap': 'nowrap', 'overflow-x': 'auto', '-webkit-overflow-scrolling': 'touch', 'scrollbar-width': 'none' };
1414
+ rules['.bw-nav-scrollable .bw-nav-link'] = { 'white-space': 'nowrap' };
1391
1415
 
1392
1416
  // List groups (structural)
1393
1417
  rules['.bw-list-group'] = { 'display': 'flex', 'flex-direction': 'column', 'padding-left': '0', 'margin-bottom': '0', 'border-radius': '0.375rem' };
@@ -1554,6 +1578,29 @@
1554
1578
  rules['.bw-modal-body'] = { 'position': 'relative', 'flex': '1 1 auto', 'padding': '1.5rem' };
1555
1579
  rules['.bw-modal-footer'] = { 'display': 'flex', 'flex-wrap': 'wrap', 'align-items': 'center', 'justify-content': 'flex-end', 'padding': '0.75rem 1.5rem', 'gap': '0.5rem' };
1556
1580
 
1581
+ // Carousel (structural)
1582
+ rules['.bw-carousel'] = { 'position': 'relative', 'overflow': 'hidden', 'border-radius': '8px' };
1583
+ rules['.bw-carousel-track'] = { 'display': 'flex', 'transition': 'transform 0.4s ease', 'height': '100%' };
1584
+ rules['.bw-carousel-slide'] = { 'min-width': '100%', 'flex-shrink': '0', 'overflow': 'hidden', 'position': 'relative', 'display': 'flex', 'align-items': 'center', 'justify-content': 'center' };
1585
+ rules['.bw-carousel-slide img'] = { 'width': '100%', 'height': '100%', 'object-fit': 'cover' };
1586
+ rules['.bw-carousel-caption'] = { 'position': 'absolute', 'bottom': '0', 'left': '0', 'right': '0', 'padding': '0.75rem 1rem' };
1587
+ rules['.bw-carousel-control'] = {
1588
+ 'position': 'absolute', 'top': '50%', 'transform': 'translateY(-50%)', 'width': '40px', 'height': '40px',
1589
+ 'border': 'none', 'border-radius': '50%', 'cursor': 'pointer', 'display': 'flex', 'align-items': 'center',
1590
+ 'justify-content': 'center', 'z-index': '2', 'padding': '0', 'transition': 'background-color 0.2s ease'
1591
+ };
1592
+ rules['.bw-carousel-control img'] = { 'width': '20px', 'height': '20px', 'pointer-events': 'none' };
1593
+ rules['.bw-carousel-control-prev'] = { 'left': '10px' };
1594
+ rules['.bw-carousel-control-next'] = { 'right': '10px' };
1595
+ rules['.bw-carousel-indicators'] = {
1596
+ 'position': 'absolute', 'bottom': '12px', 'left': '50%', 'transform': 'translateX(-50%)',
1597
+ 'display': 'flex', 'gap': '6px', 'z-index': '2'
1598
+ };
1599
+ rules['.bw-carousel-indicator'] = {
1600
+ 'width': '10px', 'height': '10px', 'border-radius': '50%', 'border': '2px solid transparent',
1601
+ 'padding': '0', 'cursor': 'pointer', 'transition': 'opacity 0.2s ease, background-color 0.2s ease'
1602
+ };
1603
+
1557
1604
  // Toast (structural)
1558
1605
  rules['.bw-toast-container'] = {
1559
1606
  'position': 'fixed', 'z-index': '1080', 'pointer-events': 'none',
@@ -1603,12 +1650,12 @@
1603
1650
  rules['.bw-form-switch .bw-switch-input:disabled'] = { 'opacity': '0.5', 'cursor': 'not-allowed' };
1604
1651
 
1605
1652
  // Skeleton (structural)
1606
- rules['.bw-skeleton'] = { 'border-radius': '4px', 'animation': 'bw-skeleton-pulse 1.5s ease-in-out infinite' };
1653
+ rules['.bw-skeleton'] = { 'border-radius': '4px', 'background-size': '400% 100%', 'animation': 'bw-skeleton-shimmer 1.4s ease infinite' };
1607
1654
  rules['.bw-skeleton-text'] = { 'height': '1em', 'margin-bottom': '0.5rem' };
1608
1655
  rules['.bw-skeleton-circle'] = { 'border-radius': '50%' };
1609
1656
  rules['.bw-skeleton-rect'] = { 'border-radius': '8px' };
1610
1657
  rules['.bw-skeleton-group'] = { 'display': 'flex', 'flex-direction': 'column' };
1611
- rules['@keyframes bw-skeleton-pulse'] = { '0%': { 'opacity': '1' }, '50%': { 'opacity': '0.4' }, '100%': { 'opacity': '1' } };
1658
+ rules['@keyframes bw-skeleton-shimmer'] = { '0%': { 'background-position': '100% 50%' }, '100%': { 'background-position': '0 50%' } };
1612
1659
 
1613
1660
  // Avatar (structural)
1614
1661
  rules['.bw-avatar'] = {
@@ -1970,12 +2017,31 @@
1970
2017
  '.bw-dark .bw-accordion-button': {
1971
2018
  'color': textColor
1972
2019
  },
2020
+ '.bw-dark .bw-accordion-button:not(.bw-collapsed)': {
2021
+ 'color': '#7dd3e0',
2022
+ 'background-color': 'rgba(125, 211, 224, 0.1)'
2023
+ },
1973
2024
  '.bw-dark .bw-accordion-button:hover': {
1974
2025
  'background-color': bodyBg
1975
2026
  },
2027
+ '.bw-dark .bw-accordion-button:not(.bw-collapsed):hover': {
2028
+ 'background-color': 'rgba(125, 211, 224, 0.15)'
2029
+ },
2030
+ '.bw-dark .bw-accordion-button:focus-visible': {
2031
+ 'box-shadow': '0 0 0 0.2rem rgba(125, 211, 224, 0.3)'
2032
+ },
1976
2033
  '.bw-dark .bw-accordion-body': {
1977
2034
  'border-top-color': borderColor
1978
2035
  },
2036
+ '.bw-dark .bw-carousel': {
2037
+ 'background-color': bodyBg
2038
+ },
2039
+ '.bw-dark .bw-carousel-control': {
2040
+ 'background-color': 'rgba(255,255,255,0.15)'
2041
+ },
2042
+ '.bw-dark .bw-carousel-control:hover': {
2043
+ 'background-color': 'rgba(255,255,255,0.25)'
2044
+ },
1979
2045
  '.bw-dark .bw-modal-content': {
1980
2046
  'background-color': surfaceBg,
1981
2047
  'border-color': borderColor
@@ -2011,7 +2077,7 @@
2011
2077
  'border-top-color': borderColor
2012
2078
  },
2013
2079
  '.bw-dark .bw-skeleton': {
2014
- 'background-color': borderColor
2080
+ 'background': 'linear-gradient(90deg, ' + borderColor + ' 25%, ' + surfaceBg + ' 37%, ' + borderColor + ' 63%)'
2015
2081
  },
2016
2082
  '.bw-dark h1, .bw-dark h2, .bw-dark h3, .bw-dark h4, .bw-dark h5, .bw-dark h6': {
2017
2083
  'color': textColor
@@ -2472,6 +2538,26 @@
2472
2538
  return str.replace(/[&<>"'/]/g, (char) => escapeMap[char]);
2473
2539
  };
2474
2540
 
2541
+ /**
2542
+ * Mark a string as raw HTML so it will not be escaped by bw.html() or bw.createDOM().
2543
+ *
2544
+ * By default, bitwrench escapes all text content to prevent XSS. Use bw.raw()
2545
+ * when you need to embed pre-sanitized HTML, entities, or inline markup.
2546
+ *
2547
+ * @param {string} str - HTML string to mark as raw
2548
+ * @returns {Object} Marked object recognized by bw.html() and bw.createDOM()
2549
+ * @category DOM Generation
2550
+ * @see bw.escapeHTML
2551
+ * @see bw.html
2552
+ * @example
2553
+ * bw.raw('Hello &mdash; World')
2554
+ * // Used in TACO content:
2555
+ * { t: 'p', c: bw.raw('Price: <strong>$9.99</strong>') }
2556
+ */
2557
+ bw.raw = function(str) {
2558
+ return { __bw_raw: true, v: String(str) };
2559
+ };
2560
+
2475
2561
  /**
2476
2562
  * Normalize CSS class names by converting underscores to hyphens for bw-prefixed classes.
2477
2563
  *
@@ -2523,6 +2609,11 @@
2523
2609
  return taco.map(t => bw.html(t, options)).join('');
2524
2610
  }
2525
2611
 
2612
+ // Handle bw.raw() marked content
2613
+ if (taco && taco.__bw_raw) {
2614
+ return taco.v;
2615
+ }
2616
+
2526
2617
  // Handle primitives and non-TACO objects
2527
2618
  if (typeof taco !== 'object' || !taco.t) {
2528
2619
  return options.raw ? String(taco) : bw.escapeHTML(String(taco));
@@ -2623,12 +2714,21 @@
2623
2714
 
2624
2715
  // Handle null/undefined
2625
2716
  if (taco == null) return document.createTextNode('');
2626
-
2717
+
2718
+ // Handle bw.raw() marked content — inject as HTML
2719
+ if (taco && taco.__bw_raw) {
2720
+ var frag = document.createDocumentFragment();
2721
+ var tmp = document.createElement('span');
2722
+ tmp.innerHTML = taco.v;
2723
+ while (tmp.firstChild) frag.appendChild(tmp.firstChild);
2724
+ return frag;
2725
+ }
2726
+
2627
2727
  // Handle text nodes
2628
2728
  if (typeof taco !== 'object' || !taco.t) {
2629
2729
  return document.createTextNode(String(taco));
2630
2730
  }
2631
-
2731
+
2632
2732
  const { t: tag, a: attrs = {}, c: content, o: opts = {} } = taco;
2633
2733
 
2634
2734
  // Create element
@@ -2693,6 +2793,9 @@
2693
2793
  }
2694
2794
  }
2695
2795
  });
2796
+ } else if (typeof content === 'object' && content.__bw_raw) {
2797
+ // Raw HTML content — inject via innerHTML
2798
+ el.innerHTML = content.v;
2696
2799
  } else if (typeof content === 'object' && content.t) {
2697
2800
  var childEl = bw.createDOM(content, options);
2698
2801
  el.appendChild(childEl);