@kodaris/krubble-app-components 1.0.13 → 1.0.15

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.
@@ -1400,6 +1400,34 @@ let KRScaffold = class KRScaffold extends i$1 {
1400
1400
  this.originalXhrOpen = null;
1401
1401
  }
1402
1402
  }
1403
+ /**
1404
+ * Resolves a navigation URL by prepending the base href.
1405
+ *
1406
+ * This method is used for:
1407
+ * 1. Setting href attributes on anchor elements (so Cmd/Ctrl+click opens correct URL in new tab)
1408
+ * 2. Comparing URLs with window.location.pathname in updateActiveNavItem()
1409
+ *
1410
+ * The original item.url is kept intact (without base href) and passed to Angular
1411
+ * via the nav-item-click event. Angular Router expects paths relative to base,
1412
+ * so it handles the base href internally.
1413
+ *
1414
+ * Example with base href "/operations/":
1415
+ * - item.url = "/settings" (used for Angular routing)
1416
+ * - resolveUrl(item) = "/operations/settings" (used for href and URL comparison)
1417
+ */
1418
+ resolveUrl(item) {
1419
+ if (!item.url)
1420
+ return '#';
1421
+ // External URLs - return as-is
1422
+ if (item.external) {
1423
+ return item.url;
1424
+ }
1425
+ // Remove leading slash from url if present, then combine with base
1426
+ const path = item.url.startsWith('/') ? item.url.slice(1) : item.url;
1427
+ const baseHref = document.querySelector('base')?.getAttribute('href') || '/';
1428
+ const base = baseHref.endsWith('/') ? baseHref : (baseHref + '/');
1429
+ return base + path;
1430
+ }
1403
1431
  // =========================================================================
1404
1432
  // Navigation Data
1405
1433
  // =========================================================================
@@ -1475,6 +1503,14 @@ let KRScaffold = class KRScaffold extends i$1 {
1475
1503
  if (this.navQuery) {
1476
1504
  const query = this.navQuery.toLowerCase();
1477
1505
  const allItems = this.getComputedNav();
1506
+ // If we're getting children of a group, check if parent group name matches query
1507
+ // If so, show all children without filtering
1508
+ if (parentId !== null) {
1509
+ const parentGroup = allItems.find(item => item.id === parentId);
1510
+ if (parentGroup?.label.toLowerCase().includes(query)) {
1511
+ return items; // Show all children when group name matches
1512
+ }
1513
+ }
1478
1514
  items = items.filter(item => {
1479
1515
  if (item.type === 'group') {
1480
1516
  // Show group if its label matches OR if it has matching children
@@ -1533,7 +1569,7 @@ let KRScaffold = class KRScaffold extends i$1 {
1533
1569
  * Handles click on the nav header (logo/title) to navigate home.
1534
1570
  * Dispatches a nav-item-click event so Angular can intercept and route.
1535
1571
  */
1536
- handleNavHeaderClick(_e) {
1572
+ handleNavHeaderClick() {
1537
1573
  // Clear active state since we're going home
1538
1574
  this.activeNavItemId = null;
1539
1575
  const navEvent = new CustomEvent('nav-item-click', {
@@ -1609,6 +1645,10 @@ let KRScaffold = class KRScaffold extends i$1 {
1609
1645
  this.toggleNavItem(item.id);
1610
1646
  }
1611
1647
  else {
1648
+ // Allow Ctrl/Cmd+click and middle-click to open in new tab without SPA navigation
1649
+ if (e.ctrlKey || e.metaKey || e.button === 1) {
1650
+ return;
1651
+ }
1612
1652
  // Set active item immediately on click for instant visual feedback
1613
1653
  this.activeNavItemId = item.id;
1614
1654
  const navEvent = new CustomEvent('nav-item-click', {
@@ -1641,7 +1681,8 @@ let KRScaffold = class KRScaffold extends i$1 {
1641
1681
  let activeItem = null;
1642
1682
  let longestMatch = 0;
1643
1683
  for (const item of allItems) {
1644
- const url = item.url; // We filtered for items with url above
1684
+ // Use resolveUrl because currentPath includes base href
1685
+ const url = this.resolveUrl(item);
1645
1686
  if (currentPath.startsWith(url) && url.length > longestMatch) {
1646
1687
  activeItem = item;
1647
1688
  longestMatch = url.length;
@@ -2216,7 +2257,7 @@ let KRScaffold = class KRScaffold extends i$1 {
2216
2257
  'nav-item--drop-below': this.navItemDropTargetId === item.id && this.navItemDropPosition === 'below',
2217
2258
  })}
2218
2259
  data-id="${item.id}"
2219
- href=${item.url || '#'}
2260
+ href=${this.resolveUrl(item)}
2220
2261
  target=${item.external ? '_blank' : A}
2221
2262
  @mousedown=${(e) => this.handleNavItemMouseDown(e, item)}
2222
2263
  @click=${(e) => this.handleNavItemClick(e, item)}
@@ -2325,9 +2366,8 @@ KRScaffold.styles = i$4 `
2325
2366
  --kr-scaffold-nav-active-bg: #e5e7eb;
2326
2367
  --kr-scaffold-nav-border: rgb(229, 229, 228);
2327
2368
  --kr-scaffold-nav-divider: #e5e7eb;
2328
- --kr-scaffold-nav-search-bg: #f3f4f6;
2329
- --kr-scaffold-nav-search-focus-bg: #ffffff;
2330
- --kr-scaffold-nav-search-focus-border: #d1d5db;
2369
+ --kr-scaffold-nav-search-bg: #ffffff;
2370
+ --kr-scaffold-nav-search-border: #d1d5db;
2331
2371
  }
2332
2372
 
2333
2373
  /* Dark scheme */
@@ -2340,8 +2380,7 @@ KRScaffold.styles = i$4 `
2340
2380
  --kr-scaffold-nav-border: transparent;
2341
2381
  --kr-scaffold-nav-divider: rgba(255, 255, 255, 0.06);
2342
2382
  --kr-scaffold-nav-search-bg: rgba(255, 255, 255, 0.15);
2343
- --kr-scaffold-nav-search-focus-bg: rgba(255, 255, 255, 0.2);
2344
- --kr-scaffold-nav-search-focus-border: rgba(255, 255, 255, 0.3);
2383
+ --kr-scaffold-nav-search-border: rgba(255, 255, 255, 0.3);
2345
2384
  }
2346
2385
 
2347
2386
  *,
@@ -2419,15 +2458,10 @@ KRScaffold.styles = i$4 `
2419
2458
  padding: 0 12px;
2420
2459
  height: 40px;
2421
2460
  gap: 8px;
2422
- border: 1px solid transparent;
2461
+ border: 1px solid var(--kr-scaffold-nav-search-border);
2423
2462
  transition: all 0.15s ease;
2424
2463
  }
2425
2464
 
2426
- .nav-search__wrapper:focus-within {
2427
- background: var(--kr-scaffold-nav-search-focus-bg);
2428
- border-color: var(--kr-scaffold-nav-search-focus-border);
2429
- }
2430
-
2431
2465
  .nav-search__icon {
2432
2466
  width: 18px;
2433
2467
  height: 18px;
@@ -3536,6 +3570,29 @@ let KRSubbar = class KRSubbar extends i$1 {
3536
3570
  _handleMenuClick() {
3537
3571
  this.dispatchEvent(new CustomEvent('menu-click', { bubbles: true, composed: true }));
3538
3572
  }
3573
+ /**
3574
+ * Resolves a breadcrumb URL by prepending the base href.
3575
+ *
3576
+ * This method is used for setting href attributes on anchor elements
3577
+ * (so Cmd/Ctrl+click opens correct URL in new tab).
3578
+ *
3579
+ * The original crumb.url is kept intact (without base href) and passed to Angular
3580
+ * via the breadcrumb-click event. Angular Router expects paths relative to base,
3581
+ * so it handles the base href internally.
3582
+ *
3583
+ * Example with base href "/operations/":
3584
+ * - crumb.url = "/settings" (used for Angular routing)
3585
+ * - resolveUrl(crumb) = "/operations/settings" (used for href)
3586
+ */
3587
+ resolveUrl(crumb) {
3588
+ if (!crumb.url)
3589
+ return '#';
3590
+ // Remove leading slash from url if present, then combine with base
3591
+ const path = crumb.url.startsWith('/') ? crumb.url.slice(1) : crumb.url;
3592
+ const baseHref = document.querySelector('base')?.getAttribute('href') || '/';
3593
+ const base = baseHref.endsWith('/') ? baseHref : (baseHref + '/');
3594
+ return base + path;
3595
+ }
3539
3596
  /**
3540
3597
  * Handles click on a breadcrumb link.
3541
3598
  * Dispatches a cancelable event so SPA routers can intercept.
@@ -3546,6 +3603,10 @@ let KRSubbar = class KRSubbar extends i$1 {
3546
3603
  e.preventDefault();
3547
3604
  return;
3548
3605
  }
3606
+ // Allow Ctrl/Cmd+click and middle-click to open in new tab without SPA navigation
3607
+ if (e.ctrlKey || e.metaKey || e.button === 1) {
3608
+ return;
3609
+ }
3549
3610
  const breadcrumbEvent = new CustomEvent('breadcrumb-click', {
3550
3611
  detail: { breadcrumb: crumb },
3551
3612
  bubbles: true,
@@ -3576,7 +3637,7 @@ let KRSubbar = class KRSubbar extends i$1 {
3576
3637
  ${index > 0 ? b `<span class="breadcrumb-separator">/</span>` : ''}
3577
3638
  <a
3578
3639
  class=${e$1({ 'breadcrumb': true, 'breadcrumb--current': isCurrent })}
3579
- href=${crumb.url || ''}
3640
+ href=${this.resolveUrl(crumb)}
3580
3641
  @click=${(e) => this._handleBreadcrumbClick(e, crumb, isCurrent)}
3581
3642
  >${crumb.label}</a>
3582
3643
  `;
@@ -3600,6 +3661,7 @@ KRSubbar.styles = i$4 `
3600
3661
  align-items: center;
3601
3662
  padding: 0 16px;
3602
3663
  width: 100%;
3664
+ flex-shrink: 0;
3603
3665
  }
3604
3666
 
3605
3667
  .breadcrumbs {