@devjuliovilla/jv-ui 1.15.0 → 1.17.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/README.md +104 -16
- package/fesm2022/devjuliovilla-jv-ui.mjs +971 -1289
- package/fesm2022/devjuliovilla-jv-ui.mjs.map +1 -1
- package/package.json +85 -1
- package/secondary/auth-pages.d.ts +1 -0
- package/secondary/auth-pages.mjs +1 -0
- package/secondary/buttons.d.ts +1 -0
- package/secondary/buttons.mjs +1 -0
- package/secondary/calendar.d.ts +1 -0
- package/secondary/calendar.mjs +1 -0
- package/secondary/collapsible.d.ts +1 -0
- package/secondary/collapsible.mjs +1 -0
- package/secondary/config.d.ts +1 -0
- package/secondary/config.mjs +1 -0
- package/secondary/containers.d.ts +1 -0
- package/secondary/containers.mjs +1 -0
- package/secondary/core.d.ts +1 -0
- package/secondary/core.mjs +1 -0
- package/secondary/dialogs.d.ts +1 -0
- package/secondary/dialogs.mjs +1 -0
- package/secondary/feedback.d.ts +1 -0
- package/secondary/feedback.mjs +1 -0
- package/secondary/forms.d.ts +1 -0
- package/secondary/forms.mjs +1 -0
- package/secondary/gallery.d.ts +1 -0
- package/secondary/gallery.mjs +1 -0
- package/secondary/grid.d.ts +1 -0
- package/secondary/grid.mjs +1 -0
- package/secondary/i18n.d.ts +1 -0
- package/secondary/i18n.mjs +1 -0
- package/secondary/icons.d.ts +1 -0
- package/secondary/icons.mjs +1 -0
- package/secondary/layout.d.ts +1 -0
- package/secondary/layout.mjs +1 -0
- package/secondary/list.d.ts +1 -0
- package/secondary/list.mjs +1 -0
- package/secondary/pagination.d.ts +1 -0
- package/secondary/pagination.mjs +1 -0
- package/secondary/services.d.ts +1 -0
- package/secondary/services.mjs +1 -0
- package/secondary/slider.d.ts +1 -0
- package/secondary/slider.mjs +1 -0
- package/secondary/tabs.d.ts +1 -0
- package/secondary/tabs.mjs +1 -0
- package/secondary/tooltip.d.ts +1 -0
- package/secondary/tooltip.mjs +1 -0
- package/types/devjuliovilla-jv-ui.d.ts +41 -12
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, computed, Component, inject, signal, Injectable, InjectionToken, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, TemplateRef,
|
|
2
|
+
import { input, computed, Component, inject, Renderer2, ElementRef, HostListener, Directive, signal, Injectable, InjectionToken, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, TemplateRef, contentChild, output, effect, forwardRef, viewChild, untracked, contentChildren, viewChildren, numberAttribute, afterNextRender, DestroyRef } from '@angular/core';
|
|
3
3
|
import { DOCUMENT, NgTemplateOutlet, CommonModule } from '@angular/common';
|
|
4
4
|
import * as i1 from '@angular/forms';
|
|
5
5
|
import { NG_VALUE_ACCESSOR, FormBuilder, Validators, ReactiveFormsModule, FormsModule } from '@angular/forms';
|
|
@@ -18009,6 +18009,193 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
18009
18009
|
args: [{ selector: 'jv-button-group', standalone: true, template: `<div class="jv-button-group" role="group"><ng-content></ng-content></div>`, styles: [".jv-button-group{display:inline-flex;flex-wrap:wrap;gap:var(--jv-spacing-sm);align-items:center}\n"] }]
|
|
18010
18010
|
}] });
|
|
18011
18011
|
|
|
18012
|
+
let tooltipSequence = 0;
|
|
18013
|
+
class JvTooltipDirective {
|
|
18014
|
+
document = inject(DOCUMENT);
|
|
18015
|
+
renderer = inject(Renderer2);
|
|
18016
|
+
hostRef = inject((ElementRef));
|
|
18017
|
+
tooltipElement = null;
|
|
18018
|
+
showTimeout = null;
|
|
18019
|
+
hideTimeout = null;
|
|
18020
|
+
tooltipId = `jv-tooltip-${++tooltipSequence}`;
|
|
18021
|
+
originalDescribedBy = null;
|
|
18022
|
+
text = input.required({ ...(ngDevMode ? { debugName: "text" } : /* istanbul ignore next */ {}), alias: 'jvTooltip' });
|
|
18023
|
+
position = input('top', { ...(ngDevMode ? { debugName: "position" } : /* istanbul ignore next */ {}), alias: 'jvTooltipPosition' });
|
|
18024
|
+
show() {
|
|
18025
|
+
if (!this.text().trim()) {
|
|
18026
|
+
return;
|
|
18027
|
+
}
|
|
18028
|
+
this.clearHideTimeout();
|
|
18029
|
+
if (this.tooltipElement) {
|
|
18030
|
+
return;
|
|
18031
|
+
}
|
|
18032
|
+
this.showTimeout = setTimeout(() => {
|
|
18033
|
+
this.renderTooltip();
|
|
18034
|
+
this.positionTooltip();
|
|
18035
|
+
this.attachTooltipDescription();
|
|
18036
|
+
}, 120);
|
|
18037
|
+
}
|
|
18038
|
+
hide() {
|
|
18039
|
+
this.clearShowTimeout();
|
|
18040
|
+
if (!this.tooltipElement) {
|
|
18041
|
+
return;
|
|
18042
|
+
}
|
|
18043
|
+
this.hideTimeout = setTimeout(() => this.destroyTooltip(), 80);
|
|
18044
|
+
}
|
|
18045
|
+
handleDocumentKeydown(event) {
|
|
18046
|
+
if (event.key === 'Escape') {
|
|
18047
|
+
this.destroyTooltip();
|
|
18048
|
+
}
|
|
18049
|
+
}
|
|
18050
|
+
handleViewportChange() {
|
|
18051
|
+
if (this.tooltipElement) {
|
|
18052
|
+
this.positionTooltip();
|
|
18053
|
+
}
|
|
18054
|
+
}
|
|
18055
|
+
ngOnDestroy() {
|
|
18056
|
+
this.clearShowTimeout();
|
|
18057
|
+
this.clearHideTimeout();
|
|
18058
|
+
this.destroyTooltip();
|
|
18059
|
+
}
|
|
18060
|
+
renderTooltip() {
|
|
18061
|
+
if (this.tooltipElement) {
|
|
18062
|
+
return;
|
|
18063
|
+
}
|
|
18064
|
+
const tooltip = this.renderer.createElement('div');
|
|
18065
|
+
tooltip.textContent = this.text();
|
|
18066
|
+
this.renderer.setAttribute(tooltip, 'id', this.tooltipId);
|
|
18067
|
+
this.renderer.setAttribute(tooltip, 'role', 'tooltip');
|
|
18068
|
+
this.renderer.setStyle(tooltip, 'position', 'fixed');
|
|
18069
|
+
this.renderer.setStyle(tooltip, 'z-index', '1400');
|
|
18070
|
+
this.renderer.setStyle(tooltip, 'max-width', '18rem');
|
|
18071
|
+
this.renderer.setStyle(tooltip, 'padding', '0.5rem 0.75rem');
|
|
18072
|
+
this.renderer.setStyle(tooltip, 'border-radius', '0.5rem');
|
|
18073
|
+
this.renderer.setStyle(tooltip, 'background', 'rgb(15 23 42)');
|
|
18074
|
+
this.renderer.setStyle(tooltip, 'color', '#ffffff');
|
|
18075
|
+
this.renderer.setStyle(tooltip, 'font-size', '0.8125rem');
|
|
18076
|
+
this.renderer.setStyle(tooltip, 'line-height', '1.4');
|
|
18077
|
+
this.renderer.setStyle(tooltip, 'box-shadow', 'var(--jv-shadow-md)');
|
|
18078
|
+
this.renderer.setStyle(tooltip, 'pointer-events', 'none');
|
|
18079
|
+
this.renderer.setStyle(tooltip, 'opacity', '0');
|
|
18080
|
+
this.renderer.setStyle(tooltip, 'transition', 'opacity 120ms ease');
|
|
18081
|
+
this.renderer.appendChild(this.document.body, tooltip);
|
|
18082
|
+
this.tooltipElement = tooltip;
|
|
18083
|
+
requestAnimationFrame(() => {
|
|
18084
|
+
if (this.tooltipElement) {
|
|
18085
|
+
this.renderer.setStyle(this.tooltipElement, 'opacity', '1');
|
|
18086
|
+
}
|
|
18087
|
+
});
|
|
18088
|
+
}
|
|
18089
|
+
positionTooltip() {
|
|
18090
|
+
const tooltip = this.tooltipElement;
|
|
18091
|
+
if (!tooltip) {
|
|
18092
|
+
return;
|
|
18093
|
+
}
|
|
18094
|
+
const hostRect = this.anchorElement().getBoundingClientRect();
|
|
18095
|
+
const tooltipRect = tooltip.getBoundingClientRect();
|
|
18096
|
+
const gap = 8;
|
|
18097
|
+
let top = hostRect.top - tooltipRect.height - gap;
|
|
18098
|
+
let left = hostRect.left + hostRect.width / 2 - tooltipRect.width / 2;
|
|
18099
|
+
switch (this.position()) {
|
|
18100
|
+
case 'right':
|
|
18101
|
+
top = hostRect.top + hostRect.height / 2 - tooltipRect.height / 2;
|
|
18102
|
+
left = hostRect.right + gap;
|
|
18103
|
+
break;
|
|
18104
|
+
case 'bottom':
|
|
18105
|
+
top = hostRect.bottom + gap;
|
|
18106
|
+
left = hostRect.left + hostRect.width / 2 - tooltipRect.width / 2;
|
|
18107
|
+
break;
|
|
18108
|
+
case 'left':
|
|
18109
|
+
top = hostRect.top + hostRect.height / 2 - tooltipRect.height / 2;
|
|
18110
|
+
left = hostRect.left - tooltipRect.width - gap;
|
|
18111
|
+
break;
|
|
18112
|
+
}
|
|
18113
|
+
this.renderer.setStyle(tooltip, 'top', `${Math.round(top)}px`);
|
|
18114
|
+
this.renderer.setStyle(tooltip, 'left', `${Math.round(left)}px`);
|
|
18115
|
+
}
|
|
18116
|
+
destroyTooltip() {
|
|
18117
|
+
this.clearHideTimeout();
|
|
18118
|
+
this.clearShowTimeout();
|
|
18119
|
+
if (!this.tooltipElement) {
|
|
18120
|
+
return;
|
|
18121
|
+
}
|
|
18122
|
+
this.restoreTooltipDescription();
|
|
18123
|
+
this.renderer.removeChild(this.document.body, this.tooltipElement);
|
|
18124
|
+
this.tooltipElement = null;
|
|
18125
|
+
}
|
|
18126
|
+
attachTooltipDescription() {
|
|
18127
|
+
const anchor = this.anchorElement();
|
|
18128
|
+
this.originalDescribedBy ??= anchor.getAttribute('aria-describedby');
|
|
18129
|
+
const describedBy = [this.originalDescribedBy, this.tooltipId]
|
|
18130
|
+
.filter((value) => !!value)
|
|
18131
|
+
.join(' ')
|
|
18132
|
+
.trim();
|
|
18133
|
+
this.renderer.setAttribute(anchor, 'aria-describedby', describedBy);
|
|
18134
|
+
}
|
|
18135
|
+
restoreTooltipDescription() {
|
|
18136
|
+
const anchor = this.anchorElement();
|
|
18137
|
+
if (this.originalDescribedBy) {
|
|
18138
|
+
this.renderer.setAttribute(anchor, 'aria-describedby', this.originalDescribedBy);
|
|
18139
|
+
}
|
|
18140
|
+
else {
|
|
18141
|
+
this.renderer.removeAttribute(anchor, 'aria-describedby');
|
|
18142
|
+
}
|
|
18143
|
+
this.originalDescribedBy = null;
|
|
18144
|
+
}
|
|
18145
|
+
anchorElement() {
|
|
18146
|
+
const host = this.hostRef.nativeElement;
|
|
18147
|
+
if (isInteractiveElement(host)) {
|
|
18148
|
+
return host;
|
|
18149
|
+
}
|
|
18150
|
+
return host.querySelector('button, a, input, select, textarea, [tabindex]:not([tabindex="-1"])') ?? host;
|
|
18151
|
+
}
|
|
18152
|
+
clearShowTimeout() {
|
|
18153
|
+
if (this.showTimeout) {
|
|
18154
|
+
clearTimeout(this.showTimeout);
|
|
18155
|
+
this.showTimeout = null;
|
|
18156
|
+
}
|
|
18157
|
+
}
|
|
18158
|
+
clearHideTimeout() {
|
|
18159
|
+
if (this.hideTimeout) {
|
|
18160
|
+
clearTimeout(this.hideTimeout);
|
|
18161
|
+
this.hideTimeout = null;
|
|
18162
|
+
}
|
|
18163
|
+
}
|
|
18164
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JvTooltipDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
18165
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.17", type: JvTooltipDirective, isStandalone: true, selector: "[jvTooltip]", inputs: { text: { classPropertyName: "text", publicName: "jvTooltip", isSignal: true, isRequired: true, transformFunction: null }, position: { classPropertyName: "position", publicName: "jvTooltipPosition", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "mouseenter": "show()", "focusin": "show()", "mouseleave": "hide()", "blur": "hide()", "document:keydown": "handleDocumentKeydown($event)", "window:scroll": "handleViewportChange()", "window:resize": "handleViewportChange()" } }, ngImport: i0 });
|
|
18166
|
+
}
|
|
18167
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JvTooltipDirective, decorators: [{
|
|
18168
|
+
type: Directive,
|
|
18169
|
+
args: [{
|
|
18170
|
+
selector: '[jvTooltip]',
|
|
18171
|
+
standalone: true,
|
|
18172
|
+
}]
|
|
18173
|
+
}], propDecorators: { text: [{ type: i0.Input, args: [{ isSignal: true, alias: "jvTooltip", required: true }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "jvTooltipPosition", required: false }] }], show: [{
|
|
18174
|
+
type: HostListener,
|
|
18175
|
+
args: ['mouseenter']
|
|
18176
|
+
}, {
|
|
18177
|
+
type: HostListener,
|
|
18178
|
+
args: ['focusin']
|
|
18179
|
+
}], hide: [{
|
|
18180
|
+
type: HostListener,
|
|
18181
|
+
args: ['mouseleave']
|
|
18182
|
+
}, {
|
|
18183
|
+
type: HostListener,
|
|
18184
|
+
args: ['blur']
|
|
18185
|
+
}], handleDocumentKeydown: [{
|
|
18186
|
+
type: HostListener,
|
|
18187
|
+
args: ['document:keydown', ['$event']]
|
|
18188
|
+
}], handleViewportChange: [{
|
|
18189
|
+
type: HostListener,
|
|
18190
|
+
args: ['window:scroll']
|
|
18191
|
+
}, {
|
|
18192
|
+
type: HostListener,
|
|
18193
|
+
args: ['window:resize']
|
|
18194
|
+
}] } });
|
|
18195
|
+
function isInteractiveElement(element) {
|
|
18196
|
+
return ['BUTTON', 'A', 'INPUT', 'SELECT', 'TEXTAREA'].includes(element.tagName) || element.tabIndex >= 0;
|
|
18197
|
+
}
|
|
18198
|
+
|
|
18012
18199
|
class JvIconButtonComponent {
|
|
18013
18200
|
icon = input.required(...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
18014
18201
|
ariaLabel = input.required(...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
@@ -18021,25 +18208,31 @@ class JvIconButtonComponent {
|
|
|
18021
18208
|
class="jv-icon-button"
|
|
18022
18209
|
[class]="'jv-icon-button--' + variant()"
|
|
18023
18210
|
[attr.aria-label]="ariaLabel()"
|
|
18211
|
+
[attr.title]="ariaLabel()"
|
|
18212
|
+
[jvTooltip]="ariaLabel()"
|
|
18024
18213
|
[disabled]="disabled()"
|
|
18025
18214
|
>
|
|
18026
18215
|
<jv-icon [name]="icon()" [size]="18" />
|
|
18216
|
+
<span class="icon-label">{{ ariaLabel() }}</span>
|
|
18027
18217
|
</button>
|
|
18028
|
-
`, isInline: true, styles: [".jv-icon-button{display:inline-grid;place-items:center;width:var(--jv-density-control-height);height:var(--jv-density-control-height);border:1px solid transparent;border-radius:999px;cursor:pointer;transition:background-color .16s ease,color .16s ease,border-color .16s ease}.jv-icon-button:disabled{opacity:.6;cursor:not-allowed}.jv-icon-button--primary{background:var(--jv-color-primary);color:#fff}.jv-icon-button--secondary{background:var(--jv-color-secondary);color:#fff}.jv-icon-button--outline{border-color:var(--jv-color-border);background:var(--jv-color-surface);color:var(--jv-color-foreground)}.jv-icon-button--ghost,.jv-icon-button--link{background:transparent;color:var(--jv-color-foreground)}.jv-icon-button--danger{background:var(--jv-color-danger);color:#fff}.jv-icon-button--success{background:var(--jv-color-success);color:#fff}.jv-icon-button--warning{background:var(--jv-color-warning);color:#111827}.jv-icon-button--outline:hover,.jv-icon-button--ghost:hover,.jv-icon-button--link:hover{background:var(--jv-color-surface-muted)}\n"], dependencies: [{ kind: "component", type: JvIconComponent, selector: "jv-icon", inputs: ["name", "size", "strokeWidth", "decorative", "ariaLabel"] }] });
|
|
18218
|
+
`, isInline: true, styles: [".jv-icon-button{display:inline-grid;place-items:center;width:var(--jv-density-control-height);height:var(--jv-density-control-height);border:1px solid transparent;border-radius:999px;cursor:pointer;transition:background-color .16s ease,color .16s ease,border-color .16s ease}.icon-label{font-size:0}.jv-icon-button:disabled{opacity:.6;cursor:not-allowed}.jv-icon-button--primary{background:var(--jv-color-primary);color:#fff}.jv-icon-button--secondary{background:var(--jv-color-secondary);color:#fff}.jv-icon-button--outline{border-color:var(--jv-color-border);background:var(--jv-color-surface);color:var(--jv-color-foreground)}.jv-icon-button--ghost,.jv-icon-button--link{background:transparent;color:var(--jv-color-foreground)}.jv-icon-button--danger{background:var(--jv-color-danger);color:#fff}.jv-icon-button--success{background:var(--jv-color-success);color:#fff}.jv-icon-button--warning{background:var(--jv-color-warning);color:#111827}.jv-icon-button--outline:hover,.jv-icon-button--ghost:hover,.jv-icon-button--link:hover{background:var(--jv-color-surface-muted)}\n"], dependencies: [{ kind: "component", type: JvIconComponent, selector: "jv-icon", inputs: ["name", "size", "strokeWidth", "decorative", "ariaLabel"] }, { kind: "directive", type: JvTooltipDirective, selector: "[jvTooltip]", inputs: ["jvTooltip", "jvTooltipPosition"] }] });
|
|
18029
18219
|
}
|
|
18030
18220
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JvIconButtonComponent, decorators: [{
|
|
18031
18221
|
type: Component,
|
|
18032
|
-
args: [{ selector: 'jv-icon-button', standalone: true, imports: [JvIconComponent], template: `
|
|
18222
|
+
args: [{ selector: 'jv-icon-button', standalone: true, imports: [JvIconComponent, JvTooltipDirective], template: `
|
|
18033
18223
|
<button
|
|
18034
18224
|
type="button"
|
|
18035
18225
|
class="jv-icon-button"
|
|
18036
18226
|
[class]="'jv-icon-button--' + variant()"
|
|
18037
18227
|
[attr.aria-label]="ariaLabel()"
|
|
18228
|
+
[attr.title]="ariaLabel()"
|
|
18229
|
+
[jvTooltip]="ariaLabel()"
|
|
18038
18230
|
[disabled]="disabled()"
|
|
18039
18231
|
>
|
|
18040
18232
|
<jv-icon [name]="icon()" [size]="18" />
|
|
18233
|
+
<span class="icon-label">{{ ariaLabel() }}</span>
|
|
18041
18234
|
</button>
|
|
18042
|
-
`, styles: [".jv-icon-button{display:inline-grid;place-items:center;width:var(--jv-density-control-height);height:var(--jv-density-control-height);border:1px solid transparent;border-radius:999px;cursor:pointer;transition:background-color .16s ease,color .16s ease,border-color .16s ease}.jv-icon-button:disabled{opacity:.6;cursor:not-allowed}.jv-icon-button--primary{background:var(--jv-color-primary);color:#fff}.jv-icon-button--secondary{background:var(--jv-color-secondary);color:#fff}.jv-icon-button--outline{border-color:var(--jv-color-border);background:var(--jv-color-surface);color:var(--jv-color-foreground)}.jv-icon-button--ghost,.jv-icon-button--link{background:transparent;color:var(--jv-color-foreground)}.jv-icon-button--danger{background:var(--jv-color-danger);color:#fff}.jv-icon-button--success{background:var(--jv-color-success);color:#fff}.jv-icon-button--warning{background:var(--jv-color-warning);color:#111827}.jv-icon-button--outline:hover,.jv-icon-button--ghost:hover,.jv-icon-button--link:hover{background:var(--jv-color-surface-muted)}\n"] }]
|
|
18235
|
+
`, styles: [".jv-icon-button{display:inline-grid;place-items:center;width:var(--jv-density-control-height);height:var(--jv-density-control-height);border:1px solid transparent;border-radius:999px;cursor:pointer;transition:background-color .16s ease,color .16s ease,border-color .16s ease}.icon-label{font-size:0}.jv-icon-button:disabled{opacity:.6;cursor:not-allowed}.jv-icon-button--primary{background:var(--jv-color-primary);color:#fff}.jv-icon-button--secondary{background:var(--jv-color-secondary);color:#fff}.jv-icon-button--outline{border-color:var(--jv-color-border);background:var(--jv-color-surface);color:var(--jv-color-foreground)}.jv-icon-button--ghost,.jv-icon-button--link{background:transparent;color:var(--jv-color-foreground)}.jv-icon-button--danger{background:var(--jv-color-danger);color:#fff}.jv-icon-button--success{background:var(--jv-color-success);color:#fff}.jv-icon-button--warning{background:var(--jv-color-warning);color:#111827}.jv-icon-button--outline:hover,.jv-icon-button--ghost:hover,.jv-icon-button--link:hover{background:var(--jv-color-surface-muted)}\n"] }]
|
|
18043
18236
|
}], propDecorators: { icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: true }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: true }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
|
|
18044
18237
|
|
|
18045
18238
|
const JV_UI_DEFAULT_CONFIG = {
|
|
@@ -22969,24 +23162,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
22969
23162
|
`, styles: [".jv-breadcrumb ol{display:flex;flex-wrap:wrap;gap:var(--jv-spacing-xs);margin:0;padding:0;list-style:none;color:var(--jv-color-foreground-muted);font-size:.875rem}.jv-breadcrumb li{display:inline-flex;align-items:center;gap:var(--jv-spacing-xs)}.jv-breadcrumb a{color:inherit;text-decoration:none}.jv-breadcrumb a:hover{color:var(--jv-color-foreground);text-decoration:underline}.separator{opacity:.7}\n"] }]
|
|
22970
23163
|
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }] } });
|
|
22971
23164
|
|
|
22972
|
-
class
|
|
22973
|
-
|
|
22974
|
-
|
|
22975
|
-
|
|
22976
|
-
|
|
22977
|
-
|
|
22978
|
-
|
|
22979
|
-
|
|
22980
|
-
|
|
22981
|
-
ariaLabel = input('Sidebar navigation', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
22982
|
-
currentTheme = input('light', ...(ngDevMode ? [{ debugName: "currentTheme" }] : /* istanbul ignore next */ []));
|
|
22983
|
-
themeOptions = input([], ...(ngDevMode ? [{ debugName: "themeOptions" }] : /* istanbul ignore next */ []));
|
|
22984
|
-
topbarActions = input([], ...(ngDevMode ? [{ debugName: "topbarActions" }] : /* istanbul ignore next */ []));
|
|
22985
|
-
showThemeSelector = input(true, ...(ngDevMode ? [{ debugName: "showThemeSelector" }] : /* istanbul ignore next */ []));
|
|
22986
|
-
collapseToggle = output();
|
|
22987
|
-
mobileClose = output();
|
|
22988
|
-
themeChange = output();
|
|
22989
|
-
actionClick = output();
|
|
23165
|
+
class JvNavigationState {
|
|
23166
|
+
items;
|
|
23167
|
+
router;
|
|
23168
|
+
expandActiveSections;
|
|
23169
|
+
sectionOverrides = signal(new Map(), ...(ngDevMode ? [{ debugName: "sectionOverrides" }] : /* istanbul ignore next */ []));
|
|
23170
|
+
normalizedItems = computed(() => this.items().map((item) => ({
|
|
23171
|
+
...item,
|
|
23172
|
+
children: item.children ?? [],
|
|
23173
|
+
})), ...(ngDevMode ? [{ debugName: "normalizedItems" }] : /* istanbul ignore next */ []));
|
|
22990
23174
|
activeChildParentIds = computed(() => {
|
|
22991
23175
|
const url = this.router.url;
|
|
22992
23176
|
const ids = new Set();
|
|
@@ -22999,22 +23183,33 @@ class JvSidebarComponent {
|
|
|
22999
23183
|
}
|
|
23000
23184
|
return ids;
|
|
23001
23185
|
}, ...(ngDevMode ? [{ debugName: "activeChildParentIds" }] : /* istanbul ignore next */ []));
|
|
23002
|
-
|
|
23003
|
-
|
|
23004
|
-
|
|
23005
|
-
|
|
23006
|
-
isExpanded(id) {
|
|
23007
|
-
return this.expandedSections().has(id) || this.activeChildParentIds().has(id);
|
|
23186
|
+
constructor(items, router, expandActiveSections = true) {
|
|
23187
|
+
this.items = items;
|
|
23188
|
+
this.router = router;
|
|
23189
|
+
this.expandActiveSections = expandActiveSections;
|
|
23008
23190
|
}
|
|
23009
|
-
|
|
23010
|
-
this.
|
|
23011
|
-
|
|
23012
|
-
|
|
23013
|
-
|
|
23014
|
-
|
|
23015
|
-
|
|
23016
|
-
|
|
23191
|
+
isExpanded(id) {
|
|
23192
|
+
return this.sectionOverrides().get(id) ?? (this.expandActiveSections && this.activeChildParentIds().has(id));
|
|
23193
|
+
}
|
|
23194
|
+
toggleSection(id, exclusive = false) {
|
|
23195
|
+
this.sectionOverrides.update((current) => {
|
|
23196
|
+
const next = new Map(current);
|
|
23197
|
+
const shouldExpand = !this.isExpanded(id);
|
|
23198
|
+
if (exclusive) {
|
|
23199
|
+
for (const item of this.normalizedItems()) {
|
|
23200
|
+
if (item.children.length > 0) {
|
|
23201
|
+
next.set(item.id, false);
|
|
23202
|
+
}
|
|
23203
|
+
}
|
|
23017
23204
|
}
|
|
23205
|
+
next.set(id, shouldExpand);
|
|
23206
|
+
return next;
|
|
23207
|
+
});
|
|
23208
|
+
}
|
|
23209
|
+
closeSection(id) {
|
|
23210
|
+
this.sectionOverrides.update((current) => {
|
|
23211
|
+
const next = new Map(current);
|
|
23212
|
+
next.set(id, false);
|
|
23018
23213
|
return next;
|
|
23019
23214
|
});
|
|
23020
23215
|
}
|
|
@@ -23028,6 +23223,38 @@ class JvSidebarComponent {
|
|
|
23028
23223
|
const target = document.querySelector(href);
|
|
23029
23224
|
target?.scrollIntoView({ block: 'start', behavior: 'smooth' });
|
|
23030
23225
|
}
|
|
23226
|
+
}
|
|
23227
|
+
|
|
23228
|
+
class JvSidebarComponent {
|
|
23229
|
+
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
23230
|
+
subtitle = input('', ...(ngDevMode ? [{ debugName: "subtitle" }] : /* istanbul ignore next */ []));
|
|
23231
|
+
brandIcon = input('monitor', ...(ngDevMode ? [{ debugName: "brandIcon" }] : /* istanbul ignore next */ []));
|
|
23232
|
+
items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
23233
|
+
collapsed = input(false, ...(ngDevMode ? [{ debugName: "collapsed" }] : /* istanbul ignore next */ []));
|
|
23234
|
+
mobileOpen = input(false, ...(ngDevMode ? [{ debugName: "mobileOpen" }] : /* istanbul ignore next */ []));
|
|
23235
|
+
ariaLabel = input('Sidebar navigation', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
23236
|
+
currentTheme = input('light', ...(ngDevMode ? [{ debugName: "currentTheme" }] : /* istanbul ignore next */ []));
|
|
23237
|
+
themeOptions = input([], ...(ngDevMode ? [{ debugName: "themeOptions" }] : /* istanbul ignore next */ []));
|
|
23238
|
+
topbarActions = input([], ...(ngDevMode ? [{ debugName: "topbarActions" }] : /* istanbul ignore next */ []));
|
|
23239
|
+
showThemeSelector = input(true, ...(ngDevMode ? [{ debugName: "showThemeSelector" }] : /* istanbul ignore next */ []));
|
|
23240
|
+
navigation = new JvNavigationState(this.items, inject(Router));
|
|
23241
|
+
collapseToggle = output();
|
|
23242
|
+
mobileClose = output();
|
|
23243
|
+
themeChange = output();
|
|
23244
|
+
actionClick = output();
|
|
23245
|
+
normalizedItems = this.navigation.normalizedItems;
|
|
23246
|
+
isExpanded(id) {
|
|
23247
|
+
return this.navigation.isExpanded(id);
|
|
23248
|
+
}
|
|
23249
|
+
toggleSection(id) {
|
|
23250
|
+
this.navigation.toggleSection(id);
|
|
23251
|
+
}
|
|
23252
|
+
isHashLink(href) {
|
|
23253
|
+
return this.navigation.isHashLink(href);
|
|
23254
|
+
}
|
|
23255
|
+
navigateTo(href) {
|
|
23256
|
+
this.navigation.navigateTo(href);
|
|
23257
|
+
}
|
|
23031
23258
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JvSidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
23032
23259
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: JvSidebarComponent, isStandalone: true, selector: "jv-sidebar", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, brandIcon: { classPropertyName: "brandIcon", publicName: "brandIcon", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, mobileOpen: { classPropertyName: "mobileOpen", publicName: "mobileOpen", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, currentTheme: { classPropertyName: "currentTheme", publicName: "currentTheme", isSignal: true, isRequired: false, transformFunction: null }, themeOptions: { classPropertyName: "themeOptions", publicName: "themeOptions", isSignal: true, isRequired: false, transformFunction: null }, topbarActions: { classPropertyName: "topbarActions", publicName: "topbarActions", isSignal: true, isRequired: false, transformFunction: null }, showThemeSelector: { classPropertyName: "showThemeSelector", publicName: "showThemeSelector", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { collapseToggle: "collapseToggle", mobileClose: "mobileClose", themeChange: "themeChange", actionClick: "actionClick" }, ngImport: i0, template: `
|
|
23033
23260
|
@if (mobileOpen()) {
|
|
@@ -23176,19 +23403,20 @@ class JvSidebarComponent {
|
|
|
23176
23403
|
|
|
23177
23404
|
<div class="mobile-actions">
|
|
23178
23405
|
@for (action of topbarActions(); track action.id) {
|
|
23179
|
-
<button type="button" class="icon-button" [attr.aria-label]="action.label" (click)="actionClick.emit(action.id); mobileClose.emit()">
|
|
23406
|
+
<button type="button" class="icon-button" [attr.aria-label]="action.label" [attr.title]="action.label" [jvTooltip]="action.label" (click)="actionClick.emit(action.id); mobileClose.emit()">
|
|
23180
23407
|
<jv-icon [name]="action.icon" [size]="18" />
|
|
23408
|
+
<span>{{ action.label }}</span>
|
|
23181
23409
|
</button>
|
|
23182
23410
|
}
|
|
23183
23411
|
</div>
|
|
23184
23412
|
</div>
|
|
23185
23413
|
</div>
|
|
23186
23414
|
</aside>
|
|
23187
|
-
`, isInline: true, styles: [".jv-sidebar-backdrop{display:none}.jv-sidebar{display:grid;grid-template-rows:auto 1fr auto;gap:var(--jv-spacing-lg);width:280px;min-width:280px;height:100vh;padding:var(--jv-spacing-lg);overflow-y:auto;border-right:1px solid var(--jv-color-border);background:var(--jv-color-surface);scrollbar-width:none;-ms-overflow-style:none}.jv-sidebar::-webkit-scrollbar{width:0;height:0;display:none}.jv-sidebar.is-collapsed{width:96px;min-width:96px;padding-inline:var(--jv-spacing-md)}.jv-sidebar-footer{display:grid;gap:var(--jv-spacing-md)}.jv-sidebar-mobile-extras{display:none}.jv-sidebar-brand,.jv-sidebar-link,.jv-sidebar-toggle{display:flex;align-items:center;gap:var(--jv-spacing-sm)}.brand-mark{display:inline-grid;place-items:center;width:var(--jv-density-control-height);height:var(--jv-density-control-height);border-radius:var(--jv-radius-md);background:color-mix(in srgb,var(--jv-color-primary) 16%,var(--jv-color-surface));color:var(--jv-color-primary);flex:0 0 auto}.brand-copy{display:grid;gap:.1rem}.brand-copy span{color:var(--jv-color-foreground-muted);font-size:.875rem}.jv-sidebar-item{display:grid;gap:var(--jv-spacing-xs);list-style:none}.jv-sidebar-list{display:grid;gap:var(--jv-spacing-xs);margin:0;padding:0}.jv-sidebar-nav{display:grid;gap:var(--jv-spacing-xs);align-content:start}.jv-sidebar-link,.jv-sidebar-child-link,.jv-sidebar-toggle{width:100%;display:flex;align-items:center;justify-content:space-between;min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-md);border:1px solid transparent;border-radius:var(--jv-radius-md);background:transparent;color:var(--jv-color-foreground-muted);text-decoration:none;cursor:pointer}.jv-sidebar-link-main{display:inline-flex;align-items:center;gap:var(--jv-spacing-sm)}.jv-sidebar-link:hover,.jv-sidebar-child-link:hover,.jv-sidebar-toggle:hover{background:var(--jv-color-surface-muted);color:var(--jv-color-foreground)}.jv-sidebar-link.is-active,.jv-sidebar-child-link.is-active{border-color:color-mix(in srgb,var(--jv-color-primary) 25%,var(--jv-color-border));background:color-mix(in srgb,var(--jv-color-primary) 12%,var(--jv-color-surface));color:var(--jv-color-foreground)}.jv-sidebar-children{display:grid;gap:var(--jv-spacing-xs);margin-left:var(--jv-spacing-xl);padding-left:var(--jv-spacing-sm);border-left:1px solid var(--jv-color-border)}.jv-sidebar-child-link{display:flex;align-items:center;min-height:calc(var(--jv-density-control-height) - .25rem);font-size:.9rem}.jv-sidebar-toggle{width:100%;background:var(--jv-color-surface-muted);cursor:pointer}@media(max-width:900px){.jv-sidebar-backdrop{display:block;position:fixed;inset:0;z-index:99;background:#0006}.jv-sidebar{position:fixed;top:0;left:0;z-index:100;width:280px;min-width:280px;height:100vh;border-right:1px solid var(--jv-color-border);border-bottom:none;box-shadow:var(--jv-shadow-lg);transform:translate(-100%);visibility:hidden;transition:transform .24s cubic-bezier(.4,0,.2,1),visibility .24s}.jv-sidebar.is-mobile-open{transform:translate(0);visibility:visible}.jv-sidebar.is-collapsed{width:280px;min-width:280px}.jv-sidebar-mobile-extras{display:flex;flex-direction:column;gap:var(--jv-spacing-md);padding-top:var(--jv-spacing-md);border-top:1px solid var(--jv-color-border)}.jv-sidebar-mobile-extras .theme-group{display:flex;flex-wrap:wrap;gap:var(--jv-spacing-xs)}.jv-sidebar-mobile-extras .theme-pill{display:inline-flex;align-items:center;gap:var(--jv-spacing-xs);min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-md);border:1px solid var(--jv-color-border);border-radius:999px;background:var(--jv-color-surface-muted);color:var(--jv-color-foreground);cursor:pointer;font:inherit}.jv-sidebar-mobile-extras .theme-pill.is-active{border-color:var(--jv-color-primary);background:color-mix(in srgb,var(--jv-color-primary) 14%,var(--jv-color-surface))}.jv-sidebar-mobile-extras .mobile-actions{display:flex;gap:var(--jv-spacing-sm)}.jv-sidebar-mobile-extras .icon-button{display:inline-
|
|
23415
|
+
`, isInline: true, styles: [".jv-sidebar-backdrop{display:none}.jv-sidebar{display:grid;grid-template-rows:auto 1fr auto;gap:var(--jv-spacing-lg);width:280px;min-width:280px;height:100vh;padding:var(--jv-spacing-lg);overflow-y:auto;border-right:1px solid var(--jv-color-border);background:var(--jv-color-surface);scrollbar-width:none;-ms-overflow-style:none}.jv-sidebar::-webkit-scrollbar{width:0;height:0;display:none}.jv-sidebar.is-collapsed{width:96px;min-width:96px;padding-inline:var(--jv-spacing-md)}.jv-sidebar-footer{display:grid;gap:var(--jv-spacing-md)}.jv-sidebar-mobile-extras{display:none}.jv-sidebar-brand,.jv-sidebar-link,.jv-sidebar-toggle{display:flex;align-items:center;gap:var(--jv-spacing-sm)}.brand-mark{display:inline-grid;place-items:center;width:var(--jv-density-control-height);height:var(--jv-density-control-height);border-radius:var(--jv-radius-md);background:color-mix(in srgb,var(--jv-color-primary) 16%,var(--jv-color-surface));color:var(--jv-color-primary);flex:0 0 auto}.brand-copy{display:grid;gap:.1rem}.brand-copy span{color:var(--jv-color-foreground-muted);font-size:.875rem}.jv-sidebar-item{display:grid;gap:var(--jv-spacing-xs);list-style:none}.jv-sidebar-list{display:grid;gap:var(--jv-spacing-xs);margin:0;padding:0}.jv-sidebar-nav{display:grid;gap:var(--jv-spacing-xs);align-content:start}.jv-sidebar-link,.jv-sidebar-child-link,.jv-sidebar-toggle{width:100%;display:flex;align-items:center;justify-content:space-between;min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-md);border:1px solid transparent;border-radius:var(--jv-radius-md);background:transparent;color:var(--jv-color-foreground-muted);text-decoration:none;cursor:pointer}.jv-sidebar-link-main{display:inline-flex;align-items:center;gap:var(--jv-spacing-sm)}.jv-sidebar-link:hover,.jv-sidebar-child-link:hover,.jv-sidebar-toggle:hover{background:var(--jv-color-surface-muted);color:var(--jv-color-foreground)}.jv-sidebar-link.is-active,.jv-sidebar-child-link.is-active{border-color:color-mix(in srgb,var(--jv-color-primary) 25%,var(--jv-color-border));background:color-mix(in srgb,var(--jv-color-primary) 12%,var(--jv-color-surface));color:var(--jv-color-foreground)}.jv-sidebar-children{display:grid;gap:var(--jv-spacing-xs);margin-left:var(--jv-spacing-xl);padding-left:var(--jv-spacing-sm);border-left:1px solid var(--jv-color-border)}.jv-sidebar-child-link{display:flex;align-items:center;min-height:calc(var(--jv-density-control-height) - .25rem);font-size:.9rem}.jv-sidebar-toggle{width:100%;background:var(--jv-color-surface-muted);cursor:pointer}@media(max-width:900px){.jv-sidebar-backdrop{display:block;position:fixed;inset:0;z-index:99;background:#0006}.jv-sidebar{position:fixed;top:0;left:0;z-index:100;width:280px;min-width:280px;height:100vh;border-right:1px solid var(--jv-color-border);border-bottom:none;box-shadow:var(--jv-shadow-lg);transform:translate(-100%);visibility:hidden;transition:transform .24s cubic-bezier(.4,0,.2,1),visibility .24s}.jv-sidebar.is-mobile-open{transform:translate(0);visibility:visible}.jv-sidebar.is-collapsed{width:280px;min-width:280px}.jv-sidebar-mobile-extras{display:flex;flex-direction:column;gap:var(--jv-spacing-md);padding-top:var(--jv-spacing-md);border-top:1px solid var(--jv-color-border)}.jv-sidebar-mobile-extras .theme-group{display:flex;flex-wrap:wrap;gap:var(--jv-spacing-xs)}.jv-sidebar-mobile-extras .theme-pill{display:inline-flex;align-items:center;gap:var(--jv-spacing-xs);min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-md);border:1px solid var(--jv-color-border);border-radius:999px;background:var(--jv-color-surface-muted);color:var(--jv-color-foreground);cursor:pointer;font:inherit}.jv-sidebar-mobile-extras .theme-pill.is-active{border-color:var(--jv-color-primary);background:color-mix(in srgb,var(--jv-color-primary) 14%,var(--jv-color-surface))}.jv-sidebar-mobile-extras .mobile-actions{display:flex;gap:var(--jv-spacing-sm)}.jv-sidebar-mobile-extras .icon-button{display:inline-flex;align-items:center;gap:var(--jv-spacing-xs);min-width:var(--jv-density-control-height);height:var(--jv-density-control-height);padding:0 var(--jv-spacing-sm);border:1px solid var(--jv-color-border);border-radius:999px;background:var(--jv-color-surface-muted);color:var(--jv-color-foreground);cursor:pointer}}\n"], dependencies: [{ kind: "component", type: JvIconComponent, selector: "jv-icon", inputs: ["name", "size", "strokeWidth", "decorative", "ariaLabel"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: JvTooltipDirective, selector: "[jvTooltip]", inputs: ["jvTooltip", "jvTooltipPosition"] }] });
|
|
23188
23416
|
}
|
|
23189
23417
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JvSidebarComponent, decorators: [{
|
|
23190
23418
|
type: Component,
|
|
23191
|
-
args: [{ selector: 'jv-sidebar', standalone: true, imports: [JvIconComponent, RouterLink], template: `
|
|
23419
|
+
args: [{ selector: 'jv-sidebar', standalone: true, imports: [JvIconComponent, RouterLink, JvTooltipDirective], template: `
|
|
23192
23420
|
@if (mobileOpen()) {
|
|
23193
23421
|
<div class="jv-sidebar-backdrop" tabindex="-1" (click)="mobileClose.emit()" (keydown.escape)="mobileClose.emit()"></div>
|
|
23194
23422
|
}
|
|
@@ -23335,15 +23563,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
23335
23563
|
|
|
23336
23564
|
<div class="mobile-actions">
|
|
23337
23565
|
@for (action of topbarActions(); track action.id) {
|
|
23338
|
-
<button type="button" class="icon-button" [attr.aria-label]="action.label" (click)="actionClick.emit(action.id); mobileClose.emit()">
|
|
23566
|
+
<button type="button" class="icon-button" [attr.aria-label]="action.label" [attr.title]="action.label" [jvTooltip]="action.label" (click)="actionClick.emit(action.id); mobileClose.emit()">
|
|
23339
23567
|
<jv-icon [name]="action.icon" [size]="18" />
|
|
23568
|
+
<span>{{ action.label }}</span>
|
|
23340
23569
|
</button>
|
|
23341
23570
|
}
|
|
23342
23571
|
</div>
|
|
23343
23572
|
</div>
|
|
23344
23573
|
</div>
|
|
23345
23574
|
</aside>
|
|
23346
|
-
`, styles: [".jv-sidebar-backdrop{display:none}.jv-sidebar{display:grid;grid-template-rows:auto 1fr auto;gap:var(--jv-spacing-lg);width:280px;min-width:280px;height:100vh;padding:var(--jv-spacing-lg);overflow-y:auto;border-right:1px solid var(--jv-color-border);background:var(--jv-color-surface);scrollbar-width:none;-ms-overflow-style:none}.jv-sidebar::-webkit-scrollbar{width:0;height:0;display:none}.jv-sidebar.is-collapsed{width:96px;min-width:96px;padding-inline:var(--jv-spacing-md)}.jv-sidebar-footer{display:grid;gap:var(--jv-spacing-md)}.jv-sidebar-mobile-extras{display:none}.jv-sidebar-brand,.jv-sidebar-link,.jv-sidebar-toggle{display:flex;align-items:center;gap:var(--jv-spacing-sm)}.brand-mark{display:inline-grid;place-items:center;width:var(--jv-density-control-height);height:var(--jv-density-control-height);border-radius:var(--jv-radius-md);background:color-mix(in srgb,var(--jv-color-primary) 16%,var(--jv-color-surface));color:var(--jv-color-primary);flex:0 0 auto}.brand-copy{display:grid;gap:.1rem}.brand-copy span{color:var(--jv-color-foreground-muted);font-size:.875rem}.jv-sidebar-item{display:grid;gap:var(--jv-spacing-xs);list-style:none}.jv-sidebar-list{display:grid;gap:var(--jv-spacing-xs);margin:0;padding:0}.jv-sidebar-nav{display:grid;gap:var(--jv-spacing-xs);align-content:start}.jv-sidebar-link,.jv-sidebar-child-link,.jv-sidebar-toggle{width:100%;display:flex;align-items:center;justify-content:space-between;min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-md);border:1px solid transparent;border-radius:var(--jv-radius-md);background:transparent;color:var(--jv-color-foreground-muted);text-decoration:none;cursor:pointer}.jv-sidebar-link-main{display:inline-flex;align-items:center;gap:var(--jv-spacing-sm)}.jv-sidebar-link:hover,.jv-sidebar-child-link:hover,.jv-sidebar-toggle:hover{background:var(--jv-color-surface-muted);color:var(--jv-color-foreground)}.jv-sidebar-link.is-active,.jv-sidebar-child-link.is-active{border-color:color-mix(in srgb,var(--jv-color-primary) 25%,var(--jv-color-border));background:color-mix(in srgb,var(--jv-color-primary) 12%,var(--jv-color-surface));color:var(--jv-color-foreground)}.jv-sidebar-children{display:grid;gap:var(--jv-spacing-xs);margin-left:var(--jv-spacing-xl);padding-left:var(--jv-spacing-sm);border-left:1px solid var(--jv-color-border)}.jv-sidebar-child-link{display:flex;align-items:center;min-height:calc(var(--jv-density-control-height) - .25rem);font-size:.9rem}.jv-sidebar-toggle{width:100%;background:var(--jv-color-surface-muted);cursor:pointer}@media(max-width:900px){.jv-sidebar-backdrop{display:block;position:fixed;inset:0;z-index:99;background:#0006}.jv-sidebar{position:fixed;top:0;left:0;z-index:100;width:280px;min-width:280px;height:100vh;border-right:1px solid var(--jv-color-border);border-bottom:none;box-shadow:var(--jv-shadow-lg);transform:translate(-100%);visibility:hidden;transition:transform .24s cubic-bezier(.4,0,.2,1),visibility .24s}.jv-sidebar.is-mobile-open{transform:translate(0);visibility:visible}.jv-sidebar.is-collapsed{width:280px;min-width:280px}.jv-sidebar-mobile-extras{display:flex;flex-direction:column;gap:var(--jv-spacing-md);padding-top:var(--jv-spacing-md);border-top:1px solid var(--jv-color-border)}.jv-sidebar-mobile-extras .theme-group{display:flex;flex-wrap:wrap;gap:var(--jv-spacing-xs)}.jv-sidebar-mobile-extras .theme-pill{display:inline-flex;align-items:center;gap:var(--jv-spacing-xs);min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-md);border:1px solid var(--jv-color-border);border-radius:999px;background:var(--jv-color-surface-muted);color:var(--jv-color-foreground);cursor:pointer;font:inherit}.jv-sidebar-mobile-extras .theme-pill.is-active{border-color:var(--jv-color-primary);background:color-mix(in srgb,var(--jv-color-primary) 14%,var(--jv-color-surface))}.jv-sidebar-mobile-extras .mobile-actions{display:flex;gap:var(--jv-spacing-sm)}.jv-sidebar-mobile-extras .icon-button{display:inline-
|
|
23575
|
+
`, styles: [".jv-sidebar-backdrop{display:none}.jv-sidebar{display:grid;grid-template-rows:auto 1fr auto;gap:var(--jv-spacing-lg);width:280px;min-width:280px;height:100vh;padding:var(--jv-spacing-lg);overflow-y:auto;border-right:1px solid var(--jv-color-border);background:var(--jv-color-surface);scrollbar-width:none;-ms-overflow-style:none}.jv-sidebar::-webkit-scrollbar{width:0;height:0;display:none}.jv-sidebar.is-collapsed{width:96px;min-width:96px;padding-inline:var(--jv-spacing-md)}.jv-sidebar-footer{display:grid;gap:var(--jv-spacing-md)}.jv-sidebar-mobile-extras{display:none}.jv-sidebar-brand,.jv-sidebar-link,.jv-sidebar-toggle{display:flex;align-items:center;gap:var(--jv-spacing-sm)}.brand-mark{display:inline-grid;place-items:center;width:var(--jv-density-control-height);height:var(--jv-density-control-height);border-radius:var(--jv-radius-md);background:color-mix(in srgb,var(--jv-color-primary) 16%,var(--jv-color-surface));color:var(--jv-color-primary);flex:0 0 auto}.brand-copy{display:grid;gap:.1rem}.brand-copy span{color:var(--jv-color-foreground-muted);font-size:.875rem}.jv-sidebar-item{display:grid;gap:var(--jv-spacing-xs);list-style:none}.jv-sidebar-list{display:grid;gap:var(--jv-spacing-xs);margin:0;padding:0}.jv-sidebar-nav{display:grid;gap:var(--jv-spacing-xs);align-content:start}.jv-sidebar-link,.jv-sidebar-child-link,.jv-sidebar-toggle{width:100%;display:flex;align-items:center;justify-content:space-between;min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-md);border:1px solid transparent;border-radius:var(--jv-radius-md);background:transparent;color:var(--jv-color-foreground-muted);text-decoration:none;cursor:pointer}.jv-sidebar-link-main{display:inline-flex;align-items:center;gap:var(--jv-spacing-sm)}.jv-sidebar-link:hover,.jv-sidebar-child-link:hover,.jv-sidebar-toggle:hover{background:var(--jv-color-surface-muted);color:var(--jv-color-foreground)}.jv-sidebar-link.is-active,.jv-sidebar-child-link.is-active{border-color:color-mix(in srgb,var(--jv-color-primary) 25%,var(--jv-color-border));background:color-mix(in srgb,var(--jv-color-primary) 12%,var(--jv-color-surface));color:var(--jv-color-foreground)}.jv-sidebar-children{display:grid;gap:var(--jv-spacing-xs);margin-left:var(--jv-spacing-xl);padding-left:var(--jv-spacing-sm);border-left:1px solid var(--jv-color-border)}.jv-sidebar-child-link{display:flex;align-items:center;min-height:calc(var(--jv-density-control-height) - .25rem);font-size:.9rem}.jv-sidebar-toggle{width:100%;background:var(--jv-color-surface-muted);cursor:pointer}@media(max-width:900px){.jv-sidebar-backdrop{display:block;position:fixed;inset:0;z-index:99;background:#0006}.jv-sidebar{position:fixed;top:0;left:0;z-index:100;width:280px;min-width:280px;height:100vh;border-right:1px solid var(--jv-color-border);border-bottom:none;box-shadow:var(--jv-shadow-lg);transform:translate(-100%);visibility:hidden;transition:transform .24s cubic-bezier(.4,0,.2,1),visibility .24s}.jv-sidebar.is-mobile-open{transform:translate(0);visibility:visible}.jv-sidebar.is-collapsed{width:280px;min-width:280px}.jv-sidebar-mobile-extras{display:flex;flex-direction:column;gap:var(--jv-spacing-md);padding-top:var(--jv-spacing-md);border-top:1px solid var(--jv-color-border)}.jv-sidebar-mobile-extras .theme-group{display:flex;flex-wrap:wrap;gap:var(--jv-spacing-xs)}.jv-sidebar-mobile-extras .theme-pill{display:inline-flex;align-items:center;gap:var(--jv-spacing-xs);min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-md);border:1px solid var(--jv-color-border);border-radius:999px;background:var(--jv-color-surface-muted);color:var(--jv-color-foreground);cursor:pointer;font:inherit}.jv-sidebar-mobile-extras .theme-pill.is-active{border-color:var(--jv-color-primary);background:color-mix(in srgb,var(--jv-color-primary) 14%,var(--jv-color-surface))}.jv-sidebar-mobile-extras .mobile-actions{display:flex;gap:var(--jv-spacing-sm)}.jv-sidebar-mobile-extras .icon-button{display:inline-flex;align-items:center;gap:var(--jv-spacing-xs);min-width:var(--jv-density-control-height);height:var(--jv-density-control-height);padding:0 var(--jv-spacing-sm);border:1px solid var(--jv-color-border);border-radius:999px;background:var(--jv-color-surface-muted);color:var(--jv-color-foreground);cursor:pointer}}\n"] }]
|
|
23347
23576
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], brandIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "brandIcon", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], collapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsed", required: false }] }], mobileOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileOpen", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], currentTheme: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentTheme", required: false }] }], themeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "themeOptions", required: false }] }], topbarActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "topbarActions", required: false }] }], showThemeSelector: [{ type: i0.Input, args: [{ isSignal: true, alias: "showThemeSelector", required: false }] }], collapseToggle: [{ type: i0.Output, args: ["collapseToggle"] }], mobileClose: [{ type: i0.Output, args: ["mobileClose"] }], themeChange: [{ type: i0.Output, args: ["themeChange"] }], actionClick: [{ type: i0.Output, args: ["actionClick"] }] } });
|
|
23348
23577
|
|
|
23349
23578
|
class JvTopbarComponent {
|
|
@@ -23397,17 +23626,18 @@ class JvTopbarComponent {
|
|
|
23397
23626
|
}
|
|
23398
23627
|
|
|
23399
23628
|
@for (action of visibleActions(); track action.id) {
|
|
23400
|
-
<button type="button" class="icon-button" [attr.aria-label]="action.label" (click)="actionClick.emit(action.id)">
|
|
23629
|
+
<button type="button" class="icon-button" [attr.aria-label]="action.label" [attr.title]="action.label" [jvTooltip]="action.label" (click)="actionClick.emit(action.id)">
|
|
23401
23630
|
<jv-icon [name]="action.icon" [size]="18" />
|
|
23631
|
+
<span class="action-label">{{ action.label }}</span>
|
|
23402
23632
|
</button>
|
|
23403
23633
|
}
|
|
23404
23634
|
</div>
|
|
23405
23635
|
</header>
|
|
23406
|
-
`, isInline: true, styles: [".jv-topbar{display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-md);padding:var(--jv-spacing-md) var(--jv-spacing-lg);border-bottom:1px solid var(--jv-color-border);background:var(--jv-color-surface)}.jv-topbar-start,.jv-topbar-end,.theme-group{display:flex;align-items:center;gap:var(--jv-spacing-sm)}.jv-topbar-end{flex-wrap:wrap;justify-content:flex-end}.title-block{display:grid;gap:.1rem}.title-block span{color:var(--jv-color-foreground-muted);font-size:.875rem}.icon-button,.theme-pill{border:1px solid var(--jv-color-border);background:var(--jv-color-surface-muted);color:var(--jv-color-foreground)}.icon-button{display:inline-
|
|
23636
|
+
`, isInline: true, styles: [".jv-topbar{display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-md);padding:var(--jv-spacing-md) var(--jv-spacing-lg);border-bottom:1px solid var(--jv-color-border);background:var(--jv-color-surface)}.jv-topbar-start,.jv-topbar-end,.theme-group{display:flex;align-items:center;gap:var(--jv-spacing-sm)}.jv-topbar-end{flex-wrap:wrap;justify-content:flex-end}.title-block{display:grid;gap:.1rem}.title-block span{color:var(--jv-color-foreground-muted);font-size:.875rem}.icon-button,.theme-pill{border:1px solid var(--jv-color-border);background:var(--jv-color-surface-muted);color:var(--jv-color-foreground)}.icon-button{display:inline-flex;align-items:center;justify-content:center;gap:var(--jv-spacing-xs);min-width:var(--jv-density-control-height);height:var(--jv-density-control-height);padding:0 var(--jv-spacing-sm);border-radius:999px;cursor:pointer}.theme-pill{display:inline-flex;align-items:center;gap:var(--jv-spacing-xs);min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-md);border-radius:999px}.theme-pill.is-active{border-color:var(--jv-color-primary);background:color-mix(in srgb,var(--jv-color-primary) 14%,var(--jv-color-surface))}@media(max-width:900px){.jv-topbar{align-items:center;flex-direction:row;justify-content:flex-start}.jv-topbar-end{display:none}}\n"], dependencies: [{ kind: "component", type: JvIconComponent, selector: "jv-icon", inputs: ["name", "size", "strokeWidth", "decorative", "ariaLabel"] }, { kind: "directive", type: JvTooltipDirective, selector: "[jvTooltip]", inputs: ["jvTooltip", "jvTooltipPosition"] }] });
|
|
23407
23637
|
}
|
|
23408
23638
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JvTopbarComponent, decorators: [{
|
|
23409
23639
|
type: Component,
|
|
23410
|
-
args: [{ selector: 'jv-topbar', standalone: true, imports: [JvIconComponent], template: `
|
|
23640
|
+
args: [{ selector: 'jv-topbar', standalone: true, imports: [JvIconComponent, JvTooltipDirective], template: `
|
|
23411
23641
|
<header class="jv-topbar">
|
|
23412
23642
|
<div class="jv-topbar-start">
|
|
23413
23643
|
<button type="button" class="icon-button" (click)="menuClick.emit()" aria-label="Toggle navigation menu">
|
|
@@ -23446,24 +23676,272 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
23446
23676
|
}
|
|
23447
23677
|
|
|
23448
23678
|
@for (action of visibleActions(); track action.id) {
|
|
23449
|
-
<button type="button" class="icon-button" [attr.aria-label]="action.label" (click)="actionClick.emit(action.id)">
|
|
23679
|
+
<button type="button" class="icon-button" [attr.aria-label]="action.label" [attr.title]="action.label" [jvTooltip]="action.label" (click)="actionClick.emit(action.id)">
|
|
23450
23680
|
<jv-icon [name]="action.icon" [size]="18" />
|
|
23681
|
+
<span class="action-label">{{ action.label }}</span>
|
|
23451
23682
|
</button>
|
|
23452
23683
|
}
|
|
23453
23684
|
</div>
|
|
23454
23685
|
</header>
|
|
23455
|
-
`, styles: [".jv-topbar{display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-md);padding:var(--jv-spacing-md) var(--jv-spacing-lg);border-bottom:1px solid var(--jv-color-border);background:var(--jv-color-surface)}.jv-topbar-start,.jv-topbar-end,.theme-group{display:flex;align-items:center;gap:var(--jv-spacing-sm)}.jv-topbar-end{flex-wrap:wrap;justify-content:flex-end}.title-block{display:grid;gap:.1rem}.title-block span{color:var(--jv-color-foreground-muted);font-size:.875rem}.icon-button,.theme-pill{border:1px solid var(--jv-color-border);background:var(--jv-color-surface-muted);color:var(--jv-color-foreground)}.icon-button{display:inline-
|
|
23686
|
+
`, styles: [".jv-topbar{display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-md);padding:var(--jv-spacing-md) var(--jv-spacing-lg);border-bottom:1px solid var(--jv-color-border);background:var(--jv-color-surface)}.jv-topbar-start,.jv-topbar-end,.theme-group{display:flex;align-items:center;gap:var(--jv-spacing-sm)}.jv-topbar-end{flex-wrap:wrap;justify-content:flex-end}.title-block{display:grid;gap:.1rem}.title-block span{color:var(--jv-color-foreground-muted);font-size:.875rem}.icon-button,.theme-pill{border:1px solid var(--jv-color-border);background:var(--jv-color-surface-muted);color:var(--jv-color-foreground)}.icon-button{display:inline-flex;align-items:center;justify-content:center;gap:var(--jv-spacing-xs);min-width:var(--jv-density-control-height);height:var(--jv-density-control-height);padding:0 var(--jv-spacing-sm);border-radius:999px;cursor:pointer}.theme-pill{display:inline-flex;align-items:center;gap:var(--jv-spacing-xs);min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-md);border-radius:999px}.theme-pill.is-active{border-color:var(--jv-color-primary);background:color-mix(in srgb,var(--jv-color-primary) 14%,var(--jv-color-surface))}@media(max-width:900px){.jv-topbar{align-items:center;flex-direction:row;justify-content:flex-start}.jv-topbar-end{display:none}}\n"] }]
|
|
23456
23687
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], currentTheme: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentTheme", required: false }] }], themeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "themeOptions", required: false }] }], actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: false }] }], showThemeSelector: [{ type: i0.Input, args: [{ isSignal: true, alias: "showThemeSelector", required: false }] }], menuClick: [{ type: i0.Output, args: ["menuClick"] }], themeChange: [{ type: i0.Output, args: ["themeChange"] }], actionClick: [{ type: i0.Output, args: ["actionClick"] }] } });
|
|
23457
23688
|
|
|
23458
|
-
class
|
|
23689
|
+
class JvTopbarMenuComponent {
|
|
23459
23690
|
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
23460
|
-
|
|
23691
|
+
subtitle = input('', ...(ngDevMode ? [{ debugName: "subtitle" }] : /* istanbul ignore next */ []));
|
|
23461
23692
|
brandIcon = input('monitor', ...(ngDevMode ? [{ debugName: "brandIcon" }] : /* istanbul ignore next */ []));
|
|
23462
|
-
|
|
23463
|
-
|
|
23464
|
-
|
|
23465
|
-
|
|
23466
|
-
|
|
23693
|
+
items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
23694
|
+
mobileOpen = input(false, ...(ngDevMode ? [{ debugName: "mobileOpen" }] : /* istanbul ignore next */ []));
|
|
23695
|
+
ariaLabel = input('Topbar navigation', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
23696
|
+
currentTheme = input('light', ...(ngDevMode ? [{ debugName: "currentTheme" }] : /* istanbul ignore next */ []));
|
|
23697
|
+
themeOptions = input([], ...(ngDevMode ? [{ debugName: "themeOptions" }] : /* istanbul ignore next */ []));
|
|
23698
|
+
actions = input([], ...(ngDevMode ? [{ debugName: "actions" }] : /* istanbul ignore next */ []));
|
|
23699
|
+
showThemeSelector = input(true, ...(ngDevMode ? [{ debugName: "showThemeSelector" }] : /* istanbul ignore next */ []));
|
|
23700
|
+
menuClick = output();
|
|
23701
|
+
mobileClose = output();
|
|
23702
|
+
themeChange = output();
|
|
23703
|
+
actionClick = output();
|
|
23704
|
+
navigation = new JvNavigationState(this.items, inject(Router), false);
|
|
23705
|
+
normalizedItems = this.navigation.normalizedItems;
|
|
23706
|
+
isExpanded(id) {
|
|
23707
|
+
return this.navigation.isExpanded(id);
|
|
23708
|
+
}
|
|
23709
|
+
toggleSection(id) {
|
|
23710
|
+
this.navigation.toggleSection(id, true);
|
|
23711
|
+
}
|
|
23712
|
+
isHashLink(href) {
|
|
23713
|
+
return this.navigation.isHashLink(href);
|
|
23714
|
+
}
|
|
23715
|
+
navigateTo(href, parentId) {
|
|
23716
|
+
this.navigation.navigateTo(href);
|
|
23717
|
+
if (parentId) {
|
|
23718
|
+
this.navigation.closeSection(parentId);
|
|
23719
|
+
}
|
|
23720
|
+
this.mobileClose.emit();
|
|
23721
|
+
}
|
|
23722
|
+
closeSection(id) {
|
|
23723
|
+
this.navigation.closeSection(id);
|
|
23724
|
+
}
|
|
23725
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JvTopbarMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
23726
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: JvTopbarMenuComponent, isStandalone: true, selector: "jv-topbar-menu", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, brandIcon: { classPropertyName: "brandIcon", publicName: "brandIcon", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, mobileOpen: { classPropertyName: "mobileOpen", publicName: "mobileOpen", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, currentTheme: { classPropertyName: "currentTheme", publicName: "currentTheme", isSignal: true, isRequired: false, transformFunction: null }, themeOptions: { classPropertyName: "themeOptions", publicName: "themeOptions", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, showThemeSelector: { classPropertyName: "showThemeSelector", publicName: "showThemeSelector", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { menuClick: "menuClick", mobileClose: "mobileClose", themeChange: "themeChange", actionClick: "actionClick" }, ngImport: i0, template: `
|
|
23727
|
+
@if (mobileOpen()) {
|
|
23728
|
+
<div class="jv-topbar-menu-backdrop" tabindex="-1" (click)="mobileClose.emit()" (keydown.escape)="mobileClose.emit()"></div>
|
|
23729
|
+
}
|
|
23730
|
+
|
|
23731
|
+
<header class="jv-topbar-menu" [class.is-mobile-open]="mobileOpen()">
|
|
23732
|
+
<div class="jv-topbar-menu-brand">
|
|
23733
|
+
<div class="brand-mark">
|
|
23734
|
+
<jv-icon [name]="brandIcon()" [size]="18" />
|
|
23735
|
+
</div>
|
|
23736
|
+
<div class="brand-copy">
|
|
23737
|
+
<strong>{{ title() }}</strong>
|
|
23738
|
+
@if (subtitle()) {
|
|
23739
|
+
<span>{{ subtitle() }}</span>
|
|
23740
|
+
}
|
|
23741
|
+
</div>
|
|
23742
|
+
</div>
|
|
23743
|
+
|
|
23744
|
+
<button type="button" class="mobile-menu-button" aria-label="Toggle navigation menu" (click)="menuClick.emit()">
|
|
23745
|
+
<jv-icon name="menu" [size]="18" />
|
|
23746
|
+
</button>
|
|
23747
|
+
|
|
23748
|
+
<nav class="jv-topbar-menu-nav" [attr.aria-label]="ariaLabel()">
|
|
23749
|
+
<ul class="jv-topbar-menu-list">
|
|
23750
|
+
@for (item of normalizedItems(); track item.id) {
|
|
23751
|
+
<li class="jv-topbar-menu-item">
|
|
23752
|
+
@if (item.children.length > 0) {
|
|
23753
|
+
<button
|
|
23754
|
+
type="button"
|
|
23755
|
+
class="jv-topbar-menu-link"
|
|
23756
|
+
[class.is-active]="item.active"
|
|
23757
|
+
[attr.aria-expanded]="isExpanded(item.id) ? 'true' : 'false'"
|
|
23758
|
+
[attr.aria-controls]="'jv-topbar-menu-section-' + item.id"
|
|
23759
|
+
(click)="toggleSection(item.id)"
|
|
23760
|
+
>
|
|
23761
|
+
@if (item.icon) {
|
|
23762
|
+
<jv-icon [name]="item.icon" [size]="17" />
|
|
23763
|
+
}
|
|
23764
|
+
<span>{{ item.label }}</span>
|
|
23765
|
+
<jv-icon [name]="isExpanded(item.id) ? 'chevron-up' : 'chevron-down'" [size]="15" />
|
|
23766
|
+
</button>
|
|
23767
|
+
|
|
23768
|
+
@if (isExpanded(item.id)) {
|
|
23769
|
+
<div class="jv-topbar-menu-dropdown" [id]="'jv-topbar-menu-section-' + item.id">
|
|
23770
|
+
@for (child of item.children; track child.id) {
|
|
23771
|
+
@if (isHashLink(child.href)) {
|
|
23772
|
+
<button type="button" class="jv-topbar-menu-child" [class.is-active]="child.active" (click)="navigateTo(child.href, item.id)">
|
|
23773
|
+
{{ child.label }}
|
|
23774
|
+
</button>
|
|
23775
|
+
} @else {
|
|
23776
|
+
<a class="jv-topbar-menu-child" [class.is-active]="child.active" [routerLink]="child.href" [attr.aria-current]="child.active ? 'page' : null" (click)="closeSection(item.id); mobileClose.emit()">
|
|
23777
|
+
{{ child.label }}
|
|
23778
|
+
</a>
|
|
23779
|
+
}
|
|
23780
|
+
}
|
|
23781
|
+
</div>
|
|
23782
|
+
}
|
|
23783
|
+
} @else {
|
|
23784
|
+
@if (isHashLink(item.href)) {
|
|
23785
|
+
<button type="button" class="jv-topbar-menu-link" [class.is-active]="item.active" (click)="navigateTo(item.href)">
|
|
23786
|
+
@if (item.icon) {
|
|
23787
|
+
<jv-icon [name]="item.icon" [size]="17" />
|
|
23788
|
+
}
|
|
23789
|
+
<span>{{ item.label }}</span>
|
|
23790
|
+
</button>
|
|
23791
|
+
} @else {
|
|
23792
|
+
<a class="jv-topbar-menu-link" [class.is-active]="item.active" [routerLink]="item.href" [attr.aria-current]="item.active ? 'page' : null" (click)="mobileClose.emit()">
|
|
23793
|
+
@if (item.icon) {
|
|
23794
|
+
<jv-icon [name]="item.icon" [size]="17" />
|
|
23795
|
+
}
|
|
23796
|
+
<span>{{ item.label }}</span>
|
|
23797
|
+
</a>
|
|
23798
|
+
}
|
|
23799
|
+
}
|
|
23800
|
+
</li>
|
|
23801
|
+
}
|
|
23802
|
+
</ul>
|
|
23803
|
+
</nav>
|
|
23804
|
+
|
|
23805
|
+
<div class="jv-topbar-menu-actions">
|
|
23806
|
+
@if (showThemeSelector()) {
|
|
23807
|
+
<div class="theme-group" aria-label="Theme selector">
|
|
23808
|
+
@for (option of themeOptions(); track option.value) {
|
|
23809
|
+
<button type="button" class="theme-pill" [class.is-active]="currentTheme() === option.value" (click)="themeChange.emit(option.value)">
|
|
23810
|
+
@if (option.icon) {
|
|
23811
|
+
<jv-icon [name]="option.icon" [size]="16" />
|
|
23812
|
+
}
|
|
23813
|
+
<span>{{ option.label }}</span>
|
|
23814
|
+
</button>
|
|
23815
|
+
}
|
|
23816
|
+
</div>
|
|
23817
|
+
}
|
|
23818
|
+
|
|
23819
|
+
@for (action of actions(); track action.id) {
|
|
23820
|
+
<button type="button" class="icon-button" [attr.aria-label]="action.label" [attr.title]="action.label" [jvTooltip]="action.label" (click)="actionClick.emit(action.id)">
|
|
23821
|
+
<jv-icon [name]="action.icon" [size]="18" />
|
|
23822
|
+
<span class="action-label">{{ action.label }}</span>
|
|
23823
|
+
</button>
|
|
23824
|
+
}
|
|
23825
|
+
</div>
|
|
23826
|
+
</header>
|
|
23827
|
+
`, isInline: true, styles: [":host{display:block;position:relative;z-index:20}.jv-topbar-menu,.jv-topbar-menu-brand,.jv-topbar-menu-list,.jv-topbar-menu-actions,.theme-group{display:flex;align-items:center}.jv-topbar-menu{gap:var(--jv-spacing-lg);min-height:4.5rem;padding:var(--jv-spacing-md) var(--jv-spacing-xl);min-width:0;border-bottom:1px solid var(--jv-color-border);background:var(--jv-color-surface)}.jv-topbar-menu-brand{gap:var(--jv-spacing-sm);flex:0 0 auto}.brand-mark{display:inline-grid;place-items:center;width:var(--jv-density-control-height);height:var(--jv-density-control-height);border-radius:var(--jv-radius-md);background:color-mix(in srgb,var(--jv-color-primary) 16%,var(--jv-color-surface));color:var(--jv-color-primary)}.brand-copy{display:grid;gap:.1rem}.brand-copy span{color:var(--jv-color-foreground-muted);font-size:.8125rem}.jv-topbar-menu-nav{min-width:0;flex:1 1 0}.jv-topbar-menu-list{gap:var(--jv-spacing-xs);margin:0;padding:0;list-style:none;min-width:0;flex-wrap:wrap}.jv-topbar-menu-item{position:relative;min-width:0;flex:0 1 auto}.jv-topbar-menu-link,.jv-topbar-menu-child,.icon-button,.theme-pill,.mobile-menu-button{border:1px solid transparent;background:transparent;color:var(--jv-color-foreground-muted);cursor:pointer;font:inherit;text-decoration:none}.jv-topbar-menu-link{display:inline-flex;align-items:center;gap:var(--jv-spacing-xs);min-height:var(--jv-density-control-height);min-width:0;width:100%;max-width:15rem;padding:0 var(--jv-spacing-sm);border-radius:var(--jv-radius-md);white-space:nowrap}.jv-topbar-menu-link span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.jv-topbar-menu-link:hover,.jv-topbar-menu-child:hover,.jv-topbar-menu-link.is-active,.jv-topbar-menu-child.is-active{background:color-mix(in srgb,var(--jv-color-primary) 12%,var(--jv-color-surface));color:var(--jv-color-foreground)}.jv-topbar-menu-dropdown{position:absolute;top:calc(100% + var(--jv-spacing-xs));left:0;display:grid;min-width:14rem;max-height:min(70vh,32rem);gap:var(--jv-spacing-xs);padding:var(--jv-spacing-sm);overflow-y:auto;border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-md);background:var(--jv-color-surface);box-shadow:var(--jv-shadow-lg);z-index:30}.jv-topbar-menu-child{display:block;padding:var(--jv-spacing-sm) var(--jv-spacing-md);border-radius:var(--jv-radius-sm);text-align:left;white-space:nowrap}.jv-topbar-menu-actions{justify-content:flex-end;gap:var(--jv-spacing-sm);flex:0 0 auto}.theme-group{gap:var(--jv-spacing-xs)}.icon-button,.mobile-menu-button{display:inline-flex;align-items:center;justify-content:center;gap:var(--jv-spacing-xs);min-width:var(--jv-density-control-height);height:var(--jv-density-control-height);padding:0 var(--jv-spacing-sm);border-color:var(--jv-color-border);border-radius:999px;background:var(--jv-color-surface-muted);color:var(--jv-color-foreground)}.icon-button{cursor:pointer}.theme-pill{display:inline-flex;align-items:center;gap:var(--jv-spacing-xs);min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-sm);border-color:var(--jv-color-border);border-radius:999px;background:var(--jv-color-surface-muted);color:var(--jv-color-foreground);font-size:.8125rem}.theme-pill.is-active{border-color:var(--jv-color-primary);background:color-mix(in srgb,var(--jv-color-primary) 14%,var(--jv-color-surface))}.mobile-menu-button,.jv-topbar-menu-backdrop{display:none}@media(max-width:1100px){.jv-topbar-menu{gap:var(--jv-spacing-md);padding-inline:var(--jv-spacing-lg)}.jv-topbar-menu-link{max-width:12rem;padding-inline:var(--jv-spacing-xs)}}@media(max-width:1400px){.jv-topbar-menu-actions .theme-group{display:none}}@media(max-width:900px){.jv-topbar-menu-backdrop{display:block;position:fixed;inset:0;z-index:19;background:#0006}.jv-topbar-menu{position:relative;justify-content:space-between;min-height:4rem;padding:var(--jv-spacing-sm) var(--jv-spacing-md)}.mobile-menu-button{display:inline-grid;order:3}.jv-topbar-menu-nav{position:fixed;top:4rem;right:0;bottom:0;z-index:21;width:min(22rem,88vw);padding:var(--jv-spacing-lg);overflow-y:auto;border-left:1px solid var(--jv-color-border);background:var(--jv-color-surface);box-shadow:var(--jv-shadow-lg);transform:translate(100%);visibility:hidden;transition:transform .24s ease,visibility .24s}.jv-topbar-menu.is-mobile-open .jv-topbar-menu-nav{transform:translate(0);visibility:visible}.jv-topbar-menu-list{display:grid;align-items:stretch}.jv-topbar-menu-link{width:100%;justify-content:flex-start;padding-inline:var(--jv-spacing-md)}.jv-topbar-menu-dropdown{position:static;min-width:0;margin-left:var(--jv-spacing-md);box-shadow:none}.jv-topbar-menu-actions{margin-left:auto}}\n"], dependencies: [{ kind: "component", type: JvIconComponent, selector: "jv-icon", inputs: ["name", "size", "strokeWidth", "decorative", "ariaLabel"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: JvTooltipDirective, selector: "[jvTooltip]", inputs: ["jvTooltip", "jvTooltipPosition"] }] });
|
|
23828
|
+
}
|
|
23829
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JvTopbarMenuComponent, decorators: [{
|
|
23830
|
+
type: Component,
|
|
23831
|
+
args: [{ selector: 'jv-topbar-menu', standalone: true, imports: [JvIconComponent, RouterLink, JvTooltipDirective], template: `
|
|
23832
|
+
@if (mobileOpen()) {
|
|
23833
|
+
<div class="jv-topbar-menu-backdrop" tabindex="-1" (click)="mobileClose.emit()" (keydown.escape)="mobileClose.emit()"></div>
|
|
23834
|
+
}
|
|
23835
|
+
|
|
23836
|
+
<header class="jv-topbar-menu" [class.is-mobile-open]="mobileOpen()">
|
|
23837
|
+
<div class="jv-topbar-menu-brand">
|
|
23838
|
+
<div class="brand-mark">
|
|
23839
|
+
<jv-icon [name]="brandIcon()" [size]="18" />
|
|
23840
|
+
</div>
|
|
23841
|
+
<div class="brand-copy">
|
|
23842
|
+
<strong>{{ title() }}</strong>
|
|
23843
|
+
@if (subtitle()) {
|
|
23844
|
+
<span>{{ subtitle() }}</span>
|
|
23845
|
+
}
|
|
23846
|
+
</div>
|
|
23847
|
+
</div>
|
|
23848
|
+
|
|
23849
|
+
<button type="button" class="mobile-menu-button" aria-label="Toggle navigation menu" (click)="menuClick.emit()">
|
|
23850
|
+
<jv-icon name="menu" [size]="18" />
|
|
23851
|
+
</button>
|
|
23852
|
+
|
|
23853
|
+
<nav class="jv-topbar-menu-nav" [attr.aria-label]="ariaLabel()">
|
|
23854
|
+
<ul class="jv-topbar-menu-list">
|
|
23855
|
+
@for (item of normalizedItems(); track item.id) {
|
|
23856
|
+
<li class="jv-topbar-menu-item">
|
|
23857
|
+
@if (item.children.length > 0) {
|
|
23858
|
+
<button
|
|
23859
|
+
type="button"
|
|
23860
|
+
class="jv-topbar-menu-link"
|
|
23861
|
+
[class.is-active]="item.active"
|
|
23862
|
+
[attr.aria-expanded]="isExpanded(item.id) ? 'true' : 'false'"
|
|
23863
|
+
[attr.aria-controls]="'jv-topbar-menu-section-' + item.id"
|
|
23864
|
+
(click)="toggleSection(item.id)"
|
|
23865
|
+
>
|
|
23866
|
+
@if (item.icon) {
|
|
23867
|
+
<jv-icon [name]="item.icon" [size]="17" />
|
|
23868
|
+
}
|
|
23869
|
+
<span>{{ item.label }}</span>
|
|
23870
|
+
<jv-icon [name]="isExpanded(item.id) ? 'chevron-up' : 'chevron-down'" [size]="15" />
|
|
23871
|
+
</button>
|
|
23872
|
+
|
|
23873
|
+
@if (isExpanded(item.id)) {
|
|
23874
|
+
<div class="jv-topbar-menu-dropdown" [id]="'jv-topbar-menu-section-' + item.id">
|
|
23875
|
+
@for (child of item.children; track child.id) {
|
|
23876
|
+
@if (isHashLink(child.href)) {
|
|
23877
|
+
<button type="button" class="jv-topbar-menu-child" [class.is-active]="child.active" (click)="navigateTo(child.href, item.id)">
|
|
23878
|
+
{{ child.label }}
|
|
23879
|
+
</button>
|
|
23880
|
+
} @else {
|
|
23881
|
+
<a class="jv-topbar-menu-child" [class.is-active]="child.active" [routerLink]="child.href" [attr.aria-current]="child.active ? 'page' : null" (click)="closeSection(item.id); mobileClose.emit()">
|
|
23882
|
+
{{ child.label }}
|
|
23883
|
+
</a>
|
|
23884
|
+
}
|
|
23885
|
+
}
|
|
23886
|
+
</div>
|
|
23887
|
+
}
|
|
23888
|
+
} @else {
|
|
23889
|
+
@if (isHashLink(item.href)) {
|
|
23890
|
+
<button type="button" class="jv-topbar-menu-link" [class.is-active]="item.active" (click)="navigateTo(item.href)">
|
|
23891
|
+
@if (item.icon) {
|
|
23892
|
+
<jv-icon [name]="item.icon" [size]="17" />
|
|
23893
|
+
}
|
|
23894
|
+
<span>{{ item.label }}</span>
|
|
23895
|
+
</button>
|
|
23896
|
+
} @else {
|
|
23897
|
+
<a class="jv-topbar-menu-link" [class.is-active]="item.active" [routerLink]="item.href" [attr.aria-current]="item.active ? 'page' : null" (click)="mobileClose.emit()">
|
|
23898
|
+
@if (item.icon) {
|
|
23899
|
+
<jv-icon [name]="item.icon" [size]="17" />
|
|
23900
|
+
}
|
|
23901
|
+
<span>{{ item.label }}</span>
|
|
23902
|
+
</a>
|
|
23903
|
+
}
|
|
23904
|
+
}
|
|
23905
|
+
</li>
|
|
23906
|
+
}
|
|
23907
|
+
</ul>
|
|
23908
|
+
</nav>
|
|
23909
|
+
|
|
23910
|
+
<div class="jv-topbar-menu-actions">
|
|
23911
|
+
@if (showThemeSelector()) {
|
|
23912
|
+
<div class="theme-group" aria-label="Theme selector">
|
|
23913
|
+
@for (option of themeOptions(); track option.value) {
|
|
23914
|
+
<button type="button" class="theme-pill" [class.is-active]="currentTheme() === option.value" (click)="themeChange.emit(option.value)">
|
|
23915
|
+
@if (option.icon) {
|
|
23916
|
+
<jv-icon [name]="option.icon" [size]="16" />
|
|
23917
|
+
}
|
|
23918
|
+
<span>{{ option.label }}</span>
|
|
23919
|
+
</button>
|
|
23920
|
+
}
|
|
23921
|
+
</div>
|
|
23922
|
+
}
|
|
23923
|
+
|
|
23924
|
+
@for (action of actions(); track action.id) {
|
|
23925
|
+
<button type="button" class="icon-button" [attr.aria-label]="action.label" [attr.title]="action.label" [jvTooltip]="action.label" (click)="actionClick.emit(action.id)">
|
|
23926
|
+
<jv-icon [name]="action.icon" [size]="18" />
|
|
23927
|
+
<span class="action-label">{{ action.label }}</span>
|
|
23928
|
+
</button>
|
|
23929
|
+
}
|
|
23930
|
+
</div>
|
|
23931
|
+
</header>
|
|
23932
|
+
`, styles: [":host{display:block;position:relative;z-index:20}.jv-topbar-menu,.jv-topbar-menu-brand,.jv-topbar-menu-list,.jv-topbar-menu-actions,.theme-group{display:flex;align-items:center}.jv-topbar-menu{gap:var(--jv-spacing-lg);min-height:4.5rem;padding:var(--jv-spacing-md) var(--jv-spacing-xl);min-width:0;border-bottom:1px solid var(--jv-color-border);background:var(--jv-color-surface)}.jv-topbar-menu-brand{gap:var(--jv-spacing-sm);flex:0 0 auto}.brand-mark{display:inline-grid;place-items:center;width:var(--jv-density-control-height);height:var(--jv-density-control-height);border-radius:var(--jv-radius-md);background:color-mix(in srgb,var(--jv-color-primary) 16%,var(--jv-color-surface));color:var(--jv-color-primary)}.brand-copy{display:grid;gap:.1rem}.brand-copy span{color:var(--jv-color-foreground-muted);font-size:.8125rem}.jv-topbar-menu-nav{min-width:0;flex:1 1 0}.jv-topbar-menu-list{gap:var(--jv-spacing-xs);margin:0;padding:0;list-style:none;min-width:0;flex-wrap:wrap}.jv-topbar-menu-item{position:relative;min-width:0;flex:0 1 auto}.jv-topbar-menu-link,.jv-topbar-menu-child,.icon-button,.theme-pill,.mobile-menu-button{border:1px solid transparent;background:transparent;color:var(--jv-color-foreground-muted);cursor:pointer;font:inherit;text-decoration:none}.jv-topbar-menu-link{display:inline-flex;align-items:center;gap:var(--jv-spacing-xs);min-height:var(--jv-density-control-height);min-width:0;width:100%;max-width:15rem;padding:0 var(--jv-spacing-sm);border-radius:var(--jv-radius-md);white-space:nowrap}.jv-topbar-menu-link span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.jv-topbar-menu-link:hover,.jv-topbar-menu-child:hover,.jv-topbar-menu-link.is-active,.jv-topbar-menu-child.is-active{background:color-mix(in srgb,var(--jv-color-primary) 12%,var(--jv-color-surface));color:var(--jv-color-foreground)}.jv-topbar-menu-dropdown{position:absolute;top:calc(100% + var(--jv-spacing-xs));left:0;display:grid;min-width:14rem;max-height:min(70vh,32rem);gap:var(--jv-spacing-xs);padding:var(--jv-spacing-sm);overflow-y:auto;border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-md);background:var(--jv-color-surface);box-shadow:var(--jv-shadow-lg);z-index:30}.jv-topbar-menu-child{display:block;padding:var(--jv-spacing-sm) var(--jv-spacing-md);border-radius:var(--jv-radius-sm);text-align:left;white-space:nowrap}.jv-topbar-menu-actions{justify-content:flex-end;gap:var(--jv-spacing-sm);flex:0 0 auto}.theme-group{gap:var(--jv-spacing-xs)}.icon-button,.mobile-menu-button{display:inline-flex;align-items:center;justify-content:center;gap:var(--jv-spacing-xs);min-width:var(--jv-density-control-height);height:var(--jv-density-control-height);padding:0 var(--jv-spacing-sm);border-color:var(--jv-color-border);border-radius:999px;background:var(--jv-color-surface-muted);color:var(--jv-color-foreground)}.icon-button{cursor:pointer}.theme-pill{display:inline-flex;align-items:center;gap:var(--jv-spacing-xs);min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-sm);border-color:var(--jv-color-border);border-radius:999px;background:var(--jv-color-surface-muted);color:var(--jv-color-foreground);font-size:.8125rem}.theme-pill.is-active{border-color:var(--jv-color-primary);background:color-mix(in srgb,var(--jv-color-primary) 14%,var(--jv-color-surface))}.mobile-menu-button,.jv-topbar-menu-backdrop{display:none}@media(max-width:1100px){.jv-topbar-menu{gap:var(--jv-spacing-md);padding-inline:var(--jv-spacing-lg)}.jv-topbar-menu-link{max-width:12rem;padding-inline:var(--jv-spacing-xs)}}@media(max-width:1400px){.jv-topbar-menu-actions .theme-group{display:none}}@media(max-width:900px){.jv-topbar-menu-backdrop{display:block;position:fixed;inset:0;z-index:19;background:#0006}.jv-topbar-menu{position:relative;justify-content:space-between;min-height:4rem;padding:var(--jv-spacing-sm) var(--jv-spacing-md)}.mobile-menu-button{display:inline-grid;order:3}.jv-topbar-menu-nav{position:fixed;top:4rem;right:0;bottom:0;z-index:21;width:min(22rem,88vw);padding:var(--jv-spacing-lg);overflow-y:auto;border-left:1px solid var(--jv-color-border);background:var(--jv-color-surface);box-shadow:var(--jv-shadow-lg);transform:translate(100%);visibility:hidden;transition:transform .24s ease,visibility .24s}.jv-topbar-menu.is-mobile-open .jv-topbar-menu-nav{transform:translate(0);visibility:visible}.jv-topbar-menu-list{display:grid;align-items:stretch}.jv-topbar-menu-link{width:100%;justify-content:flex-start;padding-inline:var(--jv-spacing-md)}.jv-topbar-menu-dropdown{position:static;min-width:0;margin-left:var(--jv-spacing-md);box-shadow:none}.jv-topbar-menu-actions{margin-left:auto}}\n"] }]
|
|
23933
|
+
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], brandIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "brandIcon", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], mobileOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileOpen", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], currentTheme: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentTheme", required: false }] }], themeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "themeOptions", required: false }] }], actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: false }] }], showThemeSelector: [{ type: i0.Input, args: [{ isSignal: true, alias: "showThemeSelector", required: false }] }], menuClick: [{ type: i0.Output, args: ["menuClick"] }], mobileClose: [{ type: i0.Output, args: ["mobileClose"] }], themeChange: [{ type: i0.Output, args: ["themeChange"] }], actionClick: [{ type: i0.Output, args: ["actionClick"] }] } });
|
|
23934
|
+
|
|
23935
|
+
class JvDashboardShellComponent {
|
|
23936
|
+
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
23937
|
+
navigationMode = input('sidebar', ...(ngDevMode ? [{ debugName: "navigationMode" }] : /* istanbul ignore next */ []));
|
|
23938
|
+
sidebarSubtitle = input('', ...(ngDevMode ? [{ debugName: "sidebarSubtitle" }] : /* istanbul ignore next */ []));
|
|
23939
|
+
brandIcon = input('monitor', ...(ngDevMode ? [{ debugName: "brandIcon" }] : /* istanbul ignore next */ []));
|
|
23940
|
+
navItems = input([], ...(ngDevMode ? [{ debugName: "navItems" }] : /* istanbul ignore next */ []));
|
|
23941
|
+
sidebarCollapsed = input(false, ...(ngDevMode ? [{ debugName: "sidebarCollapsed" }] : /* istanbul ignore next */ []));
|
|
23942
|
+
mobileSidebarOpen = input(false, ...(ngDevMode ? [{ debugName: "mobileSidebarOpen" }] : /* istanbul ignore next */ []));
|
|
23943
|
+
topbarTitle = input('', ...(ngDevMode ? [{ debugName: "topbarTitle" }] : /* istanbul ignore next */ []));
|
|
23944
|
+
topbarSubtitle = input('', ...(ngDevMode ? [{ debugName: "topbarSubtitle" }] : /* istanbul ignore next */ []));
|
|
23467
23945
|
currentTheme = input('light', ...(ngDevMode ? [{ debugName: "currentTheme" }] : /* istanbul ignore next */ []));
|
|
23468
23946
|
themeOptions = input([], ...(ngDevMode ? [{ debugName: "themeOptions" }] : /* istanbul ignore next */ []));
|
|
23469
23947
|
topbarActions = input([], ...(ngDevMode ? [{ debugName: "topbarActions" }] : /* istanbul ignore next */ []));
|
|
@@ -23474,90 +23952,130 @@ class JvDashboardShellComponent {
|
|
|
23474
23952
|
themeChange = output();
|
|
23475
23953
|
topbarActionClick = output();
|
|
23476
23954
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JvDashboardShellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
23477
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.
|
|
23478
|
-
<div class="jv-dashboard-shell" [class.is-sidebar-collapsed]="sidebarCollapsed()">
|
|
23479
|
-
|
|
23480
|
-
|
|
23481
|
-
|
|
23482
|
-
|
|
23483
|
-
|
|
23484
|
-
|
|
23485
|
-
|
|
23486
|
-
|
|
23487
|
-
[themeOptions]="themeOptions()"
|
|
23488
|
-
[topbarActions]="topbarActions()"
|
|
23489
|
-
[showThemeSelector]="showThemeSelector()"
|
|
23490
|
-
(collapseToggle)="sidebarCollapseToggle.emit()"
|
|
23491
|
-
(mobileClose)="mobileClose.emit()"
|
|
23492
|
-
(themeChange)="themeChange.emit($event)"
|
|
23493
|
-
(actionClick)="topbarActionClick.emit($event)"
|
|
23494
|
-
/>
|
|
23495
|
-
|
|
23496
|
-
<div class="jv-dashboard-main">
|
|
23497
|
-
<jv-topbar
|
|
23498
|
-
[title]="topbarTitle()"
|
|
23499
|
-
[subtitle]="topbarSubtitle()"
|
|
23955
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: JvDashboardShellComponent, isStandalone: true, selector: "jv-dashboard-shell", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, navigationMode: { classPropertyName: "navigationMode", publicName: "navigationMode", isSignal: true, isRequired: false, transformFunction: null }, sidebarSubtitle: { classPropertyName: "sidebarSubtitle", publicName: "sidebarSubtitle", isSignal: true, isRequired: false, transformFunction: null }, brandIcon: { classPropertyName: "brandIcon", publicName: "brandIcon", isSignal: true, isRequired: false, transformFunction: null }, navItems: { classPropertyName: "navItems", publicName: "navItems", isSignal: true, isRequired: false, transformFunction: null }, sidebarCollapsed: { classPropertyName: "sidebarCollapsed", publicName: "sidebarCollapsed", isSignal: true, isRequired: false, transformFunction: null }, mobileSidebarOpen: { classPropertyName: "mobileSidebarOpen", publicName: "mobileSidebarOpen", isSignal: true, isRequired: false, transformFunction: null }, topbarTitle: { classPropertyName: "topbarTitle", publicName: "topbarTitle", isSignal: true, isRequired: false, transformFunction: null }, topbarSubtitle: { classPropertyName: "topbarSubtitle", publicName: "topbarSubtitle", isSignal: true, isRequired: false, transformFunction: null }, currentTheme: { classPropertyName: "currentTheme", publicName: "currentTheme", isSignal: true, isRequired: false, transformFunction: null }, themeOptions: { classPropertyName: "themeOptions", publicName: "themeOptions", isSignal: true, isRequired: false, transformFunction: null }, topbarActions: { classPropertyName: "topbarActions", publicName: "topbarActions", isSignal: true, isRequired: false, transformFunction: null }, showThemeSelector: { classPropertyName: "showThemeSelector", publicName: "showThemeSelector", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { menuClick: "menuClick", mobileClose: "mobileClose", sidebarCollapseToggle: "sidebarCollapseToggle", themeChange: "themeChange", topbarActionClick: "topbarActionClick" }, ngImport: i0, template: `
|
|
23956
|
+
<div class="jv-dashboard-shell" [class.is-sidebar-collapsed]="sidebarCollapsed()" [class.is-topbar-navigation]="navigationMode() === 'topbar'">
|
|
23957
|
+
@if (navigationMode() === 'sidebar') {
|
|
23958
|
+
<jv-sidebar
|
|
23959
|
+
[title]="title()"
|
|
23960
|
+
[subtitle]="sidebarSubtitle()"
|
|
23961
|
+
[brandIcon]="brandIcon()"
|
|
23962
|
+
[items]="navItems()"
|
|
23963
|
+
[collapsed]="sidebarCollapsed()"
|
|
23964
|
+
[mobileOpen]="mobileSidebarOpen()"
|
|
23500
23965
|
[currentTheme]="currentTheme()"
|
|
23501
23966
|
[themeOptions]="themeOptions()"
|
|
23502
|
-
[
|
|
23967
|
+
[topbarActions]="topbarActions()"
|
|
23503
23968
|
[showThemeSelector]="showThemeSelector()"
|
|
23504
|
-
(
|
|
23969
|
+
(collapseToggle)="sidebarCollapseToggle.emit()"
|
|
23970
|
+
(mobileClose)="mobileClose.emit()"
|
|
23505
23971
|
(themeChange)="themeChange.emit($event)"
|
|
23506
23972
|
(actionClick)="topbarActionClick.emit($event)"
|
|
23507
|
-
|
|
23508
|
-
|
|
23509
|
-
|
|
23973
|
+
/>
|
|
23974
|
+
}
|
|
23975
|
+
|
|
23976
|
+
<div class="jv-dashboard-main">
|
|
23977
|
+
@if (navigationMode() === 'topbar') {
|
|
23978
|
+
<jv-topbar-menu
|
|
23979
|
+
[title]="title()"
|
|
23980
|
+
[subtitle]="sidebarSubtitle()"
|
|
23981
|
+
[brandIcon]="brandIcon()"
|
|
23982
|
+
[items]="navItems()"
|
|
23983
|
+
[mobileOpen]="mobileSidebarOpen()"
|
|
23984
|
+
[currentTheme]="currentTheme()"
|
|
23985
|
+
[themeOptions]="themeOptions()"
|
|
23986
|
+
[actions]="topbarActions()"
|
|
23987
|
+
[showThemeSelector]="showThemeSelector()"
|
|
23988
|
+
(menuClick)="menuClick.emit()"
|
|
23989
|
+
(mobileClose)="mobileClose.emit()"
|
|
23990
|
+
(themeChange)="themeChange.emit($event)"
|
|
23991
|
+
(actionClick)="topbarActionClick.emit($event)"
|
|
23992
|
+
/>
|
|
23993
|
+
} @else {
|
|
23994
|
+
<jv-topbar
|
|
23995
|
+
[title]="topbarTitle()"
|
|
23996
|
+
[subtitle]="topbarSubtitle()"
|
|
23997
|
+
[currentTheme]="currentTheme()"
|
|
23998
|
+
[themeOptions]="themeOptions()"
|
|
23999
|
+
[actions]="topbarActions()"
|
|
24000
|
+
[showThemeSelector]="showThemeSelector()"
|
|
24001
|
+
(menuClick)="menuClick.emit()"
|
|
24002
|
+
(themeChange)="themeChange.emit($event)"
|
|
24003
|
+
(actionClick)="topbarActionClick.emit($event)"
|
|
24004
|
+
>
|
|
24005
|
+
<ng-content select="[topbar-actions]" topbar-actions></ng-content>
|
|
24006
|
+
</jv-topbar>
|
|
24007
|
+
}
|
|
23510
24008
|
|
|
23511
24009
|
<main class="jv-dashboard-content">
|
|
23512
24010
|
<ng-content></ng-content>
|
|
23513
24011
|
</main>
|
|
23514
24012
|
</div>
|
|
23515
24013
|
</div>
|
|
23516
|
-
`, isInline: true, styles: [":host{display:block;height:100dvh;overflow:hidden}.jv-dashboard-shell{display:grid;height:100%;grid-template-columns:auto 1fr;background:var(--jv-color-background);overflow:hidden}.jv-dashboard-main{display:grid;grid-template-rows:auto 1fr;min-width:0;min-height:0;overflow:hidden}.jv-dashboard-content{overflow:auto;min-width:0;min-height:0;padding:var(--jv-spacing-xl);scrollbar-width:none;-ms-overflow-style:none}.jv-dashboard-content::-webkit-scrollbar{width:0;height:0;display:none}@media(max-width:900px){.jv-dashboard-shell{grid-template-columns:1fr}.jv-dashboard-content{padding:var(--jv-spacing-lg)}}\n"], dependencies: [{ kind: "component", type: JvSidebarComponent, selector: "jv-sidebar", inputs: ["title", "subtitle", "brandIcon", "items", "collapsed", "mobileOpen", "ariaLabel", "currentTheme", "themeOptions", "topbarActions", "showThemeSelector"], outputs: ["collapseToggle", "mobileClose", "themeChange", "actionClick"] }, { kind: "component", type: JvTopbarComponent, selector: "jv-topbar", inputs: ["title", "subtitle", "currentTheme", "themeOptions", "actions", "showThemeSelector"], outputs: ["menuClick", "themeChange", "actionClick"] }] });
|
|
24014
|
+
`, isInline: true, styles: [":host{display:block;height:100dvh;overflow:hidden}.jv-dashboard-shell{display:grid;height:100%;grid-template-columns:auto 1fr;background:var(--jv-color-background);overflow:hidden}.jv-dashboard-shell.is-topbar-navigation{grid-template-columns:1fr}.jv-dashboard-main{display:grid;grid-template-rows:auto 1fr;min-width:0;min-height:0;overflow:hidden}.jv-dashboard-content{overflow:auto;min-width:0;min-height:0;padding:var(--jv-spacing-xl);scrollbar-width:none;-ms-overflow-style:none}.jv-dashboard-content::-webkit-scrollbar{width:0;height:0;display:none}@media(max-width:900px){.jv-dashboard-shell{grid-template-columns:1fr}.jv-dashboard-content{padding:var(--jv-spacing-lg)}}\n"], dependencies: [{ kind: "component", type: JvSidebarComponent, selector: "jv-sidebar", inputs: ["title", "subtitle", "brandIcon", "items", "collapsed", "mobileOpen", "ariaLabel", "currentTheme", "themeOptions", "topbarActions", "showThemeSelector"], outputs: ["collapseToggle", "mobileClose", "themeChange", "actionClick"] }, { kind: "component", type: JvTopbarComponent, selector: "jv-topbar", inputs: ["title", "subtitle", "currentTheme", "themeOptions", "actions", "showThemeSelector"], outputs: ["menuClick", "themeChange", "actionClick"] }, { kind: "component", type: JvTopbarMenuComponent, selector: "jv-topbar-menu", inputs: ["title", "subtitle", "brandIcon", "items", "mobileOpen", "ariaLabel", "currentTheme", "themeOptions", "actions", "showThemeSelector"], outputs: ["menuClick", "mobileClose", "themeChange", "actionClick"] }] });
|
|
23517
24015
|
}
|
|
23518
24016
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JvDashboardShellComponent, decorators: [{
|
|
23519
24017
|
type: Component,
|
|
23520
|
-
args: [{ selector: 'jv-dashboard-shell', standalone: true, imports: [JvSidebarComponent, JvTopbarComponent], template: `
|
|
23521
|
-
<div class="jv-dashboard-shell" [class.is-sidebar-collapsed]="sidebarCollapsed()">
|
|
23522
|
-
|
|
23523
|
-
|
|
23524
|
-
|
|
23525
|
-
|
|
23526
|
-
|
|
23527
|
-
|
|
23528
|
-
|
|
23529
|
-
|
|
23530
|
-
[themeOptions]="themeOptions()"
|
|
23531
|
-
[topbarActions]="topbarActions()"
|
|
23532
|
-
[showThemeSelector]="showThemeSelector()"
|
|
23533
|
-
(collapseToggle)="sidebarCollapseToggle.emit()"
|
|
23534
|
-
(mobileClose)="mobileClose.emit()"
|
|
23535
|
-
(themeChange)="themeChange.emit($event)"
|
|
23536
|
-
(actionClick)="topbarActionClick.emit($event)"
|
|
23537
|
-
/>
|
|
23538
|
-
|
|
23539
|
-
<div class="jv-dashboard-main">
|
|
23540
|
-
<jv-topbar
|
|
23541
|
-
[title]="topbarTitle()"
|
|
23542
|
-
[subtitle]="topbarSubtitle()"
|
|
24018
|
+
args: [{ selector: 'jv-dashboard-shell', standalone: true, imports: [JvSidebarComponent, JvTopbarComponent, JvTopbarMenuComponent], template: `
|
|
24019
|
+
<div class="jv-dashboard-shell" [class.is-sidebar-collapsed]="sidebarCollapsed()" [class.is-topbar-navigation]="navigationMode() === 'topbar'">
|
|
24020
|
+
@if (navigationMode() === 'sidebar') {
|
|
24021
|
+
<jv-sidebar
|
|
24022
|
+
[title]="title()"
|
|
24023
|
+
[subtitle]="sidebarSubtitle()"
|
|
24024
|
+
[brandIcon]="brandIcon()"
|
|
24025
|
+
[items]="navItems()"
|
|
24026
|
+
[collapsed]="sidebarCollapsed()"
|
|
24027
|
+
[mobileOpen]="mobileSidebarOpen()"
|
|
23543
24028
|
[currentTheme]="currentTheme()"
|
|
23544
24029
|
[themeOptions]="themeOptions()"
|
|
23545
|
-
[
|
|
24030
|
+
[topbarActions]="topbarActions()"
|
|
23546
24031
|
[showThemeSelector]="showThemeSelector()"
|
|
23547
|
-
(
|
|
24032
|
+
(collapseToggle)="sidebarCollapseToggle.emit()"
|
|
24033
|
+
(mobileClose)="mobileClose.emit()"
|
|
23548
24034
|
(themeChange)="themeChange.emit($event)"
|
|
23549
24035
|
(actionClick)="topbarActionClick.emit($event)"
|
|
23550
|
-
|
|
23551
|
-
|
|
23552
|
-
|
|
24036
|
+
/>
|
|
24037
|
+
}
|
|
24038
|
+
|
|
24039
|
+
<div class="jv-dashboard-main">
|
|
24040
|
+
@if (navigationMode() === 'topbar') {
|
|
24041
|
+
<jv-topbar-menu
|
|
24042
|
+
[title]="title()"
|
|
24043
|
+
[subtitle]="sidebarSubtitle()"
|
|
24044
|
+
[brandIcon]="brandIcon()"
|
|
24045
|
+
[items]="navItems()"
|
|
24046
|
+
[mobileOpen]="mobileSidebarOpen()"
|
|
24047
|
+
[currentTheme]="currentTheme()"
|
|
24048
|
+
[themeOptions]="themeOptions()"
|
|
24049
|
+
[actions]="topbarActions()"
|
|
24050
|
+
[showThemeSelector]="showThemeSelector()"
|
|
24051
|
+
(menuClick)="menuClick.emit()"
|
|
24052
|
+
(mobileClose)="mobileClose.emit()"
|
|
24053
|
+
(themeChange)="themeChange.emit($event)"
|
|
24054
|
+
(actionClick)="topbarActionClick.emit($event)"
|
|
24055
|
+
/>
|
|
24056
|
+
} @else {
|
|
24057
|
+
<jv-topbar
|
|
24058
|
+
[title]="topbarTitle()"
|
|
24059
|
+
[subtitle]="topbarSubtitle()"
|
|
24060
|
+
[currentTheme]="currentTheme()"
|
|
24061
|
+
[themeOptions]="themeOptions()"
|
|
24062
|
+
[actions]="topbarActions()"
|
|
24063
|
+
[showThemeSelector]="showThemeSelector()"
|
|
24064
|
+
(menuClick)="menuClick.emit()"
|
|
24065
|
+
(themeChange)="themeChange.emit($event)"
|
|
24066
|
+
(actionClick)="topbarActionClick.emit($event)"
|
|
24067
|
+
>
|
|
24068
|
+
<ng-content select="[topbar-actions]" topbar-actions></ng-content>
|
|
24069
|
+
</jv-topbar>
|
|
24070
|
+
}
|
|
23553
24071
|
|
|
23554
24072
|
<main class="jv-dashboard-content">
|
|
23555
24073
|
<ng-content></ng-content>
|
|
23556
24074
|
</main>
|
|
23557
24075
|
</div>
|
|
23558
24076
|
</div>
|
|
23559
|
-
`, styles: [":host{display:block;height:100dvh;overflow:hidden}.jv-dashboard-shell{display:grid;height:100%;grid-template-columns:auto 1fr;background:var(--jv-color-background);overflow:hidden}.jv-dashboard-main{display:grid;grid-template-rows:auto 1fr;min-width:0;min-height:0;overflow:hidden}.jv-dashboard-content{overflow:auto;min-width:0;min-height:0;padding:var(--jv-spacing-xl);scrollbar-width:none;-ms-overflow-style:none}.jv-dashboard-content::-webkit-scrollbar{width:0;height:0;display:none}@media(max-width:900px){.jv-dashboard-shell{grid-template-columns:1fr}.jv-dashboard-content{padding:var(--jv-spacing-lg)}}\n"] }]
|
|
23560
|
-
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], sidebarSubtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarSubtitle", required: false }] }], brandIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "brandIcon", required: false }] }], navItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "navItems", required: false }] }], sidebarCollapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarCollapsed", required: false }] }], mobileSidebarOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileSidebarOpen", required: false }] }], topbarTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "topbarTitle", required: false }] }], topbarSubtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "topbarSubtitle", required: false }] }], currentTheme: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentTheme", required: false }] }], themeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "themeOptions", required: false }] }], topbarActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "topbarActions", required: false }] }], showThemeSelector: [{ type: i0.Input, args: [{ isSignal: true, alias: "showThemeSelector", required: false }] }], menuClick: [{ type: i0.Output, args: ["menuClick"] }], mobileClose: [{ type: i0.Output, args: ["mobileClose"] }], sidebarCollapseToggle: [{ type: i0.Output, args: ["sidebarCollapseToggle"] }], themeChange: [{ type: i0.Output, args: ["themeChange"] }], topbarActionClick: [{ type: i0.Output, args: ["topbarActionClick"] }] } });
|
|
24077
|
+
`, styles: [":host{display:block;height:100dvh;overflow:hidden}.jv-dashboard-shell{display:grid;height:100%;grid-template-columns:auto 1fr;background:var(--jv-color-background);overflow:hidden}.jv-dashboard-shell.is-topbar-navigation{grid-template-columns:1fr}.jv-dashboard-main{display:grid;grid-template-rows:auto 1fr;min-width:0;min-height:0;overflow:hidden}.jv-dashboard-content{overflow:auto;min-width:0;min-height:0;padding:var(--jv-spacing-xl);scrollbar-width:none;-ms-overflow-style:none}.jv-dashboard-content::-webkit-scrollbar{width:0;height:0;display:none}@media(max-width:900px){.jv-dashboard-shell{grid-template-columns:1fr}.jv-dashboard-content{padding:var(--jv-spacing-lg)}}\n"] }]
|
|
24078
|
+
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], navigationMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "navigationMode", required: false }] }], sidebarSubtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarSubtitle", required: false }] }], brandIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "brandIcon", required: false }] }], navItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "navItems", required: false }] }], sidebarCollapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarCollapsed", required: false }] }], mobileSidebarOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileSidebarOpen", required: false }] }], topbarTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "topbarTitle", required: false }] }], topbarSubtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "topbarSubtitle", required: false }] }], currentTheme: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentTheme", required: false }] }], themeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "themeOptions", required: false }] }], topbarActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "topbarActions", required: false }] }], showThemeSelector: [{ type: i0.Input, args: [{ isSignal: true, alias: "showThemeSelector", required: false }] }], menuClick: [{ type: i0.Output, args: ["menuClick"] }], mobileClose: [{ type: i0.Output, args: ["mobileClose"] }], sidebarCollapseToggle: [{ type: i0.Output, args: ["sidebarCollapseToggle"] }], themeChange: [{ type: i0.Output, args: ["themeChange"] }], topbarActionClick: [{ type: i0.Output, args: ["topbarActionClick"] }] } });
|
|
23561
24079
|
|
|
23562
24080
|
class JvPageComponent {
|
|
23563
24081
|
eyebrow = input('', ...(ngDevMode ? [{ debugName: "eyebrow" }] : /* istanbul ignore next */ []));
|
|
@@ -24076,209 +24594,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
24076
24594
|
[class.jv-tab-panel--fade]="effectiveTransition() === 'fade'"
|
|
24077
24595
|
[class.jv-tab-panel--slide-left]="effectiveTransition() === 'slide' && slideDirection() === 'left'"
|
|
24078
24596
|
[class.jv-tab-panel--slide-right]="effectiveTransition() === 'slide' && slideDirection() === 'right'"
|
|
24079
|
-
[id]="panelId(activeId)"
|
|
24080
|
-
role="tabpanel"
|
|
24081
|
-
[attr.aria-labelledby]="tabButtonId(activeId)"
|
|
24082
|
-
tabindex="0"
|
|
24083
|
-
>
|
|
24084
|
-
<ng-container [ngTemplateOutlet]="panelTemplate(activeId) ?? null" />
|
|
24085
|
-
</div>
|
|
24086
|
-
}
|
|
24087
|
-
}
|
|
24088
|
-
</div>
|
|
24089
|
-
</div>
|
|
24090
|
-
`, styles: [".jv-tabs{display:grid;gap:var(--jv-spacing-md)}.jv-tabs-header{display:flex;align-items:center;gap:var(--jv-spacing-sm);min-width:0}.jv-tabs-scroll{flex:1;min-width:0;display:flex;align-items:stretch;gap:var(--jv-spacing-xs);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none;border-bottom:1px solid var(--jv-color-border);scroll-behavior:smooth}.jv-tabs-scroll::-webkit-scrollbar{display:none}.jv-tab{position:relative;display:inline-flex;align-items:center;gap:var(--jv-spacing-xs);flex:0 0 auto;min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-md);border:0;border-bottom:2px solid transparent;background:transparent;color:var(--jv-color-foreground-muted);font:inherit;font-weight:600;white-space:nowrap;cursor:pointer;transition:color .16s ease,border-color .16s ease,background-color .16s ease}.jv-tab:hover:not(:disabled){color:var(--jv-color-foreground);background:color-mix(in srgb,var(--jv-color-primary) 6%,transparent)}.jv-tab:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:-2px;border-radius:var(--jv-radius-sm) var(--jv-radius-sm) 0 0}.jv-tab--active{color:var(--jv-color-primary);border-bottom-color:var(--jv-color-primary)}.jv-tab--disabled{opacity:.5;cursor:not-allowed}.jv-tabs-controls{display:inline-flex;align-items:center;gap:var(--jv-spacing-xs)}.jv-tabs-scroll-button{display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-md);background:var(--jv-color-surface);color:var(--jv-color-foreground);cursor:pointer}.jv-tabs-scroll-button:disabled{opacity:.4;cursor:default}.jv-tab-panel{outline:none}.jv-tab-panel--hidden{display:none}.jv-tab-panel--fade{transition:opacity .18s ease}.jv-tab-panel--hidden.jv-tab-panel--fade{display:block;opacity:0;pointer-events:none}.jv-tab-panel--slide-left,.jv-tab-panel--slide-right{transition:opacity .18s ease,transform .18s ease}.jv-tab-panel--hidden.jv-tab-panel--slide-left{display:block;opacity:0;transform:translate(20px);pointer-events:none}.jv-tab-panel--hidden.jv-tab-panel--slide-right{display:block;opacity:0;transform:translate(-20px);pointer-events:none}.jv-tab-panel--exit.jv-tab-panel--fade{position:absolute;opacity:0;pointer-events:none}.jv-tab-panel--exit.jv-tab-panel--slide-left{position:absolute;opacity:0;transform:translate(-20px);pointer-events:none}.jv-tab-panel--exit.jv-tab-panel--slide-right{position:absolute;opacity:0;transform:translate(20px);pointer-events:none}.jv-tab-panel--entering{animation:jv-tab-enter .18s ease forwards}.jv-tab-panel--entering.jv-tab-panel--slide-left{animation-name:jv-tab-slide-from-right}.jv-tab-panel--entering.jv-tab-panel--slide-right{animation-name:jv-tab-slide-from-left}@keyframes jv-tab-enter{0%{opacity:0}to{opacity:1}}@keyframes jv-tab-slide-from-right{0%{opacity:0;transform:translate(20px)}to{opacity:1;transform:translate(0)}}@keyframes jv-tab-slide-from-left{0%{opacity:0;transform:translate(-20px)}to{opacity:1;transform:translate(0)}}@media(prefers-reduced-motion:reduce){.jv-tab-panel--fade,.jv-tab-panel--slide-left,.jv-tab-panel--slide-right,.jv-tab-panel--entering{transition:none;animation:none}.jv-tab-panel--hidden.jv-tab-panel--fade,.jv-tab-panel--hidden.jv-tab-panel--slide-left,.jv-tab-panel--hidden.jv-tab-panel--slide-right{opacity:0}}\n"] }]
|
|
24091
|
-
}], ctorParameters: () => [], propDecorators: { panelTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => JvTabPanelDirective), { isSignal: true }] }], tabListRef: [{ type: i0.ViewChild, args: ['tabList', { isSignal: true }] }], tabs: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabs", required: false }] }], activeTabId: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTabId", required: false }] }], keepMounted: [{ type: i0.Input, args: [{ isSignal: true, alias: "keepMounted", required: false }] }], transition: [{ type: i0.Input, args: [{ isSignal: true, alias: "transition", required: false }] }], activeTabChange: [{ type: i0.Output, args: ["activeTabChange"] }], handleWindowResize: [{
|
|
24092
|
-
type: HostListener,
|
|
24093
|
-
args: ['window:resize']
|
|
24094
|
-
}] } });
|
|
24095
|
-
|
|
24096
|
-
let tooltipSequence = 0;
|
|
24097
|
-
class JvTooltipDirective {
|
|
24098
|
-
document = inject(DOCUMENT);
|
|
24099
|
-
renderer = inject(Renderer2);
|
|
24100
|
-
hostRef = inject((ElementRef));
|
|
24101
|
-
tooltipElement = null;
|
|
24102
|
-
showTimeout = null;
|
|
24103
|
-
hideTimeout = null;
|
|
24104
|
-
tooltipId = `jv-tooltip-${++tooltipSequence}`;
|
|
24105
|
-
originalDescribedBy = null;
|
|
24106
|
-
text = input.required({ ...(ngDevMode ? { debugName: "text" } : /* istanbul ignore next */ {}), alias: 'jvTooltip' });
|
|
24107
|
-
position = input('top', { ...(ngDevMode ? { debugName: "position" } : /* istanbul ignore next */ {}), alias: 'jvTooltipPosition' });
|
|
24108
|
-
show() {
|
|
24109
|
-
if (!this.text().trim()) {
|
|
24110
|
-
return;
|
|
24111
|
-
}
|
|
24112
|
-
this.clearHideTimeout();
|
|
24113
|
-
if (this.tooltipElement) {
|
|
24114
|
-
return;
|
|
24115
|
-
}
|
|
24116
|
-
this.showTimeout = setTimeout(() => {
|
|
24117
|
-
this.renderTooltip();
|
|
24118
|
-
this.positionTooltip();
|
|
24119
|
-
this.attachTooltipDescription();
|
|
24120
|
-
}, 120);
|
|
24121
|
-
}
|
|
24122
|
-
hide() {
|
|
24123
|
-
this.clearShowTimeout();
|
|
24124
|
-
if (!this.tooltipElement) {
|
|
24125
|
-
return;
|
|
24126
|
-
}
|
|
24127
|
-
this.hideTimeout = setTimeout(() => this.destroyTooltip(), 80);
|
|
24128
|
-
}
|
|
24129
|
-
handleDocumentKeydown(event) {
|
|
24130
|
-
if (event.key === 'Escape') {
|
|
24131
|
-
this.destroyTooltip();
|
|
24132
|
-
}
|
|
24133
|
-
}
|
|
24134
|
-
handleViewportChange() {
|
|
24135
|
-
if (this.tooltipElement) {
|
|
24136
|
-
this.positionTooltip();
|
|
24137
|
-
}
|
|
24138
|
-
}
|
|
24139
|
-
ngOnDestroy() {
|
|
24140
|
-
this.clearShowTimeout();
|
|
24141
|
-
this.clearHideTimeout();
|
|
24142
|
-
this.destroyTooltip();
|
|
24143
|
-
}
|
|
24144
|
-
renderTooltip() {
|
|
24145
|
-
if (this.tooltipElement) {
|
|
24146
|
-
return;
|
|
24147
|
-
}
|
|
24148
|
-
const tooltip = this.renderer.createElement('div');
|
|
24149
|
-
tooltip.textContent = this.text();
|
|
24150
|
-
this.renderer.setAttribute(tooltip, 'id', this.tooltipId);
|
|
24151
|
-
this.renderer.setAttribute(tooltip, 'role', 'tooltip');
|
|
24152
|
-
this.renderer.setStyle(tooltip, 'position', 'fixed');
|
|
24153
|
-
this.renderer.setStyle(tooltip, 'z-index', '1400');
|
|
24154
|
-
this.renderer.setStyle(tooltip, 'max-width', '18rem');
|
|
24155
|
-
this.renderer.setStyle(tooltip, 'padding', '0.5rem 0.75rem');
|
|
24156
|
-
this.renderer.setStyle(tooltip, 'border-radius', '0.5rem');
|
|
24157
|
-
this.renderer.setStyle(tooltip, 'background', 'rgb(15 23 42)');
|
|
24158
|
-
this.renderer.setStyle(tooltip, 'color', '#ffffff');
|
|
24159
|
-
this.renderer.setStyle(tooltip, 'font-size', '0.8125rem');
|
|
24160
|
-
this.renderer.setStyle(tooltip, 'line-height', '1.4');
|
|
24161
|
-
this.renderer.setStyle(tooltip, 'box-shadow', 'var(--jv-shadow-md)');
|
|
24162
|
-
this.renderer.setStyle(tooltip, 'pointer-events', 'none');
|
|
24163
|
-
this.renderer.setStyle(tooltip, 'opacity', '0');
|
|
24164
|
-
this.renderer.setStyle(tooltip, 'transition', 'opacity 120ms ease');
|
|
24165
|
-
this.renderer.appendChild(this.document.body, tooltip);
|
|
24166
|
-
this.tooltipElement = tooltip;
|
|
24167
|
-
requestAnimationFrame(() => {
|
|
24168
|
-
if (this.tooltipElement) {
|
|
24169
|
-
this.renderer.setStyle(this.tooltipElement, 'opacity', '1');
|
|
24170
|
-
}
|
|
24171
|
-
});
|
|
24172
|
-
}
|
|
24173
|
-
positionTooltip() {
|
|
24174
|
-
const tooltip = this.tooltipElement;
|
|
24175
|
-
if (!tooltip) {
|
|
24176
|
-
return;
|
|
24177
|
-
}
|
|
24178
|
-
const hostRect = this.anchorElement().getBoundingClientRect();
|
|
24179
|
-
const tooltipRect = tooltip.getBoundingClientRect();
|
|
24180
|
-
const gap = 8;
|
|
24181
|
-
let top = hostRect.top - tooltipRect.height - gap;
|
|
24182
|
-
let left = hostRect.left + hostRect.width / 2 - tooltipRect.width / 2;
|
|
24183
|
-
switch (this.position()) {
|
|
24184
|
-
case 'right':
|
|
24185
|
-
top = hostRect.top + hostRect.height / 2 - tooltipRect.height / 2;
|
|
24186
|
-
left = hostRect.right + gap;
|
|
24187
|
-
break;
|
|
24188
|
-
case 'bottom':
|
|
24189
|
-
top = hostRect.bottom + gap;
|
|
24190
|
-
left = hostRect.left + hostRect.width / 2 - tooltipRect.width / 2;
|
|
24191
|
-
break;
|
|
24192
|
-
case 'left':
|
|
24193
|
-
top = hostRect.top + hostRect.height / 2 - tooltipRect.height / 2;
|
|
24194
|
-
left = hostRect.left - tooltipRect.width - gap;
|
|
24195
|
-
break;
|
|
24196
|
-
}
|
|
24197
|
-
this.renderer.setStyle(tooltip, 'top', `${Math.round(top)}px`);
|
|
24198
|
-
this.renderer.setStyle(tooltip, 'left', `${Math.round(left)}px`);
|
|
24199
|
-
}
|
|
24200
|
-
destroyTooltip() {
|
|
24201
|
-
this.clearHideTimeout();
|
|
24202
|
-
this.clearShowTimeout();
|
|
24203
|
-
if (!this.tooltipElement) {
|
|
24204
|
-
return;
|
|
24205
|
-
}
|
|
24206
|
-
this.restoreTooltipDescription();
|
|
24207
|
-
this.renderer.removeChild(this.document.body, this.tooltipElement);
|
|
24208
|
-
this.tooltipElement = null;
|
|
24209
|
-
}
|
|
24210
|
-
attachTooltipDescription() {
|
|
24211
|
-
const anchor = this.anchorElement();
|
|
24212
|
-
this.originalDescribedBy ??= anchor.getAttribute('aria-describedby');
|
|
24213
|
-
const describedBy = [this.originalDescribedBy, this.tooltipId]
|
|
24214
|
-
.filter((value) => !!value)
|
|
24215
|
-
.join(' ')
|
|
24216
|
-
.trim();
|
|
24217
|
-
this.renderer.setAttribute(anchor, 'aria-describedby', describedBy);
|
|
24218
|
-
}
|
|
24219
|
-
restoreTooltipDescription() {
|
|
24220
|
-
const anchor = this.anchorElement();
|
|
24221
|
-
if (this.originalDescribedBy) {
|
|
24222
|
-
this.renderer.setAttribute(anchor, 'aria-describedby', this.originalDescribedBy);
|
|
24223
|
-
}
|
|
24224
|
-
else {
|
|
24225
|
-
this.renderer.removeAttribute(anchor, 'aria-describedby');
|
|
24226
|
-
}
|
|
24227
|
-
this.originalDescribedBy = null;
|
|
24228
|
-
}
|
|
24229
|
-
anchorElement() {
|
|
24230
|
-
const host = this.hostRef.nativeElement;
|
|
24231
|
-
if (isInteractiveElement(host)) {
|
|
24232
|
-
return host;
|
|
24233
|
-
}
|
|
24234
|
-
return host.querySelector('button, a, input, select, textarea, [tabindex]:not([tabindex="-1"])') ?? host;
|
|
24235
|
-
}
|
|
24236
|
-
clearShowTimeout() {
|
|
24237
|
-
if (this.showTimeout) {
|
|
24238
|
-
clearTimeout(this.showTimeout);
|
|
24239
|
-
this.showTimeout = null;
|
|
24240
|
-
}
|
|
24241
|
-
}
|
|
24242
|
-
clearHideTimeout() {
|
|
24243
|
-
if (this.hideTimeout) {
|
|
24244
|
-
clearTimeout(this.hideTimeout);
|
|
24245
|
-
this.hideTimeout = null;
|
|
24597
|
+
[id]="panelId(activeId)"
|
|
24598
|
+
role="tabpanel"
|
|
24599
|
+
[attr.aria-labelledby]="tabButtonId(activeId)"
|
|
24600
|
+
tabindex="0"
|
|
24601
|
+
>
|
|
24602
|
+
<ng-container [ngTemplateOutlet]="panelTemplate(activeId) ?? null" />
|
|
24603
|
+
</div>
|
|
24604
|
+
}
|
|
24246
24605
|
}
|
|
24247
|
-
|
|
24248
|
-
|
|
24249
|
-
|
|
24250
|
-
}
|
|
24251
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JvTooltipDirective, decorators: [{
|
|
24252
|
-
type: Directive,
|
|
24253
|
-
args: [{
|
|
24254
|
-
selector: '[jvTooltip]',
|
|
24255
|
-
standalone: true,
|
|
24256
|
-
}]
|
|
24257
|
-
}], propDecorators: { text: [{ type: i0.Input, args: [{ isSignal: true, alias: "jvTooltip", required: true }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "jvTooltipPosition", required: false }] }], show: [{
|
|
24258
|
-
type: HostListener,
|
|
24259
|
-
args: ['mouseenter']
|
|
24260
|
-
}, {
|
|
24261
|
-
type: HostListener,
|
|
24262
|
-
args: ['focusin']
|
|
24263
|
-
}], hide: [{
|
|
24264
|
-
type: HostListener,
|
|
24265
|
-
args: ['mouseleave']
|
|
24266
|
-
}, {
|
|
24267
|
-
type: HostListener,
|
|
24268
|
-
args: ['blur']
|
|
24269
|
-
}], handleDocumentKeydown: [{
|
|
24270
|
-
type: HostListener,
|
|
24271
|
-
args: ['document:keydown', ['$event']]
|
|
24272
|
-
}], handleViewportChange: [{
|
|
24273
|
-
type: HostListener,
|
|
24274
|
-
args: ['window:scroll']
|
|
24275
|
-
}, {
|
|
24606
|
+
</div>
|
|
24607
|
+
</div>
|
|
24608
|
+
`, styles: [".jv-tabs{display:grid;gap:var(--jv-spacing-md)}.jv-tabs-header{display:flex;align-items:center;gap:var(--jv-spacing-sm);min-width:0}.jv-tabs-scroll{flex:1;min-width:0;display:flex;align-items:stretch;gap:var(--jv-spacing-xs);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none;border-bottom:1px solid var(--jv-color-border);scroll-behavior:smooth}.jv-tabs-scroll::-webkit-scrollbar{display:none}.jv-tab{position:relative;display:inline-flex;align-items:center;gap:var(--jv-spacing-xs);flex:0 0 auto;min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-md);border:0;border-bottom:2px solid transparent;background:transparent;color:var(--jv-color-foreground-muted);font:inherit;font-weight:600;white-space:nowrap;cursor:pointer;transition:color .16s ease,border-color .16s ease,background-color .16s ease}.jv-tab:hover:not(:disabled){color:var(--jv-color-foreground);background:color-mix(in srgb,var(--jv-color-primary) 6%,transparent)}.jv-tab:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:-2px;border-radius:var(--jv-radius-sm) var(--jv-radius-sm) 0 0}.jv-tab--active{color:var(--jv-color-primary);border-bottom-color:var(--jv-color-primary)}.jv-tab--disabled{opacity:.5;cursor:not-allowed}.jv-tabs-controls{display:inline-flex;align-items:center;gap:var(--jv-spacing-xs)}.jv-tabs-scroll-button{display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-md);background:var(--jv-color-surface);color:var(--jv-color-foreground);cursor:pointer}.jv-tabs-scroll-button:disabled{opacity:.4;cursor:default}.jv-tab-panel{outline:none}.jv-tab-panel--hidden{display:none}.jv-tab-panel--fade{transition:opacity .18s ease}.jv-tab-panel--hidden.jv-tab-panel--fade{display:block;opacity:0;pointer-events:none}.jv-tab-panel--slide-left,.jv-tab-panel--slide-right{transition:opacity .18s ease,transform .18s ease}.jv-tab-panel--hidden.jv-tab-panel--slide-left{display:block;opacity:0;transform:translate(20px);pointer-events:none}.jv-tab-panel--hidden.jv-tab-panel--slide-right{display:block;opacity:0;transform:translate(-20px);pointer-events:none}.jv-tab-panel--exit.jv-tab-panel--fade{position:absolute;opacity:0;pointer-events:none}.jv-tab-panel--exit.jv-tab-panel--slide-left{position:absolute;opacity:0;transform:translate(-20px);pointer-events:none}.jv-tab-panel--exit.jv-tab-panel--slide-right{position:absolute;opacity:0;transform:translate(20px);pointer-events:none}.jv-tab-panel--entering{animation:jv-tab-enter .18s ease forwards}.jv-tab-panel--entering.jv-tab-panel--slide-left{animation-name:jv-tab-slide-from-right}.jv-tab-panel--entering.jv-tab-panel--slide-right{animation-name:jv-tab-slide-from-left}@keyframes jv-tab-enter{0%{opacity:0}to{opacity:1}}@keyframes jv-tab-slide-from-right{0%{opacity:0;transform:translate(20px)}to{opacity:1;transform:translate(0)}}@keyframes jv-tab-slide-from-left{0%{opacity:0;transform:translate(-20px)}to{opacity:1;transform:translate(0)}}@media(prefers-reduced-motion:reduce){.jv-tab-panel--fade,.jv-tab-panel--slide-left,.jv-tab-panel--slide-right,.jv-tab-panel--entering{transition:none;animation:none}.jv-tab-panel--hidden.jv-tab-panel--fade,.jv-tab-panel--hidden.jv-tab-panel--slide-left,.jv-tab-panel--hidden.jv-tab-panel--slide-right{opacity:0}}\n"] }]
|
|
24609
|
+
}], ctorParameters: () => [], propDecorators: { panelTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => JvTabPanelDirective), { isSignal: true }] }], tabListRef: [{ type: i0.ViewChild, args: ['tabList', { isSignal: true }] }], tabs: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabs", required: false }] }], activeTabId: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTabId", required: false }] }], keepMounted: [{ type: i0.Input, args: [{ isSignal: true, alias: "keepMounted", required: false }] }], transition: [{ type: i0.Input, args: [{ isSignal: true, alias: "transition", required: false }] }], activeTabChange: [{ type: i0.Output, args: ["activeTabChange"] }], handleWindowResize: [{
|
|
24276
24610
|
type: HostListener,
|
|
24277
24611
|
args: ['window:resize']
|
|
24278
24612
|
}] } });
|
|
24279
|
-
function isInteractiveElement(element) {
|
|
24280
|
-
return ['BUTTON', 'A', 'INPUT', 'SELECT', 'TEXTAREA'].includes(element.tagName) || element.tabIndex >= 0;
|
|
24281
|
-
}
|
|
24282
24613
|
|
|
24283
24614
|
const JV_GRID_DEFAULT_OPTIONS = {
|
|
24284
24615
|
searchable: true,
|
|
@@ -24583,6 +24914,266 @@ function exportGridToExcel(header, rows, filename = 'export.xlsx') {
|
|
|
24583
24914
|
downloadBlob(blob, filename);
|
|
24584
24915
|
}
|
|
24585
24916
|
|
|
24917
|
+
function flattenGridColumns(columns) {
|
|
24918
|
+
return columns.flatMap((column) => column.children?.length ? flattenGridColumns(column.children) : [column]);
|
|
24919
|
+
}
|
|
24920
|
+
function getVisibleGridColumns(columns, columnOrder) {
|
|
24921
|
+
const visibleColumns = flattenGridColumns(columns).filter((column) => !column.hidden);
|
|
24922
|
+
if (columnOrder.length === 0)
|
|
24923
|
+
return visibleColumns;
|
|
24924
|
+
return columnOrder
|
|
24925
|
+
.map((key) => visibleColumns.find((column) => String(column.key) === key))
|
|
24926
|
+
.filter((column) => Boolean(column));
|
|
24927
|
+
}
|
|
24928
|
+
function getGroupedGridColumns(columns) {
|
|
24929
|
+
return columns.filter((column) => column.children && column.children.length > 0);
|
|
24930
|
+
}
|
|
24931
|
+
|
|
24932
|
+
function getCellKeyboardTarget(key, rowIndex, columnIndex, rowCount, columnCount) {
|
|
24933
|
+
if (key === 'ArrowUp' && rowIndex === 0) {
|
|
24934
|
+
return { kind: 'header', row: 0, column: columnIndex };
|
|
24935
|
+
}
|
|
24936
|
+
const movement = {
|
|
24937
|
+
ArrowDown: [1, 0],
|
|
24938
|
+
ArrowLeft: [0, -1],
|
|
24939
|
+
ArrowRight: [0, 1],
|
|
24940
|
+
ArrowUp: [-1, 0],
|
|
24941
|
+
};
|
|
24942
|
+
const delta = movement[key];
|
|
24943
|
+
if (!delta)
|
|
24944
|
+
return null;
|
|
24945
|
+
const target = { row: rowIndex + delta[0], column: columnIndex + delta[1] };
|
|
24946
|
+
if (target.row < 0 ||
|
|
24947
|
+
target.row >= rowCount ||
|
|
24948
|
+
target.column < 0 ||
|
|
24949
|
+
target.column >= columnCount) {
|
|
24950
|
+
return null;
|
|
24951
|
+
}
|
|
24952
|
+
return { kind: 'cell', ...target };
|
|
24953
|
+
}
|
|
24954
|
+
function getHeaderKeyboardTarget(key, columnIndex, columnCount) {
|
|
24955
|
+
if (key === 'ArrowDown')
|
|
24956
|
+
return { kind: 'cell', row: 0, column: columnIndex };
|
|
24957
|
+
const delta = key === 'ArrowLeft' ? -1 : key === 'ArrowRight' ? 1 : 0;
|
|
24958
|
+
if (!delta)
|
|
24959
|
+
return null;
|
|
24960
|
+
const targetColumn = columnIndex + delta;
|
|
24961
|
+
if (targetColumn < 0 || targetColumn >= columnCount)
|
|
24962
|
+
return null;
|
|
24963
|
+
return { kind: 'header', row: 0, column: targetColumn };
|
|
24964
|
+
}
|
|
24965
|
+
|
|
24966
|
+
function getGridEditType(column) {
|
|
24967
|
+
if (column.editType)
|
|
24968
|
+
return column.editType;
|
|
24969
|
+
switch (column.type) {
|
|
24970
|
+
case 'integer':
|
|
24971
|
+
case 'number':
|
|
24972
|
+
case 'currency':
|
|
24973
|
+
case 'percent':
|
|
24974
|
+
return 'number';
|
|
24975
|
+
case 'date':
|
|
24976
|
+
return 'date';
|
|
24977
|
+
case 'time':
|
|
24978
|
+
return 'time';
|
|
24979
|
+
case 'datetime':
|
|
24980
|
+
return 'datetime';
|
|
24981
|
+
case 'boolean':
|
|
24982
|
+
return 'boolean';
|
|
24983
|
+
default:
|
|
24984
|
+
return 'text';
|
|
24985
|
+
}
|
|
24986
|
+
}
|
|
24987
|
+
function getGridInputType(column) {
|
|
24988
|
+
switch (getGridEditType(column)) {
|
|
24989
|
+
case 'number':
|
|
24990
|
+
return 'number';
|
|
24991
|
+
case 'date':
|
|
24992
|
+
return 'date';
|
|
24993
|
+
case 'time':
|
|
24994
|
+
return 'time';
|
|
24995
|
+
case 'datetime':
|
|
24996
|
+
return 'datetime-local';
|
|
24997
|
+
default:
|
|
24998
|
+
return 'text';
|
|
24999
|
+
}
|
|
25000
|
+
}
|
|
25001
|
+
function isGridBooleanTrue(value) {
|
|
25002
|
+
return value === true || value === 'true' || value === 1 || value === '1';
|
|
25003
|
+
}
|
|
25004
|
+
function getGridEditValue(value, column, toDate) {
|
|
25005
|
+
const editType = getGridEditType(column);
|
|
25006
|
+
if (editType === 'date')
|
|
25007
|
+
return toGridDateInputValue(value, toDate);
|
|
25008
|
+
if (editType === 'datetime')
|
|
25009
|
+
return toGridDateTimeInputValue(value, toDate);
|
|
25010
|
+
if (editType === 'time')
|
|
25011
|
+
return toGridTimeInputValue(value, toDate);
|
|
25012
|
+
return value == null ? '' : String(value);
|
|
25013
|
+
}
|
|
25014
|
+
function normalizeGridEditValue(column, value, toDate) {
|
|
25015
|
+
switch (getGridEditType(column)) {
|
|
25016
|
+
case 'number': {
|
|
25017
|
+
if (value === '' || value == null)
|
|
25018
|
+
return null;
|
|
25019
|
+
const number = Number(value);
|
|
25020
|
+
return Number.isFinite(number) ? number : null;
|
|
25021
|
+
}
|
|
25022
|
+
case 'date':
|
|
25023
|
+
return toGridDateInputValue(value, toDate) || null;
|
|
25024
|
+
case 'datetime': {
|
|
25025
|
+
if (value === '' || value == null)
|
|
25026
|
+
return null;
|
|
25027
|
+
const date = new Date(String(value));
|
|
25028
|
+
return Number.isNaN(date.getTime()) ? null : date.toISOString();
|
|
25029
|
+
}
|
|
25030
|
+
case 'time': {
|
|
25031
|
+
if (value === '' || value == null)
|
|
25032
|
+
return null;
|
|
25033
|
+
const time = String(value);
|
|
25034
|
+
return /^\d{2}:\d{2}$/.test(time) ? `${time}:00` : time;
|
|
25035
|
+
}
|
|
25036
|
+
case 'boolean':
|
|
25037
|
+
return Boolean(value);
|
|
25038
|
+
default:
|
|
25039
|
+
return value;
|
|
25040
|
+
}
|
|
25041
|
+
}
|
|
25042
|
+
function toGridDateInputValue(value, toDate) {
|
|
25043
|
+
if (typeof value === 'string') {
|
|
25044
|
+
const match = value.match(/^\d{4}-\d{2}-\d{2}/);
|
|
25045
|
+
if (match)
|
|
25046
|
+
return match[0];
|
|
25047
|
+
}
|
|
25048
|
+
const date = toDate(value);
|
|
25049
|
+
if (!date)
|
|
25050
|
+
return '';
|
|
25051
|
+
return `${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, '0')}-${String(date.getUTCDate()).padStart(2, '0')}`;
|
|
25052
|
+
}
|
|
25053
|
+
function toGridDateTimeInputValue(value, toDate) {
|
|
25054
|
+
const date = toDate(value);
|
|
25055
|
+
if (!date)
|
|
25056
|
+
return '';
|
|
25057
|
+
const pad = (part) => String(part).padStart(2, '0');
|
|
25058
|
+
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`;
|
|
25059
|
+
}
|
|
25060
|
+
function toGridTimeInputValue(value, toDate) {
|
|
25061
|
+
if (typeof value === 'string' && /^\d{2}:\d{2}(:\d{2})?$/.test(value))
|
|
25062
|
+
return value.slice(0, 5);
|
|
25063
|
+
const date = toDate(value);
|
|
25064
|
+
if (!date)
|
|
25065
|
+
return '';
|
|
25066
|
+
return `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;
|
|
25067
|
+
}
|
|
25068
|
+
|
|
25069
|
+
function filterGridData(data, columns, searchTerm, filters, getColumnKey, getRawCellValue, getSearchValue) {
|
|
25070
|
+
let items = data;
|
|
25071
|
+
const term = searchTerm.trim().toLowerCase();
|
|
25072
|
+
if (term) {
|
|
25073
|
+
items = items.filter((row) => columns.some((column) => {
|
|
25074
|
+
if (column.searchable === false)
|
|
25075
|
+
return false;
|
|
25076
|
+
const value = getRawCellValue(row, column);
|
|
25077
|
+
if (value == null)
|
|
25078
|
+
return false;
|
|
25079
|
+
return getSearchValue(value, column).includes(term);
|
|
25080
|
+
}));
|
|
25081
|
+
}
|
|
25082
|
+
const hasFilters = Object.values(filters).some((filter) => filter.value.trim().length > 0);
|
|
25083
|
+
if (!hasFilters)
|
|
25084
|
+
return items;
|
|
25085
|
+
return items.filter((row) => Object.entries(filters).every(([key, filter]) => {
|
|
25086
|
+
if (!filter.value.trim())
|
|
25087
|
+
return true;
|
|
25088
|
+
const column = columns.find((candidate) => getColumnKey(candidate) === key);
|
|
25089
|
+
if (!column || column.filterable === false)
|
|
25090
|
+
return true;
|
|
25091
|
+
const value = getSearchValue(getRawCellValue(row, column), column);
|
|
25092
|
+
const filterValue = filter.value.toLowerCase();
|
|
25093
|
+
switch (filter.operator) {
|
|
25094
|
+
case 'contains':
|
|
25095
|
+
return value.includes(filterValue);
|
|
25096
|
+
case 'equals':
|
|
25097
|
+
return value === filterValue;
|
|
25098
|
+
case 'startsWith':
|
|
25099
|
+
return value.startsWith(filterValue);
|
|
25100
|
+
case 'endsWith':
|
|
25101
|
+
return value.endsWith(filterValue);
|
|
25102
|
+
default:
|
|
25103
|
+
return value.includes(filterValue);
|
|
25104
|
+
}
|
|
25105
|
+
}));
|
|
25106
|
+
}
|
|
25107
|
+
function sortGridData(data, sortState, findColumn, getRawCellValue, getComparableValue) {
|
|
25108
|
+
const { columnKey, direction } = sortState;
|
|
25109
|
+
if (!columnKey || !direction)
|
|
25110
|
+
return data;
|
|
25111
|
+
const column = findColumn(columnKey);
|
|
25112
|
+
return [...data].sort((a, b) => {
|
|
25113
|
+
const valueA = getComparableValue(getRawCellValue(a, column), column);
|
|
25114
|
+
const valueB = getComparableValue(getRawCellValue(b, column), column);
|
|
25115
|
+
if (valueA == null)
|
|
25116
|
+
return 1;
|
|
25117
|
+
if (valueB == null)
|
|
25118
|
+
return -1;
|
|
25119
|
+
const comparison = valueA < valueB ? -1 : valueA > valueB ? 1 : 0;
|
|
25120
|
+
return direction === 'asc' ? comparison : -comparison;
|
|
25121
|
+
});
|
|
25122
|
+
}
|
|
25123
|
+
function paginateGridData(data, pageIndex, pageSize, totalPages) {
|
|
25124
|
+
const page = Math.min(pageIndex, totalPages - 1);
|
|
25125
|
+
return data.slice(page * pageSize, page * pageSize + pageSize);
|
|
25126
|
+
}
|
|
25127
|
+
|
|
25128
|
+
function resolveGridSelection(controlledIds, internalIds) {
|
|
25129
|
+
return new Set(controlledIds ?? internalIds);
|
|
25130
|
+
}
|
|
25131
|
+
function areAllGridRowsSelected(rows, selectedIds, getRowId) {
|
|
25132
|
+
return rows.length > 0 && rows.every((row) => selectedIds.has(getRowId(row)));
|
|
25133
|
+
}
|
|
25134
|
+
function areSomeGridRowsSelected(rows, selectedIds, getRowId) {
|
|
25135
|
+
return (rows.some((row) => selectedIds.has(getRowId(row))) &&
|
|
25136
|
+
!areAllGridRowsSelected(rows, selectedIds, getRowId));
|
|
25137
|
+
}
|
|
25138
|
+
function toggleGridRowSelection(selectedIds, rowId) {
|
|
25139
|
+
const next = new Set(selectedIds);
|
|
25140
|
+
if (next.has(rowId))
|
|
25141
|
+
next.delete(rowId);
|
|
25142
|
+
else
|
|
25143
|
+
next.add(rowId);
|
|
25144
|
+
return Array.from(next);
|
|
25145
|
+
}
|
|
25146
|
+
function toggleGridRowsSelection(selectedIds, rows, checked, getRowId) {
|
|
25147
|
+
const next = new Set(selectedIds);
|
|
25148
|
+
rows.forEach((row) => {
|
|
25149
|
+
const id = getRowId(row);
|
|
25150
|
+
if (checked)
|
|
25151
|
+
next.add(id);
|
|
25152
|
+
else
|
|
25153
|
+
next.delete(id);
|
|
25154
|
+
});
|
|
25155
|
+
return Array.from(next);
|
|
25156
|
+
}
|
|
25157
|
+
|
|
25158
|
+
function getGridVirtualRange(scrollTop, clientHeight, rowHeight, itemCount, buffer = 5) {
|
|
25159
|
+
const start = Math.max(0, Math.floor(scrollTop / rowHeight) - buffer);
|
|
25160
|
+
const end = Math.min(itemCount, Math.ceil((scrollTop + clientHeight) / rowHeight) + buffer);
|
|
25161
|
+
return { start, end };
|
|
25162
|
+
}
|
|
25163
|
+
function getGridVirtualSlice(items, start, end, enabled) {
|
|
25164
|
+
if (!enabled)
|
|
25165
|
+
return items;
|
|
25166
|
+
if (start >= items.length)
|
|
25167
|
+
return [];
|
|
25168
|
+
return items.slice(start, Math.min(end, items.length));
|
|
25169
|
+
}
|
|
25170
|
+
function getGridVirtualTotalHeight(itemCount, rowHeight) {
|
|
25171
|
+
return itemCount * rowHeight;
|
|
25172
|
+
}
|
|
25173
|
+
function getGridVirtualOffset(start, rowHeight) {
|
|
25174
|
+
return start * rowHeight;
|
|
25175
|
+
}
|
|
25176
|
+
|
|
24586
25177
|
let gridIdSequence = 0;
|
|
24587
25178
|
class JvGridComponent {
|
|
24588
25179
|
gridId = `jv-grid-${++gridIdSequence}`;
|
|
@@ -24608,7 +25199,10 @@ class JvGridComponent {
|
|
|
24608
25199
|
columnResize = output();
|
|
24609
25200
|
columnReorder = output();
|
|
24610
25201
|
rowEdit = output();
|
|
24611
|
-
effectiveOptions = computed(() => ({
|
|
25202
|
+
effectiveOptions = computed(() => ({
|
|
25203
|
+
...JV_GRID_DEFAULT_OPTIONS,
|
|
25204
|
+
...this.options(),
|
|
25205
|
+
}), ...(ngDevMode ? [{ debugName: "effectiveOptions" }] : /* istanbul ignore next */ []));
|
|
24612
25206
|
idKey = computed(() => {
|
|
24613
25207
|
const tb = this.trackBy();
|
|
24614
25208
|
if (typeof tb === 'string')
|
|
@@ -24622,14 +25216,9 @@ class JvGridComponent {
|
|
|
24622
25216
|
columnWidths = signal({}, ...(ngDevMode ? [{ debugName: "columnWidths" }] : /* istanbul ignore next */ []));
|
|
24623
25217
|
activeCell = signal({ row: 0, column: 0 }, ...(ngDevMode ? [{ debugName: "activeCell" }] : /* istanbul ignore next */ []));
|
|
24624
25218
|
visibleColumns = computed(() => {
|
|
24625
|
-
|
|
24626
|
-
const order = this.columnOrder();
|
|
24627
|
-
if (order.length > 0) {
|
|
24628
|
-
return order.map(key => cols.find(c => this.colKey(c) === key)).filter(Boolean);
|
|
24629
|
-
}
|
|
24630
|
-
return cols;
|
|
25219
|
+
return getVisibleGridColumns(this.columns(), this.columnOrder());
|
|
24631
25220
|
}, ...(ngDevMode ? [{ debugName: "visibleColumns" }] : /* istanbul ignore next */ []));
|
|
24632
|
-
groupedHeaders = computed(() => this.columns()
|
|
25221
|
+
groupedHeaders = computed(() => getGroupedGridColumns(this.columns()), ...(ngDevMode ? [{ debugName: "groupedHeaders" }] : /* istanbul ignore next */ []));
|
|
24633
25222
|
internalSelectedIds = signal([], ...(ngDevMode ? [{ debugName: "internalSelectedIds" }] : /* istanbul ignore next */ []));
|
|
24634
25223
|
searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : /* istanbul ignore next */ []));
|
|
24635
25224
|
sortState = signal({ columnKey: '', direction: null }, ...(ngDevMode ? [{ debugName: "sortState" }] : /* istanbul ignore next */ []));
|
|
@@ -24638,8 +25227,8 @@ class JvGridComponent {
|
|
|
24638
25227
|
pageSize = computed(() => this.internalPageSize() ?? this.effectiveOptions().pageSize ?? 20, ...(ngDevMode ? [{ debugName: "pageSize" }] : /* istanbul ignore next */ []));
|
|
24639
25228
|
pageSizeStr = computed(() => String(this.pageSize()), ...(ngDevMode ? [{ debugName: "pageSizeStr" }] : /* istanbul ignore next */ []));
|
|
24640
25229
|
pageSizeOptions = computed(() => (this.effectiveOptions().pageSizeOptions ?? [])
|
|
24641
|
-
.filter(size => Number.isInteger(size) && size > 0)
|
|
24642
|
-
.map(size => ({ label: String(size), value: String(size) })), ...(ngDevMode ? [{ debugName: "pageSizeOptions" }] : /* istanbul ignore next */ []));
|
|
25230
|
+
.filter((size) => Number.isInteger(size) && size > 0)
|
|
25231
|
+
.map((size) => ({ label: String(size), value: String(size) })), ...(ngDevMode ? [{ debugName: "pageSizeOptions" }] : /* istanbul ignore next */ []));
|
|
24643
25232
|
pageSizeInputSync = effect(() => {
|
|
24644
25233
|
void this.options().pageSize;
|
|
24645
25234
|
this.internalPageSize.set(null);
|
|
@@ -24654,71 +25243,18 @@ class JvGridComponent {
|
|
|
24654
25243
|
this.pageIndex.set(Math.max(0, lastPage));
|
|
24655
25244
|
}, ...(ngDevMode ? [{ debugName: "pageBoundsGuard" }] : /* istanbul ignore next */ []));
|
|
24656
25245
|
selectedIdSet = computed(() => {
|
|
24657
|
-
|
|
24658
|
-
const fromInternal = this.internalSelectedIds();
|
|
24659
|
-
const ids = fromInput !== null ? fromInput : fromInternal;
|
|
24660
|
-
return new Set(ids);
|
|
25246
|
+
return resolveGridSelection(this.selectedIds(), this.internalSelectedIds());
|
|
24661
25247
|
}, ...(ngDevMode ? [{ debugName: "selectedIdSet" }] : /* istanbul ignore next */ []));
|
|
24662
|
-
hasActiveFilters = computed(() => Object.values(this.colFilters()).some(f => f.value.trim().length > 0), ...(ngDevMode ? [{ debugName: "hasActiveFilters" }] : /* istanbul ignore next */ []));
|
|
25248
|
+
hasActiveFilters = computed(() => Object.values(this.colFilters()).some((f) => f.value.trim().length > 0), ...(ngDevMode ? [{ debugName: "hasActiveFilters" }] : /* istanbul ignore next */ []));
|
|
24663
25249
|
filteredData = computed(() => {
|
|
24664
25250
|
if (this.effectiveOptions().serverSide)
|
|
24665
25251
|
return this.data();
|
|
24666
|
-
|
|
24667
|
-
const term = this.searchTerm().trim().toLowerCase();
|
|
24668
|
-
if (term) {
|
|
24669
|
-
items = items.filter(row => {
|
|
24670
|
-
return this.visibleColumns().some(col => {
|
|
24671
|
-
if (col.searchable === false)
|
|
24672
|
-
return false;
|
|
24673
|
-
const value = this.getRawCellValue(row, col);
|
|
24674
|
-
if (value == null)
|
|
24675
|
-
return false;
|
|
24676
|
-
return this.getSearchValue(value, col).includes(term);
|
|
24677
|
-
});
|
|
24678
|
-
});
|
|
24679
|
-
}
|
|
24680
|
-
const filters = this.colFilters();
|
|
24681
|
-
const hasFilters = Object.values(filters).some(f => f.value.trim().length > 0);
|
|
24682
|
-
if (hasFilters) {
|
|
24683
|
-
items = items.filter(row => {
|
|
24684
|
-
return Object.entries(filters).every(([key, filter]) => {
|
|
24685
|
-
if (!filter.value.trim())
|
|
24686
|
-
return true;
|
|
24687
|
-
const col = this.columns().find(c => this.colKey(c) === key);
|
|
24688
|
-
if (!col || col.filterable === false)
|
|
24689
|
-
return true;
|
|
24690
|
-
const value = this.getSearchValue(this.getRawCellValue(row, col), col);
|
|
24691
|
-
const fv = filter.value.toLowerCase();
|
|
24692
|
-
switch (filter.operator) {
|
|
24693
|
-
case 'contains': return value.includes(fv);
|
|
24694
|
-
case 'equals': return value === fv;
|
|
24695
|
-
case 'startsWith': return value.startsWith(fv);
|
|
24696
|
-
case 'endsWith': return value.endsWith(fv);
|
|
24697
|
-
default: return value.includes(fv);
|
|
24698
|
-
}
|
|
24699
|
-
});
|
|
24700
|
-
});
|
|
24701
|
-
}
|
|
24702
|
-
return items;
|
|
25252
|
+
return filterGridData(this.data(), this.visibleColumns(), this.searchTerm(), this.colFilters(), (column) => this.colKey(column), (row, column) => this.getRawCellValue(row, column), (value, column) => this.getSearchValue(value, column));
|
|
24703
25253
|
}, ...(ngDevMode ? [{ debugName: "filteredData" }] : /* istanbul ignore next */ []));
|
|
24704
25254
|
sortedData = computed(() => {
|
|
24705
25255
|
if (this.effectiveOptions().serverSide)
|
|
24706
25256
|
return this.filteredData();
|
|
24707
|
-
|
|
24708
|
-
const { columnKey, direction } = this.sortState();
|
|
24709
|
-
if (!columnKey || !direction)
|
|
24710
|
-
return items;
|
|
24711
|
-
return [...items].sort((a, b) => {
|
|
24712
|
-
const col = this.findColumn(columnKey);
|
|
24713
|
-
const va = this.getComparableValue(this.getRawCellValue(a, col), col);
|
|
24714
|
-
const vb = this.getComparableValue(this.getRawCellValue(b, col), col);
|
|
24715
|
-
if (va == null)
|
|
24716
|
-
return 1;
|
|
24717
|
-
if (vb == null)
|
|
24718
|
-
return -1;
|
|
24719
|
-
const cmp = va < vb ? -1 : va > vb ? 1 : 0;
|
|
24720
|
-
return direction === 'asc' ? cmp : -cmp;
|
|
24721
|
-
});
|
|
25257
|
+
return sortGridData(this.filteredData(), this.sortState(), (key) => this.findColumn(key), (row, column) => this.getRawCellValue(row, column), (value, column) => this.getComparableValue(value, column));
|
|
24722
25258
|
}, ...(ngDevMode ? [{ debugName: "sortedData" }] : /* istanbul ignore next */ []));
|
|
24723
25259
|
effectiveTotalItems = computed(() => {
|
|
24724
25260
|
if (this.effectiveOptions().serverSide) {
|
|
@@ -24732,10 +25268,7 @@ class JvGridComponent {
|
|
|
24732
25268
|
return this.virtualDisplayData();
|
|
24733
25269
|
if (!this.effectiveOptions().pageable)
|
|
24734
25270
|
return this.sortedData();
|
|
24735
|
-
|
|
24736
|
-
const ps = this.pageSize();
|
|
24737
|
-
const page = Math.min(this.pageIndex(), this.effectiveTotalPages() - 1);
|
|
24738
|
-
return items.slice(page * ps, page * ps + ps);
|
|
25271
|
+
return paginateGridData(this.sortedData(), this.pageIndex(), this.pageSize(), this.effectiveTotalPages());
|
|
24739
25272
|
}, ...(ngDevMode ? [{ debugName: "displayData" }] : /* istanbul ignore next */ []));
|
|
24740
25273
|
virtualScrollEnabled = computed(() => this.effectiveOptions().virtualScroll && !this.effectiveOptions().serverSide, ...(ngDevMode ? [{ debugName: "virtualScrollEnabled" }] : /* istanbul ignore next */ []));
|
|
24741
25274
|
virtualStartIndex = signal(0, ...(ngDevMode ? [{ debugName: "virtualStartIndex" }] : /* istanbul ignore next */ []));
|
|
@@ -24746,23 +25279,16 @@ class JvGridComponent {
|
|
|
24746
25279
|
this.virtualEndIndex.set(Math.min(20, length));
|
|
24747
25280
|
}, ...(ngDevMode ? [{ debugName: "virtualRangeResetter" }] : /* istanbul ignore next */ []));
|
|
24748
25281
|
virtualDisplayData = computed(() => {
|
|
24749
|
-
|
|
24750
|
-
return this.sortedData();
|
|
24751
|
-
const items = this.sortedData();
|
|
24752
|
-
const start = this.virtualStartIndex();
|
|
24753
|
-
const end = this.virtualEndIndex();
|
|
24754
|
-
if (start >= items.length)
|
|
24755
|
-
return [];
|
|
24756
|
-
return items.slice(start, Math.min(end, items.length));
|
|
25282
|
+
return getGridVirtualSlice(this.sortedData(), this.virtualStartIndex(), this.virtualEndIndex(), !!this.virtualScrollEnabled());
|
|
24757
25283
|
}, ...(ngDevMode ? [{ debugName: "virtualDisplayData" }] : /* istanbul ignore next */ []));
|
|
24758
25284
|
virtualTotalHeight = computed(() => {
|
|
24759
25285
|
const count = this.effectiveOptions().serverSide
|
|
24760
25286
|
? this.effectiveTotalItems()
|
|
24761
25287
|
: this.sortedData().length;
|
|
24762
|
-
return count
|
|
25288
|
+
return getGridVirtualTotalHeight(count, this.effectiveOptions().virtualScrollRowHeight ?? 48);
|
|
24763
25289
|
}, ...(ngDevMode ? [{ debugName: "virtualTotalHeight" }] : /* istanbul ignore next */ []));
|
|
24764
25290
|
virtualOffsetY = computed(() => {
|
|
24765
|
-
return this.virtualStartIndex()
|
|
25291
|
+
return getGridVirtualOffset(this.virtualStartIndex(), this.effectiveOptions().virtualScrollRowHeight ?? 48);
|
|
24766
25292
|
}, ...(ngDevMode ? [{ debugName: "virtualOffsetY" }] : /* istanbul ignore next */ []));
|
|
24767
25293
|
pageStart = computed(() => this.effectiveTotalItems() === 0 ? 0 : this.pageIndex() * this.pageSize() + 1, ...(ngDevMode ? [{ debugName: "pageStart" }] : /* istanbul ignore next */ []));
|
|
24768
25294
|
pageEnd = computed(() => Math.min((this.pageIndex() + 1) * this.pageSize(), this.effectiveTotalItems()), ...(ngDevMode ? [{ debugName: "pageEnd" }] : /* istanbul ignore next */ []));
|
|
@@ -24778,11 +25304,11 @@ class JvGridComponent {
|
|
|
24778
25304
|
}, ...(ngDevMode ? [{ debugName: "pageRange" }] : /* istanbul ignore next */ []));
|
|
24779
25305
|
allSelected = computed(() => {
|
|
24780
25306
|
const rows = this.displayData();
|
|
24781
|
-
return rows
|
|
25307
|
+
return areAllGridRowsSelected(rows, this.selectedIdSet(), (row) => this.getRowId(row));
|
|
24782
25308
|
}, ...(ngDevMode ? [{ debugName: "allSelected" }] : /* istanbul ignore next */ []));
|
|
24783
25309
|
someSelected = computed(() => {
|
|
24784
25310
|
const rows = this.displayData();
|
|
24785
|
-
return rows
|
|
25311
|
+
return areSomeGridRowsSelected(rows, this.selectedIdSet(), (row) => this.getRowId(row));
|
|
24786
25312
|
}, ...(ngDevMode ? [{ debugName: "someSelected" }] : /* istanbul ignore next */ []));
|
|
24787
25313
|
colspan = computed(() => {
|
|
24788
25314
|
let count = this.visibleColumns().length;
|
|
@@ -24800,9 +25326,6 @@ class JvGridComponent {
|
|
|
24800
25326
|
const active = this.activeCell();
|
|
24801
25327
|
return active.row === rowIndex && active.column === columnIndex ? 0 : -1;
|
|
24802
25328
|
}
|
|
24803
|
-
flattenColumns(columns) {
|
|
24804
|
-
return columns.flatMap(col => col.children?.length ? this.flattenColumns(col.children) : [col]);
|
|
24805
|
-
}
|
|
24806
25329
|
onCellFocus(rowIndex, columnIndex) {
|
|
24807
25330
|
if (this.resolvedOptions().keyboardNavigation) {
|
|
24808
25331
|
this.activeCell.set({ row: rowIndex, column: columnIndex });
|
|
@@ -24812,34 +25335,26 @@ class JvGridComponent {
|
|
|
24812
25335
|
if (!this.resolvedOptions().keyboardNavigation)
|
|
24813
25336
|
return;
|
|
24814
25337
|
const target = event.target;
|
|
24815
|
-
if (target !== event.currentTarget &&
|
|
25338
|
+
if (target !== event.currentTarget &&
|
|
25339
|
+
target.closest('button, input, select, textarea, [contenteditable="true"]')) {
|
|
24816
25340
|
return;
|
|
24817
25341
|
}
|
|
24818
|
-
const
|
|
24819
|
-
|
|
24820
|
-
|
|
24821
|
-
|
|
24822
|
-
};
|
|
24823
|
-
if (event.key === 'ArrowUp' && rowIndex === 0) {
|
|
25342
|
+
const targetPosition = getCellKeyboardTarget(event.key, rowIndex, columnIndex, this.displayData().length, this.visibleColumns().length);
|
|
25343
|
+
if (!targetPosition)
|
|
25344
|
+
return;
|
|
25345
|
+
if (targetPosition.kind === 'header') {
|
|
24824
25346
|
event.preventDefault();
|
|
24825
|
-
this.activeCell.set({ row:
|
|
25347
|
+
this.activeCell.set({ row: targetPosition.row, column: targetPosition.column });
|
|
24826
25348
|
const table = event.currentTarget.closest('table');
|
|
24827
|
-
table
|
|
25349
|
+
table
|
|
25350
|
+
?.querySelector(`[data-column-index="${targetPosition.column}"][role="columnheader"]`)
|
|
25351
|
+
?.focus();
|
|
24828
25352
|
return;
|
|
24829
25353
|
}
|
|
24830
|
-
const delta = event.key === 'ArrowUp' ? [-1, 0] : movement[event.key];
|
|
24831
|
-
if (!delta)
|
|
24832
|
-
return;
|
|
24833
|
-
const nextRow = rowIndex + delta[0];
|
|
24834
|
-
const nextColumn = columnIndex + delta[1];
|
|
24835
|
-
const rows = this.displayData();
|
|
24836
|
-
const columns = this.visibleColumns();
|
|
24837
|
-
if (nextRow < 0 || nextRow >= rows.length || nextColumn < 0 || nextColumn >= columns.length)
|
|
24838
|
-
return;
|
|
24839
25354
|
event.preventDefault();
|
|
24840
|
-
this.activeCell.set({ row:
|
|
25355
|
+
this.activeCell.set({ row: targetPosition.row, column: targetPosition.column });
|
|
24841
25356
|
const table = event.currentTarget.closest('table');
|
|
24842
|
-
const nextCell = table?.querySelector(`.jv-grid-keyboard-cell[data-row-index="${
|
|
25357
|
+
const nextCell = table?.querySelector(`.jv-grid-keyboard-cell[data-row-index="${targetPosition.row}"][data-column-index="${targetPosition.column}"]`);
|
|
24843
25358
|
nextCell?.focus();
|
|
24844
25359
|
}
|
|
24845
25360
|
onCellF2(event, rowIndex, columnIndex) {
|
|
@@ -24861,7 +25376,10 @@ class JvGridComponent {
|
|
|
24861
25376
|
onHeaderKeydown(event, columnIndex) {
|
|
24862
25377
|
if (!this.resolvedOptions().keyboardNavigation)
|
|
24863
25378
|
return;
|
|
24864
|
-
|
|
25379
|
+
const targetPosition = getHeaderKeyboardTarget(event.key, columnIndex, this.visibleColumns().length);
|
|
25380
|
+
if (!targetPosition)
|
|
25381
|
+
return;
|
|
25382
|
+
if (targetPosition.kind === 'cell') {
|
|
24865
25383
|
const table = event.currentTarget.closest('table');
|
|
24866
25384
|
const firstCell = table?.querySelector(`.jv-grid-keyboard-cell[data-row-index="0"][data-column-index="${columnIndex}"]`);
|
|
24867
25385
|
if (firstCell) {
|
|
@@ -24871,16 +25389,12 @@ class JvGridComponent {
|
|
|
24871
25389
|
}
|
|
24872
25390
|
return;
|
|
24873
25391
|
}
|
|
24874
|
-
const delta = event.key === 'ArrowLeft' ? -1 : event.key === 'ArrowRight' ? 1 : 0;
|
|
24875
|
-
if (!delta)
|
|
24876
|
-
return;
|
|
24877
|
-
const nextColumn = columnIndex + delta;
|
|
24878
|
-
if (nextColumn < 0 || nextColumn >= this.visibleColumns().length)
|
|
24879
|
-
return;
|
|
24880
25392
|
event.preventDefault();
|
|
24881
|
-
this.activeCell.set({ row:
|
|
25393
|
+
this.activeCell.set({ row: targetPosition.row, column: targetPosition.column });
|
|
24882
25394
|
const table = event.currentTarget.closest('table');
|
|
24883
|
-
table
|
|
25395
|
+
table
|
|
25396
|
+
?.querySelector(`[data-column-index="${targetPosition.column}"][role="columnheader"]`)
|
|
25397
|
+
?.focus();
|
|
24884
25398
|
}
|
|
24885
25399
|
editState = signal(null, ...(ngDevMode ? [{ debugName: "editState" }] : /* istanbul ignore next */ []));
|
|
24886
25400
|
t = (key, params) => this.translationService.translate(key, params);
|
|
@@ -24892,7 +25406,7 @@ class JvGridComponent {
|
|
|
24892
25406
|
const tb = this.trackBy();
|
|
24893
25407
|
if (typeof tb === 'function')
|
|
24894
25408
|
return tb(row, index ?? 0);
|
|
24895
|
-
if (row && typeof row === 'object' &&
|
|
25409
|
+
if (row && typeof row === 'object' && 'id' in row) {
|
|
24896
25410
|
const id = record['id'];
|
|
24897
25411
|
if (typeof id === 'string' || typeof id === 'number')
|
|
24898
25412
|
return id;
|
|
@@ -24912,106 +25426,22 @@ class JvGridComponent {
|
|
|
24912
25426
|
return this.getRawCellValue(row, col);
|
|
24913
25427
|
}
|
|
24914
25428
|
getEditValue(row, col) {
|
|
24915
|
-
|
|
24916
|
-
const editType = this.editType(col);
|
|
24917
|
-
if (editType === 'date')
|
|
24918
|
-
return this.toDateInputValue(val);
|
|
24919
|
-
if (editType === 'datetime')
|
|
24920
|
-
return this.toDateTimeInputValue(val);
|
|
24921
|
-
if (editType === 'time')
|
|
24922
|
-
return this.toTimeInputValue(val);
|
|
24923
|
-
return val == null ? '' : String(val);
|
|
25429
|
+
return getGridEditValue(this.getCellValue(row, col), col, (value) => this.formatService.toDate(value));
|
|
24924
25430
|
}
|
|
24925
25431
|
getBooleanEditValue(row, col) {
|
|
24926
|
-
|
|
24927
|
-
return value === true || value === 'true' || value === 1 || value === '1';
|
|
25432
|
+
return isGridBooleanTrue(this.getCellValue(row, col));
|
|
24928
25433
|
}
|
|
24929
25434
|
isBooleanTrue(value) {
|
|
24930
|
-
return value
|
|
25435
|
+
return isGridBooleanTrue(value);
|
|
24931
25436
|
}
|
|
24932
25437
|
editType(col) {
|
|
24933
|
-
|
|
24934
|
-
return col.editType;
|
|
24935
|
-
switch (col.type) {
|
|
24936
|
-
case 'integer':
|
|
24937
|
-
case 'number':
|
|
24938
|
-
case 'currency':
|
|
24939
|
-
case 'percent':
|
|
24940
|
-
return 'number';
|
|
24941
|
-
case 'date':
|
|
24942
|
-
return 'date';
|
|
24943
|
-
case 'time':
|
|
24944
|
-
return 'time';
|
|
24945
|
-
case 'datetime':
|
|
24946
|
-
return 'datetime';
|
|
24947
|
-
case 'boolean':
|
|
24948
|
-
return 'boolean';
|
|
24949
|
-
default:
|
|
24950
|
-
return 'text';
|
|
24951
|
-
}
|
|
25438
|
+
return getGridEditType(col);
|
|
24952
25439
|
}
|
|
24953
25440
|
inputType(col) {
|
|
24954
|
-
|
|
24955
|
-
case 'number': return 'number';
|
|
24956
|
-
case 'date': return 'date';
|
|
24957
|
-
case 'time': return 'time';
|
|
24958
|
-
case 'datetime': return 'datetime-local';
|
|
24959
|
-
default: return 'text';
|
|
24960
|
-
}
|
|
25441
|
+
return getGridInputType(col);
|
|
24961
25442
|
}
|
|
24962
25443
|
normalizeEditValue(col, value) {
|
|
24963
|
-
|
|
24964
|
-
case 'number': {
|
|
24965
|
-
if (value === '' || value == null)
|
|
24966
|
-
return null;
|
|
24967
|
-
const number = Number(value);
|
|
24968
|
-
return Number.isFinite(number) ? number : null;
|
|
24969
|
-
}
|
|
24970
|
-
case 'date':
|
|
24971
|
-
return this.toDateInputValue(value) || null;
|
|
24972
|
-
case 'datetime': {
|
|
24973
|
-
if (value === '' || value == null)
|
|
24974
|
-
return null;
|
|
24975
|
-
const date = new Date(String(value));
|
|
24976
|
-
return Number.isNaN(date.getTime()) ? null : date.toISOString();
|
|
24977
|
-
}
|
|
24978
|
-
case 'time': {
|
|
24979
|
-
if (value === '' || value == null)
|
|
24980
|
-
return null;
|
|
24981
|
-
const time = String(value);
|
|
24982
|
-
return /^\d{2}:\d{2}$/.test(time) ? `${time}:00` : time;
|
|
24983
|
-
}
|
|
24984
|
-
case 'boolean':
|
|
24985
|
-
return Boolean(value);
|
|
24986
|
-
default:
|
|
24987
|
-
return value;
|
|
24988
|
-
}
|
|
24989
|
-
}
|
|
24990
|
-
toDateInputValue(value) {
|
|
24991
|
-
if (typeof value === 'string') {
|
|
24992
|
-
const match = value.match(/^\d{4}-\d{2}-\d{2}/);
|
|
24993
|
-
if (match)
|
|
24994
|
-
return match[0];
|
|
24995
|
-
}
|
|
24996
|
-
const date = this.formatService.toDate(value);
|
|
24997
|
-
if (!date)
|
|
24998
|
-
return '';
|
|
24999
|
-
return `${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, '0')}-${String(date.getUTCDate()).padStart(2, '0')}`;
|
|
25000
|
-
}
|
|
25001
|
-
toDateTimeInputValue(value) {
|
|
25002
|
-
const date = this.formatService.toDate(value);
|
|
25003
|
-
if (!date)
|
|
25004
|
-
return '';
|
|
25005
|
-
const pad = (part) => String(part).padStart(2, '0');
|
|
25006
|
-
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`;
|
|
25007
|
-
}
|
|
25008
|
-
toTimeInputValue(value) {
|
|
25009
|
-
if (typeof value === 'string' && /^\d{2}:\d{2}(:\d{2})?$/.test(value))
|
|
25010
|
-
return value.slice(0, 5);
|
|
25011
|
-
const date = this.formatService.toDate(value);
|
|
25012
|
-
if (!date)
|
|
25013
|
-
return '';
|
|
25014
|
-
return `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;
|
|
25444
|
+
return normalizeGridEditValue(col, value, (input) => this.formatService.toDate(input));
|
|
25015
25445
|
}
|
|
25016
25446
|
formatValue(value, col, _row) {
|
|
25017
25447
|
if (value == null)
|
|
@@ -25098,7 +25528,7 @@ class JvGridComponent {
|
|
|
25098
25528
|
return (this.resolvedOptions().editable || col.editable === true) && col.editable !== false;
|
|
25099
25529
|
}
|
|
25100
25530
|
groupColspan(group) {
|
|
25101
|
-
return
|
|
25531
|
+
return flattenGridColumns(group.children ?? []).filter((col) => !col.hidden).length || 1;
|
|
25102
25532
|
}
|
|
25103
25533
|
isEditingCell(row, col) {
|
|
25104
25534
|
const es = this.editState();
|
|
@@ -25109,13 +25539,13 @@ class JvGridComponent {
|
|
|
25109
25539
|
return es !== null && es.rowId === this.getRowId(row);
|
|
25110
25540
|
}
|
|
25111
25541
|
getEditOptions(col) {
|
|
25112
|
-
return (col.editOptions || []).map(opt => ({
|
|
25542
|
+
return (col.editOptions || []).map((opt) => ({
|
|
25113
25543
|
label: opt.label,
|
|
25114
25544
|
value: String(opt.value),
|
|
25115
25545
|
}));
|
|
25116
25546
|
}
|
|
25117
25547
|
findColumn(key) {
|
|
25118
|
-
return this.visibleColumns().find(c => this.colKey(c) === key) ?? { key, header: key };
|
|
25548
|
+
return this.visibleColumns().find((c) => this.colKey(c) === key) ?? { key, header: key };
|
|
25119
25549
|
}
|
|
25120
25550
|
toggleSort(col, event) {
|
|
25121
25551
|
if (col.sortable === false || !this.resolvedOptions().sortable)
|
|
@@ -25153,13 +25583,7 @@ class JvGridComponent {
|
|
|
25153
25583
|
return this.selectedIdSet().has(this.getRowId(row));
|
|
25154
25584
|
}
|
|
25155
25585
|
toggleRow(row) {
|
|
25156
|
-
const
|
|
25157
|
-
const set = new Set(this.selectedIdSet());
|
|
25158
|
-
if (set.has(id))
|
|
25159
|
-
set.delete(id);
|
|
25160
|
-
else
|
|
25161
|
-
set.add(id);
|
|
25162
|
-
const nextIds = Array.from(set);
|
|
25586
|
+
const nextIds = toggleGridRowSelection(this.selectedIdSet(), this.getRowId(row));
|
|
25163
25587
|
if (this.selectedIds() === null)
|
|
25164
25588
|
this.internalSelectedIds.set(nextIds);
|
|
25165
25589
|
this.selectionChange.emit(nextIds);
|
|
@@ -25173,15 +25597,7 @@ class JvGridComponent {
|
|
|
25173
25597
|
this.pageChange.emit({ pageIndex: 0, pageSize });
|
|
25174
25598
|
}
|
|
25175
25599
|
toggleSelectAll(checked) {
|
|
25176
|
-
const
|
|
25177
|
-
const rows = this.displayData();
|
|
25178
|
-
rows.forEach(r => {
|
|
25179
|
-
if (checked)
|
|
25180
|
-
set.add(this.getRowId(r));
|
|
25181
|
-
else
|
|
25182
|
-
set.delete(this.getRowId(r));
|
|
25183
|
-
});
|
|
25184
|
-
const nextIds = Array.from(set);
|
|
25600
|
+
const nextIds = toggleGridRowsSelection(this.selectedIdSet(), this.displayData(), checked, (row) => this.getRowId(row));
|
|
25185
25601
|
if (this.selectedIds() === null)
|
|
25186
25602
|
this.internalSelectedIds.set(nextIds);
|
|
25187
25603
|
this.selectionChange.emit(nextIds);
|
|
@@ -25205,7 +25621,7 @@ class JvGridComponent {
|
|
|
25205
25621
|
}
|
|
25206
25622
|
onColumnFilterChange(col, value) {
|
|
25207
25623
|
const key = this.colKey(col);
|
|
25208
|
-
this.colFilters.update(f => ({
|
|
25624
|
+
this.colFilters.update((f) => ({
|
|
25209
25625
|
...f,
|
|
25210
25626
|
[key]: { key, value, operator: 'contains' },
|
|
25211
25627
|
}));
|
|
@@ -25215,8 +25631,8 @@ class JvGridComponent {
|
|
|
25215
25631
|
getRowLabel(row, _index) {
|
|
25216
25632
|
const label = this.visibleColumns()
|
|
25217
25633
|
.slice(0, 2)
|
|
25218
|
-
.map(col => this.getCellValue(row, col))
|
|
25219
|
-
.filter(v => v != null)
|
|
25634
|
+
.map((col) => this.getCellValue(row, col))
|
|
25635
|
+
.filter((v) => v != null)
|
|
25220
25636
|
.join(' - ');
|
|
25221
25637
|
return `${label}${this.isSelected(row) ? ` (${this.t('grid.selected')})` : ''}`;
|
|
25222
25638
|
}
|
|
@@ -25250,7 +25666,7 @@ class JvGridComponent {
|
|
|
25250
25666
|
this.editState.set(null);
|
|
25251
25667
|
}
|
|
25252
25668
|
onEditValueChange(row, col, value) {
|
|
25253
|
-
const option = col.editOptions?.find(item => String(item.value) === value);
|
|
25669
|
+
const option = col.editOptions?.find((item) => String(item.value) === value);
|
|
25254
25670
|
this.commitEdit(row, col, option?.value ?? value);
|
|
25255
25671
|
}
|
|
25256
25672
|
// Column resizing
|
|
@@ -25275,7 +25691,7 @@ class JvGridComponent {
|
|
|
25275
25691
|
return;
|
|
25276
25692
|
const diff = event.clientX - this.resizeData.startX;
|
|
25277
25693
|
const newWidth = Math.max(30, this.resizeData.startWidth + diff);
|
|
25278
|
-
this.columnWidths.update(w => ({
|
|
25694
|
+
this.columnWidths.update((w) => ({
|
|
25279
25695
|
...w,
|
|
25280
25696
|
[this.colKey(this.resizeData.col)]: `${newWidth}px`,
|
|
25281
25697
|
}));
|
|
@@ -25310,7 +25726,7 @@ class JvGridComponent {
|
|
|
25310
25726
|
return;
|
|
25311
25727
|
if (this.dragIndex === targetIdx)
|
|
25312
25728
|
return;
|
|
25313
|
-
const cols = this.visibleColumns().map(c => this.colKey(c));
|
|
25729
|
+
const cols = this.visibleColumns().map((c) => this.colKey(c));
|
|
25314
25730
|
const [moved] = cols.splice(this.dragIndex, 1);
|
|
25315
25731
|
cols.splice(targetIdx, 0, moved);
|
|
25316
25732
|
this.columnOrder.set(cols);
|
|
@@ -25325,13 +25741,9 @@ class JvGridComponent {
|
|
|
25325
25741
|
if (!this.virtualScrollEnabled())
|
|
25326
25742
|
return;
|
|
25327
25743
|
const rowHeight = this.effectiveOptions().virtualScrollRowHeight ?? 48;
|
|
25328
|
-
const
|
|
25329
|
-
|
|
25330
|
-
|
|
25331
|
-
const start = Math.max(0, Math.floor(scrollTop / rowHeight) - buffer);
|
|
25332
|
-
const end = Math.min(this.sortedData().length, Math.ceil((scrollTop + clientHeight) / rowHeight) + buffer);
|
|
25333
|
-
this.virtualStartIndex.set(start);
|
|
25334
|
-
this.virtualEndIndex.set(end);
|
|
25744
|
+
const range = getGridVirtualRange(target.scrollTop, target.clientHeight, rowHeight, this.sortedData().length);
|
|
25745
|
+
this.virtualStartIndex.set(range.start);
|
|
25746
|
+
this.virtualEndIndex.set(range.end);
|
|
25335
25747
|
}
|
|
25336
25748
|
// Export
|
|
25337
25749
|
exportCsv() {
|
|
@@ -25354,753 +25766,23 @@ class JvGridComponent {
|
|
|
25354
25766
|
return configuredName.replace(/\.(csv|xlsx)$/i, '') + `.${extension}`;
|
|
25355
25767
|
}
|
|
25356
25768
|
buildExportMatrix() {
|
|
25357
|
-
const cols = this.visibleColumns().map(c => ({
|
|
25769
|
+
const cols = this.visibleColumns().map((c) => ({
|
|
25770
|
+
key: this.colKey(c),
|
|
25771
|
+
header: c.header,
|
|
25772
|
+
column: c,
|
|
25773
|
+
}));
|
|
25358
25774
|
const allData = this.effectiveOptions().serverSide ? this.data() : this.sortedData();
|
|
25359
25775
|
return {
|
|
25360
|
-
header: cols.map(c => c.header),
|
|
25361
|
-
rows: allData.map(row => cols.map(col => this.getExportValue(row[col.key], col.column))),
|
|
25776
|
+
header: cols.map((c) => c.header),
|
|
25777
|
+
rows: allData.map((row) => cols.map((col) => this.getExportValue(row[col.key], col.column))),
|
|
25362
25778
|
};
|
|
25363
25779
|
}
|
|
25364
25780
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JvGridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
25365
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: JvGridComponent, isStandalone: true, selector: "jv-grid", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, trackBy: { classPropertyName: "trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null }, selectedIds: { classPropertyName: "selectedIds", publicName: "selectedIds", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rowClick: "rowClick", rowDoubleClick: "rowDoubleClick", actionClick: "actionClick", selectionChange: "selectionChange", pageChange: "pageChange", searchChange: "searchChange", sortChange: "sortChange", columnFilter: "columnFilter", columnResize: "columnResize", columnReorder: "columnReorder", rowEdit: "rowEdit" }, ngImport: i0, template: `
|
|
25366
|
-
<div class="jv-grid" role="region" [attr.aria-label]="resolvedOptions().ariaLabel || gridLabel()">
|
|
25367
|
-
@if (resolvedOptions().searchable || resolvedOptions().exportable) {
|
|
25368
|
-
<div class="jv-grid-toolbar">
|
|
25369
|
-
@if (resolvedOptions().searchable) {
|
|
25370
|
-
<div class="jv-grid-search">
|
|
25371
|
-
<jv-icon name="search" [size]="16" />
|
|
25372
|
-
<jv-input
|
|
25373
|
-
[inputId]="gridSearchInputId"
|
|
25374
|
-
[placeholder]="t('grid.searchPlaceholder')"
|
|
25375
|
-
[ngModel]="searchTerm()"
|
|
25376
|
-
(ngModelChange)="onSearchInput($event)"
|
|
25377
|
-
/>
|
|
25378
|
-
</div>
|
|
25379
|
-
}
|
|
25380
|
-
@if (resolvedOptions().exportable) {
|
|
25381
|
-
<div class="jv-grid-export-actions">
|
|
25382
|
-
<jv-button variant="outline" icon="download" (click)="exportCsv()">{{ t('grid.exportCsv') }}</jv-button>
|
|
25383
|
-
<jv-button variant="outline" icon="file-spreadsheet" (click)="exportExcel()">{{ t('grid.exportExcel') }}</jv-button>
|
|
25384
|
-
</div>
|
|
25385
|
-
}
|
|
25386
|
-
</div>
|
|
25387
|
-
}
|
|
25388
|
-
|
|
25389
|
-
@if (resolvedOptions().loading) {
|
|
25390
|
-
<div class="jv-grid-loading" role="status" aria-live="polite">
|
|
25391
|
-
<span class="jv-grid-spinner" aria-hidden="true"></span>
|
|
25392
|
-
<span>{{ t('grid.loading') }}</span>
|
|
25393
|
-
</div>
|
|
25394
|
-
} @else {
|
|
25395
|
-
<div
|
|
25396
|
-
class="jv-grid-table-wrap"
|
|
25397
|
-
[class.jv-grid-virtual]="virtualScrollEnabled()"
|
|
25398
|
-
#tableWrap
|
|
25399
|
-
(scroll)="onVirtualScroll($any($event.target))"
|
|
25400
|
-
>
|
|
25401
|
-
@if (virtualScrollEnabled()) {
|
|
25402
|
-
<div class="jv-grid-virtual-spacer" [style.height.px]="virtualTotalHeight()"></div>
|
|
25403
|
-
}
|
|
25404
|
-
<table
|
|
25405
|
-
class="jv-grid-table"
|
|
25406
|
-
role="grid"
|
|
25407
|
-
[attr.aria-label]="resolvedOptions().ariaLabel || gridLabel()"
|
|
25408
|
-
[attr.aria-rowcount]="effectiveTotalItems()"
|
|
25409
|
-
[attr.aria-colcount]="colspan()"
|
|
25410
|
-
[class]="densityClass()"
|
|
25411
|
-
[style.position]="virtualScrollEnabled() ? 'relative' : null"
|
|
25412
|
-
[style.top.px]="virtualOffsetY()"
|
|
25413
|
-
>
|
|
25414
|
-
<caption class="sr-only">{{ resolvedOptions().ariaLabel || gridLabel() }}</caption>
|
|
25415
|
-
|
|
25416
|
-
@let hasGroupedHeaders = groupedHeaders().length > 0;
|
|
25417
|
-
|
|
25418
|
-
<thead class="jv-grid-thead">
|
|
25419
|
-
@if (hasGroupedHeaders) {
|
|
25420
|
-
<tr>
|
|
25421
|
-
@if (resolvedOptions().selectable) {
|
|
25422
|
-
<th class="jv-grid-th jv-grid-th-select" scope="col" [attr.rowspan]="2">
|
|
25423
|
-
<input
|
|
25424
|
-
type="checkbox"
|
|
25425
|
-
class="jv-grid-checkbox"
|
|
25426
|
-
[checked]="allSelected()"
|
|
25427
|
-
(change)="toggleSelectAll($any($event.target).checked)"
|
|
25428
|
-
[attr.aria-label]="allSelected() ? t('grid.deselectAll') : t('grid.selectAll')"
|
|
25429
|
-
[indeterminate]="someSelected()"
|
|
25430
|
-
/>
|
|
25431
|
-
</th>
|
|
25432
|
-
}
|
|
25433
|
-
@for (group of groupedHeaders(); track colKey(group)) {
|
|
25434
|
-
<th
|
|
25435
|
-
class="jv-grid-th"
|
|
25436
|
-
[class]="group.headerClass || ''"
|
|
25437
|
-
[class.jv-grid-th-sticky-left]="isStickyLeft(group)"
|
|
25438
|
-
[class.jv-grid-th-sticky-right]="isStickyRight(group)"
|
|
25439
|
-
[attr.colspan]="groupColspan(group)"
|
|
25440
|
-
scope="colgroup"
|
|
25441
|
-
[style.text-align]="group.align ?? 'start'"
|
|
25442
|
-
>
|
|
25443
|
-
<div class="jv-grid-th-content">{{ group.header }}</div>
|
|
25444
|
-
</th>
|
|
25445
|
-
}
|
|
25446
|
-
@if (actions().length > 0) {
|
|
25447
|
-
<th class="jv-grid-th jv-grid-th-actions" scope="col" [attr.rowspan]="2">
|
|
25448
|
-
<span class="sr-only">{{ t('grid.actionsLabel', { label: '' }) }}</span>
|
|
25449
|
-
</th>
|
|
25450
|
-
}
|
|
25451
|
-
</tr>
|
|
25452
|
-
}
|
|
25453
|
-
|
|
25454
|
-
<tr>
|
|
25455
|
-
@if (!hasGroupedHeaders && resolvedOptions().selectable) {
|
|
25456
|
-
<th class="jv-grid-th jv-grid-th-select" scope="col">
|
|
25457
|
-
<input
|
|
25458
|
-
type="checkbox"
|
|
25459
|
-
class="jv-grid-checkbox"
|
|
25460
|
-
[checked]="allSelected()"
|
|
25461
|
-
(change)="toggleSelectAll($any($event.target).checked)"
|
|
25462
|
-
[attr.aria-label]="allSelected() ? t('grid.deselectAll') : t('grid.selectAll')"
|
|
25463
|
-
[indeterminate]="someSelected()"
|
|
25464
|
-
/>
|
|
25465
|
-
</th>
|
|
25466
|
-
}
|
|
25467
|
-
@for (col of visibleColumns(); track colKey(col); let colIdx = $index) {
|
|
25468
|
-
<th
|
|
25469
|
-
class="jv-grid-th"
|
|
25470
|
-
[class]="col.headerClass || ''"
|
|
25471
|
-
[class.jv-grid-th-sortable]="col.sortable !== false && resolvedOptions().sortable"
|
|
25472
|
-
[class.jv-grid-th-sticky-left]="isStickyLeft(col)"
|
|
25473
|
-
[class.jv-grid-th-sticky-right]="isStickyRight(col)"
|
|
25474
|
-
[class.jv-grid-th-reorderable]="resolvedOptions().reorderableColumns"
|
|
25475
|
-
[style.text-align]="col.align ?? 'start'"
|
|
25476
|
-
[style.width]="getColumnWidth(col)"
|
|
25477
|
-
[style.min-width]="col.minWidth || undefined"
|
|
25478
|
-
[style.max-width]="col.maxWidth || undefined"
|
|
25479
|
-
scope="col"
|
|
25480
|
-
role="columnheader"
|
|
25481
|
-
[attr.data-column-index]="colIdx"
|
|
25482
|
-
[attr.aria-sort]="getAriaSort(col)"
|
|
25483
|
-
[attr.aria-label]="getSortLabel(col)"
|
|
25484
|
-
[tabindex]="resolvedOptions().keyboardNavigation ? (activeCell().column === colIdx ? 0 : -1) : (col.sortable !== false && resolvedOptions().sortable ? 0 : -1)"
|
|
25485
|
-
(click)="toggleSort(col)"
|
|
25486
|
-
(focus)="onHeaderFocus(colIdx)"
|
|
25487
|
-
(keydown)="onHeaderKeydown($event, colIdx)"
|
|
25488
|
-
(keydown.enter)="toggleSort(col)"
|
|
25489
|
-
(keydown.space)="toggleSort(col, $event)"
|
|
25490
|
-
draggable="{{ resolvedOptions().reorderableColumns ? 'true' : 'false' }}"
|
|
25491
|
-
(dragstart)="onDragStart($event, colIdx)"
|
|
25492
|
-
(dragover)="onDragOver($event, colIdx)"
|
|
25493
|
-
(drop)="onDrop($event, colIdx)"
|
|
25494
|
-
(dragend)="onDragEnd($event)"
|
|
25495
|
-
>
|
|
25496
|
-
<div class="jv-grid-th-content">
|
|
25497
|
-
<span>{{ col.header }}</span>
|
|
25498
|
-
@if (col.sortable !== false && resolvedOptions().sortable) {
|
|
25499
|
-
<span class="jv-grid-sort-icon" aria-hidden="true">
|
|
25500
|
-
@if (sortState().columnKey === colKey(col)) {
|
|
25501
|
-
@if (sortState().direction === 'asc') { ▲ }
|
|
25502
|
-
@if (sortState().direction === 'desc') { ▼ }
|
|
25503
|
-
}
|
|
25504
|
-
</span>
|
|
25505
|
-
}
|
|
25506
|
-
</div>
|
|
25507
|
-
@if (isColumnResizable(col)) {
|
|
25508
|
-
<div
|
|
25509
|
-
class="jv-grid-resize-handle"
|
|
25510
|
-
(mousedown)="onResizeStart($event, col, colIdx)"
|
|
25511
|
-
></div>
|
|
25512
|
-
}
|
|
25513
|
-
</th>
|
|
25514
|
-
}
|
|
25515
|
-
@if (!hasGroupedHeaders && actions().length > 0) {
|
|
25516
|
-
<th class="jv-grid-th jv-grid-th-actions" scope="col">
|
|
25517
|
-
<span class="sr-only">{{ t('grid.actionsLabel', { label: '' }) }}</span>
|
|
25518
|
-
</th>
|
|
25519
|
-
}
|
|
25520
|
-
</tr>
|
|
25521
|
-
|
|
25522
|
-
@if (resolvedOptions().columnFilters) {
|
|
25523
|
-
<tr class="jv-grid-filter-row">
|
|
25524
|
-
@if (resolvedOptions().selectable) {
|
|
25525
|
-
<th class="jv-grid-th jv-grid-th-select"></th>
|
|
25526
|
-
}
|
|
25527
|
-
@for (col of visibleColumns(); track colKey(col)) {
|
|
25528
|
-
<th class="jv-grid-th jv-grid-th-filter">
|
|
25529
|
-
@if (col.filterable !== false) {
|
|
25530
|
-
<input
|
|
25531
|
-
class="jv-grid-filter-input"
|
|
25532
|
-
[placeholder]="t('grid.filterPlaceholder')"
|
|
25533
|
-
[attr.aria-label]="t('grid.filterForColumn', { column: col.header })"
|
|
25534
|
-
[ngModel]="colFilters()[colKey(col)]?.value ?? ''"
|
|
25535
|
-
(ngModelChange)="onColumnFilterChange(col, $event)"
|
|
25536
|
-
/>
|
|
25537
|
-
}
|
|
25538
|
-
</th>
|
|
25539
|
-
}
|
|
25540
|
-
@if (actions().length > 0) {
|
|
25541
|
-
<th class="jv-grid-th jv-grid-th-actions"></th>
|
|
25542
|
-
}
|
|
25543
|
-
</tr>
|
|
25544
|
-
}
|
|
25545
|
-
</thead>
|
|
25546
|
-
|
|
25547
|
-
<tbody class="jv-grid-tbody">
|
|
25548
|
-
@if (displayData().length === 0 && !searchTerm().trim() && !hasActiveFilters()) {
|
|
25549
|
-
<tr>
|
|
25550
|
-
<td class="jv-grid-empty" [attr.colspan]="colspan()">
|
|
25551
|
-
{{ resolvedOptions().emptyMessage || t('grid.emptyMessage') }}
|
|
25552
|
-
</td>
|
|
25553
|
-
</tr>
|
|
25554
|
-
} @else if (displayData().length === 0 && (searchTerm().trim() || hasActiveFilters())) {
|
|
25555
|
-
<tr>
|
|
25556
|
-
<td class="jv-grid-empty" [attr.colspan]="colspan()">
|
|
25557
|
-
{{ resolvedOptions().noResultsMessage || t('grid.noResults') }}
|
|
25558
|
-
</td>
|
|
25559
|
-
</tr>
|
|
25560
|
-
} @else {
|
|
25561
|
-
@for (row of displayData(); track getRowId(row, $index); let rowIdx = $index) {
|
|
25562
|
-
<tr
|
|
25563
|
-
class="jv-grid-tr"
|
|
25564
|
-
role="row"
|
|
25565
|
-
[class.jv-grid-tr-editing]="isRowEditing(row)"
|
|
25566
|
-
[class.jv-grid-tr-selected]="isSelected(row)"
|
|
25567
|
-
[attr.aria-selected]="resolvedOptions().selectable ? isSelected(row) : null"
|
|
25568
|
-
(click)="onRowClick(row)"
|
|
25569
|
-
(dblclick)="onRowDblClick(row)"
|
|
25570
|
-
(keydown.enter)="onRowClick(row)"
|
|
25571
|
-
(keydown.space)="onRowClick($event, row)"
|
|
25572
|
-
[tabindex]="-1"
|
|
25573
|
-
>
|
|
25574
|
-
@if (resolvedOptions().selectable) {
|
|
25575
|
-
<td
|
|
25576
|
-
class="jv-grid-td jv-grid-td-select"
|
|
25577
|
-
[class.jv-grid-td-sticky-left]="resolvedOptions().stickyColumns"
|
|
25578
|
-
>
|
|
25579
|
-
<input
|
|
25580
|
-
type="checkbox"
|
|
25581
|
-
class="jv-grid-checkbox"
|
|
25582
|
-
[checked]="isSelected(row)"
|
|
25583
|
-
(change)="toggleRow(row); $event.stopPropagation()"
|
|
25584
|
-
(keydown.space)="$event.stopPropagation()"
|
|
25585
|
-
[attr.aria-label]="getRowLabel(row, $index)"
|
|
25586
|
-
/>
|
|
25587
|
-
</td>
|
|
25588
|
-
}
|
|
25589
|
-
@for (col of visibleColumns(); track colKey(col); let colIdx = $index) {
|
|
25590
|
-
<td
|
|
25591
|
-
class="jv-grid-td"
|
|
25592
|
-
[attr.role]="resolvedOptions().keyboardNavigation ? 'gridcell' : null"
|
|
25593
|
-
[class]="col.cellClass || ''"
|
|
25594
|
-
[class.jv-grid-td-sticky-left]="isStickyLeft(col)"
|
|
25595
|
-
[class.jv-grid-td-sticky-right]="isStickyRight(col)"
|
|
25596
|
-
[class.jv-grid-td-editable]="isCellEditable(col)"
|
|
25597
|
-
[style.text-align]="col.align ?? 'start'"
|
|
25598
|
-
(dblclick)="startEdit(row, col, $event)"
|
|
25599
|
-
(keydown.enter)="startEdit(row, col, $event)"
|
|
25600
|
-
[attr.data-row-index]="rowIdx"
|
|
25601
|
-
[attr.data-column-index]="colIdx"
|
|
25602
|
-
[class.jv-grid-keyboard-cell]="resolvedOptions().keyboardNavigation"
|
|
25603
|
-
[attr.tabindex]="cellTabIndex(rowIdx, colIdx, col)"
|
|
25604
|
-
(focus)="onCellFocus(rowIdx, colIdx)"
|
|
25605
|
-
(keydown.f2)="onCellF2($event, rowIdx, colIdx)"
|
|
25606
|
-
(keydown)="onCellKeydown($event, rowIdx, colIdx)"
|
|
25607
|
-
>
|
|
25608
|
-
@if (isEditingCell(row, col)) {
|
|
25609
|
-
@if (editType(col) === 'select' && col.editOptions) {
|
|
25610
|
-
<jv-select
|
|
25611
|
-
[options]="getEditOptions(col)"
|
|
25612
|
-
[modelValue]="getEditValue(row, col)"
|
|
25613
|
-
(selectionChange)="onEditValueChange(row, col, $event)"
|
|
25614
|
-
/>
|
|
25615
|
-
} @else if (editType(col) === 'boolean') {
|
|
25616
|
-
<input
|
|
25617
|
-
type="checkbox"
|
|
25618
|
-
class="jv-grid-checkbox"
|
|
25619
|
-
[checked]="getBooleanEditValue(row, col)"
|
|
25620
|
-
(change)="commitEdit(row, col, normalizeEditValue(col, $any($event.target).checked))"
|
|
25621
|
-
(keydown.enter)="commitEditFromKeyboard($event, row, col, normalizeEditValue(col, $any($event.target).checked))"
|
|
25622
|
-
(keydown.escape)="cancelEdit()"
|
|
25623
|
-
[attr.aria-label]="col.header"
|
|
25624
|
-
/>
|
|
25625
|
-
} @else {
|
|
25626
|
-
<input
|
|
25627
|
-
class="jv-grid-edit-input"
|
|
25628
|
-
[type]="inputType(col)"
|
|
25629
|
-
[value]="getEditValue(row, col)"
|
|
25630
|
-
(blur)="commitEdit(row, col, normalizeEditValue(col, $any($event.target).value))"
|
|
25631
|
-
(keydown.enter)="commitEditFromKeyboard($event, row, col, normalizeEditValue(col, $any($event.target).value))"
|
|
25632
|
-
(keydown.escape)="cancelEdit()"
|
|
25633
|
-
/>
|
|
25634
|
-
}
|
|
25635
|
-
} @else {
|
|
25636
|
-
@let value = getCellValue(row, col);
|
|
25637
|
-
@if (col.type === 'boolean') {
|
|
25638
|
-
@if (isBooleanTrue(value)) {
|
|
25639
|
-
<span class="jv-grid-boolean jv-grid-boolean-true" [attr.aria-label]="t('grid.booleanYes')">{{ t('grid.booleanYes') }}</span>
|
|
25640
|
-
} @else {
|
|
25641
|
-
<span class="jv-grid-boolean jv-grid-boolean-false" [attr.aria-label]="t('grid.booleanNo')">{{ t('grid.booleanNo') }}</span>
|
|
25642
|
-
}
|
|
25643
|
-
} @else if (col.format) {
|
|
25644
|
-
{{ col.format(value, row) }}
|
|
25645
|
-
} @else {
|
|
25646
|
-
{{ formatValue(value, col, row) }}
|
|
25647
|
-
}
|
|
25648
|
-
}
|
|
25649
|
-
</td>
|
|
25650
|
-
}
|
|
25651
|
-
@if (actions().length > 0) {
|
|
25652
|
-
<td
|
|
25653
|
-
class="jv-grid-td jv-grid-td-actions"
|
|
25654
|
-
[class.jv-grid-td-sticky-right]="resolvedOptions().stickyColumns"
|
|
25655
|
-
>
|
|
25656
|
-
<div class="jv-grid-actions-group">
|
|
25657
|
-
@for (action of actions(); track action.id) {
|
|
25658
|
-
<jv-button
|
|
25659
|
-
[variant]="actionVariant(action.variant)"
|
|
25660
|
-
[icon]="action.icon ?? null"
|
|
25661
|
-
[disabled]="action.disabled?.(row) ?? false"
|
|
25662
|
-
[attr.aria-label]="action.label"
|
|
25663
|
-
[title]="action.label"
|
|
25664
|
-
(click)="onActionClick(action, row); $event.stopPropagation()"
|
|
25665
|
-
></jv-button>
|
|
25666
|
-
}
|
|
25667
|
-
</div>
|
|
25668
|
-
</td>
|
|
25669
|
-
}
|
|
25670
|
-
</tr>
|
|
25671
|
-
}
|
|
25672
|
-
}
|
|
25673
|
-
</tbody>
|
|
25674
|
-
</table>
|
|
25675
|
-
</div>
|
|
25676
|
-
}
|
|
25677
|
-
|
|
25678
|
-
@if (resolvedOptions().pageable && !virtualScrollEnabled() && effectiveTotalPages() > 1 && !resolvedOptions().loading) {
|
|
25679
|
-
<nav class="jv-grid-pagination" role="navigation" [attr.aria-label]="t('grid.paginationLabel', { label: '' })">
|
|
25680
|
-
<div class="jv-grid-pagination-info" aria-live="polite" aria-atomic="true">
|
|
25681
|
-
{{ t('grid.itemsShowing', { start: pageStart(), end: pageEnd(), total: effectiveTotalItems() }) }}
|
|
25682
|
-
</div>
|
|
25683
|
-
<div class="jv-grid-pagination-controls">
|
|
25684
|
-
@if (pageSizeOptions().length > 0) {
|
|
25685
|
-
<jv-select
|
|
25686
|
-
[options]="pageSizeOptions()"
|
|
25687
|
-
[modelValue]="pageSizeStr()"
|
|
25688
|
-
[ariaLabel]="t('grid.itemsPerPage')"
|
|
25689
|
-
(selectionChange)="onPageSizeChange($event)"
|
|
25690
|
-
/>
|
|
25691
|
-
}
|
|
25692
|
-
<jv-button
|
|
25693
|
-
variant="outline"
|
|
25694
|
-
icon="chevrons-left"
|
|
25695
|
-
[disabled]="pageIndex() === 0"
|
|
25696
|
-
(click)="goToPage(0)"
|
|
25697
|
-
[attr.aria-label]="t('grid.pageFirst')"
|
|
25698
|
-
></jv-button>
|
|
25699
|
-
<jv-button
|
|
25700
|
-
variant="outline"
|
|
25701
|
-
icon="chevron-left"
|
|
25702
|
-
[disabled]="pageIndex() === 0"
|
|
25703
|
-
(click)="goToPage(pageIndex() - 1)"
|
|
25704
|
-
[attr.aria-label]="t('grid.pagePrev')"
|
|
25705
|
-
></jv-button>
|
|
25706
|
-
@for (p of pageRange(); track p) {
|
|
25707
|
-
<jv-button
|
|
25708
|
-
[variant]="p === pageIndex() ? 'primary' : 'outline'"
|
|
25709
|
-
[attr.aria-current]="p === pageIndex() ? 'page' : null"
|
|
25710
|
-
[attr.aria-label]="t('grid.pageOfTotal', { page: p + 1, total: effectiveTotalPages() })"
|
|
25711
|
-
(click)="goToPage(p)"
|
|
25712
|
-
>{{ p + 1 }}</jv-button>
|
|
25713
|
-
}
|
|
25714
|
-
<jv-button
|
|
25715
|
-
variant="outline"
|
|
25716
|
-
icon="chevron-right"
|
|
25717
|
-
[disabled]="pageIndex() >= effectiveTotalPages() - 1"
|
|
25718
|
-
(click)="goToPage(pageIndex() + 1)"
|
|
25719
|
-
[attr.aria-label]="t('grid.pageNext')"
|
|
25720
|
-
></jv-button>
|
|
25721
|
-
<jv-button
|
|
25722
|
-
variant="outline"
|
|
25723
|
-
icon="chevrons-right"
|
|
25724
|
-
[disabled]="pageIndex() >= effectiveTotalPages() - 1"
|
|
25725
|
-
(click)="goToPage(effectiveTotalPages() - 1)"
|
|
25726
|
-
[attr.aria-label]="t('grid.pageLast')"
|
|
25727
|
-
></jv-button>
|
|
25728
|
-
</div>
|
|
25729
|
-
</nav>
|
|
25730
|
-
}
|
|
25731
|
-
</div>
|
|
25732
|
-
`, isInline: true, styles: [".jv-grid{display:flex;flex-direction:column;gap:var(--jv-spacing-md)}.jv-grid-toolbar{display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-md);flex-wrap:wrap}.jv-grid-search{display:flex;align-items:center;gap:var(--jv-spacing-sm)}.jv-grid-export-actions{display:flex;align-items:center;gap:var(--jv-spacing-xs)}.jv-grid-table-wrap{overflow-x:auto;overflow-y:auto;-webkit-overflow-scrolling:touch;border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-md);position:relative}.jv-grid-virtual{max-height:600px}.jv-grid-virtual-spacer{pointer-events:none}.jv-grid-table{width:100%;border-collapse:collapse;background:var(--jv-color-surface)}.jv-grid-thead{background:var(--jv-color-surface-muted)}.jv-grid-th{padding:var(--jv-spacing-sm) var(--jv-spacing-md);font-weight:600;font-size:.875rem;color:var(--jv-color-foreground-muted);text-align:start;white-space:nowrap;border-bottom:1px solid var(--jv-color-border);-webkit-user-select:none;user-select:none;position:relative}.jv-grid-th-sortable{cursor:pointer}.jv-grid-th-sortable:hover{background:var(--jv-color-surface)}.jv-grid-th-reorderable{cursor:grab}.jv-grid-th-reorderable:active{cursor:grabbing}.jv-grid-th-sticky-left{position:sticky;left:0;z-index:2;background:var(--jv-color-surface-muted);border-right:1px solid var(--jv-color-border)}.jv-grid-th-sticky-right{position:sticky;right:0;z-index:2;background:var(--jv-color-surface-muted);border-left:1px solid var(--jv-color-border)}.jv-grid-th-content{display:flex;align-items:center;gap:var(--jv-spacing-xs)}.jv-grid-sort-icon{font-size:.75rem;line-height:1}.jv-grid-th-select,.jv-grid-td-select{width:3rem;text-align:center}.jv-grid-th-actions,.jv-grid-td-actions{width:1%;white-space:nowrap}.jv-grid-td{padding:var(--jv-spacing-sm) var(--jv-spacing-md);color:var(--jv-color-foreground);font-size:var(--jv-density-font-size);border-bottom:1px solid var(--jv-color-border)}.jv-grid-keyboard-cell:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:-2px}.jv-grid-td-sticky-left{position:sticky;left:0;z-index:1;background:var(--jv-color-surface);border-right:1px solid var(--jv-color-border)}.jv-grid-td-sticky-right{position:sticky;right:0;z-index:1;background:var(--jv-color-surface);border-left:1px solid var(--jv-color-border)}.jv-grid-t:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:-2px}.jv-grid-tr{transition:background-color .12s ease}.jv-grid-tr:hover{background:var(--jv-color-surface-muted)}.jv-grid-tr:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:-2px}.jv-grid-tr-editing{background:var(--jv-color-surface-highlight, rgba(59, 130, 246, .05))}.jv-grid-tr-selected{background:var(--jv-color-primary-light, rgba(59, 130, 246, .08))}.jv-grid-checkbox{width:1rem;height:1rem;accent-color:var(--jv-color-primary);cursor:pointer}.jv-grid-boolean{display:inline-flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;border-radius:999px;font-size:.75rem;font-weight:700}.jv-grid-boolean-true{background:var(--jv-color-success);color:#fff}.jv-grid-boolean-false{background:var(--jv-color-danger);color:#fff}.jv-grid-empty{padding:var(--jv-spacing-xl) var(--jv-spacing-md);text-align:center;color:var(--jv-color-foreground-muted);font-style:italic}.jv-grid-actions-group{display:flex;align-items:center;gap:var(--jv-spacing-xs)}.jv-grid-loading{display:flex;align-items:center;justify-content:center;gap:var(--jv-spacing-md);padding:var(--jv-spacing-xl);color:var(--jv-color-foreground-muted)}.jv-grid-spinner{width:1.25rem;height:1.25rem;border:2px solid var(--jv-color-border);border-right-color:var(--jv-color-primary);border-radius:999px;animation:jv-grid-spin .8s linear infinite}@keyframes jv-grid-spin{to{transform:rotate(360deg)}}.jv-grid-pagination{display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-md);flex-wrap:wrap}.jv-grid-pagination-info{font-size:.875rem;color:var(--jv-color-foreground-muted)}.jv-grid-pagination-controls{display:flex;align-items:center;gap:var(--jv-spacing-xs);flex-wrap:wrap}@media(max-width:640px){.jv-grid-pagination{flex-direction:column;align-items:stretch;gap:var(--jv-spacing-sm)}.jv-grid-pagination-info{text-align:center}.jv-grid-pagination-controls{justify-content:center}.jv-grid-toolbar{flex-direction:column;align-items:stretch}.jv-grid-search{width:100%}.jv-grid-export-actions{justify-content:stretch}.jv-grid-export-actions jv-button{flex:1}}.jv-grid-resize-handle{position:absolute;top:0;right:0;width:4px;height:100%;cursor:col-resize;background:transparent;z-index:3}.jv-grid-resize-handle:hover,.jv-grid-resize-handle:active{background:var(--jv-color-primary)}.jv-grid-filter-row .jv-grid-th{padding:var(--jv-spacing-xs) var(--jv-spacing-sm)}.jv-grid-filter-input{width:100%;min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-sm);border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-sm);background:var(--jv-color-surface);color:var(--jv-color-foreground);font-size:.8rem;box-sizing:border-box}.jv-grid-td-editable{cursor:pointer}.jv-grid-td-editable:hover{box-shadow:inset 0 0 0 1px var(--jv-color-primary)}.jv-grid-edit-input{width:100%;min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-sm);border:1px solid var(--jv-color-primary);border-radius:var(--jv-radius-sm);background:var(--jv-color-surface);color:var(--jv-color-foreground);font-size:var(--jv-density-font-size);box-sizing:border-box}.jv-grid-edit-input:focus{outline:2px solid var(--jv-color-primary);outline-offset:-1px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: JvButtonComponent, selector: "jv-button", inputs: ["type", "variant", "icon", "iconPosition", "loading", "disabled"] }, { kind: "component", type: JvIconComponent, selector: "jv-icon", inputs: ["name", "size", "strokeWidth", "decorative", "ariaLabel"] }, { kind: "component", type: JvInputComponent, selector: "jv-input", inputs: ["type", "placeholder", "required", "invalid", "describedBy", "inputId"] }, { kind: "component", type: JvSelectComponent, selector: "jv-select", inputs: ["options", "placeholder", "required", "invalid", "describedBy", "ariaLabel", "inputId", "modelValue"], outputs: ["selectionChange"] }] });
|
|
25781
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: JvGridComponent, isStandalone: true, selector: "jv-grid", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, trackBy: { classPropertyName: "trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null }, selectedIds: { classPropertyName: "selectedIds", publicName: "selectedIds", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rowClick: "rowClick", rowDoubleClick: "rowDoubleClick", actionClick: "actionClick", selectionChange: "selectionChange", pageChange: "pageChange", searchChange: "searchChange", sortChange: "sortChange", columnFilter: "columnFilter", columnResize: "columnResize", columnReorder: "columnReorder", rowEdit: "rowEdit" }, ngImport: i0, template: "<div class=\"jv-grid\" role=\"region\" [attr.aria-label]=\"resolvedOptions().ariaLabel || gridLabel()\">\n @if (resolvedOptions().searchable || resolvedOptions().exportable) {\n <div class=\"jv-grid-toolbar\">\n @if (resolvedOptions().searchable) {\n <div class=\"jv-grid-search\">\n <jv-icon name=\"search\" [size]=\"16\" />\n <jv-input\n [inputId]=\"gridSearchInputId\"\n [placeholder]=\"t('grid.searchPlaceholder')\"\n [ngModel]=\"searchTerm()\"\n (ngModelChange)=\"onSearchInput($event)\"\n />\n </div>\n }\n @if (resolvedOptions().exportable) {\n <div class=\"jv-grid-export-actions\">\n <jv-button variant=\"outline\" icon=\"download\" (click)=\"exportCsv()\">{{\n t('grid.exportCsv')\n }}</jv-button>\n <jv-button variant=\"outline\" icon=\"file-spreadsheet\" (click)=\"exportExcel()\">{{\n t('grid.exportExcel')\n }}</jv-button>\n </div>\n }\n </div>\n }\n\n @if (resolvedOptions().loading) {\n <div class=\"jv-grid-loading\" role=\"status\" aria-live=\"polite\">\n <span class=\"jv-grid-spinner\" aria-hidden=\"true\"></span>\n <span>{{ t('grid.loading') }}</span>\n </div>\n } @else {\n <div\n class=\"jv-grid-table-wrap\"\n [class.jv-grid-virtual]=\"virtualScrollEnabled()\"\n #tableWrap\n (scroll)=\"onVirtualScroll($any($event.target))\"\n >\n @if (virtualScrollEnabled()) {\n <div class=\"jv-grid-virtual-spacer\" [style.height.px]=\"virtualTotalHeight()\"></div>\n }\n <table\n class=\"jv-grid-table\"\n role=\"grid\"\n [attr.aria-label]=\"resolvedOptions().ariaLabel || gridLabel()\"\n [attr.aria-rowcount]=\"effectiveTotalItems()\"\n [attr.aria-colcount]=\"colspan()\"\n [class]=\"densityClass()\"\n [style.position]=\"virtualScrollEnabled() ? 'relative' : null\"\n [style.top.px]=\"virtualOffsetY()\"\n >\n <caption class=\"sr-only\">\n {{\n resolvedOptions().ariaLabel || gridLabel()\n }}\n </caption>\n\n @let hasGroupedHeaders = groupedHeaders().length > 0;\n\n <thead class=\"jv-grid-thead\">\n @if (hasGroupedHeaders) {\n <tr>\n @if (resolvedOptions().selectable) {\n <th class=\"jv-grid-th jv-grid-th-select\" scope=\"col\" [attr.rowspan]=\"2\">\n <input\n type=\"checkbox\"\n class=\"jv-grid-checkbox\"\n [checked]=\"allSelected()\"\n (change)=\"toggleSelectAll($any($event.target).checked)\"\n [attr.aria-label]=\"allSelected() ? t('grid.deselectAll') : t('grid.selectAll')\"\n [indeterminate]=\"someSelected()\"\n />\n </th>\n }\n @for (group of groupedHeaders(); track colKey(group)) {\n <th\n class=\"jv-grid-th\"\n [class]=\"group.headerClass || ''\"\n [class.jv-grid-th-sticky-left]=\"isStickyLeft(group)\"\n [class.jv-grid-th-sticky-right]=\"isStickyRight(group)\"\n [attr.colspan]=\"groupColspan(group)\"\n scope=\"colgroup\"\n [style.text-align]=\"group.align ?? 'start'\"\n >\n <div class=\"jv-grid-th-content\">{{ group.header }}</div>\n </th>\n }\n @if (actions().length > 0) {\n <th class=\"jv-grid-th jv-grid-th-actions\" scope=\"col\" [attr.rowspan]=\"2\">\n <span class=\"sr-only\">{{ t('grid.actionsLabel', { label: '' }) }}</span>\n </th>\n }\n </tr>\n }\n\n <tr>\n @if (!hasGroupedHeaders && resolvedOptions().selectable) {\n <th class=\"jv-grid-th jv-grid-th-select\" scope=\"col\">\n <input\n type=\"checkbox\"\n class=\"jv-grid-checkbox\"\n [checked]=\"allSelected()\"\n (change)=\"toggleSelectAll($any($event.target).checked)\"\n [attr.aria-label]=\"allSelected() ? t('grid.deselectAll') : t('grid.selectAll')\"\n [indeterminate]=\"someSelected()\"\n />\n </th>\n }\n @for (col of visibleColumns(); track colKey(col); let colIdx = $index) {\n <th\n class=\"jv-grid-th\"\n [class]=\"col.headerClass || ''\"\n [class.jv-grid-th-sortable]=\"col.sortable !== false && resolvedOptions().sortable\"\n [class.jv-grid-th-sticky-left]=\"isStickyLeft(col)\"\n [class.jv-grid-th-sticky-right]=\"isStickyRight(col)\"\n [class.jv-grid-th-reorderable]=\"resolvedOptions().reorderableColumns\"\n [style.text-align]=\"col.align ?? 'start'\"\n [style.width]=\"getColumnWidth(col)\"\n [style.min-width]=\"col.minWidth || undefined\"\n [style.max-width]=\"col.maxWidth || undefined\"\n scope=\"col\"\n role=\"columnheader\"\n [attr.data-column-index]=\"colIdx\"\n [attr.aria-sort]=\"getAriaSort(col)\"\n [attr.aria-label]=\"getSortLabel(col)\"\n [tabindex]=\"\n resolvedOptions().keyboardNavigation\n ? activeCell().column === colIdx\n ? 0\n : -1\n : col.sortable !== false && resolvedOptions().sortable\n ? 0\n : -1\n \"\n (click)=\"toggleSort(col)\"\n (focus)=\"onHeaderFocus(colIdx)\"\n (keydown)=\"onHeaderKeydown($event, colIdx)\"\n (keydown.enter)=\"toggleSort(col)\"\n (keydown.space)=\"toggleSort(col, $event)\"\n draggable=\"{{ resolvedOptions().reorderableColumns ? 'true' : 'false' }}\"\n (dragstart)=\"onDragStart($event, colIdx)\"\n (dragover)=\"onDragOver($event, colIdx)\"\n (drop)=\"onDrop($event, colIdx)\"\n (dragend)=\"onDragEnd($event)\"\n >\n <div class=\"jv-grid-th-content\">\n <span>{{ col.header }}</span>\n @if (col.sortable !== false && resolvedOptions().sortable) {\n <span class=\"jv-grid-sort-icon\" aria-hidden=\"true\">\n @if (sortState().columnKey === colKey(col)) {\n @if (sortState().direction === 'asc') {\n \u25B2\n }\n @if (sortState().direction === 'desc') {\n \u25BC\n }\n }\n </span>\n }\n </div>\n @if (isColumnResizable(col)) {\n <div\n class=\"jv-grid-resize-handle\"\n (mousedown)=\"onResizeStart($event, col, colIdx)\"\n ></div>\n }\n </th>\n }\n @if (!hasGroupedHeaders && actions().length > 0) {\n <th class=\"jv-grid-th jv-grid-th-actions\" scope=\"col\">\n <span class=\"sr-only\">{{ t('grid.actionsLabel', { label: '' }) }}</span>\n </th>\n }\n </tr>\n\n @if (resolvedOptions().columnFilters) {\n <tr class=\"jv-grid-filter-row\">\n @if (resolvedOptions().selectable) {\n <th class=\"jv-grid-th jv-grid-th-select\"></th>\n }\n @for (col of visibleColumns(); track colKey(col)) {\n <th class=\"jv-grid-th jv-grid-th-filter\">\n @if (col.filterable !== false) {\n <input\n class=\"jv-grid-filter-input\"\n [placeholder]=\"t('grid.filterPlaceholder')\"\n [attr.aria-label]=\"t('grid.filterForColumn', { column: col.header })\"\n [ngModel]=\"colFilters()[colKey(col)]?.value ?? ''\"\n (ngModelChange)=\"onColumnFilterChange(col, $event)\"\n />\n }\n </th>\n }\n @if (actions().length > 0) {\n <th class=\"jv-grid-th jv-grid-th-actions\"></th>\n }\n </tr>\n }\n </thead>\n\n <tbody class=\"jv-grid-tbody\">\n @if (displayData().length === 0 && !searchTerm().trim() && !hasActiveFilters()) {\n <tr>\n <td class=\"jv-grid-empty\" [attr.colspan]=\"colspan()\">\n {{ resolvedOptions().emptyMessage || t('grid.emptyMessage') }}\n </td>\n </tr>\n } @else if (displayData().length === 0 && (searchTerm().trim() || hasActiveFilters())) {\n <tr>\n <td class=\"jv-grid-empty\" [attr.colspan]=\"colspan()\">\n {{ resolvedOptions().noResultsMessage || t('grid.noResults') }}\n </td>\n </tr>\n } @else {\n @for (row of displayData(); track getRowId(row, $index); let rowIdx = $index) {\n <tr\n class=\"jv-grid-tr\"\n role=\"row\"\n [class.jv-grid-tr-editing]=\"isRowEditing(row)\"\n [class.jv-grid-tr-selected]=\"isSelected(row)\"\n [attr.aria-selected]=\"resolvedOptions().selectable ? isSelected(row) : null\"\n (click)=\"onRowClick(row)\"\n (dblclick)=\"onRowDblClick(row)\"\n (keydown.enter)=\"onRowClick(row)\"\n (keydown.space)=\"onRowClick($event, row)\"\n [tabindex]=\"-1\"\n >\n @if (resolvedOptions().selectable) {\n <td\n class=\"jv-grid-td jv-grid-td-select\"\n [class.jv-grid-td-sticky-left]=\"resolvedOptions().stickyColumns\"\n >\n <input\n type=\"checkbox\"\n class=\"jv-grid-checkbox\"\n [checked]=\"isSelected(row)\"\n (change)=\"toggleRow(row); $event.stopPropagation()\"\n (keydown.space)=\"$event.stopPropagation()\"\n [attr.aria-label]=\"getRowLabel(row, $index)\"\n />\n </td>\n }\n @for (col of visibleColumns(); track colKey(col); let colIdx = $index) {\n <td\n class=\"jv-grid-td\"\n [attr.role]=\"resolvedOptions().keyboardNavigation ? 'gridcell' : null\"\n [class]=\"col.cellClass || ''\"\n [class.jv-grid-td-sticky-left]=\"isStickyLeft(col)\"\n [class.jv-grid-td-sticky-right]=\"isStickyRight(col)\"\n [class.jv-grid-td-editable]=\"isCellEditable(col)\"\n [style.text-align]=\"col.align ?? 'start'\"\n (dblclick)=\"startEdit(row, col, $event)\"\n (keydown.enter)=\"startEdit(row, col, $event)\"\n [attr.data-row-index]=\"rowIdx\"\n [attr.data-column-index]=\"colIdx\"\n [class.jv-grid-keyboard-cell]=\"resolvedOptions().keyboardNavigation\"\n [attr.tabindex]=\"cellTabIndex(rowIdx, colIdx, col)\"\n (focus)=\"onCellFocus(rowIdx, colIdx)\"\n (keydown.f2)=\"onCellF2($event, rowIdx, colIdx)\"\n (keydown)=\"onCellKeydown($event, rowIdx, colIdx)\"\n >\n @if (isEditingCell(row, col)) {\n @if (editType(col) === 'select' && col.editOptions) {\n <jv-select\n [options]=\"getEditOptions(col)\"\n [modelValue]=\"getEditValue(row, col)\"\n (selectionChange)=\"onEditValueChange(row, col, $event)\"\n />\n } @else if (editType(col) === 'boolean') {\n <input\n type=\"checkbox\"\n class=\"jv-grid-checkbox\"\n [checked]=\"getBooleanEditValue(row, col)\"\n (change)=\"\n commitEdit(\n row,\n col,\n normalizeEditValue(col, $any($event.target).checked)\n )\n \"\n (keydown.enter)=\"\n commitEditFromKeyboard(\n $event,\n row,\n col,\n normalizeEditValue(col, $any($event.target).checked)\n )\n \"\n (keydown.escape)=\"cancelEdit()\"\n [attr.aria-label]=\"col.header\"\n />\n } @else {\n <input\n class=\"jv-grid-edit-input\"\n [type]=\"inputType(col)\"\n [value]=\"getEditValue(row, col)\"\n (blur)=\"\n commitEdit(row, col, normalizeEditValue(col, $any($event.target).value))\n \"\n (keydown.enter)=\"\n commitEditFromKeyboard(\n $event,\n row,\n col,\n normalizeEditValue(col, $any($event.target).value)\n )\n \"\n (keydown.escape)=\"cancelEdit()\"\n />\n }\n } @else {\n @let value = getCellValue(row, col);\n @if (col.type === 'boolean') {\n @if (isBooleanTrue(value)) {\n <span\n class=\"jv-grid-boolean jv-grid-boolean-true\"\n [attr.aria-label]=\"t('grid.booleanYes')\"\n >{{ t('grid.booleanYes') }}</span\n >\n } @else {\n <span\n class=\"jv-grid-boolean jv-grid-boolean-false\"\n [attr.aria-label]=\"t('grid.booleanNo')\"\n >{{ t('grid.booleanNo') }}</span\n >\n }\n } @else if (col.format) {\n {{ col.format(value, row) }}\n } @else {\n {{ formatValue(value, col, row) }}\n }\n }\n </td>\n }\n @if (actions().length > 0) {\n <td\n class=\"jv-grid-td jv-grid-td-actions\"\n [class.jv-grid-td-sticky-right]=\"resolvedOptions().stickyColumns\"\n >\n <div class=\"jv-grid-actions-group\">\n @for (action of actions(); track action.id) {\n <jv-button\n [variant]=\"actionVariant(action.variant)\"\n [icon]=\"action.icon ?? null\"\n [disabled]=\"action.disabled?.(row) ?? false\"\n [attr.aria-label]=\"action.label\"\n [title]=\"action.label\"\n (click)=\"onActionClick(action, row); $event.stopPropagation()\"\n ></jv-button>\n }\n </div>\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n }\n\n @if (\n resolvedOptions().pageable &&\n !virtualScrollEnabled() &&\n effectiveTotalPages() > 1 &&\n !resolvedOptions().loading\n ) {\n <nav\n class=\"jv-grid-pagination\"\n role=\"navigation\"\n [attr.aria-label]=\"t('grid.paginationLabel', { label: '' })\"\n >\n <div class=\"jv-grid-pagination-info\" aria-live=\"polite\" aria-atomic=\"true\">\n {{\n t('grid.itemsShowing', {\n start: pageStart(),\n end: pageEnd(),\n total: effectiveTotalItems(),\n })\n }}\n </div>\n <div class=\"jv-grid-pagination-controls\">\n @if (pageSizeOptions().length > 0) {\n <jv-select\n [options]=\"pageSizeOptions()\"\n [modelValue]=\"pageSizeStr()\"\n [ariaLabel]=\"t('grid.itemsPerPage')\"\n (selectionChange)=\"onPageSizeChange($event)\"\n />\n }\n <jv-button\n variant=\"outline\"\n icon=\"chevrons-left\"\n [disabled]=\"pageIndex() === 0\"\n (click)=\"goToPage(0)\"\n [attr.aria-label]=\"t('grid.pageFirst')\"\n ></jv-button>\n <jv-button\n variant=\"outline\"\n icon=\"chevron-left\"\n [disabled]=\"pageIndex() === 0\"\n (click)=\"goToPage(pageIndex() - 1)\"\n [attr.aria-label]=\"t('grid.pagePrev')\"\n ></jv-button>\n @for (p of pageRange(); track p) {\n <jv-button\n [variant]=\"p === pageIndex() ? 'primary' : 'outline'\"\n [attr.aria-current]=\"p === pageIndex() ? 'page' : null\"\n [attr.aria-label]=\"t('grid.pageOfTotal', { page: p + 1, total: effectiveTotalPages() })\"\n (click)=\"goToPage(p)\"\n >{{ p + 1 }}</jv-button\n >\n }\n <jv-button\n variant=\"outline\"\n icon=\"chevron-right\"\n [disabled]=\"pageIndex() >= effectiveTotalPages() - 1\"\n (click)=\"goToPage(pageIndex() + 1)\"\n [attr.aria-label]=\"t('grid.pageNext')\"\n ></jv-button>\n <jv-button\n variant=\"outline\"\n icon=\"chevrons-right\"\n [disabled]=\"pageIndex() >= effectiveTotalPages() - 1\"\n (click)=\"goToPage(effectiveTotalPages() - 1)\"\n [attr.aria-label]=\"t('grid.pageLast')\"\n ></jv-button>\n </div>\n </nav>\n }\n</div>\n", styles: [".jv-grid{display:flex;flex-direction:column;gap:var(--jv-spacing-md)}.jv-grid-toolbar{display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-md);flex-wrap:wrap}.jv-grid-search{display:flex;align-items:center;gap:var(--jv-spacing-sm)}.jv-grid-export-actions{display:flex;align-items:center;gap:var(--jv-spacing-xs)}.jv-grid-table-wrap{overflow-x:auto;overflow-y:auto;-webkit-overflow-scrolling:touch;border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-md);position:relative}.jv-grid-virtual{max-height:600px}.jv-grid-virtual-spacer{pointer-events:none}.jv-grid-table{width:100%;border-collapse:collapse;background:var(--jv-color-surface)}.jv-grid-thead{background:var(--jv-color-surface-muted)}.jv-grid-th{padding:var(--jv-spacing-sm) var(--jv-spacing-md);font-weight:600;font-size:.875rem;color:var(--jv-color-foreground-muted);text-align:start;white-space:nowrap;border-bottom:1px solid var(--jv-color-border);-webkit-user-select:none;user-select:none;position:relative}.jv-grid-th-sortable{cursor:pointer}.jv-grid-th-sortable:hover{background:var(--jv-color-surface)}.jv-grid-th-reorderable{cursor:grab}.jv-grid-th-reorderable:active{cursor:grabbing}.jv-grid-th-sticky-left{position:sticky;left:0;z-index:2;background:var(--jv-color-surface-muted);border-right:1px solid var(--jv-color-border)}.jv-grid-th-sticky-right{position:sticky;right:0;z-index:2;background:var(--jv-color-surface-muted);border-left:1px solid var(--jv-color-border)}.jv-grid-th-content{display:flex;align-items:center;gap:var(--jv-spacing-xs)}.jv-grid-sort-icon{font-size:.75rem;line-height:1}.jv-grid-th-select,.jv-grid-td-select{width:3rem;text-align:center}.jv-grid-th-actions,.jv-grid-td-actions{width:1%;white-space:nowrap}.jv-grid-td{padding:var(--jv-spacing-sm) var(--jv-spacing-md);color:var(--jv-color-foreground);font-size:var(--jv-density-font-size);border-bottom:1px solid var(--jv-color-border)}.jv-grid-keyboard-cell:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:-2px}.jv-grid-td-sticky-left{position:sticky;left:0;z-index:1;background:var(--jv-color-surface);border-right:1px solid var(--jv-color-border)}.jv-grid-td-sticky-right{position:sticky;right:0;z-index:1;background:var(--jv-color-surface);border-left:1px solid var(--jv-color-border)}.jv-grid-t:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:-2px}.jv-grid-tr{transition:background-color .12s ease}.jv-grid-tr:hover{background:var(--jv-color-surface-muted)}.jv-grid-tr:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:-2px}.jv-grid-tr-editing{background:var(--jv-color-surface-highlight, rgba(59, 130, 246, .05))}.jv-grid-tr-selected{background:var(--jv-color-primary-light, rgba(59, 130, 246, .08))}.jv-grid-checkbox{width:1rem;height:1rem;accent-color:var(--jv-color-primary);cursor:pointer}.jv-grid-boolean{display:inline-flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;border-radius:999px;font-size:.75rem;font-weight:700}.jv-grid-boolean-true{background:var(--jv-color-success);color:#fff}.jv-grid-boolean-false{background:var(--jv-color-danger);color:#fff}.jv-grid-empty{padding:var(--jv-spacing-xl) var(--jv-spacing-md);text-align:center;color:var(--jv-color-foreground-muted);font-style:italic}.jv-grid-actions-group{display:flex;align-items:center;gap:var(--jv-spacing-xs)}.jv-grid-loading{display:flex;align-items:center;justify-content:center;gap:var(--jv-spacing-md);padding:var(--jv-spacing-xl);color:var(--jv-color-foreground-muted)}.jv-grid-spinner{width:1.25rem;height:1.25rem;border:2px solid var(--jv-color-border);border-right-color:var(--jv-color-primary);border-radius:999px;animation:jv-grid-spin .8s linear infinite}@keyframes jv-grid-spin{to{transform:rotate(360deg)}}.jv-grid-pagination{display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-md);flex-wrap:wrap}.jv-grid-pagination-info{font-size:.875rem;color:var(--jv-color-foreground-muted)}.jv-grid-pagination-controls{display:flex;align-items:center;gap:var(--jv-spacing-xs);flex-wrap:wrap}@media(max-width:640px){.jv-grid-pagination{flex-direction:column;align-items:stretch;gap:var(--jv-spacing-sm)}.jv-grid-pagination-info{text-align:center}.jv-grid-pagination-controls{justify-content:center}.jv-grid-toolbar{flex-direction:column;align-items:stretch}.jv-grid-search{width:100%}.jv-grid-export-actions{justify-content:stretch}.jv-grid-export-actions jv-button{flex:1}}.jv-grid-resize-handle{position:absolute;top:0;right:0;width:4px;height:100%;cursor:col-resize;background:transparent;z-index:3}.jv-grid-resize-handle:hover,.jv-grid-resize-handle:active{background:var(--jv-color-primary)}.jv-grid-filter-row .jv-grid-th{padding:var(--jv-spacing-xs) var(--jv-spacing-sm)}.jv-grid-filter-input{width:100%;min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-sm);border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-sm);background:var(--jv-color-surface);color:var(--jv-color-foreground);font-size:.8rem;box-sizing:border-box}.jv-grid-td-editable{cursor:pointer}.jv-grid-td-editable:hover{box-shadow:inset 0 0 0 1px var(--jv-color-primary)}.jv-grid-edit-input{width:100%;min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-sm);border:1px solid var(--jv-color-primary);border-radius:var(--jv-radius-sm);background:var(--jv-color-surface);color:var(--jv-color-foreground);font-size:var(--jv-density-font-size);box-sizing:border-box}.jv-grid-edit-input:focus{outline:2px solid var(--jv-color-primary);outline-offset:-1px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: JvButtonComponent, selector: "jv-button", inputs: ["type", "variant", "icon", "iconPosition", "loading", "disabled"] }, { kind: "component", type: JvIconComponent, selector: "jv-icon", inputs: ["name", "size", "strokeWidth", "decorative", "ariaLabel"] }, { kind: "component", type: JvInputComponent, selector: "jv-input", inputs: ["type", "placeholder", "required", "invalid", "describedBy", "inputId"] }, { kind: "component", type: JvSelectComponent, selector: "jv-select", inputs: ["options", "placeholder", "required", "invalid", "describedBy", "ariaLabel", "inputId", "modelValue"], outputs: ["selectionChange"] }] });
|
|
25733
25782
|
}
|
|
25734
25783
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JvGridComponent, decorators: [{
|
|
25735
25784
|
type: Component,
|
|
25736
|
-
args: [{ selector: 'jv-grid', standalone: true, imports: [FormsModule, JvButtonComponent, JvIconComponent, JvInputComponent, JvSelectComponent], template: `
|
|
25737
|
-
<div class="jv-grid" role="region" [attr.aria-label]="resolvedOptions().ariaLabel || gridLabel()">
|
|
25738
|
-
@if (resolvedOptions().searchable || resolvedOptions().exportable) {
|
|
25739
|
-
<div class="jv-grid-toolbar">
|
|
25740
|
-
@if (resolvedOptions().searchable) {
|
|
25741
|
-
<div class="jv-grid-search">
|
|
25742
|
-
<jv-icon name="search" [size]="16" />
|
|
25743
|
-
<jv-input
|
|
25744
|
-
[inputId]="gridSearchInputId"
|
|
25745
|
-
[placeholder]="t('grid.searchPlaceholder')"
|
|
25746
|
-
[ngModel]="searchTerm()"
|
|
25747
|
-
(ngModelChange)="onSearchInput($event)"
|
|
25748
|
-
/>
|
|
25749
|
-
</div>
|
|
25750
|
-
}
|
|
25751
|
-
@if (resolvedOptions().exportable) {
|
|
25752
|
-
<div class="jv-grid-export-actions">
|
|
25753
|
-
<jv-button variant="outline" icon="download" (click)="exportCsv()">{{ t('grid.exportCsv') }}</jv-button>
|
|
25754
|
-
<jv-button variant="outline" icon="file-spreadsheet" (click)="exportExcel()">{{ t('grid.exportExcel') }}</jv-button>
|
|
25755
|
-
</div>
|
|
25756
|
-
}
|
|
25757
|
-
</div>
|
|
25758
|
-
}
|
|
25759
|
-
|
|
25760
|
-
@if (resolvedOptions().loading) {
|
|
25761
|
-
<div class="jv-grid-loading" role="status" aria-live="polite">
|
|
25762
|
-
<span class="jv-grid-spinner" aria-hidden="true"></span>
|
|
25763
|
-
<span>{{ t('grid.loading') }}</span>
|
|
25764
|
-
</div>
|
|
25765
|
-
} @else {
|
|
25766
|
-
<div
|
|
25767
|
-
class="jv-grid-table-wrap"
|
|
25768
|
-
[class.jv-grid-virtual]="virtualScrollEnabled()"
|
|
25769
|
-
#tableWrap
|
|
25770
|
-
(scroll)="onVirtualScroll($any($event.target))"
|
|
25771
|
-
>
|
|
25772
|
-
@if (virtualScrollEnabled()) {
|
|
25773
|
-
<div class="jv-grid-virtual-spacer" [style.height.px]="virtualTotalHeight()"></div>
|
|
25774
|
-
}
|
|
25775
|
-
<table
|
|
25776
|
-
class="jv-grid-table"
|
|
25777
|
-
role="grid"
|
|
25778
|
-
[attr.aria-label]="resolvedOptions().ariaLabel || gridLabel()"
|
|
25779
|
-
[attr.aria-rowcount]="effectiveTotalItems()"
|
|
25780
|
-
[attr.aria-colcount]="colspan()"
|
|
25781
|
-
[class]="densityClass()"
|
|
25782
|
-
[style.position]="virtualScrollEnabled() ? 'relative' : null"
|
|
25783
|
-
[style.top.px]="virtualOffsetY()"
|
|
25784
|
-
>
|
|
25785
|
-
<caption class="sr-only">{{ resolvedOptions().ariaLabel || gridLabel() }}</caption>
|
|
25786
|
-
|
|
25787
|
-
@let hasGroupedHeaders = groupedHeaders().length > 0;
|
|
25788
|
-
|
|
25789
|
-
<thead class="jv-grid-thead">
|
|
25790
|
-
@if (hasGroupedHeaders) {
|
|
25791
|
-
<tr>
|
|
25792
|
-
@if (resolvedOptions().selectable) {
|
|
25793
|
-
<th class="jv-grid-th jv-grid-th-select" scope="col" [attr.rowspan]="2">
|
|
25794
|
-
<input
|
|
25795
|
-
type="checkbox"
|
|
25796
|
-
class="jv-grid-checkbox"
|
|
25797
|
-
[checked]="allSelected()"
|
|
25798
|
-
(change)="toggleSelectAll($any($event.target).checked)"
|
|
25799
|
-
[attr.aria-label]="allSelected() ? t('grid.deselectAll') : t('grid.selectAll')"
|
|
25800
|
-
[indeterminate]="someSelected()"
|
|
25801
|
-
/>
|
|
25802
|
-
</th>
|
|
25803
|
-
}
|
|
25804
|
-
@for (group of groupedHeaders(); track colKey(group)) {
|
|
25805
|
-
<th
|
|
25806
|
-
class="jv-grid-th"
|
|
25807
|
-
[class]="group.headerClass || ''"
|
|
25808
|
-
[class.jv-grid-th-sticky-left]="isStickyLeft(group)"
|
|
25809
|
-
[class.jv-grid-th-sticky-right]="isStickyRight(group)"
|
|
25810
|
-
[attr.colspan]="groupColspan(group)"
|
|
25811
|
-
scope="colgroup"
|
|
25812
|
-
[style.text-align]="group.align ?? 'start'"
|
|
25813
|
-
>
|
|
25814
|
-
<div class="jv-grid-th-content">{{ group.header }}</div>
|
|
25815
|
-
</th>
|
|
25816
|
-
}
|
|
25817
|
-
@if (actions().length > 0) {
|
|
25818
|
-
<th class="jv-grid-th jv-grid-th-actions" scope="col" [attr.rowspan]="2">
|
|
25819
|
-
<span class="sr-only">{{ t('grid.actionsLabel', { label: '' }) }}</span>
|
|
25820
|
-
</th>
|
|
25821
|
-
}
|
|
25822
|
-
</tr>
|
|
25823
|
-
}
|
|
25824
|
-
|
|
25825
|
-
<tr>
|
|
25826
|
-
@if (!hasGroupedHeaders && resolvedOptions().selectable) {
|
|
25827
|
-
<th class="jv-grid-th jv-grid-th-select" scope="col">
|
|
25828
|
-
<input
|
|
25829
|
-
type="checkbox"
|
|
25830
|
-
class="jv-grid-checkbox"
|
|
25831
|
-
[checked]="allSelected()"
|
|
25832
|
-
(change)="toggleSelectAll($any($event.target).checked)"
|
|
25833
|
-
[attr.aria-label]="allSelected() ? t('grid.deselectAll') : t('grid.selectAll')"
|
|
25834
|
-
[indeterminate]="someSelected()"
|
|
25835
|
-
/>
|
|
25836
|
-
</th>
|
|
25837
|
-
}
|
|
25838
|
-
@for (col of visibleColumns(); track colKey(col); let colIdx = $index) {
|
|
25839
|
-
<th
|
|
25840
|
-
class="jv-grid-th"
|
|
25841
|
-
[class]="col.headerClass || ''"
|
|
25842
|
-
[class.jv-grid-th-sortable]="col.sortable !== false && resolvedOptions().sortable"
|
|
25843
|
-
[class.jv-grid-th-sticky-left]="isStickyLeft(col)"
|
|
25844
|
-
[class.jv-grid-th-sticky-right]="isStickyRight(col)"
|
|
25845
|
-
[class.jv-grid-th-reorderable]="resolvedOptions().reorderableColumns"
|
|
25846
|
-
[style.text-align]="col.align ?? 'start'"
|
|
25847
|
-
[style.width]="getColumnWidth(col)"
|
|
25848
|
-
[style.min-width]="col.minWidth || undefined"
|
|
25849
|
-
[style.max-width]="col.maxWidth || undefined"
|
|
25850
|
-
scope="col"
|
|
25851
|
-
role="columnheader"
|
|
25852
|
-
[attr.data-column-index]="colIdx"
|
|
25853
|
-
[attr.aria-sort]="getAriaSort(col)"
|
|
25854
|
-
[attr.aria-label]="getSortLabel(col)"
|
|
25855
|
-
[tabindex]="resolvedOptions().keyboardNavigation ? (activeCell().column === colIdx ? 0 : -1) : (col.sortable !== false && resolvedOptions().sortable ? 0 : -1)"
|
|
25856
|
-
(click)="toggleSort(col)"
|
|
25857
|
-
(focus)="onHeaderFocus(colIdx)"
|
|
25858
|
-
(keydown)="onHeaderKeydown($event, colIdx)"
|
|
25859
|
-
(keydown.enter)="toggleSort(col)"
|
|
25860
|
-
(keydown.space)="toggleSort(col, $event)"
|
|
25861
|
-
draggable="{{ resolvedOptions().reorderableColumns ? 'true' : 'false' }}"
|
|
25862
|
-
(dragstart)="onDragStart($event, colIdx)"
|
|
25863
|
-
(dragover)="onDragOver($event, colIdx)"
|
|
25864
|
-
(drop)="onDrop($event, colIdx)"
|
|
25865
|
-
(dragend)="onDragEnd($event)"
|
|
25866
|
-
>
|
|
25867
|
-
<div class="jv-grid-th-content">
|
|
25868
|
-
<span>{{ col.header }}</span>
|
|
25869
|
-
@if (col.sortable !== false && resolvedOptions().sortable) {
|
|
25870
|
-
<span class="jv-grid-sort-icon" aria-hidden="true">
|
|
25871
|
-
@if (sortState().columnKey === colKey(col)) {
|
|
25872
|
-
@if (sortState().direction === 'asc') { ▲ }
|
|
25873
|
-
@if (sortState().direction === 'desc') { ▼ }
|
|
25874
|
-
}
|
|
25875
|
-
</span>
|
|
25876
|
-
}
|
|
25877
|
-
</div>
|
|
25878
|
-
@if (isColumnResizable(col)) {
|
|
25879
|
-
<div
|
|
25880
|
-
class="jv-grid-resize-handle"
|
|
25881
|
-
(mousedown)="onResizeStart($event, col, colIdx)"
|
|
25882
|
-
></div>
|
|
25883
|
-
}
|
|
25884
|
-
</th>
|
|
25885
|
-
}
|
|
25886
|
-
@if (!hasGroupedHeaders && actions().length > 0) {
|
|
25887
|
-
<th class="jv-grid-th jv-grid-th-actions" scope="col">
|
|
25888
|
-
<span class="sr-only">{{ t('grid.actionsLabel', { label: '' }) }}</span>
|
|
25889
|
-
</th>
|
|
25890
|
-
}
|
|
25891
|
-
</tr>
|
|
25892
|
-
|
|
25893
|
-
@if (resolvedOptions().columnFilters) {
|
|
25894
|
-
<tr class="jv-grid-filter-row">
|
|
25895
|
-
@if (resolvedOptions().selectable) {
|
|
25896
|
-
<th class="jv-grid-th jv-grid-th-select"></th>
|
|
25897
|
-
}
|
|
25898
|
-
@for (col of visibleColumns(); track colKey(col)) {
|
|
25899
|
-
<th class="jv-grid-th jv-grid-th-filter">
|
|
25900
|
-
@if (col.filterable !== false) {
|
|
25901
|
-
<input
|
|
25902
|
-
class="jv-grid-filter-input"
|
|
25903
|
-
[placeholder]="t('grid.filterPlaceholder')"
|
|
25904
|
-
[attr.aria-label]="t('grid.filterForColumn', { column: col.header })"
|
|
25905
|
-
[ngModel]="colFilters()[colKey(col)]?.value ?? ''"
|
|
25906
|
-
(ngModelChange)="onColumnFilterChange(col, $event)"
|
|
25907
|
-
/>
|
|
25908
|
-
}
|
|
25909
|
-
</th>
|
|
25910
|
-
}
|
|
25911
|
-
@if (actions().length > 0) {
|
|
25912
|
-
<th class="jv-grid-th jv-grid-th-actions"></th>
|
|
25913
|
-
}
|
|
25914
|
-
</tr>
|
|
25915
|
-
}
|
|
25916
|
-
</thead>
|
|
25917
|
-
|
|
25918
|
-
<tbody class="jv-grid-tbody">
|
|
25919
|
-
@if (displayData().length === 0 && !searchTerm().trim() && !hasActiveFilters()) {
|
|
25920
|
-
<tr>
|
|
25921
|
-
<td class="jv-grid-empty" [attr.colspan]="colspan()">
|
|
25922
|
-
{{ resolvedOptions().emptyMessage || t('grid.emptyMessage') }}
|
|
25923
|
-
</td>
|
|
25924
|
-
</tr>
|
|
25925
|
-
} @else if (displayData().length === 0 && (searchTerm().trim() || hasActiveFilters())) {
|
|
25926
|
-
<tr>
|
|
25927
|
-
<td class="jv-grid-empty" [attr.colspan]="colspan()">
|
|
25928
|
-
{{ resolvedOptions().noResultsMessage || t('grid.noResults') }}
|
|
25929
|
-
</td>
|
|
25930
|
-
</tr>
|
|
25931
|
-
} @else {
|
|
25932
|
-
@for (row of displayData(); track getRowId(row, $index); let rowIdx = $index) {
|
|
25933
|
-
<tr
|
|
25934
|
-
class="jv-grid-tr"
|
|
25935
|
-
role="row"
|
|
25936
|
-
[class.jv-grid-tr-editing]="isRowEditing(row)"
|
|
25937
|
-
[class.jv-grid-tr-selected]="isSelected(row)"
|
|
25938
|
-
[attr.aria-selected]="resolvedOptions().selectable ? isSelected(row) : null"
|
|
25939
|
-
(click)="onRowClick(row)"
|
|
25940
|
-
(dblclick)="onRowDblClick(row)"
|
|
25941
|
-
(keydown.enter)="onRowClick(row)"
|
|
25942
|
-
(keydown.space)="onRowClick($event, row)"
|
|
25943
|
-
[tabindex]="-1"
|
|
25944
|
-
>
|
|
25945
|
-
@if (resolvedOptions().selectable) {
|
|
25946
|
-
<td
|
|
25947
|
-
class="jv-grid-td jv-grid-td-select"
|
|
25948
|
-
[class.jv-grid-td-sticky-left]="resolvedOptions().stickyColumns"
|
|
25949
|
-
>
|
|
25950
|
-
<input
|
|
25951
|
-
type="checkbox"
|
|
25952
|
-
class="jv-grid-checkbox"
|
|
25953
|
-
[checked]="isSelected(row)"
|
|
25954
|
-
(change)="toggleRow(row); $event.stopPropagation()"
|
|
25955
|
-
(keydown.space)="$event.stopPropagation()"
|
|
25956
|
-
[attr.aria-label]="getRowLabel(row, $index)"
|
|
25957
|
-
/>
|
|
25958
|
-
</td>
|
|
25959
|
-
}
|
|
25960
|
-
@for (col of visibleColumns(); track colKey(col); let colIdx = $index) {
|
|
25961
|
-
<td
|
|
25962
|
-
class="jv-grid-td"
|
|
25963
|
-
[attr.role]="resolvedOptions().keyboardNavigation ? 'gridcell' : null"
|
|
25964
|
-
[class]="col.cellClass || ''"
|
|
25965
|
-
[class.jv-grid-td-sticky-left]="isStickyLeft(col)"
|
|
25966
|
-
[class.jv-grid-td-sticky-right]="isStickyRight(col)"
|
|
25967
|
-
[class.jv-grid-td-editable]="isCellEditable(col)"
|
|
25968
|
-
[style.text-align]="col.align ?? 'start'"
|
|
25969
|
-
(dblclick)="startEdit(row, col, $event)"
|
|
25970
|
-
(keydown.enter)="startEdit(row, col, $event)"
|
|
25971
|
-
[attr.data-row-index]="rowIdx"
|
|
25972
|
-
[attr.data-column-index]="colIdx"
|
|
25973
|
-
[class.jv-grid-keyboard-cell]="resolvedOptions().keyboardNavigation"
|
|
25974
|
-
[attr.tabindex]="cellTabIndex(rowIdx, colIdx, col)"
|
|
25975
|
-
(focus)="onCellFocus(rowIdx, colIdx)"
|
|
25976
|
-
(keydown.f2)="onCellF2($event, rowIdx, colIdx)"
|
|
25977
|
-
(keydown)="onCellKeydown($event, rowIdx, colIdx)"
|
|
25978
|
-
>
|
|
25979
|
-
@if (isEditingCell(row, col)) {
|
|
25980
|
-
@if (editType(col) === 'select' && col.editOptions) {
|
|
25981
|
-
<jv-select
|
|
25982
|
-
[options]="getEditOptions(col)"
|
|
25983
|
-
[modelValue]="getEditValue(row, col)"
|
|
25984
|
-
(selectionChange)="onEditValueChange(row, col, $event)"
|
|
25985
|
-
/>
|
|
25986
|
-
} @else if (editType(col) === 'boolean') {
|
|
25987
|
-
<input
|
|
25988
|
-
type="checkbox"
|
|
25989
|
-
class="jv-grid-checkbox"
|
|
25990
|
-
[checked]="getBooleanEditValue(row, col)"
|
|
25991
|
-
(change)="commitEdit(row, col, normalizeEditValue(col, $any($event.target).checked))"
|
|
25992
|
-
(keydown.enter)="commitEditFromKeyboard($event, row, col, normalizeEditValue(col, $any($event.target).checked))"
|
|
25993
|
-
(keydown.escape)="cancelEdit()"
|
|
25994
|
-
[attr.aria-label]="col.header"
|
|
25995
|
-
/>
|
|
25996
|
-
} @else {
|
|
25997
|
-
<input
|
|
25998
|
-
class="jv-grid-edit-input"
|
|
25999
|
-
[type]="inputType(col)"
|
|
26000
|
-
[value]="getEditValue(row, col)"
|
|
26001
|
-
(blur)="commitEdit(row, col, normalizeEditValue(col, $any($event.target).value))"
|
|
26002
|
-
(keydown.enter)="commitEditFromKeyboard($event, row, col, normalizeEditValue(col, $any($event.target).value))"
|
|
26003
|
-
(keydown.escape)="cancelEdit()"
|
|
26004
|
-
/>
|
|
26005
|
-
}
|
|
26006
|
-
} @else {
|
|
26007
|
-
@let value = getCellValue(row, col);
|
|
26008
|
-
@if (col.type === 'boolean') {
|
|
26009
|
-
@if (isBooleanTrue(value)) {
|
|
26010
|
-
<span class="jv-grid-boolean jv-grid-boolean-true" [attr.aria-label]="t('grid.booleanYes')">{{ t('grid.booleanYes') }}</span>
|
|
26011
|
-
} @else {
|
|
26012
|
-
<span class="jv-grid-boolean jv-grid-boolean-false" [attr.aria-label]="t('grid.booleanNo')">{{ t('grid.booleanNo') }}</span>
|
|
26013
|
-
}
|
|
26014
|
-
} @else if (col.format) {
|
|
26015
|
-
{{ col.format(value, row) }}
|
|
26016
|
-
} @else {
|
|
26017
|
-
{{ formatValue(value, col, row) }}
|
|
26018
|
-
}
|
|
26019
|
-
}
|
|
26020
|
-
</td>
|
|
26021
|
-
}
|
|
26022
|
-
@if (actions().length > 0) {
|
|
26023
|
-
<td
|
|
26024
|
-
class="jv-grid-td jv-grid-td-actions"
|
|
26025
|
-
[class.jv-grid-td-sticky-right]="resolvedOptions().stickyColumns"
|
|
26026
|
-
>
|
|
26027
|
-
<div class="jv-grid-actions-group">
|
|
26028
|
-
@for (action of actions(); track action.id) {
|
|
26029
|
-
<jv-button
|
|
26030
|
-
[variant]="actionVariant(action.variant)"
|
|
26031
|
-
[icon]="action.icon ?? null"
|
|
26032
|
-
[disabled]="action.disabled?.(row) ?? false"
|
|
26033
|
-
[attr.aria-label]="action.label"
|
|
26034
|
-
[title]="action.label"
|
|
26035
|
-
(click)="onActionClick(action, row); $event.stopPropagation()"
|
|
26036
|
-
></jv-button>
|
|
26037
|
-
}
|
|
26038
|
-
</div>
|
|
26039
|
-
</td>
|
|
26040
|
-
}
|
|
26041
|
-
</tr>
|
|
26042
|
-
}
|
|
26043
|
-
}
|
|
26044
|
-
</tbody>
|
|
26045
|
-
</table>
|
|
26046
|
-
</div>
|
|
26047
|
-
}
|
|
26048
|
-
|
|
26049
|
-
@if (resolvedOptions().pageable && !virtualScrollEnabled() && effectiveTotalPages() > 1 && !resolvedOptions().loading) {
|
|
26050
|
-
<nav class="jv-grid-pagination" role="navigation" [attr.aria-label]="t('grid.paginationLabel', { label: '' })">
|
|
26051
|
-
<div class="jv-grid-pagination-info" aria-live="polite" aria-atomic="true">
|
|
26052
|
-
{{ t('grid.itemsShowing', { start: pageStart(), end: pageEnd(), total: effectiveTotalItems() }) }}
|
|
26053
|
-
</div>
|
|
26054
|
-
<div class="jv-grid-pagination-controls">
|
|
26055
|
-
@if (pageSizeOptions().length > 0) {
|
|
26056
|
-
<jv-select
|
|
26057
|
-
[options]="pageSizeOptions()"
|
|
26058
|
-
[modelValue]="pageSizeStr()"
|
|
26059
|
-
[ariaLabel]="t('grid.itemsPerPage')"
|
|
26060
|
-
(selectionChange)="onPageSizeChange($event)"
|
|
26061
|
-
/>
|
|
26062
|
-
}
|
|
26063
|
-
<jv-button
|
|
26064
|
-
variant="outline"
|
|
26065
|
-
icon="chevrons-left"
|
|
26066
|
-
[disabled]="pageIndex() === 0"
|
|
26067
|
-
(click)="goToPage(0)"
|
|
26068
|
-
[attr.aria-label]="t('grid.pageFirst')"
|
|
26069
|
-
></jv-button>
|
|
26070
|
-
<jv-button
|
|
26071
|
-
variant="outline"
|
|
26072
|
-
icon="chevron-left"
|
|
26073
|
-
[disabled]="pageIndex() === 0"
|
|
26074
|
-
(click)="goToPage(pageIndex() - 1)"
|
|
26075
|
-
[attr.aria-label]="t('grid.pagePrev')"
|
|
26076
|
-
></jv-button>
|
|
26077
|
-
@for (p of pageRange(); track p) {
|
|
26078
|
-
<jv-button
|
|
26079
|
-
[variant]="p === pageIndex() ? 'primary' : 'outline'"
|
|
26080
|
-
[attr.aria-current]="p === pageIndex() ? 'page' : null"
|
|
26081
|
-
[attr.aria-label]="t('grid.pageOfTotal', { page: p + 1, total: effectiveTotalPages() })"
|
|
26082
|
-
(click)="goToPage(p)"
|
|
26083
|
-
>{{ p + 1 }}</jv-button>
|
|
26084
|
-
}
|
|
26085
|
-
<jv-button
|
|
26086
|
-
variant="outline"
|
|
26087
|
-
icon="chevron-right"
|
|
26088
|
-
[disabled]="pageIndex() >= effectiveTotalPages() - 1"
|
|
26089
|
-
(click)="goToPage(pageIndex() + 1)"
|
|
26090
|
-
[attr.aria-label]="t('grid.pageNext')"
|
|
26091
|
-
></jv-button>
|
|
26092
|
-
<jv-button
|
|
26093
|
-
variant="outline"
|
|
26094
|
-
icon="chevrons-right"
|
|
26095
|
-
[disabled]="pageIndex() >= effectiveTotalPages() - 1"
|
|
26096
|
-
(click)="goToPage(effectiveTotalPages() - 1)"
|
|
26097
|
-
[attr.aria-label]="t('grid.pageLast')"
|
|
26098
|
-
></jv-button>
|
|
26099
|
-
</div>
|
|
26100
|
-
</nav>
|
|
26101
|
-
}
|
|
26102
|
-
</div>
|
|
26103
|
-
`, styles: [".jv-grid{display:flex;flex-direction:column;gap:var(--jv-spacing-md)}.jv-grid-toolbar{display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-md);flex-wrap:wrap}.jv-grid-search{display:flex;align-items:center;gap:var(--jv-spacing-sm)}.jv-grid-export-actions{display:flex;align-items:center;gap:var(--jv-spacing-xs)}.jv-grid-table-wrap{overflow-x:auto;overflow-y:auto;-webkit-overflow-scrolling:touch;border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-md);position:relative}.jv-grid-virtual{max-height:600px}.jv-grid-virtual-spacer{pointer-events:none}.jv-grid-table{width:100%;border-collapse:collapse;background:var(--jv-color-surface)}.jv-grid-thead{background:var(--jv-color-surface-muted)}.jv-grid-th{padding:var(--jv-spacing-sm) var(--jv-spacing-md);font-weight:600;font-size:.875rem;color:var(--jv-color-foreground-muted);text-align:start;white-space:nowrap;border-bottom:1px solid var(--jv-color-border);-webkit-user-select:none;user-select:none;position:relative}.jv-grid-th-sortable{cursor:pointer}.jv-grid-th-sortable:hover{background:var(--jv-color-surface)}.jv-grid-th-reorderable{cursor:grab}.jv-grid-th-reorderable:active{cursor:grabbing}.jv-grid-th-sticky-left{position:sticky;left:0;z-index:2;background:var(--jv-color-surface-muted);border-right:1px solid var(--jv-color-border)}.jv-grid-th-sticky-right{position:sticky;right:0;z-index:2;background:var(--jv-color-surface-muted);border-left:1px solid var(--jv-color-border)}.jv-grid-th-content{display:flex;align-items:center;gap:var(--jv-spacing-xs)}.jv-grid-sort-icon{font-size:.75rem;line-height:1}.jv-grid-th-select,.jv-grid-td-select{width:3rem;text-align:center}.jv-grid-th-actions,.jv-grid-td-actions{width:1%;white-space:nowrap}.jv-grid-td{padding:var(--jv-spacing-sm) var(--jv-spacing-md);color:var(--jv-color-foreground);font-size:var(--jv-density-font-size);border-bottom:1px solid var(--jv-color-border)}.jv-grid-keyboard-cell:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:-2px}.jv-grid-td-sticky-left{position:sticky;left:0;z-index:1;background:var(--jv-color-surface);border-right:1px solid var(--jv-color-border)}.jv-grid-td-sticky-right{position:sticky;right:0;z-index:1;background:var(--jv-color-surface);border-left:1px solid var(--jv-color-border)}.jv-grid-t:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:-2px}.jv-grid-tr{transition:background-color .12s ease}.jv-grid-tr:hover{background:var(--jv-color-surface-muted)}.jv-grid-tr:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:-2px}.jv-grid-tr-editing{background:var(--jv-color-surface-highlight, rgba(59, 130, 246, .05))}.jv-grid-tr-selected{background:var(--jv-color-primary-light, rgba(59, 130, 246, .08))}.jv-grid-checkbox{width:1rem;height:1rem;accent-color:var(--jv-color-primary);cursor:pointer}.jv-grid-boolean{display:inline-flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;border-radius:999px;font-size:.75rem;font-weight:700}.jv-grid-boolean-true{background:var(--jv-color-success);color:#fff}.jv-grid-boolean-false{background:var(--jv-color-danger);color:#fff}.jv-grid-empty{padding:var(--jv-spacing-xl) var(--jv-spacing-md);text-align:center;color:var(--jv-color-foreground-muted);font-style:italic}.jv-grid-actions-group{display:flex;align-items:center;gap:var(--jv-spacing-xs)}.jv-grid-loading{display:flex;align-items:center;justify-content:center;gap:var(--jv-spacing-md);padding:var(--jv-spacing-xl);color:var(--jv-color-foreground-muted)}.jv-grid-spinner{width:1.25rem;height:1.25rem;border:2px solid var(--jv-color-border);border-right-color:var(--jv-color-primary);border-radius:999px;animation:jv-grid-spin .8s linear infinite}@keyframes jv-grid-spin{to{transform:rotate(360deg)}}.jv-grid-pagination{display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-md);flex-wrap:wrap}.jv-grid-pagination-info{font-size:.875rem;color:var(--jv-color-foreground-muted)}.jv-grid-pagination-controls{display:flex;align-items:center;gap:var(--jv-spacing-xs);flex-wrap:wrap}@media(max-width:640px){.jv-grid-pagination{flex-direction:column;align-items:stretch;gap:var(--jv-spacing-sm)}.jv-grid-pagination-info{text-align:center}.jv-grid-pagination-controls{justify-content:center}.jv-grid-toolbar{flex-direction:column;align-items:stretch}.jv-grid-search{width:100%}.jv-grid-export-actions{justify-content:stretch}.jv-grid-export-actions jv-button{flex:1}}.jv-grid-resize-handle{position:absolute;top:0;right:0;width:4px;height:100%;cursor:col-resize;background:transparent;z-index:3}.jv-grid-resize-handle:hover,.jv-grid-resize-handle:active{background:var(--jv-color-primary)}.jv-grid-filter-row .jv-grid-th{padding:var(--jv-spacing-xs) var(--jv-spacing-sm)}.jv-grid-filter-input{width:100%;min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-sm);border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-sm);background:var(--jv-color-surface);color:var(--jv-color-foreground);font-size:.8rem;box-sizing:border-box}.jv-grid-td-editable{cursor:pointer}.jv-grid-td-editable:hover{box-shadow:inset 0 0 0 1px var(--jv-color-primary)}.jv-grid-edit-input{width:100%;min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-sm);border:1px solid var(--jv-color-primary);border-radius:var(--jv-radius-sm);background:var(--jv-color-surface);color:var(--jv-color-foreground);font-size:var(--jv-density-font-size);box-sizing:border-box}.jv-grid-edit-input:focus{outline:2px solid var(--jv-color-primary);outline-offset:-1px}\n"] }]
|
|
25785
|
+
args: [{ selector: 'jv-grid', standalone: true, imports: [FormsModule, JvButtonComponent, JvIconComponent, JvInputComponent, JvSelectComponent], template: "<div class=\"jv-grid\" role=\"region\" [attr.aria-label]=\"resolvedOptions().ariaLabel || gridLabel()\">\n @if (resolvedOptions().searchable || resolvedOptions().exportable) {\n <div class=\"jv-grid-toolbar\">\n @if (resolvedOptions().searchable) {\n <div class=\"jv-grid-search\">\n <jv-icon name=\"search\" [size]=\"16\" />\n <jv-input\n [inputId]=\"gridSearchInputId\"\n [placeholder]=\"t('grid.searchPlaceholder')\"\n [ngModel]=\"searchTerm()\"\n (ngModelChange)=\"onSearchInput($event)\"\n />\n </div>\n }\n @if (resolvedOptions().exportable) {\n <div class=\"jv-grid-export-actions\">\n <jv-button variant=\"outline\" icon=\"download\" (click)=\"exportCsv()\">{{\n t('grid.exportCsv')\n }}</jv-button>\n <jv-button variant=\"outline\" icon=\"file-spreadsheet\" (click)=\"exportExcel()\">{{\n t('grid.exportExcel')\n }}</jv-button>\n </div>\n }\n </div>\n }\n\n @if (resolvedOptions().loading) {\n <div class=\"jv-grid-loading\" role=\"status\" aria-live=\"polite\">\n <span class=\"jv-grid-spinner\" aria-hidden=\"true\"></span>\n <span>{{ t('grid.loading') }}</span>\n </div>\n } @else {\n <div\n class=\"jv-grid-table-wrap\"\n [class.jv-grid-virtual]=\"virtualScrollEnabled()\"\n #tableWrap\n (scroll)=\"onVirtualScroll($any($event.target))\"\n >\n @if (virtualScrollEnabled()) {\n <div class=\"jv-grid-virtual-spacer\" [style.height.px]=\"virtualTotalHeight()\"></div>\n }\n <table\n class=\"jv-grid-table\"\n role=\"grid\"\n [attr.aria-label]=\"resolvedOptions().ariaLabel || gridLabel()\"\n [attr.aria-rowcount]=\"effectiveTotalItems()\"\n [attr.aria-colcount]=\"colspan()\"\n [class]=\"densityClass()\"\n [style.position]=\"virtualScrollEnabled() ? 'relative' : null\"\n [style.top.px]=\"virtualOffsetY()\"\n >\n <caption class=\"sr-only\">\n {{\n resolvedOptions().ariaLabel || gridLabel()\n }}\n </caption>\n\n @let hasGroupedHeaders = groupedHeaders().length > 0;\n\n <thead class=\"jv-grid-thead\">\n @if (hasGroupedHeaders) {\n <tr>\n @if (resolvedOptions().selectable) {\n <th class=\"jv-grid-th jv-grid-th-select\" scope=\"col\" [attr.rowspan]=\"2\">\n <input\n type=\"checkbox\"\n class=\"jv-grid-checkbox\"\n [checked]=\"allSelected()\"\n (change)=\"toggleSelectAll($any($event.target).checked)\"\n [attr.aria-label]=\"allSelected() ? t('grid.deselectAll') : t('grid.selectAll')\"\n [indeterminate]=\"someSelected()\"\n />\n </th>\n }\n @for (group of groupedHeaders(); track colKey(group)) {\n <th\n class=\"jv-grid-th\"\n [class]=\"group.headerClass || ''\"\n [class.jv-grid-th-sticky-left]=\"isStickyLeft(group)\"\n [class.jv-grid-th-sticky-right]=\"isStickyRight(group)\"\n [attr.colspan]=\"groupColspan(group)\"\n scope=\"colgroup\"\n [style.text-align]=\"group.align ?? 'start'\"\n >\n <div class=\"jv-grid-th-content\">{{ group.header }}</div>\n </th>\n }\n @if (actions().length > 0) {\n <th class=\"jv-grid-th jv-grid-th-actions\" scope=\"col\" [attr.rowspan]=\"2\">\n <span class=\"sr-only\">{{ t('grid.actionsLabel', { label: '' }) }}</span>\n </th>\n }\n </tr>\n }\n\n <tr>\n @if (!hasGroupedHeaders && resolvedOptions().selectable) {\n <th class=\"jv-grid-th jv-grid-th-select\" scope=\"col\">\n <input\n type=\"checkbox\"\n class=\"jv-grid-checkbox\"\n [checked]=\"allSelected()\"\n (change)=\"toggleSelectAll($any($event.target).checked)\"\n [attr.aria-label]=\"allSelected() ? t('grid.deselectAll') : t('grid.selectAll')\"\n [indeterminate]=\"someSelected()\"\n />\n </th>\n }\n @for (col of visibleColumns(); track colKey(col); let colIdx = $index) {\n <th\n class=\"jv-grid-th\"\n [class]=\"col.headerClass || ''\"\n [class.jv-grid-th-sortable]=\"col.sortable !== false && resolvedOptions().sortable\"\n [class.jv-grid-th-sticky-left]=\"isStickyLeft(col)\"\n [class.jv-grid-th-sticky-right]=\"isStickyRight(col)\"\n [class.jv-grid-th-reorderable]=\"resolvedOptions().reorderableColumns\"\n [style.text-align]=\"col.align ?? 'start'\"\n [style.width]=\"getColumnWidth(col)\"\n [style.min-width]=\"col.minWidth || undefined\"\n [style.max-width]=\"col.maxWidth || undefined\"\n scope=\"col\"\n role=\"columnheader\"\n [attr.data-column-index]=\"colIdx\"\n [attr.aria-sort]=\"getAriaSort(col)\"\n [attr.aria-label]=\"getSortLabel(col)\"\n [tabindex]=\"\n resolvedOptions().keyboardNavigation\n ? activeCell().column === colIdx\n ? 0\n : -1\n : col.sortable !== false && resolvedOptions().sortable\n ? 0\n : -1\n \"\n (click)=\"toggleSort(col)\"\n (focus)=\"onHeaderFocus(colIdx)\"\n (keydown)=\"onHeaderKeydown($event, colIdx)\"\n (keydown.enter)=\"toggleSort(col)\"\n (keydown.space)=\"toggleSort(col, $event)\"\n draggable=\"{{ resolvedOptions().reorderableColumns ? 'true' : 'false' }}\"\n (dragstart)=\"onDragStart($event, colIdx)\"\n (dragover)=\"onDragOver($event, colIdx)\"\n (drop)=\"onDrop($event, colIdx)\"\n (dragend)=\"onDragEnd($event)\"\n >\n <div class=\"jv-grid-th-content\">\n <span>{{ col.header }}</span>\n @if (col.sortable !== false && resolvedOptions().sortable) {\n <span class=\"jv-grid-sort-icon\" aria-hidden=\"true\">\n @if (sortState().columnKey === colKey(col)) {\n @if (sortState().direction === 'asc') {\n \u25B2\n }\n @if (sortState().direction === 'desc') {\n \u25BC\n }\n }\n </span>\n }\n </div>\n @if (isColumnResizable(col)) {\n <div\n class=\"jv-grid-resize-handle\"\n (mousedown)=\"onResizeStart($event, col, colIdx)\"\n ></div>\n }\n </th>\n }\n @if (!hasGroupedHeaders && actions().length > 0) {\n <th class=\"jv-grid-th jv-grid-th-actions\" scope=\"col\">\n <span class=\"sr-only\">{{ t('grid.actionsLabel', { label: '' }) }}</span>\n </th>\n }\n </tr>\n\n @if (resolvedOptions().columnFilters) {\n <tr class=\"jv-grid-filter-row\">\n @if (resolvedOptions().selectable) {\n <th class=\"jv-grid-th jv-grid-th-select\"></th>\n }\n @for (col of visibleColumns(); track colKey(col)) {\n <th class=\"jv-grid-th jv-grid-th-filter\">\n @if (col.filterable !== false) {\n <input\n class=\"jv-grid-filter-input\"\n [placeholder]=\"t('grid.filterPlaceholder')\"\n [attr.aria-label]=\"t('grid.filterForColumn', { column: col.header })\"\n [ngModel]=\"colFilters()[colKey(col)]?.value ?? ''\"\n (ngModelChange)=\"onColumnFilterChange(col, $event)\"\n />\n }\n </th>\n }\n @if (actions().length > 0) {\n <th class=\"jv-grid-th jv-grid-th-actions\"></th>\n }\n </tr>\n }\n </thead>\n\n <tbody class=\"jv-grid-tbody\">\n @if (displayData().length === 0 && !searchTerm().trim() && !hasActiveFilters()) {\n <tr>\n <td class=\"jv-grid-empty\" [attr.colspan]=\"colspan()\">\n {{ resolvedOptions().emptyMessage || t('grid.emptyMessage') }}\n </td>\n </tr>\n } @else if (displayData().length === 0 && (searchTerm().trim() || hasActiveFilters())) {\n <tr>\n <td class=\"jv-grid-empty\" [attr.colspan]=\"colspan()\">\n {{ resolvedOptions().noResultsMessage || t('grid.noResults') }}\n </td>\n </tr>\n } @else {\n @for (row of displayData(); track getRowId(row, $index); let rowIdx = $index) {\n <tr\n class=\"jv-grid-tr\"\n role=\"row\"\n [class.jv-grid-tr-editing]=\"isRowEditing(row)\"\n [class.jv-grid-tr-selected]=\"isSelected(row)\"\n [attr.aria-selected]=\"resolvedOptions().selectable ? isSelected(row) : null\"\n (click)=\"onRowClick(row)\"\n (dblclick)=\"onRowDblClick(row)\"\n (keydown.enter)=\"onRowClick(row)\"\n (keydown.space)=\"onRowClick($event, row)\"\n [tabindex]=\"-1\"\n >\n @if (resolvedOptions().selectable) {\n <td\n class=\"jv-grid-td jv-grid-td-select\"\n [class.jv-grid-td-sticky-left]=\"resolvedOptions().stickyColumns\"\n >\n <input\n type=\"checkbox\"\n class=\"jv-grid-checkbox\"\n [checked]=\"isSelected(row)\"\n (change)=\"toggleRow(row); $event.stopPropagation()\"\n (keydown.space)=\"$event.stopPropagation()\"\n [attr.aria-label]=\"getRowLabel(row, $index)\"\n />\n </td>\n }\n @for (col of visibleColumns(); track colKey(col); let colIdx = $index) {\n <td\n class=\"jv-grid-td\"\n [attr.role]=\"resolvedOptions().keyboardNavigation ? 'gridcell' : null\"\n [class]=\"col.cellClass || ''\"\n [class.jv-grid-td-sticky-left]=\"isStickyLeft(col)\"\n [class.jv-grid-td-sticky-right]=\"isStickyRight(col)\"\n [class.jv-grid-td-editable]=\"isCellEditable(col)\"\n [style.text-align]=\"col.align ?? 'start'\"\n (dblclick)=\"startEdit(row, col, $event)\"\n (keydown.enter)=\"startEdit(row, col, $event)\"\n [attr.data-row-index]=\"rowIdx\"\n [attr.data-column-index]=\"colIdx\"\n [class.jv-grid-keyboard-cell]=\"resolvedOptions().keyboardNavigation\"\n [attr.tabindex]=\"cellTabIndex(rowIdx, colIdx, col)\"\n (focus)=\"onCellFocus(rowIdx, colIdx)\"\n (keydown.f2)=\"onCellF2($event, rowIdx, colIdx)\"\n (keydown)=\"onCellKeydown($event, rowIdx, colIdx)\"\n >\n @if (isEditingCell(row, col)) {\n @if (editType(col) === 'select' && col.editOptions) {\n <jv-select\n [options]=\"getEditOptions(col)\"\n [modelValue]=\"getEditValue(row, col)\"\n (selectionChange)=\"onEditValueChange(row, col, $event)\"\n />\n } @else if (editType(col) === 'boolean') {\n <input\n type=\"checkbox\"\n class=\"jv-grid-checkbox\"\n [checked]=\"getBooleanEditValue(row, col)\"\n (change)=\"\n commitEdit(\n row,\n col,\n normalizeEditValue(col, $any($event.target).checked)\n )\n \"\n (keydown.enter)=\"\n commitEditFromKeyboard(\n $event,\n row,\n col,\n normalizeEditValue(col, $any($event.target).checked)\n )\n \"\n (keydown.escape)=\"cancelEdit()\"\n [attr.aria-label]=\"col.header\"\n />\n } @else {\n <input\n class=\"jv-grid-edit-input\"\n [type]=\"inputType(col)\"\n [value]=\"getEditValue(row, col)\"\n (blur)=\"\n commitEdit(row, col, normalizeEditValue(col, $any($event.target).value))\n \"\n (keydown.enter)=\"\n commitEditFromKeyboard(\n $event,\n row,\n col,\n normalizeEditValue(col, $any($event.target).value)\n )\n \"\n (keydown.escape)=\"cancelEdit()\"\n />\n }\n } @else {\n @let value = getCellValue(row, col);\n @if (col.type === 'boolean') {\n @if (isBooleanTrue(value)) {\n <span\n class=\"jv-grid-boolean jv-grid-boolean-true\"\n [attr.aria-label]=\"t('grid.booleanYes')\"\n >{{ t('grid.booleanYes') }}</span\n >\n } @else {\n <span\n class=\"jv-grid-boolean jv-grid-boolean-false\"\n [attr.aria-label]=\"t('grid.booleanNo')\"\n >{{ t('grid.booleanNo') }}</span\n >\n }\n } @else if (col.format) {\n {{ col.format(value, row) }}\n } @else {\n {{ formatValue(value, col, row) }}\n }\n }\n </td>\n }\n @if (actions().length > 0) {\n <td\n class=\"jv-grid-td jv-grid-td-actions\"\n [class.jv-grid-td-sticky-right]=\"resolvedOptions().stickyColumns\"\n >\n <div class=\"jv-grid-actions-group\">\n @for (action of actions(); track action.id) {\n <jv-button\n [variant]=\"actionVariant(action.variant)\"\n [icon]=\"action.icon ?? null\"\n [disabled]=\"action.disabled?.(row) ?? false\"\n [attr.aria-label]=\"action.label\"\n [title]=\"action.label\"\n (click)=\"onActionClick(action, row); $event.stopPropagation()\"\n ></jv-button>\n }\n </div>\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n }\n\n @if (\n resolvedOptions().pageable &&\n !virtualScrollEnabled() &&\n effectiveTotalPages() > 1 &&\n !resolvedOptions().loading\n ) {\n <nav\n class=\"jv-grid-pagination\"\n role=\"navigation\"\n [attr.aria-label]=\"t('grid.paginationLabel', { label: '' })\"\n >\n <div class=\"jv-grid-pagination-info\" aria-live=\"polite\" aria-atomic=\"true\">\n {{\n t('grid.itemsShowing', {\n start: pageStart(),\n end: pageEnd(),\n total: effectiveTotalItems(),\n })\n }}\n </div>\n <div class=\"jv-grid-pagination-controls\">\n @if (pageSizeOptions().length > 0) {\n <jv-select\n [options]=\"pageSizeOptions()\"\n [modelValue]=\"pageSizeStr()\"\n [ariaLabel]=\"t('grid.itemsPerPage')\"\n (selectionChange)=\"onPageSizeChange($event)\"\n />\n }\n <jv-button\n variant=\"outline\"\n icon=\"chevrons-left\"\n [disabled]=\"pageIndex() === 0\"\n (click)=\"goToPage(0)\"\n [attr.aria-label]=\"t('grid.pageFirst')\"\n ></jv-button>\n <jv-button\n variant=\"outline\"\n icon=\"chevron-left\"\n [disabled]=\"pageIndex() === 0\"\n (click)=\"goToPage(pageIndex() - 1)\"\n [attr.aria-label]=\"t('grid.pagePrev')\"\n ></jv-button>\n @for (p of pageRange(); track p) {\n <jv-button\n [variant]=\"p === pageIndex() ? 'primary' : 'outline'\"\n [attr.aria-current]=\"p === pageIndex() ? 'page' : null\"\n [attr.aria-label]=\"t('grid.pageOfTotal', { page: p + 1, total: effectiveTotalPages() })\"\n (click)=\"goToPage(p)\"\n >{{ p + 1 }}</jv-button\n >\n }\n <jv-button\n variant=\"outline\"\n icon=\"chevron-right\"\n [disabled]=\"pageIndex() >= effectiveTotalPages() - 1\"\n (click)=\"goToPage(pageIndex() + 1)\"\n [attr.aria-label]=\"t('grid.pageNext')\"\n ></jv-button>\n <jv-button\n variant=\"outline\"\n icon=\"chevrons-right\"\n [disabled]=\"pageIndex() >= effectiveTotalPages() - 1\"\n (click)=\"goToPage(effectiveTotalPages() - 1)\"\n [attr.aria-label]=\"t('grid.pageLast')\"\n ></jv-button>\n </div>\n </nav>\n }\n</div>\n", styles: [".jv-grid{display:flex;flex-direction:column;gap:var(--jv-spacing-md)}.jv-grid-toolbar{display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-md);flex-wrap:wrap}.jv-grid-search{display:flex;align-items:center;gap:var(--jv-spacing-sm)}.jv-grid-export-actions{display:flex;align-items:center;gap:var(--jv-spacing-xs)}.jv-grid-table-wrap{overflow-x:auto;overflow-y:auto;-webkit-overflow-scrolling:touch;border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-md);position:relative}.jv-grid-virtual{max-height:600px}.jv-grid-virtual-spacer{pointer-events:none}.jv-grid-table{width:100%;border-collapse:collapse;background:var(--jv-color-surface)}.jv-grid-thead{background:var(--jv-color-surface-muted)}.jv-grid-th{padding:var(--jv-spacing-sm) var(--jv-spacing-md);font-weight:600;font-size:.875rem;color:var(--jv-color-foreground-muted);text-align:start;white-space:nowrap;border-bottom:1px solid var(--jv-color-border);-webkit-user-select:none;user-select:none;position:relative}.jv-grid-th-sortable{cursor:pointer}.jv-grid-th-sortable:hover{background:var(--jv-color-surface)}.jv-grid-th-reorderable{cursor:grab}.jv-grid-th-reorderable:active{cursor:grabbing}.jv-grid-th-sticky-left{position:sticky;left:0;z-index:2;background:var(--jv-color-surface-muted);border-right:1px solid var(--jv-color-border)}.jv-grid-th-sticky-right{position:sticky;right:0;z-index:2;background:var(--jv-color-surface-muted);border-left:1px solid var(--jv-color-border)}.jv-grid-th-content{display:flex;align-items:center;gap:var(--jv-spacing-xs)}.jv-grid-sort-icon{font-size:.75rem;line-height:1}.jv-grid-th-select,.jv-grid-td-select{width:3rem;text-align:center}.jv-grid-th-actions,.jv-grid-td-actions{width:1%;white-space:nowrap}.jv-grid-td{padding:var(--jv-spacing-sm) var(--jv-spacing-md);color:var(--jv-color-foreground);font-size:var(--jv-density-font-size);border-bottom:1px solid var(--jv-color-border)}.jv-grid-keyboard-cell:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:-2px}.jv-grid-td-sticky-left{position:sticky;left:0;z-index:1;background:var(--jv-color-surface);border-right:1px solid var(--jv-color-border)}.jv-grid-td-sticky-right{position:sticky;right:0;z-index:1;background:var(--jv-color-surface);border-left:1px solid var(--jv-color-border)}.jv-grid-t:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:-2px}.jv-grid-tr{transition:background-color .12s ease}.jv-grid-tr:hover{background:var(--jv-color-surface-muted)}.jv-grid-tr:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:-2px}.jv-grid-tr-editing{background:var(--jv-color-surface-highlight, rgba(59, 130, 246, .05))}.jv-grid-tr-selected{background:var(--jv-color-primary-light, rgba(59, 130, 246, .08))}.jv-grid-checkbox{width:1rem;height:1rem;accent-color:var(--jv-color-primary);cursor:pointer}.jv-grid-boolean{display:inline-flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;border-radius:999px;font-size:.75rem;font-weight:700}.jv-grid-boolean-true{background:var(--jv-color-success);color:#fff}.jv-grid-boolean-false{background:var(--jv-color-danger);color:#fff}.jv-grid-empty{padding:var(--jv-spacing-xl) var(--jv-spacing-md);text-align:center;color:var(--jv-color-foreground-muted);font-style:italic}.jv-grid-actions-group{display:flex;align-items:center;gap:var(--jv-spacing-xs)}.jv-grid-loading{display:flex;align-items:center;justify-content:center;gap:var(--jv-spacing-md);padding:var(--jv-spacing-xl);color:var(--jv-color-foreground-muted)}.jv-grid-spinner{width:1.25rem;height:1.25rem;border:2px solid var(--jv-color-border);border-right-color:var(--jv-color-primary);border-radius:999px;animation:jv-grid-spin .8s linear infinite}@keyframes jv-grid-spin{to{transform:rotate(360deg)}}.jv-grid-pagination{display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-md);flex-wrap:wrap}.jv-grid-pagination-info{font-size:.875rem;color:var(--jv-color-foreground-muted)}.jv-grid-pagination-controls{display:flex;align-items:center;gap:var(--jv-spacing-xs);flex-wrap:wrap}@media(max-width:640px){.jv-grid-pagination{flex-direction:column;align-items:stretch;gap:var(--jv-spacing-sm)}.jv-grid-pagination-info{text-align:center}.jv-grid-pagination-controls{justify-content:center}.jv-grid-toolbar{flex-direction:column;align-items:stretch}.jv-grid-search{width:100%}.jv-grid-export-actions{justify-content:stretch}.jv-grid-export-actions jv-button{flex:1}}.jv-grid-resize-handle{position:absolute;top:0;right:0;width:4px;height:100%;cursor:col-resize;background:transparent;z-index:3}.jv-grid-resize-handle:hover,.jv-grid-resize-handle:active{background:var(--jv-color-primary)}.jv-grid-filter-row .jv-grid-th{padding:var(--jv-spacing-xs) var(--jv-spacing-sm)}.jv-grid-filter-input{width:100%;min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-sm);border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-sm);background:var(--jv-color-surface);color:var(--jv-color-foreground);font-size:.8rem;box-sizing:border-box}.jv-grid-td-editable{cursor:pointer}.jv-grid-td-editable:hover{box-shadow:inset 0 0 0 1px var(--jv-color-primary)}.jv-grid-edit-input{width:100%;min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-sm);border:1px solid var(--jv-color-primary);border-radius:var(--jv-radius-sm);background:var(--jv-color-surface);color:var(--jv-color-foreground);font-size:var(--jv-density-font-size);box-sizing:border-box}.jv-grid-edit-input:focus{outline:2px solid var(--jv-color-primary);outline-offset:-1px}\n"] }]
|
|
26104
25786
|
}], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], trackBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackBy", required: false }] }], selectedIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedIds", required: false }] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], rowDoubleClick: [{ type: i0.Output, args: ["rowDoubleClick"] }], actionClick: [{ type: i0.Output, args: ["actionClick"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], searchChange: [{ type: i0.Output, args: ["searchChange"] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], columnFilter: [{ type: i0.Output, args: ["columnFilter"] }], columnResize: [{ type: i0.Output, args: ["columnResize"] }], columnReorder: [{ type: i0.Output, args: ["columnReorder"] }], rowEdit: [{ type: i0.Output, args: ["rowEdit"] }] } });
|
|
26105
25787
|
|
|
26106
25788
|
class JvPaginationComponent {
|
|
@@ -26274,5 +25956,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
26274
25956
|
* Generated bundle index. Do not edit.
|
|
26275
25957
|
*/
|
|
26276
25958
|
|
|
26277
|
-
export { EN, ES, JV_DEFAULT_LOCALE, JV_FALLBACK_ICON_NAME, JV_GRID_DEFAULT_OPTIONS, JV_LOCALE_DICTIONARIES, JV_LUCIDE_ICON_REGISTRY, JV_UI_CONFIG, JV_UI_CONFIG_DEFAULTS, JV_UI_DEFAULT_CONFIG, JvAccordionComponent, JvAccordionPanelDirective, JvAlertComponent, JvAnnouncementService, JvBadgeComponent, JvBreadcrumbComponent, JvButtonComponent, JvButtonGroupComponent, JvCardComponent, JvChangePasswordPageComponent, JvCheckboxComponent, JvCodeComponent, JvCollapsiblePanelComponent, JvConfirmDialogComponent, JvDashboardShellComponent, JvDatePickerComponent, JvDayPlannerComponent, JvDayPlannerDetailDirective, JvDayPlannerItemDirective, JvDialogComponent, JvDialogService, JvDividerComponent, JvFileInputComponent, JvForgotPasswordPageComponent, JvFormContainerComponent, JvFormatService, JvGridComponent, JvIconButtonComponent, JvIconComponent, JvImageGalleryComponent, JvImageSliderComponent, JvInputComponent, JvListComponent, JvListItemComponent, JvLoaderComponent, JvLoaderService, JvLoginPageComponent, JvModalSelectorComponent, JvMonthCalendarComponent, JvMonthCalendarDayDirective, JvPageComponent, JvPaginationComponent, JvRadioComponent, JvSectionComponent, JvSelectComponent, JvSidebarComponent, JvSwitchComponent, JvTabPanelDirective, JvTabsComponent, JvTextareaComponent, JvThemeService, JvToastComponent, JvToastService, JvTooltipDirective, JvTopbarComponent, JvTranslationService, JvWindowModalComponent, provideJvUi };
|
|
25959
|
+
export { EN, ES, JV_DEFAULT_LOCALE, JV_FALLBACK_ICON_NAME, JV_GRID_DEFAULT_OPTIONS, JV_LOCALE_DICTIONARIES, JV_LUCIDE_ICON_REGISTRY, JV_UI_CONFIG, JV_UI_CONFIG_DEFAULTS, JV_UI_DEFAULT_CONFIG, JvAccordionComponent, JvAccordionPanelDirective, JvAlertComponent, JvAnnouncementService, JvBadgeComponent, JvBreadcrumbComponent, JvButtonComponent, JvButtonGroupComponent, JvCardComponent, JvChangePasswordPageComponent, JvCheckboxComponent, JvCodeComponent, JvCollapsiblePanelComponent, JvConfirmDialogComponent, JvDashboardShellComponent, JvDatePickerComponent, JvDayPlannerComponent, JvDayPlannerDetailDirective, JvDayPlannerItemDirective, JvDialogComponent, JvDialogService, JvDividerComponent, JvFileInputComponent, JvForgotPasswordPageComponent, JvFormContainerComponent, JvFormatService, JvGridComponent, JvIconButtonComponent, JvIconComponent, JvImageGalleryComponent, JvImageSliderComponent, JvInputComponent, JvListComponent, JvListItemComponent, JvLoaderComponent, JvLoaderService, JvLoginPageComponent, JvModalSelectorComponent, JvMonthCalendarComponent, JvMonthCalendarDayDirective, JvPageComponent, JvPaginationComponent, JvRadioComponent, JvSectionComponent, JvSelectComponent, JvSidebarComponent, JvSwitchComponent, JvTabPanelDirective, JvTabsComponent, JvTextareaComponent, JvThemeService, JvToastComponent, JvToastService, JvTooltipDirective, JvTopbarComponent, JvTopbarMenuComponent, JvTranslationService, JvWindowModalComponent, provideJvUi };
|
|
26278
25960
|
//# sourceMappingURL=devjuliovilla-jv-ui.mjs.map
|