@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.
- package/dist/krubble-app.bundled.js +77 -15
- package/dist/krubble-app.bundled.js.map +1 -1
- package/dist/krubble-app.bundled.min.js +35 -41
- package/dist/krubble-app.bundled.min.js.map +1 -1
- package/dist/krubble-app.umd.js +77 -15
- package/dist/krubble-app.umd.js.map +1 -1
- package/dist/krubble-app.umd.min.js +38 -44
- package/dist/krubble-app.umd.min.js.map +1 -1
- package/dist/scaffold.d.ts +16 -0
- package/dist/scaffold.d.ts.map +1 -1
- package/dist/scaffold.js +48 -14
- package/dist/scaffold.js.map +1 -1
- package/dist/subbar.d.ts +15 -0
- package/dist/subbar.d.ts.map +1 -1
- package/dist/subbar.js +29 -1
- package/dist/subbar.js.map +1 -1
- package/package.json +1 -1
package/dist/krubble-app.umd.js
CHANGED
|
@@ -1403,6 +1403,34 @@
|
|
|
1403
1403
|
this.originalXhrOpen = null;
|
|
1404
1404
|
}
|
|
1405
1405
|
}
|
|
1406
|
+
/**
|
|
1407
|
+
* Resolves a navigation URL by prepending the base href.
|
|
1408
|
+
*
|
|
1409
|
+
* This method is used for:
|
|
1410
|
+
* 1. Setting href attributes on anchor elements (so Cmd/Ctrl+click opens correct URL in new tab)
|
|
1411
|
+
* 2. Comparing URLs with window.location.pathname in updateActiveNavItem()
|
|
1412
|
+
*
|
|
1413
|
+
* The original item.url is kept intact (without base href) and passed to Angular
|
|
1414
|
+
* via the nav-item-click event. Angular Router expects paths relative to base,
|
|
1415
|
+
* so it handles the base href internally.
|
|
1416
|
+
*
|
|
1417
|
+
* Example with base href "/operations/":
|
|
1418
|
+
* - item.url = "/settings" (used for Angular routing)
|
|
1419
|
+
* - resolveUrl(item) = "/operations/settings" (used for href and URL comparison)
|
|
1420
|
+
*/
|
|
1421
|
+
resolveUrl(item) {
|
|
1422
|
+
if (!item.url)
|
|
1423
|
+
return '#';
|
|
1424
|
+
// External URLs - return as-is
|
|
1425
|
+
if (item.external) {
|
|
1426
|
+
return item.url;
|
|
1427
|
+
}
|
|
1428
|
+
// Remove leading slash from url if present, then combine with base
|
|
1429
|
+
const path = item.url.startsWith('/') ? item.url.slice(1) : item.url;
|
|
1430
|
+
const baseHref = document.querySelector('base')?.getAttribute('href') || '/';
|
|
1431
|
+
const base = baseHref.endsWith('/') ? baseHref : (baseHref + '/');
|
|
1432
|
+
return base + path;
|
|
1433
|
+
}
|
|
1406
1434
|
// =========================================================================
|
|
1407
1435
|
// Navigation Data
|
|
1408
1436
|
// =========================================================================
|
|
@@ -1478,6 +1506,14 @@
|
|
|
1478
1506
|
if (this.navQuery) {
|
|
1479
1507
|
const query = this.navQuery.toLowerCase();
|
|
1480
1508
|
const allItems = this.getComputedNav();
|
|
1509
|
+
// If we're getting children of a group, check if parent group name matches query
|
|
1510
|
+
// If so, show all children without filtering
|
|
1511
|
+
if (parentId !== null) {
|
|
1512
|
+
const parentGroup = allItems.find(item => item.id === parentId);
|
|
1513
|
+
if (parentGroup?.label.toLowerCase().includes(query)) {
|
|
1514
|
+
return items; // Show all children when group name matches
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1481
1517
|
items = items.filter(item => {
|
|
1482
1518
|
if (item.type === 'group') {
|
|
1483
1519
|
// Show group if its label matches OR if it has matching children
|
|
@@ -1536,7 +1572,7 @@
|
|
|
1536
1572
|
* Handles click on the nav header (logo/title) to navigate home.
|
|
1537
1573
|
* Dispatches a nav-item-click event so Angular can intercept and route.
|
|
1538
1574
|
*/
|
|
1539
|
-
handleNavHeaderClick(
|
|
1575
|
+
handleNavHeaderClick() {
|
|
1540
1576
|
// Clear active state since we're going home
|
|
1541
1577
|
this.activeNavItemId = null;
|
|
1542
1578
|
const navEvent = new CustomEvent('nav-item-click', {
|
|
@@ -1612,6 +1648,10 @@
|
|
|
1612
1648
|
this.toggleNavItem(item.id);
|
|
1613
1649
|
}
|
|
1614
1650
|
else {
|
|
1651
|
+
// Allow Ctrl/Cmd+click and middle-click to open in new tab without SPA navigation
|
|
1652
|
+
if (e.ctrlKey || e.metaKey || e.button === 1) {
|
|
1653
|
+
return;
|
|
1654
|
+
}
|
|
1615
1655
|
// Set active item immediately on click for instant visual feedback
|
|
1616
1656
|
this.activeNavItemId = item.id;
|
|
1617
1657
|
const navEvent = new CustomEvent('nav-item-click', {
|
|
@@ -1644,7 +1684,8 @@
|
|
|
1644
1684
|
let activeItem = null;
|
|
1645
1685
|
let longestMatch = 0;
|
|
1646
1686
|
for (const item of allItems) {
|
|
1647
|
-
|
|
1687
|
+
// Use resolveUrl because currentPath includes base href
|
|
1688
|
+
const url = this.resolveUrl(item);
|
|
1648
1689
|
if (currentPath.startsWith(url) && url.length > longestMatch) {
|
|
1649
1690
|
activeItem = item;
|
|
1650
1691
|
longestMatch = url.length;
|
|
@@ -2219,7 +2260,7 @@
|
|
|
2219
2260
|
'nav-item--drop-below': this.navItemDropTargetId === item.id && this.navItemDropPosition === 'below',
|
|
2220
2261
|
})}
|
|
2221
2262
|
data-id="${item.id}"
|
|
2222
|
-
href=${item
|
|
2263
|
+
href=${this.resolveUrl(item)}
|
|
2223
2264
|
target=${item.external ? '_blank' : A}
|
|
2224
2265
|
@mousedown=${(e) => this.handleNavItemMouseDown(e, item)}
|
|
2225
2266
|
@click=${(e) => this.handleNavItemClick(e, item)}
|
|
@@ -2328,9 +2369,8 @@
|
|
|
2328
2369
|
--kr-scaffold-nav-active-bg: #e5e7eb;
|
|
2329
2370
|
--kr-scaffold-nav-border: rgb(229, 229, 228);
|
|
2330
2371
|
--kr-scaffold-nav-divider: #e5e7eb;
|
|
2331
|
-
--kr-scaffold-nav-search-bg: #
|
|
2332
|
-
--kr-scaffold-nav-search-
|
|
2333
|
-
--kr-scaffold-nav-search-focus-border: #d1d5db;
|
|
2372
|
+
--kr-scaffold-nav-search-bg: #ffffff;
|
|
2373
|
+
--kr-scaffold-nav-search-border: #d1d5db;
|
|
2334
2374
|
}
|
|
2335
2375
|
|
|
2336
2376
|
/* Dark scheme */
|
|
@@ -2343,8 +2383,7 @@
|
|
|
2343
2383
|
--kr-scaffold-nav-border: transparent;
|
|
2344
2384
|
--kr-scaffold-nav-divider: rgba(255, 255, 255, 0.06);
|
|
2345
2385
|
--kr-scaffold-nav-search-bg: rgba(255, 255, 255, 0.15);
|
|
2346
|
-
--kr-scaffold-nav-search-
|
|
2347
|
-
--kr-scaffold-nav-search-focus-border: rgba(255, 255, 255, 0.3);
|
|
2386
|
+
--kr-scaffold-nav-search-border: rgba(255, 255, 255, 0.3);
|
|
2348
2387
|
}
|
|
2349
2388
|
|
|
2350
2389
|
*,
|
|
@@ -2422,15 +2461,10 @@
|
|
|
2422
2461
|
padding: 0 12px;
|
|
2423
2462
|
height: 40px;
|
|
2424
2463
|
gap: 8px;
|
|
2425
|
-
border: 1px solid
|
|
2464
|
+
border: 1px solid var(--kr-scaffold-nav-search-border);
|
|
2426
2465
|
transition: all 0.15s ease;
|
|
2427
2466
|
}
|
|
2428
2467
|
|
|
2429
|
-
.nav-search__wrapper:focus-within {
|
|
2430
|
-
background: var(--kr-scaffold-nav-search-focus-bg);
|
|
2431
|
-
border-color: var(--kr-scaffold-nav-search-focus-border);
|
|
2432
|
-
}
|
|
2433
|
-
|
|
2434
2468
|
.nav-search__icon {
|
|
2435
2469
|
width: 18px;
|
|
2436
2470
|
height: 18px;
|
|
@@ -3539,6 +3573,29 @@
|
|
|
3539
3573
|
_handleMenuClick() {
|
|
3540
3574
|
this.dispatchEvent(new CustomEvent('menu-click', { bubbles: true, composed: true }));
|
|
3541
3575
|
}
|
|
3576
|
+
/**
|
|
3577
|
+
* Resolves a breadcrumb URL by prepending the base href.
|
|
3578
|
+
*
|
|
3579
|
+
* This method is used for setting href attributes on anchor elements
|
|
3580
|
+
* (so Cmd/Ctrl+click opens correct URL in new tab).
|
|
3581
|
+
*
|
|
3582
|
+
* The original crumb.url is kept intact (without base href) and passed to Angular
|
|
3583
|
+
* via the breadcrumb-click event. Angular Router expects paths relative to base,
|
|
3584
|
+
* so it handles the base href internally.
|
|
3585
|
+
*
|
|
3586
|
+
* Example with base href "/operations/":
|
|
3587
|
+
* - crumb.url = "/settings" (used for Angular routing)
|
|
3588
|
+
* - resolveUrl(crumb) = "/operations/settings" (used for href)
|
|
3589
|
+
*/
|
|
3590
|
+
resolveUrl(crumb) {
|
|
3591
|
+
if (!crumb.url)
|
|
3592
|
+
return '#';
|
|
3593
|
+
// Remove leading slash from url if present, then combine with base
|
|
3594
|
+
const path = crumb.url.startsWith('/') ? crumb.url.slice(1) : crumb.url;
|
|
3595
|
+
const baseHref = document.querySelector('base')?.getAttribute('href') || '/';
|
|
3596
|
+
const base = baseHref.endsWith('/') ? baseHref : (baseHref + '/');
|
|
3597
|
+
return base + path;
|
|
3598
|
+
}
|
|
3542
3599
|
/**
|
|
3543
3600
|
* Handles click on a breadcrumb link.
|
|
3544
3601
|
* Dispatches a cancelable event so SPA routers can intercept.
|
|
@@ -3549,6 +3606,10 @@
|
|
|
3549
3606
|
e.preventDefault();
|
|
3550
3607
|
return;
|
|
3551
3608
|
}
|
|
3609
|
+
// Allow Ctrl/Cmd+click and middle-click to open in new tab without SPA navigation
|
|
3610
|
+
if (e.ctrlKey || e.metaKey || e.button === 1) {
|
|
3611
|
+
return;
|
|
3612
|
+
}
|
|
3552
3613
|
const breadcrumbEvent = new CustomEvent('breadcrumb-click', {
|
|
3553
3614
|
detail: { breadcrumb: crumb },
|
|
3554
3615
|
bubbles: true,
|
|
@@ -3579,7 +3640,7 @@
|
|
|
3579
3640
|
${index > 0 ? b `<span class="breadcrumb-separator">/</span>` : ''}
|
|
3580
3641
|
<a
|
|
3581
3642
|
class=${e$1({ 'breadcrumb': true, 'breadcrumb--current': isCurrent })}
|
|
3582
|
-
href=${crumb
|
|
3643
|
+
href=${this.resolveUrl(crumb)}
|
|
3583
3644
|
@click=${(e) => this._handleBreadcrumbClick(e, crumb, isCurrent)}
|
|
3584
3645
|
>${crumb.label}</a>
|
|
3585
3646
|
`;
|
|
@@ -3603,6 +3664,7 @@
|
|
|
3603
3664
|
align-items: center;
|
|
3604
3665
|
padding: 0 16px;
|
|
3605
3666
|
width: 100%;
|
|
3667
|
+
flex-shrink: 0;
|
|
3606
3668
|
}
|
|
3607
3669
|
|
|
3608
3670
|
.breadcrumbs {
|