bitwrench 2.0.17 → 2.0.18
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.
- package/README.md +127 -38
- package/dist/bitwrench-bccl.cjs.js +8 -8
- package/dist/bitwrench-bccl.cjs.min.js +3 -3
- package/dist/bitwrench-bccl.esm.js +8 -8
- package/dist/bitwrench-bccl.esm.min.js +3 -3
- package/dist/bitwrench-bccl.umd.js +8 -8
- package/dist/bitwrench-bccl.umd.min.js +2 -2
- package/dist/bitwrench-code-edit.cjs.js +1 -1
- package/dist/bitwrench-code-edit.cjs.min.js +1 -1
- package/dist/bitwrench-code-edit.es5.js +1 -1
- package/dist/bitwrench-code-edit.es5.min.js +1 -1
- package/dist/bitwrench-code-edit.esm.js +1 -1
- package/dist/bitwrench-code-edit.esm.min.js +1 -1
- package/dist/bitwrench-code-edit.umd.js +1 -1
- package/dist/bitwrench-code-edit.umd.min.js +1 -1
- package/dist/bitwrench-lean.cjs.js +941 -775
- package/dist/bitwrench-lean.cjs.min.js +20 -20
- package/dist/bitwrench-lean.es5.js +1012 -961
- package/dist/bitwrench-lean.es5.min.js +18 -18
- package/dist/bitwrench-lean.esm.js +941 -775
- package/dist/bitwrench-lean.esm.min.js +20 -20
- package/dist/bitwrench-lean.umd.js +941 -775
- package/dist/bitwrench-lean.umd.min.js +20 -20
- package/dist/bitwrench-util-css.cjs.js +236 -0
- package/dist/bitwrench-util-css.cjs.min.js +22 -0
- package/dist/bitwrench-util-css.es5.js +414 -0
- package/dist/bitwrench-util-css.es5.min.js +21 -0
- package/dist/bitwrench-util-css.esm.js +230 -0
- package/dist/bitwrench-util-css.esm.min.js +21 -0
- package/dist/bitwrench-util-css.umd.js +242 -0
- package/dist/bitwrench-util-css.umd.min.js +21 -0
- package/dist/bitwrench.cjs.js +948 -782
- package/dist/bitwrench.cjs.min.js +21 -21
- package/dist/bitwrench.css +456 -132
- package/dist/bitwrench.es5.js +1024 -970
- package/dist/bitwrench.es5.min.js +19 -19
- package/dist/bitwrench.esm.js +949 -783
- package/dist/bitwrench.esm.min.js +21 -21
- package/dist/bitwrench.min.css +1 -1
- package/dist/bitwrench.umd.js +948 -782
- package/dist/bitwrench.umd.min.js +21 -21
- package/dist/builds.json +178 -90
- package/dist/bwserve.cjs.js +514 -68
- package/dist/bwserve.esm.js +513 -69
- package/dist/sri.json +44 -36
- package/package.json +3 -2
- package/readme.html +136 -49
- package/src/bitwrench-bccl.js +7 -7
- package/src/bitwrench-color-utils.js +31 -9
- package/src/bitwrench-esm-entry.js +11 -0
- package/src/bitwrench-styles.js +439 -232
- package/src/bitwrench-util-css.js +229 -0
- package/src/bitwrench.js +483 -485
- package/src/bwserve/attach.js +57 -0
- package/src/bwserve/bwclient.js +141 -0
- package/src/bwserve/bwshell.js +102 -0
- package/src/bwserve/client.js +151 -1
- package/src/bwserve/index.js +127 -28
- package/src/cli/attach.js +555 -0
- package/src/cli/convert.js +2 -5
- package/src/cli/index.js +7 -0
- package/src/cli/inject.js +1 -1
- package/src/cli/serve.js +6 -2
- package/src/generate-css.js +11 -4
- package/src/vendor/html2canvas.min.js +20 -0
- package/src/version.js +3 -3
- package/src/bwserve/shell.js +0 -106
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! bitwrench-lean v2.0.
|
|
1
|
+
/*! bitwrench-lean v2.0.18 | 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) :
|
|
@@ -190,14 +190,14 @@
|
|
|
190
190
|
*/
|
|
191
191
|
|
|
192
192
|
var VERSION_INFO = {
|
|
193
|
-
version: '2.0.
|
|
193
|
+
version: '2.0.18',
|
|
194
194
|
name: 'bitwrench',
|
|
195
195
|
description: 'A library for javascript UI functions.',
|
|
196
196
|
license: 'BSD-2-Clause',
|
|
197
197
|
homepage: 'https://deftio.github.com/bitwrench/pages',
|
|
198
198
|
repository: 'git+https://github.com/deftio/bitwrench.git',
|
|
199
199
|
author: 'manu a. chatterjee <deftio@deftio.com> (https://deftio.com/)',
|
|
200
|
-
buildDate: '2026-03-
|
|
200
|
+
buildDate: '2026-03-17T00:50:09.505Z'
|
|
201
201
|
};
|
|
202
202
|
|
|
203
203
|
/**
|
|
@@ -486,13 +486,16 @@
|
|
|
486
486
|
*/
|
|
487
487
|
function deriveShades(hex) {
|
|
488
488
|
var rgb = colorParse(hex);
|
|
489
|
+
// For light input colors (L > 75), mixing toward white produces invisible borders.
|
|
490
|
+
// Darken instead so borders remain visible against light backgrounds.
|
|
491
|
+
var borderColor = hexToHsl(hex)[2] > 75 ? adjustLightness(hex, -18) : mixColor(hex, '#ffffff', 0.60);
|
|
489
492
|
return {
|
|
490
493
|
base: hex,
|
|
491
494
|
hover: adjustLightness(hex, -10),
|
|
492
495
|
active: adjustLightness(hex, -15),
|
|
493
496
|
light: mixColor(hex, '#ffffff', 0.85),
|
|
494
497
|
darkText: adjustLightness(hex, -40),
|
|
495
|
-
border:
|
|
498
|
+
border: borderColor,
|
|
496
499
|
focus: 'rgba(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ',0.25)',
|
|
497
500
|
textOn: textOnColor(hex)
|
|
498
501
|
};
|
|
@@ -551,18 +554,26 @@
|
|
|
551
554
|
alt.secondary = deriveAlternateSeed(config.secondary);
|
|
552
555
|
alt.tertiary = config.tertiary ? deriveAlternateSeed(config.tertiary) : alt.primary;
|
|
553
556
|
|
|
554
|
-
// Derive alternate surface colors from primary hue
|
|
557
|
+
// Derive alternate surface colors from primary hue.
|
|
558
|
+
// Check actual page surface brightness (not seed color brightness) to decide
|
|
559
|
+
// whether alternate should be dark or light. The page surface is what the
|
|
560
|
+
// user sees; seeds can be dark while the page is still light (default L=96).
|
|
555
561
|
var priHsl = hexToHsl(config.primary);
|
|
556
562
|
var h = priHsl[0];
|
|
557
|
-
var
|
|
563
|
+
var primarySurface = config.surface || hslToHex([h, 8, 96]);
|
|
564
|
+
var isLight = relativeLuminance(primarySurface) > 0.179;
|
|
558
565
|
if (isLight) {
|
|
559
|
-
//
|
|
566
|
+
// Page surface is light → alternate needs dark surfaces
|
|
560
567
|
alt.light = hslToHex([h, Math.min(priHsl[1], 15), 15]);
|
|
561
568
|
alt.dark = hslToHex([h, 5, 88]);
|
|
569
|
+
alt.surface = hslToHex([h, 12, 18]);
|
|
570
|
+
alt.background = hslToHex([h, 10, 14]);
|
|
562
571
|
} else {
|
|
563
|
-
//
|
|
572
|
+
// Page surface is dark → alternate needs light surfaces
|
|
564
573
|
alt.light = hslToHex([h, Math.min(priHsl[1], 10), 96]);
|
|
565
574
|
alt.dark = hslToHex([h, 10, 18]);
|
|
575
|
+
alt.surface = hslToHex([h, 8, 96]);
|
|
576
|
+
alt.background = hslToHex([h, 6, 98]);
|
|
566
577
|
}
|
|
567
578
|
|
|
568
579
|
// Semantic colors: harmonize toward primary, then invert for alternate
|
|
@@ -611,10 +622,16 @@
|
|
|
611
622
|
var darkBase = config.dark || hslToHex([h, 10, 13]);
|
|
612
623
|
|
|
613
624
|
// Background & surface tokens — tinted with primary hue for theme personality.
|
|
614
|
-
//
|
|
625
|
+
// Saturation high enough that the hue is visible (each theme feels distinct)
|
|
626
|
+
// but low enough to stay neutral and readable.
|
|
615
627
|
// User can override with config.background / config.surface.
|
|
616
|
-
var bgBase = config.background || hslToHex([h,
|
|
617
|
-
var surfBase = config.surface || hslToHex([h,
|
|
628
|
+
var bgBase = config.background || hslToHex([h, 22, 96]);
|
|
629
|
+
var surfBase = config.surface || hslToHex([h, 25, 94]);
|
|
630
|
+
|
|
631
|
+
// surfaceAlt: subtle background variant for striped rows, hover states, headers.
|
|
632
|
+
// Slightly lighter than surface in dark mode, slightly darker in light mode.
|
|
633
|
+
var surfHsl = hexToHsl(surfBase);
|
|
634
|
+
var surfAlt = surfHsl[2] <= 50 ? hslToHex([surfHsl[0], surfHsl[1], Math.min(surfHsl[2] + 8, 100)]) : hslToHex([surfHsl[0], surfHsl[1], Math.max(surfHsl[2] - 3, 0)]);
|
|
618
635
|
var palette = {
|
|
619
636
|
primary: deriveShades(config.primary),
|
|
620
637
|
secondary: deriveShades(config.secondary),
|
|
@@ -626,7 +643,8 @@
|
|
|
626
643
|
light: deriveShades(lightBase),
|
|
627
644
|
dark: deriveShades(darkBase),
|
|
628
645
|
background: bgBase,
|
|
629
|
-
surface: surfBase
|
|
646
|
+
surface: surfBase,
|
|
647
|
+
surfaceAlt: surfAlt
|
|
630
648
|
};
|
|
631
649
|
return palette;
|
|
632
650
|
}
|
|
@@ -651,27 +669,28 @@
|
|
|
651
669
|
5: '1.5rem',
|
|
652
670
|
// 24px
|
|
653
671
|
6: '2rem'};
|
|
672
|
+
var _S = SPACING_SCALE;
|
|
654
673
|
var SPACING_PRESETS = {
|
|
655
674
|
compact: {
|
|
656
|
-
btn:
|
|
657
|
-
card:
|
|
658
|
-
alert:
|
|
659
|
-
cell:
|
|
660
|
-
input:
|
|
675
|
+
btn: _S[1] + ' ' + _S[3],
|
|
676
|
+
card: _S[3] + ' ' + _S[4],
|
|
677
|
+
alert: _S[2] + ' ' + _S[4],
|
|
678
|
+
cell: _S[2] + ' ' + _S[3],
|
|
679
|
+
input: _S[1] + ' ' + _S[3]
|
|
661
680
|
},
|
|
662
681
|
normal: {
|
|
663
|
-
btn:
|
|
664
|
-
card:
|
|
665
|
-
alert:
|
|
666
|
-
cell:
|
|
667
|
-
input:
|
|
682
|
+
btn: _S[2] + ' ' + _S[4],
|
|
683
|
+
card: _S[5] + ' ' + _S[5],
|
|
684
|
+
alert: _S[3] + ' ' + _S[5],
|
|
685
|
+
cell: _S[3] + ' ' + _S[4],
|
|
686
|
+
input: _S[2] + ' ' + _S[3]
|
|
668
687
|
},
|
|
669
688
|
spacious: {
|
|
670
|
-
btn:
|
|
671
|
-
card:
|
|
672
|
-
alert:
|
|
673
|
-
cell:
|
|
674
|
-
input:
|
|
689
|
+
btn: _S[3] + ' ' + _S[5],
|
|
690
|
+
card: _S[6] + ' ' + _S[6],
|
|
691
|
+
alert: _S[4] + ' ' + _S[5],
|
|
692
|
+
cell: _S[4] + ' ' + _S[5],
|
|
693
|
+
input: _S[3] + ' ' + _S[4]
|
|
675
694
|
}
|
|
676
695
|
};
|
|
677
696
|
var RADIUS_PRESETS = {
|
|
@@ -813,68 +832,13 @@
|
|
|
813
832
|
* Built-in theme presets — named color combinations
|
|
814
833
|
* Each preset provides primary, secondary, and tertiary seed colors.
|
|
815
834
|
*/
|
|
816
|
-
var THEME_PRESETS = {
|
|
817
|
-
|
|
818
|
-
primary:
|
|
819
|
-
secondary:
|
|
820
|
-
tertiary:
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
primary: '#0077b6',
|
|
824
|
-
secondary: '#90e0ef',
|
|
825
|
-
tertiary: '#00b4d8'
|
|
826
|
-
},
|
|
827
|
-
sunset: {
|
|
828
|
-
primary: '#e76f51',
|
|
829
|
-
secondary: '#264653',
|
|
830
|
-
tertiary: '#e9c46a'
|
|
831
|
-
},
|
|
832
|
-
forest: {
|
|
833
|
-
primary: '#2d6a4f',
|
|
834
|
-
secondary: '#95d5b2',
|
|
835
|
-
tertiary: '#52b788'
|
|
836
|
-
},
|
|
837
|
-
slate: {
|
|
838
|
-
primary: '#343a40',
|
|
839
|
-
secondary: '#adb5bd',
|
|
840
|
-
tertiary: '#6c757d'
|
|
841
|
-
},
|
|
842
|
-
rose: {
|
|
843
|
-
primary: '#e11d48',
|
|
844
|
-
secondary: '#fda4af',
|
|
845
|
-
tertiary: '#fb7185'
|
|
846
|
-
},
|
|
847
|
-
indigo: {
|
|
848
|
-
primary: '#4f46e5',
|
|
849
|
-
secondary: '#a5b4fc',
|
|
850
|
-
tertiary: '#818cf8'
|
|
851
|
-
},
|
|
852
|
-
amber: {
|
|
853
|
-
primary: '#d97706',
|
|
854
|
-
secondary: '#fbbf24',
|
|
855
|
-
tertiary: '#f59e0b'
|
|
856
|
-
},
|
|
857
|
-
emerald: {
|
|
858
|
-
primary: '#059669',
|
|
859
|
-
secondary: '#6ee7b7',
|
|
860
|
-
tertiary: '#34d399'
|
|
861
|
-
},
|
|
862
|
-
nord: {
|
|
863
|
-
primary: '#5e81ac',
|
|
864
|
-
secondary: '#88c0d0',
|
|
865
|
-
tertiary: '#81a1c1'
|
|
866
|
-
},
|
|
867
|
-
coral: {
|
|
868
|
-
primary: '#ef6461',
|
|
869
|
-
secondary: '#4a7c7e',
|
|
870
|
-
tertiary: '#e8a87c'
|
|
871
|
-
},
|
|
872
|
-
midnight: {
|
|
873
|
-
primary: '#1e3a5f',
|
|
874
|
-
secondary: '#7c8db5',
|
|
875
|
-
tertiary: '#3d5a80'
|
|
876
|
-
}
|
|
877
|
-
};
|
|
835
|
+
var THEME_PRESETS = Object.fromEntries([['teal', '#006666', '#6c757d', '#006666'], ['ocean', '#0077b6', '#90e0ef', '#00b4d8'], ['sunset', '#e76f51', '#264653', '#e9c46a'], ['forest', '#2d6a4f', '#95d5b2', '#52b788'], ['slate', '#343a40', '#adb5bd', '#6c757d'], ['rose', '#e11d48', '#fda4af', '#fb7185'], ['indigo', '#4f46e5', '#a5b4fc', '#818cf8'], ['amber', '#d97706', '#fbbf24', '#f59e0b'], ['emerald', '#059669', '#6ee7b7', '#34d399'], ['nord', '#5e81ac', '#88c0d0', '#81a1c1'], ['coral', '#ef6461', '#4a7c7e', '#e8a87c'], ['midnight', '#1e3a5f', '#7c8db5', '#3d5a80']].map(function (e) {
|
|
836
|
+
return [e[0], {
|
|
837
|
+
primary: e[1],
|
|
838
|
+
secondary: e[2],
|
|
839
|
+
tertiary: e[3]
|
|
840
|
+
}];
|
|
841
|
+
}));
|
|
878
842
|
|
|
879
843
|
/**
|
|
880
844
|
* Resolve layout config to spacing, radius, typeScale, elevation, and motion objects.
|
|
@@ -922,6 +886,7 @@
|
|
|
922
886
|
}).join(', ');
|
|
923
887
|
return '.' + name + ' ' + sel;
|
|
924
888
|
}
|
|
889
|
+
var _sx = scopeSelector;
|
|
925
890
|
|
|
926
891
|
// =========================================================================
|
|
927
892
|
// Themed CSS generators
|
|
@@ -930,12 +895,12 @@
|
|
|
930
895
|
function generateTypographyThemed(scope, palette, layout) {
|
|
931
896
|
var mot = layout.motion;
|
|
932
897
|
var rules = {};
|
|
933
|
-
rules[
|
|
898
|
+
rules[_sx(scope, 'a')] = {
|
|
934
899
|
'color': palette.primary.base,
|
|
935
900
|
'text-decoration': 'none',
|
|
936
901
|
'transition': 'color ' + mot.fast + ' ' + mot.easing
|
|
937
902
|
};
|
|
938
|
-
rules[
|
|
903
|
+
rules[_sx(scope, 'a:hover')] = {
|
|
939
904
|
'color': palette.primary.hover,
|
|
940
905
|
'text-decoration': 'underline'
|
|
941
906
|
};
|
|
@@ -947,11 +912,11 @@
|
|
|
947
912
|
var rd = layout.radius;
|
|
948
913
|
|
|
949
914
|
// Base button (only when scoped — unscoped uses defaultStyles)
|
|
950
|
-
rules[
|
|
915
|
+
rules[_sx(scope, '.bw_btn')] = {
|
|
951
916
|
'padding': sp.btn,
|
|
952
917
|
'border-radius': rd.btn
|
|
953
918
|
};
|
|
954
|
-
rules[
|
|
919
|
+
rules[_sx(scope, '.bw_btn:focus-visible')] = {
|
|
955
920
|
'outline': '2px solid currentColor',
|
|
956
921
|
'outline-offset': '2px',
|
|
957
922
|
'box-shadow': '0 0 0 3px ' + palette.primary.focus
|
|
@@ -960,12 +925,12 @@
|
|
|
960
925
|
// Variant colors handled by palette class on component root
|
|
961
926
|
|
|
962
927
|
// Size variants (structural, reuse layout radius)
|
|
963
|
-
rules[
|
|
928
|
+
rules[_sx(scope, '.bw_btn_lg')] = {
|
|
964
929
|
'padding': '0.625rem 1.5rem',
|
|
965
930
|
'font-size': '1rem',
|
|
966
931
|
'border-radius': rd.btn === '50rem' ? '50rem' : parseInt(rd.btn) + 2 + 'px'
|
|
967
932
|
};
|
|
968
|
-
rules[
|
|
933
|
+
rules[_sx(scope, '.bw_btn_sm')] = {
|
|
969
934
|
'padding': '0.25rem 0.75rem',
|
|
970
935
|
'font-size': '0.8125rem',
|
|
971
936
|
'border-radius': rd.btn === '50rem' ? '50rem' : Math.max(parseInt(rd.btn) - 1, 0) + 'px'
|
|
@@ -976,7 +941,7 @@
|
|
|
976
941
|
var rules = {};
|
|
977
942
|
var sp = layout.spacing;
|
|
978
943
|
var rd = layout.radius;
|
|
979
|
-
rules[
|
|
944
|
+
rules[_sx(scope, '.bw_alert')] = {
|
|
980
945
|
'padding': sp.alert,
|
|
981
946
|
'border-radius': rd.alert
|
|
982
947
|
};
|
|
@@ -994,38 +959,38 @@
|
|
|
994
959
|
var rd = layout.radius;
|
|
995
960
|
var elev = layout.elevation;
|
|
996
961
|
var motion = layout.motion;
|
|
997
|
-
rules[
|
|
962
|
+
rules[_sx(scope, '.bw_card')] = {
|
|
998
963
|
'background-color': palette.surface || '#fff',
|
|
999
964
|
'border': '1px solid ' + palette.light.border,
|
|
1000
965
|
'border-radius': rd.card,
|
|
1001
966
|
'box-shadow': elev.sm,
|
|
1002
967
|
'transition': 'box-shadow ' + motion.normal + ' ' + motion.easing + ', transform ' + motion.normal + ' ' + motion.easing
|
|
1003
968
|
};
|
|
1004
|
-
rules[
|
|
969
|
+
rules[_sx(scope, '.bw_card:hover')] = {
|
|
1005
970
|
'box-shadow': elev.md
|
|
1006
971
|
};
|
|
1007
|
-
rules[
|
|
972
|
+
rules[_sx(scope, '.bw_card_hoverable:hover')] = {
|
|
1008
973
|
'box-shadow': elev.lg
|
|
1009
974
|
};
|
|
1010
|
-
rules[
|
|
975
|
+
rules[_sx(scope, '.bw_card_body')] = {
|
|
1011
976
|
'padding': sp.card
|
|
1012
977
|
};
|
|
1013
|
-
rules[
|
|
978
|
+
rules[_sx(scope, '.bw_card_header')] = {
|
|
1014
979
|
'padding': sp.card.split(' ').map(function (v) {
|
|
1015
980
|
return (parseFloat(v) * 0.7).toFixed(3).replace(/\.?0+$/, '') + 'rem';
|
|
1016
981
|
}).join(' '),
|
|
1017
|
-
'background-color': palette.
|
|
982
|
+
'background-color': palette.surfaceAlt,
|
|
1018
983
|
'border-bottom': '1px solid ' + palette.light.border
|
|
1019
984
|
};
|
|
1020
|
-
rules[
|
|
1021
|
-
'background-color': palette.
|
|
985
|
+
rules[_sx(scope, '.bw_card_footer')] = {
|
|
986
|
+
'background-color': palette.surfaceAlt,
|
|
1022
987
|
'border-top': '1px solid ' + palette.light.border,
|
|
1023
988
|
'color': palette.secondary.base
|
|
1024
989
|
};
|
|
1025
|
-
rules[
|
|
990
|
+
rules[_sx(scope, '.bw_card_title')] = {
|
|
1026
991
|
'color': palette.dark.base
|
|
1027
992
|
};
|
|
1028
|
-
rules[
|
|
993
|
+
rules[_sx(scope, '.bw_card_subtitle')] = {
|
|
1029
994
|
'color': palette.secondary.base
|
|
1030
995
|
};
|
|
1031
996
|
|
|
@@ -1037,101 +1002,104 @@
|
|
|
1037
1002
|
var rules = {};
|
|
1038
1003
|
var sp = layout.spacing;
|
|
1039
1004
|
var rd = layout.radius;
|
|
1040
|
-
rules[
|
|
1005
|
+
rules[_sx(scope, '.bw_form_control')] = {
|
|
1041
1006
|
'padding': sp.input,
|
|
1042
1007
|
'border-radius': rd.input,
|
|
1043
1008
|
'color': palette.dark.base,
|
|
1044
1009
|
'background-color': palette.surface || '#fff',
|
|
1045
1010
|
'border-color': palette.light.border
|
|
1046
1011
|
};
|
|
1047
|
-
rules[
|
|
1012
|
+
rules[_sx(scope, '.bw_form_control:focus')] = {
|
|
1048
1013
|
'border-color': palette.primary.border,
|
|
1049
1014
|
'outline': '2px solid ' + palette.primary.base,
|
|
1050
1015
|
'outline-offset': '-1px',
|
|
1051
1016
|
'box-shadow': '0 0 0 0.25rem ' + palette.primary.focus
|
|
1052
1017
|
};
|
|
1053
|
-
rules[
|
|
1018
|
+
rules[_sx(scope, '.bw_form_control::placeholder')] = {
|
|
1054
1019
|
'color': palette.secondary.base
|
|
1055
1020
|
};
|
|
1056
|
-
rules[
|
|
1021
|
+
rules[_sx(scope, '.bw_form_label')] = {
|
|
1057
1022
|
'color': palette.dark.base
|
|
1058
1023
|
};
|
|
1059
|
-
rules[
|
|
1024
|
+
rules[_sx(scope, '.bw_form_text')] = {
|
|
1060
1025
|
'color': palette.secondary.base
|
|
1061
1026
|
};
|
|
1062
|
-
rules[
|
|
1027
|
+
rules[_sx(scope, '.bw_form_check_input:checked')] = {
|
|
1063
1028
|
'background-color': palette.primary.base,
|
|
1064
1029
|
'border-color': palette.primary.base
|
|
1065
1030
|
};
|
|
1066
|
-
rules[
|
|
1031
|
+
rules[_sx(scope, '.bw_form_check_input:focus')] = {
|
|
1067
1032
|
'box-shadow': '0 0 0 0.25rem ' + palette.primary.focus
|
|
1068
1033
|
};
|
|
1069
1034
|
// Validation states
|
|
1070
|
-
rules[
|
|
1035
|
+
rules[_sx(scope, '.bw_form_control.bw_is_valid')] = {
|
|
1071
1036
|
'border-color': palette.success.base
|
|
1072
1037
|
};
|
|
1073
|
-
rules[
|
|
1038
|
+
rules[_sx(scope, '.bw_form_control.bw_is_valid:focus')] = {
|
|
1074
1039
|
'border-color': palette.success.base,
|
|
1075
1040
|
'box-shadow': '0 0 0 0.2rem ' + palette.success.focus
|
|
1076
1041
|
};
|
|
1077
|
-
rules[
|
|
1042
|
+
rules[_sx(scope, '.bw_form_control.bw_is_invalid')] = {
|
|
1078
1043
|
'border-color': palette.danger.base
|
|
1079
1044
|
};
|
|
1080
|
-
rules[
|
|
1045
|
+
rules[_sx(scope, '.bw_form_control.bw_is_invalid:focus')] = {
|
|
1081
1046
|
'border-color': palette.danger.base,
|
|
1082
1047
|
'box-shadow': '0 0 0 0.2rem ' + palette.danger.focus
|
|
1083
1048
|
};
|
|
1084
1049
|
// Form select
|
|
1085
|
-
rules[
|
|
1050
|
+
rules[_sx(scope, '.bw_form_select')] = {
|
|
1086
1051
|
'padding': sp.input,
|
|
1087
1052
|
'border-radius': rd.input,
|
|
1088
1053
|
'color': palette.dark.base,
|
|
1089
1054
|
'background-color': palette.surface || '#fff',
|
|
1090
1055
|
'border-color': palette.light.border
|
|
1091
1056
|
};
|
|
1092
|
-
rules[
|
|
1057
|
+
rules[_sx(scope, '.bw_form_select:focus')] = {
|
|
1093
1058
|
'border-color': palette.primary.border,
|
|
1094
1059
|
'box-shadow': '0 0 0 0.25rem ' + palette.primary.focus
|
|
1095
1060
|
};
|
|
1096
1061
|
return rules;
|
|
1097
1062
|
}
|
|
1098
|
-
function generateNavigation(scope, palette) {
|
|
1063
|
+
function generateNavigation(scope, palette, layout) {
|
|
1099
1064
|
var rules = {};
|
|
1100
|
-
rules[
|
|
1101
|
-
'background-color': palette.
|
|
1065
|
+
rules[_sx(scope, '.bw_navbar')] = {
|
|
1066
|
+
'background-color': palette.surfaceAlt,
|
|
1102
1067
|
'border-bottom-color': palette.light.border
|
|
1103
1068
|
};
|
|
1104
|
-
rules[
|
|
1069
|
+
rules[_sx(scope, '.bw_navbar_brand')] = {
|
|
1105
1070
|
'color': palette.dark.base
|
|
1106
1071
|
};
|
|
1107
|
-
rules[
|
|
1108
|
-
'color': palette.secondary.base
|
|
1072
|
+
rules[_sx(scope, '.bw_navbar_nav .bw_nav_link')] = {
|
|
1073
|
+
'color': palette.secondary.base,
|
|
1074
|
+
'border-radius': layout.radius.btn
|
|
1109
1075
|
};
|
|
1110
|
-
rules[
|
|
1111
|
-
'color': palette.dark.base
|
|
1076
|
+
rules[_sx(scope, '.bw_navbar_nav .bw_nav_link:hover')] = {
|
|
1077
|
+
'color': palette.dark.base,
|
|
1078
|
+
'background-color': palette.surfaceAlt
|
|
1112
1079
|
};
|
|
1113
|
-
rules[
|
|
1080
|
+
rules[_sx(scope, '.bw_navbar_nav .bw_nav_link.active')] = {
|
|
1114
1081
|
'color': palette.primary.base,
|
|
1115
|
-
'background-color': palette.primary.focus
|
|
1082
|
+
'background-color': palette.primary.focus,
|
|
1083
|
+
'font-weight': '600'
|
|
1116
1084
|
};
|
|
1117
|
-
rules[
|
|
1085
|
+
rules[_sx(scope, '.bw_navbar_dark')] = {
|
|
1118
1086
|
'background-color': palette.dark.base,
|
|
1119
1087
|
'border-bottom-color': palette.dark.hover
|
|
1120
1088
|
};
|
|
1121
|
-
rules[
|
|
1089
|
+
rules[_sx(scope, '.bw_navbar_dark .bw_navbar_brand')] = {
|
|
1122
1090
|
'color': palette.light.base
|
|
1123
1091
|
};
|
|
1124
|
-
rules[
|
|
1125
|
-
'color':
|
|
1092
|
+
rules[_sx(scope, '.bw_navbar_dark .bw_nav_link')] = {
|
|
1093
|
+
'color': palette.light.border
|
|
1126
1094
|
};
|
|
1127
|
-
rules[
|
|
1128
|
-
'color':
|
|
1095
|
+
rules[_sx(scope, '.bw_navbar_dark .bw_nav_link:hover')] = {
|
|
1096
|
+
'color': palette.light.base
|
|
1129
1097
|
};
|
|
1130
|
-
rules[
|
|
1131
|
-
'color':
|
|
1098
|
+
rules[_sx(scope, '.bw_navbar_dark .bw_nav_link.active')] = {
|
|
1099
|
+
'color': palette.light.base,
|
|
1132
1100
|
'font-weight': '600'
|
|
1133
1101
|
};
|
|
1134
|
-
rules[
|
|
1102
|
+
rules[_sx(scope, '.bw_nav_pills .bw_nav_link.active')] = {
|
|
1135
1103
|
'color': palette.primary.textOn,
|
|
1136
1104
|
'background-color': palette.primary.base
|
|
1137
1105
|
};
|
|
@@ -1140,47 +1108,57 @@
|
|
|
1140
1108
|
function generateTables(scope, palette, layout) {
|
|
1141
1109
|
var rules = {};
|
|
1142
1110
|
var sp = layout.spacing;
|
|
1143
|
-
rules[
|
|
1111
|
+
rules[_sx(scope, '.bw_table')] = {
|
|
1144
1112
|
'color': palette.dark.base,
|
|
1145
1113
|
'border-color': palette.light.border
|
|
1146
1114
|
};
|
|
1147
|
-
rules[
|
|
1115
|
+
rules[_sx(scope, '.bw_table > :not(caption) > * > *')] = {
|
|
1148
1116
|
'padding': sp.cell,
|
|
1149
1117
|
'border-bottom-color': palette.light.border
|
|
1150
1118
|
};
|
|
1151
|
-
rules[
|
|
1119
|
+
rules[_sx(scope, '.bw_table > thead > tr > *')] = {
|
|
1152
1120
|
'color': palette.secondary.base,
|
|
1153
1121
|
'border-bottom-color': palette.light.border,
|
|
1154
|
-
'background-color': palette.
|
|
1122
|
+
'background-color': palette.surfaceAlt
|
|
1155
1123
|
};
|
|
1156
|
-
rules[
|
|
1157
|
-
'background-color':
|
|
1124
|
+
rules[_sx(scope, '.bw_table_striped > tbody > tr:nth-of-type(odd) > *')] = {
|
|
1125
|
+
'background-color': palette.surfaceAlt
|
|
1158
1126
|
};
|
|
1159
|
-
rules[
|
|
1127
|
+
rules[_sx(scope, '.bw_table_hover > tbody > tr:hover > *')] = {
|
|
1160
1128
|
'background-color': palette.primary.focus
|
|
1161
1129
|
};
|
|
1162
|
-
rules[
|
|
1130
|
+
rules[_sx(scope, '.bw_table_selectable > tbody > tr')] = {
|
|
1131
|
+
'cursor': 'pointer'
|
|
1132
|
+
};
|
|
1133
|
+
rules[_sx(scope, '.bw_table > tbody > tr.bw_table_row_selected > *')] = {
|
|
1134
|
+
'background-color': palette.primary.light
|
|
1135
|
+
};
|
|
1136
|
+
rules[_sx(scope, '.bw_table_bordered')] = {
|
|
1163
1137
|
'border-color': palette.light.border
|
|
1164
1138
|
};
|
|
1165
|
-
rules[
|
|
1139
|
+
rules[_sx(scope, '.bw_table caption')] = {
|
|
1166
1140
|
'color': palette.secondary.base
|
|
1167
1141
|
};
|
|
1168
1142
|
return rules;
|
|
1169
1143
|
}
|
|
1170
|
-
function generateTabs(scope, palette) {
|
|
1171
|
-
var rules = {}
|
|
1172
|
-
|
|
1144
|
+
function generateTabs(scope, palette, layout) {
|
|
1145
|
+
var rules = {},
|
|
1146
|
+
mo = layout.motion;
|
|
1147
|
+
rules[_sx(scope, '.bw_nav_tabs')] = {
|
|
1173
1148
|
'border-bottom-color': palette.light.border
|
|
1174
1149
|
};
|
|
1175
|
-
rules[
|
|
1176
|
-
'color': palette.secondary.base
|
|
1150
|
+
rules[_sx(scope, '.bw_nav_link')] = {
|
|
1151
|
+
'color': palette.secondary.base,
|
|
1152
|
+
'transition': 'color ' + mo.fast + ' ' + mo.easing + ', border-color ' + mo.fast + ' ' + mo.easing + ', background-color ' + mo.fast + ' ' + mo.easing
|
|
1177
1153
|
};
|
|
1178
|
-
rules[
|
|
1154
|
+
rules[_sx(scope, '.bw_nav_tabs .bw_nav_link:hover')] = {
|
|
1179
1155
|
'color': palette.dark.base,
|
|
1156
|
+
'background-color': palette.surfaceAlt,
|
|
1180
1157
|
'border-bottom-color': palette.light.border
|
|
1181
1158
|
};
|
|
1182
|
-
rules[
|
|
1159
|
+
rules[_sx(scope, '.bw_nav_tabs .bw_nav_link.active')] = {
|
|
1183
1160
|
'color': palette.primary.base,
|
|
1161
|
+
'background-color': palette.primary.focus,
|
|
1184
1162
|
'border-bottom': '2px solid ' + palette.primary.base
|
|
1185
1163
|
};
|
|
1186
1164
|
return rules;
|
|
@@ -1188,49 +1166,62 @@
|
|
|
1188
1166
|
function generateListGroups(scope, palette, layout) {
|
|
1189
1167
|
var rules = {};
|
|
1190
1168
|
var sp = layout.spacing;
|
|
1191
|
-
|
|
1169
|
+
var mo = layout.motion;
|
|
1170
|
+
rules[_sx(scope, '.bw_list_group_item')] = {
|
|
1192
1171
|
'padding': sp.cell,
|
|
1193
1172
|
'color': palette.dark.base,
|
|
1194
1173
|
'background-color': palette.surface || '#fff',
|
|
1195
|
-
'border-color': palette.light.border
|
|
1174
|
+
'border-color': palette.light.border,
|
|
1175
|
+
'transition': 'color ' + mo.fast + ' ' + mo.easing + ', background-color ' + mo.fast + ' ' + mo.easing
|
|
1196
1176
|
};
|
|
1197
|
-
rules[
|
|
1198
|
-
'background-color': palette.
|
|
1177
|
+
rules[_sx(scope, 'a.bw_list_group_item:hover')] = {
|
|
1178
|
+
'background-color': palette.surfaceAlt,
|
|
1199
1179
|
'color': palette.dark.hover
|
|
1200
1180
|
};
|
|
1201
|
-
rules[
|
|
1181
|
+
rules[_sx(scope, '.bw_list_group_item.active')] = {
|
|
1202
1182
|
'color': palette.primary.textOn,
|
|
1203
1183
|
'background-color': palette.primary.base,
|
|
1204
1184
|
'border-color': palette.primary.base
|
|
1205
1185
|
};
|
|
1206
|
-
rules[
|
|
1186
|
+
rules[_sx(scope, '.bw_list_group_item.disabled')] = {
|
|
1207
1187
|
'color': palette.secondary.base,
|
|
1208
1188
|
'background-color': palette.surface || '#fff'
|
|
1209
1189
|
};
|
|
1210
1190
|
return rules;
|
|
1211
1191
|
}
|
|
1212
|
-
function generatePagination(scope, palette) {
|
|
1213
|
-
var rules = {}
|
|
1214
|
-
|
|
1192
|
+
function generatePagination(scope, palette, layout) {
|
|
1193
|
+
var rules = {},
|
|
1194
|
+
mo = layout.motion,
|
|
1195
|
+
rd = layout.radius;
|
|
1196
|
+
rules[_sx(scope, '.bw_page_item:first-child .bw_page_link')] = {
|
|
1197
|
+
'border-top-left-radius': rd.btn,
|
|
1198
|
+
'border-bottom-left-radius': rd.btn
|
|
1199
|
+
};
|
|
1200
|
+
rules[_sx(scope, '.bw_page_item:last-child .bw_page_link')] = {
|
|
1201
|
+
'border-top-right-radius': rd.btn,
|
|
1202
|
+
'border-bottom-right-radius': rd.btn
|
|
1203
|
+
};
|
|
1204
|
+
rules[_sx(scope, '.bw_page_link')] = {
|
|
1215
1205
|
'color': palette.primary.base,
|
|
1216
1206
|
'background-color': palette.surface || '#fff',
|
|
1217
|
-
'border-color': palette.light.border
|
|
1207
|
+
'border-color': palette.light.border,
|
|
1208
|
+
'transition': 'color ' + mo.fast + ' ' + mo.easing + ', background-color ' + mo.fast + ' ' + mo.easing
|
|
1218
1209
|
};
|
|
1219
|
-
rules[
|
|
1210
|
+
rules[_sx(scope, '.bw_page_link:hover')] = {
|
|
1220
1211
|
'color': palette.primary.hover,
|
|
1221
|
-
'background-color': palette.
|
|
1212
|
+
'background-color': palette.surfaceAlt,
|
|
1222
1213
|
'border-color': palette.light.border
|
|
1223
1214
|
};
|
|
1224
|
-
rules[
|
|
1215
|
+
rules[_sx(scope, '.bw_page_link:focus')] = {
|
|
1225
1216
|
'outline': '2px solid ' + palette.primary.base,
|
|
1226
1217
|
'outline-offset': '-2px'
|
|
1227
1218
|
};
|
|
1228
|
-
rules[
|
|
1219
|
+
rules[_sx(scope, '.bw_page_item.bw_active .bw_page_link')] = {
|
|
1229
1220
|
'color': palette.primary.textOn,
|
|
1230
1221
|
'background-color': palette.primary.base,
|
|
1231
1222
|
'border-color': palette.primary.base
|
|
1232
1223
|
};
|
|
1233
|
-
rules[
|
|
1224
|
+
rules[_sx(scope, '.bw_page_item.bw_disabled .bw_page_link')] = {
|
|
1234
1225
|
'color': palette.secondary.base,
|
|
1235
1226
|
'background-color': palette.surface || '#fff',
|
|
1236
1227
|
'border-color': palette.light.border
|
|
@@ -1239,12 +1230,12 @@
|
|
|
1239
1230
|
}
|
|
1240
1231
|
function generateProgress(scope, palette) {
|
|
1241
1232
|
var rules = {};
|
|
1242
|
-
rules[
|
|
1243
|
-
'background-color': palette.
|
|
1233
|
+
rules[_sx(scope, '.bw_progress')] = {
|
|
1234
|
+
'background-color': palette.surfaceAlt,
|
|
1244
1235
|
'box-shadow': 'inset 0 1px 2px rgba(0,0,0,.1)'
|
|
1245
1236
|
};
|
|
1246
|
-
rules[
|
|
1247
|
-
'color':
|
|
1237
|
+
rules[_sx(scope, '.bw_progress_bar')] = {
|
|
1238
|
+
'color': palette.primary.textOn,
|
|
1248
1239
|
'background-color': palette.primary.base,
|
|
1249
1240
|
'box-shadow': 'inset 0 -1px 0 rgba(0,0,0,.15)'
|
|
1250
1241
|
};
|
|
@@ -1263,25 +1254,31 @@
|
|
|
1263
1254
|
'color': palette.dark.base,
|
|
1264
1255
|
'background-color': bg
|
|
1265
1256
|
};
|
|
1266
|
-
rules[
|
|
1267
|
-
// Also apply to the scope element itself so themes work on any container, not just body
|
|
1268
|
-
if (scope) {
|
|
1269
|
-
rules['.' + scope] = baseReset;
|
|
1270
|
-
}
|
|
1257
|
+
rules[_sx(scope, 'body')] = baseReset;
|
|
1271
1258
|
return rules;
|
|
1272
1259
|
}
|
|
1273
|
-
function generateBreadcrumbThemed(scope, palette) {
|
|
1274
|
-
var rules = {}
|
|
1275
|
-
|
|
1260
|
+
function generateBreadcrumbThemed(scope, palette, layout) {
|
|
1261
|
+
var rules = {},
|
|
1262
|
+
mo = layout.motion;
|
|
1263
|
+
rules[_sx(scope, '.bw_breadcrumb')] = {
|
|
1264
|
+
'background-color': palette.surfaceAlt,
|
|
1265
|
+
'padding': '0.625rem 1rem',
|
|
1266
|
+
'border-radius': layout.radius.btn
|
|
1267
|
+
};
|
|
1268
|
+
rules[_sx(scope, '.bw_breadcrumb_item + .bw_breadcrumb_item::before')] = {
|
|
1276
1269
|
'color': palette.secondary.base
|
|
1277
1270
|
};
|
|
1278
|
-
rules[
|
|
1279
|
-
'color': palette.
|
|
1271
|
+
rules[_sx(scope, '.bw_breadcrumb_item a')] = {
|
|
1272
|
+
'color': palette.primary.base,
|
|
1273
|
+
'transition': 'color ' + mo.fast + ' ' + mo.easing
|
|
1280
1274
|
};
|
|
1281
|
-
rules[
|
|
1275
|
+
rules[_sx(scope, '.bw_breadcrumb_item a:hover')] = {
|
|
1282
1276
|
'color': palette.primary.hover,
|
|
1283
1277
|
'text-decoration': 'underline'
|
|
1284
1278
|
};
|
|
1279
|
+
rules[_sx(scope, '.bw_breadcrumb_item.active')] = {
|
|
1280
|
+
'color': palette.dark.base
|
|
1281
|
+
};
|
|
1285
1282
|
return rules;
|
|
1286
1283
|
}
|
|
1287
1284
|
|
|
@@ -1289,240 +1286,273 @@
|
|
|
1289
1286
|
|
|
1290
1287
|
function generateCloseButtonThemed(scope, palette) {
|
|
1291
1288
|
var rules = {};
|
|
1292
|
-
rules[
|
|
1289
|
+
rules[_sx(scope, '.bw_close')] = {
|
|
1293
1290
|
'color': palette.dark.base,
|
|
1294
1291
|
'opacity': '0.5'
|
|
1295
1292
|
};
|
|
1296
|
-
rules[
|
|
1293
|
+
rules[_sx(scope, '.bw_close:focus')] = {
|
|
1297
1294
|
'box-shadow': '0 0 0 0.25rem ' + palette.primary.focus
|
|
1298
1295
|
};
|
|
1299
1296
|
return rules;
|
|
1300
1297
|
}
|
|
1301
1298
|
function generateSectionsThemed(scope, palette) {
|
|
1302
1299
|
var rules = {};
|
|
1303
|
-
rules[
|
|
1300
|
+
rules[_sx(scope, '.bw_section_subtitle')] = {
|
|
1304
1301
|
'color': palette.secondary.base
|
|
1305
1302
|
};
|
|
1306
|
-
rules[
|
|
1303
|
+
rules[_sx(scope, '.bw_feature_description')] = {
|
|
1307
1304
|
'color': palette.secondary.base
|
|
1308
1305
|
};
|
|
1309
|
-
rules[
|
|
1306
|
+
rules[_sx(scope, '.bw_cta_description')] = {
|
|
1310
1307
|
'color': palette.secondary.base
|
|
1311
1308
|
};
|
|
1312
1309
|
return rules;
|
|
1313
1310
|
}
|
|
1314
|
-
function generateAccordionThemed(scope, palette) {
|
|
1311
|
+
function generateAccordionThemed(scope, palette, layout) {
|
|
1315
1312
|
var rules = {};
|
|
1316
|
-
|
|
1313
|
+
var rd = layout ? layout.radius : {
|
|
1314
|
+
card: '8px'
|
|
1315
|
+
};
|
|
1316
|
+
rules[_sx(scope, '.bw_accordion_item')] = {
|
|
1317
1317
|
'background-color': palette.surface || '#fff',
|
|
1318
1318
|
'border-color': palette.light.border
|
|
1319
1319
|
};
|
|
1320
|
-
rules[
|
|
1320
|
+
rules[_sx(scope, '.bw_accordion_item:first-child')] = {
|
|
1321
|
+
'border-top-left-radius': rd.card,
|
|
1322
|
+
'border-top-right-radius': rd.card
|
|
1323
|
+
};
|
|
1324
|
+
rules[_sx(scope, '.bw_accordion_item:last-child')] = {
|
|
1325
|
+
'border-bottom-left-radius': rd.card,
|
|
1326
|
+
'border-bottom-right-radius': rd.card
|
|
1327
|
+
};
|
|
1328
|
+
rules[_sx(scope, '.bw_accordion_button')] = {
|
|
1321
1329
|
'color': palette.dark.base
|
|
1322
1330
|
};
|
|
1323
|
-
rules[
|
|
1331
|
+
rules[_sx(scope, '.bw_accordion_button:not(.bw_collapsed)')] = {
|
|
1324
1332
|
'color': palette.primary.darkText,
|
|
1325
|
-
'background-color': palette.primary.light
|
|
1333
|
+
'background-color': palette.primary.light,
|
|
1334
|
+
'border-left': '3px solid ' + palette.primary.base
|
|
1326
1335
|
};
|
|
1327
|
-
rules[
|
|
1328
|
-
'background-color': palette.
|
|
1336
|
+
rules[_sx(scope, '.bw_accordion_button:hover')] = {
|
|
1337
|
+
'background-color': palette.surfaceAlt
|
|
1329
1338
|
};
|
|
1330
|
-
rules[
|
|
1331
|
-
'background-color': palette.primary.
|
|
1339
|
+
rules[_sx(scope, '.bw_accordion_button:not(.bw_collapsed):hover')] = {
|
|
1340
|
+
'background-color': palette.primary.base,
|
|
1341
|
+
'color': palette.primary.textOn
|
|
1332
1342
|
};
|
|
1333
|
-
rules[
|
|
1343
|
+
rules[_sx(scope, '.bw_accordion_button:focus-visible')] = {
|
|
1334
1344
|
'box-shadow': '0 0 0 0.2rem ' + palette.primary.focus
|
|
1335
1345
|
};
|
|
1336
|
-
rules[
|
|
1337
|
-
'border-top': '1px solid ' + palette.light.border
|
|
1346
|
+
rules[_sx(scope, '.bw_accordion_body')] = {
|
|
1347
|
+
'border-top': '1px solid ' + palette.light.border,
|
|
1348
|
+
'background-color': palette.surfaceAlt
|
|
1338
1349
|
};
|
|
1339
1350
|
return rules;
|
|
1340
1351
|
}
|
|
1341
1352
|
function generateCarouselThemed(scope, palette) {
|
|
1342
1353
|
var rules = {};
|
|
1343
|
-
rules[
|
|
1344
|
-
'background-color': palette.
|
|
1354
|
+
rules[_sx(scope, '.bw_carousel')] = {
|
|
1355
|
+
'background-color': palette.surfaceAlt
|
|
1345
1356
|
};
|
|
1346
|
-
rules[
|
|
1357
|
+
rules[_sx(scope, '.bw_carousel_indicator.active')] = {
|
|
1347
1358
|
'background-color': palette.primary.base
|
|
1348
1359
|
};
|
|
1349
|
-
rules[
|
|
1350
|
-
'background-color':
|
|
1351
|
-
'color':
|
|
1360
|
+
rules[_sx(scope, '.bw_carousel_control')] = {
|
|
1361
|
+
'background-color': palette.dark.base,
|
|
1362
|
+
'color': palette.dark.textOn
|
|
1352
1363
|
};
|
|
1353
|
-
rules[
|
|
1354
|
-
'background-color':
|
|
1364
|
+
rules[_sx(scope, '.bw_carousel_control:hover')] = {
|
|
1365
|
+
'background-color': palette.dark.hover
|
|
1355
1366
|
};
|
|
1356
|
-
rules[
|
|
1357
|
-
'background': 'linear-gradient(transparent,
|
|
1358
|
-
'color':
|
|
1367
|
+
rules[_sx(scope, '.bw_carousel_caption')] = {
|
|
1368
|
+
'background': 'linear-gradient(transparent, ' + palette.dark.base + ')',
|
|
1369
|
+
'color': palette.dark.textOn
|
|
1359
1370
|
};
|
|
1360
1371
|
return rules;
|
|
1361
1372
|
}
|
|
1362
1373
|
function generateModalThemed(scope, palette, layout) {
|
|
1363
1374
|
var rules = {};
|
|
1364
|
-
rules[
|
|
1375
|
+
rules[_sx(scope, '.bw_modal_content')] = {
|
|
1365
1376
|
'background-color': palette.surface || '#fff',
|
|
1366
1377
|
'border-color': palette.light.border,
|
|
1367
1378
|
'box-shadow': layout.elevation.lg
|
|
1368
1379
|
};
|
|
1369
|
-
rules[
|
|
1380
|
+
rules[_sx(scope, '.bw_modal_header')] = {
|
|
1370
1381
|
'border-bottom-color': palette.light.border
|
|
1371
1382
|
};
|
|
1372
|
-
rules[
|
|
1383
|
+
rules[_sx(scope, '.bw_modal_footer')] = {
|
|
1373
1384
|
'border-top-color': palette.light.border
|
|
1374
1385
|
};
|
|
1375
|
-
rules[
|
|
1386
|
+
rules[_sx(scope, '.bw_modal_title')] = {
|
|
1376
1387
|
'color': palette.dark.base
|
|
1377
1388
|
};
|
|
1378
1389
|
return rules;
|
|
1379
1390
|
}
|
|
1380
1391
|
function generateToastThemed(scope, palette, layout) {
|
|
1381
1392
|
var rules = {};
|
|
1382
|
-
rules[
|
|
1393
|
+
rules[_sx(scope, '.bw_toast')] = {
|
|
1383
1394
|
'background-color': palette.surface || '#fff',
|
|
1384
|
-
'border-color':
|
|
1395
|
+
'border-color': palette.light.border,
|
|
1385
1396
|
'box-shadow': layout.elevation.lg
|
|
1386
1397
|
};
|
|
1387
|
-
rules[
|
|
1388
|
-
'border-bottom-color':
|
|
1398
|
+
rules[_sx(scope, '.bw_toast_header')] = {
|
|
1399
|
+
'border-bottom-color': palette.light.border
|
|
1389
1400
|
};
|
|
1390
1401
|
// Variant toast borders handled by palette class
|
|
1391
1402
|
return rules;
|
|
1392
1403
|
}
|
|
1393
1404
|
function generateDropdownThemed(scope, palette, layout) {
|
|
1394
1405
|
var rules = {};
|
|
1395
|
-
rules[
|
|
1406
|
+
rules[_sx(scope, '.bw_dropdown_menu')] = {
|
|
1396
1407
|
'background-color': palette.surface || '#fff',
|
|
1397
1408
|
'border-color': palette.light.border,
|
|
1398
1409
|
'box-shadow': layout.elevation.md
|
|
1399
1410
|
};
|
|
1400
|
-
rules[
|
|
1401
|
-
'color': palette.dark.base
|
|
1411
|
+
rules[_sx(scope, '.bw_dropdown_item')] = {
|
|
1412
|
+
'color': palette.dark.base,
|
|
1413
|
+
'transition': 'background-color ' + layout.motion.fast + ' ' + layout.motion.easing
|
|
1402
1414
|
};
|
|
1403
|
-
rules[
|
|
1415
|
+
rules[_sx(scope, '.bw_dropdown_item:hover')] = {
|
|
1404
1416
|
'color': palette.dark.hover,
|
|
1405
|
-
'background-color': palette.
|
|
1417
|
+
'background-color': palette.surfaceAlt
|
|
1406
1418
|
};
|
|
1407
|
-
rules[
|
|
1419
|
+
rules[_sx(scope, '.bw_dropdown_item.disabled')] = {
|
|
1408
1420
|
'color': palette.secondary.base
|
|
1409
1421
|
};
|
|
1410
|
-
rules[
|
|
1422
|
+
rules[_sx(scope, '.bw_dropdown_divider')] = {
|
|
1411
1423
|
'border-top-color': palette.light.border
|
|
1412
1424
|
};
|
|
1413
1425
|
return rules;
|
|
1414
1426
|
}
|
|
1415
1427
|
function generateSwitchThemed(scope, palette) {
|
|
1416
1428
|
var rules = {};
|
|
1417
|
-
rules[
|
|
1429
|
+
rules[_sx(scope, '.bw_form_switch .bw_switch_input')] = {
|
|
1418
1430
|
'background-color': palette.secondary.base,
|
|
1419
1431
|
'border-color': palette.secondary.base
|
|
1420
1432
|
};
|
|
1421
|
-
rules[
|
|
1433
|
+
rules[_sx(scope, '.bw_form_switch .bw_switch_input:checked')] = {
|
|
1422
1434
|
'background-color': palette.primary.base,
|
|
1423
1435
|
'border-color': palette.primary.base
|
|
1424
1436
|
};
|
|
1425
|
-
rules[
|
|
1437
|
+
rules[_sx(scope, '.bw_form_switch .bw_switch_input:focus')] = {
|
|
1426
1438
|
'box-shadow': '0 0 0 0.25rem ' + palette.primary.focus
|
|
1427
1439
|
};
|
|
1428
1440
|
return rules;
|
|
1429
1441
|
}
|
|
1430
1442
|
function generateSkeletonThemed(scope, palette) {
|
|
1431
1443
|
var rules = {};
|
|
1432
|
-
rules[
|
|
1433
|
-
'background': 'linear-gradient(90deg, ' + palette.light.border + ' 25%, ' + palette.
|
|
1444
|
+
rules[_sx(scope, '.bw_skeleton')] = {
|
|
1445
|
+
'background': 'linear-gradient(90deg, ' + palette.light.border + ' 25%, ' + palette.surfaceAlt + ' 37%, ' + palette.light.border + ' 63%)'
|
|
1434
1446
|
};
|
|
1435
1447
|
return rules;
|
|
1436
1448
|
}
|
|
1437
1449
|
|
|
1438
1450
|
// generateAvatarThemed: removed — palette class on root handles variants
|
|
1439
1451
|
|
|
1440
|
-
function generateStatCardThemed(scope, palette) {
|
|
1441
|
-
var rules = {}
|
|
1452
|
+
function generateStatCardThemed(scope, palette, layout) {
|
|
1453
|
+
var rules = {},
|
|
1454
|
+
mo = layout.motion,
|
|
1455
|
+
el = layout.elevation,
|
|
1456
|
+
rd = layout.radius;
|
|
1457
|
+
rules[_sx(scope, '.bw_stat_card')] = {
|
|
1458
|
+
'background-color': palette.surface || '#fff',
|
|
1459
|
+
'color': palette.dark.base,
|
|
1460
|
+
'border': '1px solid ' + palette.light.border,
|
|
1461
|
+
'border-radius': rd.card,
|
|
1462
|
+
'box-shadow': el.sm,
|
|
1463
|
+
'transition': 'box-shadow ' + mo.fast + ' ' + mo.easing + ', transform ' + mo.fast + ' ' + mo.easing
|
|
1464
|
+
};
|
|
1465
|
+
rules[_sx(scope, '.bw_stat_card:hover')] = {
|
|
1466
|
+
'box-shadow': el.md
|
|
1467
|
+
};
|
|
1442
1468
|
// Variant border colors handled by palette class
|
|
1443
|
-
rules[
|
|
1469
|
+
rules[_sx(scope, '.bw_stat_change_up')] = {
|
|
1444
1470
|
'color': palette.success.base
|
|
1445
1471
|
};
|
|
1446
|
-
rules[
|
|
1472
|
+
rules[_sx(scope, '.bw_stat_change_down')] = {
|
|
1447
1473
|
'color': palette.danger.base
|
|
1448
1474
|
};
|
|
1449
1475
|
return rules;
|
|
1450
1476
|
}
|
|
1451
1477
|
function generateTimelineThemed(scope, palette) {
|
|
1452
1478
|
var rules = {};
|
|
1453
|
-
rules[
|
|
1479
|
+
rules[_sx(scope, '.bw_timeline::before')] = {
|
|
1454
1480
|
'background-color': palette.light.border
|
|
1455
1481
|
};
|
|
1456
1482
|
// Variant marker colors handled by palette class
|
|
1457
|
-
rules[
|
|
1483
|
+
rules[_sx(scope, '.bw_timeline_date')] = {
|
|
1458
1484
|
'color': palette.secondary.base
|
|
1459
1485
|
};
|
|
1460
1486
|
return rules;
|
|
1461
1487
|
}
|
|
1462
1488
|
function generateStepperThemed(scope, palette) {
|
|
1463
1489
|
var rules = {};
|
|
1464
|
-
rules[
|
|
1465
|
-
'background-color': palette.
|
|
1490
|
+
rules[_sx(scope, '.bw_step_indicator')] = {
|
|
1491
|
+
'background-color': palette.surfaceAlt,
|
|
1466
1492
|
'border': '2px solid ' + palette.light.border,
|
|
1467
1493
|
'color': palette.secondary.base
|
|
1468
1494
|
};
|
|
1469
|
-
rules[
|
|
1495
|
+
rules[_sx(scope, '.bw_step + .bw_step::before')] = {
|
|
1470
1496
|
'background-color': palette.light.border
|
|
1471
1497
|
};
|
|
1472
|
-
rules[
|
|
1498
|
+
rules[_sx(scope, '.bw_step_active .bw_step_indicator')] = {
|
|
1473
1499
|
'background-color': palette.primary.base,
|
|
1474
1500
|
'color': palette.primary.textOn
|
|
1475
1501
|
};
|
|
1476
|
-
rules[
|
|
1502
|
+
rules[_sx(scope, '.bw_step_active .bw_step_label')] = {
|
|
1477
1503
|
'color': palette.dark.base,
|
|
1478
1504
|
'font-weight': '600'
|
|
1479
1505
|
};
|
|
1480
|
-
rules[
|
|
1506
|
+
rules[_sx(scope, '.bw_step_completed .bw_step_indicator')] = {
|
|
1481
1507
|
'background-color': palette.primary.base,
|
|
1482
1508
|
'color': palette.primary.textOn
|
|
1483
1509
|
};
|
|
1484
|
-
rules[
|
|
1510
|
+
rules[_sx(scope, '.bw_step_completed .bw_step_label')] = {
|
|
1485
1511
|
'color': palette.primary.base
|
|
1486
1512
|
};
|
|
1487
|
-
rules[
|
|
1513
|
+
rules[_sx(scope, '.bw_step_completed + .bw_step::before')] = {
|
|
1488
1514
|
'background-color': palette.primary.base
|
|
1489
1515
|
};
|
|
1490
1516
|
return rules;
|
|
1491
1517
|
}
|
|
1492
1518
|
function generateChipInputThemed(scope, palette) {
|
|
1493
1519
|
var rules = {};
|
|
1494
|
-
rules[
|
|
1495
|
-
'border-color': palette.light.border
|
|
1520
|
+
rules[_sx(scope, '.bw_chip_input')] = {
|
|
1521
|
+
'border-color': palette.light.border,
|
|
1522
|
+
'background-color': palette.surface || '#fff',
|
|
1523
|
+
'color': palette.dark.base
|
|
1496
1524
|
};
|
|
1497
|
-
rules[
|
|
1525
|
+
rules[_sx(scope, '.bw_chip_input:focus-within')] = {
|
|
1498
1526
|
'border-color': palette.primary.base,
|
|
1499
1527
|
'box-shadow': '0 0 0 0.2rem ' + palette.primary.focus
|
|
1500
1528
|
};
|
|
1501
|
-
rules[
|
|
1502
|
-
'background-color': palette.
|
|
1529
|
+
rules[_sx(scope, '.bw_chip')] = {
|
|
1530
|
+
'background-color': palette.surfaceAlt,
|
|
1503
1531
|
'color': palette.dark.base
|
|
1504
1532
|
};
|
|
1505
|
-
rules[
|
|
1533
|
+
rules[_sx(scope, '.bw_chip_remove:hover')] = {
|
|
1506
1534
|
'color': palette.danger.base,
|
|
1507
1535
|
'background-color': palette.danger.light
|
|
1508
1536
|
};
|
|
1509
1537
|
return rules;
|
|
1510
1538
|
}
|
|
1511
|
-
function generateFileUploadThemed(scope, palette) {
|
|
1512
|
-
var rules = {}
|
|
1513
|
-
|
|
1539
|
+
function generateFileUploadThemed(scope, palette, layout) {
|
|
1540
|
+
var rules = {},
|
|
1541
|
+
mo = layout.motion;
|
|
1542
|
+
rules[_sx(scope, '.bw_file_upload')] = {
|
|
1514
1543
|
'border-color': palette.light.border,
|
|
1515
|
-
'background-color': palette.
|
|
1544
|
+
'background-color': palette.surfaceAlt,
|
|
1545
|
+
'transition': 'border-color ' + mo.fast + ' ' + mo.easing + ', background-color ' + mo.fast + ' ' + mo.easing
|
|
1516
1546
|
};
|
|
1517
|
-
rules[
|
|
1547
|
+
rules[_sx(scope, '.bw_file_upload:hover')] = {
|
|
1518
1548
|
'border-color': palette.primary.base,
|
|
1519
1549
|
'background-color': palette.primary.light
|
|
1520
1550
|
};
|
|
1521
|
-
rules[
|
|
1551
|
+
rules[_sx(scope, '.bw_file_upload:focus')] = {
|
|
1522
1552
|
'outline': '2px solid ' + palette.primary.base,
|
|
1523
1553
|
'outline-offset': '2px'
|
|
1524
1554
|
};
|
|
1525
|
-
rules[
|
|
1555
|
+
rules[_sx(scope, '.bw_file_upload.bw_file_upload_active')] = {
|
|
1526
1556
|
'border-color': palette.primary.base,
|
|
1527
1557
|
'background-color': palette.primary.light,
|
|
1528
1558
|
'border-style': 'solid'
|
|
@@ -1531,37 +1561,93 @@
|
|
|
1531
1561
|
}
|
|
1532
1562
|
function generateRangeThemed(scope, palette) {
|
|
1533
1563
|
var rules = {};
|
|
1534
|
-
rules[
|
|
1564
|
+
rules[_sx(scope, '.bw_range')] = {
|
|
1535
1565
|
'background-color': palette.light.border
|
|
1536
1566
|
};
|
|
1537
|
-
rules[
|
|
1567
|
+
rules[_sx(scope, '.bw_range::-webkit-slider-thumb')] = {
|
|
1538
1568
|
'background-color': palette.primary.base,
|
|
1539
|
-
'border-color': '#fff',
|
|
1569
|
+
'border-color': palette.surface || '#fff',
|
|
1540
1570
|
'box-shadow': '0 1px 3px rgba(0,0,0,0.2)',
|
|
1541
1571
|
'transition': 'background-color 0.15s ease-out, transform 0.15s ease-out'
|
|
1542
1572
|
};
|
|
1543
|
-
rules[
|
|
1573
|
+
rules[_sx(scope, '.bw_range::-moz-range-thumb')] = {
|
|
1544
1574
|
'background-color': palette.primary.base,
|
|
1545
|
-
'border-color': '#fff',
|
|
1575
|
+
'border-color': palette.surface || '#fff',
|
|
1546
1576
|
'box-shadow': '0 1px 3px rgba(0,0,0,0.2)'
|
|
1547
1577
|
};
|
|
1548
1578
|
return rules;
|
|
1549
1579
|
}
|
|
1550
|
-
function
|
|
1551
|
-
var rules = {}
|
|
1552
|
-
|
|
1580
|
+
function generateTooltipThemed(scope, palette, layout) {
|
|
1581
|
+
var rules = {},
|
|
1582
|
+
sp = layout.spacing,
|
|
1583
|
+
rd = layout.radius,
|
|
1584
|
+
el = layout.elevation,
|
|
1585
|
+
mo = layout.motion;
|
|
1586
|
+
rules[_sx(scope, '.bw_tooltip')] = {
|
|
1587
|
+
'background-color': palette.dark.base,
|
|
1588
|
+
'color': palette.dark.textOn,
|
|
1589
|
+
'padding': sp.input,
|
|
1590
|
+
'border-radius': rd.badge,
|
|
1591
|
+
'box-shadow': el.md,
|
|
1592
|
+
'transition': 'opacity ' + mo.fast + ' ' + mo.easing + ', transform ' + mo.fast + ' ' + mo.easing
|
|
1593
|
+
};
|
|
1594
|
+
return rules;
|
|
1595
|
+
}
|
|
1596
|
+
function generatePopoverThemed(scope, palette, layout) {
|
|
1597
|
+
var rules = {},
|
|
1598
|
+
sp = layout.spacing,
|
|
1599
|
+
rd = layout.radius,
|
|
1600
|
+
el = layout.elevation,
|
|
1601
|
+
mo = layout.motion;
|
|
1602
|
+
rules[_sx(scope, '.bw_popover')] = {
|
|
1603
|
+
'background-color': palette.surface || '#fff',
|
|
1604
|
+
'color': palette.dark.base,
|
|
1605
|
+
'border': '1px solid ' + palette.light.border,
|
|
1606
|
+
'border-radius': rd.card,
|
|
1607
|
+
'box-shadow': el.lg,
|
|
1608
|
+
'transition': 'opacity ' + mo.fast + ' ' + mo.easing + ', transform ' + mo.fast + ' ' + mo.easing
|
|
1609
|
+
};
|
|
1610
|
+
rules[_sx(scope, '.bw_popover_header')] = {
|
|
1611
|
+
'background-color': palette.surfaceAlt,
|
|
1612
|
+
'border-bottom': '1px solid ' + palette.light.border,
|
|
1613
|
+
'padding': sp.input
|
|
1614
|
+
};
|
|
1615
|
+
rules[_sx(scope, '.bw_popover_body')] = {
|
|
1616
|
+
'padding': sp.card
|
|
1617
|
+
};
|
|
1618
|
+
return rules;
|
|
1619
|
+
}
|
|
1620
|
+
function generateSearchThemed(scope, palette, layout) {
|
|
1621
|
+
var rules = {},
|
|
1622
|
+
mo = layout.motion;
|
|
1623
|
+
rules[_sx(scope, '.bw_search_input')] = {
|
|
1624
|
+
'background-color': palette.surface || '#fff',
|
|
1625
|
+
'color': palette.dark.base
|
|
1626
|
+
};
|
|
1627
|
+
rules[_sx(scope, '.bw_search_clear')] = {
|
|
1628
|
+
'transition': 'color ' + mo.fast + ' ' + mo.easing + ', background-color ' + mo.fast + ' ' + mo.easing
|
|
1629
|
+
};
|
|
1630
|
+
rules[_sx(scope, '.bw_search_clear:hover')] = {
|
|
1553
1631
|
'color': palette.dark.base
|
|
1554
1632
|
};
|
|
1555
1633
|
return rules;
|
|
1556
1634
|
}
|
|
1557
|
-
function generateCodeDemoThemed(scope, palette) {
|
|
1635
|
+
function generateCodeDemoThemed(scope, palette, layout) {
|
|
1558
1636
|
var rules = {};
|
|
1559
|
-
|
|
1637
|
+
var rd = layout ? layout.radius : {
|
|
1638
|
+
card: '0.375rem'
|
|
1639
|
+
};
|
|
1640
|
+
rules[_sx(scope, '.bw_code_demo')] = {
|
|
1641
|
+
'background-color': palette.surface || '#fff',
|
|
1642
|
+
'color': palette.dark.base,
|
|
1643
|
+
'border-radius': rd.card
|
|
1644
|
+
};
|
|
1645
|
+
rules[_sx(scope, '.bw_code_copy_btn_copied')] = {
|
|
1560
1646
|
'background': palette.success.base,
|
|
1561
1647
|
'color': palette.success.textOn,
|
|
1562
1648
|
'border-color': palette.success.base
|
|
1563
1649
|
};
|
|
1564
|
-
rules[
|
|
1650
|
+
rules[_sx(scope, '.bw_copy_btn:hover')] = {
|
|
1565
1651
|
'background': 'rgba(255,255,255,0.2)',
|
|
1566
1652
|
'color': '#fff'
|
|
1567
1653
|
};
|
|
@@ -1570,7 +1656,7 @@
|
|
|
1570
1656
|
function generateNavPillsThemed(scope, palette, layout) {
|
|
1571
1657
|
var rules = {};
|
|
1572
1658
|
var rd = layout.radius;
|
|
1573
|
-
rules[
|
|
1659
|
+
rules[_sx(scope, '.bw_nav_pills .bw_nav_link')] = {
|
|
1574
1660
|
'border-radius': rd.btn
|
|
1575
1661
|
};
|
|
1576
1662
|
return rules;
|
|
@@ -1598,21 +1684,21 @@
|
|
|
1598
1684
|
var s = palette[k];
|
|
1599
1685
|
|
|
1600
1686
|
// --- Root palette class: sets default bg/color/border ---
|
|
1601
|
-
rules[
|
|
1687
|
+
rules[_sx(scope, '.bw_' + k)] = {
|
|
1602
1688
|
'background-color': s.base,
|
|
1603
1689
|
'color': s.textOn,
|
|
1604
1690
|
'border-color': s.base
|
|
1605
1691
|
};
|
|
1606
1692
|
|
|
1607
1693
|
// --- Pseudo-states (shared across all components) ---
|
|
1608
|
-
rules[
|
|
1694
|
+
rules[_sx(scope, '.bw_' + k + ':hover')] = {
|
|
1609
1695
|
'background-color': s.hover,
|
|
1610
1696
|
'border-color': s.active
|
|
1611
1697
|
};
|
|
1612
|
-
rules[
|
|
1698
|
+
rules[_sx(scope, '.bw_' + k + ':active')] = {
|
|
1613
1699
|
'background-color': s.active
|
|
1614
1700
|
};
|
|
1615
|
-
rules[
|
|
1701
|
+
rules[_sx(scope, '.bw_' + k + ':focus-visible')] = {
|
|
1616
1702
|
'box-shadow': '0 0 0 3px ' + s.focus,
|
|
1617
1703
|
'outline': 'none'
|
|
1618
1704
|
};
|
|
@@ -1620,71 +1706,110 @@
|
|
|
1620
1706
|
// --- Component-specific overrides ---
|
|
1621
1707
|
|
|
1622
1708
|
// Alerts: light bg, dark text, subtle border
|
|
1623
|
-
rules[
|
|
1709
|
+
rules[_sx(scope, '.bw_alert.bw_' + k)] = {
|
|
1624
1710
|
'background-color': s.light,
|
|
1625
1711
|
'color': s.darkText,
|
|
1626
1712
|
'border-color': s.border
|
|
1627
1713
|
};
|
|
1628
1714
|
|
|
1629
1715
|
// Toast: inherit bg, left border accent
|
|
1630
|
-
rules[
|
|
1716
|
+
rules[_sx(scope, '.bw_toast.bw_' + k)] = {
|
|
1631
1717
|
'background-color': 'inherit',
|
|
1632
1718
|
'color': 'inherit',
|
|
1633
1719
|
'border-left': '4px solid ' + s.base
|
|
1634
1720
|
};
|
|
1635
1721
|
|
|
1636
1722
|
// Stat card: inherit bg, left border accent
|
|
1637
|
-
rules[
|
|
1723
|
+
rules[_sx(scope, '.bw_stat_card.bw_' + k)] = {
|
|
1638
1724
|
'background-color': 'inherit',
|
|
1639
1725
|
'color': 'inherit',
|
|
1640
1726
|
'border-left-color': s.base
|
|
1641
1727
|
};
|
|
1642
1728
|
|
|
1643
1729
|
// Card accent: left border accent, inherit bg
|
|
1644
|
-
rules[
|
|
1730
|
+
rules[_sx(scope, '.bw_card.bw_' + k)] = {
|
|
1645
1731
|
'background-color': 'inherit',
|
|
1646
1732
|
'color': 'inherit',
|
|
1647
1733
|
'border-left': '4px solid ' + s.base
|
|
1648
1734
|
};
|
|
1649
1735
|
|
|
1650
1736
|
// Timeline marker: colored dot
|
|
1651
|
-
rules[
|
|
1737
|
+
rules[_sx(scope, '.bw_timeline_marker.bw_' + k)] = {
|
|
1652
1738
|
'box-shadow': '0 0 0 2px ' + s.base
|
|
1653
1739
|
};
|
|
1654
1740
|
|
|
1655
|
-
// Spinner:
|
|
1656
|
-
|
|
1741
|
+
// Spinner: set color, re-apply border pattern so the root palette class
|
|
1742
|
+
// border-color doesn't fill in the transparent gap that makes it spin.
|
|
1743
|
+
// Also neutralize hover/active which would override border-right-color.
|
|
1744
|
+
rules[_sx(scope, '.bw_spinner_border.bw_' + k)] = {
|
|
1657
1745
|
'background-color': 'transparent',
|
|
1658
1746
|
'color': s.base,
|
|
1659
|
-
'border-color':
|
|
1747
|
+
'border-color': s.base,
|
|
1748
|
+
'border-right-color': 'transparent'
|
|
1749
|
+
};
|
|
1750
|
+
rules[_sx(scope, '.bw_spinner_border.bw_' + k + ':hover')] = {
|
|
1751
|
+
'background-color': 'transparent',
|
|
1752
|
+
'border-color': s.base,
|
|
1753
|
+
'border-right-color': 'transparent'
|
|
1754
|
+
};
|
|
1755
|
+
rules[_sx(scope, '.bw_spinner_grow.bw_' + k)] = {
|
|
1756
|
+
'background-color': s.base,
|
|
1757
|
+
'color': s.base
|
|
1660
1758
|
};
|
|
1661
1759
|
|
|
1662
1760
|
// Outline button: transparent bg, colored border+text, solid on hover
|
|
1663
|
-
rules[
|
|
1761
|
+
rules[_sx(scope, '.bw_btn_outline.bw_' + k)] = {
|
|
1664
1762
|
'background-color': 'transparent',
|
|
1665
1763
|
'color': s.base,
|
|
1666
1764
|
'border-color': s.base
|
|
1667
1765
|
};
|
|
1668
|
-
rules[
|
|
1766
|
+
rules[_sx(scope, '.bw_btn_outline.bw_' + k + ':hover')] = {
|
|
1669
1767
|
'background-color': s.base,
|
|
1670
1768
|
'color': s.textOn
|
|
1671
1769
|
};
|
|
1672
1770
|
|
|
1673
1771
|
// Hero: gradient background
|
|
1674
|
-
rules[
|
|
1772
|
+
rules[_sx(scope, '.bw_hero.bw_' + k)] = {
|
|
1675
1773
|
'background': 'linear-gradient(135deg, ' + s.base + ' 0%, ' + s.hover + ' 100%)',
|
|
1676
1774
|
'color': s.textOn
|
|
1677
1775
|
};
|
|
1678
1776
|
|
|
1679
|
-
// Progress bar:
|
|
1680
|
-
rules[
|
|
1681
|
-
'color':
|
|
1777
|
+
// Progress bar: contrasting text on colored bg
|
|
1778
|
+
rules[_sx(scope, '.bw_progress_bar.bw_' + k)] = {
|
|
1779
|
+
'color': s.textOn
|
|
1780
|
+
};
|
|
1781
|
+
|
|
1782
|
+
// Background utility: .bw_bg_primary, .bw_bg_secondary, etc.
|
|
1783
|
+
rules[_sx(scope, '.bw_bg_' + k)] = {
|
|
1784
|
+
'background-color': s.base,
|
|
1785
|
+
'color': s.textOn
|
|
1786
|
+
};
|
|
1787
|
+
|
|
1788
|
+
// Text color utility: .bw_text_primary, .bw_text_secondary, etc.
|
|
1789
|
+
rules[_sx(scope, '.bw_text_' + k)] = {
|
|
1790
|
+
'color': s.base
|
|
1682
1791
|
};
|
|
1683
1792
|
});
|
|
1684
1793
|
|
|
1685
|
-
// Text muted
|
|
1686
|
-
rules[
|
|
1687
|
-
'color':
|
|
1794
|
+
// Text muted — always a neutral gray, never a brand color
|
|
1795
|
+
rules[_sx(scope, '.bw_text_muted')] = {
|
|
1796
|
+
'color': '#6c757d'
|
|
1797
|
+
};
|
|
1798
|
+
|
|
1799
|
+
// Common bg/text utilities that aren't per-variant
|
|
1800
|
+
rules[_sx(scope, '.bw_bg_dark')] = {
|
|
1801
|
+
'background-color': '#212529',
|
|
1802
|
+
'color': '#f8f9fa'
|
|
1803
|
+
};
|
|
1804
|
+
rules[_sx(scope, '.bw_bg_light')] = {
|
|
1805
|
+
'background-color': '#f8f9fa',
|
|
1806
|
+
'color': '#212529'
|
|
1807
|
+
};
|
|
1808
|
+
rules[_sx(scope, '.bw_text_light')] = {
|
|
1809
|
+
'color': '#f8f9fa'
|
|
1810
|
+
};
|
|
1811
|
+
rules[_sx(scope, '.bw_text_dark')] = {
|
|
1812
|
+
'color': '#212529'
|
|
1688
1813
|
};
|
|
1689
1814
|
return rules;
|
|
1690
1815
|
}
|
|
@@ -1699,7 +1824,7 @@
|
|
|
1699
1824
|
* @returns {Object} CSS rules object
|
|
1700
1825
|
*/
|
|
1701
1826
|
function generateThemedCSS(scopeName, palette, layout) {
|
|
1702
|
-
return Object.assign({}, generateResetThemed(scopeName, palette), generateTypographyThemed(scopeName, palette, layout), generateButtons(scopeName, palette, layout), generateAlerts(scopeName, palette, layout), generateCards(scopeName, palette, layout), generateForms(scopeName, palette, layout), generateNavigation(scopeName, palette), generateTables(scopeName, palette, layout), generateTabs(scopeName, palette), generateListGroups(scopeName, palette, layout), generatePagination(scopeName, palette), generateProgress(scopeName, palette), generateBreadcrumbThemed(scopeName, palette), generateCloseButtonThemed(scopeName, palette), generateSectionsThemed(scopeName, palette), generateAccordionThemed(scopeName, palette), generateCarouselThemed(scopeName, palette), generateModalThemed(scopeName, palette, layout), generateToastThemed(scopeName, palette, layout), generateDropdownThemed(scopeName, palette, layout), generateSwitchThemed(scopeName, palette), generateSkeletonThemed(scopeName, palette), generateStatCardThemed(scopeName, palette), generateTimelineThemed(scopeName, palette), generateStepperThemed(scopeName, palette), generateChipInputThemed(scopeName, palette), generateFileUploadThemed(scopeName, palette), generateRangeThemed(scopeName, palette), generateSearchThemed(scopeName, palette), generateCodeDemoThemed(scopeName, palette), generateNavPillsThemed(scopeName, palette, layout), generatePaletteClasses(scopeName, palette));
|
|
1827
|
+
return Object.assign({}, generateResetThemed(scopeName, palette), generateTypographyThemed(scopeName, palette, layout), generateButtons(scopeName, palette, layout), generateAlerts(scopeName, palette, layout), generateCards(scopeName, palette, layout), generateForms(scopeName, palette, layout), generateNavigation(scopeName, palette, layout), generateTables(scopeName, palette, layout), generateTabs(scopeName, palette, layout), generateListGroups(scopeName, palette, layout), generatePagination(scopeName, palette, layout), generateProgress(scopeName, palette), generateBreadcrumbThemed(scopeName, palette, layout), generateCloseButtonThemed(scopeName, palette), generateSectionsThemed(scopeName, palette), generateAccordionThemed(scopeName, palette, layout), generateCarouselThemed(scopeName, palette), generateModalThemed(scopeName, palette, layout), generateToastThemed(scopeName, palette, layout), generateDropdownThemed(scopeName, palette, layout), generateSwitchThemed(scopeName, palette), generateSkeletonThemed(scopeName, palette), generateStatCardThemed(scopeName, palette, layout), generateTimelineThemed(scopeName, palette), generateStepperThemed(scopeName, palette), generateChipInputThemed(scopeName, palette), generateFileUploadThemed(scopeName, palette, layout), generateRangeThemed(scopeName, palette), generateSearchThemed(scopeName, palette, layout), generateTooltipThemed(scopeName, palette, layout), generatePopoverThemed(scopeName, palette, layout), generateCodeDemoThemed(scopeName, palette, layout), generateNavPillsThemed(scopeName, palette, layout), generatePaletteClasses(scopeName, palette));
|
|
1703
1828
|
}
|
|
1704
1829
|
|
|
1705
1830
|
// =========================================================================
|
|
@@ -2194,6 +2319,12 @@
|
|
|
2194
2319
|
'border-width': '1px',
|
|
2195
2320
|
'border-style': 'solid'
|
|
2196
2321
|
},
|
|
2322
|
+
'.bw_table_selectable > tbody > tr': {
|
|
2323
|
+
'cursor': 'pointer'
|
|
2324
|
+
},
|
|
2325
|
+
'.bw_table > tbody > tr.bw_table_row_selected > *': {
|
|
2326
|
+
'background-color': 'rgba(0, 102, 102, 0.1)'
|
|
2327
|
+
},
|
|
2197
2328
|
'.bw_table_responsive': {
|
|
2198
2329
|
'overflow-x': 'auto',
|
|
2199
2330
|
'-webkit-overflow-scrolling': 'touch'
|
|
@@ -2307,6 +2438,7 @@
|
|
|
2307
2438
|
'display': 'block',
|
|
2308
2439
|
'font-size': '0.875rem',
|
|
2309
2440
|
'font-weight': '500',
|
|
2441
|
+
'padding': '0.625rem 1rem',
|
|
2310
2442
|
'text-decoration': 'none',
|
|
2311
2443
|
'cursor': 'pointer',
|
|
2312
2444
|
'border': 'none',
|
|
@@ -2409,16 +2541,15 @@
|
|
|
2409
2541
|
'padding': '0.375rem 0.75rem',
|
|
2410
2542
|
'margin-left': '-1px',
|
|
2411
2543
|
'line-height': '1.25',
|
|
2412
|
-
'text-decoration': 'none'
|
|
2544
|
+
'text-decoration': 'none',
|
|
2545
|
+
'border': '1px solid transparent',
|
|
2546
|
+
'cursor': 'pointer',
|
|
2547
|
+
'font-family': 'inherit',
|
|
2548
|
+
'font-size': 'inherit',
|
|
2549
|
+
'background': 'none'
|
|
2413
2550
|
},
|
|
2414
2551
|
'.bw_page_item:first-child .bw_page_link': {
|
|
2415
|
-
'margin-left': '0'
|
|
2416
|
-
'border-top-left-radius': '0.375rem',
|
|
2417
|
-
'border-bottom-left-radius': '0.375rem'
|
|
2418
|
-
},
|
|
2419
|
-
'.bw_page_item:last-child .bw_page_link': {
|
|
2420
|
-
'border-top-right-radius': '0.375rem',
|
|
2421
|
-
'border-bottom-right-radius': '0.375rem'
|
|
2552
|
+
'margin-left': '0'
|
|
2422
2553
|
},
|
|
2423
2554
|
'.bw_page_link:focus-visible': {
|
|
2424
2555
|
'z-index': '3',
|
|
@@ -2789,6 +2920,7 @@
|
|
|
2789
2920
|
'display': 'flex',
|
|
2790
2921
|
'align-items': 'center',
|
|
2791
2922
|
'width': '100%',
|
|
2923
|
+
'padding': '0.875rem 1.25rem',
|
|
2792
2924
|
'font-size': '1rem',
|
|
2793
2925
|
'font-weight': '500',
|
|
2794
2926
|
'text-align': 'left',
|
|
@@ -2811,20 +2943,16 @@
|
|
|
2811
2943
|
'.bw_accordion_button:not(.bw_collapsed)::after': {
|
|
2812
2944
|
'transform': 'rotate(-180deg)'
|
|
2813
2945
|
},
|
|
2946
|
+
'.bw_accordion_body': {
|
|
2947
|
+
'padding': '1rem 1.25rem'
|
|
2948
|
+
},
|
|
2814
2949
|
'.bw_accordion_collapse': {
|
|
2815
2950
|
'max-height': '0',
|
|
2816
|
-
'overflow': 'hidden'
|
|
2951
|
+
'overflow': 'hidden',
|
|
2952
|
+
'transition': 'max-height 0.3s ease'
|
|
2817
2953
|
},
|
|
2818
2954
|
'.bw_accordion_collapse.bw_collapse_show': {
|
|
2819
2955
|
'max-height': 'none'
|
|
2820
|
-
},
|
|
2821
|
-
'.bw_accordion_item:first-child': {
|
|
2822
|
-
'border-top-left-radius': '8px',
|
|
2823
|
-
'border-top-right-radius': '8px'
|
|
2824
|
-
},
|
|
2825
|
-
'.bw_accordion_item:last-child': {
|
|
2826
|
-
'border-bottom-left-radius': '8px',
|
|
2827
|
-
'border-bottom-right-radius': '8px'
|
|
2828
2956
|
}
|
|
2829
2957
|
},
|
|
2830
2958
|
// ---- Carousel ----
|
|
@@ -3192,7 +3320,11 @@
|
|
|
3192
3320
|
// ---- Stat card ----
|
|
3193
3321
|
statCard: {
|
|
3194
3322
|
'.bw_stat_card': {
|
|
3195
|
-
'
|
|
3323
|
+
'padding': '1.25rem',
|
|
3324
|
+
'border-left': '4px solid transparent',
|
|
3325
|
+
'border-radius': '0.375rem',
|
|
3326
|
+
'background-color': 'inherit',
|
|
3327
|
+
'transition': 'transform 0.15s ease'
|
|
3196
3328
|
},
|
|
3197
3329
|
'.bw_stat_card:hover': {
|
|
3198
3330
|
'transform': 'translateY(-1px)'
|
|
@@ -4210,6 +4342,52 @@
|
|
|
4210
4342
|
'margin-right': '.5rem'
|
|
4211
4343
|
};
|
|
4212
4344
|
|
|
4345
|
+
// Typography — bw_ prefixed utilities via loops
|
|
4346
|
+
var _imp = function _imp(p, v) {
|
|
4347
|
+
var o = {};
|
|
4348
|
+
o[p] = v + ' !important';
|
|
4349
|
+
return o;
|
|
4350
|
+
};
|
|
4351
|
+
[['fs', {
|
|
4352
|
+
'xs': '0.75rem',
|
|
4353
|
+
'sm': '0.875rem',
|
|
4354
|
+
'base': '1rem',
|
|
4355
|
+
'lg': '1.125rem',
|
|
4356
|
+
'xl': '1.25rem',
|
|
4357
|
+
'2xl': '1.5rem'
|
|
4358
|
+
}, 'font-size'], ['fw', {
|
|
4359
|
+
light: '300',
|
|
4360
|
+
normal: '400',
|
|
4361
|
+
medium: '500',
|
|
4362
|
+
semibold: '600',
|
|
4363
|
+
bold: '700'
|
|
4364
|
+
}, 'font-weight'], ['lh', {
|
|
4365
|
+
tight: '1.25',
|
|
4366
|
+
normal: '1.5',
|
|
4367
|
+
relaxed: '1.75'
|
|
4368
|
+
}, 'line-height']].forEach(function (d) {
|
|
4369
|
+
for (var dk in d[1]) rules['.bw_' + d[0] + '_' + dk] = _imp(d[2], d[1][dk]);
|
|
4370
|
+
});
|
|
4371
|
+
|
|
4372
|
+
// Flex utilities
|
|
4373
|
+
rules['.bw_flex'] = {
|
|
4374
|
+
'display': 'flex'
|
|
4375
|
+
};
|
|
4376
|
+
rules['.bw_flex_column'] = {
|
|
4377
|
+
'flex-direction': 'column'
|
|
4378
|
+
};
|
|
4379
|
+
rules['.bw_flex_wrap'] = {
|
|
4380
|
+
'flex-wrap': 'wrap'
|
|
4381
|
+
};
|
|
4382
|
+
rules['.bw_flex_center'] = {
|
|
4383
|
+
'display': 'flex',
|
|
4384
|
+
'align-items': 'center',
|
|
4385
|
+
'justify-content': 'center'
|
|
4386
|
+
};
|
|
4387
|
+
for (var gk in spacingValues) rules['.bw_gap_' + gk] = {
|
|
4388
|
+
'gap': spacingValues[gk] + ' !important'
|
|
4389
|
+
};
|
|
4390
|
+
|
|
4213
4391
|
// Visibility
|
|
4214
4392
|
rules['.bw_visible, .visible'] = {
|
|
4215
4393
|
'visibility': 'visible !important'
|
|
@@ -4288,6 +4466,26 @@
|
|
|
4288
4466
|
return getStructuralCSS();
|
|
4289
4467
|
}
|
|
4290
4468
|
|
|
4469
|
+
/**
|
|
4470
|
+
* Get CSS reset rules only (box-sizing, html/body font, reduced-motion).
|
|
4471
|
+
* Separate from themed/structural rules for independent injection.
|
|
4472
|
+
* @returns {Object} CSS rules object for the reset layer
|
|
4473
|
+
*/
|
|
4474
|
+
function getResetStyles() {
|
|
4475
|
+
var rules = {};
|
|
4476
|
+
Object.assign(rules, structuralRules.base);
|
|
4477
|
+
// Include reduced-motion preference
|
|
4478
|
+
rules['@media (prefers-reduced-motion: reduce)'] = {
|
|
4479
|
+
'*, *::before, *::after': {
|
|
4480
|
+
'animation-duration': '0.01ms !important',
|
|
4481
|
+
'animation-iteration-count': '1 !important',
|
|
4482
|
+
'transition-duration': '0.01ms !important',
|
|
4483
|
+
'scroll-behavior': 'auto !important'
|
|
4484
|
+
}
|
|
4485
|
+
};
|
|
4486
|
+
return rules;
|
|
4487
|
+
}
|
|
4488
|
+
|
|
4291
4489
|
// =========================================================================
|
|
4292
4490
|
// defaultStyles — backward-compatible categorized view
|
|
4293
4491
|
// =========================================================================
|
|
@@ -4322,57 +4520,40 @@
|
|
|
4322
4520
|
});
|
|
4323
4521
|
|
|
4324
4522
|
/**
|
|
4325
|
-
*
|
|
4326
|
-
*
|
|
4327
|
-
*
|
|
4328
|
-
*
|
|
4329
|
-
* @param {
|
|
4330
|
-
*
|
|
4331
|
-
* @
|
|
4332
|
-
* @returns {Object} CSS rules object scoped under .bw_theme_alt (+ optional .name)
|
|
4523
|
+
* Prefix every selector in a rules object with a scope selector.
|
|
4524
|
+
* Handles @media/@keyframes blocks and comma-separated selectors.
|
|
4525
|
+
* @param {Object} rules - CSS rules object
|
|
4526
|
+
* @param {string} prefix - Scope prefix (e.g. '#my-dashboard', '.bw_theme_alt')
|
|
4527
|
+
* @param {boolean} [compound=false] - If true, use compound selector (no space)
|
|
4528
|
+
* for the first segment: `#scope.bw_theme_alt .sel` vs `#scope .sel`
|
|
4529
|
+
* @returns {Object} New rules object with scoped selectors
|
|
4333
4530
|
*/
|
|
4334
|
-
function
|
|
4335
|
-
|
|
4336
|
-
var
|
|
4337
|
-
|
|
4338
|
-
// Re-scope every selector under .bw_theme_alt (+ optional theme name)
|
|
4339
|
-
var altPrefix = name ? '.' + name + '.bw_theme_alt' : '.bw_theme_alt';
|
|
4340
|
-
var altRules = {};
|
|
4341
|
-
for (var sel in rawRules) {
|
|
4342
|
-
if (!rawRules.hasOwnProperty(sel)) continue;
|
|
4531
|
+
function scopeRulesUnder(rules, prefix, compound) {
|
|
4532
|
+
var scoped = {};
|
|
4533
|
+
for (var sel in rules) {
|
|
4534
|
+
if (!rules.hasOwnProperty(sel)) continue;
|
|
4343
4535
|
if (sel.charAt(0) === '@') {
|
|
4344
4536
|
// @media / @keyframes — recurse into the block
|
|
4345
|
-
var innerBlock =
|
|
4346
|
-
var
|
|
4537
|
+
var innerBlock = rules[sel];
|
|
4538
|
+
var scopedInner = {};
|
|
4347
4539
|
for (var innerSel in innerBlock) {
|
|
4348
4540
|
if (!innerBlock.hasOwnProperty(innerSel)) continue;
|
|
4349
|
-
|
|
4541
|
+
scopedInner[_prefixSelector(innerSel, prefix)] = innerBlock[innerSel];
|
|
4350
4542
|
}
|
|
4351
|
-
|
|
4543
|
+
scoped[sel] = scopedInner;
|
|
4352
4544
|
} else {
|
|
4353
|
-
|
|
4354
|
-
// Handle comma-separated selectors
|
|
4355
|
-
var parts = sel.split(',');
|
|
4356
|
-
var scopedParts = [];
|
|
4357
|
-
for (var i = 0; i < parts.length; i++) {
|
|
4358
|
-
var s = parts[i].trim();
|
|
4359
|
-
// 'body' selector gets special treatment: .bw_theme_alt body
|
|
4360
|
-
if (s === 'body' || s.indexOf('body') === 0) {
|
|
4361
|
-
scopedParts.push(altPrefix + ' ' + s);
|
|
4362
|
-
} else {
|
|
4363
|
-
scopedParts.push(altPrefix + ' ' + s);
|
|
4364
|
-
}
|
|
4365
|
-
}
|
|
4366
|
-
altRules[scopedParts.join(', ')] = rawRules[sel];
|
|
4545
|
+
scoped[_prefixSelector(sel, prefix)] = rules[sel];
|
|
4367
4546
|
}
|
|
4368
4547
|
}
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4548
|
+
return scoped;
|
|
4549
|
+
}
|
|
4550
|
+
function _prefixSelector(sel, prefix) {
|
|
4551
|
+
var parts = sel.split(',');
|
|
4552
|
+
var result = [];
|
|
4553
|
+
for (var i = 0; i < parts.length; i++) {
|
|
4554
|
+
result.push(prefix + ' ' + parts[i].trim());
|
|
4555
|
+
}
|
|
4556
|
+
return result.join(', ');
|
|
4376
4557
|
}
|
|
4377
4558
|
|
|
4378
4559
|
/**
|
|
@@ -5421,7 +5602,12 @@
|
|
|
5421
5602
|
el = document.querySelector('[data-bw_id="' + id + '"]');
|
|
5422
5603
|
}
|
|
5423
5604
|
|
|
5424
|
-
// 5.
|
|
5605
|
+
// 5. Try class-based lookup for bw_uuid_* tokens (UUID addressing)
|
|
5606
|
+
if (!el && id.indexOf('bw_uuid_') === 0) {
|
|
5607
|
+
el = document.querySelector('.' + id);
|
|
5608
|
+
}
|
|
5609
|
+
|
|
5610
|
+
// 6. Cache the result for next time
|
|
5425
5611
|
if (el) {
|
|
5426
5612
|
bw._nodeMap[id] = el;
|
|
5427
5613
|
}
|
|
@@ -5473,6 +5659,79 @@
|
|
|
5473
5659
|
}
|
|
5474
5660
|
};
|
|
5475
5661
|
|
|
5662
|
+
// ===================================================================================
|
|
5663
|
+
// bw.assignUUID() / bw.getUUID() — Explicit UUID addressing for TACO objects
|
|
5664
|
+
// ===================================================================================
|
|
5665
|
+
|
|
5666
|
+
/**
|
|
5667
|
+
* Regex to match a bw_uuid_* token in a class string.
|
|
5668
|
+
* @private
|
|
5669
|
+
*/
|
|
5670
|
+
var _UUID_RE = /\bbw_uuid_[a-z0-9_]+\b/;
|
|
5671
|
+
|
|
5672
|
+
/**
|
|
5673
|
+
* Assign a UUID to a TACO object by appending a `bw_uuid_*` token to `taco.a.class`.
|
|
5674
|
+
*
|
|
5675
|
+
* Idempotent by default — calling twice returns the same UUID. Pass `forceNew=true`
|
|
5676
|
+
* to replace an existing UUID (useful in loops where each TACO needs a unique ID).
|
|
5677
|
+
*
|
|
5678
|
+
* @param {Object} taco - A TACO object `{t, a, c, o}`
|
|
5679
|
+
* @param {boolean} [forceNew=false] - If true, replaces any existing UUID with a new one
|
|
5680
|
+
* @returns {string} The UUID string (e.g. 'bw_uuid_a1b2c3d4e5')
|
|
5681
|
+
* @category Identifiers
|
|
5682
|
+
* @example
|
|
5683
|
+
* var card = bw.makeStatCard({ value: '0', label: 'Scans' });
|
|
5684
|
+
* var uuid = bw.assignUUID(card); // 'bw_uuid_a1b2c3d4e5'
|
|
5685
|
+
* var same = bw.assignUUID(card); // same UUID (idempotent)
|
|
5686
|
+
* var diff = bw.assignUUID(card, true); // new UUID (forced)
|
|
5687
|
+
*/
|
|
5688
|
+
bw.assignUUID = function (taco, forceNew) {
|
|
5689
|
+
if (!taco || !_is(taco, 'object')) return null;
|
|
5690
|
+
|
|
5691
|
+
// Ensure taco.a exists
|
|
5692
|
+
if (!taco.a) taco.a = {};
|
|
5693
|
+
if (!_is(taco.a["class"], 'string')) taco.a["class"] = taco.a["class"] ? String(taco.a["class"]) : '';
|
|
5694
|
+
var existing = taco.a["class"].match(_UUID_RE);
|
|
5695
|
+
if (existing && !forceNew) {
|
|
5696
|
+
return existing[0];
|
|
5697
|
+
}
|
|
5698
|
+
|
|
5699
|
+
// Remove old UUID if forceNew
|
|
5700
|
+
if (existing) {
|
|
5701
|
+
taco.a["class"] = taco.a["class"].replace(_UUID_RE, '').replace(/\s+/g, ' ').trim();
|
|
5702
|
+
}
|
|
5703
|
+
var uuid = bw.uuid('uuid');
|
|
5704
|
+
taco.a["class"] = (taco.a["class"] ? taco.a["class"] + ' ' : '') + uuid;
|
|
5705
|
+
return uuid;
|
|
5706
|
+
};
|
|
5707
|
+
|
|
5708
|
+
/**
|
|
5709
|
+
* Read the UUID from a TACO object or DOM element. Pure getter, no side effects.
|
|
5710
|
+
*
|
|
5711
|
+
* @param {Object|Element} tacoOrElement - A TACO object or DOM element
|
|
5712
|
+
* @returns {string|null} The UUID string, or null if none assigned
|
|
5713
|
+
* @category Identifiers
|
|
5714
|
+
* @example
|
|
5715
|
+
* bw.getUUID(card) // 'bw_uuid_a1b2c3d4e5' (from TACO)
|
|
5716
|
+
* bw.getUUID(domEl) // 'bw_uuid_a1b2c3d4e5' (from DOM element)
|
|
5717
|
+
* bw.getUUID({t:'div'}) // null (no UUID)
|
|
5718
|
+
*/
|
|
5719
|
+
bw.getUUID = function (tacoOrElement) {
|
|
5720
|
+
if (!tacoOrElement) return null;
|
|
5721
|
+
var classStr;
|
|
5722
|
+
// DOM element: check className
|
|
5723
|
+
if (tacoOrElement.className !== undefined && tacoOrElement.tagName) {
|
|
5724
|
+
classStr = tacoOrElement.className;
|
|
5725
|
+
}
|
|
5726
|
+
// TACO object: check a.class
|
|
5727
|
+
else if (tacoOrElement.a && _is(tacoOrElement.a["class"], 'string')) {
|
|
5728
|
+
classStr = tacoOrElement.a["class"];
|
|
5729
|
+
}
|
|
5730
|
+
if (!classStr) return null;
|
|
5731
|
+
var match = classStr.match(_UUID_RE);
|
|
5732
|
+
return match ? match[0] : null;
|
|
5733
|
+
};
|
|
5734
|
+
|
|
5476
5735
|
/**
|
|
5477
5736
|
* Escape HTML special characters to prevent XSS.
|
|
5478
5737
|
*
|
|
@@ -5525,6 +5784,45 @@
|
|
|
5525
5784
|
};
|
|
5526
5785
|
};
|
|
5527
5786
|
|
|
5787
|
+
/**
|
|
5788
|
+
* Hyperscript-style TACO constructor.
|
|
5789
|
+
*
|
|
5790
|
+
* A convenience helper that returns a canonical TACO object from positional
|
|
5791
|
+
* arguments. The return value is a plain object — serializable, works with
|
|
5792
|
+
* bwserve, and accepted everywhere TACO is accepted.
|
|
5793
|
+
*
|
|
5794
|
+
* @param {string} tag - HTML tag name (e.g. 'div', 'p', 'section')
|
|
5795
|
+
* @param {Object|null} [attrs] - HTML attributes object. Pass null or omit to skip.
|
|
5796
|
+
* @param {*} [content] - Content: string, number, TACO object, or array of children.
|
|
5797
|
+
* @param {Object} [options] - TACO options (state, lifecycle hooks, render fn).
|
|
5798
|
+
* @returns {Object} Plain TACO object {t, a?, c?, o?}
|
|
5799
|
+
* @category Utilities
|
|
5800
|
+
* @see bw.html
|
|
5801
|
+
* @see bw.createDOM
|
|
5802
|
+
* @see bw.DOM
|
|
5803
|
+
* @example
|
|
5804
|
+
* bw.h('div')
|
|
5805
|
+
* // => { t: 'div' }
|
|
5806
|
+
*
|
|
5807
|
+
* bw.h('p', { class: 'bw_text_muted' }, 'Hello')
|
|
5808
|
+
* // => { t: 'p', a: { class: 'bw_text_muted' }, c: 'Hello' }
|
|
5809
|
+
*
|
|
5810
|
+
* bw.h('ul', null, [
|
|
5811
|
+
* bw.h('li', null, 'one'),
|
|
5812
|
+
* bw.h('li', null, 'two')
|
|
5813
|
+
* ])
|
|
5814
|
+
* // => { t: 'ul', c: [{ t: 'li', c: 'one' }, { t: 'li', c: 'two' }] }
|
|
5815
|
+
*/
|
|
5816
|
+
bw.h = function (tag, attrs, content, options) {
|
|
5817
|
+
var taco = {
|
|
5818
|
+
t: String(tag)
|
|
5819
|
+
};
|
|
5820
|
+
if (attrs !== null && attrs !== undefined) taco.a = attrs;
|
|
5821
|
+
if (content !== undefined) taco.c = content;
|
|
5822
|
+
if (options !== undefined) taco.o = options;
|
|
5823
|
+
return taco;
|
|
5824
|
+
};
|
|
5825
|
+
|
|
5528
5826
|
/**
|
|
5529
5827
|
* Convert a TACO object (or array of TACOs) to an HTML string.
|
|
5530
5828
|
*
|
|
@@ -5799,9 +6097,7 @@
|
|
|
5799
6097
|
if (theme) {
|
|
5800
6098
|
var themeConfig = _is(theme, 'string') ? THEME_PRESETS[theme.toLowerCase()] || null : theme;
|
|
5801
6099
|
if (themeConfig) {
|
|
5802
|
-
var themeResult = bw.
|
|
5803
|
-
inject: false
|
|
5804
|
-
}));
|
|
6100
|
+
var themeResult = bw.makeStyles(themeConfig);
|
|
5805
6101
|
themeCSS = themeResult.css;
|
|
5806
6102
|
}
|
|
5807
6103
|
}
|
|
@@ -5835,14 +6131,14 @@
|
|
|
5835
6131
|
// Combine all CSS
|
|
5836
6132
|
var allCSS = (themeCSS ? themeCSS + '\n' : '') + css;
|
|
5837
6133
|
|
|
5838
|
-
// Body-end script: registry entries + optional
|
|
6134
|
+
// Body-end script: registry entries + optional loadStyles
|
|
5839
6135
|
var bodyEndScript = '';
|
|
5840
6136
|
var bodyEndParts = [];
|
|
5841
6137
|
if (registryEntries) {
|
|
5842
6138
|
bodyEndParts.push(registryEntries);
|
|
5843
6139
|
}
|
|
5844
6140
|
if (runtime === 'inline' || runtime === 'cdn') {
|
|
5845
|
-
bodyEndParts.push('if(typeof bw!=="undefined"){bw.
|
|
6141
|
+
bodyEndParts.push('if(typeof bw!=="undefined"){bw.loadStyles();}');
|
|
5846
6142
|
}
|
|
5847
6143
|
if (bodyEndParts.length > 0) {
|
|
5848
6144
|
bodyEndScript = '<script>\n' + bodyEndParts.join('\n') + '\n</script>';
|
|
@@ -6016,6 +6312,14 @@
|
|
|
6016
6312
|
bw._registerNode(el, null);
|
|
6017
6313
|
}
|
|
6018
6314
|
|
|
6315
|
+
// Register UUID class in node cache (bw_uuid_* tokens in class string)
|
|
6316
|
+
if (el.className) {
|
|
6317
|
+
var uuidMatch = el.className.match(_UUID_RE);
|
|
6318
|
+
if (uuidMatch) {
|
|
6319
|
+
bw._nodeMap[uuidMatch[0]] = el;
|
|
6320
|
+
}
|
|
6321
|
+
}
|
|
6322
|
+
|
|
6019
6323
|
// Handle lifecycle hooks and state
|
|
6020
6324
|
if (opts.mounted || opts.unmount || opts.render || opts.state) {
|
|
6021
6325
|
var id = attrs['data-bw_id'] || bw.uuid();
|
|
@@ -6375,6 +6679,16 @@
|
|
|
6375
6679
|
bw.cleanup = function (element) {
|
|
6376
6680
|
if (!bw._isBrowser || !element) return;
|
|
6377
6681
|
|
|
6682
|
+
// Deregister UUID classes from node cache (element + descendants)
|
|
6683
|
+
// Covers elements that have UUID but no data-bw_id
|
|
6684
|
+
var selfUuidMatch = element.className && element.className.match(_UUID_RE);
|
|
6685
|
+
if (selfUuidMatch) delete bw._nodeMap[selfUuidMatch[0]];
|
|
6686
|
+
var uuidEls = element.querySelectorAll('[class*="bw_uuid_"]');
|
|
6687
|
+
uuidEls.forEach(function (uel) {
|
|
6688
|
+
var m = uel.className && uel.className.match(_UUID_RE);
|
|
6689
|
+
if (m) delete bw._nodeMap[m[0]];
|
|
6690
|
+
});
|
|
6691
|
+
|
|
6378
6692
|
// Find all elements with data-bw_id
|
|
6379
6693
|
var elements = element.querySelectorAll('[data-bw_id]');
|
|
6380
6694
|
elements.forEach(function (el) {
|
|
@@ -6388,6 +6702,10 @@
|
|
|
6388
6702
|
// Deregister from node cache
|
|
6389
6703
|
bw._deregisterNode(el, id);
|
|
6390
6704
|
|
|
6705
|
+
// Deregister UUID class from node cache
|
|
6706
|
+
var uuidMatch = el.className && el.className.match(_UUID_RE);
|
|
6707
|
+
if (uuidMatch) delete bw._nodeMap[uuidMatch[0]];
|
|
6708
|
+
|
|
6391
6709
|
// Clean up pub/sub subscriptions tied to this element
|
|
6392
6710
|
if (el._bw_subs) {
|
|
6393
6711
|
el._bw_subs.forEach(function (unsub) {
|
|
@@ -6414,6 +6732,10 @@
|
|
|
6414
6732
|
// Deregister from node cache
|
|
6415
6733
|
bw._deregisterNode(element, id);
|
|
6416
6734
|
|
|
6735
|
+
// Deregister UUID class from node cache
|
|
6736
|
+
var elemUuidMatch = element.className && element.className.match(_UUID_RE);
|
|
6737
|
+
if (elemUuidMatch) delete bw._nodeMap[elemUuidMatch[0]];
|
|
6738
|
+
|
|
6417
6739
|
// Clean up pub/sub subscriptions tied to element itself
|
|
6418
6740
|
if (element._bw_subs) {
|
|
6419
6741
|
element._bw_subs.forEach(function (unsub) {
|
|
@@ -7030,7 +7352,7 @@
|
|
|
7030
7352
|
willMount: o.willMount || null,
|
|
7031
7353
|
mounted: o.mounted || null,
|
|
7032
7354
|
willUpdate: o.willUpdate || null,
|
|
7033
|
-
onUpdate: o.onUpdate || null,
|
|
7355
|
+
onUpdate: o.onUpdate || o.updated || null,
|
|
7034
7356
|
unmount: o.unmount || null,
|
|
7035
7357
|
willDestroy: o.willDestroy || null
|
|
7036
7358
|
};
|
|
@@ -8015,7 +8337,7 @@
|
|
|
8015
8337
|
* and calls the named method. This is the bitwrench equivalent of
|
|
8016
8338
|
* Win32 SendMessage(hwnd, msg, wParam, lParam).
|
|
8017
8339
|
*
|
|
8018
|
-
* @param {string} target - Component UUID (data-bw_comp_id) or user tag (CSS class)
|
|
8340
|
+
* @param {string} target - Component UUID (bw_uuid_*), comp ID (data-bw_comp_id), or user tag (CSS class)
|
|
8019
8341
|
* @param {string} action - Method name to call on the component
|
|
8020
8342
|
* @param {*} data - Data to pass to the method
|
|
8021
8343
|
* @returns {boolean} True if message was dispatched successfully
|
|
@@ -8032,9 +8354,14 @@
|
|
|
8032
8354
|
* };
|
|
8033
8355
|
*/
|
|
8034
8356
|
bw.message = function (target, action, data) {
|
|
8035
|
-
// Try
|
|
8036
|
-
var el = bw
|
|
8037
|
-
|
|
8357
|
+
// Try bw._el() first (handles UUID class, nodeMap cache, getElementById)
|
|
8358
|
+
var el = bw._el(target);
|
|
8359
|
+
// Then try data-bw_comp_id attribute
|
|
8360
|
+
if (!el || !el._bwComponentHandle) {
|
|
8361
|
+
el = bw.$('[data-bw_comp_id="' + target + '"]')[0];
|
|
8362
|
+
}
|
|
8363
|
+
// Then try CSS class (user tag)
|
|
8364
|
+
if (!el || !el._bwComponentHandle) {
|
|
8038
8365
|
el = bw.$('.' + target)[0];
|
|
8039
8366
|
}
|
|
8040
8367
|
if (!el || !el._bwComponentHandle) return false;
|
|
@@ -8048,61 +8375,24 @@
|
|
|
8048
8375
|
};
|
|
8049
8376
|
|
|
8050
8377
|
// ===================================================================================
|
|
8051
|
-
// bw.
|
|
8378
|
+
// bw.apply() / bw.parseJSONFlex() — Server-driven UI protocol
|
|
8052
8379
|
// ===================================================================================
|
|
8053
8380
|
|
|
8054
8381
|
/**
|
|
8055
8382
|
* Registry of named functions sent via register messages.
|
|
8056
|
-
* Populated by
|
|
8057
|
-
* Invoked by
|
|
8383
|
+
* Populated by bw.apply({ type: 'register', name, body }).
|
|
8384
|
+
* Invoked by bw.apply({ type: 'call', name, args }).
|
|
8058
8385
|
* @private
|
|
8059
8386
|
*/
|
|
8060
8387
|
bw._clientFunctions = {};
|
|
8061
8388
|
|
|
8062
8389
|
/**
|
|
8063
|
-
* Whether exec messages are allowed. Set by
|
|
8390
|
+
* Whether exec messages are allowed. Set by bwclient connect opts.allowExec.
|
|
8064
8391
|
* Default false — exec messages are rejected unless explicitly opted in.
|
|
8065
8392
|
* @private
|
|
8066
8393
|
*/
|
|
8067
8394
|
bw._allowExec = false;
|
|
8068
8395
|
|
|
8069
|
-
/**
|
|
8070
|
-
* Built-in client functions available via call() without registration.
|
|
8071
|
-
* @private
|
|
8072
|
-
*/
|
|
8073
|
-
bw._builtinClientFunctions = {
|
|
8074
|
-
scrollTo: function scrollTo(selector) {
|
|
8075
|
-
var el = bw._el(selector);
|
|
8076
|
-
if (el) el.scrollTop = el.scrollHeight;
|
|
8077
|
-
},
|
|
8078
|
-
focus: function focus(selector) {
|
|
8079
|
-
var el = bw._el(selector);
|
|
8080
|
-
if (el && _is(el.focus, 'function')) el.focus();
|
|
8081
|
-
},
|
|
8082
|
-
download: function download(filename, content, mimeType) {
|
|
8083
|
-
if (typeof document === 'undefined') return;
|
|
8084
|
-
var blob = new Blob([content], {
|
|
8085
|
-
type: mimeType || 'text/plain'
|
|
8086
|
-
});
|
|
8087
|
-
var a = document.createElement('a');
|
|
8088
|
-
a.href = URL.createObjectURL(blob);
|
|
8089
|
-
a.download = filename;
|
|
8090
|
-
a.click();
|
|
8091
|
-
URL.revokeObjectURL(a.href);
|
|
8092
|
-
},
|
|
8093
|
-
clipboard: function clipboard(text) {
|
|
8094
|
-
if (typeof navigator !== 'undefined' && navigator.clipboard) {
|
|
8095
|
-
navigator.clipboard.writeText(text);
|
|
8096
|
-
}
|
|
8097
|
-
},
|
|
8098
|
-
redirect: function redirect(url) {
|
|
8099
|
-
if (typeof window !== 'undefined') window.location.href = url;
|
|
8100
|
-
},
|
|
8101
|
-
log: function log() {
|
|
8102
|
-
console.log.apply(console, arguments);
|
|
8103
|
-
}
|
|
8104
|
-
};
|
|
8105
|
-
|
|
8106
8396
|
/**
|
|
8107
8397
|
* Parse a bwserve protocol message string, supporting both strict JSON
|
|
8108
8398
|
* and r-prefixed relaxed JSON (single-quoted strings, trailing commas).
|
|
@@ -8117,9 +8407,9 @@
|
|
|
8117
8407
|
* @param {string} str - JSON or r-prefixed relaxed JSON string
|
|
8118
8408
|
* @returns {Object} Parsed message object
|
|
8119
8409
|
* @throws {SyntaxError} If the string is not valid JSON or relaxed JSON
|
|
8120
|
-
* @category
|
|
8410
|
+
* @category Core
|
|
8121
8411
|
*/
|
|
8122
|
-
bw.
|
|
8412
|
+
bw.parseJSONFlex = function (str) {
|
|
8123
8413
|
str = (str || '').trim();
|
|
8124
8414
|
if (str.charAt(0) !== 'r') return JSON.parse(str);
|
|
8125
8415
|
str = str.slice(1);
|
|
@@ -8197,10 +8487,10 @@
|
|
|
8197
8487
|
* append — target.appendChild(bw.createDOM(node))
|
|
8198
8488
|
* remove — bw.cleanup(target); target.remove()
|
|
8199
8489
|
* patch — bw.patch(target, content, attr)
|
|
8200
|
-
* batch — iterate ops, call
|
|
8490
|
+
* batch — iterate ops, call bw.apply for each
|
|
8201
8491
|
* message — bw.message(target, action, data)
|
|
8202
8492
|
* register — store a named function for later call()
|
|
8203
|
-
* call — invoke a registered
|
|
8493
|
+
* call — invoke a registered function
|
|
8204
8494
|
* exec — execute arbitrary JS (requires allowExec)
|
|
8205
8495
|
*
|
|
8206
8496
|
* Target resolution:
|
|
@@ -8209,9 +8499,9 @@
|
|
|
8209
8499
|
*
|
|
8210
8500
|
* @param {Object} msg - Protocol message
|
|
8211
8501
|
* @returns {boolean} true if the message was applied successfully
|
|
8212
|
-
* @category
|
|
8502
|
+
* @category Core
|
|
8213
8503
|
*/
|
|
8214
|
-
bw.
|
|
8504
|
+
bw.apply = function (msg) {
|
|
8215
8505
|
if (!msg || !msg.type) return false;
|
|
8216
8506
|
var type = msg.type;
|
|
8217
8507
|
var target = msg.target;
|
|
@@ -8239,7 +8529,7 @@
|
|
|
8239
8529
|
if (!_isA(msg.ops)) return false;
|
|
8240
8530
|
var allOk = true;
|
|
8241
8531
|
msg.ops.forEach(function (op) {
|
|
8242
|
-
if (!bw.
|
|
8532
|
+
if (!bw.apply(op)) allOk = false;
|
|
8243
8533
|
});
|
|
8244
8534
|
return allOk;
|
|
8245
8535
|
} else if (type === 'message') {
|
|
@@ -8255,7 +8545,7 @@
|
|
|
8255
8545
|
}
|
|
8256
8546
|
} else if (type === 'call') {
|
|
8257
8547
|
if (!msg.name) return false;
|
|
8258
|
-
var fn = bw._clientFunctions[msg.name]
|
|
8548
|
+
var fn = bw._clientFunctions[msg.name];
|
|
8259
8549
|
if (!_is(fn, 'function')) return false;
|
|
8260
8550
|
try {
|
|
8261
8551
|
var args = _isA(msg.args) ? msg.args : [];
|
|
@@ -8282,141 +8572,6 @@
|
|
|
8282
8572
|
return false;
|
|
8283
8573
|
};
|
|
8284
8574
|
|
|
8285
|
-
/**
|
|
8286
|
-
* Connect to a bwserve SSE endpoint and apply protocol messages automatically.
|
|
8287
|
-
*
|
|
8288
|
-
* Returns a connection object with sendAction(), on(), and close() methods.
|
|
8289
|
-
*
|
|
8290
|
-
* @param {string} url - SSE endpoint URL (e.g., '/__bw/events/client-1')
|
|
8291
|
-
* @param {Object} [opts] - Connection options
|
|
8292
|
-
* @param {string} [opts.transport='sse'] - Transport type: 'sse' (default) or 'poll'
|
|
8293
|
-
* @param {number} [opts.interval=2000] - Poll interval in ms (only for 'poll' transport)
|
|
8294
|
-
* @param {string} [opts.actionUrl] - POST endpoint for actions (default: derived from url)
|
|
8295
|
-
* @param {boolean} [opts.reconnect=true] - Auto-reconnect on disconnect
|
|
8296
|
-
* @param {boolean} [opts.allowExec=false] - Enable exec message type (arbitrary JS execution)
|
|
8297
|
-
* @param {Function} [opts.onStatus] - Status callback: 'connecting'|'connected'|'disconnected'
|
|
8298
|
-
* @param {Function} [opts.onMessage] - Raw message callback (before clientApply)
|
|
8299
|
-
* @returns {Object} Connection object { sendAction, on, close, status }
|
|
8300
|
-
* @category Server
|
|
8301
|
-
*/
|
|
8302
|
-
bw.clientConnect = function (url, opts) {
|
|
8303
|
-
opts = opts || {};
|
|
8304
|
-
var transport = opts.transport || 'sse';
|
|
8305
|
-
var actionUrl = opts.actionUrl || url.replace(/\/events\//, '/action/');
|
|
8306
|
-
var reconnect = opts.reconnect !== false;
|
|
8307
|
-
var onStatus = opts.onStatus || function () {};
|
|
8308
|
-
var onMessage = opts.onMessage || null;
|
|
8309
|
-
var handlers = {};
|
|
8310
|
-
// Set the global allowExec flag from connection options
|
|
8311
|
-
bw._allowExec = !!opts.allowExec;
|
|
8312
|
-
var conn = {
|
|
8313
|
-
status: 'connecting',
|
|
8314
|
-
_es: null,
|
|
8315
|
-
_pollTimer: null
|
|
8316
|
-
};
|
|
8317
|
-
function setStatus(s) {
|
|
8318
|
-
conn.status = s;
|
|
8319
|
-
onStatus(s);
|
|
8320
|
-
}
|
|
8321
|
-
function handleMessage(data) {
|
|
8322
|
-
try {
|
|
8323
|
-
var msg = _is(data, 'string') ? bw.clientParse(data) : data;
|
|
8324
|
-
if (onMessage) onMessage(msg);
|
|
8325
|
-
if (handlers.message) handlers.message(msg);
|
|
8326
|
-
bw.clientApply(msg);
|
|
8327
|
-
} catch (e) {
|
|
8328
|
-
if (handlers.error) handlers.error(e);
|
|
8329
|
-
}
|
|
8330
|
-
}
|
|
8331
|
-
if (transport === 'sse' && typeof EventSource !== 'undefined') {
|
|
8332
|
-
setStatus('connecting');
|
|
8333
|
-
var es = new EventSource(url);
|
|
8334
|
-
conn._es = es;
|
|
8335
|
-
es.onopen = function () {
|
|
8336
|
-
setStatus('connected');
|
|
8337
|
-
if (handlers.open) handlers.open();
|
|
8338
|
-
};
|
|
8339
|
-
es.onmessage = function (e) {
|
|
8340
|
-
handleMessage(e.data);
|
|
8341
|
-
};
|
|
8342
|
-
es.onerror = function () {
|
|
8343
|
-
if (conn.status === 'connected') {
|
|
8344
|
-
setStatus('disconnected');
|
|
8345
|
-
}
|
|
8346
|
-
if (handlers.error) handlers.error(new Error('SSE connection error'));
|
|
8347
|
-
if (!reconnect) {
|
|
8348
|
-
es.close();
|
|
8349
|
-
}
|
|
8350
|
-
// EventSource auto-reconnects by default when reconnect=true
|
|
8351
|
-
};
|
|
8352
|
-
} else if (transport === 'poll') {
|
|
8353
|
-
var interval = opts.interval || 2000;
|
|
8354
|
-
setStatus('connected');
|
|
8355
|
-
conn._pollTimer = setInterval(function () {
|
|
8356
|
-
fetch(url).then(function (r) {
|
|
8357
|
-
return r.json();
|
|
8358
|
-
}).then(function (msgs) {
|
|
8359
|
-
if (_isA(msgs)) {
|
|
8360
|
-
msgs.forEach(handleMessage);
|
|
8361
|
-
} else if (msgs && msgs.type) {
|
|
8362
|
-
handleMessage(msgs);
|
|
8363
|
-
}
|
|
8364
|
-
})["catch"](function (e) {
|
|
8365
|
-
if (handlers.error) handlers.error(e);
|
|
8366
|
-
});
|
|
8367
|
-
}, interval);
|
|
8368
|
-
}
|
|
8369
|
-
|
|
8370
|
-
/**
|
|
8371
|
-
* Send an action to the server via POST.
|
|
8372
|
-
* @param {string} action - Action name
|
|
8373
|
-
* @param {Object} [data] - Action payload
|
|
8374
|
-
*/
|
|
8375
|
-
conn.sendAction = function (action, data) {
|
|
8376
|
-
var body = JSON.stringify({
|
|
8377
|
-
type: 'action',
|
|
8378
|
-
action: action,
|
|
8379
|
-
data: data || {}
|
|
8380
|
-
});
|
|
8381
|
-
fetch(actionUrl, {
|
|
8382
|
-
method: 'POST',
|
|
8383
|
-
headers: {
|
|
8384
|
-
'Content-Type': 'application/json'
|
|
8385
|
-
},
|
|
8386
|
-
body: body
|
|
8387
|
-
})["catch"](function (e) {
|
|
8388
|
-
if (handlers.error) handlers.error(e);
|
|
8389
|
-
});
|
|
8390
|
-
};
|
|
8391
|
-
|
|
8392
|
-
/**
|
|
8393
|
-
* Register an event handler.
|
|
8394
|
-
* @param {string} event - 'open'|'message'|'error'|'close'
|
|
8395
|
-
* @param {Function} handler
|
|
8396
|
-
*/
|
|
8397
|
-
conn.on = function (event, handler) {
|
|
8398
|
-
handlers[event] = handler;
|
|
8399
|
-
return conn;
|
|
8400
|
-
};
|
|
8401
|
-
|
|
8402
|
-
/**
|
|
8403
|
-
* Close the connection.
|
|
8404
|
-
*/
|
|
8405
|
-
conn.close = function () {
|
|
8406
|
-
if (conn._es) {
|
|
8407
|
-
conn._es.close();
|
|
8408
|
-
conn._es = null;
|
|
8409
|
-
}
|
|
8410
|
-
if (conn._pollTimer) {
|
|
8411
|
-
clearInterval(conn._pollTimer);
|
|
8412
|
-
conn._pollTimer = null;
|
|
8413
|
-
}
|
|
8414
|
-
setStatus('disconnected');
|
|
8415
|
-
if (handlers.close) handlers.close();
|
|
8416
|
-
};
|
|
8417
|
-
return conn;
|
|
8418
|
-
};
|
|
8419
|
-
|
|
8420
8575
|
// ===================================================================================
|
|
8421
8576
|
// bw.inspect() — Debug utility
|
|
8422
8577
|
// ===================================================================================
|
|
@@ -8645,7 +8800,7 @@
|
|
|
8645
8800
|
* @returns {Element} The style element
|
|
8646
8801
|
* @category CSS & Styling
|
|
8647
8802
|
* @see bw.css
|
|
8648
|
-
* @see bw.
|
|
8803
|
+
* @see bw.loadStyles
|
|
8649
8804
|
* @example
|
|
8650
8805
|
* bw.injectCSS('.my-class { color: red; }');
|
|
8651
8806
|
* bw.injectCSS({ '.card': { padding: '1rem' } }, { id: 'card-styles' });
|
|
@@ -8691,9 +8846,8 @@
|
|
|
8691
8846
|
* @param {...Object} styles - Style objects to merge (left-to-right)
|
|
8692
8847
|
* @returns {Object} Merged style object
|
|
8693
8848
|
* @category CSS & Styling
|
|
8694
|
-
* @see bw.u
|
|
8695
8849
|
* @example
|
|
8696
|
-
* var style = bw.s(
|
|
8850
|
+
* var style = bw.s({ display: 'flex' }, { gap: '1rem' }, { color: 'red' });
|
|
8697
8851
|
* // => { display: 'flex', gap: '1rem', color: 'red' }
|
|
8698
8852
|
*/
|
|
8699
8853
|
bw.s = function () {
|
|
@@ -8705,216 +8859,6 @@
|
|
|
8705
8859
|
return result;
|
|
8706
8860
|
};
|
|
8707
8861
|
|
|
8708
|
-
/**
|
|
8709
|
-
* Pre-built CSS utility objects (like Tailwind utilities, but in JS).
|
|
8710
|
-
*
|
|
8711
|
-
* Compose with `bw.s()` to build inline styles without writing raw CSS strings.
|
|
8712
|
-
* Includes flex, padding, margin, typography, color, border, and transition utilities.
|
|
8713
|
-
*
|
|
8714
|
-
* @category CSS & Styling
|
|
8715
|
-
* @see bw.s
|
|
8716
|
-
* @example
|
|
8717
|
-
* { t: 'div', a: { style: bw.s(bw.u.flex, bw.u.gap4, bw.u.p4) },
|
|
8718
|
-
* c: 'Flexbox with 1rem gap and padding' }
|
|
8719
|
-
*/
|
|
8720
|
-
bw.u = {
|
|
8721
|
-
// Display
|
|
8722
|
-
flex: {
|
|
8723
|
-
display: 'flex'
|
|
8724
|
-
},
|
|
8725
|
-
flexCol: {
|
|
8726
|
-
display: 'flex',
|
|
8727
|
-
flexDirection: 'column'
|
|
8728
|
-
},
|
|
8729
|
-
flexRow: {
|
|
8730
|
-
display: 'flex',
|
|
8731
|
-
flexDirection: 'row'
|
|
8732
|
-
},
|
|
8733
|
-
flexWrap: {
|
|
8734
|
-
display: 'flex',
|
|
8735
|
-
flexWrap: 'wrap'
|
|
8736
|
-
},
|
|
8737
|
-
block: {
|
|
8738
|
-
display: 'block'
|
|
8739
|
-
},
|
|
8740
|
-
inline: {
|
|
8741
|
-
display: 'inline'
|
|
8742
|
-
},
|
|
8743
|
-
hidden: {
|
|
8744
|
-
display: 'none'
|
|
8745
|
-
},
|
|
8746
|
-
// Flex alignment
|
|
8747
|
-
justifyCenter: {
|
|
8748
|
-
justifyContent: 'center'
|
|
8749
|
-
},
|
|
8750
|
-
justifyBetween: {
|
|
8751
|
-
justifyContent: 'space-between'
|
|
8752
|
-
},
|
|
8753
|
-
justifyEnd: {
|
|
8754
|
-
justifyContent: 'flex-end'
|
|
8755
|
-
},
|
|
8756
|
-
alignCenter: {
|
|
8757
|
-
alignItems: 'center'
|
|
8758
|
-
},
|
|
8759
|
-
alignStart: {
|
|
8760
|
-
alignItems: 'flex-start'
|
|
8761
|
-
},
|
|
8762
|
-
alignEnd: {
|
|
8763
|
-
alignItems: 'flex-end'
|
|
8764
|
-
},
|
|
8765
|
-
// Gap (0.25rem increments)
|
|
8766
|
-
gap1: {
|
|
8767
|
-
gap: '0.25rem'
|
|
8768
|
-
},
|
|
8769
|
-
gap2: {
|
|
8770
|
-
gap: '0.5rem'
|
|
8771
|
-
},
|
|
8772
|
-
gap3: {
|
|
8773
|
-
gap: '0.75rem'
|
|
8774
|
-
},
|
|
8775
|
-
gap4: {
|
|
8776
|
-
gap: '1rem'
|
|
8777
|
-
},
|
|
8778
|
-
gap6: {
|
|
8779
|
-
gap: '1.5rem'
|
|
8780
|
-
},
|
|
8781
|
-
gap8: {
|
|
8782
|
-
gap: '2rem'
|
|
8783
|
-
},
|
|
8784
|
-
// Padding
|
|
8785
|
-
p0: {
|
|
8786
|
-
padding: '0'
|
|
8787
|
-
},
|
|
8788
|
-
p1: {
|
|
8789
|
-
padding: '0.25rem'
|
|
8790
|
-
},
|
|
8791
|
-
p2: {
|
|
8792
|
-
padding: '0.5rem'
|
|
8793
|
-
},
|
|
8794
|
-
p3: {
|
|
8795
|
-
padding: '0.75rem'
|
|
8796
|
-
},
|
|
8797
|
-
p4: {
|
|
8798
|
-
padding: '1rem'
|
|
8799
|
-
},
|
|
8800
|
-
p6: {
|
|
8801
|
-
padding: '1.5rem'
|
|
8802
|
-
},
|
|
8803
|
-
p8: {
|
|
8804
|
-
padding: '2rem'
|
|
8805
|
-
},
|
|
8806
|
-
px4: {
|
|
8807
|
-
paddingLeft: '1rem',
|
|
8808
|
-
paddingRight: '1rem'
|
|
8809
|
-
},
|
|
8810
|
-
py2: {
|
|
8811
|
-
paddingTop: '0.5rem',
|
|
8812
|
-
paddingBottom: '0.5rem'
|
|
8813
|
-
},
|
|
8814
|
-
py4: {
|
|
8815
|
-
paddingTop: '1rem',
|
|
8816
|
-
paddingBottom: '1rem'
|
|
8817
|
-
},
|
|
8818
|
-
// Margin (same scale)
|
|
8819
|
-
m0: {
|
|
8820
|
-
margin: '0'
|
|
8821
|
-
},
|
|
8822
|
-
m4: {
|
|
8823
|
-
margin: '1rem'
|
|
8824
|
-
},
|
|
8825
|
-
mt2: {
|
|
8826
|
-
marginTop: '0.5rem'
|
|
8827
|
-
},
|
|
8828
|
-
mt4: {
|
|
8829
|
-
marginTop: '1rem'
|
|
8830
|
-
},
|
|
8831
|
-
mb2: {
|
|
8832
|
-
marginBottom: '0.5rem'
|
|
8833
|
-
},
|
|
8834
|
-
mb4: {
|
|
8835
|
-
marginBottom: '1rem'
|
|
8836
|
-
},
|
|
8837
|
-
mx_auto: {
|
|
8838
|
-
marginLeft: 'auto',
|
|
8839
|
-
marginRight: 'auto'
|
|
8840
|
-
},
|
|
8841
|
-
// Typography
|
|
8842
|
-
textSm: {
|
|
8843
|
-
fontSize: '0.875rem'
|
|
8844
|
-
},
|
|
8845
|
-
textBase: {
|
|
8846
|
-
fontSize: '1rem'
|
|
8847
|
-
},
|
|
8848
|
-
textLg: {
|
|
8849
|
-
fontSize: '1.125rem'
|
|
8850
|
-
},
|
|
8851
|
-
textXl: {
|
|
8852
|
-
fontSize: '1.25rem'
|
|
8853
|
-
},
|
|
8854
|
-
text2xl: {
|
|
8855
|
-
fontSize: '1.5rem'
|
|
8856
|
-
},
|
|
8857
|
-
text3xl: {
|
|
8858
|
-
fontSize: '1.875rem'
|
|
8859
|
-
},
|
|
8860
|
-
bold: {
|
|
8861
|
-
fontWeight: '700'
|
|
8862
|
-
},
|
|
8863
|
-
semibold: {
|
|
8864
|
-
fontWeight: '600'
|
|
8865
|
-
},
|
|
8866
|
-
italic: {
|
|
8867
|
-
fontStyle: 'italic'
|
|
8868
|
-
},
|
|
8869
|
-
textCenter: {
|
|
8870
|
-
textAlign: 'center'
|
|
8871
|
-
},
|
|
8872
|
-
textRight: {
|
|
8873
|
-
textAlign: 'right'
|
|
8874
|
-
},
|
|
8875
|
-
// Colors (from design tokens)
|
|
8876
|
-
bgWhite: {
|
|
8877
|
-
background: '#ffffff'
|
|
8878
|
-
},
|
|
8879
|
-
bgTeal: {
|
|
8880
|
-
background: '#006666',
|
|
8881
|
-
color: '#ffffff'
|
|
8882
|
-
},
|
|
8883
|
-
textWhite: {
|
|
8884
|
-
color: '#ffffff'
|
|
8885
|
-
},
|
|
8886
|
-
textTeal: {
|
|
8887
|
-
color: '#006666'
|
|
8888
|
-
},
|
|
8889
|
-
textMuted: {
|
|
8890
|
-
color: '#888'
|
|
8891
|
-
},
|
|
8892
|
-
// Borders
|
|
8893
|
-
rounded: {
|
|
8894
|
-
borderRadius: '0.375rem'
|
|
8895
|
-
},
|
|
8896
|
-
roundedLg: {
|
|
8897
|
-
borderRadius: '0.5rem'
|
|
8898
|
-
},
|
|
8899
|
-
roundedFull: {
|
|
8900
|
-
borderRadius: '9999px'
|
|
8901
|
-
},
|
|
8902
|
-
border: {
|
|
8903
|
-
border: '1px solid #d8d8d8'
|
|
8904
|
-
},
|
|
8905
|
-
// Sizing
|
|
8906
|
-
wFull: {
|
|
8907
|
-
width: '100%'
|
|
8908
|
-
},
|
|
8909
|
-
hFull: {
|
|
8910
|
-
height: '100%'
|
|
8911
|
-
},
|
|
8912
|
-
// Transitions
|
|
8913
|
-
transition: {
|
|
8914
|
-
transition: 'all 0.2s ease'
|
|
8915
|
-
}
|
|
8916
|
-
};
|
|
8917
|
-
|
|
8918
8862
|
/**
|
|
8919
8863
|
* Generate responsive CSS with media query breakpoints.
|
|
8920
8864
|
*
|
|
@@ -9040,111 +8984,48 @@
|
|
|
9040
8984
|
};
|
|
9041
8985
|
}
|
|
9042
8986
|
|
|
9043
|
-
|
|
9044
|
-
|
|
9045
|
-
|
|
9046
|
-
* Injects bitwrench's batteries-included CSS (buttons, cards, grids, forms,
|
|
9047
|
-
* alerts, badges, nav, tabs, etc.) into the document head. Call once at app startup.
|
|
9048
|
-
* Returns null in Node.js (no DOM).
|
|
9049
|
-
*
|
|
9050
|
-
* @param {Object} [options] - Style loading options
|
|
9051
|
-
* @param {boolean} [options.minify=true] - Minify the CSS output
|
|
9052
|
-
* @returns {Element|null} Style element if in browser, null in Node.js
|
|
9053
|
-
* @category CSS & Styling
|
|
9054
|
-
* @see bw.setTheme
|
|
9055
|
-
* @see bw.applyTheme
|
|
9056
|
-
* @see bw.toggleTheme
|
|
9057
|
-
* @example
|
|
9058
|
-
* bw.loadDefaultStyles(); // inject all default CSS
|
|
9059
|
-
*/
|
|
9060
|
-
bw.loadDefaultStyles = function () {
|
|
9061
|
-
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
9062
|
-
var _options$minify2 = options.minify,
|
|
9063
|
-
minify = _options$minify2 === void 0 ? true : _options$minify2,
|
|
9064
|
-
palette = options.palette;
|
|
9065
|
-
|
|
9066
|
-
// 1. Inject structural CSS (layout, sizing — never changes with theme)
|
|
9067
|
-
if (bw._isBrowser) {
|
|
9068
|
-
var structuralCSS = bw.css(getStructuralStyles());
|
|
9069
|
-
bw.injectCSS(structuralCSS, {
|
|
9070
|
-
id: 'bw_structural',
|
|
9071
|
-
append: false,
|
|
9072
|
-
minify: minify
|
|
9073
|
-
});
|
|
9074
|
-
}
|
|
8987
|
+
// =========================================================================
|
|
8988
|
+
// v2.0.18 Clean Styles API — makeStyles / applyStyles / loadStyles / etc.
|
|
8989
|
+
// =========================================================================
|
|
9075
8990
|
|
|
9076
|
-
|
|
9077
|
-
|
|
9078
|
-
|
|
9079
|
-
|
|
9080
|
-
|
|
9081
|
-
|
|
9082
|
-
|
|
8991
|
+
/**
|
|
8992
|
+
* Convert a scope selector to a <style> element id.
|
|
8993
|
+
* @private
|
|
8994
|
+
* @param {string} [scope] - Scope selector (e.g. '#my-dashboard', '.preview')
|
|
8995
|
+
* @returns {string} Style element id (e.g. 'bw_style_my_dashboard')
|
|
8996
|
+
*/
|
|
8997
|
+
function _scopeToStyleId(scope) {
|
|
8998
|
+
if (!scope || scope === '' || scope === 'global') return 'bw_style_global';
|
|
8999
|
+
if (scope === 'reset') return 'bw_style_reset';
|
|
9000
|
+
// Strip leading # or . and convert - to _
|
|
9001
|
+
var clean = scope.replace(/^[#.]/, '').replace(/-/g, '_');
|
|
9002
|
+
return 'bw_style_' + clean;
|
|
9003
|
+
}
|
|
9083
9004
|
|
|
9084
9005
|
/**
|
|
9085
|
-
* Generate a complete
|
|
9086
|
-
*
|
|
9087
|
-
*
|
|
9088
|
-
*
|
|
9089
|
-
*
|
|
9090
|
-
*
|
|
9091
|
-
*
|
|
9092
|
-
* @param {string}
|
|
9093
|
-
* @param {
|
|
9094
|
-
* @param {string} config.primary - Primary brand color hex
|
|
9095
|
-
* @param {string} config.secondary - Secondary color hex
|
|
9096
|
-
* @param {string} [config.tertiary] - Tertiary/accent color hex (defaults to primary)
|
|
9097
|
-
* @param {string} [config.success='#198754'] - Success color hex
|
|
9098
|
-
* @param {string} [config.danger='#dc3545'] - Danger color hex
|
|
9099
|
-
* @param {string} [config.warning='#ffc107'] - Warning color hex
|
|
9100
|
-
* @param {string} [config.info='#0dcaf0'] - Info color hex
|
|
9101
|
-
* @param {string} [config.light='#f8f9fa'] - Light color hex
|
|
9102
|
-
* @param {string} [config.dark='#212529'] - Dark color hex
|
|
9103
|
-
* @param {string} [config.background] - Page background hex (default: '#ffffff' light, derived dark)
|
|
9104
|
-
* @param {string} [config.surface] - Surface/card background hex (default: '#f8f9fa' light, derived dark)
|
|
9006
|
+
* Generate a complete styles object from seed colors and layout config.
|
|
9007
|
+
* Pure function — no DOM, no state, no side effects.
|
|
9008
|
+
*
|
|
9009
|
+
* All parameters are optional. Defaults to the bitwrench default palette.
|
|
9010
|
+
*
|
|
9011
|
+
* @param {Object} [config] - Style configuration
|
|
9012
|
+
* @param {string} [config.primary='#006666'] - Primary brand color hex
|
|
9013
|
+
* @param {string} [config.secondary='#6c757d'] - Secondary color hex
|
|
9014
|
+
* @param {string} [config.tertiary] - Tertiary color hex (defaults to primary)
|
|
9105
9015
|
* @param {string} [config.spacing='normal'] - 'compact' | 'normal' | 'spacious'
|
|
9106
9016
|
* @param {string} [config.radius='md'] - 'none' | 'sm' | 'md' | 'lg' | 'pill'
|
|
9107
|
-
* @
|
|
9108
|
-
* @param {string|number} [config.typeRatio='normal'] - 'tight' | 'normal' | 'relaxed' | 'dramatic' or a number
|
|
9109
|
-
* @param {string} [config.elevation='md'] - 'flat' | 'sm' | 'md' | 'lg'
|
|
9110
|
-
* @param {string} [config.motion='standard'] - 'reduced' | 'standard' | 'expressive'
|
|
9111
|
-
* @param {number} [config.harmonize=0.20] - 0-1, semantic color hue shift toward primary
|
|
9112
|
-
* @param {boolean} [config.inject=true] - Inject into DOM (browser only)
|
|
9113
|
-
* @returns {Object} { css, palette, name, isLightPrimary, alternate: { css, palette } }
|
|
9017
|
+
* @returns {Object} { css, alternateCss, rules, alternateRules, palette, alternatePalette, isLightPrimary }
|
|
9114
9018
|
* @category CSS & Styling
|
|
9115
|
-
* @see bw.
|
|
9116
|
-
* @see bw.
|
|
9117
|
-
* @see bw.loadDefaultStyles
|
|
9019
|
+
* @see bw.applyStyles
|
|
9020
|
+
* @see bw.loadStyles
|
|
9118
9021
|
* @example
|
|
9119
|
-
*
|
|
9120
|
-
*
|
|
9121
|
-
*
|
|
9122
|
-
* secondary: '#90e0ef',
|
|
9123
|
-
* tertiary: '#00b4d8'
|
|
9124
|
-
* });
|
|
9125
|
-
*
|
|
9126
|
-
* // Apply to a container
|
|
9127
|
-
* document.getElementById('app').classList.add('ocean');
|
|
9128
|
-
*
|
|
9129
|
-
* // Toggle to alternate palette
|
|
9130
|
-
* bw.toggleTheme();
|
|
9131
|
-
*
|
|
9132
|
-
* // Generate CSS for static export (Node.js)
|
|
9133
|
-
* var result = bw.generateTheme('sunset', {
|
|
9134
|
-
* primary: '#e76f51',
|
|
9135
|
-
* secondary: '#264653',
|
|
9136
|
-
* inject: false
|
|
9137
|
-
* });
|
|
9138
|
-
* fs.writeFileSync('sunset.css', result.css + result.alternate.css);
|
|
9022
|
+
* var styles = bw.makeStyles({ primary: '#4f46e5', secondary: '#d97706' });
|
|
9023
|
+
* console.log(styles.palette.primary.base); // '#4f46e5'
|
|
9024
|
+
* // styles.css contains all themed CSS — nothing injected
|
|
9139
9025
|
*/
|
|
9140
|
-
bw.
|
|
9141
|
-
|
|
9142
|
-
|
|
9143
|
-
}
|
|
9144
|
-
|
|
9145
|
-
// Merge with defaults; if user didn't supply tertiary, default to their primary
|
|
9146
|
-
var fullConfig = Object.assign({}, DEFAULT_PALETTE_CONFIG, config);
|
|
9147
|
-
if (!config.tertiary) fullConfig.tertiary = fullConfig.primary;
|
|
9026
|
+
bw.makeStyles = function (config) {
|
|
9027
|
+
var fullConfig = Object.assign({}, DEFAULT_PALETTE_CONFIG, config || {});
|
|
9028
|
+
if (config && !config.tertiary) fullConfig.tertiary = fullConfig.primary;
|
|
9148
9029
|
|
|
9149
9030
|
// Derive primary palette
|
|
9150
9031
|
var palette = derivePalette(fullConfig);
|
|
@@ -9152,136 +9033,211 @@
|
|
|
9152
9033
|
// Resolve layout
|
|
9153
9034
|
var layout = resolveLayout(fullConfig);
|
|
9154
9035
|
|
|
9155
|
-
// Generate primary themed CSS rules
|
|
9156
|
-
var themedRules = generateThemedCSS(
|
|
9036
|
+
// Generate primary themed CSS rules (unscoped)
|
|
9037
|
+
var themedRules = generateThemedCSS('', palette, layout);
|
|
9157
9038
|
var cssStr = bw.css(themedRules);
|
|
9158
9039
|
|
|
9159
9040
|
// Derive alternate palette (luminance-inverted)
|
|
9160
9041
|
var altConfig = deriveAlternateConfig(fullConfig);
|
|
9161
9042
|
var altPalette = derivePalette(altConfig);
|
|
9162
9043
|
|
|
9163
|
-
// Generate alternate CSS
|
|
9164
|
-
|
|
9165
|
-
var
|
|
9044
|
+
// Generate alternate CSS rules WITHOUT .bw_theme_alt prefix (raw rules)
|
|
9045
|
+
// applyStyles() wraps them appropriately based on scope
|
|
9046
|
+
var altRawRules = generateThemedCSS('', altPalette, layout);
|
|
9047
|
+
|
|
9048
|
+
// Add body-level surface overrides for the alternate palette.
|
|
9049
|
+
// When .bw_theme_alt is on <html>, ".bw_theme_alt body" correctly matches.
|
|
9050
|
+
altRawRules['body'] = {
|
|
9051
|
+
'color': altPalette.dark.base,
|
|
9052
|
+
'background-color': altPalette.surface || altPalette.light.base
|
|
9053
|
+
};
|
|
9054
|
+
var altCssStr = bw.css(altRawRules);
|
|
9166
9055
|
|
|
9167
9056
|
// Determine if primary is light-flavored
|
|
9168
9057
|
var lightPrimary = isLightPalette(fullConfig);
|
|
9058
|
+
return {
|
|
9059
|
+
css: cssStr,
|
|
9060
|
+
alternateCss: altCssStr,
|
|
9061
|
+
rules: themedRules,
|
|
9062
|
+
alternateRules: altRawRules,
|
|
9063
|
+
palette: palette,
|
|
9064
|
+
alternatePalette: altPalette,
|
|
9065
|
+
isLightPrimary: lightPrimary
|
|
9066
|
+
};
|
|
9067
|
+
};
|
|
9169
9068
|
|
|
9170
|
-
|
|
9171
|
-
|
|
9172
|
-
|
|
9173
|
-
|
|
9174
|
-
|
|
9175
|
-
|
|
9176
|
-
|
|
9177
|
-
|
|
9178
|
-
|
|
9179
|
-
|
|
9180
|
-
|
|
9181
|
-
|
|
9182
|
-
|
|
9183
|
-
|
|
9184
|
-
|
|
9069
|
+
/**
|
|
9070
|
+
* Inject styles into the DOM with optional scoping.
|
|
9071
|
+
*
|
|
9072
|
+
* Takes a styles object from `makeStyles()` and creates a single `<style>`
|
|
9073
|
+
* element in `<head>`. If a scope selector is provided, all CSS rules are
|
|
9074
|
+
* wrapped under that selector. Alternate CSS is wrapped under `.bw_theme_alt`.
|
|
9075
|
+
*
|
|
9076
|
+
* @param {Object} styles - Result of `bw.makeStyles()`
|
|
9077
|
+
* @param {string} [scope] - Scope selector (e.g. '#my-dashboard', '.preview'). Omit for global.
|
|
9078
|
+
* @returns {Element|null} The `<style>` element, or null in Node.js
|
|
9079
|
+
* @category CSS & Styling
|
|
9080
|
+
* @see bw.makeStyles
|
|
9081
|
+
* @see bw.loadStyles
|
|
9082
|
+
* @see bw.clearStyles
|
|
9083
|
+
* @example
|
|
9084
|
+
* var styles = bw.makeStyles({ primary: '#4f46e5' });
|
|
9085
|
+
* bw.applyStyles(styles); // global
|
|
9086
|
+
* bw.applyStyles(styles, '#my-dashboard'); // scoped
|
|
9087
|
+
*/
|
|
9088
|
+
bw.applyStyles = function (styles, scope) {
|
|
9089
|
+
if (!bw._isBrowser) return null;
|
|
9090
|
+
if (!styles || !styles.rules) {
|
|
9091
|
+
_cw('bw.applyStyles: invalid styles object');
|
|
9092
|
+
return null;
|
|
9185
9093
|
}
|
|
9094
|
+
var styleId = _scopeToStyleId(scope);
|
|
9186
9095
|
|
|
9187
|
-
//
|
|
9188
|
-
|
|
9189
|
-
|
|
9190
|
-
|
|
9191
|
-
color: palette.primary.textOn
|
|
9192
|
-
};
|
|
9193
|
-
bw.u.textTeal = {
|
|
9194
|
-
color: palette.primary.base
|
|
9195
|
-
};
|
|
9196
|
-
bw.u.bgWhite = {
|
|
9197
|
-
background: '#ffffff'
|
|
9198
|
-
};
|
|
9199
|
-
bw.u.textWhite = {
|
|
9200
|
-
color: '#ffffff'
|
|
9201
|
-
};
|
|
9096
|
+
// Scope the primary rules if a scope is provided
|
|
9097
|
+
var primaryRules = styles.rules;
|
|
9098
|
+
if (scope) {
|
|
9099
|
+
primaryRules = scopeRulesUnder(primaryRules, scope);
|
|
9202
9100
|
}
|
|
9203
9101
|
|
|
9204
|
-
//
|
|
9205
|
-
var
|
|
9206
|
-
|
|
9207
|
-
|
|
9208
|
-
|
|
9209
|
-
|
|
9210
|
-
|
|
9211
|
-
|
|
9212
|
-
|
|
9102
|
+
// Wrap alternate rules with .bw_theme_alt
|
|
9103
|
+
var altRules = styles.alternateRules;
|
|
9104
|
+
if (altRules) {
|
|
9105
|
+
if (scope) {
|
|
9106
|
+
// Scoped compound: #scope.bw_theme_alt .bw_card
|
|
9107
|
+
altRules = scopeRulesUnder(altRules, scope + '.bw_theme_alt');
|
|
9108
|
+
} else {
|
|
9109
|
+
// Global: .bw_theme_alt .bw_card
|
|
9110
|
+
altRules = scopeRulesUnder(altRules, '.bw_theme_alt');
|
|
9213
9111
|
}
|
|
9214
|
-
}
|
|
9215
|
-
|
|
9216
|
-
|
|
9217
|
-
|
|
9112
|
+
}
|
|
9113
|
+
|
|
9114
|
+
// Combine primary + alternate into one CSS string
|
|
9115
|
+
var combined = bw.css(primaryRules);
|
|
9116
|
+
if (altRules) {
|
|
9117
|
+
combined += '\n' + bw.css(altRules);
|
|
9118
|
+
}
|
|
9119
|
+
return bw.injectCSS(combined, {
|
|
9120
|
+
id: styleId,
|
|
9121
|
+
append: false
|
|
9122
|
+
});
|
|
9218
9123
|
};
|
|
9219
9124
|
|
|
9220
9125
|
/**
|
|
9221
|
-
*
|
|
9222
|
-
*
|
|
9126
|
+
* Generate and apply styles in one call. Convenience wrapper.
|
|
9127
|
+
*
|
|
9128
|
+
* Equivalent to: `bw.applyStyles(bw.makeStyles(config), scope)`
|
|
9223
9129
|
*
|
|
9224
|
-
* @param {
|
|
9225
|
-
* @
|
|
9130
|
+
* @param {Object} [config] - Style configuration (same as `makeStyles`)
|
|
9131
|
+
* @param {string} [scope] - Scope selector (same as `applyStyles`)
|
|
9132
|
+
* @returns {Element|null} The `<style>` element, or null in Node.js
|
|
9226
9133
|
* @category CSS & Styling
|
|
9227
|
-
* @see bw.
|
|
9228
|
-
* @see bw.
|
|
9134
|
+
* @see bw.makeStyles
|
|
9135
|
+
* @see bw.applyStyles
|
|
9229
9136
|
* @example
|
|
9230
|
-
* bw.
|
|
9231
|
-
* bw.
|
|
9232
|
-
* bw.
|
|
9233
|
-
*/
|
|
9234
|
-
bw.
|
|
9235
|
-
|
|
9236
|
-
|
|
9237
|
-
|
|
9238
|
-
|
|
9239
|
-
|
|
9240
|
-
|
|
9241
|
-
|
|
9242
|
-
|
|
9243
|
-
|
|
9137
|
+
* bw.loadStyles(); // defaults, global
|
|
9138
|
+
* bw.loadStyles({ primary: '#4f46e5' }); // custom, global
|
|
9139
|
+
* bw.loadStyles({ primary: '#4f46e5' }, '#my-dashboard'); // custom, scoped
|
|
9140
|
+
*/
|
|
9141
|
+
bw.loadStyles = function (config, scope) {
|
|
9142
|
+
// Also inject structural CSS first (only once)
|
|
9143
|
+
if (bw._isBrowser) {
|
|
9144
|
+
var existing = document.getElementById('bw_structural');
|
|
9145
|
+
if (!existing) {
|
|
9146
|
+
var structuralCSS = bw.css(getStructuralStyles());
|
|
9147
|
+
bw.injectCSS(structuralCSS, {
|
|
9148
|
+
id: 'bw_structural',
|
|
9149
|
+
append: false
|
|
9150
|
+
});
|
|
9151
|
+
}
|
|
9244
9152
|
}
|
|
9245
|
-
bw.
|
|
9246
|
-
|
|
9153
|
+
return bw.applyStyles(bw.makeStyles(config), scope);
|
|
9154
|
+
};
|
|
9155
|
+
|
|
9156
|
+
/**
|
|
9157
|
+
* Inject the CSS reset (box-sizing, html/body font, reduced-motion).
|
|
9158
|
+
* Idempotent — if already injected, returns the existing `<style>` element.
|
|
9159
|
+
*
|
|
9160
|
+
* @returns {Element|null} The `<style>` element, or null in Node.js
|
|
9161
|
+
* @category CSS & Styling
|
|
9162
|
+
* @see bw.loadStyles
|
|
9163
|
+
* @see bw.clearStyles
|
|
9164
|
+
* @example
|
|
9165
|
+
* bw.loadReset(); // inject once, safe to call multiple times
|
|
9166
|
+
*/
|
|
9167
|
+
bw.loadReset = function () {
|
|
9168
|
+
if (!bw._isBrowser) return null;
|
|
9169
|
+
var existing = document.getElementById('bw_style_reset');
|
|
9170
|
+
if (existing) return existing;
|
|
9171
|
+
return bw.injectCSS(bw.css(getResetStyles()), {
|
|
9172
|
+
id: 'bw_style_reset',
|
|
9173
|
+
append: false
|
|
9174
|
+
});
|
|
9247
9175
|
};
|
|
9248
9176
|
|
|
9249
9177
|
/**
|
|
9250
|
-
* Toggle between primary and alternate
|
|
9178
|
+
* Toggle between primary and alternate palettes.
|
|
9251
9179
|
*
|
|
9180
|
+
* Adds/removes the `bw_theme_alt` class on the scoping element.
|
|
9181
|
+
* Without a scope, toggles on `<html>` (global).
|
|
9182
|
+
* With a scope, toggles on the first matching element.
|
|
9183
|
+
*
|
|
9184
|
+
* @param {string} [scope] - Scope selector (e.g. '#my-dashboard'). Omit for global.
|
|
9252
9185
|
* @returns {string} Active mode after toggle: 'primary' or 'alternate'
|
|
9253
9186
|
* @category CSS & Styling
|
|
9254
|
-
* @see bw.
|
|
9255
|
-
* @see bw.
|
|
9187
|
+
* @see bw.applyStyles
|
|
9188
|
+
* @see bw.clearStyles
|
|
9256
9189
|
* @example
|
|
9257
|
-
* bw.
|
|
9190
|
+
* bw.toggleStyles(); // global toggle on <html>
|
|
9191
|
+
* bw.toggleStyles('#my-dashboard'); // scoped toggle
|
|
9258
9192
|
*/
|
|
9259
|
-
bw.
|
|
9260
|
-
|
|
9261
|
-
|
|
9193
|
+
bw.toggleStyles = function (scope) {
|
|
9194
|
+
if (!bw._isBrowser) return 'primary';
|
|
9195
|
+
var target;
|
|
9196
|
+
if (scope) {
|
|
9197
|
+
var els = bw.$(scope);
|
|
9198
|
+
target = els[0];
|
|
9199
|
+
} else {
|
|
9200
|
+
target = document.documentElement;
|
|
9201
|
+
}
|
|
9202
|
+
if (!target) return 'primary';
|
|
9203
|
+
var hasAlt = target.classList.contains('bw_theme_alt');
|
|
9204
|
+
if (hasAlt) {
|
|
9205
|
+
target.classList.remove('bw_theme_alt');
|
|
9206
|
+
return 'primary';
|
|
9207
|
+
} else {
|
|
9208
|
+
target.classList.add('bw_theme_alt');
|
|
9209
|
+
return 'alternate';
|
|
9210
|
+
}
|
|
9262
9211
|
};
|
|
9263
9212
|
|
|
9264
9213
|
/**
|
|
9265
|
-
* Remove
|
|
9266
|
-
*
|
|
9267
|
-
*
|
|
9214
|
+
* Remove injected styles for a given scope.
|
|
9215
|
+
*
|
|
9216
|
+
* Finds the `<style>` element by id and removes it. Also removes
|
|
9217
|
+
* the `bw_theme_alt` class from the relevant element.
|
|
9268
9218
|
*
|
|
9219
|
+
* @param {string} [scope] - Scope selector. Omit to remove global styles.
|
|
9269
9220
|
* @category CSS & Styling
|
|
9270
|
-
* @see bw.
|
|
9221
|
+
* @see bw.applyStyles
|
|
9222
|
+
* @see bw.loadStyles
|
|
9271
9223
|
* @example
|
|
9272
|
-
* bw.
|
|
9273
|
-
* bw.
|
|
9274
|
-
|
|
9275
|
-
|
|
9276
|
-
|
|
9277
|
-
|
|
9278
|
-
|
|
9279
|
-
|
|
9280
|
-
|
|
9281
|
-
|
|
9224
|
+
* bw.clearStyles(); // remove global styles
|
|
9225
|
+
* bw.clearStyles('#my-dashboard'); // remove scoped styles
|
|
9226
|
+
* bw.clearStyles('reset'); // remove the CSS reset
|
|
9227
|
+
*/
|
|
9228
|
+
bw.clearStyles = function (scope) {
|
|
9229
|
+
if (!bw._isBrowser) return;
|
|
9230
|
+
var styleId = _scopeToStyleId(scope);
|
|
9231
|
+
var el = document.getElementById(styleId);
|
|
9232
|
+
if (el) el.remove();
|
|
9233
|
+
|
|
9234
|
+
// Also remove bw_theme_alt from the relevant element
|
|
9235
|
+
if (scope && scope !== 'reset' && scope !== 'global') {
|
|
9236
|
+
var targets = bw.$(scope);
|
|
9237
|
+
if (targets[0]) targets[0].classList.remove('bw_theme_alt');
|
|
9238
|
+
} else if (!scope || scope === 'global') {
|
|
9239
|
+
document.documentElement.classList.remove('bw_theme_alt');
|
|
9282
9240
|
}
|
|
9283
|
-
bw._activeTheme = null;
|
|
9284
|
-
bw._activeThemeMode = 'primary';
|
|
9285
9241
|
};
|
|
9286
9242
|
|
|
9287
9243
|
// Expose color utility functions on bw namespace
|
|
@@ -9503,10 +9459,15 @@
|
|
|
9503
9459
|
* @param {Object} config - Table configuration
|
|
9504
9460
|
* @param {Array<Object>} config.data - Array of row objects to display
|
|
9505
9461
|
* @param {Array<Object>} [config.columns] - Column definitions with key, label, render
|
|
9506
|
-
* @param {string} [config.className='
|
|
9462
|
+
* @param {string} [config.className=''] - Additional CSS classes for table element
|
|
9507
9463
|
* @param {boolean} [config.sortable=true] - Enable click-to-sort headers
|
|
9508
9464
|
* @param {Function} [config.onSort] - Sort callback (column, direction)
|
|
9509
|
-
* @
|
|
9465
|
+
* @param {boolean} [config.selectable=false] - Enable row selection on click
|
|
9466
|
+
* @param {Function} [config.onRowClick] - Row click callback (row, index, event)
|
|
9467
|
+
* @param {number} [config.pageSize] - Rows per page (enables pagination when set)
|
|
9468
|
+
* @param {number} [config.currentPage=1] - Current page number (1-based)
|
|
9469
|
+
* @param {Function} [config.onPageChange] - Page change callback (newPage)
|
|
9470
|
+
* @returns {Object} TACO object for table (with optional pagination controls)
|
|
9510
9471
|
* @category Component Builders
|
|
9511
9472
|
* @see bw.makeDataTable
|
|
9512
9473
|
* @example
|
|
@@ -9518,7 +9479,12 @@
|
|
|
9518
9479
|
* columns: [
|
|
9519
9480
|
* { key: 'name', label: 'Name' },
|
|
9520
9481
|
* { key: 'age', label: 'Age' }
|
|
9521
|
-
* ]
|
|
9482
|
+
* ],
|
|
9483
|
+
* selectable: true,
|
|
9484
|
+
* onRowClick: function(row, i) { console.log('clicked', row.name); },
|
|
9485
|
+
* pageSize: 10,
|
|
9486
|
+
* currentPage: 1,
|
|
9487
|
+
* onPageChange: function(page) { console.log('page', page); }
|
|
9522
9488
|
* });
|
|
9523
9489
|
*/
|
|
9524
9490
|
bw.makeTable = function (config) {
|
|
@@ -9536,12 +9502,20 @@
|
|
|
9536
9502
|
onSort = config.onSort,
|
|
9537
9503
|
sortColumn = config.sortColumn,
|
|
9538
9504
|
_config$sortDirection = config.sortDirection,
|
|
9539
|
-
sortDirection = _config$sortDirection === void 0 ? 'asc' : _config$sortDirection
|
|
9540
|
-
|
|
9541
|
-
|
|
9505
|
+
sortDirection = _config$sortDirection === void 0 ? 'asc' : _config$sortDirection,
|
|
9506
|
+
_config$selectable = config.selectable,
|
|
9507
|
+
selectable = _config$selectable === void 0 ? false : _config$selectable,
|
|
9508
|
+
onRowClick = config.onRowClick,
|
|
9509
|
+
pageSize = config.pageSize,
|
|
9510
|
+
_config$currentPage = config.currentPage,
|
|
9511
|
+
currentPage = _config$currentPage === void 0 ? 1 : _config$currentPage,
|
|
9512
|
+
onPageChange = config.onPageChange;
|
|
9513
|
+
|
|
9514
|
+
// Build class list: always include bw_table, add striped/hover/selectable, append user className
|
|
9542
9515
|
var cls = 'bw_table';
|
|
9543
9516
|
if (striped) cls += ' bw_table_striped';
|
|
9544
|
-
if (hover) cls += ' bw_table_hover';
|
|
9517
|
+
if (hover || selectable) cls += ' bw_table_hover';
|
|
9518
|
+
if (selectable) cls += ' bw_table_selectable';
|
|
9545
9519
|
if (className) cls += ' ' + className;
|
|
9546
9520
|
cls = cls.trim();
|
|
9547
9521
|
|
|
@@ -9580,6 +9554,15 @@
|
|
|
9580
9554
|
});
|
|
9581
9555
|
}
|
|
9582
9556
|
|
|
9557
|
+
// Pagination
|
|
9558
|
+
var totalRows = sortedData.length;
|
|
9559
|
+
var totalPages = pageSize ? Math.max(1, Math.ceil(totalRows / pageSize)) : 1;
|
|
9560
|
+
var page = Math.max(1, Math.min(currentPage, totalPages));
|
|
9561
|
+
if (pageSize) {
|
|
9562
|
+
var start = (page - 1) * pageSize;
|
|
9563
|
+
sortedData = sortedData.slice(start, start + pageSize);
|
|
9564
|
+
}
|
|
9565
|
+
|
|
9583
9566
|
// Create sort handler
|
|
9584
9567
|
var handleSort = function handleSort(column) {
|
|
9585
9568
|
if (!sortable) return;
|
|
@@ -9625,12 +9608,28 @@
|
|
|
9625
9608
|
}
|
|
9626
9609
|
};
|
|
9627
9610
|
|
|
9628
|
-
// Build table body
|
|
9611
|
+
// Build table body with selectable/onRowClick support
|
|
9629
9612
|
var tbody = {
|
|
9630
9613
|
t: 'tbody',
|
|
9631
|
-
c: sortedData.map(function (row) {
|
|
9614
|
+
c: sortedData.map(function (row, idx) {
|
|
9615
|
+
var globalIdx = pageSize ? (page - 1) * pageSize + idx : idx;
|
|
9616
|
+
var rowAttrs = {};
|
|
9617
|
+
if (selectable || onRowClick) {
|
|
9618
|
+
rowAttrs.style = 'cursor:pointer;';
|
|
9619
|
+
rowAttrs.onclick = function (e) {
|
|
9620
|
+
if (selectable) {
|
|
9621
|
+
// Toggle selected class on this row
|
|
9622
|
+
var tr = e.currentTarget;
|
|
9623
|
+
tr.classList.toggle('bw_table_row_selected');
|
|
9624
|
+
}
|
|
9625
|
+
if (onRowClick) {
|
|
9626
|
+
onRowClick(row, globalIdx, e);
|
|
9627
|
+
}
|
|
9628
|
+
};
|
|
9629
|
+
}
|
|
9632
9630
|
return {
|
|
9633
9631
|
t: 'tr',
|
|
9632
|
+
a: rowAttrs,
|
|
9634
9633
|
c: cols.map(function (col) {
|
|
9635
9634
|
return {
|
|
9636
9635
|
t: 'td',
|
|
@@ -9640,13 +9639,65 @@
|
|
|
9640
9639
|
};
|
|
9641
9640
|
})
|
|
9642
9641
|
};
|
|
9643
|
-
|
|
9642
|
+
var table = {
|
|
9644
9643
|
t: 'table',
|
|
9645
9644
|
a: {
|
|
9646
9645
|
"class": cls
|
|
9647
9646
|
},
|
|
9648
9647
|
c: [thead, tbody]
|
|
9649
9648
|
};
|
|
9649
|
+
|
|
9650
|
+
// If no pagination, return table directly
|
|
9651
|
+
if (!pageSize) return table;
|
|
9652
|
+
|
|
9653
|
+
// Build pagination controls
|
|
9654
|
+
var pageButtons = [];
|
|
9655
|
+
// Previous button
|
|
9656
|
+
pageButtons.push({
|
|
9657
|
+
t: 'button',
|
|
9658
|
+
a: {
|
|
9659
|
+
"class": 'bw_btn bw_btn_sm',
|
|
9660
|
+
disabled: page <= 1 ? 'disabled' : undefined,
|
|
9661
|
+
onclick: page > 1 && onPageChange ? function () {
|
|
9662
|
+
onPageChange(page - 1);
|
|
9663
|
+
} : undefined
|
|
9664
|
+
},
|
|
9665
|
+
c: 'Prev'
|
|
9666
|
+
});
|
|
9667
|
+
// Page info
|
|
9668
|
+
pageButtons.push({
|
|
9669
|
+
t: 'span',
|
|
9670
|
+
a: {
|
|
9671
|
+
style: 'margin:0 0.5rem;font-size:0.875rem;'
|
|
9672
|
+
},
|
|
9673
|
+
c: 'Page ' + page + ' of ' + totalPages
|
|
9674
|
+
});
|
|
9675
|
+
// Next button
|
|
9676
|
+
pageButtons.push({
|
|
9677
|
+
t: 'button',
|
|
9678
|
+
a: {
|
|
9679
|
+
"class": 'bw_btn bw_btn_sm',
|
|
9680
|
+
disabled: page >= totalPages ? 'disabled' : undefined,
|
|
9681
|
+
onclick: page < totalPages && onPageChange ? function () {
|
|
9682
|
+
onPageChange(page + 1);
|
|
9683
|
+
} : undefined
|
|
9684
|
+
},
|
|
9685
|
+
c: 'Next'
|
|
9686
|
+
});
|
|
9687
|
+
return {
|
|
9688
|
+
t: 'div',
|
|
9689
|
+
a: {
|
|
9690
|
+
"class": 'bw_table_paginated'
|
|
9691
|
+
},
|
|
9692
|
+
c: [table, {
|
|
9693
|
+
t: 'div',
|
|
9694
|
+
a: {
|
|
9695
|
+
"class": 'bw_table_pagination',
|
|
9696
|
+
style: 'display:flex;align-items:center;justify-content:flex-end;padding:0.5rem 0;gap:0.25rem;'
|
|
9697
|
+
},
|
|
9698
|
+
c: pageButtons
|
|
9699
|
+
}]
|
|
9700
|
+
};
|
|
9650
9701
|
};
|
|
9651
9702
|
|
|
9652
9703
|
/**
|