bitwrench 2.0.10 → 2.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- /*! bitwrench v2.0.10 | BSD-2-Clause | http://deftio.com/bitwrench */
1
+ /*! bitwrench v2.0.11 | 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) :
@@ -203,14 +203,14 @@
203
203
  */
204
204
 
205
205
  var VERSION_INFO = {
206
- version: '2.0.10',
206
+ version: '2.0.11',
207
207
  name: 'bitwrench',
208
208
  description: 'A library for javascript UI functions.',
209
209
  license: 'BSD-2-Clause',
210
- homepage: 'http://deftio.com/bitwrench',
210
+ homepage: 'https://deftio.github.com/bitwrench/pages',
211
211
  repository: 'git+https://github.com/deftio/bitwrench.git',
212
212
  author: 'manu a. chatterjee <deftio@deftio.com> (https://deftio.com/)',
213
- buildDate: '2026-03-07T03:14:16.606Z'
213
+ buildDate: '2026-03-07T11:05:08.522Z'
214
214
  };
215
215
 
216
216
  /**
@@ -955,7 +955,7 @@
955
955
  'background-color': palette.light.light
956
956
  };
957
957
  rules[scopeSelector(scope, '.bw-table-striped > tbody > tr:nth-of-type(odd) > *')] = {
958
- 'background-color': 'rgba(0, 0, 0, 0.025)'
958
+ 'background-color': 'rgba(0, 0, 0, 0.05)'
959
959
  };
960
960
  rules[scopeSelector(scope, '.bw-table-hover > tbody > tr:hover > *')] = {
961
961
  'background-color': palette.primary.focus
@@ -1142,6 +1142,114 @@
1142
1142
  };
1143
1143
  return rules;
1144
1144
  }
1145
+ function generateAccordionThemed(scope, palette) {
1146
+ var rules = {};
1147
+ rules[scopeSelector(scope, '.bw-accordion-item')] = {
1148
+ 'background-color': '#fff',
1149
+ 'border-color': palette.light.border
1150
+ };
1151
+ rules[scopeSelector(scope, '.bw-accordion-button')] = {
1152
+ 'color': palette.dark.base
1153
+ };
1154
+ rules[scopeSelector(scope, '.bw-accordion-button:hover')] = {
1155
+ 'background-color': palette.light.light
1156
+ };
1157
+ rules[scopeSelector(scope, '.bw-accordion-body')] = {
1158
+ 'border-top': '1px solid ' + palette.light.border
1159
+ };
1160
+ return rules;
1161
+ }
1162
+ function generateModalThemed(scope, palette) {
1163
+ var rules = {};
1164
+ rules[scopeSelector(scope, '.bw-modal-content')] = {
1165
+ 'background-color': '#fff',
1166
+ 'border-color': palette.light.border,
1167
+ 'box-shadow': '0 0.5rem 1rem rgba(0,0,0,0.15)'
1168
+ };
1169
+ rules[scopeSelector(scope, '.bw-modal-header')] = {
1170
+ 'border-bottom-color': palette.light.border
1171
+ };
1172
+ rules[scopeSelector(scope, '.bw-modal-footer')] = {
1173
+ 'border-top-color': palette.light.border
1174
+ };
1175
+ rules[scopeSelector(scope, '.bw-modal-title')] = {
1176
+ 'color': palette.dark.base
1177
+ };
1178
+ return rules;
1179
+ }
1180
+ function generateToastThemed(scope, palette) {
1181
+ var rules = {};
1182
+ rules[scopeSelector(scope, '.bw-toast')] = {
1183
+ 'background-color': '#fff',
1184
+ 'border-color': 'rgba(0,0,0,0.1)',
1185
+ 'box-shadow': '0 0.5rem 1rem rgba(0,0,0,0.15)'
1186
+ };
1187
+ rules[scopeSelector(scope, '.bw-toast-header')] = {
1188
+ 'border-bottom-color': 'rgba(0,0,0,0.05)'
1189
+ };
1190
+ var variants = ['primary', 'secondary', 'success', 'danger', 'warning', 'info'];
1191
+ variants.forEach(function (v) {
1192
+ rules[scopeSelector(scope, '.bw-toast-' + v)] = {
1193
+ 'border-left': '4px solid ' + palette[v].base
1194
+ };
1195
+ });
1196
+ return rules;
1197
+ }
1198
+ function generateDropdownThemed(scope, palette) {
1199
+ var rules = {};
1200
+ rules[scopeSelector(scope, '.bw-dropdown-menu')] = {
1201
+ 'background-color': '#fff',
1202
+ 'border-color': palette.light.border,
1203
+ 'box-shadow': '0 0.5rem 1rem rgba(0,0,0,0.15)'
1204
+ };
1205
+ rules[scopeSelector(scope, '.bw-dropdown-item')] = {
1206
+ 'color': palette.dark.base
1207
+ };
1208
+ rules[scopeSelector(scope, '.bw-dropdown-item:hover')] = {
1209
+ 'color': palette.dark.hover,
1210
+ 'background-color': palette.light.light
1211
+ };
1212
+ rules[scopeSelector(scope, '.bw-dropdown-item.disabled')] = {
1213
+ 'color': palette.secondary.base
1214
+ };
1215
+ rules[scopeSelector(scope, '.bw-dropdown-divider')] = {
1216
+ 'border-top-color': palette.light.border
1217
+ };
1218
+ return rules;
1219
+ }
1220
+ function generateSwitchThemed(scope, palette) {
1221
+ var rules = {};
1222
+ rules[scopeSelector(scope, '.bw-form-switch .bw-switch-input')] = {
1223
+ 'background-color': palette.secondary.base,
1224
+ 'border-color': palette.secondary.base
1225
+ };
1226
+ rules[scopeSelector(scope, '.bw-form-switch .bw-switch-input:checked')] = {
1227
+ 'background-color': palette.primary.base,
1228
+ 'border-color': palette.primary.base
1229
+ };
1230
+ rules[scopeSelector(scope, '.bw-form-switch .bw-switch-input:focus')] = {
1231
+ 'box-shadow': '0 0 0 0.25rem ' + palette.primary.focus
1232
+ };
1233
+ return rules;
1234
+ }
1235
+ function generateSkeletonThemed(scope, palette) {
1236
+ var rules = {};
1237
+ rules[scopeSelector(scope, '.bw-skeleton')] = {
1238
+ 'background-color': palette.light.border
1239
+ };
1240
+ return rules;
1241
+ }
1242
+ function generateAvatarThemed(scope, palette) {
1243
+ var rules = {};
1244
+ var variants = ['primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark'];
1245
+ variants.forEach(function (v) {
1246
+ rules[scopeSelector(scope, '.bw-avatar-' + v)] = {
1247
+ 'background-color': palette[v].base,
1248
+ 'color': palette[v].textOn
1249
+ };
1250
+ });
1251
+ return rules;
1252
+ }
1145
1253
 
1146
1254
  /**
1147
1255
  * Generate all themed CSS rules from a palette and layout.
@@ -1153,7 +1261,7 @@
1153
1261
  * @returns {Object} CSS rules object
1154
1262
  */
1155
1263
  function generateThemedCSS(scopeName, palette, layout) {
1156
- return Object.assign({}, generateResetThemed(scopeName, palette), generateTypographyThemed(scopeName, palette), generateButtons(scopeName, palette, layout), generateAlerts(scopeName, palette, layout), generateBadges(scopeName, palette), 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), generateHero(scopeName, palette), generateBreadcrumbThemed(scopeName, palette), generateSpinnerThemed(scopeName, palette), generateCloseButtonThemed(scopeName, palette), generateSectionsThemed(scopeName, palette), generateUtilityColors(scopeName, palette));
1264
+ return Object.assign({}, generateResetThemed(scopeName, palette), generateTypographyThemed(scopeName, palette), generateButtons(scopeName, palette, layout), generateAlerts(scopeName, palette, layout), generateBadges(scopeName, palette), 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), generateHero(scopeName, palette), generateBreadcrumbThemed(scopeName, palette), generateSpinnerThemed(scopeName, palette), generateCloseButtonThemed(scopeName, palette), generateSectionsThemed(scopeName, palette), generateAccordionThemed(scopeName, palette), generateModalThemed(scopeName, palette), generateToastThemed(scopeName, palette), generateDropdownThemed(scopeName, palette), generateSwitchThemed(scopeName, palette), generateSkeletonThemed(scopeName, palette), generateAvatarThemed(scopeName, palette), generateUtilityColors(scopeName, palette));
1157
1265
  }
1158
1266
 
1159
1267
  // =========================================================================
@@ -1798,7 +1906,7 @@
1798
1906
  'justify-content': 'space-between',
1799
1907
  'padding': '0.5rem 1.5rem'
1800
1908
  };
1801
- rules['.bw-navbar > .container'] = {
1909
+ rules['.bw-navbar > .bw-container, .bw-navbar > .container'] = {
1802
1910
  'display': 'flex',
1803
1911
  'flex-wrap': 'wrap',
1804
1912
  'align-items': 'center',
@@ -1900,10 +2008,10 @@
1900
2008
  // Badges (structural)
1901
2009
  rules['.bw-badge'] = {
1902
2010
  'display': 'inline-block',
1903
- 'padding': '.35em .65em',
1904
- 'font-size': '.75em',
1905
- 'font-weight': '700',
1906
- 'line-height': '1',
2011
+ 'padding': '.4em .75em',
2012
+ 'font-size': '.875em',
2013
+ 'font-weight': '600',
2014
+ 'line-height': '1.3',
1907
2015
  'text-align': 'center',
1908
2016
  'white-space': 'nowrap',
1909
2017
  'vertical-align': 'baseline',
@@ -1912,6 +2020,14 @@
1912
2020
  rules['.bw-badge:empty'] = {
1913
2021
  'display': 'none'
1914
2022
  };
2023
+ rules['.bw-badge-sm'] = {
2024
+ 'font-size': '.75em',
2025
+ 'padding': '.25em .5em'
2026
+ };
2027
+ rules['.bw-badge-lg'] = {
2028
+ 'font-size': '1em',
2029
+ 'padding': '.5em .9em'
2030
+ };
1915
2031
  rules['.bw-badge-pill'] = {
1916
2032
  'border-radius': '50rem'
1917
2033
  };
@@ -2108,7 +2224,11 @@
2108
2224
  };
2109
2225
  rules['.bw-hero-title'] = {
2110
2226
  'font-weight': '300',
2111
- 'letter-spacing': '-0.05rem'
2227
+ 'letter-spacing': '-0.05rem',
2228
+ 'color': 'inherit'
2229
+ };
2230
+ rules['.bw-hero-subtitle'] = {
2231
+ 'color': 'inherit'
2112
2232
  };
2113
2233
  rules['.bw-hero-actions'] = {
2114
2234
  'display': 'flex',
@@ -2297,312 +2417,742 @@
2297
2417
  rules['.bw-code-demo'] = {
2298
2418
  'margin-bottom': '2rem'
2299
2419
  };
2420
+ rules['.bw-code-pre'] = {
2421
+ 'margin': '0',
2422
+ 'border': 'none',
2423
+ 'border-radius': '6px',
2424
+ 'overflow-x': 'auto'
2425
+ };
2426
+ rules['.bw-code-block'] = {
2427
+ 'display': 'block',
2428
+ 'padding': '1.25rem',
2429
+ 'font-family': '"SF Mono", Monaco, "Cascadia Code", "Roboto Mono", Consolas, "Courier New", monospace',
2430
+ 'font-size': '0.8125rem',
2431
+ 'line-height': '1.6'
2432
+ };
2433
+ rules['.bw-code-copy-btn'] = {
2434
+ 'position': 'absolute',
2435
+ 'top': '0.5rem',
2436
+ 'right': '0.5rem',
2437
+ 'padding': '0.25rem 0.625rem',
2438
+ 'font-size': '0.6875rem',
2439
+ 'border-radius': '4px',
2440
+ 'cursor': 'pointer',
2441
+ 'font-family': 'inherit',
2442
+ 'transition': 'all 0.15s'
2443
+ };
2300
2444
 
2301
- // Spacing utilities (structural)
2302
- var spacingValues = {
2303
- '0': '0',
2304
- '1': '.25rem',
2305
- '2': '.5rem',
2306
- '3': '1rem',
2307
- '4': '1.5rem',
2308
- '5': '3rem'
2445
+ // Button group (structural)
2446
+ rules['.bw-btn-group, .bw-btn-group-vertical'] = {
2447
+ 'position': 'relative',
2448
+ 'display': 'inline-flex',
2449
+ 'vertical-align': 'middle'
2309
2450
  };
2310
- for (var k in spacingValues) {
2311
- var v = spacingValues[k];
2312
- rules['.bw-m-' + k] = {
2313
- 'margin': v + ' !important'
2314
- };
2315
- rules['.bw-mt-' + k] = {
2316
- 'margin-top': v + ' !important'
2317
- };
2318
- rules['.bw-mb-' + k] = {
2319
- 'margin-bottom': v + ' !important'
2320
- };
2321
- rules['.bw-ms-' + k] = {
2322
- 'margin-left': v + ' !important'
2323
- };
2324
- rules['.bw-me-' + k] = {
2325
- 'margin-right': v + ' !important'
2326
- };
2327
- rules['.bw-p-' + k] = {
2328
- 'padding': v + ' !important'
2329
- };
2330
- rules['.bw-pt-' + k + ', .pt-' + k] = {
2331
- 'padding-top': v + ' !important'
2332
- };
2333
- rules['.bw-pb-' + k + ', .pb-' + k] = {
2334
- 'padding-bottom': v + ' !important'
2335
- };
2336
- rules['.bw-ps-' + k + ', .ps-' + k] = {
2337
- 'padding-left': v + ' !important'
2338
- };
2339
- rules['.bw-pe-' + k + ', .pe-' + k] = {
2340
- 'padding-right': v + ' !important'
2341
- };
2342
- }
2343
- rules['.bw-m-auto, .m-auto'] = {
2344
- 'margin': 'auto !important'
2451
+ rules['.bw-btn-group > .bw-btn, .bw-btn-group-vertical > .bw-btn'] = {
2452
+ 'position': 'relative',
2453
+ 'flex': '1 1 auto',
2454
+ 'border-radius': '0',
2455
+ 'margin-left': '-1px'
2345
2456
  };
2346
- rules['.bw-py-3'] = {
2347
- 'padding-top': '1rem !important',
2348
- 'padding-bottom': '1rem !important'
2457
+ rules['.bw-btn-group > .bw-btn:first-child'] = {
2458
+ 'margin-left': '0',
2459
+ 'border-top-left-radius': '6px',
2460
+ 'border-bottom-left-radius': '6px'
2349
2461
  };
2350
- rules['.bw-py-4'] = {
2351
- 'padding-top': '1.5rem !important',
2352
- 'padding-bottom': '1.5rem !important'
2462
+ rules['.bw-btn-group > .bw-btn:last-child'] = {
2463
+ 'border-top-right-radius': '6px',
2464
+ 'border-bottom-right-radius': '6px'
2353
2465
  };
2354
- rules['.bw-py-5'] = {
2355
- 'padding-top': '3rem !important',
2356
- 'padding-bottom': '3rem !important'
2466
+ rules['.bw-btn-group-vertical'] = {
2467
+ 'flex-direction': 'column',
2468
+ 'align-items': 'flex-start',
2469
+ 'justify-content': 'center'
2357
2470
  };
2358
- rules['.bw-py-6'] = {
2359
- 'padding-top': '4rem !important',
2360
- 'padding-bottom': '4rem !important'
2471
+ rules['.bw-btn-group-vertical > .bw-btn'] = {
2472
+ 'width': '100%',
2473
+ 'margin-left': '0',
2474
+ 'margin-top': '-1px'
2475
+ };
2476
+ rules['.bw-btn-group-vertical > .bw-btn:first-child'] = {
2477
+ 'margin-top': '0',
2478
+ 'border-top-left-radius': '6px',
2479
+ 'border-top-right-radius': '6px',
2480
+ 'border-bottom-left-radius': '0',
2481
+ 'border-bottom-right-radius': '0'
2482
+ };
2483
+ rules['.bw-btn-group-vertical > .bw-btn:last-child'] = {
2484
+ 'border-top-left-radius': '0',
2485
+ 'border-top-right-radius': '0',
2486
+ 'border-bottom-left-radius': '6px',
2487
+ 'border-bottom-right-radius': '6px'
2361
2488
  };
2362
2489
 
2363
- // Display utilities (structural)
2364
- rules['.bw-d-none'] = {
2365
- 'display': 'none'
2490
+ // Accordion (structural)
2491
+ rules['.bw-accordion'] = {
2492
+ 'border-radius': '8px',
2493
+ 'overflow': 'hidden'
2366
2494
  };
2367
- rules['.bw-d-block'] = {
2368
- 'display': 'block'
2495
+ rules['.bw-accordion-item'] = {
2496
+ 'border': '1px solid transparent'
2369
2497
  };
2370
- rules['.bw-d-inline'] = {
2371
- 'display': 'inline'
2498
+ rules['.bw-accordion-item + .bw-accordion-item'] = {
2499
+ 'border-top': '0'
2372
2500
  };
2373
- rules['.bw-d-inline-block'] = {
2374
- 'display': 'inline-block'
2501
+ rules['.bw-accordion-header'] = {
2502
+ 'margin': '0'
2375
2503
  };
2376
- rules['.bw-d-flex'] = {
2377
- 'display': 'flex'
2504
+ rules['.bw-accordion-button'] = {
2505
+ 'position': 'relative',
2506
+ 'display': 'flex',
2507
+ 'align-items': 'center',
2508
+ 'width': '100%',
2509
+ 'padding': '1rem 1.25rem',
2510
+ 'font-size': '1rem',
2511
+ 'font-weight': '500',
2512
+ 'text-align': 'left',
2513
+ 'background-color': 'transparent',
2514
+ 'border': '0',
2515
+ 'overflow-anchor': 'none',
2516
+ 'cursor': 'pointer',
2517
+ 'font-family': 'inherit',
2518
+ 'transition': 'color 0.15s ease-in-out, background-color 0.15s ease-in-out'
2378
2519
  };
2379
- rules['.bw-text-left'] = {
2380
- 'text-align': 'left'
2520
+ rules['.bw-accordion-button::after'] = {
2521
+ 'flex-shrink': '0',
2522
+ 'width': '1.25rem',
2523
+ 'height': '1.25rem',
2524
+ 'margin-left': 'auto',
2525
+ 'content': '""',
2526
+ 'background-repeat': 'no-repeat',
2527
+ 'background-size': '1.25rem',
2528
+ 'transition': 'transform 0.2s ease-in-out'
2381
2529
  };
2382
- rules['.bw-text-right'] = {
2383
- 'text-align': 'right'
2530
+ rules['.bw-accordion-button:not(.bw-collapsed)::after'] = {
2531
+ 'transform': 'rotate(-180deg)'
2384
2532
  };
2385
- rules['.bw-text-center'] = {
2386
- 'text-align': 'center'
2533
+ rules['.bw-accordion-collapse'] = {
2534
+ 'max-height': '0',
2535
+ 'overflow': 'hidden',
2536
+ 'transition': 'max-height 0.3s ease'
2387
2537
  };
2388
-
2389
- // Flexbox utilities (structural)
2390
- var jc = {
2391
- start: 'flex-start',
2392
- end: 'flex-end',
2393
- center: 'center',
2394
- between: 'space-between',
2395
- around: 'space-around'
2538
+ rules['.bw-accordion-collapse.bw-collapse-show'] = {
2539
+ 'max-height': 'none'
2396
2540
  };
2397
- for (var jk in jc) {
2398
- rules['.bw-justify-content-' + jk + ', .justify-content-' + jk] = {
2399
- 'justify-content': jc[jk]
2400
- };
2401
- }
2402
- var ai = {
2403
- start: 'flex-start',
2404
- end: 'flex-end',
2405
- center: 'center'
2541
+ rules['.bw-accordion-body'] = {
2542
+ 'padding': '1rem 1.25rem'
2406
2543
  };
2407
- for (var ak in ai) {
2408
- rules['.bw-align-items-' + ak + ', .align-items-' + ak] = {
2409
- 'align-items': ai[ak]
2410
- };
2411
- }
2412
2544
 
2413
- // Size utilities (structural)
2414
- ['25', '50', '75', '100'].forEach(function (n) {
2415
- rules['.bw-w-' + n + ', .w-' + n] = {
2416
- 'width': n + '% !important'
2417
- };
2418
- rules['.bw-h-' + n + ', .h-' + n] = {
2419
- 'height': n + '% !important'
2420
- };
2421
- });
2422
- rules['.bw-w-auto, .w-auto'] = {
2423
- 'width': 'auto !important'
2545
+ // Modal (structural)
2546
+ rules['.bw-modal'] = {
2547
+ 'display': 'none',
2548
+ 'position': 'fixed',
2549
+ 'top': '0',
2550
+ 'left': '0',
2551
+ 'width': '100%',
2552
+ 'height': '100%',
2553
+ 'z-index': '1050',
2554
+ 'overflow-x': 'hidden',
2555
+ 'overflow-y': 'auto',
2556
+ 'opacity': '0',
2557
+ 'transition': 'opacity 0.15s linear'
2424
2558
  };
2425
- rules['.bw-h-auto, .h-auto'] = {
2426
- 'height': 'auto !important'
2559
+ rules['.bw-modal.bw-modal-show'] = {
2560
+ 'display': 'flex',
2561
+ 'align-items': 'center',
2562
+ 'justify-content': 'center',
2563
+ 'opacity': '1'
2427
2564
  };
2428
- rules['.bw-mw-100, .mw-100'] = {
2429
- 'max-width': '100% !important'
2565
+ rules['.bw-modal-dialog'] = {
2566
+ 'position': 'relative',
2567
+ 'width': '100%',
2568
+ 'max-width': '500px',
2569
+ 'margin': '1.75rem auto',
2570
+ 'pointer-events': 'none',
2571
+ 'transform': 'translateY(-20px)',
2572
+ 'transition': 'transform 0.2s ease-out'
2430
2573
  };
2431
- rules['.bw-mh-100, .mh-100'] = {
2432
- 'max-height': '100% !important'
2574
+ rules['.bw-modal.bw-modal-show .bw-modal-dialog'] = {
2575
+ 'transform': 'translateY(0)'
2433
2576
  };
2434
-
2435
- // Position utilities (structural)
2436
- ['static', 'relative', 'absolute', 'fixed', 'sticky'].forEach(function (p) {
2437
- rules['.bw-position-' + p + ', .position-' + p] = {
2438
- 'position': p + ' !important'
2439
- };
2440
- });
2441
- rules['.bw-translate-middle, .translate-middle'] = {
2442
- 'transform': 'translate(-50%, -50%) !important'
2577
+ rules['.bw-modal-sm'] = {
2578
+ 'max-width': '300px'
2443
2579
  };
2444
-
2445
- // Overflow utilities (structural)
2446
- ['auto', 'hidden', 'visible', 'scroll'].forEach(function (o) {
2447
- rules['.bw-overflow-' + o + ', .overflow-' + o] = {
2448
- 'overflow': o + ' !important'
2449
- };
2450
- });
2451
-
2452
- // Visibility utilities (structural)
2453
- rules['.bw-visible, .visible'] = {
2454
- 'visibility': 'visible !important'
2580
+ rules['.bw-modal-lg'] = {
2581
+ 'max-width': '800px'
2455
2582
  };
2456
- rules['.bw-invisible, .invisible'] = {
2457
- 'visibility': 'hidden !important'
2583
+ rules['.bw-modal-xl'] = {
2584
+ 'max-width': '1140px'
2458
2585
  };
2459
-
2460
- // User select utilities (structural)
2461
- ['all', 'auto', 'none'].forEach(function (u) {
2462
- rules['.bw-user-select-' + u + ', .user-select-' + u] = {
2463
- 'user-select': u + ' !important'
2464
- };
2465
- });
2466
-
2467
- // Pointer events
2468
- rules['.pe-none'] = {
2469
- 'pointer-events': 'none !important'
2586
+ rules['.bw-modal-content'] = {
2587
+ 'position': 'relative',
2588
+ 'display': 'flex',
2589
+ 'flex-direction': 'column',
2590
+ 'pointer-events': 'auto',
2591
+ 'background-clip': 'padding-box',
2592
+ 'border': '1px solid transparent',
2593
+ 'border-radius': '8px',
2594
+ 'outline': '0'
2470
2595
  };
2471
- rules['.pe-auto'] = {
2472
- 'pointer-events': 'auto !important'
2596
+ rules['.bw-modal-header'] = {
2597
+ 'display': 'flex',
2598
+ 'align-items': 'center',
2599
+ 'justify-content': 'space-between',
2600
+ 'padding': '1rem 1.5rem'
2601
+ };
2602
+ rules['.bw-modal-title'] = {
2603
+ 'margin': '0',
2604
+ 'font-size': '1.25rem',
2605
+ 'font-weight': '600',
2606
+ 'line-height': '1.3'
2607
+ };
2608
+ rules['.bw-modal-body'] = {
2609
+ 'position': 'relative',
2610
+ 'flex': '1 1 auto',
2611
+ 'padding': '1.5rem'
2612
+ };
2613
+ rules['.bw-modal-footer'] = {
2614
+ 'display': 'flex',
2615
+ 'flex-wrap': 'wrap',
2616
+ 'align-items': 'center',
2617
+ 'justify-content': 'flex-end',
2618
+ 'padding': '0.75rem 1.5rem',
2619
+ 'gap': '0.5rem'
2473
2620
  };
2474
2621
 
2475
- // Typography utilities (structural)
2476
- rules['.fw-light'] = {
2477
- 'font-weight': '300 !important'
2622
+ // Toast (structural)
2623
+ rules['.bw-toast-container'] = {
2624
+ 'position': 'fixed',
2625
+ 'z-index': '1080',
2626
+ 'pointer-events': 'none',
2627
+ 'display': 'flex',
2628
+ 'flex-direction': 'column',
2629
+ 'gap': '0.5rem',
2630
+ 'padding': '1rem'
2478
2631
  };
2479
- rules['.fw-lighter'] = {
2480
- 'font-weight': 'lighter !important'
2632
+ rules['.bw-toast'] = {
2633
+ 'pointer-events': 'auto',
2634
+ 'width': '350px',
2635
+ 'max-width': '100%',
2636
+ 'background-clip': 'padding-box',
2637
+ 'border-radius': '8px',
2638
+ 'opacity': '0',
2639
+ 'transform': 'translateY(-10px)',
2640
+ 'transition': 'opacity 0.3s ease, transform 0.3s ease'
2481
2641
  };
2482
- rules['.fw-normal'] = {
2483
- 'font-weight': '400 !important'
2642
+ rules['.bw-toast.bw-toast-show'] = {
2643
+ 'opacity': '1',
2644
+ 'transform': 'translateY(0)'
2484
2645
  };
2485
- rules['.fw-bold'] = {
2486
- 'font-weight': '700 !important'
2646
+ rules['.bw-toast.bw-toast-hiding'] = {
2647
+ 'opacity': '0',
2648
+ 'transform': 'translateY(-10px)'
2487
2649
  };
2488
- rules['.fw-bolder'] = {
2489
- 'font-weight': 'bolder !important'
2650
+ rules['.bw-toast-header'] = {
2651
+ 'display': 'flex',
2652
+ 'align-items': 'center',
2653
+ 'justify-content': 'space-between',
2654
+ 'padding': '0.5rem 0.75rem',
2655
+ 'font-size': '0.875rem'
2490
2656
  };
2491
- rules['.fst-italic'] = {
2492
- 'font-style': 'italic !important'
2657
+ rules['.bw-toast-body'] = {
2658
+ 'padding': '0.75rem',
2659
+ 'font-size': '0.9375rem'
2493
2660
  };
2494
- rules['.fst-normal'] = {
2495
- 'font-style': 'normal !important'
2661
+
2662
+ // Dropdown (structural)
2663
+ rules['.bw-dropdown'] = {
2664
+ 'position': 'relative',
2665
+ 'display': 'inline-block'
2496
2666
  };
2497
- rules['.text-decoration-none'] = {
2498
- 'text-decoration': 'none !important'
2667
+ rules['.bw-dropdown-toggle::after'] = {
2668
+ 'display': 'inline-block',
2669
+ 'margin-left': '0.255em',
2670
+ 'vertical-align': '0.255em',
2671
+ 'content': '""',
2672
+ 'border-top': '0.3em solid',
2673
+ 'border-right': '0.3em solid transparent',
2674
+ 'border-bottom': '0',
2675
+ 'border-left': '0.3em solid transparent'
2676
+ };
2677
+ rules['.bw-dropdown-menu'] = {
2678
+ 'position': 'absolute',
2679
+ 'top': '100%',
2680
+ 'left': '0',
2681
+ 'z-index': '1000',
2682
+ 'display': 'none',
2683
+ 'min-width': '10rem',
2684
+ 'padding': '0.5rem 0',
2685
+ 'margin': '0.125rem 0 0',
2686
+ 'background-clip': 'padding-box',
2687
+ 'border-radius': '6px'
2499
2688
  };
2500
- rules['.text-decoration-underline'] = {
2501
- 'text-decoration': 'underline !important'
2689
+ rules['.bw-dropdown-menu.bw-dropdown-show'] = {
2690
+ 'display': 'block'
2502
2691
  };
2503
- rules['.text-decoration-line-through'] = {
2504
- 'text-decoration': 'line-through !important'
2692
+ rules['.bw-dropdown-menu-end'] = {
2693
+ 'left': 'auto',
2694
+ 'right': '0'
2505
2695
  };
2506
- rules['.text-lowercase'] = {
2507
- 'text-transform': 'lowercase !important'
2696
+ rules['.bw-dropdown-item'] = {
2697
+ 'display': 'block',
2698
+ 'width': '100%',
2699
+ 'padding': '0.375rem 1rem',
2700
+ 'clear': 'both',
2701
+ 'font-weight': '400',
2702
+ 'text-align': 'inherit',
2703
+ 'text-decoration': 'none',
2704
+ 'white-space': 'nowrap',
2705
+ 'background-color': 'transparent',
2706
+ 'border': '0',
2707
+ 'font-size': '0.9375rem',
2708
+ 'transition': 'background-color 0.15s, color 0.15s'
2508
2709
  };
2509
- rules['.text-uppercase'] = {
2510
- 'text-transform': 'uppercase !important'
2710
+ rules['.bw-dropdown-divider'] = {
2711
+ 'height': '0',
2712
+ 'margin': '0.5rem 0',
2713
+ 'overflow': 'hidden',
2714
+ 'opacity': '1'
2511
2715
  };
2512
- rules['.text-capitalize'] = {
2513
- 'text-transform': 'capitalize !important'
2716
+
2717
+ // Switch (structural)
2718
+ rules['.bw-form-switch'] = {
2719
+ 'padding-left': '2.5em'
2514
2720
  };
2515
- rules['.text-wrap'] = {
2516
- 'white-space': 'normal !important'
2721
+ rules['.bw-form-switch .bw-switch-input'] = {
2722
+ 'width': '2em',
2723
+ 'height': '1.125em',
2724
+ 'margin-left': '-2.5em',
2725
+ 'border-radius': '2em',
2726
+ 'appearance': 'none',
2727
+ 'background-position': 'left center',
2728
+ 'background-repeat': 'no-repeat',
2729
+ 'background-size': 'contain',
2730
+ 'transition': 'background-position 0.15s ease-in-out, background-color 0.15s ease-in-out',
2731
+ 'cursor': 'pointer'
2517
2732
  };
2518
- rules['.text-nowrap'] = {
2519
- 'white-space': 'nowrap !important'
2733
+ rules['.bw-form-switch .bw-switch-input:checked'] = {
2734
+ 'background-position': 'right center'
2735
+ };
2736
+ rules['.bw-form-switch .bw-switch-input:disabled'] = {
2737
+ 'opacity': '0.5',
2738
+ 'cursor': 'not-allowed'
2520
2739
  };
2521
2740
 
2522
- // Font-size utilities (structural)
2523
- rules['.fs-1'] = {
2524
- 'font-size': 'calc(1.375rem + 1.5vw) !important'
2741
+ // Skeleton (structural)
2742
+ rules['.bw-skeleton'] = {
2743
+ 'border-radius': '4px',
2744
+ 'animation': 'bw-skeleton-pulse 1.5s ease-in-out infinite'
2525
2745
  };
2526
- rules['.fs-2'] = {
2527
- 'font-size': 'calc(1.325rem + .9vw) !important'
2746
+ rules['.bw-skeleton-text'] = {
2747
+ 'height': '1em',
2748
+ 'margin-bottom': '0.5rem'
2528
2749
  };
2529
- rules['.fs-3'] = {
2530
- 'font-size': 'calc(1.3rem + .6vw) !important'
2750
+ rules['.bw-skeleton-circle'] = {
2751
+ 'border-radius': '50%'
2531
2752
  };
2532
- rules['.fs-4'] = {
2533
- 'font-size': 'calc(1.275rem + .3vw) !important'
2753
+ rules['.bw-skeleton-rect'] = {
2754
+ 'border-radius': '8px'
2534
2755
  };
2535
- rules['.fs-5'] = {
2536
- 'font-size': '1.25rem !important'
2756
+ rules['.bw-skeleton-group'] = {
2757
+ 'display': 'flex',
2758
+ 'flex-direction': 'column'
2537
2759
  };
2538
- rules['.fs-6'] = {
2539
- 'font-size': '1rem !important'
2760
+ rules['@keyframes bw-skeleton-pulse'] = {
2761
+ '0%': {
2762
+ 'opacity': '1'
2763
+ },
2764
+ '50%': {
2765
+ 'opacity': '0.4'
2766
+ },
2767
+ '100%': {
2768
+ 'opacity': '1'
2769
+ }
2540
2770
  };
2541
2771
 
2542
- // List utilities (structural)
2543
- rules['.list-unstyled'] = {
2544
- 'padding-left': '0',
2545
- 'list-style': 'none'
2772
+ // Avatar (structural)
2773
+ rules['.bw-avatar'] = {
2774
+ 'display': 'inline-flex',
2775
+ 'align-items': 'center',
2776
+ 'justify-content': 'center',
2777
+ 'border-radius': '50%',
2778
+ 'overflow': 'hidden',
2779
+ 'font-weight': '600',
2780
+ 'text-transform': 'uppercase',
2781
+ 'vertical-align': 'middle',
2782
+ 'object-fit': 'cover'
2546
2783
  };
2547
- rules['.list-inline'] = {
2548
- 'padding-left': '0',
2549
- 'list-style': 'none'
2784
+ rules['.bw-avatar-sm'] = {
2785
+ 'width': '2rem',
2786
+ 'height': '2rem',
2787
+ 'font-size': '0.75rem'
2550
2788
  };
2551
- rules['.list-inline-item'] = {
2552
- 'display': 'inline-block'
2789
+ rules['.bw-avatar-md'] = {
2790
+ 'width': '3rem',
2791
+ 'height': '3rem',
2792
+ 'font-size': '1rem'
2553
2793
  };
2554
- rules['.list-inline-item:not(:last-child)'] = {
2555
- 'margin-right': '.5rem'
2794
+ rules['.bw-avatar-lg'] = {
2795
+ 'width': '4rem',
2796
+ 'height': '4rem',
2797
+ 'font-size': '1.25rem'
2798
+ };
2799
+ rules['.bw-avatar-xl'] = {
2800
+ 'width': '5rem',
2801
+ 'height': '5rem',
2802
+ 'font-size': '1.5rem'
2556
2803
  };
2557
2804
 
2558
- // Opacity utilities (structural)
2559
- rules['.opacity-0'] = {
2560
- 'opacity': '0 !important'
2805
+ // Bar chart (structural)
2806
+ rules['.bw-bar-chart-container'] = {
2807
+ 'padding': '1rem',
2808
+ 'border': '1px solid transparent',
2809
+ 'border-radius': '8px'
2561
2810
  };
2562
- rules['.opacity-25'] = {
2563
- 'opacity': '.25 !important'
2811
+ rules['.bw-bar-chart'] = {
2812
+ 'display': 'flex',
2813
+ 'align-items': 'flex-end',
2814
+ 'gap': '6px',
2815
+ 'padding': '0 0.5rem'
2564
2816
  };
2565
- rules['.opacity-50'] = {
2566
- 'opacity': '.5 !important'
2817
+ rules['.bw-bar-group'] = {
2818
+ 'flex': '1',
2819
+ 'display': 'flex',
2820
+ 'flex-direction': 'column',
2821
+ 'align-items': 'center',
2822
+ 'height': '100%',
2823
+ 'justify-content': 'flex-end'
2567
2824
  };
2568
- rules['.opacity-75'] = {
2569
- 'opacity': '.75 !important'
2825
+ rules['.bw-bar'] = {
2826
+ 'width': '100%',
2827
+ 'border-radius': '3px 3px 0 0',
2828
+ 'transition': 'height 0.5s ease',
2829
+ 'min-height': '4px'
2570
2830
  };
2571
- rules['.opacity-100'] = {
2572
- 'opacity': '1 !important'
2831
+ rules['.bw-bar:hover'] = {
2832
+ 'opacity': '0.85'
2833
+ };
2834
+ rules['.bw-bar-value'] = {
2835
+ 'font-size': '0.65rem',
2836
+ 'font-weight': '600',
2837
+ 'margin-bottom': '2px',
2838
+ 'text-align': 'center'
2839
+ };
2840
+ rules['.bw-bar-label'] = {
2841
+ 'font-size': '0.7rem',
2842
+ 'margin-top': '4px',
2843
+ 'text-align': 'center'
2844
+ };
2845
+ rules['.bw-bar-chart-title'] = {
2846
+ 'font-size': '1.1rem',
2847
+ 'font-weight': '600',
2848
+ 'margin': '0 0 0.75rem 0'
2573
2849
  };
2574
2850
 
2575
- // Responsive grid
2576
- Object.assign(rules, defaultStyles.responsive);
2577
- return addUnderscoreAliases(rules);
2578
- }
2579
-
2580
- // =========================================================================
2581
- // getAllStyles — backwards compatible
2582
- // =========================================================================
2583
-
2584
- /**
2585
- * Add underscore aliases for all bw- selectors
2586
- * @param {Object} rules - CSS rules object
2587
- * @returns {Object} - Rules with underscore aliases added
2588
- */
2589
- function addUnderscoreAliases(rules) {
2590
- var result = {};
2591
- for (var _i = 0, _Object$entries = Object.entries(rules); _i < _Object$entries.length; _i++) {
2592
- var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
2593
- selector = _Object$entries$_i[0],
2594
- styles = _Object$entries$_i[1];
2595
- result[selector] = styles;
2596
- if (selector.includes('.bw-')) {
2597
- var underscoreSelector = selector.replace(/\.bw-/g, '.bw_');
2598
- result[underscoreSelector] = styles;
2599
- }
2851
+ // Spacing utilities (structural)
2852
+ var spacingValues = {
2853
+ '0': '0',
2854
+ '1': '.25rem',
2855
+ '2': '.5rem',
2856
+ '3': '1rem',
2857
+ '4': '1.5rem',
2858
+ '5': '3rem'
2859
+ };
2860
+ for (var k in spacingValues) {
2861
+ var v = spacingValues[k];
2862
+ rules['.bw-m-' + k] = {
2863
+ 'margin': v + ' !important'
2864
+ };
2865
+ rules['.bw-mt-' + k] = {
2866
+ 'margin-top': v + ' !important'
2867
+ };
2868
+ rules['.bw-mb-' + k] = {
2869
+ 'margin-bottom': v + ' !important'
2870
+ };
2871
+ rules['.bw-ms-' + k] = {
2872
+ 'margin-left': v + ' !important'
2873
+ };
2874
+ rules['.bw-me-' + k] = {
2875
+ 'margin-right': v + ' !important'
2876
+ };
2877
+ rules['.bw-p-' + k] = {
2878
+ 'padding': v + ' !important'
2879
+ };
2880
+ rules['.bw-pt-' + k + ', .pt-' + k] = {
2881
+ 'padding-top': v + ' !important'
2882
+ };
2883
+ rules['.bw-pb-' + k + ', .pb-' + k] = {
2884
+ 'padding-bottom': v + ' !important'
2885
+ };
2886
+ rules['.bw-ps-' + k + ', .ps-' + k] = {
2887
+ 'padding-left': v + ' !important'
2888
+ };
2889
+ rules['.bw-pe-' + k + ', .pe-' + k] = {
2890
+ 'padding-right': v + ' !important'
2891
+ };
2600
2892
  }
2601
- return result;
2602
- }
2603
-
2604
- // =========================================================================
2605
- // Theme tokens (backwards compatible)
2893
+ rules['.bw-m-auto, .m-auto'] = {
2894
+ 'margin': 'auto !important'
2895
+ };
2896
+ rules['.bw-py-3'] = {
2897
+ 'padding-top': '1rem !important',
2898
+ 'padding-bottom': '1rem !important'
2899
+ };
2900
+ rules['.bw-py-4'] = {
2901
+ 'padding-top': '1.5rem !important',
2902
+ 'padding-bottom': '1.5rem !important'
2903
+ };
2904
+ rules['.bw-py-5'] = {
2905
+ 'padding-top': '3rem !important',
2906
+ 'padding-bottom': '3rem !important'
2907
+ };
2908
+ rules['.bw-py-6'] = {
2909
+ 'padding-top': '4rem !important',
2910
+ 'padding-bottom': '4rem !important'
2911
+ };
2912
+
2913
+ // Display utilities (structural)
2914
+ rules['.bw-d-none'] = {
2915
+ 'display': 'none'
2916
+ };
2917
+ rules['.bw-d-block'] = {
2918
+ 'display': 'block'
2919
+ };
2920
+ rules['.bw-d-inline'] = {
2921
+ 'display': 'inline'
2922
+ };
2923
+ rules['.bw-d-inline-block'] = {
2924
+ 'display': 'inline-block'
2925
+ };
2926
+ rules['.bw-d-flex'] = {
2927
+ 'display': 'flex'
2928
+ };
2929
+ rules['.bw-text-left'] = {
2930
+ 'text-align': 'left'
2931
+ };
2932
+ rules['.bw-text-right'] = {
2933
+ 'text-align': 'right'
2934
+ };
2935
+ rules['.bw-text-center'] = {
2936
+ 'text-align': 'center'
2937
+ };
2938
+
2939
+ // Flexbox utilities (structural)
2940
+ var jc = {
2941
+ start: 'flex-start',
2942
+ end: 'flex-end',
2943
+ center: 'center',
2944
+ between: 'space-between',
2945
+ around: 'space-around'
2946
+ };
2947
+ for (var jk in jc) {
2948
+ rules['.bw-justify-content-' + jk + ', .justify-content-' + jk] = {
2949
+ 'justify-content': jc[jk]
2950
+ };
2951
+ }
2952
+ var ai = {
2953
+ start: 'flex-start',
2954
+ end: 'flex-end',
2955
+ center: 'center'
2956
+ };
2957
+ for (var ak in ai) {
2958
+ rules['.bw-align-items-' + ak + ', .align-items-' + ak] = {
2959
+ 'align-items': ai[ak]
2960
+ };
2961
+ }
2962
+
2963
+ // Size utilities (structural)
2964
+ ['25', '50', '75', '100'].forEach(function (n) {
2965
+ rules['.bw-w-' + n + ', .w-' + n] = {
2966
+ 'width': n + '% !important'
2967
+ };
2968
+ rules['.bw-h-' + n + ', .h-' + n] = {
2969
+ 'height': n + '% !important'
2970
+ };
2971
+ });
2972
+ rules['.bw-w-auto, .w-auto'] = {
2973
+ 'width': 'auto !important'
2974
+ };
2975
+ rules['.bw-h-auto, .h-auto'] = {
2976
+ 'height': 'auto !important'
2977
+ };
2978
+ rules['.bw-mw-100, .mw-100'] = {
2979
+ 'max-width': '100% !important'
2980
+ };
2981
+ rules['.bw-mh-100, .mh-100'] = {
2982
+ 'max-height': '100% !important'
2983
+ };
2984
+
2985
+ // Position utilities (structural)
2986
+ ['static', 'relative', 'absolute', 'fixed', 'sticky'].forEach(function (p) {
2987
+ rules['.bw-position-' + p + ', .position-' + p] = {
2988
+ 'position': p + ' !important'
2989
+ };
2990
+ });
2991
+ rules['.bw-translate-middle, .translate-middle'] = {
2992
+ 'transform': 'translate(-50%, -50%) !important'
2993
+ };
2994
+
2995
+ // Overflow utilities (structural)
2996
+ ['auto', 'hidden', 'visible', 'scroll'].forEach(function (o) {
2997
+ rules['.bw-overflow-' + o + ', .overflow-' + o] = {
2998
+ 'overflow': o + ' !important'
2999
+ };
3000
+ });
3001
+
3002
+ // Visibility utilities (structural)
3003
+ rules['.bw-visible, .visible'] = {
3004
+ 'visibility': 'visible !important'
3005
+ };
3006
+ rules['.bw-invisible, .invisible'] = {
3007
+ 'visibility': 'hidden !important'
3008
+ };
3009
+
3010
+ // User select utilities (structural)
3011
+ ['all', 'auto', 'none'].forEach(function (u) {
3012
+ rules['.bw-user-select-' + u + ', .user-select-' + u] = {
3013
+ 'user-select': u + ' !important'
3014
+ };
3015
+ });
3016
+
3017
+ // Pointer events
3018
+ rules['.pe-none'] = {
3019
+ 'pointer-events': 'none !important'
3020
+ };
3021
+ rules['.pe-auto'] = {
3022
+ 'pointer-events': 'auto !important'
3023
+ };
3024
+
3025
+ // Typography utilities (structural)
3026
+ rules['.fw-light'] = {
3027
+ 'font-weight': '300 !important'
3028
+ };
3029
+ rules['.fw-lighter'] = {
3030
+ 'font-weight': 'lighter !important'
3031
+ };
3032
+ rules['.fw-normal'] = {
3033
+ 'font-weight': '400 !important'
3034
+ };
3035
+ rules['.fw-bold'] = {
3036
+ 'font-weight': '700 !important'
3037
+ };
3038
+ rules['.fw-bolder'] = {
3039
+ 'font-weight': 'bolder !important'
3040
+ };
3041
+ rules['.fst-italic'] = {
3042
+ 'font-style': 'italic !important'
3043
+ };
3044
+ rules['.fst-normal'] = {
3045
+ 'font-style': 'normal !important'
3046
+ };
3047
+ rules['.text-decoration-none'] = {
3048
+ 'text-decoration': 'none !important'
3049
+ };
3050
+ rules['.text-decoration-underline'] = {
3051
+ 'text-decoration': 'underline !important'
3052
+ };
3053
+ rules['.text-decoration-line-through'] = {
3054
+ 'text-decoration': 'line-through !important'
3055
+ };
3056
+ rules['.text-lowercase'] = {
3057
+ 'text-transform': 'lowercase !important'
3058
+ };
3059
+ rules['.text-uppercase'] = {
3060
+ 'text-transform': 'uppercase !important'
3061
+ };
3062
+ rules['.text-capitalize'] = {
3063
+ 'text-transform': 'capitalize !important'
3064
+ };
3065
+ rules['.text-wrap'] = {
3066
+ 'white-space': 'normal !important'
3067
+ };
3068
+ rules['.text-nowrap'] = {
3069
+ 'white-space': 'nowrap !important'
3070
+ };
3071
+
3072
+ // Font-size utilities (structural)
3073
+ rules['.fs-1'] = {
3074
+ 'font-size': 'calc(1.375rem + 1.5vw) !important'
3075
+ };
3076
+ rules['.fs-2'] = {
3077
+ 'font-size': 'calc(1.325rem + .9vw) !important'
3078
+ };
3079
+ rules['.fs-3'] = {
3080
+ 'font-size': 'calc(1.3rem + .6vw) !important'
3081
+ };
3082
+ rules['.fs-4'] = {
3083
+ 'font-size': 'calc(1.275rem + .3vw) !important'
3084
+ };
3085
+ rules['.fs-5'] = {
3086
+ 'font-size': '1.25rem !important'
3087
+ };
3088
+ rules['.fs-6'] = {
3089
+ 'font-size': '1rem !important'
3090
+ };
3091
+
3092
+ // List utilities (structural)
3093
+ rules['.list-unstyled'] = {
3094
+ 'padding-left': '0',
3095
+ 'list-style': 'none'
3096
+ };
3097
+ rules['.list-inline'] = {
3098
+ 'padding-left': '0',
3099
+ 'list-style': 'none'
3100
+ };
3101
+ rules['.list-inline-item'] = {
3102
+ 'display': 'inline-block'
3103
+ };
3104
+ rules['.list-inline-item:not(:last-child)'] = {
3105
+ 'margin-right': '.5rem'
3106
+ };
3107
+
3108
+ // Opacity utilities (structural)
3109
+ rules['.opacity-0'] = {
3110
+ 'opacity': '0 !important'
3111
+ };
3112
+ rules['.opacity-25'] = {
3113
+ 'opacity': '.25 !important'
3114
+ };
3115
+ rules['.opacity-50'] = {
3116
+ 'opacity': '.5 !important'
3117
+ };
3118
+ rules['.opacity-75'] = {
3119
+ 'opacity': '.75 !important'
3120
+ };
3121
+ rules['.opacity-100'] = {
3122
+ 'opacity': '1 !important'
3123
+ };
3124
+
3125
+ // Responsive grid
3126
+ Object.assign(rules, defaultStyles.responsive);
3127
+ return addUnderscoreAliases(rules);
3128
+ }
3129
+
3130
+ // =========================================================================
3131
+ // getAllStyles — backwards compatible
3132
+ // =========================================================================
3133
+
3134
+ /**
3135
+ * Add underscore aliases for all bw- selectors
3136
+ * @param {Object} rules - CSS rules object
3137
+ * @returns {Object} - Rules with underscore aliases added
3138
+ */
3139
+ function addUnderscoreAliases(rules) {
3140
+ var result = {};
3141
+ for (var _i = 0, _Object$entries = Object.entries(rules); _i < _Object$entries.length; _i++) {
3142
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
3143
+ selector = _Object$entries$_i[0],
3144
+ styles = _Object$entries$_i[1];
3145
+ result[selector] = styles;
3146
+ if (selector.includes('.bw-')) {
3147
+ var underscoreSelector = selector.replace(/\.bw-/g, '.bw_');
3148
+ result[underscoreSelector] = styles;
3149
+ }
3150
+ }
3151
+ return result;
3152
+ }
3153
+
3154
+ // =========================================================================
3155
+ // Theme tokens (backwards compatible)
2606
3156
  // =========================================================================
2607
3157
 
2608
3158
  var theme = {
@@ -2776,6 +3326,56 @@
2776
3326
  '.bw-dark .bw-close': {
2777
3327
  'color': textColor
2778
3328
  },
3329
+ '.bw-dark .bw-accordion-item': {
3330
+ 'background-color': surfaceBg,
3331
+ 'border-color': borderColor
3332
+ },
3333
+ '.bw-dark .bw-accordion-button': {
3334
+ 'color': textColor
3335
+ },
3336
+ '.bw-dark .bw-accordion-button:hover': {
3337
+ 'background-color': bodyBg
3338
+ },
3339
+ '.bw-dark .bw-accordion-body': {
3340
+ 'border-top-color': borderColor
3341
+ },
3342
+ '.bw-dark .bw-modal-content': {
3343
+ 'background-color': surfaceBg,
3344
+ 'border-color': borderColor
3345
+ },
3346
+ '.bw-dark .bw-modal-header': {
3347
+ 'border-bottom-color': borderColor
3348
+ },
3349
+ '.bw-dark .bw-modal-footer': {
3350
+ 'border-top-color': borderColor
3351
+ },
3352
+ '.bw-dark .bw-modal-title': {
3353
+ 'color': textColor
3354
+ },
3355
+ '.bw-dark .bw-toast': {
3356
+ 'background-color': surfaceBg,
3357
+ 'border-color': borderColor
3358
+ },
3359
+ '.bw-dark .bw-toast-header': {
3360
+ 'border-bottom-color': borderColor,
3361
+ 'color': textColor
3362
+ },
3363
+ '.bw-dark .bw-dropdown-menu': {
3364
+ 'background-color': surfaceBg,
3365
+ 'border-color': borderColor
3366
+ },
3367
+ '.bw-dark .bw-dropdown-item': {
3368
+ 'color': textColor
3369
+ },
3370
+ '.bw-dark .bw-dropdown-item:hover': {
3371
+ 'background-color': bodyBg
3372
+ },
3373
+ '.bw-dark .bw-dropdown-divider': {
3374
+ 'border-top-color': borderColor
3375
+ },
3376
+ '.bw-dark .bw-skeleton': {
3377
+ 'background-color': borderColor
3378
+ },
2779
3379
  '.bw-dark h1, .bw-dark h2, .bw-dark h3, .bw-dark h4, .bw-dark h5, .bw-dark h6': {
2780
3380
  'color': textColor
2781
3381
  },
@@ -2803,8 +3403,11 @@
2803
3403
  }
2804
3404
 
2805
3405
  var _excluded$1 = ["type", "placeholder", "value", "id", "name", "disabled", "readonly", "required", "className", "style"],
2806
- _excluded2 = ["placeholder", "value", "rows", "id", "name", "disabled", "readonly", "required", "className"],
2807
- _excluded3 = ["options", "value", "id", "name", "disabled", "required", "className"];
3406
+ _excluded2$1 = ["placeholder", "value", "rows", "id", "name", "disabled", "readonly", "required", "className"],
3407
+ _excluded3 = ["options", "value", "id", "name", "disabled", "required", "className"],
3408
+ _excluded4 = ["label", "checked", "id", "name", "disabled", "value", "className"],
3409
+ _excluded5 = ["label", "name", "value", "checked", "id", "disabled", "className"],
3410
+ _excluded6 = ["label", "checked", "id", "name", "disabled", "className"];
2808
3411
  /**
2809
3412
  * Bitwrench v2 Components
2810
3413
  *
@@ -3429,7 +4032,13 @@
3429
4032
  a: {
3430
4033
  type: 'button',
3431
4034
  "class": 'bw-close',
3432
- 'aria-label': 'Close'
4035
+ 'aria-label': 'Close',
4036
+ onclick: function onclick(e) {
4037
+ var alert = e.target.closest('.bw-alert');
4038
+ if (alert) {
4039
+ alert.remove();
4040
+ }
4041
+ }
3433
4042
  },
3434
4043
  c: '×'
3435
4044
  }].filter(Boolean)
@@ -3442,26 +4051,30 @@
3442
4051
  * @param {Object} [props] - Badge configuration
3443
4052
  * @param {string} [props.text] - Badge display text
3444
4053
  * @param {string} [props.variant="primary"] - Color variant
4054
+ * @param {string} [props.size] - Size variant: 'sm' or 'lg' (default is medium)
3445
4055
  * @param {boolean} [props.pill=false] - Use pill (rounded) shape
3446
4056
  * @param {string} [props.className] - Additional CSS classes
3447
4057
  * @returns {Object} TACO object representing a badge span
3448
4058
  * @category Component Builders
3449
4059
  * @example
3450
4060
  * const badge = makeBadge({ text: "New", variant: "danger", pill: true });
4061
+ * const small = makeBadge({ text: "3", variant: "info", size: "sm" });
3451
4062
  */
3452
4063
  function makeBadge() {
3453
4064
  var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
3454
4065
  var text = props.text,
3455
4066
  _props$variant3 = props.variant,
3456
4067
  variant = _props$variant3 === void 0 ? 'primary' : _props$variant3,
4068
+ size = props.size,
3457
4069
  _props$pill = props.pill,
3458
4070
  pill = _props$pill === void 0 ? false : _props$pill,
3459
4071
  _props$className9 = props.className,
3460
4072
  className = _props$className9 === void 0 ? '' : _props$className9;
4073
+ var sizeClass = size === 'sm' ? ' bw-badge-sm' : size === 'lg' ? ' bw-badge-lg' : '';
3461
4074
  return {
3462
4075
  t: 'span',
3463
4076
  a: {
3464
- "class": "bw-badge bw-badge-".concat(variant, " ").concat(pill ? 'bw-badge-pill' : '', " ").concat(className).trim()
4077
+ "class": "bw-badge bw-badge-".concat(variant).concat(sizeClass, " ").concat(pill ? 'bw-badge-pill' : '', " ").concat(className).trim()
3465
4078
  },
3466
4079
  c: text
3467
4080
  };
@@ -3843,7 +4456,7 @@
3843
4456
  required = _props$required2 === void 0 ? false : _props$required2,
3844
4457
  _props$className10 = props.className,
3845
4458
  className = _props$className10 === void 0 ? '' : _props$className10,
3846
- eventHandlers = _objectWithoutProperties(props, _excluded2);
4459
+ eventHandlers = _objectWithoutProperties(props, _excluded2$1);
3847
4460
  return {
3848
4461
  t: 'textarea',
3849
4462
  a: _objectSpread2({
@@ -3949,15 +4562,18 @@
3949
4562
  name = props.name,
3950
4563
  _props$disabled5 = props.disabled,
3951
4564
  disabled = _props$disabled5 === void 0 ? false : _props$disabled5,
3952
- value = props.value;
4565
+ value = props.value,
4566
+ _props$className12 = props.className,
4567
+ className = _props$className12 === void 0 ? '' : _props$className12,
4568
+ eventHandlers = _objectWithoutProperties(props, _excluded4);
3953
4569
  return {
3954
4570
  t: 'div',
3955
4571
  a: {
3956
- "class": 'bw-form-check'
4572
+ "class": "bw-form-check ".concat(className).trim()
3957
4573
  },
3958
4574
  c: [{
3959
4575
  t: 'input',
3960
- a: {
4576
+ a: _objectSpread2({
3961
4577
  type: 'checkbox',
3962
4578
  "class": 'bw-form-check-input',
3963
4579
  checked: checked,
@@ -3965,7 +4581,7 @@
3965
4581
  name: name,
3966
4582
  disabled: disabled,
3967
4583
  value: value
3968
- }
4584
+ }, eventHandlers)
3969
4585
  }, label && {
3970
4586
  t: 'label',
3971
4587
  a: {
@@ -4004,8 +4620,8 @@
4004
4620
  direction = _props$direction === void 0 ? 'vertical' : _props$direction,
4005
4621
  _props$gap = props.gap,
4006
4622
  gap = _props$gap === void 0 ? 3 : _props$gap,
4007
- _props$className12 = props.className,
4008
- className = _props$className12 === void 0 ? '' : _props$className12;
4623
+ _props$className13 = props.className,
4624
+ className = _props$className13 === void 0 ? '' : _props$className13;
4009
4625
  return {
4010
4626
  t: 'div',
4011
4627
  a: {
@@ -4096,8 +4712,8 @@
4096
4712
  overlay = _props$overlay === void 0 ? false : _props$overlay,
4097
4713
  backgroundImage = props.backgroundImage,
4098
4714
  actions = props.actions,
4099
- _props$className13 = props.className,
4100
- className = _props$className13 === void 0 ? '' : _props$className13;
4715
+ _props$className14 = props.className,
4716
+ className = _props$className14 === void 0 ? '' : _props$className14;
4101
4717
  var sizeClasses = {
4102
4718
  sm: 'bw-py-3',
4103
4719
  md: 'bw-py-4',
@@ -4186,8 +4802,8 @@
4186
4802
  centered = _props$centered2 === void 0 ? true : _props$centered2,
4187
4803
  _props$iconSize = props.iconSize,
4188
4804
  iconSize = _props$iconSize === void 0 ? '3rem' : _props$iconSize,
4189
- _props$className14 = props.className,
4190
- className = _props$className14 === void 0 ? '' : _props$className14;
4805
+ _props$className15 = props.className,
4806
+ className = _props$className15 === void 0 ? '' : _props$className15;
4191
4807
  var colClass = "bw-col-md-".concat(12 / columns);
4192
4808
  return {
4193
4809
  t: 'div',
@@ -4213,8 +4829,8 @@
4213
4829
  c: [feature.icon && {
4214
4830
  t: 'div',
4215
4831
  a: {
4216
- "class": 'bw-feature-icon bw-mb-3',
4217
- style: "font-size: ".concat(iconSize, "; color: var(--bw-primary);")
4832
+ "class": 'bw-feature-icon bw-mb-3 bw-text-primary',
4833
+ style: "font-size: ".concat(iconSize, ";")
4218
4834
  },
4219
4835
  c: feature.icon
4220
4836
  }, feature.title && {
@@ -4267,8 +4883,8 @@
4267
4883
  variant = _props$variant7 === void 0 ? 'light' : _props$variant7,
4268
4884
  _props$centered3 = props.centered,
4269
4885
  centered = _props$centered3 === void 0 ? true : _props$centered3,
4270
- _props$className15 = props.className,
4271
- className = _props$className15 === void 0 ? '' : _props$className15;
4886
+ _props$className16 = props.className,
4887
+ className = _props$className16 === void 0 ? '' : _props$className16;
4272
4888
  return {
4273
4889
  t: 'section',
4274
4890
  a: {
@@ -4337,8 +4953,8 @@
4337
4953
  variant = _props$variant8 === void 0 ? 'default' : _props$variant8,
4338
4954
  _props$spacing = props.spacing,
4339
4955
  spacing = _props$spacing === void 0 ? 'md' : _props$spacing,
4340
- _props$className16 = props.className,
4341
- className = _props$className16 === void 0 ? '' : _props$className16;
4956
+ _props$className17 = props.className,
4957
+ className = _props$className17 === void 0 ? '' : _props$className17;
4342
4958
  var spacingClasses = {
4343
4959
  sm: 'bw-py-3',
4344
4960
  md: 'bw-py-4',
@@ -4375,522 +4991,1451 @@
4375
4991
  }].filter(Boolean)
4376
4992
  }, content].filter(Boolean)
4377
4993
  }
4378
- };
4379
- }
4380
-
4381
- // =========================================================================
4382
- // Component Handle Classes
4383
- //
4384
- // Handle classes provide imperative DOM manipulation for rendered components.
4385
- // They cache child element references for efficient updates without
4386
- // full re-renders. Used by bw.createCard(), bw.createTable(), etc.
4387
- // =========================================================================
4994
+ };
4995
+ }
4996
+
4997
+ // =========================================================================
4998
+ // Component Handle Classes
4999
+ //
5000
+ // Handle classes provide imperative DOM manipulation for rendered components.
5001
+ // They cache child element references for efficient updates without
5002
+ // full re-renders. Used by bw.createCard(), bw.createTable(), etc.
5003
+ // =========================================================================
5004
+
5005
+ /**
5006
+ * Imperative handle for a rendered card component
5007
+ *
5008
+ * Provides methods to update card title, content, and CSS classes
5009
+ * without re-rendering the entire component. Created automatically
5010
+ * when using bw.createCard().
5011
+ *
5012
+ * @category Component Handles
5013
+ */
5014
+ var CardHandle = /*#__PURE__*/function () {
5015
+ /**
5016
+ * @param {Element} element - The card's root DOM element
5017
+ * @param {Object} taco - The original TACO object used to create the card
5018
+ */
5019
+ function CardHandle(element, taco) {
5020
+ var _taco$o;
5021
+ _classCallCheck(this, CardHandle);
5022
+ this.element = element;
5023
+ this._taco = taco;
5024
+ this.state = ((_taco$o = taco.o) === null || _taco$o === void 0 ? void 0 : _taco$o.state) || {};
5025
+
5026
+ // Cache child elements
5027
+ this.children = {
5028
+ header: element.querySelector('.bw-card-header'),
5029
+ title: element.querySelector('.bw-card-title'),
5030
+ body: element.querySelector('.bw-card-body'),
5031
+ footer: element.querySelector('.bw-card-footer')
5032
+ };
5033
+ }
5034
+
5035
+ /**
5036
+ * Update the card title text
5037
+ *
5038
+ * @param {string} title - New title text
5039
+ * @returns {CardHandle} this (for chaining)
5040
+ */
5041
+ return _createClass(CardHandle, [{
5042
+ key: "setTitle",
5043
+ value: function setTitle(title) {
5044
+ if (this.children.title) {
5045
+ this.children.title.textContent = title;
5046
+ }
5047
+ return this;
5048
+ }
5049
+
5050
+ /**
5051
+ * Replace the card body content
5052
+ *
5053
+ * @param {string|Object} content - New content (string or TACO object)
5054
+ * @returns {CardHandle} this (for chaining)
5055
+ */
5056
+ }, {
5057
+ key: "setContent",
5058
+ value: function setContent(content) {
5059
+ if (this.children.body) {
5060
+ if (typeof content === 'string') {
5061
+ this.children.body.textContent = content;
5062
+ } else {
5063
+ // Re-render content
5064
+ this.children.body.innerHTML = '';
5065
+ var newContent = window.bw.taco.toDOM(content);
5066
+ this.children.body.appendChild(newContent);
5067
+ }
5068
+ }
5069
+ return this;
5070
+ }
5071
+
5072
+ /**
5073
+ * Add a CSS class to the card root element
5074
+ *
5075
+ * @param {string} className - Class to add
5076
+ * @returns {CardHandle} this (for chaining)
5077
+ */
5078
+ }, {
5079
+ key: "addClass",
5080
+ value: function addClass(className) {
5081
+ this.element.classList.add(className);
5082
+ return this;
5083
+ }
5084
+
5085
+ /**
5086
+ * Remove a CSS class from the card root element
5087
+ *
5088
+ * @param {string} className - Class to remove
5089
+ * @returns {CardHandle} this (for chaining)
5090
+ */
5091
+ }, {
5092
+ key: "removeClass",
5093
+ value: function removeClass(className) {
5094
+ this.element.classList.remove(className);
5095
+ return this;
5096
+ }
5097
+
5098
+ /**
5099
+ * Query a child element within the card
5100
+ *
5101
+ * @param {string} selector - CSS selector
5102
+ * @returns {Element|null} Matching element or null
5103
+ */
5104
+ }, {
5105
+ key: "select",
5106
+ value: function select(selector) {
5107
+ return this.element.querySelector(selector);
5108
+ }
5109
+ }]);
5110
+ }();
5111
+
5112
+ /**
5113
+ * Imperative handle for a rendered table component
5114
+ *
5115
+ * Provides methods for data updates and column sorting. Caches
5116
+ * thead/tbody/header references for efficient DOM updates.
5117
+ * Created automatically when using bw.createTable().
5118
+ *
5119
+ * @category Component Handles
5120
+ */
5121
+ var TableHandle = /*#__PURE__*/function () {
5122
+ /**
5123
+ * @param {Element} element - The table's root DOM element
5124
+ * @param {Object} taco - The original TACO object used to create the table
5125
+ */
5126
+ function TableHandle(element, taco) {
5127
+ var _taco$o2;
5128
+ _classCallCheck(this, TableHandle);
5129
+ this.element = element;
5130
+ this._taco = taco;
5131
+ this.state = ((_taco$o2 = taco.o) === null || _taco$o2 === void 0 ? void 0 : _taco$o2.state) || {};
5132
+ this._data = this.state.data || [];
5133
+ this._sortColumn = null;
5134
+ this._sortDirection = 'asc';
5135
+
5136
+ // Cache elements
5137
+ this.children = {
5138
+ thead: element.querySelector('thead'),
5139
+ tbody: element.querySelector('tbody'),
5140
+ headers: element.querySelectorAll('th')
5141
+ };
5142
+
5143
+ // Set up sorting if enabled
5144
+ if (this.state.sortable) {
5145
+ this._setupSorting();
5146
+ }
5147
+ }
5148
+
5149
+ /**
5150
+ * Attach click-to-sort handlers on all column headers
5151
+ * @private
5152
+ */
5153
+ return _createClass(TableHandle, [{
5154
+ key: "_setupSorting",
5155
+ value: function _setupSorting() {
5156
+ var _this = this;
5157
+ this.children.headers.forEach(function (th, index) {
5158
+ th.style.cursor = 'pointer';
5159
+ th.onclick = function () {
5160
+ return _this.sortBy(th.textContent);
5161
+ };
5162
+ });
5163
+ }
5164
+
5165
+ /**
5166
+ * Replace the table data and re-render the body
5167
+ *
5168
+ * @param {Array<Object>} data - Array of row objects
5169
+ * @returns {TableHandle} this (for chaining)
5170
+ */
5171
+ }, {
5172
+ key: "setData",
5173
+ value: function setData(data) {
5174
+ this._data = data;
5175
+ this._renderBody();
5176
+ return this;
5177
+ }
5178
+
5179
+ /**
5180
+ * Sort the table by a column name
5181
+ *
5182
+ * Toggles direction if the same column is sorted again.
5183
+ *
5184
+ * @param {string} column - Column header text to sort by
5185
+ * @param {string} [direction] - Sort direction ("asc" or "desc"); toggles if omitted
5186
+ * @returns {TableHandle} this (for chaining)
5187
+ */
5188
+ }, {
5189
+ key: "sortBy",
5190
+ value: function sortBy(column, direction) {
5191
+ var _this2 = this;
5192
+ if (column === this._sortColumn && !direction) {
5193
+ this._sortDirection = this._sortDirection === 'asc' ? 'desc' : 'asc';
5194
+ } else {
5195
+ this._sortColumn = column;
5196
+ this._sortDirection = direction || 'asc';
5197
+ }
5198
+ var columnKey = Object.keys(this._data[0])[Array.from(this.children.headers).findIndex(function (th) {
5199
+ return th.textContent === column;
5200
+ })];
5201
+ this._data.sort(function (a, b) {
5202
+ var aVal = a[columnKey];
5203
+ var bVal = b[columnKey];
5204
+ var result = aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
5205
+ return _this2._sortDirection === 'asc' ? result : -result;
5206
+ });
5207
+ this._renderBody();
5208
+ return this;
5209
+ }
5210
+
5211
+ /**
5212
+ * Re-render the tbody from current _data
5213
+ * @private
5214
+ */
5215
+ }, {
5216
+ key: "_renderBody",
5217
+ value: function _renderBody() {
5218
+ var _this3 = this;
5219
+ this.children.tbody.innerHTML = '';
5220
+ this._data.forEach(function (row) {
5221
+ var tr = document.createElement('tr');
5222
+ Object.values(row).forEach(function (value) {
5223
+ var td = document.createElement('td');
5224
+ td.textContent = value;
5225
+ tr.appendChild(td);
5226
+ });
5227
+ _this3.children.tbody.appendChild(tr);
5228
+ });
5229
+ }
5230
+ }]);
5231
+ }();
4388
5232
 
4389
5233
  /**
4390
- * Imperative handle for a rendered card component
5234
+ * Imperative handle for a rendered navbar component
4391
5235
  *
4392
- * Provides methods to update card title, content, and CSS classes
4393
- * without re-rendering the entire component. Created automatically
4394
- * when using bw.createCard().
5236
+ * Provides methods to update the active navigation link.
5237
+ * Created automatically when using bw.createNavbar().
4395
5238
  *
4396
5239
  * @category Component Handles
4397
5240
  */
4398
- var CardHandle = /*#__PURE__*/function () {
5241
+ var NavbarHandle = /*#__PURE__*/function () {
4399
5242
  /**
4400
- * @param {Element} element - The card's root DOM element
4401
- * @param {Object} taco - The original TACO object used to create the card
5243
+ * @param {Element} element - The navbar's root DOM element
5244
+ * @param {Object} taco - The original TACO object used to create the navbar
4402
5245
  */
4403
- function CardHandle(element, taco) {
4404
- var _taco$o;
4405
- _classCallCheck(this, CardHandle);
5246
+ function NavbarHandle(element, taco) {
5247
+ var _taco$o3;
5248
+ _classCallCheck(this, NavbarHandle);
4406
5249
  this.element = element;
4407
5250
  this._taco = taco;
4408
- this.state = ((_taco$o = taco.o) === null || _taco$o === void 0 ? void 0 : _taco$o.state) || {};
4409
-
4410
- // Cache child elements
5251
+ this.state = ((_taco$o3 = taco.o) === null || _taco$o3 === void 0 ? void 0 : _taco$o3.state) || {};
4411
5252
  this.children = {
4412
- header: element.querySelector('.bw-card-header'),
4413
- title: element.querySelector('.bw-card-title'),
4414
- body: element.querySelector('.bw-card-body'),
4415
- footer: element.querySelector('.bw-card-footer')
5253
+ brand: element.querySelector('.bw-navbar-brand'),
5254
+ links: element.querySelectorAll('.bw-nav-link')
4416
5255
  };
4417
5256
  }
4418
5257
 
4419
5258
  /**
4420
- * Update the card title text
5259
+ * Set the active navigation link by href
4421
5260
  *
4422
- * @param {string} title - New title text
4423
- * @returns {CardHandle} this (for chaining)
5261
+ * @param {string} href - The href value of the link to activate
5262
+ * @returns {NavbarHandle} this (for chaining)
4424
5263
  */
4425
- return _createClass(CardHandle, [{
4426
- key: "setTitle",
4427
- value: function setTitle(title) {
4428
- if (this.children.title) {
4429
- this.children.title.textContent = title;
4430
- }
4431
- return this;
4432
- }
4433
-
4434
- /**
4435
- * Replace the card body content
4436
- *
4437
- * @param {string|Object} content - New content (string or TACO object)
4438
- * @returns {CardHandle} this (for chaining)
4439
- */
4440
- }, {
4441
- key: "setContent",
4442
- value: function setContent(content) {
4443
- if (this.children.body) {
4444
- if (typeof content === 'string') {
4445
- this.children.body.textContent = content;
5264
+ return _createClass(NavbarHandle, [{
5265
+ key: "setActive",
5266
+ value: function setActive(href) {
5267
+ this.children.links.forEach(function (link) {
5268
+ if (link.getAttribute('href') === href) {
5269
+ link.classList.add('active');
4446
5270
  } else {
4447
- // Re-render content
4448
- this.children.body.innerHTML = '';
4449
- var newContent = window.bw.taco.toDOM(content);
4450
- this.children.body.appendChild(newContent);
5271
+ link.classList.remove('active');
4451
5272
  }
4452
- }
5273
+ });
4453
5274
  return this;
4454
5275
  }
5276
+ }]);
5277
+ }();
4455
5278
 
4456
- /**
4457
- * Add a CSS class to the card root element
4458
- *
4459
- * @param {string} className - Class to add
4460
- * @returns {CardHandle} this (for chaining)
4461
- */
4462
- }, {
4463
- key: "addClass",
4464
- value: function addClass(className) {
4465
- this.element.classList.add(className);
4466
- return this;
4467
- }
5279
+ /**
5280
+ * Imperative handle for a rendered tabs component
5281
+ *
5282
+ * Provides programmatic tab switching. Sets up click handlers
5283
+ * on tab buttons and manages active states on both buttons and panes.
5284
+ * Created automatically when using bw.createTabs().
5285
+ *
5286
+ * @category Component Handles
5287
+ */
5288
+ var TabsHandle = /*#__PURE__*/function () {
5289
+ /**
5290
+ * @param {Element} element - The tabs container DOM element
5291
+ * @param {Object} taco - The original TACO object used to create the tabs
5292
+ */
5293
+ function TabsHandle(element, taco) {
5294
+ var _taco$o4;
5295
+ _classCallCheck(this, TabsHandle);
5296
+ this.element = element;
5297
+ this._taco = taco;
5298
+ this.state = ((_taco$o4 = taco.o) === null || _taco$o4 === void 0 ? void 0 : _taco$o4.state) || {};
5299
+ this.children = {
5300
+ navItems: element.querySelectorAll('.bw-nav-link'),
5301
+ tabPanes: element.querySelectorAll('.bw-tab-pane')
5302
+ };
5303
+ this._setupTabs();
5304
+ }
4468
5305
 
4469
- /**
4470
- * Remove a CSS class from the card root element
4471
- *
4472
- * @param {string} className - Class to remove
4473
- * @returns {CardHandle} this (for chaining)
4474
- */
4475
- }, {
4476
- key: "removeClass",
4477
- value: function removeClass(className) {
4478
- this.element.classList.remove(className);
4479
- return this;
5306
+ /**
5307
+ * Attach click handlers to tab navigation buttons
5308
+ * @private
5309
+ */
5310
+ return _createClass(TabsHandle, [{
5311
+ key: "_setupTabs",
5312
+ value: function _setupTabs() {
5313
+ var _this4 = this;
5314
+ this.children.navItems.forEach(function (navItem, index) {
5315
+ navItem.onclick = function (e) {
5316
+ e.preventDefault();
5317
+ _this4.switchTo(index);
5318
+ };
5319
+ });
4480
5320
  }
4481
5321
 
4482
5322
  /**
4483
- * Query a child element within the card
5323
+ * Programmatically switch to a tab by index
4484
5324
  *
4485
- * @param {string} selector - CSS selector
4486
- * @returns {Element|null} Matching element or null
5325
+ * @param {number} index - Zero-based tab index to activate
5326
+ * @returns {TabsHandle} this (for chaining)
4487
5327
  */
4488
5328
  }, {
4489
- key: "select",
4490
- value: function select(selector) {
4491
- return this.element.querySelector(selector);
5329
+ key: "switchTo",
5330
+ value: function switchTo(index) {
5331
+ this.children.navItems.forEach(function (item, i) {
5332
+ if (i === index) {
5333
+ item.classList.add('active');
5334
+ } else {
5335
+ item.classList.remove('active');
5336
+ }
5337
+ });
5338
+ this.children.tabPanes.forEach(function (pane, i) {
5339
+ if (i === index) {
5340
+ pane.classList.add('active');
5341
+ } else {
5342
+ pane.classList.remove('active');
5343
+ }
5344
+ });
5345
+ this.state.activeIndex = index;
5346
+ return this;
4492
5347
  }
4493
5348
  }]);
4494
5349
  }();
4495
5350
 
4496
5351
  /**
4497
- * Imperative handle for a rendered table component
5352
+ * Create a code demo component for documentation pages
5353
+ *
5354
+ * Displays a live result alongside source code in a tabbed interface.
5355
+ * Includes a copy-to-clipboard button on the code tab.
5356
+ *
5357
+ * @param {Object} [props] - Code demo configuration
5358
+ * @param {string} [props.title] - Demo title heading
5359
+ * @param {string} [props.description] - Demo description text
5360
+ * @param {string} [props.code] - Source code to display (adds a "Code" tab when present)
5361
+ * @param {string|Object|Array} [props.result] - Live result content for the "Result" tab
5362
+ * @param {string} [props.language="javascript"] - Code language for syntax class
5363
+ * @returns {Object} TACO object representing a code demo with tabbed Result/Code views
5364
+ * @category Component Builders
5365
+ * @example
5366
+ * const demo = makeCodeDemo({
5367
+ * title: "Button Example",
5368
+ * description: "A simple primary button",
5369
+ * code: 'makeButton({ text: "Click me" })',
5370
+ * result: makeButton({ text: "Click me" })
5371
+ * });
5372
+ */
5373
+ function makeCodeDemo() {
5374
+ var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
5375
+ var title = props.title,
5376
+ description = props.description,
5377
+ code = props.code,
5378
+ result = props.result,
5379
+ _props$language = props.language,
5380
+ language = _props$language === void 0 ? 'javascript' : _props$language;
5381
+
5382
+ // Generate unique ID for this demo
5383
+ var demoId = "demo-".concat(Math.random().toString(36).substr(2, 9));
5384
+ var tabs = [{
5385
+ label: 'Result',
5386
+ active: true,
5387
+ content: result
5388
+ }];
5389
+
5390
+ // Only add Code tab if code is provided
5391
+ if (code) {
5392
+ tabs.push({
5393
+ label: 'Code',
5394
+ content: {
5395
+ t: 'div',
5396
+ a: {
5397
+ style: 'position: relative;'
5398
+ },
5399
+ c: [{
5400
+ t: 'button',
5401
+ a: {
5402
+ "class": 'bw-copy-btn bw-code-copy-btn',
5403
+ onclick: function onclick(e) {
5404
+ navigator.clipboard.writeText(code).then(function () {
5405
+ var btn = e.target;
5406
+ var originalText = btn.textContent;
5407
+ btn.textContent = 'Copied!';
5408
+ btn.style.background = '#006666';
5409
+ btn.style.color = '#fff';
5410
+ setTimeout(function () {
5411
+ btn.textContent = originalText;
5412
+ btn.style.background = 'rgba(255,255,255,0.12)';
5413
+ btn.style.color = '#aaa';
5414
+ }, 2000);
5415
+ });
5416
+ }
5417
+ },
5418
+ c: 'Copy'
5419
+ }, typeof globalThis !== 'undefined' && typeof globalThis.bw !== 'undefined' && typeof globalThis.bw.codeEditor === 'function' ? globalThis.bw.codeEditor({
5420
+ code: code,
5421
+ lang: language === 'javascript' ? 'js' : language,
5422
+ readOnly: true,
5423
+ height: 'auto'
5424
+ }) : {
5425
+ t: 'pre',
5426
+ a: {
5427
+ "class": 'bw-code-pre'
5428
+ },
5429
+ c: {
5430
+ t: 'code',
5431
+ a: {
5432
+ "class": "bw-code-block language-".concat(language)
5433
+ },
5434
+ c: code
5435
+ }
5436
+ }]
5437
+ }
5438
+ });
5439
+ }
5440
+ var content = [title && {
5441
+ t: 'h3',
5442
+ c: title
5443
+ }, description && {
5444
+ t: 'p',
5445
+ a: {
5446
+ "class": 'bw-text-muted',
5447
+ style: 'margin-bottom: 1rem;'
5448
+ },
5449
+ c: description
5450
+ }, makeTabs({
5451
+ tabs: tabs,
5452
+ id: demoId
5453
+ })].filter(Boolean);
5454
+ return {
5455
+ t: 'div',
5456
+ a: {
5457
+ "class": 'bw-code-demo'
5458
+ },
5459
+ c: content
5460
+ };
5461
+ }
5462
+
5463
+ /**
5464
+ * Registry mapping component type names to their handle classes
4498
5465
  *
4499
- * Provides methods for data updates and column sorting. Caches
4500
- * thead/tbody/header references for efficient DOM updates.
4501
- * Created automatically when using bw.createTable().
5466
+ * Used by bw.createCard(), bw.createTable(), etc. to wrap rendered
5467
+ * DOM elements in the appropriate imperative handle.
4502
5468
  *
4503
- * @category Component Handles
5469
+ * @type {Object.<string, Function>}
4504
5470
  */
4505
- var TableHandle = /*#__PURE__*/function () {
4506
- /**
4507
- * @param {Element} element - The table's root DOM element
4508
- * @param {Object} taco - The original TACO object used to create the table
4509
- */
4510
- function TableHandle(element, taco) {
4511
- var _taco$o2;
4512
- _classCallCheck(this, TableHandle);
4513
- this.element = element;
4514
- this._taco = taco;
4515
- this.state = ((_taco$o2 = taco.o) === null || _taco$o2 === void 0 ? void 0 : _taco$o2.state) || {};
4516
- this._data = this.state.data || [];
4517
- this._sortColumn = null;
4518
- this._sortDirection = 'asc';
5471
+ // =========================================================================
5472
+ // Phase 1: Quick Wins
5473
+ // =========================================================================
4519
5474
 
4520
- // Cache elements
4521
- this.children = {
4522
- thead: element.querySelector('thead'),
4523
- tbody: element.querySelector('tbody'),
4524
- headers: element.querySelectorAll('th')
5475
+ /**
5476
+ * Create a pagination navigation component
5477
+ *
5478
+ * @param {Object} [props] - Pagination configuration
5479
+ * @param {number} [props.pages=1] - Total number of pages
5480
+ * @param {number} [props.currentPage=1] - Currently active page (1-based)
5481
+ * @param {Function} [props.onPageChange] - Callback when page changes, receives page number
5482
+ * @param {string} [props.size] - Size variant ("sm" or "lg")
5483
+ * @param {string} [props.className] - Additional CSS classes
5484
+ * @returns {Object} TACO object representing a pagination nav
5485
+ * @category Component Builders
5486
+ * @example
5487
+ * const pager = makePagination({
5488
+ * pages: 10,
5489
+ * currentPage: 3,
5490
+ * onPageChange: (page) => loadPage(page)
5491
+ * });
5492
+ */
5493
+ function makePagination() {
5494
+ var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
5495
+ var _props$pages = props.pages,
5496
+ pages = _props$pages === void 0 ? 1 : _props$pages,
5497
+ _props$currentPage = props.currentPage,
5498
+ currentPage = _props$currentPage === void 0 ? 1 : _props$currentPage,
5499
+ onPageChange = props.onPageChange,
5500
+ size = props.size,
5501
+ _props$className18 = props.className,
5502
+ className = _props$className18 === void 0 ? '' : _props$className18;
5503
+ function handleClick(page) {
5504
+ return function (e) {
5505
+ e.preventDefault();
5506
+ if (page < 1 || page > pages || page === currentPage) return;
5507
+ if (onPageChange) onPageChange(page);
4525
5508
  };
5509
+ }
5510
+ var items = [];
4526
5511
 
4527
- // Set up sorting if enabled
4528
- if (this.state.sortable) {
4529
- this._setupSorting();
5512
+ // Previous arrow
5513
+ items.push({
5514
+ t: 'li',
5515
+ a: {
5516
+ "class": "bw-page-item ".concat(currentPage <= 1 ? 'bw-disabled' : '').trim()
5517
+ },
5518
+ c: {
5519
+ t: 'a',
5520
+ a: {
5521
+ "class": 'bw-page-link',
5522
+ href: '#',
5523
+ onclick: handleClick(currentPage - 1),
5524
+ 'aria-label': 'Previous'
5525
+ },
5526
+ c: "\u2039"
4530
5527
  }
4531
- }
5528
+ });
4532
5529
 
4533
- /**
4534
- * Attach click-to-sort handlers on all column headers
4535
- * @private
4536
- */
4537
- return _createClass(TableHandle, [{
4538
- key: "_setupSorting",
4539
- value: function _setupSorting() {
4540
- var _this = this;
4541
- this.children.headers.forEach(function (th, index) {
4542
- th.style.cursor = 'pointer';
4543
- th.onclick = function () {
4544
- return _this.sortBy(th.textContent);
4545
- };
5530
+ // Page numbers
5531
+ for (var i = 1; i <= pages; i++) {
5532
+ (function (pageNum) {
5533
+ items.push({
5534
+ t: 'li',
5535
+ a: {
5536
+ "class": "bw-page-item ".concat(pageNum === currentPage ? 'bw-active' : '').trim()
5537
+ },
5538
+ c: {
5539
+ t: 'a',
5540
+ a: {
5541
+ "class": 'bw-page-link',
5542
+ href: '#',
5543
+ onclick: handleClick(pageNum)
5544
+ },
5545
+ c: '' + pageNum
5546
+ }
4546
5547
  });
4547
- }
5548
+ })(i);
5549
+ }
4548
5550
 
4549
- /**
4550
- * Replace the table data and re-render the body
4551
- *
4552
- * @param {Array<Object>} data - Array of row objects
4553
- * @returns {TableHandle} this (for chaining)
4554
- */
4555
- }, {
4556
- key: "setData",
4557
- value: function setData(data) {
4558
- this._data = data;
4559
- this._renderBody();
4560
- return this;
5551
+ // Next arrow
5552
+ items.push({
5553
+ t: 'li',
5554
+ a: {
5555
+ "class": "bw-page-item ".concat(currentPage >= pages ? 'bw-disabled' : '').trim()
5556
+ },
5557
+ c: {
5558
+ t: 'a',
5559
+ a: {
5560
+ "class": 'bw-page-link',
5561
+ href: '#',
5562
+ onclick: handleClick(currentPage + 1),
5563
+ 'aria-label': 'Next'
5564
+ },
5565
+ c: "\u203A"
4561
5566
  }
4562
-
4563
- /**
4564
- * Sort the table by a column name
4565
- *
4566
- * Toggles direction if the same column is sorted again.
4567
- *
4568
- * @param {string} column - Column header text to sort by
4569
- * @param {string} [direction] - Sort direction ("asc" or "desc"); toggles if omitted
4570
- * @returns {TableHandle} this (for chaining)
4571
- */
4572
- }, {
4573
- key: "sortBy",
4574
- value: function sortBy(column, direction) {
4575
- var _this2 = this;
4576
- if (column === this._sortColumn && !direction) {
4577
- this._sortDirection = this._sortDirection === 'asc' ? 'desc' : 'asc';
4578
- } else {
4579
- this._sortColumn = column;
4580
- this._sortDirection = direction || 'asc';
4581
- }
4582
- var columnKey = Object.keys(this._data[0])[Array.from(this.children.headers).findIndex(function (th) {
4583
- return th.textContent === column;
4584
- })];
4585
- this._data.sort(function (a, b) {
4586
- var aVal = a[columnKey];
4587
- var bVal = b[columnKey];
4588
- var result = aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
4589
- return _this2._sortDirection === 'asc' ? result : -result;
4590
- });
4591
- this._renderBody();
4592
- return this;
5567
+ });
5568
+ return {
5569
+ t: 'nav',
5570
+ a: {
5571
+ 'aria-label': 'Pagination'
5572
+ },
5573
+ c: {
5574
+ t: 'ul',
5575
+ a: {
5576
+ "class": "bw-pagination ".concat(size ? 'bw-pagination-' + size : '', " ").concat(className).trim()
5577
+ },
5578
+ c: items
4593
5579
  }
5580
+ };
5581
+ }
4594
5582
 
4595
- /**
4596
- * Re-render the tbody from current _data
4597
- * @private
4598
- */
4599
- }, {
4600
- key: "_renderBody",
4601
- value: function _renderBody() {
4602
- var _this3 = this;
4603
- this.children.tbody.innerHTML = '';
4604
- this._data.forEach(function (row) {
4605
- var tr = document.createElement('tr');
4606
- Object.values(row).forEach(function (value) {
4607
- var td = document.createElement('td');
4608
- td.textContent = value;
4609
- tr.appendChild(td);
4610
- });
4611
- _this3.children.tbody.appendChild(tr);
4612
- });
5583
+ /**
5584
+ * Create a radio button input with label
5585
+ *
5586
+ * @param {Object} [props] - Radio configuration
5587
+ * @param {string} [props.label] - Radio label text
5588
+ * @param {string} [props.name] - Radio group name
5589
+ * @param {string} [props.value] - Radio value attribute
5590
+ * @param {boolean} [props.checked=false] - Whether the radio is selected
5591
+ * @param {string} [props.id] - Element ID (links label to radio)
5592
+ * @param {boolean} [props.disabled=false] - Whether the radio is disabled
5593
+ * @param {string} [props.className] - Additional CSS classes
5594
+ * @returns {Object} TACO object representing a radio form group
5595
+ * @category Component Builders
5596
+ * @example
5597
+ * const radio = makeRadio({
5598
+ * label: "Option A",
5599
+ * name: "choice",
5600
+ * value: "a",
5601
+ * checked: true
5602
+ * });
5603
+ */
5604
+ function makeRadio() {
5605
+ var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
5606
+ var label = props.label,
5607
+ name = props.name,
5608
+ value = props.value,
5609
+ _props$checked2 = props.checked,
5610
+ checked = _props$checked2 === void 0 ? false : _props$checked2,
5611
+ id = props.id,
5612
+ _props$disabled6 = props.disabled,
5613
+ disabled = _props$disabled6 === void 0 ? false : _props$disabled6,
5614
+ _props$className19 = props.className,
5615
+ className = _props$className19 === void 0 ? '' : _props$className19,
5616
+ eventHandlers = _objectWithoutProperties(props, _excluded5);
5617
+ return {
5618
+ t: 'div',
5619
+ a: {
5620
+ "class": "bw-form-check ".concat(className).trim()
5621
+ },
5622
+ c: [{
5623
+ t: 'input',
5624
+ a: _objectSpread2({
5625
+ type: 'radio',
5626
+ "class": 'bw-form-check-input',
5627
+ name: name,
5628
+ value: value,
5629
+ checked: checked,
5630
+ id: id,
5631
+ disabled: disabled
5632
+ }, eventHandlers)
5633
+ }, label && {
5634
+ t: 'label',
5635
+ a: {
5636
+ "class": 'bw-form-check-label',
5637
+ "for": id
5638
+ },
5639
+ c: label
5640
+ }].filter(Boolean)
5641
+ };
5642
+ }
5643
+
5644
+ /**
5645
+ * Create a button group wrapper
5646
+ *
5647
+ * @param {Object} [props] - Button group configuration
5648
+ * @param {Array} [props.children] - Button TACO objects to group
5649
+ * @param {string} [props.size] - Size variant ("sm" or "lg")
5650
+ * @param {boolean} [props.vertical=false] - Stack buttons vertically
5651
+ * @param {string} [props.className] - Additional CSS classes
5652
+ * @returns {Object} TACO object representing a button group
5653
+ * @category Component Builders
5654
+ * @example
5655
+ * const group = makeButtonGroup({
5656
+ * children: [
5657
+ * makeButton({ text: "Left", variant: "primary" }),
5658
+ * makeButton({ text: "Middle", variant: "primary" }),
5659
+ * makeButton({ text: "Right", variant: "primary" })
5660
+ * ]
5661
+ * });
5662
+ */
5663
+ function makeButtonGroup() {
5664
+ var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
5665
+ var children = props.children,
5666
+ size = props.size,
5667
+ _props$vertical2 = props.vertical,
5668
+ vertical = _props$vertical2 === void 0 ? false : _props$vertical2,
5669
+ _props$className20 = props.className,
5670
+ className = _props$className20 === void 0 ? '' : _props$className20;
5671
+ return {
5672
+ t: 'div',
5673
+ a: {
5674
+ "class": "".concat(vertical ? 'bw-btn-group-vertical' : 'bw-btn-group', " ").concat(size ? 'bw-btn-group-' + size : '', " ").concat(className).trim(),
5675
+ role: 'group'
5676
+ },
5677
+ c: children
5678
+ };
5679
+ }
5680
+
5681
+ // =========================================================================
5682
+ // Phase 2: Core Interactive
5683
+ // =========================================================================
5684
+
5685
+ /**
5686
+ * Create an accordion component with collapsible items
5687
+ *
5688
+ * @param {Object} [props] - Accordion configuration
5689
+ * @param {Array<Object>} [props.items=[]] - Accordion items
5690
+ * @param {string} props.items[].title - Header text for the accordion item
5691
+ * @param {string|Object|Array} props.items[].content - Collapsible content
5692
+ * @param {boolean} [props.items[].open=false] - Whether the item is initially open
5693
+ * @param {boolean} [props.multiOpen=false] - Allow multiple items open simultaneously
5694
+ * @param {string} [props.className] - Additional CSS classes
5695
+ * @returns {Object} TACO object representing an accordion
5696
+ * @category Component Builders
5697
+ * @example
5698
+ * const accordion = makeAccordion({
5699
+ * items: [
5700
+ * { title: "Section 1", content: "Content 1", open: true },
5701
+ * { title: "Section 2", content: "Content 2" }
5702
+ * ]
5703
+ * });
5704
+ */
5705
+ function makeAccordion() {
5706
+ var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
5707
+ var _props$items5 = props.items,
5708
+ items = _props$items5 === void 0 ? [] : _props$items5,
5709
+ _props$multiOpen = props.multiOpen,
5710
+ multiOpen = _props$multiOpen === void 0 ? false : _props$multiOpen,
5711
+ _props$className21 = props.className,
5712
+ className = _props$className21 === void 0 ? '' : _props$className21;
5713
+ return {
5714
+ t: 'div',
5715
+ a: {
5716
+ "class": "bw-accordion ".concat(className).trim()
5717
+ },
5718
+ c: items.map(function (item, index) {
5719
+ return {
5720
+ t: 'div',
5721
+ a: {
5722
+ "class": 'bw-accordion-item'
5723
+ },
5724
+ c: [{
5725
+ t: 'h2',
5726
+ a: {
5727
+ "class": 'bw-accordion-header'
5728
+ },
5729
+ c: {
5730
+ t: 'button',
5731
+ a: {
5732
+ "class": "bw-accordion-button ".concat(item.open ? '' : 'bw-collapsed').trim(),
5733
+ type: 'button',
5734
+ 'aria-expanded': item.open ? 'true' : 'false',
5735
+ 'data-accordion-index': index,
5736
+ onclick: function onclick(e) {
5737
+ var btn = e.target.closest('.bw-accordion-button');
5738
+ var accordionEl = btn.closest('.bw-accordion');
5739
+ var accordionItem = btn.closest('.bw-accordion-item');
5740
+ var collapse = accordionItem.querySelector('.bw-accordion-collapse');
5741
+ var isOpen = collapse.classList.contains('bw-collapse-show');
5742
+ if (!multiOpen) {
5743
+ // Close all siblings
5744
+ var allCollapses = accordionEl.querySelectorAll('.bw-accordion-collapse');
5745
+ var allButtons = accordionEl.querySelectorAll('.bw-accordion-button');
5746
+ for (var j = 0; j < allCollapses.length; j++) {
5747
+ allCollapses[j].classList.remove('bw-collapse-show');
5748
+ allCollapses[j].style.maxHeight = null;
5749
+ }
5750
+ for (var k = 0; k < allButtons.length; k++) {
5751
+ allButtons[k].classList.add('bw-collapsed');
5752
+ allButtons[k].setAttribute('aria-expanded', 'false');
5753
+ }
5754
+ }
5755
+ if (isOpen) {
5756
+ collapse.classList.remove('bw-collapse-show');
5757
+ collapse.style.maxHeight = null;
5758
+ btn.classList.add('bw-collapsed');
5759
+ btn.setAttribute('aria-expanded', 'false');
5760
+ } else {
5761
+ collapse.classList.add('bw-collapse-show');
5762
+ collapse.style.maxHeight = collapse.scrollHeight + 'px';
5763
+ btn.classList.remove('bw-collapsed');
5764
+ btn.setAttribute('aria-expanded', 'true');
5765
+ }
5766
+ }
5767
+ },
5768
+ c: item.title
5769
+ }
5770
+ }, {
5771
+ t: 'div',
5772
+ a: {
5773
+ "class": "bw-accordion-collapse ".concat(item.open ? 'bw-collapse-show' : '').trim()
5774
+ },
5775
+ c: {
5776
+ t: 'div',
5777
+ a: {
5778
+ "class": 'bw-accordion-body'
5779
+ },
5780
+ c: item.content
5781
+ },
5782
+ o: item.open ? {
5783
+ mounted: function mounted(el) {
5784
+ el.style.maxHeight = el.scrollHeight + 'px';
5785
+ }
5786
+ } : undefined
5787
+ }]
5788
+ };
5789
+ }),
5790
+ o: {
5791
+ type: 'accordion',
5792
+ state: {
5793
+ multiOpen: multiOpen
5794
+ }
4613
5795
  }
4614
- }]);
4615
- }();
5796
+ };
5797
+ }
4616
5798
 
4617
5799
  /**
4618
- * Imperative handle for a rendered navbar component
5800
+ * Imperative handle for a rendered modal component
4619
5801
  *
4620
- * Provides methods to update the active navigation link.
4621
- * Created automatically when using bw.createNavbar().
5802
+ * Provides `.show()`, `.hide()`, `.toggle()`, and `.destroy()` methods
5803
+ * for controlling the modal programmatically.
4622
5804
  *
4623
5805
  * @category Component Handles
4624
5806
  */
4625
- var NavbarHandle = /*#__PURE__*/function () {
5807
+ var ModalHandle = /*#__PURE__*/function () {
4626
5808
  /**
4627
- * @param {Element} element - The navbar's root DOM element
4628
- * @param {Object} taco - The original TACO object used to create the navbar
5809
+ * @param {Element} element - The modal backdrop DOM element
5810
+ * @param {Object} taco - The original TACO object
4629
5811
  */
4630
- function NavbarHandle(element, taco) {
4631
- var _taco$o3;
4632
- _classCallCheck(this, NavbarHandle);
5812
+ function ModalHandle(element, taco) {
5813
+ _classCallCheck(this, ModalHandle);
4633
5814
  this.element = element;
4634
5815
  this._taco = taco;
4635
- this.state = ((_taco$o3 = taco.o) === null || _taco$o3 === void 0 ? void 0 : _taco$o3.state) || {};
4636
- this.children = {
4637
- brand: element.querySelector('.bw-navbar-brand'),
4638
- links: element.querySelectorAll('.bw-nav-link')
4639
- };
5816
+ this._escHandler = null;
4640
5817
  }
4641
5818
 
4642
- /**
4643
- * Set the active navigation link by href
4644
- *
4645
- * @param {string} href - The href value of the link to activate
4646
- * @returns {NavbarHandle} this (for chaining)
4647
- */
4648
- return _createClass(NavbarHandle, [{
4649
- key: "setActive",
4650
- value: function setActive(href) {
4651
- this.children.links.forEach(function (link) {
4652
- if (link.getAttribute('href') === href) {
4653
- link.classList.add('active');
4654
- } else {
4655
- link.classList.remove('active');
4656
- }
4657
- });
5819
+ /** Show the modal */
5820
+ return _createClass(ModalHandle, [{
5821
+ key: "show",
5822
+ value: function show() {
5823
+ this.element.classList.add('bw-modal-show');
5824
+ document.body.style.overflow = 'hidden';
5825
+ return this;
5826
+ }
5827
+
5828
+ /** Hide the modal */
5829
+ }, {
5830
+ key: "hide",
5831
+ value: function hide() {
5832
+ this.element.classList.remove('bw-modal-show');
5833
+ document.body.style.overflow = '';
5834
+ return this;
5835
+ }
5836
+
5837
+ /** Toggle modal visibility */
5838
+ }, {
5839
+ key: "toggle",
5840
+ value: function toggle() {
5841
+ if (this.element.classList.contains('bw-modal-show')) {
5842
+ this.hide();
5843
+ } else {
5844
+ this.show();
5845
+ }
4658
5846
  return this;
4659
5847
  }
5848
+
5849
+ /** Remove the modal from DOM and clean up */
5850
+ }, {
5851
+ key: "destroy",
5852
+ value: function destroy() {
5853
+ this.hide();
5854
+ if (this._escHandler) {
5855
+ document.removeEventListener('keydown', this._escHandler);
5856
+ }
5857
+ if (this.element.parentNode) {
5858
+ this.element.parentNode.removeChild(this.element);
5859
+ }
5860
+ }
4660
5861
  }]);
4661
5862
  }();
4662
5863
 
4663
5864
  /**
4664
- * Imperative handle for a rendered tabs component
4665
- *
4666
- * Provides programmatic tab switching. Sets up click handlers
4667
- * on tab buttons and manages active states on both buttons and panes.
4668
- * Created automatically when using bw.createTabs().
4669
- *
4670
- * @category Component Handles
5865
+ * Create a modal dialog overlay
5866
+ *
5867
+ * @param {Object} [props] - Modal configuration
5868
+ * @param {string} [props.title] - Modal title in header
5869
+ * @param {string|Object|Array} [props.content] - Modal body content
5870
+ * @param {string|Object|Array} [props.footer] - Modal footer content
5871
+ * @param {string} [props.size] - Modal size ("sm", "lg", "xl")
5872
+ * @param {boolean} [props.closeButton=true] - Show X close button in header
5873
+ * @param {Function} [props.onClose] - Callback when modal is closed
5874
+ * @param {string} [props.className] - Additional CSS classes
5875
+ * @returns {Object} TACO object representing a modal
5876
+ * @category Component Builders
5877
+ * @example
5878
+ * const modal = makeModal({
5879
+ * title: "Confirm",
5880
+ * content: "Are you sure?",
5881
+ * footer: makeButton({ text: "OK", variant: "primary" })
5882
+ * });
4671
5883
  */
4672
- var TabsHandle = /*#__PURE__*/function () {
4673
- /**
4674
- * @param {Element} element - The tabs container DOM element
4675
- * @param {Object} taco - The original TACO object used to create the tabs
4676
- */
4677
- function TabsHandle(element, taco) {
4678
- var _taco$o4;
4679
- _classCallCheck(this, TabsHandle);
4680
- this.element = element;
4681
- this._taco = taco;
4682
- this.state = ((_taco$o4 = taco.o) === null || _taco$o4 === void 0 ? void 0 : _taco$o4.state) || {};
4683
- this.children = {
4684
- navItems: element.querySelectorAll('.bw-nav-link'),
4685
- tabPanes: element.querySelectorAll('.bw-tab-pane')
4686
- };
4687
- this._setupTabs();
5884
+ function makeModal() {
5885
+ var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
5886
+ var title = props.title,
5887
+ content = props.content,
5888
+ footer = props.footer,
5889
+ size = props.size,
5890
+ _props$closeButton = props.closeButton,
5891
+ closeButton = _props$closeButton === void 0 ? true : _props$closeButton,
5892
+ onClose = props.onClose,
5893
+ _props$className22 = props.className,
5894
+ className = _props$className22 === void 0 ? '' : _props$className22;
5895
+ function closeModal(el) {
5896
+ var backdrop = el.closest('.bw-modal');
5897
+ if (backdrop) {
5898
+ backdrop.classList.remove('bw-modal-show');
5899
+ document.body.style.overflow = '';
5900
+ }
5901
+ if (onClose) onClose();
4688
5902
  }
4689
-
4690
- /**
4691
- * Attach click handlers to tab navigation buttons
4692
- * @private
4693
- */
4694
- return _createClass(TabsHandle, [{
4695
- key: "_setupTabs",
4696
- value: function _setupTabs() {
4697
- var _this4 = this;
4698
- this.children.navItems.forEach(function (navItem, index) {
4699
- navItem.onclick = function (e) {
4700
- e.preventDefault();
4701
- _this4.switchTo(index);
5903
+ return {
5904
+ t: 'div',
5905
+ a: {
5906
+ "class": "bw-modal ".concat(className).trim()
5907
+ },
5908
+ c: {
5909
+ t: 'div',
5910
+ a: {
5911
+ "class": "bw-modal-dialog ".concat(size ? 'bw-modal-' + size : '').trim()
5912
+ },
5913
+ c: {
5914
+ t: 'div',
5915
+ a: {
5916
+ "class": 'bw-modal-content'
5917
+ },
5918
+ c: [(title || closeButton) && {
5919
+ t: 'div',
5920
+ a: {
5921
+ "class": 'bw-modal-header'
5922
+ },
5923
+ c: [title && {
5924
+ t: 'h5',
5925
+ a: {
5926
+ "class": 'bw-modal-title'
5927
+ },
5928
+ c: title
5929
+ }, closeButton && {
5930
+ t: 'button',
5931
+ a: {
5932
+ type: 'button',
5933
+ "class": 'bw-close',
5934
+ 'aria-label': 'Close',
5935
+ onclick: function onclick(e) {
5936
+ closeModal(e.target);
5937
+ }
5938
+ },
5939
+ c: "\xD7"
5940
+ }].filter(Boolean)
5941
+ }, content && {
5942
+ t: 'div',
5943
+ a: {
5944
+ "class": 'bw-modal-body'
5945
+ },
5946
+ c: content
5947
+ }, footer && {
5948
+ t: 'div',
5949
+ a: {
5950
+ "class": 'bw-modal-footer'
5951
+ },
5952
+ c: footer
5953
+ }].filter(Boolean)
5954
+ }
5955
+ },
5956
+ o: {
5957
+ type: 'modal',
5958
+ mounted: function mounted(el) {
5959
+ // Click backdrop to close
5960
+ el.addEventListener('click', function (e) {
5961
+ if (e.target === el) closeModal(el);
5962
+ });
5963
+ // Escape key to close
5964
+ var escHandler = function escHandler(e) {
5965
+ if (e.key === 'Escape' && el.classList.contains('bw-modal-show')) {
5966
+ closeModal(el);
5967
+ }
4702
5968
  };
4703
- });
5969
+ document.addEventListener('keydown', escHandler);
5970
+ el._bw_escHandler = escHandler;
5971
+ },
5972
+ unmount: function unmount(el) {
5973
+ if (el._bw_escHandler) {
5974
+ document.removeEventListener('keydown', el._bw_escHandler);
5975
+ }
5976
+ document.body.style.overflow = '';
5977
+ }
4704
5978
  }
5979
+ };
5980
+ }
4705
5981
 
4706
- /**
4707
- * Programmatically switch to a tab by index
4708
- *
4709
- * @param {number} index - Zero-based tab index to activate
4710
- * @returns {TabsHandle} this (for chaining)
4711
- */
4712
- }, {
4713
- key: "switchTo",
4714
- value: function switchTo(index) {
4715
- this.children.navItems.forEach(function (item, i) {
4716
- if (i === index) {
4717
- item.classList.add('active');
4718
- } else {
4719
- item.classList.remove('active');
5982
+ /**
5983
+ * Create a toast notification popup
5984
+ *
5985
+ * @param {Object} [props] - Toast configuration
5986
+ * @param {string} [props.title] - Toast title
5987
+ * @param {string|Object|Array} [props.content] - Toast body content
5988
+ * @param {string} [props.variant="info"] - Color variant ("primary", "success", "danger", "warning", "info")
5989
+ * @param {boolean} [props.autoDismiss=true] - Auto-dismiss after delay
5990
+ * @param {number} [props.delay=5000] - Auto-dismiss delay in ms
5991
+ * @param {string} [props.position="top-right"] - Container position
5992
+ * @param {string} [props.className] - Additional CSS classes
5993
+ * @returns {Object} TACO object representing a toast
5994
+ * @category Component Builders
5995
+ * @example
5996
+ * const toast = makeToast({
5997
+ * title: "Success",
5998
+ * content: "File saved!",
5999
+ * variant: "success"
6000
+ * });
6001
+ */
6002
+ function makeToast() {
6003
+ var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
6004
+ var title = props.title,
6005
+ content = props.content,
6006
+ _props$variant9 = props.variant,
6007
+ variant = _props$variant9 === void 0 ? 'info' : _props$variant9,
6008
+ _props$autoDismiss = props.autoDismiss,
6009
+ autoDismiss = _props$autoDismiss === void 0 ? true : _props$autoDismiss,
6010
+ _props$delay = props.delay,
6011
+ delay = _props$delay === void 0 ? 5000 : _props$delay,
6012
+ _props$position = props.position,
6013
+ position = _props$position === void 0 ? 'top-right' : _props$position,
6014
+ _props$className23 = props.className,
6015
+ className = _props$className23 === void 0 ? '' : _props$className23;
6016
+ return {
6017
+ t: 'div',
6018
+ a: {
6019
+ "class": "bw-toast bw-toast-".concat(variant, " ").concat(className).trim(),
6020
+ role: 'alert',
6021
+ 'data-position': position
6022
+ },
6023
+ c: [title && {
6024
+ t: 'div',
6025
+ a: {
6026
+ "class": 'bw-toast-header'
6027
+ },
6028
+ c: [{
6029
+ t: 'strong',
6030
+ c: title
6031
+ }, {
6032
+ t: 'button',
6033
+ a: {
6034
+ type: 'button',
6035
+ "class": 'bw-close',
6036
+ 'aria-label': 'Close',
6037
+ onclick: function onclick(e) {
6038
+ var toast = e.target.closest('.bw-toast');
6039
+ if (toast) {
6040
+ toast.classList.add('bw-toast-hiding');
6041
+ setTimeout(function () {
6042
+ if (toast.parentNode) toast.parentNode.removeChild(toast);
6043
+ }, 300);
6044
+ }
6045
+ }
6046
+ },
6047
+ c: "\xD7"
6048
+ }]
6049
+ }, content && {
6050
+ t: 'div',
6051
+ a: {
6052
+ "class": 'bw-toast-body'
6053
+ },
6054
+ c: content
6055
+ }].filter(Boolean),
6056
+ o: {
6057
+ type: 'toast',
6058
+ mounted: function mounted(el) {
6059
+ // Trigger show animation
6060
+ requestAnimationFrame(function () {
6061
+ el.classList.add('bw-toast-show');
6062
+ });
6063
+ // Auto-dismiss
6064
+ if (autoDismiss) {
6065
+ setTimeout(function () {
6066
+ el.classList.add('bw-toast-hiding');
6067
+ setTimeout(function () {
6068
+ if (el.parentNode) el.parentNode.removeChild(el);
6069
+ }, 300);
6070
+ }, delay);
4720
6071
  }
4721
- });
4722
- this.children.tabPanes.forEach(function (pane, i) {
4723
- if (i === index) {
4724
- pane.classList.add('active');
4725
- } else {
4726
- pane.classList.remove('active');
6072
+ }
6073
+ }
6074
+ };
6075
+ }
6076
+
6077
+ // =========================================================================
6078
+ // Phase 3: Essential Modern
6079
+ // =========================================================================
6080
+
6081
+ /**
6082
+ * Create a dropdown menu triggered by a button
6083
+ *
6084
+ * @param {Object} [props] - Dropdown configuration
6085
+ * @param {string|Object} [props.trigger] - Button text or TACO for the trigger
6086
+ * @param {Array<Object>} [props.items=[]] - Menu items
6087
+ * @param {string} [props.items[].text] - Item display text
6088
+ * @param {string} [props.items[].href] - Item link URL
6089
+ * @param {Function} [props.items[].onclick] - Item click handler
6090
+ * @param {boolean} [props.items[].divider] - Render as a divider line
6091
+ * @param {boolean} [props.items[].disabled] - Whether the item is disabled
6092
+ * @param {string} [props.align="start"] - Menu alignment ("start" or "end")
6093
+ * @param {string} [props.variant="primary"] - Trigger button variant
6094
+ * @param {string} [props.className] - Additional CSS classes
6095
+ * @returns {Object} TACO object representing a dropdown
6096
+ * @category Component Builders
6097
+ * @example
6098
+ * const dropdown = makeDropdown({
6099
+ * trigger: "Actions",
6100
+ * items: [
6101
+ * { text: "Edit", onclick: () => edit() },
6102
+ * { divider: true },
6103
+ * { text: "Delete", onclick: () => del() }
6104
+ * ]
6105
+ * });
6106
+ */
6107
+ function makeDropdown() {
6108
+ var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
6109
+ var trigger = props.trigger,
6110
+ _props$items6 = props.items,
6111
+ items = _props$items6 === void 0 ? [] : _props$items6,
6112
+ _props$align = props.align,
6113
+ align = _props$align === void 0 ? 'start' : _props$align,
6114
+ _props$variant0 = props.variant,
6115
+ variant = _props$variant0 === void 0 ? 'primary' : _props$variant0,
6116
+ _props$className24 = props.className,
6117
+ className = _props$className24 === void 0 ? '' : _props$className24;
6118
+ var triggerTaco;
6119
+ if (typeof trigger === 'string' || trigger === undefined) {
6120
+ triggerTaco = {
6121
+ t: 'button',
6122
+ a: {
6123
+ "class": "bw-btn bw-btn-".concat(variant, " bw-dropdown-toggle"),
6124
+ type: 'button',
6125
+ onclick: function onclick(e) {
6126
+ var dropdown = e.target.closest('.bw-dropdown');
6127
+ var menu = dropdown.querySelector('.bw-dropdown-menu');
6128
+ menu.classList.toggle('bw-dropdown-show');
6129
+ }
6130
+ },
6131
+ c: trigger || 'Dropdown'
6132
+ };
6133
+ } else {
6134
+ triggerTaco = trigger;
6135
+ }
6136
+ return {
6137
+ t: 'div',
6138
+ a: {
6139
+ "class": "bw-dropdown ".concat(className).trim()
6140
+ },
6141
+ c: [triggerTaco, {
6142
+ t: 'div',
6143
+ a: {
6144
+ "class": "bw-dropdown-menu ".concat(align === 'end' ? 'bw-dropdown-menu-end' : '').trim()
6145
+ },
6146
+ c: items.map(function (item) {
6147
+ if (item.divider) {
6148
+ return {
6149
+ t: 'hr',
6150
+ a: {
6151
+ "class": 'bw-dropdown-divider'
6152
+ }
6153
+ };
6154
+ }
6155
+ return {
6156
+ t: 'a',
6157
+ a: {
6158
+ "class": "bw-dropdown-item ".concat(item.disabled ? 'disabled' : '').trim(),
6159
+ href: item.href || '#',
6160
+ onclick: item.disabled ? undefined : function (e) {
6161
+ if (!item.href) e.preventDefault();
6162
+ var dropdown = e.target.closest('.bw-dropdown');
6163
+ var menu = dropdown.querySelector('.bw-dropdown-menu');
6164
+ menu.classList.remove('bw-dropdown-show');
6165
+ if (item.onclick) item.onclick(e);
6166
+ }
6167
+ },
6168
+ c: item.text
6169
+ };
6170
+ })
6171
+ }],
6172
+ o: {
6173
+ type: 'dropdown',
6174
+ mounted: function mounted(el) {
6175
+ // Click outside to close
6176
+ var outsideHandler = function outsideHandler(e) {
6177
+ if (!el.contains(e.target)) {
6178
+ var menu = el.querySelector('.bw-dropdown-menu');
6179
+ if (menu) menu.classList.remove('bw-dropdown-show');
6180
+ }
6181
+ };
6182
+ document.addEventListener('click', outsideHandler);
6183
+ el._bw_outsideHandler = outsideHandler;
6184
+ },
6185
+ unmount: function unmount(el) {
6186
+ if (el._bw_outsideHandler) {
6187
+ document.removeEventListener('click', el._bw_outsideHandler);
4727
6188
  }
4728
- });
4729
- this.state.activeIndex = index;
4730
- return this;
6189
+ }
4731
6190
  }
4732
- }]);
4733
- }();
6191
+ };
6192
+ }
4734
6193
 
4735
6194
  /**
4736
- * Create a code demo component for documentation pages
4737
- *
4738
- * Displays a live result alongside source code in a tabbed interface.
4739
- * Includes a copy-to-clipboard button on the code tab.
6195
+ * Create a toggle switch (styled checkbox)
4740
6196
  *
4741
- * @param {Object} [props] - Code demo configuration
4742
- * @param {string} [props.title] - Demo title heading
4743
- * @param {string} [props.description] - Demo description text
4744
- * @param {string} [props.code] - Source code to display (adds a "Code" tab when present)
4745
- * @param {string|Object|Array} [props.result] - Live result content for the "Result" tab
4746
- * @param {string} [props.language="javascript"] - Code language for syntax class
4747
- * @returns {Object} TACO object representing a code demo with tabbed Result/Code views
6197
+ * @param {Object} [props] - Switch configuration
6198
+ * @param {string} [props.label] - Switch label text
6199
+ * @param {boolean} [props.checked=false] - Whether the switch is on
6200
+ * @param {string} [props.id] - Element ID (links label to switch)
6201
+ * @param {string} [props.name] - Input name attribute
6202
+ * @param {boolean} [props.disabled=false] - Whether the switch is disabled
6203
+ * @param {string} [props.className] - Additional CSS classes
6204
+ * @returns {Object} TACO object representing a toggle switch
4748
6205
  * @category Component Builders
4749
6206
  * @example
4750
- * const demo = makeCodeDemo({
4751
- * title: "Button Example",
4752
- * description: "A simple primary button",
4753
- * code: 'makeButton({ text: "Click me" })',
4754
- * result: makeButton({ text: "Click me" })
6207
+ * const toggle = makeSwitch({
6208
+ * label: "Dark mode",
6209
+ * checked: false,
6210
+ * onchange: (e) => toggleDark(e.target.checked)
4755
6211
  * });
4756
6212
  */
4757
- function makeCodeDemo() {
6213
+ function makeSwitch() {
4758
6214
  var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
4759
- var title = props.title,
4760
- description = props.description,
4761
- code = props.code,
4762
- result = props.result,
4763
- _props$language = props.language,
4764
- language = _props$language === void 0 ? 'javascript' : _props$language;
6215
+ var label = props.label,
6216
+ _props$checked3 = props.checked,
6217
+ checked = _props$checked3 === void 0 ? false : _props$checked3,
6218
+ id = props.id,
6219
+ name = props.name,
6220
+ _props$disabled7 = props.disabled,
6221
+ disabled = _props$disabled7 === void 0 ? false : _props$disabled7,
6222
+ _props$className25 = props.className,
6223
+ className = _props$className25 === void 0 ? '' : _props$className25,
6224
+ eventHandlers = _objectWithoutProperties(props, _excluded6);
6225
+ return {
6226
+ t: 'div',
6227
+ a: {
6228
+ "class": "bw-form-check bw-form-switch ".concat(className).trim()
6229
+ },
6230
+ c: [{
6231
+ t: 'input',
6232
+ a: _objectSpread2({
6233
+ type: 'checkbox',
6234
+ "class": 'bw-form-check-input bw-switch-input',
6235
+ role: 'switch',
6236
+ checked: checked,
6237
+ id: id,
6238
+ name: name,
6239
+ disabled: disabled
6240
+ }, eventHandlers)
6241
+ }, label && {
6242
+ t: 'label',
6243
+ a: {
6244
+ "class": 'bw-form-check-label',
6245
+ "for": id
6246
+ },
6247
+ c: label
6248
+ }].filter(Boolean)
6249
+ };
6250
+ }
4765
6251
 
4766
- // Generate unique ID for this demo
4767
- var demoId = "demo-".concat(Math.random().toString(36).substr(2, 9));
4768
- var tabs = [{
4769
- label: 'Result',
4770
- active: true,
4771
- content: result
4772
- }];
6252
+ /**
6253
+ * Create a skeleton loading placeholder
6254
+ *
6255
+ * @param {Object} [props] - Skeleton configuration
6256
+ * @param {string} [props.variant="text"] - Shape variant ("text", "circle", "rect")
6257
+ * @param {string} [props.width] - Custom width (e.g. "200px", "100%")
6258
+ * @param {string} [props.height] - Custom height (e.g. "20px")
6259
+ * @param {number} [props.count=1] - Number of skeleton lines (for text variant)
6260
+ * @param {string} [props.className] - Additional CSS classes
6261
+ * @returns {Object} TACO object representing a skeleton placeholder
6262
+ * @category Component Builders
6263
+ * @example
6264
+ * const skeleton = makeSkeleton({ variant: "text", count: 3, width: "100%" });
6265
+ */
6266
+ function makeSkeleton() {
6267
+ var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
6268
+ var _props$variant1 = props.variant,
6269
+ variant = _props$variant1 === void 0 ? 'text' : _props$variant1,
6270
+ width = props.width,
6271
+ height = props.height,
6272
+ _props$count = props.count,
6273
+ count = _props$count === void 0 ? 1 : _props$count,
6274
+ _props$className26 = props.className,
6275
+ className = _props$className26 === void 0 ? '' : _props$className26;
6276
+ if (variant === 'circle') {
6277
+ var circleSize = width || height || '3rem';
6278
+ return {
6279
+ t: 'div',
6280
+ a: {
6281
+ "class": "bw-skeleton bw-skeleton-circle ".concat(className).trim(),
6282
+ style: {
6283
+ width: circleSize,
6284
+ height: circleSize
6285
+ }
6286
+ }
6287
+ };
6288
+ }
6289
+ if (variant === 'rect') {
6290
+ return {
6291
+ t: 'div',
6292
+ a: {
6293
+ "class": "bw-skeleton bw-skeleton-rect ".concat(className).trim(),
6294
+ style: {
6295
+ width: width || '100%',
6296
+ height: height || '120px'
6297
+ }
6298
+ }
6299
+ };
6300
+ }
4773
6301
 
4774
- // Only add Code tab if code is provided
4775
- if (code) {
4776
- tabs.push({
4777
- label: 'Code',
4778
- content: {
4779
- t: 'div',
4780
- a: {
4781
- style: 'position: relative;'
4782
- },
4783
- c: [{
4784
- t: 'button',
4785
- a: {
4786
- "class": 'bw-copy-btn',
4787
- style: 'position: absolute; top: 0.5rem; right: 0.5rem; padding: 0.25rem 0.625rem; font-size: 0.6875rem; background: rgba(255,255,255,0.12); color: #aaa; border: 1px solid rgba(255,255,255,0.15); border-radius: 4px; cursor: pointer; font-family: inherit; transition: all 0.15s;',
4788
- onclick: function onclick(e) {
4789
- navigator.clipboard.writeText(code).then(function () {
4790
- var btn = e.target;
4791
- var originalText = btn.textContent;
4792
- btn.textContent = 'Copied!';
4793
- btn.style.background = '#006666';
4794
- btn.style.color = '#fff';
4795
- setTimeout(function () {
4796
- btn.textContent = originalText;
4797
- btn.style.background = 'rgba(255,255,255,0.12)';
4798
- btn.style.color = '#aaa';
4799
- }, 2000);
4800
- });
4801
- }
4802
- },
4803
- c: 'Copy'
4804
- }, {
4805
- t: 'pre',
4806
- a: {
4807
- style: 'margin: 0; background: #1e293b; border: none; border-radius: 6px; overflow-x: auto;'
4808
- },
4809
- c: {
4810
- t: 'code',
4811
- a: {
4812
- "class": "language-".concat(language),
4813
- style: 'display: block; padding: 1.25rem; font-family: "SF Mono", Monaco, "Cascadia Code", "Roboto Mono", Consolas, "Courier New", monospace; font-size: 0.8125rem; line-height: 1.6; color: #e2e8f0;'
4814
- },
4815
- c: code
4816
- }
4817
- }]
6302
+ // Text variant multiple lines
6303
+ if (count === 1) {
6304
+ return {
6305
+ t: 'div',
6306
+ a: {
6307
+ "class": "bw-skeleton bw-skeleton-text ".concat(className).trim(),
6308
+ style: {
6309
+ width: width || '100%',
6310
+ height: height || '1em'
6311
+ }
6312
+ }
6313
+ };
6314
+ }
6315
+ var lines = [];
6316
+ for (var i = 0; i < count; i++) {
6317
+ lines.push({
6318
+ t: 'div',
6319
+ a: {
6320
+ "class": 'bw-skeleton bw-skeleton-text',
6321
+ style: {
6322
+ width: i === count - 1 ? '75%' : width || '100%',
6323
+ height: height || '1em'
6324
+ }
4818
6325
  }
4819
6326
  });
4820
6327
  }
4821
- var content = [title && {
4822
- t: 'h3',
4823
- c: title
4824
- }, description && {
4825
- t: 'p',
4826
- a: {
4827
- style: 'color: #6c757d; margin-bottom: 1rem;'
4828
- },
4829
- c: description
4830
- }, makeTabs({
4831
- tabs: tabs,
4832
- id: demoId
4833
- })].filter(Boolean);
4834
6328
  return {
4835
6329
  t: 'div',
4836
6330
  a: {
4837
- "class": 'bw-code-demo'
6331
+ "class": "bw-skeleton-group ".concat(className).trim()
4838
6332
  },
4839
- c: content
6333
+ c: lines
4840
6334
  };
4841
6335
  }
4842
6336
 
4843
6337
  /**
4844
- * Registry mapping component type names to their handle classes
4845
- *
4846
- * Used by bw.createCard(), bw.createTable(), etc. to wrap rendered
4847
- * DOM elements in the appropriate imperative handle.
4848
- *
4849
- * @type {Object.<string, Function>}
6338
+ * Create a user avatar with image or initials fallback
6339
+ *
6340
+ * @param {Object} [props] - Avatar configuration
6341
+ * @param {string} [props.src] - Image source URL
6342
+ * @param {string} [props.alt] - Image alt text
6343
+ * @param {string} [props.initials] - Fallback initials (e.g. "JD")
6344
+ * @param {string} [props.size="md"] - Size ("sm", "md", "lg", "xl")
6345
+ * @param {string} [props.variant="primary"] - Background color variant for initials
6346
+ * @param {string} [props.className] - Additional CSS classes
6347
+ * @returns {Object} TACO object representing an avatar
6348
+ * @category Component Builders
6349
+ * @example
6350
+ * const avatar = makeAvatar({ src: "/photo.jpg", alt: "Jane Doe", size: "lg" });
6351
+ * const avatarInitials = makeAvatar({ initials: "JD", variant: "success" });
4850
6352
  */
6353
+ function makeAvatar() {
6354
+ var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
6355
+ var src = props.src,
6356
+ _props$alt = props.alt,
6357
+ alt = _props$alt === void 0 ? '' : _props$alt,
6358
+ initials = props.initials,
6359
+ _props$size3 = props.size,
6360
+ size = _props$size3 === void 0 ? 'md' : _props$size3,
6361
+ _props$variant10 = props.variant,
6362
+ variant = _props$variant10 === void 0 ? 'primary' : _props$variant10,
6363
+ _props$className27 = props.className,
6364
+ className = _props$className27 === void 0 ? '' : _props$className27;
6365
+ if (src) {
6366
+ return {
6367
+ t: 'img',
6368
+ a: {
6369
+ "class": "bw-avatar bw-avatar-".concat(size, " ").concat(className).trim(),
6370
+ src: src,
6371
+ alt: alt
6372
+ }
6373
+ };
6374
+ }
6375
+ return {
6376
+ t: 'div',
6377
+ a: {
6378
+ "class": "bw-avatar bw-avatar-".concat(size, " bw-avatar-").concat(variant, " ").concat(className).trim()
6379
+ },
6380
+ c: initials || ''
6381
+ };
6382
+ }
4851
6383
  var componentHandles = {
4852
6384
  card: CardHandle,
4853
6385
  table: TableHandle,
4854
6386
  navbar: NavbarHandle,
4855
- tabs: TabsHandle
6387
+ tabs: TabsHandle,
6388
+ modal: ModalHandle
4856
6389
  };
4857
6390
 
4858
6391
  var components = /*#__PURE__*/Object.freeze({
4859
6392
  __proto__: null,
4860
6393
  CardHandle: CardHandle,
6394
+ ModalHandle: ModalHandle,
4861
6395
  NavbarHandle: NavbarHandle,
4862
6396
  TableHandle: TableHandle,
4863
6397
  TabsHandle: TabsHandle,
4864
6398
  componentHandles: componentHandles,
6399
+ makeAccordion: makeAccordion,
4865
6400
  makeAlert: makeAlert,
6401
+ makeAvatar: makeAvatar,
4866
6402
  makeBadge: makeBadge,
4867
6403
  makeBreadcrumb: makeBreadcrumb,
4868
6404
  makeButton: makeButton,
6405
+ makeButtonGroup: makeButtonGroup,
4869
6406
  makeCTA: makeCTA,
4870
6407
  makeCard: makeCard,
4871
6408
  makeCheckbox: makeCheckbox,
4872
6409
  makeCodeDemo: makeCodeDemo,
4873
6410
  makeCol: makeCol,
4874
6411
  makeContainer: makeContainer,
6412
+ makeDropdown: makeDropdown,
4875
6413
  makeFeatureGrid: makeFeatureGrid,
4876
6414
  makeForm: makeForm,
4877
6415
  makeFormGroup: makeFormGroup,
4878
6416
  makeHero: makeHero,
4879
6417
  makeInput: makeInput,
4880
6418
  makeListGroup: makeListGroup,
6419
+ makeModal: makeModal,
4881
6420
  makeNav: makeNav,
4882
6421
  makeNavbar: makeNavbar,
6422
+ makePagination: makePagination,
4883
6423
  makeProgress: makeProgress,
6424
+ makeRadio: makeRadio,
4884
6425
  makeRow: makeRow,
4885
6426
  makeSection: makeSection,
4886
6427
  makeSelect: makeSelect,
6428
+ makeSkeleton: makeSkeleton,
4887
6429
  makeSpinner: makeSpinner,
4888
6430
  makeStack: makeStack,
6431
+ makeSwitch: makeSwitch,
4889
6432
  makeTabs: makeTabs,
4890
- makeTextarea: makeTextarea
6433
+ makeTextarea: makeTextarea,
6434
+ makeToast: makeToast
4891
6435
  });
4892
6436
 
4893
- var _excluded = ["title", "data", "columns", "className", "responsive"];
6437
+ var _excluded = ["data", "headerRow", "columns"],
6438
+ _excluded2 = ["title", "data", "columns", "className", "striped", "hover", "responsive"];
4894
6439
 
4895
6440
  // Environment-aware module loader for optional Node.js built-ins (fs).
4896
6441
  // Strategy: try require() first (CJS/UMD), fall back to import() (ESM).
@@ -6014,6 +7559,16 @@
6014
7559
  if (attr) {
6015
7560
  // Patch an attribute
6016
7561
  el.setAttribute(attr, String(content));
7562
+ } else if (Array.isArray(content)) {
7563
+ // Patch with array of children (strings and/or TACOs)
7564
+ el.innerHTML = '';
7565
+ content.forEach(function (item) {
7566
+ if (typeof item === 'string' || typeof item === 'number') {
7567
+ el.appendChild(document.createTextNode(String(item)));
7568
+ } else if (item && item.t) {
7569
+ el.appendChild(bw.createDOM(item));
7570
+ }
7571
+ });
6017
7572
  } else if (_typeof(content) === 'object' && content !== null && content.t) {
6018
7573
  // Patch with a TACO — replace children
6019
7574
  el.innerHTML = '';
@@ -7395,6 +8950,7 @@
7395
8950
  */
7396
8951
  bw.htmlTable = function (data) {
7397
8952
  var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
8953
+ console.warn('bw.htmlTable() is deprecated. Use bw.makeTableFromArray() for TACO output or bw.makeTable() for object-array data.');
7398
8954
  if (bw.typeOf(data) !== "array" || data.length < 1) return "";
7399
8955
  var dopts = {
7400
8956
  useFirstRowAsHeaders: true,
@@ -7485,6 +9041,7 @@
7485
9041
  */
7486
9042
  bw.htmlTabs = function (tabData) {
7487
9043
  var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
9044
+ console.warn('bw.htmlTabs() is deprecated. Use bw.makeTabs() instead.');
7488
9045
  if (bw.typeOf(tabData) !== "array" || tabData.length < 1) return "";
7489
9046
  var dopts = {
7490
9047
  atr: {
@@ -7545,6 +9102,7 @@
7545
9102
  * @category Legacy (v1)
7546
9103
  */
7547
9104
  bw.selectTabContent = function (tabElement) {
9105
+ console.warn('bw.selectTabContent() is deprecated. Use bw.makeTabs() instead.');
7548
9106
  if (!bw._isBrowser || !tabElement) return;
7549
9107
  var container = tabElement.closest(".bw-tab-container");
7550
9108
  if (!container) return;
@@ -8096,7 +9654,11 @@
8096
9654
  data = _config$data === void 0 ? [] : _config$data,
8097
9655
  columns = config.columns,
8098
9656
  _config$className = config.className,
8099
- className = _config$className === void 0 ? "table" : _config$className,
9657
+ className = _config$className === void 0 ? '' : _config$className,
9658
+ _config$striped = config.striped,
9659
+ striped = _config$striped === void 0 ? false : _config$striped,
9660
+ _config$hover = config.hover,
9661
+ hover = _config$hover === void 0 ? false : _config$hover,
8100
9662
  _config$sortable = config.sortable,
8101
9663
  sortable = _config$sortable === void 0 ? true : _config$sortable,
8102
9664
  onSort = config.onSort,
@@ -8104,6 +9666,13 @@
8104
9666
  _config$sortDirection = config.sortDirection,
8105
9667
  sortDirection = _config$sortDirection === void 0 ? 'asc' : _config$sortDirection;
8106
9668
 
9669
+ // Build class list: always include bw-table, add striped/hover, append user className
9670
+ var cls = 'bw-table';
9671
+ if (striped) cls += ' bw-table-striped';
9672
+ if (hover) cls += ' bw-table-hover';
9673
+ if (className) cls += ' ' + className;
9674
+ cls = cls.trim();
9675
+
8107
9676
  // Auto-detect columns if not provided
8108
9677
  var cols = columns || (data.length > 0 ? Object.keys(data[0]).map(function (key) {
8109
9678
  return {
@@ -8202,12 +9771,227 @@
8202
9771
  return {
8203
9772
  t: 'table',
8204
9773
  a: {
8205
- "class": className
9774
+ "class": cls
8206
9775
  },
8207
9776
  c: [thead, tbody]
8208
9777
  };
8209
9778
  };
8210
9779
 
9780
+ /**
9781
+ * Create a table from a 2D array.
9782
+ *
9783
+ * Converts a 2D array into the object-array format that `bw.makeTable()`
9784
+ * expects, then delegates. By default, the first row is used as column
9785
+ * headers. All standard `makeTable` props (striped, hover, sortable,
9786
+ * columns, onSort, etc.) are passed through.
9787
+ *
9788
+ * @param {Object} config - Configuration object
9789
+ * @param {Array<Array>} config.data - 2D array of values
9790
+ * @param {boolean} [config.headerRow=true] - Treat first row as column headers
9791
+ * @param {boolean} [config.striped=false] - Striped rows
9792
+ * @param {boolean} [config.hover=false] - Hover highlight
9793
+ * @param {boolean} [config.sortable=true] - Enable sort
9794
+ * @param {Array<Object>} [config.columns] - Override auto-generated column defs
9795
+ * @param {string} [config.className=''] - Additional CSS classes
9796
+ * @param {Function} [config.onSort] - Sort callback
9797
+ * @param {string} [config.sortColumn] - Currently sorted column key
9798
+ * @param {string} [config.sortDirection='asc'] - Sort direction
9799
+ * @returns {Object} TACO object for table
9800
+ * @category Component Builders
9801
+ * @see bw.makeTable
9802
+ * @example
9803
+ * bw.makeTableFromArray({
9804
+ * data: [
9805
+ * ['Name', 'Role', 'Status'],
9806
+ * ['Alice', 'Engineer', 'Active'],
9807
+ * ['Bob', 'Designer', 'Away']
9808
+ * ],
9809
+ * striped: true,
9810
+ * hover: true
9811
+ * });
9812
+ */
9813
+ bw.makeTableFromArray = function (config) {
9814
+ var _config$data2 = config.data,
9815
+ data = _config$data2 === void 0 ? [] : _config$data2,
9816
+ _config$headerRow = config.headerRow,
9817
+ headerRow = _config$headerRow === void 0 ? true : _config$headerRow,
9818
+ columns = config.columns,
9819
+ rest = _objectWithoutProperties(config, _excluded);
9820
+ if (!Array.isArray(data) || data.length === 0) {
9821
+ return bw.makeTable(_objectSpread2({
9822
+ data: [],
9823
+ columns: columns || []
9824
+ }, rest));
9825
+ }
9826
+
9827
+ // Determine headers
9828
+ var headers;
9829
+ var rows;
9830
+ if (headerRow && data.length > 0) {
9831
+ headers = data[0].map(function (h) {
9832
+ return String(h);
9833
+ });
9834
+ rows = data.slice(1);
9835
+ } else {
9836
+ // Generate col0, col1, ... headers
9837
+ var width = data[0].length;
9838
+ headers = [];
9839
+ for (var i = 0; i < width; i++) {
9840
+ headers.push('col' + i);
9841
+ }
9842
+ rows = data;
9843
+ }
9844
+
9845
+ // Convert rows to object arrays
9846
+ var objData = rows.map(function (row) {
9847
+ var obj = {};
9848
+ headers.forEach(function (key, i) {
9849
+ obj[key] = row[i] !== undefined ? row[i] : '';
9850
+ });
9851
+ return obj;
9852
+ });
9853
+
9854
+ // Auto-generate column defs if not provided
9855
+ var cols = columns || headers.map(function (key) {
9856
+ return {
9857
+ key: key,
9858
+ label: key
9859
+ };
9860
+ });
9861
+ return bw.makeTable(_objectSpread2({
9862
+ data: objData,
9863
+ columns: cols
9864
+ }, rest));
9865
+ };
9866
+
9867
+ /**
9868
+ * Create a vertical bar chart from data.
9869
+ *
9870
+ * Renders a pure-CSS bar chart using flexbox and percentage heights.
9871
+ * No canvas, SVG, or external charting library required.
9872
+ *
9873
+ * @param {Object} config - Chart configuration
9874
+ * @param {Array<Object>} config.data - Array of data objects
9875
+ * @param {string} [config.labelKey='label'] - Key for bar labels
9876
+ * @param {string} [config.valueKey='value'] - Key for bar values
9877
+ * @param {string} [config.title] - Chart title
9878
+ * @param {string} [config.color='#006666'] - Bar color (hex or CSS color)
9879
+ * @param {string} [config.height='200px'] - Height of the chart area
9880
+ * @param {Function} [config.formatValue] - Value label formatter: (value) => string
9881
+ * @param {boolean} [config.showValues=true] - Show value labels above bars
9882
+ * @param {boolean} [config.showLabels=true] - Show labels below bars
9883
+ * @param {string} [config.className=''] - Additional CSS classes
9884
+ * @returns {Object} TACO object
9885
+ * @category Component Builders
9886
+ * @example
9887
+ * bw.makeBarChart({
9888
+ * data: [
9889
+ * { label: 'Jan', value: 12400 },
9890
+ * { label: 'Feb', value: 15800 },
9891
+ * { label: 'Mar', value: 9200 }
9892
+ * ],
9893
+ * title: 'Monthly Revenue',
9894
+ * color: '#0077b6',
9895
+ * formatValue: (v) => '$' + (v / 1000).toFixed(1) + 'k'
9896
+ * });
9897
+ */
9898
+ bw.makeBarChart = function (config) {
9899
+ var _config$data3 = config.data,
9900
+ data = _config$data3 === void 0 ? [] : _config$data3,
9901
+ _config$labelKey = config.labelKey,
9902
+ labelKey = _config$labelKey === void 0 ? 'label' : _config$labelKey,
9903
+ _config$valueKey = config.valueKey,
9904
+ valueKey = _config$valueKey === void 0 ? 'value' : _config$valueKey,
9905
+ title = config.title,
9906
+ _config$color = config.color,
9907
+ color = _config$color === void 0 ? '#006666' : _config$color,
9908
+ _config$height = config.height,
9909
+ height = _config$height === void 0 ? '200px' : _config$height,
9910
+ formatValue = config.formatValue,
9911
+ _config$showValues = config.showValues,
9912
+ showValues = _config$showValues === void 0 ? true : _config$showValues,
9913
+ _config$showLabels = config.showLabels,
9914
+ showLabels = _config$showLabels === void 0 ? true : _config$showLabels,
9915
+ _config$className2 = config.className,
9916
+ className = _config$className2 === void 0 ? '' : _config$className2;
9917
+ if (!Array.isArray(data) || data.length === 0) {
9918
+ return {
9919
+ t: 'div',
9920
+ a: {
9921
+ "class": ('bw-bar-chart-container ' + className).trim()
9922
+ },
9923
+ c: ''
9924
+ };
9925
+ }
9926
+ var values = data.map(function (d) {
9927
+ return Number(d[valueKey]) || 0;
9928
+ });
9929
+ var maxVal = Math.max.apply(null, values);
9930
+ var bars = data.map(function (d, i) {
9931
+ var val = values[i];
9932
+ var pct = maxVal > 0 ? val / maxVal * 100 : 0;
9933
+ var formatted = formatValue ? formatValue(val) : String(val);
9934
+ var children = [];
9935
+ if (showValues) {
9936
+ children.push({
9937
+ t: 'div',
9938
+ a: {
9939
+ "class": 'bw-bar-value'
9940
+ },
9941
+ c: formatted
9942
+ });
9943
+ }
9944
+ children.push({
9945
+ t: 'div',
9946
+ a: {
9947
+ "class": 'bw-bar',
9948
+ style: 'height:' + pct + '%;background:' + color + ';'
9949
+ }
9950
+ });
9951
+ if (showLabels) {
9952
+ children.push({
9953
+ t: 'div',
9954
+ a: {
9955
+ "class": 'bw-bar-label'
9956
+ },
9957
+ c: String(d[labelKey] || '')
9958
+ });
9959
+ }
9960
+ return {
9961
+ t: 'div',
9962
+ a: {
9963
+ "class": 'bw-bar-group'
9964
+ },
9965
+ c: children
9966
+ };
9967
+ });
9968
+ var chartChildren = [];
9969
+ if (title) {
9970
+ chartChildren.push({
9971
+ t: 'h3',
9972
+ a: {
9973
+ "class": 'bw-bar-chart-title'
9974
+ },
9975
+ c: title
9976
+ });
9977
+ }
9978
+ chartChildren.push({
9979
+ t: 'div',
9980
+ a: {
9981
+ "class": 'bw-bar-chart',
9982
+ style: 'height:' + height + ';'
9983
+ },
9984
+ c: bars
9985
+ });
9986
+ return {
9987
+ t: 'div',
9988
+ a: {
9989
+ "class": ('bw-bar-chart-container ' + className).trim()
9990
+ },
9991
+ c: chartChildren
9992
+ };
9993
+ };
9994
+
8211
9995
  /**
8212
9996
  * Create a responsive data table with title and optional wrapper
8213
9997
  *
@@ -8218,7 +10002,9 @@
8218
10002
  * @param {string} [config.title] - Table title heading
8219
10003
  * @param {Array<Object>} config.data - Array of row objects
8220
10004
  * @param {Array<Object>} [config.columns] - Column definitions
8221
- * @param {string} [config.className="table table-striped table-hover"] - Table CSS class
10005
+ * @param {string} [config.className=''] - Additional CSS classes for the table
10006
+ * @param {boolean} [config.striped=true] - Add striped row styling
10007
+ * @param {boolean} [config.hover=true] - Add hover row highlighting
8222
10008
  * @param {boolean} [config.responsive=true] - Wrap table in responsive overflow div
8223
10009
  * @returns {Object} TACO object for table with wrapper
8224
10010
  * @example
@@ -8232,15 +10018,21 @@
8232
10018
  var title = config.title,
8233
10019
  data = config.data,
8234
10020
  columns = config.columns,
8235
- _config$className2 = config.className,
8236
- className = _config$className2 === void 0 ? "table table-striped table-hover" : _config$className2,
10021
+ _config$className3 = config.className,
10022
+ className = _config$className3 === void 0 ? '' : _config$className3,
10023
+ _config$striped2 = config.striped,
10024
+ striped = _config$striped2 === void 0 ? true : _config$striped2,
10025
+ _config$hover2 = config.hover,
10026
+ hover = _config$hover2 === void 0 ? true : _config$hover2,
8237
10027
  _config$responsive = config.responsive,
8238
10028
  responsive = _config$responsive === void 0 ? true : _config$responsive,
8239
- tableConfig = _objectWithoutProperties(config, _excluded);
10029
+ tableConfig = _objectWithoutProperties(config, _excluded2);
8240
10030
  var table = bw.makeTable(_objectSpread2({
8241
10031
  data: data,
8242
10032
  columns: columns,
8243
- className: className
10033
+ className: className,
10034
+ striped: striped,
10035
+ hover: hover
8244
10036
  }, tableConfig));
8245
10037
  var content = [];
8246
10038
  if (title) {