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
package/dist/bitwrench.es5.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! bitwrench v2.0.
|
|
1
|
+
/*! bitwrench 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
|
-
|
|
1276
|
-
|
|
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
|
|
1277
1267
|
};
|
|
1278
|
-
rules[
|
|
1268
|
+
rules[_sx(scope, '.bw_breadcrumb_item + .bw_breadcrumb_item::before')] = {
|
|
1279
1269
|
'color': palette.secondary.base
|
|
1280
1270
|
};
|
|
1281
|
-
rules[
|
|
1271
|
+
rules[_sx(scope, '.bw_breadcrumb_item a')] = {
|
|
1272
|
+
'color': palette.primary.base,
|
|
1273
|
+
'transition': 'color ' + mo.fast + ' ' + mo.easing
|
|
1274
|
+
};
|
|
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
|
/**
|
|
@@ -5414,7 +5595,7 @@
|
|
|
5414
5595
|
if (breakpoint === 'xs') {
|
|
5415
5596
|
classes.push("bw_col_".concat(value));
|
|
5416
5597
|
} else {
|
|
5417
|
-
classes.push("bw_col_".concat(breakpoint, "
|
|
5598
|
+
classes.push("bw_col_".concat(breakpoint, "_").concat(value));
|
|
5418
5599
|
}
|
|
5419
5600
|
});
|
|
5420
5601
|
} else if (size) {
|
|
@@ -6939,12 +7120,13 @@
|
|
|
6939
7120
|
"class": "bw_page_item ".concat(currentPage <= 1 ? 'bw_disabled' : '').trim()
|
|
6940
7121
|
},
|
|
6941
7122
|
c: {
|
|
6942
|
-
t: '
|
|
7123
|
+
t: 'button',
|
|
6943
7124
|
a: {
|
|
6944
7125
|
"class": 'bw_page_link',
|
|
6945
|
-
|
|
7126
|
+
type: 'button',
|
|
6946
7127
|
onclick: handleClick(currentPage - 1),
|
|
6947
|
-
'aria-label': 'Previous'
|
|
7128
|
+
'aria-label': 'Previous',
|
|
7129
|
+
disabled: currentPage <= 1 ? true : undefined
|
|
6948
7130
|
},
|
|
6949
7131
|
c: "\u2039"
|
|
6950
7132
|
}
|
|
@@ -6959,11 +7141,12 @@
|
|
|
6959
7141
|
"class": "bw_page_item ".concat(pageNum === currentPage ? 'bw_active' : '').trim()
|
|
6960
7142
|
},
|
|
6961
7143
|
c: {
|
|
6962
|
-
t: '
|
|
7144
|
+
t: 'button',
|
|
6963
7145
|
a: {
|
|
6964
7146
|
"class": 'bw_page_link',
|
|
6965
|
-
|
|
6966
|
-
onclick: handleClick(pageNum)
|
|
7147
|
+
type: 'button',
|
|
7148
|
+
onclick: handleClick(pageNum),
|
|
7149
|
+
'aria-current': pageNum === currentPage ? 'page' : undefined
|
|
6967
7150
|
},
|
|
6968
7151
|
c: '' + pageNum
|
|
6969
7152
|
}
|
|
@@ -6978,12 +7161,13 @@
|
|
|
6978
7161
|
"class": "bw_page_item ".concat(currentPage >= pages ? 'bw_disabled' : '').trim()
|
|
6979
7162
|
},
|
|
6980
7163
|
c: {
|
|
6981
|
-
t: '
|
|
7164
|
+
t: 'button',
|
|
6982
7165
|
a: {
|
|
6983
7166
|
"class": 'bw_page_link',
|
|
6984
|
-
|
|
7167
|
+
type: 'button',
|
|
6985
7168
|
onclick: handleClick(currentPage + 1),
|
|
6986
|
-
'aria-label': 'Next'
|
|
7169
|
+
'aria-label': 'Next',
|
|
7170
|
+
disabled: currentPage >= pages ? true : undefined
|
|
6987
7171
|
},
|
|
6988
7172
|
c: "\u203A"
|
|
6989
7173
|
}
|
|
@@ -9496,7 +9680,12 @@
|
|
|
9496
9680
|
el = document.querySelector('[data-bw_id="' + id + '"]');
|
|
9497
9681
|
}
|
|
9498
9682
|
|
|
9499
|
-
// 5.
|
|
9683
|
+
// 5. Try class-based lookup for bw_uuid_* tokens (UUID addressing)
|
|
9684
|
+
if (!el && id.indexOf('bw_uuid_') === 0) {
|
|
9685
|
+
el = document.querySelector('.' + id);
|
|
9686
|
+
}
|
|
9687
|
+
|
|
9688
|
+
// 6. Cache the result for next time
|
|
9500
9689
|
if (el) {
|
|
9501
9690
|
bw._nodeMap[id] = el;
|
|
9502
9691
|
}
|
|
@@ -9548,6 +9737,79 @@
|
|
|
9548
9737
|
}
|
|
9549
9738
|
};
|
|
9550
9739
|
|
|
9740
|
+
// ===================================================================================
|
|
9741
|
+
// bw.assignUUID() / bw.getUUID() — Explicit UUID addressing for TACO objects
|
|
9742
|
+
// ===================================================================================
|
|
9743
|
+
|
|
9744
|
+
/**
|
|
9745
|
+
* Regex to match a bw_uuid_* token in a class string.
|
|
9746
|
+
* @private
|
|
9747
|
+
*/
|
|
9748
|
+
var _UUID_RE = /\bbw_uuid_[a-z0-9_]+\b/;
|
|
9749
|
+
|
|
9750
|
+
/**
|
|
9751
|
+
* Assign a UUID to a TACO object by appending a `bw_uuid_*` token to `taco.a.class`.
|
|
9752
|
+
*
|
|
9753
|
+
* Idempotent by default — calling twice returns the same UUID. Pass `forceNew=true`
|
|
9754
|
+
* to replace an existing UUID (useful in loops where each TACO needs a unique ID).
|
|
9755
|
+
*
|
|
9756
|
+
* @param {Object} taco - A TACO object `{t, a, c, o}`
|
|
9757
|
+
* @param {boolean} [forceNew=false] - If true, replaces any existing UUID with a new one
|
|
9758
|
+
* @returns {string} The UUID string (e.g. 'bw_uuid_a1b2c3d4e5')
|
|
9759
|
+
* @category Identifiers
|
|
9760
|
+
* @example
|
|
9761
|
+
* var card = bw.makeStatCard({ value: '0', label: 'Scans' });
|
|
9762
|
+
* var uuid = bw.assignUUID(card); // 'bw_uuid_a1b2c3d4e5'
|
|
9763
|
+
* var same = bw.assignUUID(card); // same UUID (idempotent)
|
|
9764
|
+
* var diff = bw.assignUUID(card, true); // new UUID (forced)
|
|
9765
|
+
*/
|
|
9766
|
+
bw.assignUUID = function (taco, forceNew) {
|
|
9767
|
+
if (!taco || !_is(taco, 'object')) return null;
|
|
9768
|
+
|
|
9769
|
+
// Ensure taco.a exists
|
|
9770
|
+
if (!taco.a) taco.a = {};
|
|
9771
|
+
if (!_is(taco.a["class"], 'string')) taco.a["class"] = taco.a["class"] ? String(taco.a["class"]) : '';
|
|
9772
|
+
var existing = taco.a["class"].match(_UUID_RE);
|
|
9773
|
+
if (existing && !forceNew) {
|
|
9774
|
+
return existing[0];
|
|
9775
|
+
}
|
|
9776
|
+
|
|
9777
|
+
// Remove old UUID if forceNew
|
|
9778
|
+
if (existing) {
|
|
9779
|
+
taco.a["class"] = taco.a["class"].replace(_UUID_RE, '').replace(/\s+/g, ' ').trim();
|
|
9780
|
+
}
|
|
9781
|
+
var uuid = bw.uuid('uuid');
|
|
9782
|
+
taco.a["class"] = (taco.a["class"] ? taco.a["class"] + ' ' : '') + uuid;
|
|
9783
|
+
return uuid;
|
|
9784
|
+
};
|
|
9785
|
+
|
|
9786
|
+
/**
|
|
9787
|
+
* Read the UUID from a TACO object or DOM element. Pure getter, no side effects.
|
|
9788
|
+
*
|
|
9789
|
+
* @param {Object|Element} tacoOrElement - A TACO object or DOM element
|
|
9790
|
+
* @returns {string|null} The UUID string, or null if none assigned
|
|
9791
|
+
* @category Identifiers
|
|
9792
|
+
* @example
|
|
9793
|
+
* bw.getUUID(card) // 'bw_uuid_a1b2c3d4e5' (from TACO)
|
|
9794
|
+
* bw.getUUID(domEl) // 'bw_uuid_a1b2c3d4e5' (from DOM element)
|
|
9795
|
+
* bw.getUUID({t:'div'}) // null (no UUID)
|
|
9796
|
+
*/
|
|
9797
|
+
bw.getUUID = function (tacoOrElement) {
|
|
9798
|
+
if (!tacoOrElement) return null;
|
|
9799
|
+
var classStr;
|
|
9800
|
+
// DOM element: check className
|
|
9801
|
+
if (tacoOrElement.className !== undefined && tacoOrElement.tagName) {
|
|
9802
|
+
classStr = tacoOrElement.className;
|
|
9803
|
+
}
|
|
9804
|
+
// TACO object: check a.class
|
|
9805
|
+
else if (tacoOrElement.a && _is(tacoOrElement.a["class"], 'string')) {
|
|
9806
|
+
classStr = tacoOrElement.a["class"];
|
|
9807
|
+
}
|
|
9808
|
+
if (!classStr) return null;
|
|
9809
|
+
var match = classStr.match(_UUID_RE);
|
|
9810
|
+
return match ? match[0] : null;
|
|
9811
|
+
};
|
|
9812
|
+
|
|
9551
9813
|
/**
|
|
9552
9814
|
* Escape HTML special characters to prevent XSS.
|
|
9553
9815
|
*
|
|
@@ -9600,6 +9862,45 @@
|
|
|
9600
9862
|
};
|
|
9601
9863
|
};
|
|
9602
9864
|
|
|
9865
|
+
/**
|
|
9866
|
+
* Hyperscript-style TACO constructor.
|
|
9867
|
+
*
|
|
9868
|
+
* A convenience helper that returns a canonical TACO object from positional
|
|
9869
|
+
* arguments. The return value is a plain object — serializable, works with
|
|
9870
|
+
* bwserve, and accepted everywhere TACO is accepted.
|
|
9871
|
+
*
|
|
9872
|
+
* @param {string} tag - HTML tag name (e.g. 'div', 'p', 'section')
|
|
9873
|
+
* @param {Object|null} [attrs] - HTML attributes object. Pass null or omit to skip.
|
|
9874
|
+
* @param {*} [content] - Content: string, number, TACO object, or array of children.
|
|
9875
|
+
* @param {Object} [options] - TACO options (state, lifecycle hooks, render fn).
|
|
9876
|
+
* @returns {Object} Plain TACO object {t, a?, c?, o?}
|
|
9877
|
+
* @category Utilities
|
|
9878
|
+
* @see bw.html
|
|
9879
|
+
* @see bw.createDOM
|
|
9880
|
+
* @see bw.DOM
|
|
9881
|
+
* @example
|
|
9882
|
+
* bw.h('div')
|
|
9883
|
+
* // => { t: 'div' }
|
|
9884
|
+
*
|
|
9885
|
+
* bw.h('p', { class: 'bw_text_muted' }, 'Hello')
|
|
9886
|
+
* // => { t: 'p', a: { class: 'bw_text_muted' }, c: 'Hello' }
|
|
9887
|
+
*
|
|
9888
|
+
* bw.h('ul', null, [
|
|
9889
|
+
* bw.h('li', null, 'one'),
|
|
9890
|
+
* bw.h('li', null, 'two')
|
|
9891
|
+
* ])
|
|
9892
|
+
* // => { t: 'ul', c: [{ t: 'li', c: 'one' }, { t: 'li', c: 'two' }] }
|
|
9893
|
+
*/
|
|
9894
|
+
bw.h = function (tag, attrs, content, options) {
|
|
9895
|
+
var taco = {
|
|
9896
|
+
t: String(tag)
|
|
9897
|
+
};
|
|
9898
|
+
if (attrs !== null && attrs !== undefined) taco.a = attrs;
|
|
9899
|
+
if (content !== undefined) taco.c = content;
|
|
9900
|
+
if (options !== undefined) taco.o = options;
|
|
9901
|
+
return taco;
|
|
9902
|
+
};
|
|
9903
|
+
|
|
9603
9904
|
/**
|
|
9604
9905
|
* Convert a TACO object (or array of TACOs) to an HTML string.
|
|
9605
9906
|
*
|
|
@@ -9874,9 +10175,7 @@
|
|
|
9874
10175
|
if (theme) {
|
|
9875
10176
|
var themeConfig = _is(theme, 'string') ? THEME_PRESETS[theme.toLowerCase()] || null : theme;
|
|
9876
10177
|
if (themeConfig) {
|
|
9877
|
-
var themeResult = bw.
|
|
9878
|
-
inject: false
|
|
9879
|
-
}));
|
|
10178
|
+
var themeResult = bw.makeStyles(themeConfig);
|
|
9880
10179
|
themeCSS = themeResult.css;
|
|
9881
10180
|
}
|
|
9882
10181
|
}
|
|
@@ -9910,14 +10209,14 @@
|
|
|
9910
10209
|
// Combine all CSS
|
|
9911
10210
|
var allCSS = (themeCSS ? themeCSS + '\n' : '') + css;
|
|
9912
10211
|
|
|
9913
|
-
// Body-end script: registry entries + optional
|
|
10212
|
+
// Body-end script: registry entries + optional loadStyles
|
|
9914
10213
|
var bodyEndScript = '';
|
|
9915
10214
|
var bodyEndParts = [];
|
|
9916
10215
|
if (registryEntries) {
|
|
9917
10216
|
bodyEndParts.push(registryEntries);
|
|
9918
10217
|
}
|
|
9919
10218
|
if (runtime === 'inline' || runtime === 'cdn') {
|
|
9920
|
-
bodyEndParts.push('if(typeof bw!=="undefined"){bw.
|
|
10219
|
+
bodyEndParts.push('if(typeof bw!=="undefined"){bw.loadStyles();}');
|
|
9921
10220
|
}
|
|
9922
10221
|
if (bodyEndParts.length > 0) {
|
|
9923
10222
|
bodyEndScript = '<script>\n' + bodyEndParts.join('\n') + '\n</script>';
|
|
@@ -10091,6 +10390,14 @@
|
|
|
10091
10390
|
bw._registerNode(el, null);
|
|
10092
10391
|
}
|
|
10093
10392
|
|
|
10393
|
+
// Register UUID class in node cache (bw_uuid_* tokens in class string)
|
|
10394
|
+
if (el.className) {
|
|
10395
|
+
var uuidMatch = el.className.match(_UUID_RE);
|
|
10396
|
+
if (uuidMatch) {
|
|
10397
|
+
bw._nodeMap[uuidMatch[0]] = el;
|
|
10398
|
+
}
|
|
10399
|
+
}
|
|
10400
|
+
|
|
10094
10401
|
// Handle lifecycle hooks and state
|
|
10095
10402
|
if (opts.mounted || opts.unmount || opts.render || opts.state) {
|
|
10096
10403
|
var id = attrs['data-bw_id'] || bw.uuid();
|
|
@@ -10450,6 +10757,16 @@
|
|
|
10450
10757
|
bw.cleanup = function (element) {
|
|
10451
10758
|
if (!bw._isBrowser || !element) return;
|
|
10452
10759
|
|
|
10760
|
+
// Deregister UUID classes from node cache (element + descendants)
|
|
10761
|
+
// Covers elements that have UUID but no data-bw_id
|
|
10762
|
+
var selfUuidMatch = element.className && element.className.match(_UUID_RE);
|
|
10763
|
+
if (selfUuidMatch) delete bw._nodeMap[selfUuidMatch[0]];
|
|
10764
|
+
var uuidEls = element.querySelectorAll('[class*="bw_uuid_"]');
|
|
10765
|
+
uuidEls.forEach(function (uel) {
|
|
10766
|
+
var m = uel.className && uel.className.match(_UUID_RE);
|
|
10767
|
+
if (m) delete bw._nodeMap[m[0]];
|
|
10768
|
+
});
|
|
10769
|
+
|
|
10453
10770
|
// Find all elements with data-bw_id
|
|
10454
10771
|
var elements = element.querySelectorAll('[data-bw_id]');
|
|
10455
10772
|
elements.forEach(function (el) {
|
|
@@ -10463,6 +10780,10 @@
|
|
|
10463
10780
|
// Deregister from node cache
|
|
10464
10781
|
bw._deregisterNode(el, id);
|
|
10465
10782
|
|
|
10783
|
+
// Deregister UUID class from node cache
|
|
10784
|
+
var uuidMatch = el.className && el.className.match(_UUID_RE);
|
|
10785
|
+
if (uuidMatch) delete bw._nodeMap[uuidMatch[0]];
|
|
10786
|
+
|
|
10466
10787
|
// Clean up pub/sub subscriptions tied to this element
|
|
10467
10788
|
if (el._bw_subs) {
|
|
10468
10789
|
el._bw_subs.forEach(function (unsub) {
|
|
@@ -10489,6 +10810,10 @@
|
|
|
10489
10810
|
// Deregister from node cache
|
|
10490
10811
|
bw._deregisterNode(element, id);
|
|
10491
10812
|
|
|
10813
|
+
// Deregister UUID class from node cache
|
|
10814
|
+
var elemUuidMatch = element.className && element.className.match(_UUID_RE);
|
|
10815
|
+
if (elemUuidMatch) delete bw._nodeMap[elemUuidMatch[0]];
|
|
10816
|
+
|
|
10492
10817
|
// Clean up pub/sub subscriptions tied to element itself
|
|
10493
10818
|
if (element._bw_subs) {
|
|
10494
10819
|
element._bw_subs.forEach(function (unsub) {
|
|
@@ -11105,7 +11430,7 @@
|
|
|
11105
11430
|
willMount: o.willMount || null,
|
|
11106
11431
|
mounted: o.mounted || null,
|
|
11107
11432
|
willUpdate: o.willUpdate || null,
|
|
11108
|
-
onUpdate: o.onUpdate || null,
|
|
11433
|
+
onUpdate: o.onUpdate || o.updated || null,
|
|
11109
11434
|
unmount: o.unmount || null,
|
|
11110
11435
|
willDestroy: o.willDestroy || null
|
|
11111
11436
|
};
|
|
@@ -12090,7 +12415,7 @@
|
|
|
12090
12415
|
* and calls the named method. This is the bitwrench equivalent of
|
|
12091
12416
|
* Win32 SendMessage(hwnd, msg, wParam, lParam).
|
|
12092
12417
|
*
|
|
12093
|
-
* @param {string} target - Component UUID (data-bw_comp_id) or user tag (CSS class)
|
|
12418
|
+
* @param {string} target - Component UUID (bw_uuid_*), comp ID (data-bw_comp_id), or user tag (CSS class)
|
|
12094
12419
|
* @param {string} action - Method name to call on the component
|
|
12095
12420
|
* @param {*} data - Data to pass to the method
|
|
12096
12421
|
* @returns {boolean} True if message was dispatched successfully
|
|
@@ -12107,9 +12432,14 @@
|
|
|
12107
12432
|
* };
|
|
12108
12433
|
*/
|
|
12109
12434
|
bw.message = function (target, action, data) {
|
|
12110
|
-
// Try
|
|
12111
|
-
var el = bw
|
|
12112
|
-
|
|
12435
|
+
// Try bw._el() first (handles UUID class, nodeMap cache, getElementById)
|
|
12436
|
+
var el = bw._el(target);
|
|
12437
|
+
// Then try data-bw_comp_id attribute
|
|
12438
|
+
if (!el || !el._bwComponentHandle) {
|
|
12439
|
+
el = bw.$('[data-bw_comp_id="' + target + '"]')[0];
|
|
12440
|
+
}
|
|
12441
|
+
// Then try CSS class (user tag)
|
|
12442
|
+
if (!el || !el._bwComponentHandle) {
|
|
12113
12443
|
el = bw.$('.' + target)[0];
|
|
12114
12444
|
}
|
|
12115
12445
|
if (!el || !el._bwComponentHandle) return false;
|
|
@@ -12123,61 +12453,24 @@
|
|
|
12123
12453
|
};
|
|
12124
12454
|
|
|
12125
12455
|
// ===================================================================================
|
|
12126
|
-
// bw.
|
|
12456
|
+
// bw.apply() / bw.parseJSONFlex() — Server-driven UI protocol
|
|
12127
12457
|
// ===================================================================================
|
|
12128
12458
|
|
|
12129
12459
|
/**
|
|
12130
12460
|
* Registry of named functions sent via register messages.
|
|
12131
|
-
* Populated by
|
|
12132
|
-
* Invoked by
|
|
12461
|
+
* Populated by bw.apply({ type: 'register', name, body }).
|
|
12462
|
+
* Invoked by bw.apply({ type: 'call', name, args }).
|
|
12133
12463
|
* @private
|
|
12134
12464
|
*/
|
|
12135
12465
|
bw._clientFunctions = {};
|
|
12136
12466
|
|
|
12137
12467
|
/**
|
|
12138
|
-
* Whether exec messages are allowed. Set by
|
|
12468
|
+
* Whether exec messages are allowed. Set by bwclient connect opts.allowExec.
|
|
12139
12469
|
* Default false — exec messages are rejected unless explicitly opted in.
|
|
12140
12470
|
* @private
|
|
12141
12471
|
*/
|
|
12142
12472
|
bw._allowExec = false;
|
|
12143
12473
|
|
|
12144
|
-
/**
|
|
12145
|
-
* Built-in client functions available via call() without registration.
|
|
12146
|
-
* @private
|
|
12147
|
-
*/
|
|
12148
|
-
bw._builtinClientFunctions = {
|
|
12149
|
-
scrollTo: function scrollTo(selector) {
|
|
12150
|
-
var el = bw._el(selector);
|
|
12151
|
-
if (el) el.scrollTop = el.scrollHeight;
|
|
12152
|
-
},
|
|
12153
|
-
focus: function focus(selector) {
|
|
12154
|
-
var el = bw._el(selector);
|
|
12155
|
-
if (el && _is(el.focus, 'function')) el.focus();
|
|
12156
|
-
},
|
|
12157
|
-
download: function download(filename, content, mimeType) {
|
|
12158
|
-
if (typeof document === 'undefined') return;
|
|
12159
|
-
var blob = new Blob([content], {
|
|
12160
|
-
type: mimeType || 'text/plain'
|
|
12161
|
-
});
|
|
12162
|
-
var a = document.createElement('a');
|
|
12163
|
-
a.href = URL.createObjectURL(blob);
|
|
12164
|
-
a.download = filename;
|
|
12165
|
-
a.click();
|
|
12166
|
-
URL.revokeObjectURL(a.href);
|
|
12167
|
-
},
|
|
12168
|
-
clipboard: function clipboard(text) {
|
|
12169
|
-
if (typeof navigator !== 'undefined' && navigator.clipboard) {
|
|
12170
|
-
navigator.clipboard.writeText(text);
|
|
12171
|
-
}
|
|
12172
|
-
},
|
|
12173
|
-
redirect: function redirect(url) {
|
|
12174
|
-
if (typeof window !== 'undefined') window.location.href = url;
|
|
12175
|
-
},
|
|
12176
|
-
log: function log() {
|
|
12177
|
-
console.log.apply(console, arguments);
|
|
12178
|
-
}
|
|
12179
|
-
};
|
|
12180
|
-
|
|
12181
12474
|
/**
|
|
12182
12475
|
* Parse a bwserve protocol message string, supporting both strict JSON
|
|
12183
12476
|
* and r-prefixed relaxed JSON (single-quoted strings, trailing commas).
|
|
@@ -12192,9 +12485,9 @@
|
|
|
12192
12485
|
* @param {string} str - JSON or r-prefixed relaxed JSON string
|
|
12193
12486
|
* @returns {Object} Parsed message object
|
|
12194
12487
|
* @throws {SyntaxError} If the string is not valid JSON or relaxed JSON
|
|
12195
|
-
* @category
|
|
12488
|
+
* @category Core
|
|
12196
12489
|
*/
|
|
12197
|
-
bw.
|
|
12490
|
+
bw.parseJSONFlex = function (str) {
|
|
12198
12491
|
str = (str || '').trim();
|
|
12199
12492
|
if (str.charAt(0) !== 'r') return JSON.parse(str);
|
|
12200
12493
|
str = str.slice(1);
|
|
@@ -12272,10 +12565,10 @@
|
|
|
12272
12565
|
* append — target.appendChild(bw.createDOM(node))
|
|
12273
12566
|
* remove — bw.cleanup(target); target.remove()
|
|
12274
12567
|
* patch — bw.patch(target, content, attr)
|
|
12275
|
-
* batch — iterate ops, call
|
|
12568
|
+
* batch — iterate ops, call bw.apply for each
|
|
12276
12569
|
* message — bw.message(target, action, data)
|
|
12277
12570
|
* register — store a named function for later call()
|
|
12278
|
-
* call — invoke a registered
|
|
12571
|
+
* call — invoke a registered function
|
|
12279
12572
|
* exec — execute arbitrary JS (requires allowExec)
|
|
12280
12573
|
*
|
|
12281
12574
|
* Target resolution:
|
|
@@ -12284,9 +12577,9 @@
|
|
|
12284
12577
|
*
|
|
12285
12578
|
* @param {Object} msg - Protocol message
|
|
12286
12579
|
* @returns {boolean} true if the message was applied successfully
|
|
12287
|
-
* @category
|
|
12580
|
+
* @category Core
|
|
12288
12581
|
*/
|
|
12289
|
-
bw.
|
|
12582
|
+
bw.apply = function (msg) {
|
|
12290
12583
|
if (!msg || !msg.type) return false;
|
|
12291
12584
|
var type = msg.type;
|
|
12292
12585
|
var target = msg.target;
|
|
@@ -12314,7 +12607,7 @@
|
|
|
12314
12607
|
if (!_isA(msg.ops)) return false;
|
|
12315
12608
|
var allOk = true;
|
|
12316
12609
|
msg.ops.forEach(function (op) {
|
|
12317
|
-
if (!bw.
|
|
12610
|
+
if (!bw.apply(op)) allOk = false;
|
|
12318
12611
|
});
|
|
12319
12612
|
return allOk;
|
|
12320
12613
|
} else if (type === 'message') {
|
|
@@ -12330,7 +12623,7 @@
|
|
|
12330
12623
|
}
|
|
12331
12624
|
} else if (type === 'call') {
|
|
12332
12625
|
if (!msg.name) return false;
|
|
12333
|
-
var fn = bw._clientFunctions[msg.name]
|
|
12626
|
+
var fn = bw._clientFunctions[msg.name];
|
|
12334
12627
|
if (!_is(fn, 'function')) return false;
|
|
12335
12628
|
try {
|
|
12336
12629
|
var args = _isA(msg.args) ? msg.args : [];
|
|
@@ -12357,141 +12650,6 @@
|
|
|
12357
12650
|
return false;
|
|
12358
12651
|
};
|
|
12359
12652
|
|
|
12360
|
-
/**
|
|
12361
|
-
* Connect to a bwserve SSE endpoint and apply protocol messages automatically.
|
|
12362
|
-
*
|
|
12363
|
-
* Returns a connection object with sendAction(), on(), and close() methods.
|
|
12364
|
-
*
|
|
12365
|
-
* @param {string} url - SSE endpoint URL (e.g., '/__bw/events/client-1')
|
|
12366
|
-
* @param {Object} [opts] - Connection options
|
|
12367
|
-
* @param {string} [opts.transport='sse'] - Transport type: 'sse' (default) or 'poll'
|
|
12368
|
-
* @param {number} [opts.interval=2000] - Poll interval in ms (only for 'poll' transport)
|
|
12369
|
-
* @param {string} [opts.actionUrl] - POST endpoint for actions (default: derived from url)
|
|
12370
|
-
* @param {boolean} [opts.reconnect=true] - Auto-reconnect on disconnect
|
|
12371
|
-
* @param {boolean} [opts.allowExec=false] - Enable exec message type (arbitrary JS execution)
|
|
12372
|
-
* @param {Function} [opts.onStatus] - Status callback: 'connecting'|'connected'|'disconnected'
|
|
12373
|
-
* @param {Function} [opts.onMessage] - Raw message callback (before clientApply)
|
|
12374
|
-
* @returns {Object} Connection object { sendAction, on, close, status }
|
|
12375
|
-
* @category Server
|
|
12376
|
-
*/
|
|
12377
|
-
bw.clientConnect = function (url, opts) {
|
|
12378
|
-
opts = opts || {};
|
|
12379
|
-
var transport = opts.transport || 'sse';
|
|
12380
|
-
var actionUrl = opts.actionUrl || url.replace(/\/events\//, '/action/');
|
|
12381
|
-
var reconnect = opts.reconnect !== false;
|
|
12382
|
-
var onStatus = opts.onStatus || function () {};
|
|
12383
|
-
var onMessage = opts.onMessage || null;
|
|
12384
|
-
var handlers = {};
|
|
12385
|
-
// Set the global allowExec flag from connection options
|
|
12386
|
-
bw._allowExec = !!opts.allowExec;
|
|
12387
|
-
var conn = {
|
|
12388
|
-
status: 'connecting',
|
|
12389
|
-
_es: null,
|
|
12390
|
-
_pollTimer: null
|
|
12391
|
-
};
|
|
12392
|
-
function setStatus(s) {
|
|
12393
|
-
conn.status = s;
|
|
12394
|
-
onStatus(s);
|
|
12395
|
-
}
|
|
12396
|
-
function handleMessage(data) {
|
|
12397
|
-
try {
|
|
12398
|
-
var msg = _is(data, 'string') ? bw.clientParse(data) : data;
|
|
12399
|
-
if (onMessage) onMessage(msg);
|
|
12400
|
-
if (handlers.message) handlers.message(msg);
|
|
12401
|
-
bw.clientApply(msg);
|
|
12402
|
-
} catch (e) {
|
|
12403
|
-
if (handlers.error) handlers.error(e);
|
|
12404
|
-
}
|
|
12405
|
-
}
|
|
12406
|
-
if (transport === 'sse' && typeof EventSource !== 'undefined') {
|
|
12407
|
-
setStatus('connecting');
|
|
12408
|
-
var es = new EventSource(url);
|
|
12409
|
-
conn._es = es;
|
|
12410
|
-
es.onopen = function () {
|
|
12411
|
-
setStatus('connected');
|
|
12412
|
-
if (handlers.open) handlers.open();
|
|
12413
|
-
};
|
|
12414
|
-
es.onmessage = function (e) {
|
|
12415
|
-
handleMessage(e.data);
|
|
12416
|
-
};
|
|
12417
|
-
es.onerror = function () {
|
|
12418
|
-
if (conn.status === 'connected') {
|
|
12419
|
-
setStatus('disconnected');
|
|
12420
|
-
}
|
|
12421
|
-
if (handlers.error) handlers.error(new Error('SSE connection error'));
|
|
12422
|
-
if (!reconnect) {
|
|
12423
|
-
es.close();
|
|
12424
|
-
}
|
|
12425
|
-
// EventSource auto-reconnects by default when reconnect=true
|
|
12426
|
-
};
|
|
12427
|
-
} else if (transport === 'poll') {
|
|
12428
|
-
var interval = opts.interval || 2000;
|
|
12429
|
-
setStatus('connected');
|
|
12430
|
-
conn._pollTimer = setInterval(function () {
|
|
12431
|
-
fetch(url).then(function (r) {
|
|
12432
|
-
return r.json();
|
|
12433
|
-
}).then(function (msgs) {
|
|
12434
|
-
if (_isA(msgs)) {
|
|
12435
|
-
msgs.forEach(handleMessage);
|
|
12436
|
-
} else if (msgs && msgs.type) {
|
|
12437
|
-
handleMessage(msgs);
|
|
12438
|
-
}
|
|
12439
|
-
})["catch"](function (e) {
|
|
12440
|
-
if (handlers.error) handlers.error(e);
|
|
12441
|
-
});
|
|
12442
|
-
}, interval);
|
|
12443
|
-
}
|
|
12444
|
-
|
|
12445
|
-
/**
|
|
12446
|
-
* Send an action to the server via POST.
|
|
12447
|
-
* @param {string} action - Action name
|
|
12448
|
-
* @param {Object} [data] - Action payload
|
|
12449
|
-
*/
|
|
12450
|
-
conn.sendAction = function (action, data) {
|
|
12451
|
-
var body = JSON.stringify({
|
|
12452
|
-
type: 'action',
|
|
12453
|
-
action: action,
|
|
12454
|
-
data: data || {}
|
|
12455
|
-
});
|
|
12456
|
-
fetch(actionUrl, {
|
|
12457
|
-
method: 'POST',
|
|
12458
|
-
headers: {
|
|
12459
|
-
'Content-Type': 'application/json'
|
|
12460
|
-
},
|
|
12461
|
-
body: body
|
|
12462
|
-
})["catch"](function (e) {
|
|
12463
|
-
if (handlers.error) handlers.error(e);
|
|
12464
|
-
});
|
|
12465
|
-
};
|
|
12466
|
-
|
|
12467
|
-
/**
|
|
12468
|
-
* Register an event handler.
|
|
12469
|
-
* @param {string} event - 'open'|'message'|'error'|'close'
|
|
12470
|
-
* @param {Function} handler
|
|
12471
|
-
*/
|
|
12472
|
-
conn.on = function (event, handler) {
|
|
12473
|
-
handlers[event] = handler;
|
|
12474
|
-
return conn;
|
|
12475
|
-
};
|
|
12476
|
-
|
|
12477
|
-
/**
|
|
12478
|
-
* Close the connection.
|
|
12479
|
-
*/
|
|
12480
|
-
conn.close = function () {
|
|
12481
|
-
if (conn._es) {
|
|
12482
|
-
conn._es.close();
|
|
12483
|
-
conn._es = null;
|
|
12484
|
-
}
|
|
12485
|
-
if (conn._pollTimer) {
|
|
12486
|
-
clearInterval(conn._pollTimer);
|
|
12487
|
-
conn._pollTimer = null;
|
|
12488
|
-
}
|
|
12489
|
-
setStatus('disconnected');
|
|
12490
|
-
if (handlers.close) handlers.close();
|
|
12491
|
-
};
|
|
12492
|
-
return conn;
|
|
12493
|
-
};
|
|
12494
|
-
|
|
12495
12653
|
// ===================================================================================
|
|
12496
12654
|
// bw.inspect() — Debug utility
|
|
12497
12655
|
// ===================================================================================
|
|
@@ -12720,7 +12878,7 @@
|
|
|
12720
12878
|
* @returns {Element} The style element
|
|
12721
12879
|
* @category CSS & Styling
|
|
12722
12880
|
* @see bw.css
|
|
12723
|
-
* @see bw.
|
|
12881
|
+
* @see bw.loadStyles
|
|
12724
12882
|
* @example
|
|
12725
12883
|
* bw.injectCSS('.my-class { color: red; }');
|
|
12726
12884
|
* bw.injectCSS({ '.card': { padding: '1rem' } }, { id: 'card-styles' });
|
|
@@ -12766,9 +12924,8 @@
|
|
|
12766
12924
|
* @param {...Object} styles - Style objects to merge (left-to-right)
|
|
12767
12925
|
* @returns {Object} Merged style object
|
|
12768
12926
|
* @category CSS & Styling
|
|
12769
|
-
* @see bw.u
|
|
12770
12927
|
* @example
|
|
12771
|
-
* var style = bw.s(
|
|
12928
|
+
* var style = bw.s({ display: 'flex' }, { gap: '1rem' }, { color: 'red' });
|
|
12772
12929
|
* // => { display: 'flex', gap: '1rem', color: 'red' }
|
|
12773
12930
|
*/
|
|
12774
12931
|
bw.s = function () {
|
|
@@ -12780,216 +12937,6 @@
|
|
|
12780
12937
|
return result;
|
|
12781
12938
|
};
|
|
12782
12939
|
|
|
12783
|
-
/**
|
|
12784
|
-
* Pre-built CSS utility objects (like Tailwind utilities, but in JS).
|
|
12785
|
-
*
|
|
12786
|
-
* Compose with `bw.s()` to build inline styles without writing raw CSS strings.
|
|
12787
|
-
* Includes flex, padding, margin, typography, color, border, and transition utilities.
|
|
12788
|
-
*
|
|
12789
|
-
* @category CSS & Styling
|
|
12790
|
-
* @see bw.s
|
|
12791
|
-
* @example
|
|
12792
|
-
* { t: 'div', a: { style: bw.s(bw.u.flex, bw.u.gap4, bw.u.p4) },
|
|
12793
|
-
* c: 'Flexbox with 1rem gap and padding' }
|
|
12794
|
-
*/
|
|
12795
|
-
bw.u = {
|
|
12796
|
-
// Display
|
|
12797
|
-
flex: {
|
|
12798
|
-
display: 'flex'
|
|
12799
|
-
},
|
|
12800
|
-
flexCol: {
|
|
12801
|
-
display: 'flex',
|
|
12802
|
-
flexDirection: 'column'
|
|
12803
|
-
},
|
|
12804
|
-
flexRow: {
|
|
12805
|
-
display: 'flex',
|
|
12806
|
-
flexDirection: 'row'
|
|
12807
|
-
},
|
|
12808
|
-
flexWrap: {
|
|
12809
|
-
display: 'flex',
|
|
12810
|
-
flexWrap: 'wrap'
|
|
12811
|
-
},
|
|
12812
|
-
block: {
|
|
12813
|
-
display: 'block'
|
|
12814
|
-
},
|
|
12815
|
-
inline: {
|
|
12816
|
-
display: 'inline'
|
|
12817
|
-
},
|
|
12818
|
-
hidden: {
|
|
12819
|
-
display: 'none'
|
|
12820
|
-
},
|
|
12821
|
-
// Flex alignment
|
|
12822
|
-
justifyCenter: {
|
|
12823
|
-
justifyContent: 'center'
|
|
12824
|
-
},
|
|
12825
|
-
justifyBetween: {
|
|
12826
|
-
justifyContent: 'space-between'
|
|
12827
|
-
},
|
|
12828
|
-
justifyEnd: {
|
|
12829
|
-
justifyContent: 'flex-end'
|
|
12830
|
-
},
|
|
12831
|
-
alignCenter: {
|
|
12832
|
-
alignItems: 'center'
|
|
12833
|
-
},
|
|
12834
|
-
alignStart: {
|
|
12835
|
-
alignItems: 'flex-start'
|
|
12836
|
-
},
|
|
12837
|
-
alignEnd: {
|
|
12838
|
-
alignItems: 'flex-end'
|
|
12839
|
-
},
|
|
12840
|
-
// Gap (0.25rem increments)
|
|
12841
|
-
gap1: {
|
|
12842
|
-
gap: '0.25rem'
|
|
12843
|
-
},
|
|
12844
|
-
gap2: {
|
|
12845
|
-
gap: '0.5rem'
|
|
12846
|
-
},
|
|
12847
|
-
gap3: {
|
|
12848
|
-
gap: '0.75rem'
|
|
12849
|
-
},
|
|
12850
|
-
gap4: {
|
|
12851
|
-
gap: '1rem'
|
|
12852
|
-
},
|
|
12853
|
-
gap6: {
|
|
12854
|
-
gap: '1.5rem'
|
|
12855
|
-
},
|
|
12856
|
-
gap8: {
|
|
12857
|
-
gap: '2rem'
|
|
12858
|
-
},
|
|
12859
|
-
// Padding
|
|
12860
|
-
p0: {
|
|
12861
|
-
padding: '0'
|
|
12862
|
-
},
|
|
12863
|
-
p1: {
|
|
12864
|
-
padding: '0.25rem'
|
|
12865
|
-
},
|
|
12866
|
-
p2: {
|
|
12867
|
-
padding: '0.5rem'
|
|
12868
|
-
},
|
|
12869
|
-
p3: {
|
|
12870
|
-
padding: '0.75rem'
|
|
12871
|
-
},
|
|
12872
|
-
p4: {
|
|
12873
|
-
padding: '1rem'
|
|
12874
|
-
},
|
|
12875
|
-
p6: {
|
|
12876
|
-
padding: '1.5rem'
|
|
12877
|
-
},
|
|
12878
|
-
p8: {
|
|
12879
|
-
padding: '2rem'
|
|
12880
|
-
},
|
|
12881
|
-
px4: {
|
|
12882
|
-
paddingLeft: '1rem',
|
|
12883
|
-
paddingRight: '1rem'
|
|
12884
|
-
},
|
|
12885
|
-
py2: {
|
|
12886
|
-
paddingTop: '0.5rem',
|
|
12887
|
-
paddingBottom: '0.5rem'
|
|
12888
|
-
},
|
|
12889
|
-
py4: {
|
|
12890
|
-
paddingTop: '1rem',
|
|
12891
|
-
paddingBottom: '1rem'
|
|
12892
|
-
},
|
|
12893
|
-
// Margin (same scale)
|
|
12894
|
-
m0: {
|
|
12895
|
-
margin: '0'
|
|
12896
|
-
},
|
|
12897
|
-
m4: {
|
|
12898
|
-
margin: '1rem'
|
|
12899
|
-
},
|
|
12900
|
-
mt2: {
|
|
12901
|
-
marginTop: '0.5rem'
|
|
12902
|
-
},
|
|
12903
|
-
mt4: {
|
|
12904
|
-
marginTop: '1rem'
|
|
12905
|
-
},
|
|
12906
|
-
mb2: {
|
|
12907
|
-
marginBottom: '0.5rem'
|
|
12908
|
-
},
|
|
12909
|
-
mb4: {
|
|
12910
|
-
marginBottom: '1rem'
|
|
12911
|
-
},
|
|
12912
|
-
mx_auto: {
|
|
12913
|
-
marginLeft: 'auto',
|
|
12914
|
-
marginRight: 'auto'
|
|
12915
|
-
},
|
|
12916
|
-
// Typography
|
|
12917
|
-
textSm: {
|
|
12918
|
-
fontSize: '0.875rem'
|
|
12919
|
-
},
|
|
12920
|
-
textBase: {
|
|
12921
|
-
fontSize: '1rem'
|
|
12922
|
-
},
|
|
12923
|
-
textLg: {
|
|
12924
|
-
fontSize: '1.125rem'
|
|
12925
|
-
},
|
|
12926
|
-
textXl: {
|
|
12927
|
-
fontSize: '1.25rem'
|
|
12928
|
-
},
|
|
12929
|
-
text2xl: {
|
|
12930
|
-
fontSize: '1.5rem'
|
|
12931
|
-
},
|
|
12932
|
-
text3xl: {
|
|
12933
|
-
fontSize: '1.875rem'
|
|
12934
|
-
},
|
|
12935
|
-
bold: {
|
|
12936
|
-
fontWeight: '700'
|
|
12937
|
-
},
|
|
12938
|
-
semibold: {
|
|
12939
|
-
fontWeight: '600'
|
|
12940
|
-
},
|
|
12941
|
-
italic: {
|
|
12942
|
-
fontStyle: 'italic'
|
|
12943
|
-
},
|
|
12944
|
-
textCenter: {
|
|
12945
|
-
textAlign: 'center'
|
|
12946
|
-
},
|
|
12947
|
-
textRight: {
|
|
12948
|
-
textAlign: 'right'
|
|
12949
|
-
},
|
|
12950
|
-
// Colors (from design tokens)
|
|
12951
|
-
bgWhite: {
|
|
12952
|
-
background: '#ffffff'
|
|
12953
|
-
},
|
|
12954
|
-
bgTeal: {
|
|
12955
|
-
background: '#006666',
|
|
12956
|
-
color: '#ffffff'
|
|
12957
|
-
},
|
|
12958
|
-
textWhite: {
|
|
12959
|
-
color: '#ffffff'
|
|
12960
|
-
},
|
|
12961
|
-
textTeal: {
|
|
12962
|
-
color: '#006666'
|
|
12963
|
-
},
|
|
12964
|
-
textMuted: {
|
|
12965
|
-
color: '#888'
|
|
12966
|
-
},
|
|
12967
|
-
// Borders
|
|
12968
|
-
rounded: {
|
|
12969
|
-
borderRadius: '0.375rem'
|
|
12970
|
-
},
|
|
12971
|
-
roundedLg: {
|
|
12972
|
-
borderRadius: '0.5rem'
|
|
12973
|
-
},
|
|
12974
|
-
roundedFull: {
|
|
12975
|
-
borderRadius: '9999px'
|
|
12976
|
-
},
|
|
12977
|
-
border: {
|
|
12978
|
-
border: '1px solid #d8d8d8'
|
|
12979
|
-
},
|
|
12980
|
-
// Sizing
|
|
12981
|
-
wFull: {
|
|
12982
|
-
width: '100%'
|
|
12983
|
-
},
|
|
12984
|
-
hFull: {
|
|
12985
|
-
height: '100%'
|
|
12986
|
-
},
|
|
12987
|
-
// Transitions
|
|
12988
|
-
transition: {
|
|
12989
|
-
transition: 'all 0.2s ease'
|
|
12990
|
-
}
|
|
12991
|
-
};
|
|
12992
|
-
|
|
12993
12940
|
/**
|
|
12994
12941
|
* Generate responsive CSS with media query breakpoints.
|
|
12995
12942
|
*
|
|
@@ -13115,111 +13062,48 @@
|
|
|
13115
13062
|
};
|
|
13116
13063
|
}
|
|
13117
13064
|
|
|
13065
|
+
// =========================================================================
|
|
13066
|
+
// v2.0.18 Clean Styles API — makeStyles / applyStyles / loadStyles / etc.
|
|
13067
|
+
// =========================================================================
|
|
13068
|
+
|
|
13118
13069
|
/**
|
|
13119
|
-
*
|
|
13120
|
-
*
|
|
13121
|
-
*
|
|
13122
|
-
*
|
|
13123
|
-
* Returns null in Node.js (no DOM).
|
|
13124
|
-
*
|
|
13125
|
-
* @param {Object} [options] - Style loading options
|
|
13126
|
-
* @param {boolean} [options.minify=true] - Minify the CSS output
|
|
13127
|
-
* @returns {Element|null} Style element if in browser, null in Node.js
|
|
13128
|
-
* @category CSS & Styling
|
|
13129
|
-
* @see bw.setTheme
|
|
13130
|
-
* @see bw.applyTheme
|
|
13131
|
-
* @see bw.toggleTheme
|
|
13132
|
-
* @example
|
|
13133
|
-
* bw.loadDefaultStyles(); // inject all default CSS
|
|
13070
|
+
* Convert a scope selector to a <style> element id.
|
|
13071
|
+
* @private
|
|
13072
|
+
* @param {string} [scope] - Scope selector (e.g. '#my-dashboard', '.preview')
|
|
13073
|
+
* @returns {string} Style element id (e.g. 'bw_style_my_dashboard')
|
|
13134
13074
|
*/
|
|
13135
|
-
|
|
13136
|
-
|
|
13137
|
-
|
|
13138
|
-
|
|
13139
|
-
|
|
13140
|
-
|
|
13141
|
-
|
|
13142
|
-
if (bw._isBrowser) {
|
|
13143
|
-
var structuralCSS = bw.css(getStructuralStyles());
|
|
13144
|
-
bw.injectCSS(structuralCSS, {
|
|
13145
|
-
id: 'bw_structural',
|
|
13146
|
-
append: false,
|
|
13147
|
-
minify: minify
|
|
13148
|
-
});
|
|
13149
|
-
}
|
|
13150
|
-
|
|
13151
|
-
// 2. Inject cosmetic CSS via generateTheme (colors, shadows, radii)
|
|
13152
|
-
var paletteConfig = Object.assign({}, DEFAULT_PALETTE_CONFIG, palette || {});
|
|
13153
|
-
var result = bw.generateTheme('', Object.assign({}, paletteConfig, {
|
|
13154
|
-
inject: true
|
|
13155
|
-
}));
|
|
13156
|
-
return result;
|
|
13157
|
-
};
|
|
13075
|
+
function _scopeToStyleId(scope) {
|
|
13076
|
+
if (!scope || scope === '' || scope === 'global') return 'bw_style_global';
|
|
13077
|
+
if (scope === 'reset') return 'bw_style_reset';
|
|
13078
|
+
// Strip leading # or . and convert - to _
|
|
13079
|
+
var clean = scope.replace(/^[#.]/, '').replace(/-/g, '_');
|
|
13080
|
+
return 'bw_style_' + clean;
|
|
13081
|
+
}
|
|
13158
13082
|
|
|
13159
13083
|
/**
|
|
13160
|
-
* Generate a complete
|
|
13161
|
-
*
|
|
13162
|
-
*
|
|
13163
|
-
*
|
|
13164
|
-
*
|
|
13165
|
-
*
|
|
13166
|
-
*
|
|
13167
|
-
* @param {string}
|
|
13168
|
-
* @param {
|
|
13169
|
-
* @param {string} config.primary - Primary brand color hex
|
|
13170
|
-
* @param {string} config.secondary - Secondary color hex
|
|
13171
|
-
* @param {string} [config.tertiary] - Tertiary/accent color hex (defaults to primary)
|
|
13172
|
-
* @param {string} [config.success='#198754'] - Success color hex
|
|
13173
|
-
* @param {string} [config.danger='#dc3545'] - Danger color hex
|
|
13174
|
-
* @param {string} [config.warning='#ffc107'] - Warning color hex
|
|
13175
|
-
* @param {string} [config.info='#0dcaf0'] - Info color hex
|
|
13176
|
-
* @param {string} [config.light='#f8f9fa'] - Light color hex
|
|
13177
|
-
* @param {string} [config.dark='#212529'] - Dark color hex
|
|
13178
|
-
* @param {string} [config.background] - Page background hex (default: '#ffffff' light, derived dark)
|
|
13179
|
-
* @param {string} [config.surface] - Surface/card background hex (default: '#f8f9fa' light, derived dark)
|
|
13084
|
+
* Generate a complete styles object from seed colors and layout config.
|
|
13085
|
+
* Pure function — no DOM, no state, no side effects.
|
|
13086
|
+
*
|
|
13087
|
+
* All parameters are optional. Defaults to the bitwrench default palette.
|
|
13088
|
+
*
|
|
13089
|
+
* @param {Object} [config] - Style configuration
|
|
13090
|
+
* @param {string} [config.primary='#006666'] - Primary brand color hex
|
|
13091
|
+
* @param {string} [config.secondary='#6c757d'] - Secondary color hex
|
|
13092
|
+
* @param {string} [config.tertiary] - Tertiary color hex (defaults to primary)
|
|
13180
13093
|
* @param {string} [config.spacing='normal'] - 'compact' | 'normal' | 'spacious'
|
|
13181
13094
|
* @param {string} [config.radius='md'] - 'none' | 'sm' | 'md' | 'lg' | 'pill'
|
|
13182
|
-
* @
|
|
13183
|
-
* @param {string|number} [config.typeRatio='normal'] - 'tight' | 'normal' | 'relaxed' | 'dramatic' or a number
|
|
13184
|
-
* @param {string} [config.elevation='md'] - 'flat' | 'sm' | 'md' | 'lg'
|
|
13185
|
-
* @param {string} [config.motion='standard'] - 'reduced' | 'standard' | 'expressive'
|
|
13186
|
-
* @param {number} [config.harmonize=0.20] - 0-1, semantic color hue shift toward primary
|
|
13187
|
-
* @param {boolean} [config.inject=true] - Inject into DOM (browser only)
|
|
13188
|
-
* @returns {Object} { css, palette, name, isLightPrimary, alternate: { css, palette } }
|
|
13095
|
+
* @returns {Object} { css, alternateCss, rules, alternateRules, palette, alternatePalette, isLightPrimary }
|
|
13189
13096
|
* @category CSS & Styling
|
|
13190
|
-
* @see bw.
|
|
13191
|
-
* @see bw.
|
|
13192
|
-
* @see bw.loadDefaultStyles
|
|
13097
|
+
* @see bw.applyStyles
|
|
13098
|
+
* @see bw.loadStyles
|
|
13193
13099
|
* @example
|
|
13194
|
-
*
|
|
13195
|
-
*
|
|
13196
|
-
*
|
|
13197
|
-
* secondary: '#90e0ef',
|
|
13198
|
-
* tertiary: '#00b4d8'
|
|
13199
|
-
* });
|
|
13200
|
-
*
|
|
13201
|
-
* // Apply to a container
|
|
13202
|
-
* document.getElementById('app').classList.add('ocean');
|
|
13203
|
-
*
|
|
13204
|
-
* // Toggle to alternate palette
|
|
13205
|
-
* bw.toggleTheme();
|
|
13206
|
-
*
|
|
13207
|
-
* // Generate CSS for static export (Node.js)
|
|
13208
|
-
* var result = bw.generateTheme('sunset', {
|
|
13209
|
-
* primary: '#e76f51',
|
|
13210
|
-
* secondary: '#264653',
|
|
13211
|
-
* inject: false
|
|
13212
|
-
* });
|
|
13213
|
-
* fs.writeFileSync('sunset.css', result.css + result.alternate.css);
|
|
13100
|
+
* var styles = bw.makeStyles({ primary: '#4f46e5', secondary: '#d97706' });
|
|
13101
|
+
* console.log(styles.palette.primary.base); // '#4f46e5'
|
|
13102
|
+
* // styles.css contains all themed CSS — nothing injected
|
|
13214
13103
|
*/
|
|
13215
|
-
bw.
|
|
13216
|
-
|
|
13217
|
-
|
|
13218
|
-
}
|
|
13219
|
-
|
|
13220
|
-
// Merge with defaults; if user didn't supply tertiary, default to their primary
|
|
13221
|
-
var fullConfig = Object.assign({}, DEFAULT_PALETTE_CONFIG, config);
|
|
13222
|
-
if (!config.tertiary) fullConfig.tertiary = fullConfig.primary;
|
|
13104
|
+
bw.makeStyles = function (config) {
|
|
13105
|
+
var fullConfig = Object.assign({}, DEFAULT_PALETTE_CONFIG, config || {});
|
|
13106
|
+
if (config && !config.tertiary) fullConfig.tertiary = fullConfig.primary;
|
|
13223
13107
|
|
|
13224
13108
|
// Derive primary palette
|
|
13225
13109
|
var palette = derivePalette(fullConfig);
|
|
@@ -13227,136 +13111,211 @@
|
|
|
13227
13111
|
// Resolve layout
|
|
13228
13112
|
var layout = resolveLayout(fullConfig);
|
|
13229
13113
|
|
|
13230
|
-
// Generate primary themed CSS rules
|
|
13231
|
-
var themedRules = generateThemedCSS(
|
|
13114
|
+
// Generate primary themed CSS rules (unscoped)
|
|
13115
|
+
var themedRules = generateThemedCSS('', palette, layout);
|
|
13232
13116
|
var cssStr = bw.css(themedRules);
|
|
13233
13117
|
|
|
13234
13118
|
// Derive alternate palette (luminance-inverted)
|
|
13235
13119
|
var altConfig = deriveAlternateConfig(fullConfig);
|
|
13236
13120
|
var altPalette = derivePalette(altConfig);
|
|
13237
13121
|
|
|
13238
|
-
// Generate alternate CSS
|
|
13239
|
-
|
|
13240
|
-
var
|
|
13122
|
+
// Generate alternate CSS rules WITHOUT .bw_theme_alt prefix (raw rules)
|
|
13123
|
+
// applyStyles() wraps them appropriately based on scope
|
|
13124
|
+
var altRawRules = generateThemedCSS('', altPalette, layout);
|
|
13125
|
+
|
|
13126
|
+
// Add body-level surface overrides for the alternate palette.
|
|
13127
|
+
// When .bw_theme_alt is on <html>, ".bw_theme_alt body" correctly matches.
|
|
13128
|
+
altRawRules['body'] = {
|
|
13129
|
+
'color': altPalette.dark.base,
|
|
13130
|
+
'background-color': altPalette.surface || altPalette.light.base
|
|
13131
|
+
};
|
|
13132
|
+
var altCssStr = bw.css(altRawRules);
|
|
13241
13133
|
|
|
13242
13134
|
// Determine if primary is light-flavored
|
|
13243
13135
|
var lightPrimary = isLightPalette(fullConfig);
|
|
13136
|
+
return {
|
|
13137
|
+
css: cssStr,
|
|
13138
|
+
alternateCss: altCssStr,
|
|
13139
|
+
rules: themedRules,
|
|
13140
|
+
alternateRules: altRawRules,
|
|
13141
|
+
palette: palette,
|
|
13142
|
+
alternatePalette: altPalette,
|
|
13143
|
+
isLightPrimary: lightPrimary
|
|
13144
|
+
};
|
|
13145
|
+
};
|
|
13244
13146
|
|
|
13245
|
-
|
|
13246
|
-
|
|
13247
|
-
|
|
13248
|
-
|
|
13249
|
-
|
|
13250
|
-
|
|
13251
|
-
|
|
13252
|
-
|
|
13253
|
-
|
|
13254
|
-
|
|
13255
|
-
|
|
13256
|
-
|
|
13257
|
-
|
|
13258
|
-
|
|
13259
|
-
|
|
13147
|
+
/**
|
|
13148
|
+
* Inject styles into the DOM with optional scoping.
|
|
13149
|
+
*
|
|
13150
|
+
* Takes a styles object from `makeStyles()` and creates a single `<style>`
|
|
13151
|
+
* element in `<head>`. If a scope selector is provided, all CSS rules are
|
|
13152
|
+
* wrapped under that selector. Alternate CSS is wrapped under `.bw_theme_alt`.
|
|
13153
|
+
*
|
|
13154
|
+
* @param {Object} styles - Result of `bw.makeStyles()`
|
|
13155
|
+
* @param {string} [scope] - Scope selector (e.g. '#my-dashboard', '.preview'). Omit for global.
|
|
13156
|
+
* @returns {Element|null} The `<style>` element, or null in Node.js
|
|
13157
|
+
* @category CSS & Styling
|
|
13158
|
+
* @see bw.makeStyles
|
|
13159
|
+
* @see bw.loadStyles
|
|
13160
|
+
* @see bw.clearStyles
|
|
13161
|
+
* @example
|
|
13162
|
+
* var styles = bw.makeStyles({ primary: '#4f46e5' });
|
|
13163
|
+
* bw.applyStyles(styles); // global
|
|
13164
|
+
* bw.applyStyles(styles, '#my-dashboard'); // scoped
|
|
13165
|
+
*/
|
|
13166
|
+
bw.applyStyles = function (styles, scope) {
|
|
13167
|
+
if (!bw._isBrowser) return null;
|
|
13168
|
+
if (!styles || !styles.rules) {
|
|
13169
|
+
_cw('bw.applyStyles: invalid styles object');
|
|
13170
|
+
return null;
|
|
13260
13171
|
}
|
|
13172
|
+
var styleId = _scopeToStyleId(scope);
|
|
13261
13173
|
|
|
13262
|
-
//
|
|
13263
|
-
|
|
13264
|
-
|
|
13265
|
-
|
|
13266
|
-
color: palette.primary.textOn
|
|
13267
|
-
};
|
|
13268
|
-
bw.u.textTeal = {
|
|
13269
|
-
color: palette.primary.base
|
|
13270
|
-
};
|
|
13271
|
-
bw.u.bgWhite = {
|
|
13272
|
-
background: '#ffffff'
|
|
13273
|
-
};
|
|
13274
|
-
bw.u.textWhite = {
|
|
13275
|
-
color: '#ffffff'
|
|
13276
|
-
};
|
|
13174
|
+
// Scope the primary rules if a scope is provided
|
|
13175
|
+
var primaryRules = styles.rules;
|
|
13176
|
+
if (scope) {
|
|
13177
|
+
primaryRules = scopeRulesUnder(primaryRules, scope);
|
|
13277
13178
|
}
|
|
13278
13179
|
|
|
13279
|
-
//
|
|
13280
|
-
var
|
|
13281
|
-
|
|
13282
|
-
|
|
13283
|
-
|
|
13284
|
-
|
|
13285
|
-
|
|
13286
|
-
|
|
13287
|
-
|
|
13180
|
+
// Wrap alternate rules with .bw_theme_alt
|
|
13181
|
+
var altRules = styles.alternateRules;
|
|
13182
|
+
if (altRules) {
|
|
13183
|
+
if (scope) {
|
|
13184
|
+
// Scoped compound: #scope.bw_theme_alt .bw_card
|
|
13185
|
+
altRules = scopeRulesUnder(altRules, scope + '.bw_theme_alt');
|
|
13186
|
+
} else {
|
|
13187
|
+
// Global: .bw_theme_alt .bw_card
|
|
13188
|
+
altRules = scopeRulesUnder(altRules, '.bw_theme_alt');
|
|
13288
13189
|
}
|
|
13289
|
-
}
|
|
13290
|
-
|
|
13291
|
-
|
|
13292
|
-
|
|
13190
|
+
}
|
|
13191
|
+
|
|
13192
|
+
// Combine primary + alternate into one CSS string
|
|
13193
|
+
var combined = bw.css(primaryRules);
|
|
13194
|
+
if (altRules) {
|
|
13195
|
+
combined += '\n' + bw.css(altRules);
|
|
13196
|
+
}
|
|
13197
|
+
return bw.injectCSS(combined, {
|
|
13198
|
+
id: styleId,
|
|
13199
|
+
append: false
|
|
13200
|
+
});
|
|
13293
13201
|
};
|
|
13294
13202
|
|
|
13295
13203
|
/**
|
|
13296
|
-
*
|
|
13297
|
-
*
|
|
13204
|
+
* Generate and apply styles in one call. Convenience wrapper.
|
|
13205
|
+
*
|
|
13206
|
+
* Equivalent to: `bw.applyStyles(bw.makeStyles(config), scope)`
|
|
13298
13207
|
*
|
|
13299
|
-
* @param {
|
|
13300
|
-
* @
|
|
13208
|
+
* @param {Object} [config] - Style configuration (same as `makeStyles`)
|
|
13209
|
+
* @param {string} [scope] - Scope selector (same as `applyStyles`)
|
|
13210
|
+
* @returns {Element|null} The `<style>` element, or null in Node.js
|
|
13301
13211
|
* @category CSS & Styling
|
|
13302
|
-
* @see bw.
|
|
13303
|
-
* @see bw.
|
|
13212
|
+
* @see bw.makeStyles
|
|
13213
|
+
* @see bw.applyStyles
|
|
13304
13214
|
* @example
|
|
13305
|
-
* bw.
|
|
13306
|
-
* bw.
|
|
13307
|
-
* bw.
|
|
13308
|
-
*/
|
|
13309
|
-
bw.
|
|
13310
|
-
|
|
13311
|
-
|
|
13312
|
-
|
|
13313
|
-
|
|
13314
|
-
|
|
13315
|
-
|
|
13316
|
-
|
|
13317
|
-
|
|
13318
|
-
|
|
13215
|
+
* bw.loadStyles(); // defaults, global
|
|
13216
|
+
* bw.loadStyles({ primary: '#4f46e5' }); // custom, global
|
|
13217
|
+
* bw.loadStyles({ primary: '#4f46e5' }, '#my-dashboard'); // custom, scoped
|
|
13218
|
+
*/
|
|
13219
|
+
bw.loadStyles = function (config, scope) {
|
|
13220
|
+
// Also inject structural CSS first (only once)
|
|
13221
|
+
if (bw._isBrowser) {
|
|
13222
|
+
var existing = document.getElementById('bw_structural');
|
|
13223
|
+
if (!existing) {
|
|
13224
|
+
var structuralCSS = bw.css(getStructuralStyles());
|
|
13225
|
+
bw.injectCSS(structuralCSS, {
|
|
13226
|
+
id: 'bw_structural',
|
|
13227
|
+
append: false
|
|
13228
|
+
});
|
|
13229
|
+
}
|
|
13319
13230
|
}
|
|
13320
|
-
bw.
|
|
13321
|
-
return bw._activeThemeMode;
|
|
13231
|
+
return bw.applyStyles(bw.makeStyles(config), scope);
|
|
13322
13232
|
};
|
|
13323
13233
|
|
|
13324
13234
|
/**
|
|
13325
|
-
*
|
|
13235
|
+
* Inject the CSS reset (box-sizing, html/body font, reduced-motion).
|
|
13236
|
+
* Idempotent — if already injected, returns the existing `<style>` element.
|
|
13326
13237
|
*
|
|
13238
|
+
* @returns {Element|null} The `<style>` element, or null in Node.js
|
|
13239
|
+
* @category CSS & Styling
|
|
13240
|
+
* @see bw.loadStyles
|
|
13241
|
+
* @see bw.clearStyles
|
|
13242
|
+
* @example
|
|
13243
|
+
* bw.loadReset(); // inject once, safe to call multiple times
|
|
13244
|
+
*/
|
|
13245
|
+
bw.loadReset = function () {
|
|
13246
|
+
if (!bw._isBrowser) return null;
|
|
13247
|
+
var existing = document.getElementById('bw_style_reset');
|
|
13248
|
+
if (existing) return existing;
|
|
13249
|
+
return bw.injectCSS(bw.css(getResetStyles()), {
|
|
13250
|
+
id: 'bw_style_reset',
|
|
13251
|
+
append: false
|
|
13252
|
+
});
|
|
13253
|
+
};
|
|
13254
|
+
|
|
13255
|
+
/**
|
|
13256
|
+
* Toggle between primary and alternate palettes.
|
|
13257
|
+
*
|
|
13258
|
+
* Adds/removes the `bw_theme_alt` class on the scoping element.
|
|
13259
|
+
* Without a scope, toggles on `<html>` (global).
|
|
13260
|
+
* With a scope, toggles on the first matching element.
|
|
13261
|
+
*
|
|
13262
|
+
* @param {string} [scope] - Scope selector (e.g. '#my-dashboard'). Omit for global.
|
|
13327
13263
|
* @returns {string} Active mode after toggle: 'primary' or 'alternate'
|
|
13328
13264
|
* @category CSS & Styling
|
|
13329
|
-
* @see bw.
|
|
13330
|
-
* @see bw.
|
|
13265
|
+
* @see bw.applyStyles
|
|
13266
|
+
* @see bw.clearStyles
|
|
13331
13267
|
* @example
|
|
13332
|
-
* bw.
|
|
13268
|
+
* bw.toggleStyles(); // global toggle on <html>
|
|
13269
|
+
* bw.toggleStyles('#my-dashboard'); // scoped toggle
|
|
13333
13270
|
*/
|
|
13334
|
-
bw.
|
|
13335
|
-
|
|
13336
|
-
|
|
13271
|
+
bw.toggleStyles = function (scope) {
|
|
13272
|
+
if (!bw._isBrowser) return 'primary';
|
|
13273
|
+
var target;
|
|
13274
|
+
if (scope) {
|
|
13275
|
+
var els = bw.$(scope);
|
|
13276
|
+
target = els[0];
|
|
13277
|
+
} else {
|
|
13278
|
+
target = document.documentElement;
|
|
13279
|
+
}
|
|
13280
|
+
if (!target) return 'primary';
|
|
13281
|
+
var hasAlt = target.classList.contains('bw_theme_alt');
|
|
13282
|
+
if (hasAlt) {
|
|
13283
|
+
target.classList.remove('bw_theme_alt');
|
|
13284
|
+
return 'primary';
|
|
13285
|
+
} else {
|
|
13286
|
+
target.classList.add('bw_theme_alt');
|
|
13287
|
+
return 'alternate';
|
|
13288
|
+
}
|
|
13337
13289
|
};
|
|
13338
13290
|
|
|
13339
13291
|
/**
|
|
13340
|
-
* Remove
|
|
13341
|
-
* Use this before generating a new theme with a different name to prevent
|
|
13342
|
-
* stale CSS accumulation.
|
|
13292
|
+
* Remove injected styles for a given scope.
|
|
13343
13293
|
*
|
|
13294
|
+
* Finds the `<style>` element by id and removes it. Also removes
|
|
13295
|
+
* the `bw_theme_alt` class from the relevant element.
|
|
13296
|
+
*
|
|
13297
|
+
* @param {string} [scope] - Scope selector. Omit to remove global styles.
|
|
13344
13298
|
* @category CSS & Styling
|
|
13345
|
-
* @see bw.
|
|
13299
|
+
* @see bw.applyStyles
|
|
13300
|
+
* @see bw.loadStyles
|
|
13346
13301
|
* @example
|
|
13347
|
-
* bw.
|
|
13348
|
-
* bw.
|
|
13349
|
-
|
|
13350
|
-
|
|
13351
|
-
|
|
13352
|
-
|
|
13353
|
-
|
|
13354
|
-
|
|
13355
|
-
|
|
13356
|
-
|
|
13302
|
+
* bw.clearStyles(); // remove global styles
|
|
13303
|
+
* bw.clearStyles('#my-dashboard'); // remove scoped styles
|
|
13304
|
+
* bw.clearStyles('reset'); // remove the CSS reset
|
|
13305
|
+
*/
|
|
13306
|
+
bw.clearStyles = function (scope) {
|
|
13307
|
+
if (!bw._isBrowser) return;
|
|
13308
|
+
var styleId = _scopeToStyleId(scope);
|
|
13309
|
+
var el = document.getElementById(styleId);
|
|
13310
|
+
if (el) el.remove();
|
|
13311
|
+
|
|
13312
|
+
// Also remove bw_theme_alt from the relevant element
|
|
13313
|
+
if (scope && scope !== 'reset' && scope !== 'global') {
|
|
13314
|
+
var targets = bw.$(scope);
|
|
13315
|
+
if (targets[0]) targets[0].classList.remove('bw_theme_alt');
|
|
13316
|
+
} else if (!scope || scope === 'global') {
|
|
13317
|
+
document.documentElement.classList.remove('bw_theme_alt');
|
|
13357
13318
|
}
|
|
13358
|
-
bw._activeTheme = null;
|
|
13359
|
-
bw._activeThemeMode = 'primary';
|
|
13360
13319
|
};
|
|
13361
13320
|
|
|
13362
13321
|
// Expose color utility functions on bw namespace
|
|
@@ -13578,10 +13537,15 @@
|
|
|
13578
13537
|
* @param {Object} config - Table configuration
|
|
13579
13538
|
* @param {Array<Object>} config.data - Array of row objects to display
|
|
13580
13539
|
* @param {Array<Object>} [config.columns] - Column definitions with key, label, render
|
|
13581
|
-
* @param {string} [config.className='
|
|
13540
|
+
* @param {string} [config.className=''] - Additional CSS classes for table element
|
|
13582
13541
|
* @param {boolean} [config.sortable=true] - Enable click-to-sort headers
|
|
13583
13542
|
* @param {Function} [config.onSort] - Sort callback (column, direction)
|
|
13584
|
-
* @
|
|
13543
|
+
* @param {boolean} [config.selectable=false] - Enable row selection on click
|
|
13544
|
+
* @param {Function} [config.onRowClick] - Row click callback (row, index, event)
|
|
13545
|
+
* @param {number} [config.pageSize] - Rows per page (enables pagination when set)
|
|
13546
|
+
* @param {number} [config.currentPage=1] - Current page number (1-based)
|
|
13547
|
+
* @param {Function} [config.onPageChange] - Page change callback (newPage)
|
|
13548
|
+
* @returns {Object} TACO object for table (with optional pagination controls)
|
|
13585
13549
|
* @category Component Builders
|
|
13586
13550
|
* @see bw.makeDataTable
|
|
13587
13551
|
* @example
|
|
@@ -13593,7 +13557,12 @@
|
|
|
13593
13557
|
* columns: [
|
|
13594
13558
|
* { key: 'name', label: 'Name' },
|
|
13595
13559
|
* { key: 'age', label: 'Age' }
|
|
13596
|
-
* ]
|
|
13560
|
+
* ],
|
|
13561
|
+
* selectable: true,
|
|
13562
|
+
* onRowClick: function(row, i) { console.log('clicked', row.name); },
|
|
13563
|
+
* pageSize: 10,
|
|
13564
|
+
* currentPage: 1,
|
|
13565
|
+
* onPageChange: function(page) { console.log('page', page); }
|
|
13597
13566
|
* });
|
|
13598
13567
|
*/
|
|
13599
13568
|
bw.makeTable = function (config) {
|
|
@@ -13611,12 +13580,20 @@
|
|
|
13611
13580
|
onSort = config.onSort,
|
|
13612
13581
|
sortColumn = config.sortColumn,
|
|
13613
13582
|
_config$sortDirection = config.sortDirection,
|
|
13614
|
-
sortDirection = _config$sortDirection === void 0 ? 'asc' : _config$sortDirection
|
|
13615
|
-
|
|
13616
|
-
|
|
13583
|
+
sortDirection = _config$sortDirection === void 0 ? 'asc' : _config$sortDirection,
|
|
13584
|
+
_config$selectable = config.selectable,
|
|
13585
|
+
selectable = _config$selectable === void 0 ? false : _config$selectable,
|
|
13586
|
+
onRowClick = config.onRowClick,
|
|
13587
|
+
pageSize = config.pageSize,
|
|
13588
|
+
_config$currentPage = config.currentPage,
|
|
13589
|
+
currentPage = _config$currentPage === void 0 ? 1 : _config$currentPage,
|
|
13590
|
+
onPageChange = config.onPageChange;
|
|
13591
|
+
|
|
13592
|
+
// Build class list: always include bw_table, add striped/hover/selectable, append user className
|
|
13617
13593
|
var cls = 'bw_table';
|
|
13618
13594
|
if (striped) cls += ' bw_table_striped';
|
|
13619
|
-
if (hover) cls += ' bw_table_hover';
|
|
13595
|
+
if (hover || selectable) cls += ' bw_table_hover';
|
|
13596
|
+
if (selectable) cls += ' bw_table_selectable';
|
|
13620
13597
|
if (className) cls += ' ' + className;
|
|
13621
13598
|
cls = cls.trim();
|
|
13622
13599
|
|
|
@@ -13655,6 +13632,15 @@
|
|
|
13655
13632
|
});
|
|
13656
13633
|
}
|
|
13657
13634
|
|
|
13635
|
+
// Pagination
|
|
13636
|
+
var totalRows = sortedData.length;
|
|
13637
|
+
var totalPages = pageSize ? Math.max(1, Math.ceil(totalRows / pageSize)) : 1;
|
|
13638
|
+
var page = Math.max(1, Math.min(currentPage, totalPages));
|
|
13639
|
+
if (pageSize) {
|
|
13640
|
+
var start = (page - 1) * pageSize;
|
|
13641
|
+
sortedData = sortedData.slice(start, start + pageSize);
|
|
13642
|
+
}
|
|
13643
|
+
|
|
13658
13644
|
// Create sort handler
|
|
13659
13645
|
var handleSort = function handleSort(column) {
|
|
13660
13646
|
if (!sortable) return;
|
|
@@ -13700,12 +13686,28 @@
|
|
|
13700
13686
|
}
|
|
13701
13687
|
};
|
|
13702
13688
|
|
|
13703
|
-
// Build table body
|
|
13689
|
+
// Build table body with selectable/onRowClick support
|
|
13704
13690
|
var tbody = {
|
|
13705
13691
|
t: 'tbody',
|
|
13706
|
-
c: sortedData.map(function (row) {
|
|
13692
|
+
c: sortedData.map(function (row, idx) {
|
|
13693
|
+
var globalIdx = pageSize ? (page - 1) * pageSize + idx : idx;
|
|
13694
|
+
var rowAttrs = {};
|
|
13695
|
+
if (selectable || onRowClick) {
|
|
13696
|
+
rowAttrs.style = 'cursor:pointer;';
|
|
13697
|
+
rowAttrs.onclick = function (e) {
|
|
13698
|
+
if (selectable) {
|
|
13699
|
+
// Toggle selected class on this row
|
|
13700
|
+
var tr = e.currentTarget;
|
|
13701
|
+
tr.classList.toggle('bw_table_row_selected');
|
|
13702
|
+
}
|
|
13703
|
+
if (onRowClick) {
|
|
13704
|
+
onRowClick(row, globalIdx, e);
|
|
13705
|
+
}
|
|
13706
|
+
};
|
|
13707
|
+
}
|
|
13707
13708
|
return {
|
|
13708
13709
|
t: 'tr',
|
|
13710
|
+
a: rowAttrs,
|
|
13709
13711
|
c: cols.map(function (col) {
|
|
13710
13712
|
return {
|
|
13711
13713
|
t: 'td',
|
|
@@ -13715,13 +13717,65 @@
|
|
|
13715
13717
|
};
|
|
13716
13718
|
})
|
|
13717
13719
|
};
|
|
13718
|
-
|
|
13720
|
+
var table = {
|
|
13719
13721
|
t: 'table',
|
|
13720
13722
|
a: {
|
|
13721
13723
|
"class": cls
|
|
13722
13724
|
},
|
|
13723
13725
|
c: [thead, tbody]
|
|
13724
13726
|
};
|
|
13727
|
+
|
|
13728
|
+
// If no pagination, return table directly
|
|
13729
|
+
if (!pageSize) return table;
|
|
13730
|
+
|
|
13731
|
+
// Build pagination controls
|
|
13732
|
+
var pageButtons = [];
|
|
13733
|
+
// Previous button
|
|
13734
|
+
pageButtons.push({
|
|
13735
|
+
t: 'button',
|
|
13736
|
+
a: {
|
|
13737
|
+
"class": 'bw_btn bw_btn_sm',
|
|
13738
|
+
disabled: page <= 1 ? 'disabled' : undefined,
|
|
13739
|
+
onclick: page > 1 && onPageChange ? function () {
|
|
13740
|
+
onPageChange(page - 1);
|
|
13741
|
+
} : undefined
|
|
13742
|
+
},
|
|
13743
|
+
c: 'Prev'
|
|
13744
|
+
});
|
|
13745
|
+
// Page info
|
|
13746
|
+
pageButtons.push({
|
|
13747
|
+
t: 'span',
|
|
13748
|
+
a: {
|
|
13749
|
+
style: 'margin:0 0.5rem;font-size:0.875rem;'
|
|
13750
|
+
},
|
|
13751
|
+
c: 'Page ' + page + ' of ' + totalPages
|
|
13752
|
+
});
|
|
13753
|
+
// Next button
|
|
13754
|
+
pageButtons.push({
|
|
13755
|
+
t: 'button',
|
|
13756
|
+
a: {
|
|
13757
|
+
"class": 'bw_btn bw_btn_sm',
|
|
13758
|
+
disabled: page >= totalPages ? 'disabled' : undefined,
|
|
13759
|
+
onclick: page < totalPages && onPageChange ? function () {
|
|
13760
|
+
onPageChange(page + 1);
|
|
13761
|
+
} : undefined
|
|
13762
|
+
},
|
|
13763
|
+
c: 'Next'
|
|
13764
|
+
});
|
|
13765
|
+
return {
|
|
13766
|
+
t: 'div',
|
|
13767
|
+
a: {
|
|
13768
|
+
"class": 'bw_table_paginated'
|
|
13769
|
+
},
|
|
13770
|
+
c: [table, {
|
|
13771
|
+
t: 'div',
|
|
13772
|
+
a: {
|
|
13773
|
+
"class": 'bw_table_pagination',
|
|
13774
|
+
style: 'display:flex;align-items:center;justify-content:flex-end;padding:0.5rem 0;gap:0.25rem;'
|
|
13775
|
+
},
|
|
13776
|
+
c: pageButtons
|
|
13777
|
+
}]
|
|
13778
|
+
};
|
|
13725
13779
|
};
|
|
13726
13780
|
|
|
13727
13781
|
/**
|