nath-angular-ui 0.6.0 → 0.7.0
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/fesm2022/nath-angular-ui.mjs +384 -32
- package/fesm2022/nath-angular-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/styles/styles.css +5 -1
- package/types/nath-angular-ui.d.ts +89 -31
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, ElementRef, model, input, output, contentChild, TemplateRef, viewChild, signal, computed, effect, ViewEncapsulation, ChangeDetectionStrategy, Component,
|
|
2
|
+
import { inject, ElementRef, model, input, output, contentChild, TemplateRef, viewChild, signal, computed, effect, ViewEncapsulation, ChangeDetectionStrategy, Component, Service, Pipe, InjectionToken, Injector, EnvironmentInjector, ApplicationRef, createEnvironmentInjector, createComponent, Injectable, Renderer2, DestroyRef, viewChildren, SecurityContext, untracked, HostListener, ViewChild, booleanAttribute, Directive, contentChildren, ViewContainerRef } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/common';
|
|
4
4
|
import { CommonModule, NgTemplateOutlet, DOCUMENT, NgStyle, NgClass, KeyValuePipe } from '@angular/common';
|
|
5
5
|
import * as i2 from '@angular/cdk/overlay';
|
|
6
6
|
import { OverlayModule } from '@angular/cdk/overlay';
|
|
7
|
-
import { LucideX, LucideChevronDown, isLucideIconComponent, LucideDynamicIcon, LucideHouse, LucideMinimize2, LucideMaximize2, LucideEye, LucideLoaderCircle, LucideSquare, LucideSquareCheck, LucideInbox, LucideChevronRight, LucideChevronsRight, LucideChevronLeft, LucideChevronsLeft, LucideCircle, LucideArrowUp, LucideArrowDown, LucideArrowUp01, LucideArrowDown01, LucideArrowUpAZ, LucideArrowDownAZ, LucideMoon, LucideSun, LucideCircleCheck, LucideCircleAlert, LucideInfo, LucideTriangleAlert } from '@lucide/angular';
|
|
7
|
+
import { LucideX, LucideChevronDown, isLucideIconComponent, LucideDynamicIcon, LucideHouse, LucideMinimize2, LucideMaximize2, LucideEye, LucideLoaderCircle, LucideMenu, LucideSquare, LucideSquareCheck, LucideInbox, LucideChevronRight, LucideChevronsRight, LucideChevronLeft, LucideChevronsLeft, LucideCircle, LucideArrowUp, LucideArrowDown, LucideArrowUp01, LucideArrowDown01, LucideArrowUpAZ, LucideArrowDownAZ, LucideMoon, LucideSun, LucideCircleCheck, LucideCircleAlert, LucideInfo, LucideTriangleAlert } from '@lucide/angular';
|
|
8
8
|
import * as i1$1 from '@angular/router';
|
|
9
9
|
import { RouterModule, Router, NavigationEnd, RouterLink, RouterLinkActive } from '@angular/router';
|
|
10
10
|
import * as i1$2 from '@angular/forms';
|
|
@@ -305,7 +305,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
|
|
|
305
305
|
args: [{ selector: 'nath-boolean-control', imports: [CommonModule, LucideDynamicIcon], encapsulation: ViewEncapsulation.None, template: "@if (mode() === 'checkbox') {\r\n <div class=\"nath-boolean-checkbox-container\">\r\n <label\r\n class=\"nath-boolean-checkbox-label\"\r\n [class.nath-boolean-disabled]=\"disabled()\"\r\n [class]=\"styleClass()\"\r\n >\r\n <input\r\n #checkboxElement\r\n type=\"checkbox\"\r\n [checked]=\"value() === true\"\r\n (change)=\"toggle()\"\r\n [id]=\"inputId()\"\r\n [disabled]=\"disabled()\"\r\n />\r\n @if (label()) {\r\n <span>\r\n {{ label() }}\r\n </span>\r\n }\r\n </label>\r\n </div>\r\n}\r\n\r\n@if (mode() === 'switch') {\r\n <label\r\n class=\"nath-boolean-switch-label\"\r\n [class.nath-boolean-disabled]=\"disabled()\"\r\n [class]=\"styleClass()\"\r\n >\r\n <div class=\"nath-boolean-switch-wrapper\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"value() === true\"\r\n (change)=\"toggle()\"\r\n class=\"nath-boolean-switch-input\"\r\n [id]=\"inputId()\"\r\n [disabled]=\"disabled()\"\r\n />\r\n <div\r\n class=\"nath-boolean-switch-track\"\r\n [class.is-null]=\"value() === null\"\r\n [class.nath-boolean-disabled]=\"disabled()\"\r\n >\r\n @if (icon()) {\r\n <div\r\n class=\"nath-boolean-switch-handle-content\"\r\n [class.is-off]=\"value() === false\"\r\n [class.is-null]=\"value() === null\"\r\n [class.is-on]=\"value() === true\"\r\n >\r\n @if (isLucideIconComponent(icon()!)) {\r\n <svg [lucideIcon]=\"icon()!\" />\r\n } @else {\r\n <i [ngClass]=\"[icon()!]\"></i>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n @if (label()) {\r\n <span>\r\n {{ label() }}\r\n </span>\r\n }\r\n </label>\r\n}\r\n\r\n@if (mode() === 'toggle') {\r\n <button\r\n type=\"button\"\r\n (click)=\"toggle()\"\r\n class=\"nath-boolean-toggle-button\"\r\n [class]=\"styleClass()\"\r\n [id]=\"inputId()\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <span class=\"nath-boolean-toggle-content\" [ngClass]=\"toggleButtonClasses()\">\r\n @if (icon()) {\r\n @if (isLucideIconComponent(icon()!)) {\r\n <svg [lucideIcon]=\"icon()!\" />\r\n } @else {\r\n <i [ngClass]=\"[icon()!]\"></i>\r\n }\r\n }\r\n {{ label() || fallbackButtonLabel() }}\r\n </span>\r\n </button>\r\n}\r\n", styles: ["nath-boolean-control,.nath-boolean-theme{--nath-boolean-gap: .75rem;--nath-boolean-disabled-opacity: .5;--nath-boolean-transition: all .2s ease-in-out;--nath-switch-width: 3.5rem;--nath-switch-height: 2rem;--nath-switch-bg-off: var(--color-zinc-300, oklch(87.1% .006 286.286));--nath-switch-bg-on: var(--color-primary-500, #8e9ba5);--nath-switch-bg-null: var(--color-zinc-300, oklch(87.1% .006 286.286));--nath-switch-handle-bg: var(--color-zinc-400, oklch(70.5% .015 286.067));--nath-switch-handle-bg-on: var(--color-zinc-900, oklch(14.1% .005 285.823));--nath-switch-handle-size: 1.75rem;--nath-switch-handle-offset: 2px;--nath-switch-focus-ring: 1px solid var(--color-zinc-900, oklch(14.1% .005 285.823));--nath-toggle-bg-null: var(--color-zinc-400, oklch(70.5% .015 286.067));--nath-toggle-text-null: var(--color-zinc-900, oklch(14.1% .005 285.823));--nath-toggle-bg-on: var(--color-zinc-50, oklch(98.4% .001 286.375));--nath-toggle-text-on: var(--color-zinc-900, oklch(14.1% .005 285.823));--nath-toggle-bg-off: transparent;--nath-toggle-text-off: inherit;--nath-toggle-padding: .25rem;--nath-toggle-inner-padding: .25rem .375rem;--nath-toggle-border-radius: .375rem;--nath-toggle-button-bg: var(--color-slate-300, oklch(92% .004 286.32));--nath-toggle-button-text: var(--color-slate-800, oklch(27.8% .033 256.848));--nath-toggle-button-hover-bg: var(--color-slate-300, oklch(92% .004 286.32));display:block}.dark nath-boolean-control,.dark .nath-boolean-theme{--nath-switch-bg-off: var(--color-zinc-700, oklch(37% .013 285.805));--nath-switch-bg-null: var(--color-zinc-600, oklch(44.2% .017 285.786));--nath-switch-focus-ring: 1px solid var(--color-zinc-50, oklch(98.4% .001 286.375));--nath-toggle-bg-on: var(--color-zinc-50, oklch(98.4% .001 286.375));--nath-toggle-text-on: var(--color-zinc-900, oklch(14.1% .005 285.823));--nath-toggle-button-bg: var(--color-slate-800, oklch(27.4% .006 286.033));--nath-toggle-button-text: var(--color-slate-200, oklch(92% .004 286.32));--nath-toggle-button-hover-bg: var(--color-slate-700, oklch(37% .013 285.805))}.nath-boolean-checkbox-container{display:flex;align-items:center;gap:var(--nath-boolean-gap);-webkit-user-select:none;user-select:none}.nath-boolean-checkbox-label{display:flex;align-items:center;gap:.5rem;cursor:pointer;white-space:nowrap}.nath-boolean-disabled{opacity:var(--nath-boolean-disabled-opacity);cursor:not-allowed;pointer-events:none}.nath-boolean-switch-label{display:flex;align-items:center;gap:.5rem;cursor:pointer}.nath-boolean-switch-wrapper{position:relative;display:inline-flex;align-items:center}.nath-boolean-switch-input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.nath-boolean-switch-track{width:var(--nath-switch-width);height:var(--nath-switch-height);background-color:var(--nath-switch-bg-off);border-radius:9999px;transition:var(--nath-boolean-transition);position:relative;display:flex;align-items:center}.nath-boolean-switch-input:focus-visible+.nath-boolean-switch-track{outline:var(--nath-switch-focus-ring)}.nath-boolean-switch-track:after{content:\"\";position:absolute;top:var(--nath-switch-handle-offset);left:var(--nath-switch-handle-offset);height:var(--nath-switch-handle-size);width:var(--nath-switch-handle-size);background-color:var(--nath-switch-handle-bg);border-radius:50%;transition:var(--nath-boolean-transition)}.nath-boolean-switch-input:checked+.nath-boolean-switch-track{background-color:var(--nath-switch-bg-on)}.nath-boolean-switch-input:checked+.nath-boolean-switch-track:after{transform:translate(calc(var(--nath-switch-width) - var(--nath-switch-handle-size) - (var(--nath-switch-handle-offset) * 2)));background-color:var(--nath-switch-handle-bg-on)}.nath-boolean-switch-track.is-null{background-color:var(--nath-switch-bg-null)}.nath-boolean-switch-track.is-null:after{transform:translate(calc((var(--nath-switch-width) - var(--nath-switch-handle-size) - (var(--nath-switch-handle-offset) * 2)) / 2))}.nath-boolean-switch-handle-content{position:absolute;top:var(--nath-switch-handle-offset);z-index:10;display:flex;height:var(--nath-switch-handle-size);width:var(--nath-switch-handle-size);align-items:center;justify-content:center;transition:var(--nath-boolean-transition);pointer-events:none;border-radius:50%;overflow:hidden}.nath-boolean-switch-handle-content.is-off{left:var(--nath-switch-handle-offset)}.nath-boolean-switch-handle-content.is-null{left:calc(50% - (var(--nath-switch-handle-size) / 2))}.nath-boolean-switch-handle-content.is-on{right:var(--nath-switch-handle-offset)}.nath-boolean-toggle-button{padding:.25rem;width:100%;cursor:pointer;border:1px solid transparent;border-radius:.375rem;box-sizing:border-box;display:inline-flex;gap:.5rem;align-items:center;justify-content:center;line-height:1.25rem;text-decoration:none;transition:all .2s;box-shadow:0 1px 2px #0000000d;background-color:var(--nath-toggle-button-bg);color:var(--nath-toggle-button-text)}.nath-boolean-toggle-button:hover:not(:disabled){background-color:var(--nath-toggle-button-hover-bg)}.nath-boolean-toggle-button:focus{outline:none}.nath-boolean-toggle-button:disabled{opacity:.5;cursor:not-allowed}.dark .nath-boolean-toggle-button:disabled{opacity:.3}.nath-boolean-toggle-content{padding:var(--nath-toggle-inner-padding);display:inline-flex;gap:.5rem;align-items:center;justify-content:center;line-height:1.25rem;border-radius:var(--nath-toggle-border-radius);width:100%;transition:var(--nath-boolean-transition)}.nath-boolean-toggle-null{background-color:var(--nath-toggle-bg-null);color:var(--nath-toggle-text-null)}.nath-boolean-toggle-on{background-color:var(--nath-toggle-bg-on);color:var(--nath-toggle-text-on)}.nath-boolean-toggle-off{background-color:var(--nath-toggle-bg-off);color:var(--nath-toggle-text-off)}\n"] }]
|
|
306
306
|
}], ctorParameters: () => [], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], allowIndeterminate: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowIndeterminate", required: false }] }], inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", required: false }] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], yesLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "yesLabel", required: false }] }], noLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "noLabel", required: false }] }], indeterminateLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminateLabel", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], toggled: [{ type: i0.Output, args: ["toggled"] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], checkboxRef: [{ type: i0.ViewChild, args: ['checkboxElement', { isSignal: true }] }] } });
|
|
307
307
|
|
|
308
|
-
class
|
|
308
|
+
class NathBreadcrumbService {
|
|
309
309
|
// A private writable signal holding the home item which will always be visible, if any
|
|
310
310
|
_home = signal(null, /* @ts-ignore */
|
|
311
311
|
...(ngDevMode ? [{ debugName: "_home" }] : /* istanbul ignore next */ []));
|
|
@@ -327,11 +327,20 @@ class BreadcrumbService {
|
|
|
327
327
|
* @param crumbs Array of breadcrumbs items
|
|
328
328
|
*/
|
|
329
329
|
set(crumbs) {
|
|
330
|
-
this._breadcrumbs.set(crumbs);
|
|
330
|
+
this._breadcrumbs.set(crumbs.filter((crumb) => crumb !== null));
|
|
331
331
|
}
|
|
332
|
+
/**
|
|
333
|
+
* Add a new breadcrumb to the current breadcrumbs array.
|
|
334
|
+
* @param crumb
|
|
335
|
+
*/
|
|
332
336
|
add(crumb) {
|
|
333
337
|
this._breadcrumbs.update((v) => [...v, crumb]);
|
|
334
338
|
}
|
|
339
|
+
/**
|
|
340
|
+
* Update a breadcrumb at a specific index.
|
|
341
|
+
* @param index
|
|
342
|
+
* @param crumb
|
|
343
|
+
*/
|
|
335
344
|
update(index, crumb) {
|
|
336
345
|
this._breadcrumbs.update((v) => {
|
|
337
346
|
const copy = [...v];
|
|
@@ -340,23 +349,31 @@ class BreadcrumbService {
|
|
|
340
349
|
});
|
|
341
350
|
}
|
|
342
351
|
/**
|
|
343
|
-
*
|
|
352
|
+
* Remove a breadcrumb at a specific index.
|
|
353
|
+
* @param index
|
|
354
|
+
*/
|
|
355
|
+
remove(index) {
|
|
356
|
+
this._breadcrumbs.update((v) => {
|
|
357
|
+
const copy = [...v];
|
|
358
|
+
copy.splice(index, 1);
|
|
359
|
+
return copy;
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Clear all breadcrumbs.
|
|
344
364
|
*/
|
|
345
365
|
clear() {
|
|
346
366
|
this._breadcrumbs.set([]);
|
|
347
367
|
}
|
|
348
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type:
|
|
349
|
-
static ɵprov = i0.ɵɵ
|
|
368
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NathBreadcrumbService, deps: [], target: i0.ɵɵFactoryTarget.Service });
|
|
369
|
+
static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.5", ngImport: i0, type: NathBreadcrumbService });
|
|
350
370
|
}
|
|
351
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type:
|
|
352
|
-
type:
|
|
353
|
-
args: [{
|
|
354
|
-
providedIn: 'root', // Shared instance across the app
|
|
355
|
-
}]
|
|
371
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NathBreadcrumbService, decorators: [{
|
|
372
|
+
type: Service
|
|
356
373
|
}] });
|
|
357
374
|
|
|
358
375
|
class NathBreadcrumbs {
|
|
359
|
-
breadcrumbService = inject(
|
|
376
|
+
breadcrumbService = inject(NathBreadcrumbService);
|
|
360
377
|
// Directly expose the read-only signal to the template
|
|
361
378
|
home = this.breadcrumbService.home;
|
|
362
379
|
breadcrumbs = this.breadcrumbService.breadcrumbs;
|
|
@@ -1400,6 +1417,35 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
|
|
|
1400
1417
|
`, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: {}, styles: ["nath-image-preview,.nath-image-preview-theme{--nath-image-preview-bg: var(--color-zinc-300, oklch(81.7% .012 286.033));--nath-image-preview-text-muted: var(--color-zinc-500, oklch(55.2% .016 285.938));--nath-image-preview-hover-overlay: rgba(0, 0, 0, .5);--nath-image-preview-hover-icon-color: white;--nath-image-preview-modal-bg: rgba(0, 0, 0, .8);--nath-image-preview-modal-backdrop-blur: 4px;--nath-image-preview-close-bg: rgba(0, 0, 0, .4);--nath-image-preview-close-hover-bg: rgba(0, 0, 0, .6);--nath-image-preview-close-color: white;--nath-image-preview-close-hover-color: var(--color-gray-300, oklch(81.7% .012 286.033));--nath-image-preview-image-shadow: 0 25px 50px -12px rgb(0 0 0 / .25)}.dark nath-image-preview,.dark .nath-image-preview-theme{--nath-image-preview-bg: var(--color-zinc-900, oklch(21% .006 285.885));--nath-image-preview-text-muted: var(--color-zinc-400, oklch(70.5% .015 286.067))}nath-image-preview{position:relative;height:100%;width:100%;display:inline-flex;align-items:center;justify-content:center;background-color:var(--nath-image-preview-bg);overflow:hidden}.nath-image-preview-no-image{width:100%;height:100%;font-size:4rem;display:flex;justify-content:center;align-items:center;padding:2rem}.nath-image-preview-text-muted{color:var(--nath-image-preview-text-muted)}.nath-image-preview-thumbnail{max-width:100%;max-height:100%;object-fit:cover;cursor:pointer}.nath-image-preview-hover-trigger{position:absolute;top:0;right:0;width:100%;height:100%;display:flex;align-items:center;justify-content:center;cursor:pointer;opacity:0;transition:opacity .2s,background-color .2s}.nath-image-preview-hover-trigger:hover{opacity:1;background-color:var(--nath-image-preview-hover-overlay)}.nath-image-preview-eye-icon{font-size:1.5rem;color:var(--nath-image-preview-hover-icon-color)}.nath-image-preview-modal{position:fixed;inset:0;z-index:50;display:flex;align-items:center;justify-content:center;background-color:var(--nath-image-preview-modal-bg);-webkit-backdrop-filter:blur(var(--nath-image-preview-modal-backdrop-blur));backdrop-filter:blur(var(--nath-image-preview-modal-backdrop-blur));transition:opacity .3s}.nath-image-preview-close-btn{position:absolute;top:1rem;right:1rem;color:var(--nath-image-preview-close-color);padding:.5rem;border-radius:9999px;background-color:var(--nath-image-preview-close-bg);transition:color .2s,background-color .2s;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center}.nath-image-preview-close-btn:hover{color:var(--nath-image-preview-close-hover-color);background-color:var(--nath-image-preview-close-hover-bg)}.nath-image-preview-modal-content{max-width:90vw;max-height:90vh;display:flex;align-items:center;justify-content:center}.nath-image-preview-full-image{max-width:100%;max-height:90vh;object-fit:contain;border-radius:.25rem;box-shadow:var(--nath-image-preview-image-shadow)}.nath-image-preview-animate-spin{animation:nath-image-preview-spin 1s linear infinite}@keyframes nath-image-preview-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
|
|
1401
1418
|
}], ctorParameters: () => [], propDecorators: { image: [{ type: i0.Input, args: [{ isSignal: true, alias: "image", required: true }] }], thumbnail: [{ type: i0.Input, args: [{ isSignal: true, alias: "thumbnail", required: false }] }], text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: true }] }], fallbackIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "fallbackIcon", required: true }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], preview: [{ type: i0.Input, args: [{ isSignal: true, alias: "preview", required: false }] }], imageClick: [{ type: i0.Output, args: ["imageClick"] }] } });
|
|
1402
1419
|
|
|
1420
|
+
/**
|
|
1421
|
+
* Finds the next or previous sibling of an element that matches a selector.
|
|
1422
|
+
*/
|
|
1423
|
+
function findSibling(el, selector, direction = 'next') {
|
|
1424
|
+
if (!el)
|
|
1425
|
+
return null;
|
|
1426
|
+
let sibling = direction === 'next' ? el.nextElementSibling : el.previousElementSibling;
|
|
1427
|
+
let indexOffset = 0;
|
|
1428
|
+
while (sibling) {
|
|
1429
|
+
if (direction === 'next')
|
|
1430
|
+
indexOffset += 1;
|
|
1431
|
+
else
|
|
1432
|
+
indexOffset -= 1;
|
|
1433
|
+
if (sibling.matches(selector)) {
|
|
1434
|
+
return { sibling, indexOffset };
|
|
1435
|
+
}
|
|
1436
|
+
sibling = direction === 'next' ? sibling.nextElementSibling : sibling.previousElementSibling;
|
|
1437
|
+
}
|
|
1438
|
+
return null;
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
function previousSibling(el, selector) {
|
|
1442
|
+
const previousEl = el.previousElementSibling;
|
|
1443
|
+
if (!selector || previousEl?.matches(selector)) {
|
|
1444
|
+
return previousEl;
|
|
1445
|
+
}
|
|
1446
|
+
return null;
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1403
1449
|
const SUBMENU_ALIGNMENT_CONFIG = {
|
|
1404
1450
|
ESTIMATED_INITIAL_WIDTH_PX: 200,
|
|
1405
1451
|
VIEWPORT_COLLISION_PADDING_PX: 8,
|
|
@@ -1408,7 +1454,10 @@ class NathMenuList {
|
|
|
1408
1454
|
// ────────────────────────────────────────────────────────────────────────────────
|
|
1409
1455
|
// INJECTIONS
|
|
1410
1456
|
// ────────────────────────────────────────────────────────────────────────────────
|
|
1457
|
+
document = inject(DOCUMENT);
|
|
1411
1458
|
sanitizer = inject(DomSanitizer);
|
|
1459
|
+
destroyRef = inject(DestroyRef);
|
|
1460
|
+
elementRef = inject(ElementRef);
|
|
1412
1461
|
// ────────────────────────────────────────────────────────────────────────────────
|
|
1413
1462
|
// I/O
|
|
1414
1463
|
// ────────────────────────────────────────────────────────────────────────────────
|
|
@@ -1426,13 +1475,35 @@ class NathMenuList {
|
|
|
1426
1475
|
...(ngDevMode ? [{ debugName: "submenuContainers" }] : /* istanbul ignore next */ []));
|
|
1427
1476
|
activeItem = signal(null, /* @ts-ignore */
|
|
1428
1477
|
...(ngDevMode ? [{ debugName: "activeItem" }] : /* istanbul ignore next */ []));
|
|
1429
|
-
|
|
1478
|
+
focusedIndex = signal(-1, /* @ts-ignore */
|
|
1479
|
+
...(ngDevMode ? [{ debugName: "focusedIndex" }] : /* istanbul ignore next */ []));
|
|
1430
1480
|
submenuTop = signal(0, /* @ts-ignore */
|
|
1431
1481
|
...(ngDevMode ? [{ debugName: "submenuTop" }] : /* istanbul ignore next */ []));
|
|
1432
1482
|
submenuLeft = signal(0, /* @ts-ignore */
|
|
1433
1483
|
...(ngDevMode ? [{ debugName: "submenuLeft" }] : /* istanbul ignore next */ []));
|
|
1434
1484
|
nextSubmenuDirection = signal('right', /* @ts-ignore */
|
|
1435
1485
|
...(ngDevMode ? [{ debugName: "nextSubmenuDirection" }] : /* istanbul ignore next */ []));
|
|
1486
|
+
menuItemsElements = signal([], /* @ts-ignore */
|
|
1487
|
+
...(ngDevMode ? [{ debugName: "menuItemsElements" }] : /* istanbul ignore next */ []));
|
|
1488
|
+
// ────────────────────────────────────────────────────────────────────────────────
|
|
1489
|
+
// COMPUTED
|
|
1490
|
+
// ────────────────────────────────────────────────────────────────────────────────
|
|
1491
|
+
// ────────────────────────────────────────────────────────────────────────────────
|
|
1492
|
+
ngAfterViewInit() {
|
|
1493
|
+
const menuList = this.elementRef.nativeElement;
|
|
1494
|
+
if (menuList) {
|
|
1495
|
+
const items = Array.from(menuList.querySelectorAll(':scope > div > ul > .nath-menu-item'));
|
|
1496
|
+
this.menuItemsElements.set(items);
|
|
1497
|
+
setTimeout(() => {
|
|
1498
|
+
const first = this.menuItemsElements()[0];
|
|
1499
|
+
first?.focus();
|
|
1500
|
+
!!first && this.focusedIndex.set(0);
|
|
1501
|
+
});
|
|
1502
|
+
}
|
|
1503
|
+
fromEvent(this.document, 'keydown')
|
|
1504
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
1505
|
+
.subscribe((event) => this.handleKeyDown(event));
|
|
1506
|
+
}
|
|
1436
1507
|
// ────────────────────────────────────────────────────────────────────────────────
|
|
1437
1508
|
// METHODS
|
|
1438
1509
|
// ────────────────────────────────────────────────────────────────────────────────
|
|
@@ -1469,7 +1540,7 @@ class NathMenuList {
|
|
|
1469
1540
|
const subRect = subContainer.getBoundingClientRect();
|
|
1470
1541
|
const dynamicMenuWidth = subRect.width;
|
|
1471
1542
|
// Check if trending right spills off screen boundary
|
|
1472
|
-
if (currentDir === 'right' && liRect.right + dynamicMenuWidth >
|
|
1543
|
+
if (currentDir === 'right' && liRect.right + dynamicMenuWidth > globalThis.innerWidth) {
|
|
1473
1544
|
currentDir = 'left';
|
|
1474
1545
|
}
|
|
1475
1546
|
// Shift horizontal layout flush using viewport targets
|
|
@@ -1481,13 +1552,13 @@ class NathMenuList {
|
|
|
1481
1552
|
}
|
|
1482
1553
|
this.nextSubmenuDirection.set(currentDir);
|
|
1483
1554
|
// Fluid vertical overflow protection
|
|
1484
|
-
if (subRect.bottom >
|
|
1485
|
-
const overflowDistance = subRect.bottom -
|
|
1555
|
+
if (subRect.bottom > globalThis.innerHeight) {
|
|
1556
|
+
const overflowDistance = subRect.bottom - globalThis.innerHeight;
|
|
1486
1557
|
// Shift up smoothly based on screen collision
|
|
1487
1558
|
this.submenuTop.set(liRect.top - overflowDistance - SUBMENU_ALIGNMENT_CONFIG.VIEWPORT_COLLISION_PADDING_PX);
|
|
1488
1559
|
}
|
|
1489
1560
|
// Reveal once calculations are complete
|
|
1490
|
-
subContainer.
|
|
1561
|
+
subContainer.style.visibility = 'visible';
|
|
1491
1562
|
});
|
|
1492
1563
|
}
|
|
1493
1564
|
executeItem(item, index, event) {
|
|
@@ -1502,12 +1573,110 @@ class NathMenuList {
|
|
|
1502
1573
|
}
|
|
1503
1574
|
}
|
|
1504
1575
|
isLucideIconComponent = isLucideIconComponent;
|
|
1576
|
+
onMouseLeave(event) {
|
|
1577
|
+
// Clear the active item to hide any opened sub-menu
|
|
1578
|
+
this.activeItem.set(null);
|
|
1579
|
+
}
|
|
1580
|
+
debounce = (callback, wait) => {
|
|
1581
|
+
let timeoutId = null;
|
|
1582
|
+
return (...args) => {
|
|
1583
|
+
globalThis.clearTimeout(timeoutId);
|
|
1584
|
+
timeoutId = globalThis.setTimeout(() => {
|
|
1585
|
+
callback(...args);
|
|
1586
|
+
}, wait);
|
|
1587
|
+
};
|
|
1588
|
+
};
|
|
1589
|
+
handleKeyDown = this.debounce((event) => {
|
|
1590
|
+
const items = this.menuItemsElements();
|
|
1591
|
+
const currentIndex = this.focusedIndex();
|
|
1592
|
+
const currentItem = items[currentIndex];
|
|
1593
|
+
const currentMenuItem = this.items().at(currentIndex);
|
|
1594
|
+
let newIndex = currentIndex;
|
|
1595
|
+
switch (event.key) {
|
|
1596
|
+
case 'ArrowDown':
|
|
1597
|
+
event.preventDefault();
|
|
1598
|
+
event.stopPropagation();
|
|
1599
|
+
if (currentIndex < items.length - 1) {
|
|
1600
|
+
const nextInteractiveItem = findSibling(items[currentIndex], '.nath-menu-item--interactive', 'next');
|
|
1601
|
+
if (nextInteractiveItem?.indexOffset) {
|
|
1602
|
+
newIndex = currentIndex + nextInteractiveItem.indexOffset;
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
else {
|
|
1606
|
+
// We're at the last item, go back to the first
|
|
1607
|
+
newIndex = 0;
|
|
1608
|
+
}
|
|
1609
|
+
break;
|
|
1610
|
+
case 'ArrowUp':
|
|
1611
|
+
event.preventDefault();
|
|
1612
|
+
event.stopPropagation();
|
|
1613
|
+
if (currentIndex > 0) {
|
|
1614
|
+
const nextInteractiveItem = findSibling(items[currentIndex], '.nath-menu-item--interactive', 'previous');
|
|
1615
|
+
if (nextInteractiveItem?.indexOffset) {
|
|
1616
|
+
newIndex = currentIndex + nextInteractiveItem.indexOffset;
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
else {
|
|
1620
|
+
// We're at the first item, go to the last
|
|
1621
|
+
for (let i = items.length - 1; i >= 0; i--) {
|
|
1622
|
+
if (items[i].classList.contains('nath-menu-item--interactive')) {
|
|
1623
|
+
newIndex = i;
|
|
1624
|
+
break;
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
break;
|
|
1629
|
+
case 'ArrowRight':
|
|
1630
|
+
// Open sub-menu if any
|
|
1631
|
+
event.preventDefault();
|
|
1632
|
+
event.stopPropagation();
|
|
1633
|
+
if (currentMenuItem?.items?.length && !currentMenuItem?.disabled) {
|
|
1634
|
+
items[currentIndex].dispatchEvent(new Event('mouseenter'));
|
|
1635
|
+
this.focusedIndex.set(-1);
|
|
1636
|
+
}
|
|
1637
|
+
return;
|
|
1638
|
+
case 'ArrowLeft':
|
|
1639
|
+
// Close sub-menu
|
|
1640
|
+
if (currentMenuItem) {
|
|
1641
|
+
const thisList = this.elementRef.nativeElement;
|
|
1642
|
+
if (thisList.parentElement?.classList.contains('nath-menu-submenu-panel')) {
|
|
1643
|
+
const parentList = previousSibling(thisList.parentElement, '.nath-menu-list');
|
|
1644
|
+
parentList?.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft' }));
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
if (this.activeItem()?.items?.length) {
|
|
1648
|
+
newIndex = this.items().findIndex((item) => item.label && item.label === this.activeItem()?.label);
|
|
1649
|
+
this.activeItem.set(null);
|
|
1650
|
+
}
|
|
1651
|
+
break;
|
|
1652
|
+
case 'Escape':
|
|
1653
|
+
event.preventDefault();
|
|
1654
|
+
const thisList = this.elementRef.nativeElement;
|
|
1655
|
+
if (thisList.parentElement?.classList.contains('nath-menu-submenu-panel')) {
|
|
1656
|
+
const parentList = previousSibling(thisList.parentElement, '.nath-menu-list');
|
|
1657
|
+
parentList?.parentElement?.dispatchEvent(new MouseEvent('mouseleave'));
|
|
1658
|
+
}
|
|
1659
|
+
return;
|
|
1660
|
+
case 'Enter':
|
|
1661
|
+
case ' ':
|
|
1662
|
+
event.preventDefault();
|
|
1663
|
+
if (currentIndex >= 0 && currentIndex < items.length) {
|
|
1664
|
+
const item = this.items()[currentIndex];
|
|
1665
|
+
this.onItemClick(item, currentIndex, event);
|
|
1666
|
+
}
|
|
1667
|
+
return;
|
|
1668
|
+
default:
|
|
1669
|
+
return;
|
|
1670
|
+
}
|
|
1671
|
+
this.focusedIndex.set(newIndex);
|
|
1672
|
+
setTimeout(() => items[newIndex]?.focus());
|
|
1673
|
+
}, 100);
|
|
1505
1674
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NathMenuList, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1506
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: NathMenuList, isStandalone: true, selector: "nath-menu-list", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null }, flat: { classPropertyName: "flat", publicName: "flat", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { whenCommand: "whenCommand" }, viewQueries: [{ propertyName: "submenuContainers", predicate: ["submenuContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "<ul class=\"nath-menu-list-theme nath-menu-list nath-menu-custom-scrollbar\">\
|
|
1675
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: NathMenuList, isStandalone: true, selector: "nath-menu-list", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null }, flat: { classPropertyName: "flat", publicName: "flat", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { whenCommand: "whenCommand" }, viewQueries: [{ propertyName: "submenuContainers", predicate: ["submenuContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "<div (mouseleave)=\"onMouseLeave($event)\">\n <ul class=\"nath-menu-list-theme nath-menu-list nath-menu-custom-scrollbar\">\n @for (item of items(); track $index) {\n <li\n class=\"nath-menu-item\"\n [class.nath-menu-item--enabled]=\"!item.disabled\"\n [class.nath-menu-item--disabled]=\"item.disabled\"\n [class.nath-menu-item--padded]=\"!item.separator\"\n [class.nath-menu-item--separator]=\"item.separator\"\n [class.nath-menu-item--clickable]=\"item.routerLink || item.command || item.url\"\n [class.nath-menu-item--header]=\"!item.routerLink && !item.command && !item.url\"\n [class.nath-menu-item--interactive]=\"\n !item.disabled &&\n (item.routerLink || item.command || item.url || (item.items?.length && !flat()))\n \"\n [routerLink]=\"item.routerLink\"\n [queryParams]=\"item.queryParams\"\n routerLinkActive=\"nath-menu-item--active\"\n [routerLinkActiveOptions]=\"item.routerLinkActiveOptions || { exact: false }\"\n [attr.tabindex]=\"-1\"\n [attr.title]=\"item.title\"\n (mouseenter)=\"!item.disabled && onItemHover(item, $event)\"\n (click)=\"onItemClick(item, $index, $event)\"\n (keydown)=\"$event.preventDefault(); handleKeyDown($event)\"\n (focus)=\"focusedIndex() < 0 && focusedIndex.set($index)\"\n >\n @if (!item.separator) {\n <span class=\"nath-menu-item-content\">\n @if (item.icon) {\n @if (isLucideIconComponent(item.icon)) {\n <svg [lucideIcon]=\"item.icon\" />\n } @else {\n <i [class]=\"item.icon\"></i>\n }\n }\n @if (item.escape === false) {\n <span [innerHTML]=\"getMenuLabel(item)\"></span>\n } @else {\n <span class=\"nath-menu-item-text-truncate\">{{ item.label }}</span>\n }\n </span>\n\n @if (item.items && item.items.length > 0 && !flat()) {\n <span class=\"nath-menu-item-arrow\">\u203A</span>\n }\n }\n </li>\n\n @if (flat() && item.items) {\n <nath-menu-list [items]=\"item.items\" (whenCommand)=\"whenCommand.emit($event)\" />\n }\n } @empty {\n <li class=\"nath-menu-item nath-menu-item--padded nath-menu-item--disabled\">\n No actions available\n </li>\n }\n </ul>\n\n @if (!flat()) {\n @if (activeItem()?.items?.length) {\n <div\n #submenuContainer\n class=\"nath-menu-list-theme nath-menu-submenu-panel\"\n [style.left.px]=\"submenuLeft()\"\n [style.top.px]=\"submenuTop()\"\n >\n <nath-menu-list\n [items]=\"activeItem()!.items!\"\n [direction]=\"nextSubmenuDirection()\"\n (whenCommand)=\"whenCommand.emit($event)\"\n />\n </div>\n }\n }\n</div>\n", styles: ["nath-menu-list,.nath-menu-list-theme{--nath-menu-list-text: var(--color-zinc-700, oklch(37.1% .021 264.444));--nath-menu-list-text-muted: var(--color-zinc-500, oklch(55.2% .016 285.938));--nath-menu-list-text-disabled: var(--color-zinc-300, oklch(87.1% .006 286.286));--nath-menu-list-hover-bg: var(--color-zinc-100, oklch(96.7% .003 264.542));--nath-menu-list-border: var(--color-zinc-200, oklch(92% .004 286.32));--nath-menu-list-bg: #ffffff;--nath-menu-list-shadow: 0 10px 15px -3px rgba(0, 0, 0, .1), 0 4px 6px -2px rgba(0, 0, 0, .05);--nath-menu-list-z-index: 10000}.dark nath-menu-list,.dark .nath-menu-list-theme{--nath-menu-list-text: var(--color-zinc-200, oklch(92% .004 286.32));--nath-menu-list-text-muted: var(--color-zinc-400, oklch(70.5% .015 286.067));--nath-menu-list-text-disabled: var(--color-zinc-600, oklch(44.2% .017 285.786));--nath-menu-list-hover-bg: var(--color-zinc-800, oklch(27.4% .006 286.033));--nath-menu-list-border: var(--color-zinc-700, oklch(37% .013 285.805));--nath-menu-list-bg: var(--color-zinc-900, oklch(21% .006 285.885))}.nath-menu-list{max-height:90vh;overflow-y:auto;overflow-x:hidden;list-style-type:none;margin:0;padding:0;width:100%}.nath-menu-item{position:relative;display:flex;align-items:center;justify-content:space-between;gap:1rem;transition:background-color .15s,color .15s}.nath-menu-item--enabled{color:var(--nath-menu-list-text)}.nath-menu-item--interactive:hover,.nath-menu-item--interactive:focus,.nath-menu-item--interactive:focus-within{background-color:var(--nath-menu-list-hover-bg)}.nath-menu-item--padded{padding:.5rem 1rem}.nath-menu-item--separator{border-top:1px solid var(--nath-menu-list-border)}.nath-menu-item--clickable{cursor:pointer}.nath-menu-item--header{font-weight:700}.nath-menu-item--disabled{color:var(--nath-menu-list-text-disabled);cursor:default;opacity:.6;pointer-events:none}.nath-menu-item-content{display:flex;align-items:center;gap:.5rem;min-width:0;pointer-events:none}.nath-menu-item-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.nath-menu-item-arrow{font-size:1.5rem;color:var(--nath-menu-list-text-muted);flex-shrink:0;pointer-events:none}.nath-menu-submenu-panel{position:fixed;background-color:var(--nath-menu-list-bg);border:1px solid var(--nath-menu-list-border);border-radius:.5rem;box-shadow:var(--nath-menu-list-shadow);padding:.5rem 0;color:var(--nath-menu-list-text);z-index:var(--nath-menu-list-z-index);overflow:visible;visibility:hidden}.nath-menu-custom-scrollbar::-webkit-scrollbar{width:6px}.nath-menu-custom-scrollbar::-webkit-scrollbar-thumb{background-color:var(--color-zinc-300, oklch(87.1% .006 286.286));border-radius:3px}\n"], dependencies: [{ kind: "component", type: NathMenuList, selector: "nath-menu-list", inputs: ["items", "direction", "flat"], outputs: ["whenCommand"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "component", type: LucideDynamicIcon, selector: "svg[lucideIcon]", inputs: ["lucideIcon"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
1507
1676
|
}
|
|
1508
1677
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NathMenuList, decorators: [{
|
|
1509
1678
|
type: Component,
|
|
1510
|
-
args: [{ selector: 'nath-menu-list', imports: [RouterLink, RouterLinkActive, LucideDynamicIcon], host: {}, encapsulation: ViewEncapsulation.None, template: "<ul class=\"nath-menu-list-theme nath-menu-list nath-menu-custom-scrollbar\">\
|
|
1679
|
+
args: [{ selector: 'nath-menu-list', imports: [RouterLink, RouterLinkActive, LucideDynamicIcon], host: {}, encapsulation: ViewEncapsulation.None, template: "<div (mouseleave)=\"onMouseLeave($event)\">\n <ul class=\"nath-menu-list-theme nath-menu-list nath-menu-custom-scrollbar\">\n @for (item of items(); track $index) {\n <li\n class=\"nath-menu-item\"\n [class.nath-menu-item--enabled]=\"!item.disabled\"\n [class.nath-menu-item--disabled]=\"item.disabled\"\n [class.nath-menu-item--padded]=\"!item.separator\"\n [class.nath-menu-item--separator]=\"item.separator\"\n [class.nath-menu-item--clickable]=\"item.routerLink || item.command || item.url\"\n [class.nath-menu-item--header]=\"!item.routerLink && !item.command && !item.url\"\n [class.nath-menu-item--interactive]=\"\n !item.disabled &&\n (item.routerLink || item.command || item.url || (item.items?.length && !flat()))\n \"\n [routerLink]=\"item.routerLink\"\n [queryParams]=\"item.queryParams\"\n routerLinkActive=\"nath-menu-item--active\"\n [routerLinkActiveOptions]=\"item.routerLinkActiveOptions || { exact: false }\"\n [attr.tabindex]=\"-1\"\n [attr.title]=\"item.title\"\n (mouseenter)=\"!item.disabled && onItemHover(item, $event)\"\n (click)=\"onItemClick(item, $index, $event)\"\n (keydown)=\"$event.preventDefault(); handleKeyDown($event)\"\n (focus)=\"focusedIndex() < 0 && focusedIndex.set($index)\"\n >\n @if (!item.separator) {\n <span class=\"nath-menu-item-content\">\n @if (item.icon) {\n @if (isLucideIconComponent(item.icon)) {\n <svg [lucideIcon]=\"item.icon\" />\n } @else {\n <i [class]=\"item.icon\"></i>\n }\n }\n @if (item.escape === false) {\n <span [innerHTML]=\"getMenuLabel(item)\"></span>\n } @else {\n <span class=\"nath-menu-item-text-truncate\">{{ item.label }}</span>\n }\n </span>\n\n @if (item.items && item.items.length > 0 && !flat()) {\n <span class=\"nath-menu-item-arrow\">\u203A</span>\n }\n }\n </li>\n\n @if (flat() && item.items) {\n <nath-menu-list [items]=\"item.items\" (whenCommand)=\"whenCommand.emit($event)\" />\n }\n } @empty {\n <li class=\"nath-menu-item nath-menu-item--padded nath-menu-item--disabled\">\n No actions available\n </li>\n }\n </ul>\n\n @if (!flat()) {\n @if (activeItem()?.items?.length) {\n <div\n #submenuContainer\n class=\"nath-menu-list-theme nath-menu-submenu-panel\"\n [style.left.px]=\"submenuLeft()\"\n [style.top.px]=\"submenuTop()\"\n >\n <nath-menu-list\n [items]=\"activeItem()!.items!\"\n [direction]=\"nextSubmenuDirection()\"\n (whenCommand)=\"whenCommand.emit($event)\"\n />\n </div>\n }\n }\n</div>\n", styles: ["nath-menu-list,.nath-menu-list-theme{--nath-menu-list-text: var(--color-zinc-700, oklch(37.1% .021 264.444));--nath-menu-list-text-muted: var(--color-zinc-500, oklch(55.2% .016 285.938));--nath-menu-list-text-disabled: var(--color-zinc-300, oklch(87.1% .006 286.286));--nath-menu-list-hover-bg: var(--color-zinc-100, oklch(96.7% .003 264.542));--nath-menu-list-border: var(--color-zinc-200, oklch(92% .004 286.32));--nath-menu-list-bg: #ffffff;--nath-menu-list-shadow: 0 10px 15px -3px rgba(0, 0, 0, .1), 0 4px 6px -2px rgba(0, 0, 0, .05);--nath-menu-list-z-index: 10000}.dark nath-menu-list,.dark .nath-menu-list-theme{--nath-menu-list-text: var(--color-zinc-200, oklch(92% .004 286.32));--nath-menu-list-text-muted: var(--color-zinc-400, oklch(70.5% .015 286.067));--nath-menu-list-text-disabled: var(--color-zinc-600, oklch(44.2% .017 285.786));--nath-menu-list-hover-bg: var(--color-zinc-800, oklch(27.4% .006 286.033));--nath-menu-list-border: var(--color-zinc-700, oklch(37% .013 285.805));--nath-menu-list-bg: var(--color-zinc-900, oklch(21% .006 285.885))}.nath-menu-list{max-height:90vh;overflow-y:auto;overflow-x:hidden;list-style-type:none;margin:0;padding:0;width:100%}.nath-menu-item{position:relative;display:flex;align-items:center;justify-content:space-between;gap:1rem;transition:background-color .15s,color .15s}.nath-menu-item--enabled{color:var(--nath-menu-list-text)}.nath-menu-item--interactive:hover,.nath-menu-item--interactive:focus,.nath-menu-item--interactive:focus-within{background-color:var(--nath-menu-list-hover-bg)}.nath-menu-item--padded{padding:.5rem 1rem}.nath-menu-item--separator{border-top:1px solid var(--nath-menu-list-border)}.nath-menu-item--clickable{cursor:pointer}.nath-menu-item--header{font-weight:700}.nath-menu-item--disabled{color:var(--nath-menu-list-text-disabled);cursor:default;opacity:.6;pointer-events:none}.nath-menu-item-content{display:flex;align-items:center;gap:.5rem;min-width:0;pointer-events:none}.nath-menu-item-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.nath-menu-item-arrow{font-size:1.5rem;color:var(--nath-menu-list-text-muted);flex-shrink:0;pointer-events:none}.nath-menu-submenu-panel{position:fixed;background-color:var(--nath-menu-list-bg);border:1px solid var(--nath-menu-list-border);border-radius:.5rem;box-shadow:var(--nath-menu-list-shadow);padding:.5rem 0;color:var(--nath-menu-list-text);z-index:var(--nath-menu-list-z-index);overflow:visible;visibility:hidden}.nath-menu-custom-scrollbar::-webkit-scrollbar{width:6px}.nath-menu-custom-scrollbar::-webkit-scrollbar-thumb{background-color:var(--color-zinc-300, oklch(87.1% .006 286.286));border-radius:3px}\n"] }]
|
|
1511
1680
|
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], direction: [{ type: i0.Input, args: [{ isSignal: true, alias: "direction", required: false }] }], flat: [{ type: i0.Input, args: [{ isSignal: true, alias: "flat", required: false }] }], whenCommand: [{ type: i0.Output, args: ["whenCommand"] }], submenuContainers: [{ type: i0.ViewChildren, args: ['submenuContainer', { isSignal: true }] }] } });
|
|
1512
1681
|
|
|
1513
1682
|
const TIERED_MENU_LAYOUT_CONFIG = {
|
|
@@ -1519,6 +1688,8 @@ class NathMenu {
|
|
|
1519
1688
|
...(ngDevMode ? [{ debugName: "model" }] : /* istanbul ignore next */ []));
|
|
1520
1689
|
styleClass = model('', /* @ts-ignore */
|
|
1521
1690
|
...(ngDevMode ? [{ debugName: "styleClass" }] : /* istanbul ignore next */ []));
|
|
1691
|
+
panelStyleClass = model('', /* @ts-ignore */
|
|
1692
|
+
...(ngDevMode ? [{ debugName: "panelStyleClass" }] : /* istanbul ignore next */ []));
|
|
1522
1693
|
positionX = input('auto', /* @ts-ignore */
|
|
1523
1694
|
...(ngDevMode ? [{ debugName: "positionX" }] : /* istanbul ignore next */ []));
|
|
1524
1695
|
positionY = input('auto', /* @ts-ignore */
|
|
@@ -1547,12 +1718,12 @@ class NathMenu {
|
|
|
1547
1718
|
show(event) {
|
|
1548
1719
|
event.stopPropagation();
|
|
1549
1720
|
event.preventDefault();
|
|
1550
|
-
let x = event.clientX;
|
|
1551
|
-
let y = event.clientY;
|
|
1552
|
-
const positionX = this.positionX();
|
|
1553
|
-
const positionY = this.positionY();
|
|
1554
1721
|
const target = event.currentTarget;
|
|
1555
1722
|
const targetRect = target.getBoundingClientRect();
|
|
1723
|
+
let x = event instanceof MouseEvent ? event.clientX : targetRect.x;
|
|
1724
|
+
let y = event instanceof MouseEvent ? event.clientY : targetRect.y + targetRect.height;
|
|
1725
|
+
const positionX = this.positionX();
|
|
1726
|
+
const positionY = this.positionY();
|
|
1556
1727
|
if (positionX !== 'auto' && target) {
|
|
1557
1728
|
if (positionX === 'left') {
|
|
1558
1729
|
x = targetRect.left;
|
|
@@ -1609,6 +1780,18 @@ class NathMenu {
|
|
|
1609
1780
|
this.adjustedPosition.set({ x: adjustedX, y: adjustedY });
|
|
1610
1781
|
el.classList.remove('nath-menu-panel--invisible');
|
|
1611
1782
|
});
|
|
1783
|
+
setTimeout(() => {
|
|
1784
|
+
const rootMenuElement = this.rootMenuElement();
|
|
1785
|
+
if (!rootMenuElement)
|
|
1786
|
+
return;
|
|
1787
|
+
const el = rootMenuElement.nativeElement;
|
|
1788
|
+
event.preventDefault();
|
|
1789
|
+
// Focus first item in submenu
|
|
1790
|
+
const submenu = el.querySelector('.nath-menu-item');
|
|
1791
|
+
if (submenu) {
|
|
1792
|
+
submenu.focus();
|
|
1793
|
+
}
|
|
1794
|
+
});
|
|
1612
1795
|
}
|
|
1613
1796
|
hide() {
|
|
1614
1797
|
if (this.isVisible() && !this.inline()) {
|
|
@@ -1645,15 +1828,184 @@ class NathMenu {
|
|
|
1645
1828
|
}
|
|
1646
1829
|
}
|
|
1647
1830
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NathMenu, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1648
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: NathMenu, isStandalone: true, selector: "nath-menu", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: true, isRequired: false, transformFunction: null }, positionX: { classPropertyName: "positionX", publicName: "positionX", isSignal: true, isRequired: false, transformFunction: null }, positionY: { classPropertyName: "positionY", publicName: "positionY", isSignal: true, isRequired: false, transformFunction: null }, inline: { classPropertyName: "inline", publicName: "inline", isSignal: true, isRequired: false, transformFunction: null }, flat: { classPropertyName: "flat", publicName: "flat", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { model: "modelChange", styleClass: "styleClassChange", whenHide: "whenHide" }, host: { listeners: { "document:click": "hide();" }, properties: { "class": "styleClass()" } }, viewQueries: [{ propertyName: "rootMenuElement", first: true, predicate: ["rootMenu"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (isVisible()) {\n <div\n #rootMenu\n class=\"nath-menu-theme nath-menu-panel\"\n [class.nath-menu-panel--inline]=\"inline()\"\n [class.nath-menu-panel--invisible]=\"!inline()\"\n [style.left.px]=\"adjustedPosition().x\"\n [style.top.px]=\"adjustedPosition().y\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"$event.stopPropagation()\"\n >\n <nath-menu-list
|
|
1831
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: NathMenu, isStandalone: true, selector: "nath-menu", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: true, isRequired: false, transformFunction: null }, panelStyleClass: { classPropertyName: "panelStyleClass", publicName: "panelStyleClass", isSignal: true, isRequired: false, transformFunction: null }, positionX: { classPropertyName: "positionX", publicName: "positionX", isSignal: true, isRequired: false, transformFunction: null }, positionY: { classPropertyName: "positionY", publicName: "positionY", isSignal: true, isRequired: false, transformFunction: null }, inline: { classPropertyName: "inline", publicName: "inline", isSignal: true, isRequired: false, transformFunction: null }, flat: { classPropertyName: "flat", publicName: "flat", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { model: "modelChange", styleClass: "styleClassChange", panelStyleClass: "panelStyleClassChange", whenHide: "whenHide" }, host: { listeners: { "document:click": "hide();" }, properties: { "class": "styleClass()" } }, viewQueries: [{ propertyName: "rootMenuElement", first: true, predicate: ["rootMenu"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (isVisible()) {\n <div\n #rootMenu\n class=\"nath-menu-theme nath-menu-panel {{ panelStyleClass() }}\"\n [class.nath-menu-panel--inline]=\"inline()\"\n [class.nath-menu-panel--invisible]=\"!inline()\"\n [style.left.px]=\"adjustedPosition().x\"\n [style.top.px]=\"adjustedPosition().y\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"$event.stopPropagation()\"\n >\n <nath-menu-list\n [items]=\"model()\"\n [flat]=\"flat()\"\n (whenCommand)=\"handleCommand($event)\"\n (keydown.escape)=\"hide()\"\n />\n </div>\n}\n", styles: ["nath-menu,.nath-menu-theme{--nath-menu-bg: #ffffff;--nath-menu-border: var(--color-zinc-200, oklch(92% .004 286.32));--nath-menu-shadow: 0 20px 25px -5px rgba(0, 0, 0, .1), 0 8px 10px -6px rgba(0, 0, 0, .1);--nath-menu-text: var(--color-gray-700, oklch(37.1% .021 264.444));--nath-menu-font-size: .875rem;--nath-menu-padding: .5rem 0;--nath-menu-radius: .5rem;--nath-menu-z-index: 999999}.dark nath-menu,.dark .nath-menu-theme{--nath-menu-bg: var(--color-zinc-900, oklch(21% .006 285.885));--nath-menu-border: var(--color-zinc-700, oklch(37% .013 285.805));--nath-menu-text: var(--color-zinc-200, oklch(92% .004 286.32))}nath-menu{display:block}.nath-menu-panel{position:fixed;background-color:var(--nath-menu-bg);border:1px solid var(--nath-menu-border);border-radius:var(--nath-menu-radius);box-shadow:var(--nath-menu-shadow);padding:var(--nath-menu-padding);font-size:var(--nath-menu-font-size);color:var(--nath-menu-text);z-index:var(--nath-menu-z-index);overflow:visible}.nath-menu-panel--inline{position:static}.nath-menu-panel--invisible{visibility:hidden}\n"], dependencies: [{ kind: "component", type: NathMenuList, selector: "nath-menu-list", inputs: ["items", "direction", "flat"], outputs: ["whenCommand"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
1649
1832
|
}
|
|
1650
1833
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NathMenu, decorators: [{
|
|
1651
1834
|
type: Component,
|
|
1652
1835
|
args: [{ selector: 'nath-menu', imports: [NathMenuList], host: {
|
|
1653
1836
|
'[class]': `styleClass()`,
|
|
1654
1837
|
'(document:click)': `hide();`,
|
|
1655
|
-
}, encapsulation: ViewEncapsulation.None, template: "@if (isVisible()) {\n <div\n #rootMenu\n class=\"nath-menu-theme nath-menu-panel\"\n [class.nath-menu-panel--inline]=\"inline()\"\n [class.nath-menu-panel--invisible]=\"!inline()\"\n [style.left.px]=\"adjustedPosition().x\"\n [style.top.px]=\"adjustedPosition().y\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"$event.stopPropagation()\"\n >\n <nath-menu-list
|
|
1656
|
-
}], propDecorators: { model: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: false }] }, { type: i0.Output, args: ["modelChange"] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }, { type: i0.Output, args: ["styleClassChange"] }], positionX: [{ type: i0.Input, args: [{ isSignal: true, alias: "positionX", required: false }] }], positionY: [{ type: i0.Input, args: [{ isSignal: true, alias: "positionY", required: false }] }], inline: [{ type: i0.Input, args: [{ isSignal: true, alias: "inline", required: false }] }], flat: [{ type: i0.Input, args: [{ isSignal: true, alias: "flat", required: false }] }], whenHide: [{ type: i0.Output, args: ["whenHide"] }], rootMenuElement: [{ type: i0.ViewChild, args: ['rootMenu', { isSignal: true }] }] } });
|
|
1838
|
+
}, encapsulation: ViewEncapsulation.None, template: "@if (isVisible()) {\n <div\n #rootMenu\n class=\"nath-menu-theme nath-menu-panel {{ panelStyleClass() }}\"\n [class.nath-menu-panel--inline]=\"inline()\"\n [class.nath-menu-panel--invisible]=\"!inline()\"\n [style.left.px]=\"adjustedPosition().x\"\n [style.top.px]=\"adjustedPosition().y\"\n (click)=\"$event.stopPropagation()\"\n (keydown.enter)=\"$event.stopPropagation()\"\n >\n <nath-menu-list\n [items]=\"model()\"\n [flat]=\"flat()\"\n (whenCommand)=\"handleCommand($event)\"\n (keydown.escape)=\"hide()\"\n />\n </div>\n}\n", styles: ["nath-menu,.nath-menu-theme{--nath-menu-bg: #ffffff;--nath-menu-border: var(--color-zinc-200, oklch(92% .004 286.32));--nath-menu-shadow: 0 20px 25px -5px rgba(0, 0, 0, .1), 0 8px 10px -6px rgba(0, 0, 0, .1);--nath-menu-text: var(--color-gray-700, oklch(37.1% .021 264.444));--nath-menu-font-size: .875rem;--nath-menu-padding: .5rem 0;--nath-menu-radius: .5rem;--nath-menu-z-index: 999999}.dark nath-menu,.dark .nath-menu-theme{--nath-menu-bg: var(--color-zinc-900, oklch(21% .006 285.885));--nath-menu-border: var(--color-zinc-700, oklch(37% .013 285.805));--nath-menu-text: var(--color-zinc-200, oklch(92% .004 286.32))}nath-menu{display:block}.nath-menu-panel{position:fixed;background-color:var(--nath-menu-bg);border:1px solid var(--nath-menu-border);border-radius:var(--nath-menu-radius);box-shadow:var(--nath-menu-shadow);padding:var(--nath-menu-padding);font-size:var(--nath-menu-font-size);color:var(--nath-menu-text);z-index:var(--nath-menu-z-index);overflow:visible}.nath-menu-panel--inline{position:static}.nath-menu-panel--invisible{visibility:hidden}\n"] }]
|
|
1839
|
+
}], propDecorators: { model: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: false }] }, { type: i0.Output, args: ["modelChange"] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }, { type: i0.Output, args: ["styleClassChange"] }], panelStyleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelStyleClass", required: false }] }, { type: i0.Output, args: ["panelStyleClassChange"] }], positionX: [{ type: i0.Input, args: [{ isSignal: true, alias: "positionX", required: false }] }], positionY: [{ type: i0.Input, args: [{ isSignal: true, alias: "positionY", required: false }] }], inline: [{ type: i0.Input, args: [{ isSignal: true, alias: "inline", required: false }] }], flat: [{ type: i0.Input, args: [{ isSignal: true, alias: "flat", required: false }] }], whenHide: [{ type: i0.Output, args: ["whenHide"] }], rootMenuElement: [{ type: i0.ViewChild, args: ['rootMenu', { isSignal: true }] }] } });
|
|
1840
|
+
|
|
1841
|
+
class NathMenuBar {
|
|
1842
|
+
document = inject(DOCUMENT);
|
|
1843
|
+
sanitizer = inject(DomSanitizer);
|
|
1844
|
+
destroyRef = inject(DestroyRef);
|
|
1845
|
+
model = input([], /* @ts-ignore */
|
|
1846
|
+
...(ngDevMode ? [{ debugName: "model" }] : /* istanbul ignore next */ []));
|
|
1847
|
+
styleClass = input('', /* @ts-ignore */
|
|
1848
|
+
...(ngDevMode ? [{ debugName: "styleClass" }] : /* istanbul ignore next */ []));
|
|
1849
|
+
whenCommand = output();
|
|
1850
|
+
menuBarElement = viewChild('menuBar', /* @ts-ignore */
|
|
1851
|
+
...(ngDevMode ? [{ debugName: "menuBarElement" }] : /* istanbul ignore next */ []));
|
|
1852
|
+
dropdownMenu = viewChild('dropdownMenu', /* @ts-ignore */
|
|
1853
|
+
...(ngDevMode ? [{ debugName: "dropdownMenu" }] : /* istanbul ignore next */ []));
|
|
1854
|
+
isMobileMenuOpen = signal(false, /* @ts-ignore */
|
|
1855
|
+
...(ngDevMode ? [{ debugName: "isMobileMenuOpen" }] : /* istanbul ignore next */ []));
|
|
1856
|
+
activeItem = signal(null, /* @ts-ignore */
|
|
1857
|
+
...(ngDevMode ? [{ debugName: "activeItem" }] : /* istanbul ignore next */ []));
|
|
1858
|
+
activeItemIndex = signal(-1, /* @ts-ignore */
|
|
1859
|
+
...(ngDevMode ? [{ debugName: "activeItemIndex" }] : /* istanbul ignore next */ []));
|
|
1860
|
+
focusedIndex = signal(-1, /* @ts-ignore */
|
|
1861
|
+
...(ngDevMode ? [{ debugName: "focusedIndex" }] : /* istanbul ignore next */ []));
|
|
1862
|
+
menuItemsElements = signal([], /* @ts-ignore */
|
|
1863
|
+
...(ngDevMode ? [{ debugName: "menuItemsElements" }] : /* istanbul ignore next */ []));
|
|
1864
|
+
ngAfterViewInit() {
|
|
1865
|
+
const menuBar = this.menuBarElement()?.nativeElement;
|
|
1866
|
+
if (menuBar) {
|
|
1867
|
+
const items = Array.from(menuBar.querySelectorAll('.nath-menu-bar-item'));
|
|
1868
|
+
this.menuItemsElements.set(items);
|
|
1869
|
+
}
|
|
1870
|
+
fromEvent(this.document, 'keydown')
|
|
1871
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
1872
|
+
.subscribe((event) => this.handleKeyDown(event));
|
|
1873
|
+
}
|
|
1874
|
+
handleDocumentClick(event) {
|
|
1875
|
+
const menuBar = this.menuBarElement()?.nativeElement;
|
|
1876
|
+
if (!menuBar)
|
|
1877
|
+
return;
|
|
1878
|
+
if (!menuBar.contains(event.target)) {
|
|
1879
|
+
this.closeAllMenus();
|
|
1880
|
+
this.isMobileMenuOpen.set(false);
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
handleItemClick(item, index, event) {
|
|
1884
|
+
if (item.disabled)
|
|
1885
|
+
return;
|
|
1886
|
+
event.stopPropagation();
|
|
1887
|
+
if (item.items && item.items.length > 0) {
|
|
1888
|
+
this.toggleSubmenu(item, index, event);
|
|
1889
|
+
}
|
|
1890
|
+
else {
|
|
1891
|
+
this.executeItem(item, index, event);
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1894
|
+
handleItemHover(item, index, event) {
|
|
1895
|
+
if (this.isMobileMenuOpen())
|
|
1896
|
+
return;
|
|
1897
|
+
if (item.items && item.items.length > 0) {
|
|
1898
|
+
this.activeItem.set(item);
|
|
1899
|
+
this.activeItemIndex.set(index);
|
|
1900
|
+
if (this.activeItem()?.items?.length) {
|
|
1901
|
+
this.dropdownMenu()?.show(event);
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
toggleSubmenu(item, index, event) {
|
|
1906
|
+
if (this.activeItem() === item) {
|
|
1907
|
+
this.activeItem.set(null);
|
|
1908
|
+
this.activeItemIndex.set(-1);
|
|
1909
|
+
}
|
|
1910
|
+
else {
|
|
1911
|
+
this.activeItem.set(item);
|
|
1912
|
+
this.activeItemIndex.set(index);
|
|
1913
|
+
if (!this.isMobileMenuOpen() && this.activeItem()?.items?.length) {
|
|
1914
|
+
this.dropdownMenu()?.show(event);
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
closeAllMenus() {
|
|
1919
|
+
this.activeItem.set(null);
|
|
1920
|
+
this.activeItemIndex.set(-1);
|
|
1921
|
+
}
|
|
1922
|
+
toggleMobileMenu() {
|
|
1923
|
+
this.isMobileMenuOpen.update((open) => !open);
|
|
1924
|
+
if (!this.isMobileMenuOpen()) {
|
|
1925
|
+
this.closeAllMenus();
|
|
1926
|
+
}
|
|
1927
|
+
}
|
|
1928
|
+
executeItem(item, index, event) {
|
|
1929
|
+
if (item.command) {
|
|
1930
|
+
item.command({
|
|
1931
|
+
originalEvent: event,
|
|
1932
|
+
item,
|
|
1933
|
+
index,
|
|
1934
|
+
});
|
|
1935
|
+
}
|
|
1936
|
+
this.whenCommand.emit({ item, index, event });
|
|
1937
|
+
this.closeAllMenus();
|
|
1938
|
+
this.isMobileMenuOpen.set(false);
|
|
1939
|
+
}
|
|
1940
|
+
handleKeyDown(event) {
|
|
1941
|
+
const items = this.menuItemsElements();
|
|
1942
|
+
if (items.length === 0)
|
|
1943
|
+
return;
|
|
1944
|
+
const currentIndex = this.focusedIndex();
|
|
1945
|
+
let newIndex;
|
|
1946
|
+
switch (event.key) {
|
|
1947
|
+
case 'ArrowRight':
|
|
1948
|
+
event.preventDefault();
|
|
1949
|
+
newIndex = currentIndex < items.length - 1 ? currentIndex + 1 : 0;
|
|
1950
|
+
break;
|
|
1951
|
+
case 'ArrowLeft':
|
|
1952
|
+
event.preventDefault();
|
|
1953
|
+
newIndex = currentIndex > 0 ? currentIndex - 1 : items.length - 1;
|
|
1954
|
+
break;
|
|
1955
|
+
case 'ArrowDown':
|
|
1956
|
+
return;
|
|
1957
|
+
case 'Escape':
|
|
1958
|
+
event.preventDefault();
|
|
1959
|
+
this.closeAllMenus();
|
|
1960
|
+
this.isMobileMenuOpen.set(false);
|
|
1961
|
+
this.focusedIndex.set(-1);
|
|
1962
|
+
return;
|
|
1963
|
+
case 'Enter':
|
|
1964
|
+
case ' ':
|
|
1965
|
+
event.preventDefault();
|
|
1966
|
+
if (currentIndex >= 0 && currentIndex < items.length) {
|
|
1967
|
+
const item = this.model()[currentIndex];
|
|
1968
|
+
this.handleItemClick(item, currentIndex, event);
|
|
1969
|
+
}
|
|
1970
|
+
return;
|
|
1971
|
+
default:
|
|
1972
|
+
return;
|
|
1973
|
+
}
|
|
1974
|
+
this.focusedIndex.set(newIndex);
|
|
1975
|
+
items[newIndex]?.focus();
|
|
1976
|
+
}
|
|
1977
|
+
handleSubmenuCommand(payload) {
|
|
1978
|
+
this.executeItem(payload.item, payload.index, payload.event);
|
|
1979
|
+
}
|
|
1980
|
+
getMenuLabel(item) {
|
|
1981
|
+
if (!item.label)
|
|
1982
|
+
return '';
|
|
1983
|
+
return item.escape === false
|
|
1984
|
+
? (this.sanitizer.sanitize(SecurityContext.HTML, item.label) ?? '')
|
|
1985
|
+
: item.label;
|
|
1986
|
+
}
|
|
1987
|
+
isLucideIconComponent = isLucideIconComponent;
|
|
1988
|
+
ngOnDestroy() {
|
|
1989
|
+
this.closeAllMenus();
|
|
1990
|
+
}
|
|
1991
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NathMenuBar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1992
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: NathMenuBar, isStandalone: true, selector: "nath-menu-bar", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { whenCommand: "whenCommand" }, host: { listeners: { "document:click": "handleDocumentClick($event)" }, properties: { "class": "styleClass()" } }, viewQueries: [{ propertyName: "menuBarElement", first: true, predicate: ["menuBar"], descendants: true, isSignal: true }, { propertyName: "dropdownMenu", first: true, predicate: ["dropdownMenu"], descendants: true, isSignal: true }], ngImport: i0, template: "<nav #menuBar class=\"nath-menu-bar-theme nath-menu-bar\" role=\"menubar\">\n <!-- Desktop Menu Bar -->\n <ul class=\"nath-menu-bar-list\">\n @for (item of model(); track item.label; let index = $index) {\n <li\n class=\"nath-menu-bar-item\"\n [class.nath-menu-bar-item--active]=\"activeItem() === item\"\n [class.nath-menu-bar-item--disabled]=\"item.disabled\"\n [class.nath-menu-bar-item--focused]=\"focusedIndex() === index\"\n [attr.tabindex]=\"item.disabled ? -1 : 0\"\n [attr.role]=\"item.items && item.items.length > 0 ? 'menuitem' : 'menuitem'\"\n [attr.aria-haspopup]=\"item.items && item.items.length > 0 ? 'true' : 'false'\"\n [attr.aria-expanded]=\"activeItem() === item ? 'true' : 'false'\"\n (mouseenter)=\"handleItemHover(item, index, $event)\"\n (click)=\"handleItemClick(item, index, $event)\"\n (keydown)=\"handleKeyDown($event)\"\n >\n <span class=\"nath-menu-bar-item-content\">\n @if (item.icon) {\n @if (isLucideIconComponent(item.icon)) {\n <svg [lucideIcon]=\"item.icon\" [size]=\"16\" />\n } @else {\n <i [class]=\"item.icon\"></i>\n }\n }\n @if (item.escape === false) {\n <span [innerHTML]=\"getMenuLabel(item)\"></span>\n } @else {\n <span>{{ item.label }}</span>\n }\n @if (item.items && item.items.length > 0) {\n <svg lucideChevronDown [size]=\"14\" class=\"nath-menu-bar-arrow\" />\n }\n </span>\n\n @if (item.routerLink) {\n <a\n [routerLink]=\"item.routerLink\"\n [queryParams]=\"item.queryParams\"\n [fragment]=\"item.fragment\"\n [queryParamsHandling]=\"item.queryParamsHandling\"\n [preserveFragment]=\"item.preserveFragment\"\n [skipLocationChange]=\"item.skipLocationChange\"\n [replaceUrl]=\"item.replaceUrl\"\n [state]=\"item.state\"\n [attr.target]=\"item.target\"\n class=\"nath-menu-bar-link\"\n ><span></span\n ></a>\n } @else if (item.url) {\n <a [href]=\"item.url\" [attr.target]=\"item.target || '_blank'\" class=\"nath-menu-bar-link\"\n ><span></span\n ></a>\n }\n </li>\n }\n </ul>\n\n <!-- Mobile Menu Button -->\n <button\n class=\"nath-menu-bar-toggle\"\n [class.nath-menu-bar-toggle--active]=\"isMobileMenuOpen()\"\n (click)=\"toggleMobileMenu()\"\n [attr.aria-label]=\"isMobileMenuOpen() ? 'Close menu' : 'Open menu'\"\n [attr.aria-expanded]=\"isMobileMenuOpen()\"\n >\n @if (isMobileMenuOpen()) {\n <svg lucideX [size]=\"24\" />\n } @else {\n <svg lucideMenu [size]=\"24\" />\n }\n </button>\n</nav>\n\n<!-- Mobile Menu Overlay -->\n@if (isMobileMenuOpen()) {\n <div\n class=\"nath-menu-bar-mobile-overlay\"\n (click)=\"toggleMobileMenu()\"\n (keydown.enter)=\"toggleMobileMenu()\"\n ></div>\n}\n\n<!-- Mobile Menu Panel -->\n@if (isMobileMenuOpen()) {\n <div class=\"nath-menu-bar-mobile-panel\">\n <ul class=\"nath-menu-bar-mobile-list\">\n @for (item of model(); track item.label; let index = $index) {\n <li\n class=\"nath-menu-bar-mobile-item\"\n [class.nath-menu-bar-mobile-item--disabled]=\"item.disabled\"\n [class.nath-menu-bar-mobile-item--expanded]=\"activeItem() === item\"\n >\n <div\n class=\"nath-menu-bar-mobile-item-content\"\n (click)=\"handleItemClick(item, index, $event)\"\n (keydown.enter)=\"handleItemClick(item, index, $event)\"\n >\n <span class=\"nath-menu-bar-mobile-item-text\">\n @if (item.icon) {\n @if (isLucideIconComponent(item.icon)) {\n <svg [lucideIcon]=\"item.icon\" [size]=\"18\" />\n } @else {\n <i [class]=\"item.icon\"></i>\n }\n }\n <span>{{ item.label }}</span>\n </span>\n @if (item.items && item.items.length > 0) {\n <svg\n lucideChevronDown\n [size]=\"16\"\n class=\"nath-menu-bar-mobile-arrow\"\n [class.nath-menu-bar-mobile-arrow--rotated]=\"activeItem() === item\"\n />\n }\n </div>\n\n @if (item.items && item.items.length > 0 && activeItem() === item) {\n <ul class=\"nath-menu-bar-mobile-submenu\">\n @for (subItem of item.items; track subItem.label; let subIndex = $index) {\n <li\n class=\"nath-menu-bar-mobile-submenu-item\"\n [class.nath-menu-bar-mobile-submenu-item--disabled]=\"subItem.disabled\"\n (click)=\"handleItemClick(subItem, subIndex, $event)\"\n (keydown.enter)=\"handleItemClick(subItem, subIndex, $event)\"\n >\n <span class=\"nath-menu-bar-mobile-submenu-item-text\">\n @if (subItem.icon) {\n @if (isLucideIconComponent(subItem.icon)) {\n <svg [lucideIcon]=\"subItem.icon\" [size]=\"16\" />\n } @else {\n <i [class]=\"subItem.icon\"></i>\n }\n }\n <span>{{ subItem.label }}</span>\n </span>\n </li>\n }\n </ul>\n }\n </li>\n }\n </ul>\n </div>\n}\n<nath-menu\n #dropdownMenu\n [model]=\"activeItem()?.items ?? []\"\n [positionX]=\"'left'\"\n [positionY]=\"'bottom'\"\n panelStyleClass=\"nath-menu-bar-dropdown\"\n/>\n", styles: ["nath-menu-bar,.nath-menu-bar-theme{--nath-menu-bar-bg: #ffffff;--nath-menu-bar-border: var(--color-zinc-200, oklch(92% .004 286.32));--nath-menu-bar-text: var(--color-gray-700, oklch(37.1% .021 264.444));--nath-menu-bar-hover-bg: var(--color-zinc-100, oklch(96.7% .003 264.542));--nath-menu-bar-active-bg: var(--color-zinc-100, oklch(96.7% .003 264.542));--nath-menu-bar-shadow: 0 4px 6px -1px rgba(0, 0, 0, .1), 0 2px 4px -1px rgba(0, 0, 0, .06);--nath-menu-bar-font-size: .875rem;--nath-menu-bar-height: 3rem;--nath-menu-bar-z-index: 1000}.dark nath-menu-bar,.dark .nath-menu-bar-theme{--nath-menu-bar-bg: var(--color-zinc-900, oklch(21% .006 285.885));--nath-menu-bar-border: var(--color-zinc-700, oklch(37% .013 285.805));--nath-menu-bar-text: var(--color-zinc-200, oklch(92% .004 286.32));--nath-menu-bar-hover-bg: var(--color-zinc-800, oklch(27.4% .006 286.033));--nath-menu-bar-active-bg: var(--color-zinc-800, oklch(27.4% .006 286.033))}.nath-menu-bar{position:relative;display:flex;align-items:center;justify-content:space-between;background-color:var(--nath-menu-bar-bg);border-bottom:1px solid var(--nath-menu-bar-border);height:var(--nath-menu-bar-height);padding:0 1rem;font-size:var(--nath-menu-bar-font-size);color:var(--nath-menu-bar-text);z-index:var(--nath-menu-bar-z-index)}.nath-menu-bar-list{display:flex;list-style:none;margin:0;padding:0;gap:.5rem}.nath-menu-bar-item{position:relative;display:flex;align-items:center;padding:.5rem .75rem;border-radius:.375rem;cursor:pointer;transition:background-color .15s ease;outline:none}.nath-menu-bar-item:hover:not(.nath-menu-bar-item--disabled){background-color:var(--nath-menu-bar-hover-bg)}.nath-menu-bar-item--active{background-color:var(--nath-menu-bar-active-bg)}.nath-menu-bar-item--disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.nath-menu-bar-item--focused{box-shadow:0 0 0 2px var(--color-blue-500, oklch(.5 .15 250))}.nath-menu-bar-item-content{display:flex;align-items:center;gap:.5rem;color:var(--nath-menu-bar-text);text-decoration:none}.nath-menu-bar-item-content svg{flex-shrink:0}.nath-menu-bar-arrow{margin-left:.25rem;color:var(--nath-menu-bar-text);opacity:.7;transition:transform .2s ease}.nath-menu-bar-item--active .nath-menu-bar-arrow{transform:rotate(180deg)}.nath-menu-bar-link{position:absolute;inset:0;text-decoration:none}.nath-menu-bar-toggle{display:none;align-items:center;justify-content:center;width:2.5rem;height:2.5rem;padding:0;background:transparent;border:none;border-radius:.375rem;cursor:pointer;color:var(--nath-menu-bar-text);transition:background-color .15s ease}.nath-menu-bar-toggle:hover{background-color:var(--nath-menu-bar-hover-bg)}.nath-menu-bar-toggle:focus{outline:none;box-shadow:0 0 0 2px var(--color-blue-500, oklch(.5 .15 250))}.nath-menu-bar-mobile-overlay{position:fixed;inset:0;background-color:#00000080;z-index:calc(var(--nath-menu-bar-z-index) - 1)}.nath-menu-bar-mobile-panel{position:fixed;top:var(--nath-menu-bar-height);left:0;right:0;bottom:0;background-color:var(--nath-menu-bar-bg);overflow-y:auto;z-index:var(--nath-menu-bar-z-index);padding:1rem}.nath-menu-bar-mobile-list{list-style:none;margin:0;padding:0}.nath-menu-bar-mobile-item{border-bottom:1px solid var(--nath-menu-bar-border)}.nath-menu-bar-mobile-item:last-child{border-bottom:none}.nath-menu-bar-mobile-item--disabled{opacity:.5;pointer-events:none}.nath-menu-bar-mobile-item-content{display:flex;align-items:center;justify-content:space-between;padding:1rem;cursor:pointer;transition:background-color .15s ease}.nath-menu-bar-mobile-item-content:hover{background-color:var(--nath-menu-bar-hover-bg)}.nath-menu-bar-mobile-item-text{display:flex;align-items:center;gap:.75rem;font-weight:500}.nath-menu-bar-mobile-arrow{transition:transform .2s ease}.nath-menu-bar-mobile-arrow--rotated{transform:rotate(180deg)}.nath-menu-bar-mobile-submenu{list-style:none;margin:0;padding:0 0 0 1.5rem;background-color:var(--nath-menu-bar-hover-bg)}.nath-menu-bar-mobile-submenu-item{padding:.75rem 1rem;cursor:pointer;transition:background-color .15s ease;border-bottom:1px solid var(--nath-menu-bar-border)}.nath-menu-bar-mobile-submenu-item:last-child{border-bottom:none}.nath-menu-bar-mobile-submenu-item:hover{background-color:var(--nath-menu-bar-active-bg)}.nath-menu-bar-mobile-submenu-item--disabled{opacity:.5;pointer-events:none}.nath-menu-bar-mobile-submenu-item-text{display:flex;align-items:center;gap:.75rem}@media(max-width:768px){.nath-menu-bar-list{display:none}.nath-menu-bar-toggle{display:flex}.nath-menu-bar-dropdown{display:none}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "component", type: NathMenu, selector: "nath-menu", inputs: ["model", "styleClass", "panelStyleClass", "positionX", "positionY", "inline", "flat"], outputs: ["modelChange", "styleClassChange", "panelStyleClassChange", "whenHide"] }, { kind: "component", type: LucideMenu, selector: "svg[lucideMenu]" }, { kind: "component", type: LucideX, selector: "svg[lucideX]" }, { kind: "component", type: LucideChevronDown, selector: "svg[lucideChevronDown]" }, { kind: "component", type: LucideDynamicIcon, selector: "svg[lucideIcon]", inputs: ["lucideIcon"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
1993
|
+
}
|
|
1994
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NathMenuBar, decorators: [{
|
|
1995
|
+
type: Component,
|
|
1996
|
+
args: [{ selector: 'nath-menu-bar', imports: [
|
|
1997
|
+
CommonModule,
|
|
1998
|
+
RouterLink,
|
|
1999
|
+
NathMenu,
|
|
2000
|
+
LucideMenu,
|
|
2001
|
+
LucideX,
|
|
2002
|
+
LucideChevronDown,
|
|
2003
|
+
LucideDynamicIcon,
|
|
2004
|
+
], host: {
|
|
2005
|
+
'[class]': `styleClass()`,
|
|
2006
|
+
'(document:click)': `handleDocumentClick($event)`,
|
|
2007
|
+
}, encapsulation: ViewEncapsulation.None, template: "<nav #menuBar class=\"nath-menu-bar-theme nath-menu-bar\" role=\"menubar\">\n <!-- Desktop Menu Bar -->\n <ul class=\"nath-menu-bar-list\">\n @for (item of model(); track item.label; let index = $index) {\n <li\n class=\"nath-menu-bar-item\"\n [class.nath-menu-bar-item--active]=\"activeItem() === item\"\n [class.nath-menu-bar-item--disabled]=\"item.disabled\"\n [class.nath-menu-bar-item--focused]=\"focusedIndex() === index\"\n [attr.tabindex]=\"item.disabled ? -1 : 0\"\n [attr.role]=\"item.items && item.items.length > 0 ? 'menuitem' : 'menuitem'\"\n [attr.aria-haspopup]=\"item.items && item.items.length > 0 ? 'true' : 'false'\"\n [attr.aria-expanded]=\"activeItem() === item ? 'true' : 'false'\"\n (mouseenter)=\"handleItemHover(item, index, $event)\"\n (click)=\"handleItemClick(item, index, $event)\"\n (keydown)=\"handleKeyDown($event)\"\n >\n <span class=\"nath-menu-bar-item-content\">\n @if (item.icon) {\n @if (isLucideIconComponent(item.icon)) {\n <svg [lucideIcon]=\"item.icon\" [size]=\"16\" />\n } @else {\n <i [class]=\"item.icon\"></i>\n }\n }\n @if (item.escape === false) {\n <span [innerHTML]=\"getMenuLabel(item)\"></span>\n } @else {\n <span>{{ item.label }}</span>\n }\n @if (item.items && item.items.length > 0) {\n <svg lucideChevronDown [size]=\"14\" class=\"nath-menu-bar-arrow\" />\n }\n </span>\n\n @if (item.routerLink) {\n <a\n [routerLink]=\"item.routerLink\"\n [queryParams]=\"item.queryParams\"\n [fragment]=\"item.fragment\"\n [queryParamsHandling]=\"item.queryParamsHandling\"\n [preserveFragment]=\"item.preserveFragment\"\n [skipLocationChange]=\"item.skipLocationChange\"\n [replaceUrl]=\"item.replaceUrl\"\n [state]=\"item.state\"\n [attr.target]=\"item.target\"\n class=\"nath-menu-bar-link\"\n ><span></span\n ></a>\n } @else if (item.url) {\n <a [href]=\"item.url\" [attr.target]=\"item.target || '_blank'\" class=\"nath-menu-bar-link\"\n ><span></span\n ></a>\n }\n </li>\n }\n </ul>\n\n <!-- Mobile Menu Button -->\n <button\n class=\"nath-menu-bar-toggle\"\n [class.nath-menu-bar-toggle--active]=\"isMobileMenuOpen()\"\n (click)=\"toggleMobileMenu()\"\n [attr.aria-label]=\"isMobileMenuOpen() ? 'Close menu' : 'Open menu'\"\n [attr.aria-expanded]=\"isMobileMenuOpen()\"\n >\n @if (isMobileMenuOpen()) {\n <svg lucideX [size]=\"24\" />\n } @else {\n <svg lucideMenu [size]=\"24\" />\n }\n </button>\n</nav>\n\n<!-- Mobile Menu Overlay -->\n@if (isMobileMenuOpen()) {\n <div\n class=\"nath-menu-bar-mobile-overlay\"\n (click)=\"toggleMobileMenu()\"\n (keydown.enter)=\"toggleMobileMenu()\"\n ></div>\n}\n\n<!-- Mobile Menu Panel -->\n@if (isMobileMenuOpen()) {\n <div class=\"nath-menu-bar-mobile-panel\">\n <ul class=\"nath-menu-bar-mobile-list\">\n @for (item of model(); track item.label; let index = $index) {\n <li\n class=\"nath-menu-bar-mobile-item\"\n [class.nath-menu-bar-mobile-item--disabled]=\"item.disabled\"\n [class.nath-menu-bar-mobile-item--expanded]=\"activeItem() === item\"\n >\n <div\n class=\"nath-menu-bar-mobile-item-content\"\n (click)=\"handleItemClick(item, index, $event)\"\n (keydown.enter)=\"handleItemClick(item, index, $event)\"\n >\n <span class=\"nath-menu-bar-mobile-item-text\">\n @if (item.icon) {\n @if (isLucideIconComponent(item.icon)) {\n <svg [lucideIcon]=\"item.icon\" [size]=\"18\" />\n } @else {\n <i [class]=\"item.icon\"></i>\n }\n }\n <span>{{ item.label }}</span>\n </span>\n @if (item.items && item.items.length > 0) {\n <svg\n lucideChevronDown\n [size]=\"16\"\n class=\"nath-menu-bar-mobile-arrow\"\n [class.nath-menu-bar-mobile-arrow--rotated]=\"activeItem() === item\"\n />\n }\n </div>\n\n @if (item.items && item.items.length > 0 && activeItem() === item) {\n <ul class=\"nath-menu-bar-mobile-submenu\">\n @for (subItem of item.items; track subItem.label; let subIndex = $index) {\n <li\n class=\"nath-menu-bar-mobile-submenu-item\"\n [class.nath-menu-bar-mobile-submenu-item--disabled]=\"subItem.disabled\"\n (click)=\"handleItemClick(subItem, subIndex, $event)\"\n (keydown.enter)=\"handleItemClick(subItem, subIndex, $event)\"\n >\n <span class=\"nath-menu-bar-mobile-submenu-item-text\">\n @if (subItem.icon) {\n @if (isLucideIconComponent(subItem.icon)) {\n <svg [lucideIcon]=\"subItem.icon\" [size]=\"16\" />\n } @else {\n <i [class]=\"subItem.icon\"></i>\n }\n }\n <span>{{ subItem.label }}</span>\n </span>\n </li>\n }\n </ul>\n }\n </li>\n }\n </ul>\n </div>\n}\n<nath-menu\n #dropdownMenu\n [model]=\"activeItem()?.items ?? []\"\n [positionX]=\"'left'\"\n [positionY]=\"'bottom'\"\n panelStyleClass=\"nath-menu-bar-dropdown\"\n/>\n", styles: ["nath-menu-bar,.nath-menu-bar-theme{--nath-menu-bar-bg: #ffffff;--nath-menu-bar-border: var(--color-zinc-200, oklch(92% .004 286.32));--nath-menu-bar-text: var(--color-gray-700, oklch(37.1% .021 264.444));--nath-menu-bar-hover-bg: var(--color-zinc-100, oklch(96.7% .003 264.542));--nath-menu-bar-active-bg: var(--color-zinc-100, oklch(96.7% .003 264.542));--nath-menu-bar-shadow: 0 4px 6px -1px rgba(0, 0, 0, .1), 0 2px 4px -1px rgba(0, 0, 0, .06);--nath-menu-bar-font-size: .875rem;--nath-menu-bar-height: 3rem;--nath-menu-bar-z-index: 1000}.dark nath-menu-bar,.dark .nath-menu-bar-theme{--nath-menu-bar-bg: var(--color-zinc-900, oklch(21% .006 285.885));--nath-menu-bar-border: var(--color-zinc-700, oklch(37% .013 285.805));--nath-menu-bar-text: var(--color-zinc-200, oklch(92% .004 286.32));--nath-menu-bar-hover-bg: var(--color-zinc-800, oklch(27.4% .006 286.033));--nath-menu-bar-active-bg: var(--color-zinc-800, oklch(27.4% .006 286.033))}.nath-menu-bar{position:relative;display:flex;align-items:center;justify-content:space-between;background-color:var(--nath-menu-bar-bg);border-bottom:1px solid var(--nath-menu-bar-border);height:var(--nath-menu-bar-height);padding:0 1rem;font-size:var(--nath-menu-bar-font-size);color:var(--nath-menu-bar-text);z-index:var(--nath-menu-bar-z-index)}.nath-menu-bar-list{display:flex;list-style:none;margin:0;padding:0;gap:.5rem}.nath-menu-bar-item{position:relative;display:flex;align-items:center;padding:.5rem .75rem;border-radius:.375rem;cursor:pointer;transition:background-color .15s ease;outline:none}.nath-menu-bar-item:hover:not(.nath-menu-bar-item--disabled){background-color:var(--nath-menu-bar-hover-bg)}.nath-menu-bar-item--active{background-color:var(--nath-menu-bar-active-bg)}.nath-menu-bar-item--disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.nath-menu-bar-item--focused{box-shadow:0 0 0 2px var(--color-blue-500, oklch(.5 .15 250))}.nath-menu-bar-item-content{display:flex;align-items:center;gap:.5rem;color:var(--nath-menu-bar-text);text-decoration:none}.nath-menu-bar-item-content svg{flex-shrink:0}.nath-menu-bar-arrow{margin-left:.25rem;color:var(--nath-menu-bar-text);opacity:.7;transition:transform .2s ease}.nath-menu-bar-item--active .nath-menu-bar-arrow{transform:rotate(180deg)}.nath-menu-bar-link{position:absolute;inset:0;text-decoration:none}.nath-menu-bar-toggle{display:none;align-items:center;justify-content:center;width:2.5rem;height:2.5rem;padding:0;background:transparent;border:none;border-radius:.375rem;cursor:pointer;color:var(--nath-menu-bar-text);transition:background-color .15s ease}.nath-menu-bar-toggle:hover{background-color:var(--nath-menu-bar-hover-bg)}.nath-menu-bar-toggle:focus{outline:none;box-shadow:0 0 0 2px var(--color-blue-500, oklch(.5 .15 250))}.nath-menu-bar-mobile-overlay{position:fixed;inset:0;background-color:#00000080;z-index:calc(var(--nath-menu-bar-z-index) - 1)}.nath-menu-bar-mobile-panel{position:fixed;top:var(--nath-menu-bar-height);left:0;right:0;bottom:0;background-color:var(--nath-menu-bar-bg);overflow-y:auto;z-index:var(--nath-menu-bar-z-index);padding:1rem}.nath-menu-bar-mobile-list{list-style:none;margin:0;padding:0}.nath-menu-bar-mobile-item{border-bottom:1px solid var(--nath-menu-bar-border)}.nath-menu-bar-mobile-item:last-child{border-bottom:none}.nath-menu-bar-mobile-item--disabled{opacity:.5;pointer-events:none}.nath-menu-bar-mobile-item-content{display:flex;align-items:center;justify-content:space-between;padding:1rem;cursor:pointer;transition:background-color .15s ease}.nath-menu-bar-mobile-item-content:hover{background-color:var(--nath-menu-bar-hover-bg)}.nath-menu-bar-mobile-item-text{display:flex;align-items:center;gap:.75rem;font-weight:500}.nath-menu-bar-mobile-arrow{transition:transform .2s ease}.nath-menu-bar-mobile-arrow--rotated{transform:rotate(180deg)}.nath-menu-bar-mobile-submenu{list-style:none;margin:0;padding:0 0 0 1.5rem;background-color:var(--nath-menu-bar-hover-bg)}.nath-menu-bar-mobile-submenu-item{padding:.75rem 1rem;cursor:pointer;transition:background-color .15s ease;border-bottom:1px solid var(--nath-menu-bar-border)}.nath-menu-bar-mobile-submenu-item:last-child{border-bottom:none}.nath-menu-bar-mobile-submenu-item:hover{background-color:var(--nath-menu-bar-active-bg)}.nath-menu-bar-mobile-submenu-item--disabled{opacity:.5;pointer-events:none}.nath-menu-bar-mobile-submenu-item-text{display:flex;align-items:center;gap:.75rem}@media(max-width:768px){.nath-menu-bar-list{display:none}.nath-menu-bar-toggle{display:flex}.nath-menu-bar-dropdown{display:none}}\n"] }]
|
|
2008
|
+
}], propDecorators: { model: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: false }] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], whenCommand: [{ type: i0.Output, args: ["whenCommand"] }], menuBarElement: [{ type: i0.ViewChild, args: ['menuBar', { isSignal: true }] }], dropdownMenu: [{ type: i0.ViewChild, args: ['dropdownMenu', { isSignal: true }] }] } });
|
|
1657
2009
|
|
|
1658
2010
|
let nextId$1 = 0;
|
|
1659
2011
|
class NathMultiselect {
|
|
@@ -4810,7 +5162,7 @@ class NathSplitButton {
|
|
|
4810
5162
|
</button>
|
|
4811
5163
|
</div>
|
|
4812
5164
|
<nath-menu [model]="menu()" [positionX]="positionX()" [positionY]="positionY()" />
|
|
4813
|
-
`, isInline: true, styles: ["nath-split-button,.nath-split-button-theme{--nath-split-button-border: var(--color-zinc-300, oklch(83.1% .007 285.938));--nath-split-button-bg: var(--color-zinc-100, oklch(96.7% .003 286.375));--nath-split-button-text: var(--color-zinc-900, oklch(21% .006 285.885));--nath-split-button-hover-bg: var(--color-zinc-200, oklch(92% .004 286.32));--nath-split-button-active-bg: var(--color-zinc-300, oklch(83.1% .007 285.938));--nath-split-button-radius: .375rem}.dark nath-split-button,.dark .nath-split-button-theme{--nath-split-button-border: var(--color-zinc-700, oklch(37.1% .008 285.539));--nath-split-button-bg: var(--color-zinc-800, oklch(27.8% .006 285.923));--nath-split-button-text: var(--color-zinc-100, oklch(96.7% .003 286.375));--nath-split-button-hover-bg: var(--color-zinc-700, oklch(37.1% .008 285.539));--nath-split-button-active-bg: var(--color-zinc-600, oklch(44.6% .012 285.938))}nath-split-button{display:inline-block;vertical-align:middle}.nath-split-button-container{display:flex;align-items:stretch}.nath-split-button-main,.nath-split-button-trigger{display:inline-flex;align-items:center;justify-content:center;padding:.5rem .75rem;font-size:.875rem;line-height:1.25rem;font-weight:500;cursor:pointer;transition:all .2s;border:1px solid var(--nath-split-button-border);background-color:var(--nath-split-button-bg);color:var(--nath-split-button-text);outline:none;white-space:nowrap}.nath-split-button-main{border-radius:var(--nath-split-button-radius) 0 0 var(--nath-split-button-radius);border-right:none}.nath-split-button-trigger{border-radius:0 var(--nath-split-button-radius) var(--nath-split-button-radius) 0}.nath-split-button-main:hover,.nath-split-button-trigger:hover{background-color:var(--nath-split-button-hover-bg)}.nath-split-button-main:active,.nath-split-button-trigger:active{background-color:var(--nath-split-button-active-bg)}.nath-split-button-main:focus-visible,.nath-split-button-trigger:focus-visible{z-index:10;outline:2px solid var(--nath-split-button-border);outline-offset:-2px}.nath-split-button-main:disabled,.nath-split-button-trigger:disabled{opacity:.5;cursor:not-allowed;pointer-events:none}\n"], dependencies: [{ kind: "component", type: LucideChevronDown, selector: "svg[lucideChevronDown]" }, { kind: "component", type: NathMenu, selector: "nath-menu", inputs: ["model", "styleClass", "positionX", "positionY", "inline", "flat"], outputs: ["modelChange", "styleClassChange", "whenHide"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
5165
|
+
`, isInline: true, styles: ["nath-split-button,.nath-split-button-theme{--nath-split-button-border: var(--color-zinc-300, oklch(83.1% .007 285.938));--nath-split-button-bg: var(--color-zinc-100, oklch(96.7% .003 286.375));--nath-split-button-text: var(--color-zinc-900, oklch(21% .006 285.885));--nath-split-button-hover-bg: var(--color-zinc-200, oklch(92% .004 286.32));--nath-split-button-active-bg: var(--color-zinc-300, oklch(83.1% .007 285.938));--nath-split-button-radius: .375rem}.dark nath-split-button,.dark .nath-split-button-theme{--nath-split-button-border: var(--color-zinc-700, oklch(37.1% .008 285.539));--nath-split-button-bg: var(--color-zinc-800, oklch(27.8% .006 285.923));--nath-split-button-text: var(--color-zinc-100, oklch(96.7% .003 286.375));--nath-split-button-hover-bg: var(--color-zinc-700, oklch(37.1% .008 285.539));--nath-split-button-active-bg: var(--color-zinc-600, oklch(44.6% .012 285.938))}nath-split-button{display:inline-block;vertical-align:middle}.nath-split-button-container{display:flex;align-items:stretch}.nath-split-button-main,.nath-split-button-trigger{display:inline-flex;align-items:center;justify-content:center;padding:.5rem .75rem;font-size:.875rem;line-height:1.25rem;font-weight:500;cursor:pointer;transition:all .2s;border:1px solid var(--nath-split-button-border);background-color:var(--nath-split-button-bg);color:var(--nath-split-button-text);outline:none;white-space:nowrap}.nath-split-button-main{border-radius:var(--nath-split-button-radius) 0 0 var(--nath-split-button-radius);border-right:none}.nath-split-button-trigger{border-radius:0 var(--nath-split-button-radius) var(--nath-split-button-radius) 0}.nath-split-button-main:hover,.nath-split-button-trigger:hover{background-color:var(--nath-split-button-hover-bg)}.nath-split-button-main:active,.nath-split-button-trigger:active{background-color:var(--nath-split-button-active-bg)}.nath-split-button-main:focus-visible,.nath-split-button-trigger:focus-visible{z-index:10;outline:2px solid var(--nath-split-button-border);outline-offset:-2px}.nath-split-button-main:disabled,.nath-split-button-trigger:disabled{opacity:.5;cursor:not-allowed;pointer-events:none}\n"], dependencies: [{ kind: "component", type: LucideChevronDown, selector: "svg[lucideChevronDown]" }, { kind: "component", type: NathMenu, selector: "nath-menu", inputs: ["model", "styleClass", "panelStyleClass", "positionX", "positionY", "inline", "flat"], outputs: ["modelChange", "styleClassChange", "panelStyleClassChange", "whenHide"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
4814
5166
|
}
|
|
4815
5167
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NathSplitButton, decorators: [{
|
|
4816
5168
|
type: Component,
|
|
@@ -5145,7 +5497,7 @@ class NathThemeSwitch {
|
|
|
5145
5497
|
<svg [lucideIcon]="themeService.isDarkMode() ? LucideMoon : LucideSun"></svg>
|
|
5146
5498
|
</button>
|
|
5147
5499
|
<nath-menu #themeMenu [model]="themes" positionX="left" positionY="bottom" />
|
|
5148
|
-
`, isInline: true, styles: ["app-theme-switch{display:inline-block}\n"], dependencies: [{ kind: "component", type: NathMenu, selector: "nath-menu", inputs: ["model", "styleClass", "positionX", "positionY", "inline", "flat"], outputs: ["modelChange", "styleClassChange", "whenHide"] }, { kind: "component", type: LucideDynamicIcon, selector: "svg[lucideIcon]", inputs: ["lucideIcon"] }], changeDetection: i0.ChangeDetectionStrategy.Eager, encapsulation: i0.ViewEncapsulation.None });
|
|
5500
|
+
`, isInline: true, styles: ["app-theme-switch{display:inline-block}\n"], dependencies: [{ kind: "component", type: NathMenu, selector: "nath-menu", inputs: ["model", "styleClass", "panelStyleClass", "positionX", "positionY", "inline", "flat"], outputs: ["modelChange", "styleClassChange", "panelStyleClassChange", "whenHide"] }, { kind: "component", type: LucideDynamicIcon, selector: "svg[lucideIcon]", inputs: ["lucideIcon"] }], changeDetection: i0.ChangeDetectionStrategy.Eager, encapsulation: i0.ViewEncapsulation.None });
|
|
5149
5501
|
}
|
|
5150
5502
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NathThemeSwitch, decorators: [{
|
|
5151
5503
|
type: Component,
|
|
@@ -5599,9 +5951,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
|
|
|
5599
5951
|
}]
|
|
5600
5952
|
}], propDecorators: { tooltipContent: [{ type: i0.Input, args: [{ isSignal: true, alias: "nathTooltip", required: false }] }], tooltipPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltipPosition", required: false }] }], showDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDelay", required: false }] }], hideDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideDelay", required: false }] }] } });
|
|
5601
5953
|
|
|
5602
|
-
function
|
|
5954
|
+
function nextSibling(el, selector) {
|
|
5603
5955
|
const nextEl = el.nextElementSibling;
|
|
5604
|
-
if (!selector ||
|
|
5956
|
+
if (!selector || nextEl?.matches(selector)) {
|
|
5605
5957
|
return nextEl;
|
|
5606
5958
|
}
|
|
5607
5959
|
return null;
|
|
@@ -5632,5 +5984,5 @@ function isSortOrderValid(order) {
|
|
|
5632
5984
|
* Generated bundle index. Do not edit.
|
|
5633
5985
|
*/
|
|
5634
5986
|
|
|
5635
|
-
export {
|
|
5987
|
+
export { DARK_THEME_CLASS, DIALOG_DATA, NathAutocomplete, NathBooleanControl, NathBreadcrumbService, NathBreadcrumbs, NathCodeViewer, NathConfirmationDialog, NathConfirmationService, NathDatepicker, NathDialogContainer, NathDialogRef, NathDialogService, NathDrawer, NathFileUpload, NathFloatingLabel, NathFormField, NathImagePreview, NathMenu, NathMenuBar, NathMenuList, NathMultiselect, NathPaginatedView, NathPaginator, NathPanel, NathPickList, NathProgressBar, NathProgressCircle, NathRadioButtonGroup, NathRatingHeart, NathRatingInput, NathSelect, NathShowErrors, NathSkeleton, NathSlider, NathSortIcon, NathSplitButton, NathTabs, NathTag, NathThemeSwitch, NathToastContainer, NathToc, NathTooltipContainer, NathTooltipDirective, ORDER, RATING_MAP, THEME_CONFIG, TabDirective, TabPanelDirective, ThemeService, ToastService, getRatingColor, hasRequiredValidator, isRequired, isSortOrderValid, isTruthy, nextSibling, provideThemeConfig, rangeMinMax, rangeNotMinMax, validateAllFormFields };
|
|
5636
5988
|
//# sourceMappingURL=nath-angular-ui.mjs.map
|