@kodaris/krubble-app-components 1.0.13 → 1.0.14
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 +69 -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 +69 -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 +40 -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
|
// =========================================================================
|
|
@@ -1536,7 +1564,7 @@
|
|
|
1536
1564
|
* Handles click on the nav header (logo/title) to navigate home.
|
|
1537
1565
|
* Dispatches a nav-item-click event so Angular can intercept and route.
|
|
1538
1566
|
*/
|
|
1539
|
-
handleNavHeaderClick(
|
|
1567
|
+
handleNavHeaderClick() {
|
|
1540
1568
|
// Clear active state since we're going home
|
|
1541
1569
|
this.activeNavItemId = null;
|
|
1542
1570
|
const navEvent = new CustomEvent('nav-item-click', {
|
|
@@ -1612,6 +1640,10 @@
|
|
|
1612
1640
|
this.toggleNavItem(item.id);
|
|
1613
1641
|
}
|
|
1614
1642
|
else {
|
|
1643
|
+
// Allow Ctrl/Cmd+click and middle-click to open in new tab without SPA navigation
|
|
1644
|
+
if (e.ctrlKey || e.metaKey || e.button === 1) {
|
|
1645
|
+
return;
|
|
1646
|
+
}
|
|
1615
1647
|
// Set active item immediately on click for instant visual feedback
|
|
1616
1648
|
this.activeNavItemId = item.id;
|
|
1617
1649
|
const navEvent = new CustomEvent('nav-item-click', {
|
|
@@ -1644,7 +1676,8 @@
|
|
|
1644
1676
|
let activeItem = null;
|
|
1645
1677
|
let longestMatch = 0;
|
|
1646
1678
|
for (const item of allItems) {
|
|
1647
|
-
|
|
1679
|
+
// Use resolveUrl because currentPath includes base href
|
|
1680
|
+
const url = this.resolveUrl(item);
|
|
1648
1681
|
if (currentPath.startsWith(url) && url.length > longestMatch) {
|
|
1649
1682
|
activeItem = item;
|
|
1650
1683
|
longestMatch = url.length;
|
|
@@ -2219,7 +2252,7 @@
|
|
|
2219
2252
|
'nav-item--drop-below': this.navItemDropTargetId === item.id && this.navItemDropPosition === 'below',
|
|
2220
2253
|
})}
|
|
2221
2254
|
data-id="${item.id}"
|
|
2222
|
-
href=${item
|
|
2255
|
+
href=${this.resolveUrl(item)}
|
|
2223
2256
|
target=${item.external ? '_blank' : A}
|
|
2224
2257
|
@mousedown=${(e) => this.handleNavItemMouseDown(e, item)}
|
|
2225
2258
|
@click=${(e) => this.handleNavItemClick(e, item)}
|
|
@@ -2328,9 +2361,8 @@
|
|
|
2328
2361
|
--kr-scaffold-nav-active-bg: #e5e7eb;
|
|
2329
2362
|
--kr-scaffold-nav-border: rgb(229, 229, 228);
|
|
2330
2363
|
--kr-scaffold-nav-divider: #e5e7eb;
|
|
2331
|
-
--kr-scaffold-nav-search-bg: #
|
|
2332
|
-
--kr-scaffold-nav-search-
|
|
2333
|
-
--kr-scaffold-nav-search-focus-border: #d1d5db;
|
|
2364
|
+
--kr-scaffold-nav-search-bg: #ffffff;
|
|
2365
|
+
--kr-scaffold-nav-search-border: #d1d5db;
|
|
2334
2366
|
}
|
|
2335
2367
|
|
|
2336
2368
|
/* Dark scheme */
|
|
@@ -2343,8 +2375,7 @@
|
|
|
2343
2375
|
--kr-scaffold-nav-border: transparent;
|
|
2344
2376
|
--kr-scaffold-nav-divider: rgba(255, 255, 255, 0.06);
|
|
2345
2377
|
--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);
|
|
2378
|
+
--kr-scaffold-nav-search-border: rgba(255, 255, 255, 0.3);
|
|
2348
2379
|
}
|
|
2349
2380
|
|
|
2350
2381
|
*,
|
|
@@ -2422,15 +2453,10 @@
|
|
|
2422
2453
|
padding: 0 12px;
|
|
2423
2454
|
height: 40px;
|
|
2424
2455
|
gap: 8px;
|
|
2425
|
-
border: 1px solid
|
|
2456
|
+
border: 1px solid var(--kr-scaffold-nav-search-border);
|
|
2426
2457
|
transition: all 0.15s ease;
|
|
2427
2458
|
}
|
|
2428
2459
|
|
|
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
2460
|
.nav-search__icon {
|
|
2435
2461
|
width: 18px;
|
|
2436
2462
|
height: 18px;
|
|
@@ -3539,6 +3565,29 @@
|
|
|
3539
3565
|
_handleMenuClick() {
|
|
3540
3566
|
this.dispatchEvent(new CustomEvent('menu-click', { bubbles: true, composed: true }));
|
|
3541
3567
|
}
|
|
3568
|
+
/**
|
|
3569
|
+
* Resolves a breadcrumb URL by prepending the base href.
|
|
3570
|
+
*
|
|
3571
|
+
* This method is used for setting href attributes on anchor elements
|
|
3572
|
+
* (so Cmd/Ctrl+click opens correct URL in new tab).
|
|
3573
|
+
*
|
|
3574
|
+
* The original crumb.url is kept intact (without base href) and passed to Angular
|
|
3575
|
+
* via the breadcrumb-click event. Angular Router expects paths relative to base,
|
|
3576
|
+
* so it handles the base href internally.
|
|
3577
|
+
*
|
|
3578
|
+
* Example with base href "/operations/":
|
|
3579
|
+
* - crumb.url = "/settings" (used for Angular routing)
|
|
3580
|
+
* - resolveUrl(crumb) = "/operations/settings" (used for href)
|
|
3581
|
+
*/
|
|
3582
|
+
resolveUrl(crumb) {
|
|
3583
|
+
if (!crumb.url)
|
|
3584
|
+
return '#';
|
|
3585
|
+
// Remove leading slash from url if present, then combine with base
|
|
3586
|
+
const path = crumb.url.startsWith('/') ? crumb.url.slice(1) : crumb.url;
|
|
3587
|
+
const baseHref = document.querySelector('base')?.getAttribute('href') || '/';
|
|
3588
|
+
const base = baseHref.endsWith('/') ? baseHref : (baseHref + '/');
|
|
3589
|
+
return base + path;
|
|
3590
|
+
}
|
|
3542
3591
|
/**
|
|
3543
3592
|
* Handles click on a breadcrumb link.
|
|
3544
3593
|
* Dispatches a cancelable event so SPA routers can intercept.
|
|
@@ -3549,6 +3598,10 @@
|
|
|
3549
3598
|
e.preventDefault();
|
|
3550
3599
|
return;
|
|
3551
3600
|
}
|
|
3601
|
+
// Allow Ctrl/Cmd+click and middle-click to open in new tab without SPA navigation
|
|
3602
|
+
if (e.ctrlKey || e.metaKey || e.button === 1) {
|
|
3603
|
+
return;
|
|
3604
|
+
}
|
|
3552
3605
|
const breadcrumbEvent = new CustomEvent('breadcrumb-click', {
|
|
3553
3606
|
detail: { breadcrumb: crumb },
|
|
3554
3607
|
bubbles: true,
|
|
@@ -3579,7 +3632,7 @@
|
|
|
3579
3632
|
${index > 0 ? b `<span class="breadcrumb-separator">/</span>` : ''}
|
|
3580
3633
|
<a
|
|
3581
3634
|
class=${e$1({ 'breadcrumb': true, 'breadcrumb--current': isCurrent })}
|
|
3582
|
-
href=${crumb
|
|
3635
|
+
href=${this.resolveUrl(crumb)}
|
|
3583
3636
|
@click=${(e) => this._handleBreadcrumbClick(e, crumb, isCurrent)}
|
|
3584
3637
|
>${crumb.label}</a>
|
|
3585
3638
|
`;
|
|
@@ -3603,6 +3656,7 @@
|
|
|
3603
3656
|
align-items: center;
|
|
3604
3657
|
padding: 0 16px;
|
|
3605
3658
|
width: 100%;
|
|
3659
|
+
flex-shrink: 0;
|
|
3606
3660
|
}
|
|
3607
3661
|
|
|
3608
3662
|
.breadcrumbs {
|