@apexara/ng-components 1.0.6-test.7 → 1.0.6
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 +35 -0
- package/fesm2022/apexara-ng-components-button.mjs +15 -3
- package/fesm2022/apexara-ng-components-button.mjs.map +1 -1
- package/fesm2022/apexara-ng-components-chip.mjs +1 -1
- package/fesm2022/apexara-ng-components-chip.mjs.map +1 -1
- package/fesm2022/apexara-ng-components-datepicker.mjs +1 -1
- package/fesm2022/apexara-ng-components-datepicker.mjs.map +1 -1
- package/fesm2022/apexara-ng-components-dialog.mjs +26 -3
- package/fesm2022/apexara-ng-components-dialog.mjs.map +1 -1
- package/fesm2022/apexara-ng-components-drawer.mjs +26 -7
- package/fesm2022/apexara-ng-components-drawer.mjs.map +1 -1
- package/fesm2022/apexara-ng-components-expander.mjs +5 -2
- package/fesm2022/apexara-ng-components-expander.mjs.map +1 -1
- package/fesm2022/apexara-ng-components-filter-pill.mjs +58 -0
- package/fesm2022/apexara-ng-components-filter-pill.mjs.map +1 -0
- package/fesm2022/apexara-ng-components-image.mjs +15 -5
- package/fesm2022/apexara-ng-components-image.mjs.map +1 -1
- package/fesm2022/apexara-ng-components-input.mjs +30 -7
- package/fesm2022/apexara-ng-components-input.mjs.map +1 -1
- package/fesm2022/apexara-ng-components-more-options.mjs +1 -1
- package/fesm2022/apexara-ng-components-more-options.mjs.map +1 -1
- package/fesm2022/apexara-ng-components-select.mjs +258 -9
- package/fesm2022/apexara-ng-components-select.mjs.map +1 -1
- package/fesm2022/apexara-ng-components-services.mjs +6 -0
- package/fesm2022/apexara-ng-components-services.mjs.map +1 -1
- package/fesm2022/apexara-ng-components-snackbar.mjs +2 -2
- package/fesm2022/apexara-ng-components-snackbar.mjs.map +1 -1
- package/fesm2022/apexara-ng-components-table.mjs +154 -2
- package/fesm2022/apexara-ng-components-table.mjs.map +1 -1
- package/fesm2022/apexara-ng-components-textarea.mjs +10 -2
- package/fesm2022/apexara-ng-components-textarea.mjs.map +1 -1
- package/package.json +5 -1
- package/types/apexara-ng-components-button.d.ts +3 -2
- package/types/apexara-ng-components-dialog.d.ts +6 -1
- package/types/apexara-ng-components-drawer.d.ts +10 -2
- package/types/apexara-ng-components-expander.d.ts +2 -0
- package/types/apexara-ng-components-filter-pill.d.ts +30 -0
- package/types/apexara-ng-components-image.d.ts +2 -1
- package/types/apexara-ng-components-input.d.ts +14 -2
- package/types/apexara-ng-components-select.d.ts +31 -1
- package/types/apexara-ng-components-services.d.ts +1 -0
- package/types/apexara-ng-components-table.d.ts +36 -3
- package/types/apexara-ng-components-textarea.d.ts +5 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { EventEmitter, Output, Input, ViewChild, ContentChild, Component } from '@angular/core';
|
|
2
|
+
import { EventEmitter, HostListener, Output, Input, ViewChild, ContentChild, Component } from '@angular/core';
|
|
3
3
|
import { NgTemplateOutlet } from '@angular/common';
|
|
4
4
|
import * as i1 from '@apexara/ng-components/services';
|
|
5
5
|
|
|
@@ -8,7 +8,25 @@ class ApexDialogComponent {
|
|
|
8
8
|
this.elementRef = elementRef;
|
|
9
9
|
this.overlayService = overlayService;
|
|
10
10
|
this.closeIcon = false;
|
|
11
|
+
// Escape closes the dialog (APG modal pattern). Opt out for dialogs that
|
|
12
|
+
// must not be dismissable (e.g. blocking confirmations).
|
|
13
|
+
this.closeOnEscape = true;
|
|
11
14
|
this.closeIconClick = new EventEmitter();
|
|
15
|
+
// Ids for aria-labelledby/-describedby wiring to the projected templates.
|
|
16
|
+
this.titleId = `apex-dialog-title-${ApexDialogComponent.nextA11yId++}`;
|
|
17
|
+
this.descriptionId = `${this.titleId}-description`;
|
|
18
|
+
}
|
|
19
|
+
static { this.nextA11yId = 0; }
|
|
20
|
+
onEscape() {
|
|
21
|
+
if (!this.closeOnEscape) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
// With stacked dialogs only the top-most one (last overlay child) closes.
|
|
25
|
+
const el = this.elementRef.nativeElement;
|
|
26
|
+
if (el.parentElement && el.parentElement.lastElementChild !== el) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
this.closeIconClick.emit();
|
|
12
30
|
}
|
|
13
31
|
ngAfterViewInit() {
|
|
14
32
|
this.overlayService.appendToOverlay(this.elementRef.nativeElement, true);
|
|
@@ -29,13 +47,13 @@ class ApexDialogComponent {
|
|
|
29
47
|
}
|
|
30
48
|
}
|
|
31
49
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: ApexDialogComponent, deps: [{ token: i0.ElementRef }, { token: i1.OverlayService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
32
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: ApexDialogComponent, isStandalone: true, selector: "apex-dialog", inputs: { closeIcon: "closeIcon" }, outputs: { closeIconClick: "closeIconClick" }, queries: [{ propertyName: "title", first: true, predicate: ["title"], descendants: true }, { propertyName: "description", first: true, predicate: ["description"], descendants: true }, { propertyName: "content", first: true, predicate: ["content"], descendants: true }, { propertyName: "actions", first: true, predicate: ["actions"], descendants: true }], viewQueries: [{ propertyName: "closeIconTemplate", first: true, predicate: ["closeIcon"], descendants: true }], ngImport: i0, template: "<div class=\"backdrop\"></div>\n\n<div class=\"container\">\n <div class=\"dialog\">\n @if (closeIcon) {\n <div #closeIcon tabindex=\"0\" class=\"close-icon\" (keydown)=\"handleKeydown($event)\" (click)=\"onCloseIconClick()\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M15 5 5 15M15 15 5 5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n }\n\n @if (title) {\n <span class=\"title\">\n <ng-container [ngTemplateOutlet]=\"title\"></ng-container>\n </span>\n }\n
|
|
50
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: ApexDialogComponent, isStandalone: true, selector: "apex-dialog", inputs: { closeIcon: "closeIcon", closeOnEscape: "closeOnEscape" }, outputs: { closeIconClick: "closeIconClick" }, host: { listeners: { "document:keydown.escape": "onEscape()" } }, queries: [{ propertyName: "title", first: true, predicate: ["title"], descendants: true }, { propertyName: "description", first: true, predicate: ["description"], descendants: true }, { propertyName: "content", first: true, predicate: ["content"], descendants: true }, { propertyName: "actions", first: true, predicate: ["actions"], descendants: true }], viewQueries: [{ propertyName: "closeIconTemplate", first: true, predicate: ["closeIcon"], descendants: true }], ngImport: i0, template: "<div class=\"backdrop\" aria-hidden=\"true\"></div>\n\n<div class=\"container\">\n <div class=\"dialog\" role=\"dialog\" aria-modal=\"true\" [attr.aria-labelledby]=\"title ? titleId : null\" [attr.aria-describedby]=\"description ? descriptionId : null\">\n @if (closeIcon) {\n <div #closeIcon tabindex=\"0\" role=\"button\" aria-label=\"Close dialog\" class=\"close-icon\" (keydown)=\"handleKeydown($event)\" (click)=\"onCloseIconClick()\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path d=\"M15 5 5 15M15 15 5 5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n }\n\n @if (title) {\n <span class=\"title\" [id]=\"titleId\">\n <ng-container [ngTemplateOutlet]=\"title\"></ng-container>\n </span>\n }\n\n @if (description) {\n <span class=\"description\" [id]=\"descriptionId\">\n <ng-container [ngTemplateOutlet]=\"description\"></ng-container>\n </span>\n }\n \n @if (content) {\n <div class=\"content\">\n <ng-container [ngTemplateOutlet]=\"content\"></ng-container>\n </div>\n }\n \n @if (actions) {\n <div class=\"actions\">\n <ng-container [ngTemplateOutlet]=\"actions\"></ng-container>\n </div>\n }\n </div>\n</div>\n", styles: [".backdrop{width:100%;height:100%;position:fixed;top:0;left:0;background-color:var(--apex-dialog-backdrop-background, #0B1222);opacity:.5}.container{width:100%;height:100%;position:fixed;top:0;left:0;display:flex;pointer-events:all;align-items:center;justify-content:center}.dialog{width:calc(100% - 48px);max-width:var(--apex-dialog-max-width, 432px);max-height:calc(100% - 48px);position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;box-sizing:border-box;border-radius:8px;background-color:var(--apex-dialog-background, #FFFFFF);padding:40px}.close-icon{width:20px;height:20px;position:absolute;top:20px;right:20px;cursor:pointer}.close-icon svg path{stroke:var(--apex-dialog-close-icon-color, #000000)}.close-icon:hover svg path{stroke:var(--apex-dialog-close-icon-hover-color, #000000)}.title{color:var(--apex-dialog-title-color, #0B1222);text-align:center;font-size:28px;font-weight:600;margin-bottom:12px}.description{color:var(--apex-dialog-description-color, #5D6068);text-align:center}.content{width:100%;overflow-y:auto}.description:not(:empty),.content:not(:empty){margin-bottom:24px}:host-context(.mobile) .dialog>.actions{width:100%}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); }
|
|
33
51
|
}
|
|
34
52
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: ApexDialogComponent, decorators: [{
|
|
35
53
|
type: Component,
|
|
36
54
|
args: [{ selector: 'apex-dialog', imports: [
|
|
37
55
|
NgTemplateOutlet,
|
|
38
|
-
], template: "<div class=\"backdrop\"></div>\n\n<div class=\"container\">\n <div class=\"dialog\">\n @if (closeIcon) {\n <div #closeIcon tabindex=\"0\" class=\"close-icon\" (keydown)=\"handleKeydown($event)\" (click)=\"onCloseIconClick()\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M15 5 5 15M15 15 5 5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n }\n\n @if (title) {\n <span class=\"title\">\n <ng-container [ngTemplateOutlet]=\"title\"></ng-container>\n </span>\n }\n
|
|
56
|
+
], template: "<div class=\"backdrop\" aria-hidden=\"true\"></div>\n\n<div class=\"container\">\n <div class=\"dialog\" role=\"dialog\" aria-modal=\"true\" [attr.aria-labelledby]=\"title ? titleId : null\" [attr.aria-describedby]=\"description ? descriptionId : null\">\n @if (closeIcon) {\n <div #closeIcon tabindex=\"0\" role=\"button\" aria-label=\"Close dialog\" class=\"close-icon\" (keydown)=\"handleKeydown($event)\" (click)=\"onCloseIconClick()\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path d=\"M15 5 5 15M15 15 5 5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n }\n\n @if (title) {\n <span class=\"title\" [id]=\"titleId\">\n <ng-container [ngTemplateOutlet]=\"title\"></ng-container>\n </span>\n }\n\n @if (description) {\n <span class=\"description\" [id]=\"descriptionId\">\n <ng-container [ngTemplateOutlet]=\"description\"></ng-container>\n </span>\n }\n \n @if (content) {\n <div class=\"content\">\n <ng-container [ngTemplateOutlet]=\"content\"></ng-container>\n </div>\n }\n \n @if (actions) {\n <div class=\"actions\">\n <ng-container [ngTemplateOutlet]=\"actions\"></ng-container>\n </div>\n }\n </div>\n</div>\n", styles: [".backdrop{width:100%;height:100%;position:fixed;top:0;left:0;background-color:var(--apex-dialog-backdrop-background, #0B1222);opacity:.5}.container{width:100%;height:100%;position:fixed;top:0;left:0;display:flex;pointer-events:all;align-items:center;justify-content:center}.dialog{width:calc(100% - 48px);max-width:var(--apex-dialog-max-width, 432px);max-height:calc(100% - 48px);position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;box-sizing:border-box;border-radius:8px;background-color:var(--apex-dialog-background, #FFFFFF);padding:40px}.close-icon{width:20px;height:20px;position:absolute;top:20px;right:20px;cursor:pointer}.close-icon svg path{stroke:var(--apex-dialog-close-icon-color, #000000)}.close-icon:hover svg path{stroke:var(--apex-dialog-close-icon-hover-color, #000000)}.title{color:var(--apex-dialog-title-color, #0B1222);text-align:center;font-size:28px;font-weight:600;margin-bottom:12px}.description{color:var(--apex-dialog-description-color, #5D6068);text-align:center}.content{width:100%;overflow-y:auto}.description:not(:empty),.content:not(:empty){margin-bottom:24px}:host-context(.mobile) .dialog>.actions{width:100%}\n"] }]
|
|
39
57
|
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1.OverlayService }], propDecorators: { title: [{
|
|
40
58
|
type: ContentChild,
|
|
41
59
|
args: ['title']
|
|
@@ -53,8 +71,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
53
71
|
args: ['closeIcon']
|
|
54
72
|
}], closeIcon: [{
|
|
55
73
|
type: Input
|
|
74
|
+
}], closeOnEscape: [{
|
|
75
|
+
type: Input
|
|
56
76
|
}], closeIconClick: [{
|
|
57
77
|
type: Output
|
|
78
|
+
}], onEscape: [{
|
|
79
|
+
type: HostListener,
|
|
80
|
+
args: ['document:keydown.escape']
|
|
58
81
|
}] } });
|
|
59
82
|
|
|
60
83
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apexara-ng-components-dialog.mjs","sources":["../../../../projects/apexara/ng-components/dialog/src/dialog.component.ts","../../../../projects/apexara/ng-components/dialog/src/dialog.component.html","../../../../projects/apexara/ng-components/dialog/apexara-ng-components-dialog.ts"],"sourcesContent":["import { Component, OnDestroy, ContentChild, TemplateRef, Input, Output, EventEmitter, ElementRef, ViewChild } from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\n\nimport { OverlayService } from '@apexara/ng-components/services';\n\n@Component({\n selector: 'apex-dialog',\n templateUrl: './dialog.component.html',\n styleUrls: ['./dialog.component.css'],\n imports: [\n NgTemplateOutlet,\n ],\n})\n\nexport class ApexDialogComponent implements OnDestroy {\n\n constructor(\n private elementRef: ElementRef,\n private overlayService: OverlayService) {\n }\n\n @ContentChild('title') title?: TemplateRef<any>;\n @ContentChild('description') description?: TemplateRef<any>;\n @ContentChild('content') content?: TemplateRef<any>;\n @ContentChild('actions') actions?: TemplateRef<any>;\n\n @ViewChild('closeIcon') closeIconTemplate?: ElementRef;\n\n @Input() closeIcon: boolean = false;\n\n @Output() closeIconClick = new EventEmitter<void>();\n\n public ngAfterViewInit(): void {\n this.overlayService.appendToOverlay(this.elementRef.nativeElement, true);\n }\n\n public ngOnDestroy(): void {\n this.overlayService.removeFromOverlay(this.elementRef.nativeElement);\n }\n\n public onCloseIconClick(): void {\n this.closeIconClick.emit();\n }\n\n public handleKeydown(event: KeyboardEvent): void {\n if (!(document.activeElement === this.closeIconTemplate?.nativeElement)) {\n return;\n }\n\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n this.closeIconClick.emit();\n }\n }\n\n}\n","<div class=\"backdrop\"></div>\n\n<div class=\"container\">\n <div class=\"dialog\">\n @if (closeIcon) {\n <div #closeIcon tabindex=\"0\" class=\"close-icon\" (keydown)=\"handleKeydown($event)\" (click)=\"onCloseIconClick()\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M15 5 5 15M15 15 5 5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n }\n\n @if (title) {\n <span class=\"title\">\n <ng-container [ngTemplateOutlet]=\"title\"></ng-container>\n </span>\n }\n
|
|
1
|
+
{"version":3,"file":"apexara-ng-components-dialog.mjs","sources":["../../../../projects/apexara/ng-components/dialog/src/dialog.component.ts","../../../../projects/apexara/ng-components/dialog/src/dialog.component.html","../../../../projects/apexara/ng-components/dialog/apexara-ng-components-dialog.ts"],"sourcesContent":["import { Component, OnDestroy, ContentChild, TemplateRef, Input, Output, EventEmitter, ElementRef, ViewChild, HostListener } from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\n\nimport { OverlayService } from '@apexara/ng-components/services';\n\n@Component({\n selector: 'apex-dialog',\n templateUrl: './dialog.component.html',\n styleUrls: ['./dialog.component.css'],\n imports: [\n NgTemplateOutlet,\n ],\n})\n\nexport class ApexDialogComponent implements OnDestroy {\n\n constructor(\n private elementRef: ElementRef,\n private overlayService: OverlayService) {\n }\n\n @ContentChild('title') title?: TemplateRef<any>;\n @ContentChild('description') description?: TemplateRef<any>;\n @ContentChild('content') content?: TemplateRef<any>;\n @ContentChild('actions') actions?: TemplateRef<any>;\n\n @ViewChild('closeIcon') closeIconTemplate?: ElementRef;\n\n @Input() closeIcon: boolean = false;\n\n // Escape closes the dialog (APG modal pattern). Opt out for dialogs that\n // must not be dismissable (e.g. blocking confirmations).\n @Input() closeOnEscape: boolean = true;\n\n @Output() closeIconClick = new EventEmitter<void>();\n\n private static nextA11yId = 0;\n\n // Ids for aria-labelledby/-describedby wiring to the projected templates.\n public readonly titleId = `apex-dialog-title-${ApexDialogComponent.nextA11yId++}`;\n public readonly descriptionId = `${this.titleId}-description`;\n\n @HostListener('document:keydown.escape')\n public onEscape(): void {\n if (!this.closeOnEscape) {\n return;\n }\n\n // With stacked dialogs only the top-most one (last overlay child) closes.\n const el = this.elementRef.nativeElement as HTMLElement;\n\n if (el.parentElement && el.parentElement.lastElementChild !== el) {\n return;\n }\n\n this.closeIconClick.emit();\n }\n\n public ngAfterViewInit(): void {\n this.overlayService.appendToOverlay(this.elementRef.nativeElement, true);\n }\n\n public ngOnDestroy(): void {\n this.overlayService.removeFromOverlay(this.elementRef.nativeElement);\n }\n\n public onCloseIconClick(): void {\n this.closeIconClick.emit();\n }\n\n public handleKeydown(event: KeyboardEvent): void {\n if (!(document.activeElement === this.closeIconTemplate?.nativeElement)) {\n return;\n }\n\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n this.closeIconClick.emit();\n }\n }\n\n}\n","<div class=\"backdrop\" aria-hidden=\"true\"></div>\n\n<div class=\"container\">\n <div class=\"dialog\" role=\"dialog\" aria-modal=\"true\" [attr.aria-labelledby]=\"title ? titleId : null\" [attr.aria-describedby]=\"description ? descriptionId : null\">\n @if (closeIcon) {\n <div #closeIcon tabindex=\"0\" role=\"button\" aria-label=\"Close dialog\" class=\"close-icon\" (keydown)=\"handleKeydown($event)\" (click)=\"onCloseIconClick()\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path d=\"M15 5 5 15M15 15 5 5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n }\n\n @if (title) {\n <span class=\"title\" [id]=\"titleId\">\n <ng-container [ngTemplateOutlet]=\"title\"></ng-container>\n </span>\n }\n\n @if (description) {\n <span class=\"description\" [id]=\"descriptionId\">\n <ng-container [ngTemplateOutlet]=\"description\"></ng-container>\n </span>\n }\n \n @if (content) {\n <div class=\"content\">\n <ng-container [ngTemplateOutlet]=\"content\"></ng-container>\n </div>\n }\n \n @if (actions) {\n <div class=\"actions\">\n <ng-container [ngTemplateOutlet]=\"actions\"></ng-container>\n </div>\n }\n </div>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,19 +1,35 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { signal, EventEmitter, ContentChild, Output, Component } from '@angular/core';
|
|
2
|
+
import { signal, EventEmitter, ContentChild, Output, HostListener, Component } from '@angular/core';
|
|
3
3
|
import { NgTemplateOutlet } from '@angular/common';
|
|
4
|
-
import * as i1 from '@
|
|
4
|
+
import * as i1 from '@angular/cdk/a11y';
|
|
5
|
+
import * as i2 from '@apexara/ng-components/services';
|
|
5
6
|
|
|
6
7
|
class ApexDrawerComponent {
|
|
7
|
-
constructor(scrollBlockService) {
|
|
8
|
+
constructor(elementRef, focusTrapFactory, scrollBlockService) {
|
|
9
|
+
this.elementRef = elementRef;
|
|
10
|
+
this.focusTrapFactory = focusTrapFactory;
|
|
8
11
|
this.scrollBlockService = scrollBlockService;
|
|
9
12
|
this.isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
13
|
+
this.titleId = `apex-drawer-title-${ApexDrawerComponent.nextA11yId++}`;
|
|
14
|
+
// APG modal pattern: trap focus while open, return it to the opener on close.
|
|
15
|
+
this.focusTrap = null;
|
|
16
|
+
this.previouslyFocused = null;
|
|
10
17
|
this.closeChange = new EventEmitter();
|
|
11
18
|
this.scrollBlockService.activate();
|
|
12
19
|
}
|
|
20
|
+
static { this.nextA11yId = 0; }
|
|
21
|
+
onEscape() {
|
|
22
|
+
this.close();
|
|
23
|
+
}
|
|
13
24
|
ngOnDestroy() {
|
|
14
25
|
this.scrollBlockService.deactivate();
|
|
26
|
+
this.focusTrap?.destroy();
|
|
27
|
+
this.previouslyFocused?.focus();
|
|
15
28
|
}
|
|
16
29
|
ngAfterViewInit() {
|
|
30
|
+
this.previouslyFocused = document.activeElement;
|
|
31
|
+
this.focusTrap = this.focusTrapFactory.create(this.elementRef.nativeElement);
|
|
32
|
+
this.focusTrap.focusInitialElementWhenReady();
|
|
17
33
|
requestAnimationFrame(() => {
|
|
18
34
|
this.isOpen.set(true);
|
|
19
35
|
});
|
|
@@ -27,15 +43,18 @@ class ApexDrawerComponent {
|
|
|
27
43
|
this.closeChange.emit();
|
|
28
44
|
}, 250);
|
|
29
45
|
}
|
|
30
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: ApexDrawerComponent, deps: [{ token: i1.ScrollBlockService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
31
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: ApexDrawerComponent, isStandalone: true, selector: "apex-drawer", outputs: { closeChange: "closeChange" }, queries: [{ propertyName: "title", first: true, predicate: ["title"], descendants: true }, { propertyName: "description", first: true, predicate: ["description"], descendants: true }, { propertyName: "content", first: true, predicate: ["content"], descendants: true }, { propertyName: "actions", first: true, predicate: ["actions"], descendants: true }], ngImport: i0, template: "<div class=\"backdrop\"></div>\n\n<div class=\"wrapper\">\n <div class=\"container\" [class.open]=\"isOpen()\">\n <div class=\"close-icon\" tabindex=\"0\" (click)=\"close()\" (keydown.enter)=\"close()\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M15 5 5 15M15 15 5 5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n\n <div class=\"header\">\n @if (title) {\n <span class=\"title\">\n <ng-container [ngTemplateOutlet]=\"title\"></ng-container>\n </span>\n }\n \n @if (description) {\n <span class=\"description\">\n <ng-container [ngTemplateOutlet]=\"description\"></ng-container>\n </span>\n }\n </div>\n\n @if (content) {\n <div class=\"content\">\n <ng-container [ngTemplateOutlet]=\"content\"></ng-container>\n </div>\n }\n\n @if (actions) {\n <div class=\"actions\">\n <ng-container [ngTemplateOutlet]=\"actions\"></ng-container>\n </div>\n }\n </div>\n</div>\n", styles: [".backdrop{width:100%;height:100%;position:fixed;top:0;left:0;background-color:var(--apex-drawer-backdrop-background, #0B1222);opacity:.5;z-index:96}.wrapper{width:100%;height:100vh;display:flex;justify-content:right;position:fixed;top:0;left:0;z-index:97}.container{max-width:100%;width:var(--apex-drawer-width, 410px);height:100%;display:flex;flex-direction:column;row-gap:32px;padding:44px 24px;position:relative;background-color:var(--apex-drawer-background, #FFFFFF);box-shadow:var(--apex-drawer-box-shadow, 0px 4px 8px 0px #D6D6D635);box-sizing:border-box;transform:translate(100%);transition:transform .25s cubic-bezier(.4,0,.1,1)}.container.open{transform:translate(0)}.close-icon{width:20px;height:20px;position:absolute;top:16px;right:16px;cursor:pointer}.close-icon svg path{stroke:var(--apex-drawer-close-icon-color, #000000)}.close-icon:hover svg path{stroke:var(--apex-drawer-close-icon-hover-color, #000000)}.header{display:flex;flex-direction:column;row-gap:12px}.title{color:var(--apex-drawer-title-color, #0B1222);font-size:24px;font-weight:600}.description{color:var(--apex-drawer-description-color, #5D6068)}.content{width:100%;height:100%;overflow-y:auto}.actions{width:100%;height:fit-content}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); }
|
|
46
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: ApexDrawerComponent, deps: [{ token: i0.ElementRef }, { token: i1.FocusTrapFactory }, { token: i2.ScrollBlockService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
47
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: ApexDrawerComponent, isStandalone: true, selector: "apex-drawer", outputs: { closeChange: "closeChange" }, host: { listeners: { "document:keydown.escape": "onEscape()" } }, queries: [{ propertyName: "title", first: true, predicate: ["title"], descendants: true }, { propertyName: "description", first: true, predicate: ["description"], descendants: true }, { propertyName: "content", first: true, predicate: ["content"], descendants: true }, { propertyName: "actions", first: true, predicate: ["actions"], descendants: true }], ngImport: i0, template: "<div class=\"backdrop\" aria-hidden=\"true\"></div>\n\n<div class=\"wrapper\">\n <div class=\"container\" role=\"dialog\" aria-modal=\"true\" [attr.aria-labelledby]=\"title ? titleId : null\" [class.open]=\"isOpen()\">\n <div class=\"close-icon\" tabindex=\"0\" role=\"button\" aria-label=\"Close\" (click)=\"close()\" (keydown.enter)=\"close()\" (keydown.space)=\"$event.preventDefault(); close()\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path d=\"M15 5 5 15M15 15 5 5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n\n <div class=\"header\">\n @if (title) {\n <span class=\"title\" [id]=\"titleId\">\n <ng-container [ngTemplateOutlet]=\"title\"></ng-container>\n </span>\n }\n \n @if (description) {\n <span class=\"description\">\n <ng-container [ngTemplateOutlet]=\"description\"></ng-container>\n </span>\n }\n </div>\n\n @if (content) {\n <div class=\"content\">\n <ng-container [ngTemplateOutlet]=\"content\"></ng-container>\n </div>\n }\n\n @if (actions) {\n <div class=\"actions\">\n <ng-container [ngTemplateOutlet]=\"actions\"></ng-container>\n </div>\n }\n </div>\n</div>\n", styles: [".backdrop{width:100%;height:100%;position:fixed;top:0;left:0;background-color:var(--apex-drawer-backdrop-background, #0B1222);opacity:.5;z-index:96}.wrapper{width:100%;height:100vh;display:flex;justify-content:right;position:fixed;top:0;left:0;z-index:97}.container{max-width:100%;width:var(--apex-drawer-width, 410px);height:100%;display:flex;flex-direction:column;row-gap:32px;padding:44px 24px;position:relative;background-color:var(--apex-drawer-background, #FFFFFF);box-shadow:var(--apex-drawer-box-shadow, 0px 4px 8px 0px #D6D6D635);box-sizing:border-box;transform:translate(100%);transition:transform .25s cubic-bezier(.4,0,.1,1)}.container.open{transform:translate(0)}.close-icon{width:20px;height:20px;position:absolute;top:16px;right:16px;cursor:pointer}.close-icon svg path{stroke:var(--apex-drawer-close-icon-color, #000000)}.close-icon:hover svg path{stroke:var(--apex-drawer-close-icon-hover-color, #000000)}.header{display:flex;flex-direction:column;row-gap:12px}.title{color:var(--apex-drawer-title-color, #0B1222);font-size:24px;font-weight:600}.description{color:var(--apex-drawer-description-color, #5D6068)}.content{width:100%;height:100%;overflow-y:auto}.actions{width:100%;height:fit-content}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); }
|
|
32
48
|
}
|
|
33
49
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: ApexDrawerComponent, decorators: [{
|
|
34
50
|
type: Component,
|
|
35
51
|
args: [{ selector: 'apex-drawer', imports: [
|
|
36
52
|
NgTemplateOutlet,
|
|
37
|
-
], template: "<div class=\"backdrop\"></div>\n\n<div class=\"wrapper\">\n <div class=\"container\" [class.open]=\"isOpen()\">\n <div class=\"close-icon\" tabindex=\"0\" (click)=\"close()\" (keydown.enter)=\"close()\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M15 5 5 15M15 15 5 5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n\n <div class=\"header\">\n @if (title) {\n <span class=\"title\">\n <ng-container [ngTemplateOutlet]=\"title\"></ng-container>\n </span>\n }\n \n @if (description) {\n <span class=\"description\">\n <ng-container [ngTemplateOutlet]=\"description\"></ng-container>\n </span>\n }\n </div>\n\n @if (content) {\n <div class=\"content\">\n <ng-container [ngTemplateOutlet]=\"content\"></ng-container>\n </div>\n }\n\n @if (actions) {\n <div class=\"actions\">\n <ng-container [ngTemplateOutlet]=\"actions\"></ng-container>\n </div>\n }\n </div>\n</div>\n", styles: [".backdrop{width:100%;height:100%;position:fixed;top:0;left:0;background-color:var(--apex-drawer-backdrop-background, #0B1222);opacity:.5;z-index:96}.wrapper{width:100%;height:100vh;display:flex;justify-content:right;position:fixed;top:0;left:0;z-index:97}.container{max-width:100%;width:var(--apex-drawer-width, 410px);height:100%;display:flex;flex-direction:column;row-gap:32px;padding:44px 24px;position:relative;background-color:var(--apex-drawer-background, #FFFFFF);box-shadow:var(--apex-drawer-box-shadow, 0px 4px 8px 0px #D6D6D635);box-sizing:border-box;transform:translate(100%);transition:transform .25s cubic-bezier(.4,0,.1,1)}.container.open{transform:translate(0)}.close-icon{width:20px;height:20px;position:absolute;top:16px;right:16px;cursor:pointer}.close-icon svg path{stroke:var(--apex-drawer-close-icon-color, #000000)}.close-icon:hover svg path{stroke:var(--apex-drawer-close-icon-hover-color, #000000)}.header{display:flex;flex-direction:column;row-gap:12px}.title{color:var(--apex-drawer-title-color, #0B1222);font-size:24px;font-weight:600}.description{color:var(--apex-drawer-description-color, #5D6068)}.content{width:100%;height:100%;overflow-y:auto}.actions{width:100%;height:fit-content}\n"] }]
|
|
38
|
-
}], ctorParameters: () => [{ type: i1.ScrollBlockService }], propDecorators: {
|
|
53
|
+
], template: "<div class=\"backdrop\" aria-hidden=\"true\"></div>\n\n<div class=\"wrapper\">\n <div class=\"container\" role=\"dialog\" aria-modal=\"true\" [attr.aria-labelledby]=\"title ? titleId : null\" [class.open]=\"isOpen()\">\n <div class=\"close-icon\" tabindex=\"0\" role=\"button\" aria-label=\"Close\" (click)=\"close()\" (keydown.enter)=\"close()\" (keydown.space)=\"$event.preventDefault(); close()\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path d=\"M15 5 5 15M15 15 5 5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n\n <div class=\"header\">\n @if (title) {\n <span class=\"title\" [id]=\"titleId\">\n <ng-container [ngTemplateOutlet]=\"title\"></ng-container>\n </span>\n }\n \n @if (description) {\n <span class=\"description\">\n <ng-container [ngTemplateOutlet]=\"description\"></ng-container>\n </span>\n }\n </div>\n\n @if (content) {\n <div class=\"content\">\n <ng-container [ngTemplateOutlet]=\"content\"></ng-container>\n </div>\n }\n\n @if (actions) {\n <div class=\"actions\">\n <ng-container [ngTemplateOutlet]=\"actions\"></ng-container>\n </div>\n }\n </div>\n</div>\n", styles: [".backdrop{width:100%;height:100%;position:fixed;top:0;left:0;background-color:var(--apex-drawer-backdrop-background, #0B1222);opacity:.5;z-index:96}.wrapper{width:100%;height:100vh;display:flex;justify-content:right;position:fixed;top:0;left:0;z-index:97}.container{max-width:100%;width:var(--apex-drawer-width, 410px);height:100%;display:flex;flex-direction:column;row-gap:32px;padding:44px 24px;position:relative;background-color:var(--apex-drawer-background, #FFFFFF);box-shadow:var(--apex-drawer-box-shadow, 0px 4px 8px 0px #D6D6D635);box-sizing:border-box;transform:translate(100%);transition:transform .25s cubic-bezier(.4,0,.1,1)}.container.open{transform:translate(0)}.close-icon{width:20px;height:20px;position:absolute;top:16px;right:16px;cursor:pointer}.close-icon svg path{stroke:var(--apex-drawer-close-icon-color, #000000)}.close-icon:hover svg path{stroke:var(--apex-drawer-close-icon-hover-color, #000000)}.header{display:flex;flex-direction:column;row-gap:12px}.title{color:var(--apex-drawer-title-color, #0B1222);font-size:24px;font-weight:600}.description{color:var(--apex-drawer-description-color, #5D6068)}.content{width:100%;height:100%;overflow-y:auto}.actions{width:100%;height:fit-content}\n"] }]
|
|
54
|
+
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1.FocusTrapFactory }, { type: i2.ScrollBlockService }], propDecorators: { onEscape: [{
|
|
55
|
+
type: HostListener,
|
|
56
|
+
args: ['document:keydown.escape']
|
|
57
|
+
}], closeChange: [{
|
|
39
58
|
type: Output
|
|
40
59
|
}], title: [{
|
|
41
60
|
type: ContentChild,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apexara-ng-components-drawer.mjs","sources":["../../../../projects/apexara/ng-components/drawer/src/drawer.component.ts","../../../../projects/apexara/ng-components/drawer/src/drawer.component.html","../../../../projects/apexara/ng-components/drawer/apexara-ng-components-drawer.ts"],"sourcesContent":["import { Component, OnDestroy, ContentChild, TemplateRef, EventEmitter, Output, AfterViewInit, signal } from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\n\nimport { ScrollBlockService } from '@apexara/ng-components/services';\n\n@Component({\n selector: 'apex-drawer',\n templateUrl: './drawer.component.html',\n styleUrls: ['./drawer.component.css'],\n imports: [\n NgTemplateOutlet,\n ],\n})\n\nexport class ApexDrawerComponent implements AfterViewInit, OnDestroy {\n\n constructor(\n private scrollBlockService: ScrollBlockService) {\n\n this.scrollBlockService.activate();\n }\n\n public isOpen = signal(false);\n\n @Output() closeChange = new EventEmitter<void>();\n\n @ContentChild('title') title?: TemplateRef<any>;\n @ContentChild('description') description?: TemplateRef<any>;\n @ContentChild('content') content?: TemplateRef<any>;\n @ContentChild('actions') actions?: TemplateRef<any>;\n\n public ngOnDestroy(): void {\n this.scrollBlockService.deactivate();\n }\n\n public ngAfterViewInit(): void {\n requestAnimationFrame(() => {\n this.isOpen.set(true);\n });\n }\n\n public close(): void {\n if (!this.closeChange) {\n return;\n }\n\n this.isOpen.set(false);\n\n setTimeout(() => {\n this.closeChange.emit();\n }, 250);\n }\n\n}\n","<div class=\"backdrop\"></div>\n\n<div class=\"wrapper\">\n <div class=\"container\" [class.open]=\"isOpen()\">\n <div class=\"close-icon\" tabindex=\"0\" (click)=\"close()\" (keydown.enter)=\"close()\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M15 5 5 15M15 15 5 5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n\n <div class=\"header\">\n @if (title) {\n <span class=\"title\">\n <ng-container [ngTemplateOutlet]=\"title\"></ng-container>\n </span>\n }\n \n @if (description) {\n <span class=\"description\">\n <ng-container [ngTemplateOutlet]=\"description\"></ng-container>\n </span>\n }\n </div>\n\n @if (content) {\n <div class=\"content\">\n <ng-container [ngTemplateOutlet]=\"content\"></ng-container>\n </div>\n }\n\n @if (actions) {\n <div class=\"actions\">\n <ng-container [ngTemplateOutlet]=\"actions\"></ng-container>\n </div>\n }\n </div>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"apexara-ng-components-drawer.mjs","sources":["../../../../projects/apexara/ng-components/drawer/src/drawer.component.ts","../../../../projects/apexara/ng-components/drawer/src/drawer.component.html","../../../../projects/apexara/ng-components/drawer/apexara-ng-components-drawer.ts"],"sourcesContent":["import { Component, OnDestroy, ContentChild, TemplateRef, EventEmitter, Output, AfterViewInit, signal, ElementRef, HostListener } from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\n\nimport { FocusTrap, FocusTrapFactory } from '@angular/cdk/a11y';\n\nimport { ScrollBlockService } from '@apexara/ng-components/services';\n\n@Component({\n selector: 'apex-drawer',\n templateUrl: './drawer.component.html',\n styleUrls: ['./drawer.component.css'],\n imports: [\n NgTemplateOutlet,\n ],\n})\n\nexport class ApexDrawerComponent implements AfterViewInit, OnDestroy {\n\n constructor(\n private elementRef: ElementRef,\n private focusTrapFactory: FocusTrapFactory,\n private scrollBlockService: ScrollBlockService) {\n\n this.scrollBlockService.activate();\n }\n\n public isOpen = signal(false);\n\n private static nextA11yId = 0;\n\n public readonly titleId = `apex-drawer-title-${ApexDrawerComponent.nextA11yId++}`;\n\n // APG modal pattern: trap focus while open, return it to the opener on close.\n private focusTrap: FocusTrap | null = null;\n private previouslyFocused: HTMLElement | null = null;\n\n @HostListener('document:keydown.escape')\n public onEscape(): void {\n this.close();\n }\n\n @Output() closeChange = new EventEmitter<void>();\n\n @ContentChild('title') title?: TemplateRef<any>;\n @ContentChild('description') description?: TemplateRef<any>;\n @ContentChild('content') content?: TemplateRef<any>;\n @ContentChild('actions') actions?: TemplateRef<any>;\n\n public ngOnDestroy(): void {\n this.scrollBlockService.deactivate();\n\n this.focusTrap?.destroy();\n this.previouslyFocused?.focus();\n }\n\n public ngAfterViewInit(): void {\n this.previouslyFocused = document.activeElement as HTMLElement | null;\n\n this.focusTrap = this.focusTrapFactory.create(this.elementRef.nativeElement);\n this.focusTrap.focusInitialElementWhenReady();\n\n requestAnimationFrame(() => {\n this.isOpen.set(true);\n });\n }\n\n public close(): void {\n if (!this.closeChange) {\n return;\n }\n\n this.isOpen.set(false);\n\n setTimeout(() => {\n this.closeChange.emit();\n }, 250);\n }\n\n}\n","<div class=\"backdrop\" aria-hidden=\"true\"></div>\n\n<div class=\"wrapper\">\n <div class=\"container\" role=\"dialog\" aria-modal=\"true\" [attr.aria-labelledby]=\"title ? titleId : null\" [class.open]=\"isOpen()\">\n <div class=\"close-icon\" tabindex=\"0\" role=\"button\" aria-label=\"Close\" (click)=\"close()\" (keydown.enter)=\"close()\" (keydown.space)=\"$event.preventDefault(); close()\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path d=\"M15 5 5 15M15 15 5 5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n\n <div class=\"header\">\n @if (title) {\n <span class=\"title\" [id]=\"titleId\">\n <ng-container [ngTemplateOutlet]=\"title\"></ng-container>\n </span>\n }\n \n @if (description) {\n <span class=\"description\">\n <ng-container [ngTemplateOutlet]=\"description\"></ng-container>\n </span>\n }\n </div>\n\n @if (content) {\n <div class=\"content\">\n <ng-container [ngTemplateOutlet]=\"content\"></ng-container>\n </div>\n }\n\n @if (actions) {\n <div class=\"actions\">\n <ng-container [ngTemplateOutlet]=\"actions\"></ng-container>\n </div>\n }\n </div>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;MAgBa,mBAAmB,CAAA;AAE9B,IAAA,WAAA,CACU,UAAsB,EACtB,gBAAkC,EAClC,kBAAsC,EAAA;QAFtC,IAAA,CAAA,UAAU,GAAV,UAAU;QACV,IAAA,CAAA,gBAAgB,GAAhB,gBAAgB;QAChB,IAAA,CAAA,kBAAkB,GAAlB,kBAAkB;AAKrB,QAAA,IAAA,CAAA,MAAM,GAAG,MAAM,CAAC,KAAK,kDAAC;AAIb,QAAA,IAAA,CAAA,OAAO,GAAG,CAAA,kBAAA,EAAqB,mBAAmB,CAAC,UAAU,EAAE,EAAE;;QAGzE,IAAA,CAAA,SAAS,GAAqB,IAAI;QAClC,IAAA,CAAA,iBAAiB,GAAuB,IAAI;AAO1C,QAAA,IAAA,CAAA,WAAW,GAAG,IAAI,YAAY,EAAQ;AAlB9C,QAAA,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE;IACpC;aAIe,IAAA,CAAA,UAAU,GAAG,CAAH,CAAK;IASvB,QAAQ,GAAA;QACb,IAAI,CAAC,KAAK,EAAE;IACd;IASO,WAAW,GAAA;AAChB,QAAA,IAAI,CAAC,kBAAkB,CAAC,UAAU,EAAE;AAEpC,QAAA,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE;AACzB,QAAA,IAAI,CAAC,iBAAiB,EAAE,KAAK,EAAE;IACjC;IAEO,eAAe,GAAA;AACpB,QAAA,IAAI,CAAC,iBAAiB,GAAG,QAAQ,CAAC,aAAmC;AAErE,QAAA,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC;AAC5E,QAAA,IAAI,CAAC,SAAS,CAAC,4BAA4B,EAAE;QAE7C,qBAAqB,CAAC,MAAK;AACzB,YAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;AACvB,QAAA,CAAC,CAAC;IACJ;IAEO,KAAK,GAAA;AACV,QAAA,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;YACrB;QACF;AAEA,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;QAEtB,UAAU,CAAC,MAAK;AACd,YAAA,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE;QACzB,CAAC,EAAE,GAAG,CAAC;IACT;8GA5DW,mBAAmB,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,UAAA,EAAA,EAAA,EAAA,KAAA,EAAA,EAAA,CAAA,gBAAA,EAAA,EAAA,EAAA,KAAA,EAAA,EAAA,CAAA,kBAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;kGAAnB,mBAAmB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,aAAA,EAAA,OAAA,EAAA,EAAA,WAAA,EAAA,aAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,yBAAA,EAAA,YAAA,EAAA,EAAA,EAAA,OAAA,EAAA,CAAA,EAAA,YAAA,EAAA,OAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,OAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,EAAA,YAAA,EAAA,aAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,aAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,EAAA,YAAA,EAAA,SAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,SAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,EAAA,YAAA,EAAA,SAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,SAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EChBhC,+gDAqCA,EAAA,MAAA,EAAA,CAAA,ksCAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EDzBI,gBAAgB,EAAA,QAAA,EAAA,oBAAA,EAAA,MAAA,EAAA,CAAA,yBAAA,EAAA,kBAAA,EAAA,0BAAA,CAAA,EAAA,CAAA,EAAA,CAAA,CAAA;;2FAIP,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBAT/B,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,aAAa,EAAA,OAAA,EAGd;wBACP,gBAAgB;AACjB,qBAAA,EAAA,QAAA,EAAA,+gDAAA,EAAA,MAAA,EAAA,CAAA,ksCAAA,CAAA,EAAA;;sBAuBA,YAAY;uBAAC,yBAAyB;;sBAKtC;;sBAEA,YAAY;uBAAC,OAAO;;sBACpB,YAAY;uBAAC,aAAa;;sBAC1B,YAAY;uBAAC,SAAS;;sBACtB,YAAY;uBAAC,SAAS;;;AE9CzB;;AAEG;;;;"}
|
|
@@ -4,17 +4,20 @@ import { NgClass } from '@angular/common';
|
|
|
4
4
|
|
|
5
5
|
class ApexExpanderComponent {
|
|
6
6
|
constructor() {
|
|
7
|
+
// Links the disclosure header to its panel via aria-controls.
|
|
8
|
+
this.contentId = `apex-expander-content-${ApexExpanderComponent.nextA11yId++}`;
|
|
7
9
|
this.isOpen = false;
|
|
8
10
|
this.maxHeight = null;
|
|
9
11
|
}
|
|
12
|
+
static { this.nextA11yId = 0; }
|
|
10
13
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: ApexExpanderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
11
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.2", type: ApexExpanderComponent, isStandalone: true, selector: "apex-expander", inputs: { isOpen: "isOpen", maxHeight: "maxHeight" }, ngImport: i0, template: "<div [ngClass]=\"{ container: true, open: isOpen, 'fit-content': !maxHeight }\">\n <div class=\"header\" role=\"button\" tabindex=\"0\" (click)=\"isOpen = !isOpen\">\n <span class=\"title\">\n <ng-content select=\"[title]\"></ng-content>\n </span>\n\n <span class=\"chevron\"></span>\n </div>\n\n <div class=\"content-wrapper\">\n <div class=\"content\" [style.max-height]=\"maxHeight ? maxHeight + 'px' : 'none'\">\n <ng-content select=\"[content]\"></ng-content>\n </div>\n </div>\n</div>\n", styles: [":host{display:block;touch-action:manipulation}.container{display:flex;flex-direction:column;background-color:var(--apex-expander-background-color, #FFFFFF);border-radius:8px;border:var(--apex-expander-border, 0px);box-shadow:var(--apex-expander-box-shadow, 0px 4px 8px 0px rgba(214, 214, 214, .35))}.header{display:flex;align-items:center;justify-content:space-between;column-gap:30px;cursor:pointer;padding:20px 30px}.header:focus{outline:var(--apex-expander-outline-color, none)}.header .title{width:100%;font-size:16px;font-weight:500;color:var(--apex-expander-title-color, #0B1222)}.header .chevron{width:8px;height:8px;flex-shrink:0;position:relative;bottom:3px;transform-origin:center;transform:rotate(-135deg);transition:all .25s cubic-bezier(.4,0,.1,1);border-top:2px solid var(--apex-expander-chevron-color, #5D6068);border-left:2px solid var(--apex-expander-chevron-color, #5D6068);border-top-left-radius:3px;border-top-right-radius:1px;border-bottom-left-radius:1px}.container.open .header .chevron{bottom:-3px;transform:rotate(45deg);border-top:2px solid var(--apex-expander-chevron-open-color, #F96138);border-left:2px solid var(--apex-expander-chevron-open-color, #F96138)}.content-wrapper{display:grid;grid-template-rows:0fr;transition:grid-template-rows .25s cubic-bezier(.4,0,.1,1),padding-bottom .25s cubic-bezier(.4,0,.1,1);padding-bottom:0}.container.open .content-wrapper{grid-template-rows:1fr;padding-bottom:20px}.content{overflow:hidden;font-size:15px;color:var(--apex-expander-content-color, #5D6068);padding-left:30px;padding-right:30px;min-height:0}.container.open .content{overflow:auto}.container.fit-content .content::-webkit-scrollbar{display:none}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); }
|
|
14
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.2", type: ApexExpanderComponent, isStandalone: true, selector: "apex-expander", inputs: { isOpen: "isOpen", maxHeight: "maxHeight" }, ngImport: i0, template: "<div [ngClass]=\"{ container: true, open: isOpen, 'fit-content': !maxHeight }\">\n <div class=\"header\" role=\"button\" tabindex=\"0\" [attr.aria-expanded]=\"isOpen\" [attr.aria-controls]=\"contentId\" (click)=\"isOpen = !isOpen\" (keydown.enter)=\"isOpen = !isOpen\" (keydown.space)=\"$event.preventDefault(); isOpen = !isOpen\">\n <span class=\"title\">\n <ng-content select=\"[title]\"></ng-content>\n </span>\n\n <span class=\"chevron\" aria-hidden=\"true\"></span>\n </div>\n\n <div class=\"content-wrapper\" [id]=\"contentId\">\n <div class=\"content\" [style.max-height]=\"maxHeight ? maxHeight + 'px' : 'none'\">\n <ng-content select=\"[content]\"></ng-content>\n </div>\n </div>\n</div>\n", styles: [":host{display:block;touch-action:manipulation}.container{display:flex;flex-direction:column;background-color:var(--apex-expander-background-color, #FFFFFF);border-radius:8px;border:var(--apex-expander-border, 0px);box-shadow:var(--apex-expander-box-shadow, 0px 4px 8px 0px rgba(214, 214, 214, .35))}.header{display:flex;align-items:center;justify-content:space-between;column-gap:30px;cursor:pointer;padding:20px 30px}.header:focus{outline:var(--apex-expander-outline-color, none)}.header .title{width:100%;font-size:16px;font-weight:500;color:var(--apex-expander-title-color, #0B1222)}.header .chevron{width:8px;height:8px;flex-shrink:0;position:relative;bottom:3px;transform-origin:center;transform:rotate(-135deg);transition:all .25s cubic-bezier(.4,0,.1,1);border-top:2px solid var(--apex-expander-chevron-color, #5D6068);border-left:2px solid var(--apex-expander-chevron-color, #5D6068);border-top-left-radius:3px;border-top-right-radius:1px;border-bottom-left-radius:1px}.container.open .header .chevron{bottom:-3px;transform:rotate(45deg);border-top:2px solid var(--apex-expander-chevron-open-color, #F96138);border-left:2px solid var(--apex-expander-chevron-open-color, #F96138)}.content-wrapper{display:grid;grid-template-rows:0fr;transition:grid-template-rows .25s cubic-bezier(.4,0,.1,1),padding-bottom .25s cubic-bezier(.4,0,.1,1);padding-bottom:0}.container.open .content-wrapper{grid-template-rows:1fr;padding-bottom:20px}.content{overflow:hidden;font-size:15px;color:var(--apex-expander-content-color, #5D6068);padding-left:30px;padding-right:30px;min-height:0}.container.open .content{overflow:auto}.container.fit-content .content::-webkit-scrollbar{display:none}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); }
|
|
12
15
|
}
|
|
13
16
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: ApexExpanderComponent, decorators: [{
|
|
14
17
|
type: Component,
|
|
15
18
|
args: [{ selector: 'apex-expander', imports: [
|
|
16
19
|
NgClass,
|
|
17
|
-
], template: "<div [ngClass]=\"{ container: true, open: isOpen, 'fit-content': !maxHeight }\">\n <div class=\"header\" role=\"button\" tabindex=\"0\" (click)=\"isOpen = !isOpen\">\n <span class=\"title\">\n <ng-content select=\"[title]\"></ng-content>\n </span>\n\n <span class=\"chevron\"></span>\n </div>\n\n <div class=\"content-wrapper\">\n <div class=\"content\" [style.max-height]=\"maxHeight ? maxHeight + 'px' : 'none'\">\n <ng-content select=\"[content]\"></ng-content>\n </div>\n </div>\n</div>\n", styles: [":host{display:block;touch-action:manipulation}.container{display:flex;flex-direction:column;background-color:var(--apex-expander-background-color, #FFFFFF);border-radius:8px;border:var(--apex-expander-border, 0px);box-shadow:var(--apex-expander-box-shadow, 0px 4px 8px 0px rgba(214, 214, 214, .35))}.header{display:flex;align-items:center;justify-content:space-between;column-gap:30px;cursor:pointer;padding:20px 30px}.header:focus{outline:var(--apex-expander-outline-color, none)}.header .title{width:100%;font-size:16px;font-weight:500;color:var(--apex-expander-title-color, #0B1222)}.header .chevron{width:8px;height:8px;flex-shrink:0;position:relative;bottom:3px;transform-origin:center;transform:rotate(-135deg);transition:all .25s cubic-bezier(.4,0,.1,1);border-top:2px solid var(--apex-expander-chevron-color, #5D6068);border-left:2px solid var(--apex-expander-chevron-color, #5D6068);border-top-left-radius:3px;border-top-right-radius:1px;border-bottom-left-radius:1px}.container.open .header .chevron{bottom:-3px;transform:rotate(45deg);border-top:2px solid var(--apex-expander-chevron-open-color, #F96138);border-left:2px solid var(--apex-expander-chevron-open-color, #F96138)}.content-wrapper{display:grid;grid-template-rows:0fr;transition:grid-template-rows .25s cubic-bezier(.4,0,.1,1),padding-bottom .25s cubic-bezier(.4,0,.1,1);padding-bottom:0}.container.open .content-wrapper{grid-template-rows:1fr;padding-bottom:20px}.content{overflow:hidden;font-size:15px;color:var(--apex-expander-content-color, #5D6068);padding-left:30px;padding-right:30px;min-height:0}.container.open .content{overflow:auto}.container.fit-content .content::-webkit-scrollbar{display:none}\n"] }]
|
|
20
|
+
], template: "<div [ngClass]=\"{ container: true, open: isOpen, 'fit-content': !maxHeight }\">\n <div class=\"header\" role=\"button\" tabindex=\"0\" [attr.aria-expanded]=\"isOpen\" [attr.aria-controls]=\"contentId\" (click)=\"isOpen = !isOpen\" (keydown.enter)=\"isOpen = !isOpen\" (keydown.space)=\"$event.preventDefault(); isOpen = !isOpen\">\n <span class=\"title\">\n <ng-content select=\"[title]\"></ng-content>\n </span>\n\n <span class=\"chevron\" aria-hidden=\"true\"></span>\n </div>\n\n <div class=\"content-wrapper\" [id]=\"contentId\">\n <div class=\"content\" [style.max-height]=\"maxHeight ? maxHeight + 'px' : 'none'\">\n <ng-content select=\"[content]\"></ng-content>\n </div>\n </div>\n</div>\n", styles: [":host{display:block;touch-action:manipulation}.container{display:flex;flex-direction:column;background-color:var(--apex-expander-background-color, #FFFFFF);border-radius:8px;border:var(--apex-expander-border, 0px);box-shadow:var(--apex-expander-box-shadow, 0px 4px 8px 0px rgba(214, 214, 214, .35))}.header{display:flex;align-items:center;justify-content:space-between;column-gap:30px;cursor:pointer;padding:20px 30px}.header:focus{outline:var(--apex-expander-outline-color, none)}.header .title{width:100%;font-size:16px;font-weight:500;color:var(--apex-expander-title-color, #0B1222)}.header .chevron{width:8px;height:8px;flex-shrink:0;position:relative;bottom:3px;transform-origin:center;transform:rotate(-135deg);transition:all .25s cubic-bezier(.4,0,.1,1);border-top:2px solid var(--apex-expander-chevron-color, #5D6068);border-left:2px solid var(--apex-expander-chevron-color, #5D6068);border-top-left-radius:3px;border-top-right-radius:1px;border-bottom-left-radius:1px}.container.open .header .chevron{bottom:-3px;transform:rotate(45deg);border-top:2px solid var(--apex-expander-chevron-open-color, #F96138);border-left:2px solid var(--apex-expander-chevron-open-color, #F96138)}.content-wrapper{display:grid;grid-template-rows:0fr;transition:grid-template-rows .25s cubic-bezier(.4,0,.1,1),padding-bottom .25s cubic-bezier(.4,0,.1,1);padding-bottom:0}.container.open .content-wrapper{grid-template-rows:1fr;padding-bottom:20px}.content{overflow:hidden;font-size:15px;color:var(--apex-expander-content-color, #5D6068);padding-left:30px;padding-right:30px;min-height:0}.container.open .content{overflow:auto}.container.fit-content .content::-webkit-scrollbar{display:none}\n"] }]
|
|
18
21
|
}], propDecorators: { isOpen: [{
|
|
19
22
|
type: Input
|
|
20
23
|
}], maxHeight: [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apexara-ng-components-expander.mjs","sources":["../../../../projects/apexara/ng-components/expander/src/expander.component.ts","../../../../projects/apexara/ng-components/expander/src/expander.component.html","../../../../projects/apexara/ng-components/expander/apexara-ng-components-expander.ts"],"sourcesContent":["import { Component, Input } from '@angular/core';\nimport { NgClass } from '@angular/common';\n\n@Component({\n selector: 'apex-expander',\n templateUrl: './expander.component.html',\n styleUrls: ['./expander.component.css'],\n imports: [\n NgClass,\n ],\n})\n\nexport class ApexExpanderComponent {\n\n @Input() isOpen = false;\n @Input() maxHeight: number | null = null;\n\n}\n","<div [ngClass]=\"{ container: true, open: isOpen, 'fit-content': !maxHeight }\">\n <div class=\"header\" role=\"button\" tabindex=\"0\" (click)=\"isOpen = !isOpen\">\n <span class=\"title\">\n <ng-content select=\"[title]\"></ng-content>\n </span>\n\n <span class=\"chevron\"></span>\n </div>\n\n <div class=\"content-wrapper\">\n <div class=\"content\" [style.max-height]=\"maxHeight ? maxHeight + 'px' : 'none'\">\n <ng-content select=\"[content]\"></ng-content>\n </div>\n </div>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;MAYa,qBAAqB,CAAA;AATlC,IAAA,WAAA,GAAA;
|
|
1
|
+
{"version":3,"file":"apexara-ng-components-expander.mjs","sources":["../../../../projects/apexara/ng-components/expander/src/expander.component.ts","../../../../projects/apexara/ng-components/expander/src/expander.component.html","../../../../projects/apexara/ng-components/expander/apexara-ng-components-expander.ts"],"sourcesContent":["import { Component, Input } from '@angular/core';\nimport { NgClass } from '@angular/common';\n\n@Component({\n selector: 'apex-expander',\n templateUrl: './expander.component.html',\n styleUrls: ['./expander.component.css'],\n imports: [\n NgClass,\n ],\n})\n\nexport class ApexExpanderComponent {\n\n private static nextA11yId = 0;\n\n // Links the disclosure header to its panel via aria-controls.\n public readonly contentId = `apex-expander-content-${ApexExpanderComponent.nextA11yId++}`;\n\n @Input() isOpen = false;\n @Input() maxHeight: number | null = null;\n\n}\n","<div [ngClass]=\"{ container: true, open: isOpen, 'fit-content': !maxHeight }\">\n <div class=\"header\" role=\"button\" tabindex=\"0\" [attr.aria-expanded]=\"isOpen\" [attr.aria-controls]=\"contentId\" (click)=\"isOpen = !isOpen\" (keydown.enter)=\"isOpen = !isOpen\" (keydown.space)=\"$event.preventDefault(); isOpen = !isOpen\">\n <span class=\"title\">\n <ng-content select=\"[title]\"></ng-content>\n </span>\n\n <span class=\"chevron\" aria-hidden=\"true\"></span>\n </div>\n\n <div class=\"content-wrapper\" [id]=\"contentId\">\n <div class=\"content\" [style.max-height]=\"maxHeight ? maxHeight + 'px' : 'none'\">\n <ng-content select=\"[content]\"></ng-content>\n </div>\n </div>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;MAYa,qBAAqB,CAAA;AATlC,IAAA,WAAA,GAAA;;AAckB,QAAA,IAAA,CAAA,SAAS,GAAG,CAAA,sBAAA,EAAyB,qBAAqB,CAAC,UAAU,EAAE,EAAE;QAEhF,IAAA,CAAA,MAAM,GAAG,KAAK;QACd,IAAA,CAAA,SAAS,GAAkB,IAAI;AAEzC,IAAA;aARgB,IAAA,CAAA,UAAU,GAAG,CAAH,CAAK;8GAFnB,qBAAqB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;kGAArB,qBAAqB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EAAA,QAAA,EAAA,SAAA,EAAA,WAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECZlC,iwBAeA,EAAA,MAAA,EAAA,CAAA,mpDAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EDPI,OAAO,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,SAAA,CAAA,EAAA,CAAA,EAAA,CAAA,CAAA;;2FAIE,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBATjC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,eAAe,EAAA,OAAA,EAGhB;wBACP,OAAO;AACR,qBAAA,EAAA,QAAA,EAAA,iwBAAA,EAAA,MAAA,EAAA,CAAA,mpDAAA,CAAA,EAAA;;sBAUA;;sBACA;;;AEpBH;;AAEG;;;;"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { input, output, computed, Component } from '@angular/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A filter-bar trigger — the same inset-label chip as apex-select's Inset variant, for controls
|
|
6
|
+
* whose dropdown is a custom panel the consumer owns (a Beds & Baths popover, a More Filters panel)
|
|
7
|
+
* rather than an option list. Empty, it shows the control's name; once a value is set it stacks that
|
|
8
|
+
* name as a small caption above the value, with a clear (×) in place of the caret.
|
|
9
|
+
*
|
|
10
|
+
* It draws its border, caption, value and caret from the same `--apex-select-*` CSS variables as
|
|
11
|
+
* apex-select's Inset variant, so a bar that mixes real selects with these custom filters reads as
|
|
12
|
+
* one set of controls and there is a single visual source of truth — no lookalike CSS to drift.
|
|
13
|
+
*/
|
|
14
|
+
class ApexFilterPillComponent {
|
|
15
|
+
constructor() {
|
|
16
|
+
// The control's name: shown on its own while empty, then as the caption above the value once set.
|
|
17
|
+
this.label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
18
|
+
// The picked value shown under the caption once set; null or empty keeps the name showing alone.
|
|
19
|
+
this.value = input(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
20
|
+
// Open state — rotates the caret and (via the consumer) reflects the panel being open.
|
|
21
|
+
this.open = input(false, ...(ngDevMode ? [{ debugName: "open" }] : []));
|
|
22
|
+
this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
23
|
+
// Whether a clear button replaces the caret once there is a value to clear.
|
|
24
|
+
this.clearable = input(false, ...(ngDevMode ? [{ debugName: "clearable" }] : []));
|
|
25
|
+
// The trigger was activated (not the clear button) — the consumer opens or closes its panel.
|
|
26
|
+
this.pillClick = output();
|
|
27
|
+
// The clear button was activated — the consumer resets the filter.
|
|
28
|
+
this.clearClick = output();
|
|
29
|
+
this.hasValue = computed(() => !!this.value(), ...(ngDevMode ? [{ debugName: "hasValue" }] : []));
|
|
30
|
+
// The clear button shows only when the chip is clearable and actually has a value set.
|
|
31
|
+
this.showClear = computed(() => this.clearable() && this.hasValue(), ...(ngDevMode ? [{ debugName: "showClear" }] : []));
|
|
32
|
+
// The caret shows only while empty; a value swaps it for the clear button, matching the Inset select.
|
|
33
|
+
this.showCaret = computed(() => !this.hasValue(), ...(ngDevMode ? [{ debugName: "showCaret" }] : []));
|
|
34
|
+
}
|
|
35
|
+
onClick() {
|
|
36
|
+
if (!this.disabled()) {
|
|
37
|
+
this.pillClick.emit();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
onClear(event) {
|
|
41
|
+
// Keep the clear from also toggling the panel open.
|
|
42
|
+
event.stopPropagation();
|
|
43
|
+
this.clearClick.emit();
|
|
44
|
+
}
|
|
45
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: ApexFilterPillComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
46
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: ApexFilterPillComponent, isStandalone: true, selector: "apex-filter-pill", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pillClick: "pillClick", clearClick: "clearClick" }, ngImport: i0, template: "<button\n type=\"button\"\n class=\"filter-pill\"\n [class.is-open]=\"open()\"\n [class.has-value]=\"hasValue()\"\n [disabled]=\"disabled()\"\n aria-haspopup=\"dialog\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-label]=\"hasValue() ? label() + ': ' + value() : label()\"\n (click)=\"onClick()\">\n @if (hasValue()) {\n <span class=\"filter-pill-stack\" aria-hidden=\"true\">\n <span class=\"filter-pill-label\">{{ label() }}</span>\n <span class=\"filter-pill-value\">{{ value() }}</span>\n </span>\n } @else {\n <span class=\"filter-pill-placeholder\">{{ label() }}</span>\n }\n\n @if (showClear()) {\n <span class=\"filter-pill-clear\" role=\"button\" [attr.aria-label]=\"'Clear ' + label()\" (click)=\"onClear($event)\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path d=\"M3 3 9 9M9 3 3 9\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n </svg>\n </span>\n }\n\n @if (showCaret()) {\n <span class=\"filter-pill-arrow-wrapper\" aria-hidden=\"true\"><span class=\"filter-pill-arrow\"></span></span>\n }\n</button>\n", styles: [":host{display:block;min-width:0}.filter-pill{width:100%;height:44px;box-sizing:border-box;position:relative;display:flex;align-items:center;gap:8px;border:1px solid var(--apex-select-inset-border-color, #D3D3D3);border-radius:4px;background:transparent;font-family:inherit;cursor:pointer;transition:border .15s ease;padding:0 16px}.filter-pill:not(:disabled):hover{border-color:var(--apex-select-input-border-hover-color, #4B5368)}.filter-pill:disabled{background-color:var(--apex-select-inset-disabled-background-color, #F3F3F3);border-color:var(--apex-select-inset-disabled-border-color, #E4E4E4);cursor:not-allowed}.filter-pill-placeholder{overflow:hidden;flex:1;text-align:left;font-size:13px;font-weight:500;line-height:1;color:var(--apex-select-input-placeholder-color, #7C8182);white-space:nowrap;text-overflow:ellipsis}.filter-pill-stack{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;gap:4px;padding:0 38px 0 16px;pointer-events:none}.filter-pill-label{font-size:var(--apex-select-inset-label-font-size, 10px);font-weight:600;letter-spacing:.04em;text-transform:uppercase;line-height:1;color:var(--apex-select-inset-label-color, #7C8182)}.filter-pill-value{overflow:hidden;font-size:var(--apex-select-inset-value-font-size, 13px);font-weight:600;line-height:1;color:var(--apex-select-inset-value-color, #141414);white-space:nowrap;text-overflow:ellipsis}.filter-pill-clear{position:absolute;top:50%;right:12px;transform:translateY(-50%);width:18px;height:18px;display:inline-grid;place-items:center;border-radius:999px;color:var(--apex-select-inset-clear-color, #7C8182);cursor:pointer}.filter-pill-clear:hover{background:var(--apex-select-inset-clear-hover-background, #141414);color:var(--apex-select-inset-clear-hover-color, #FFFFFF)}.filter-pill-clear svg{width:11px;height:11px;display:block}.filter-pill-arrow-wrapper{width:8px;height:8px;flex:none}.filter-pill-arrow{width:8px;height:8px;display:block;position:relative;bottom:3px;border-top:2px solid var(--apex-select-arrow-color, #5D6068);border-left:2px solid var(--apex-select-arrow-color, #5D6068);border-top-left-radius:3px;border-top-right-radius:1px;border-bottom-left-radius:1px;transition:all .25s ease-in-out;transform-origin:center;transform:rotate(-135deg)}.filter-pill.is-open .filter-pill-arrow{bottom:-2px;border-top-color:var(--apex-select-arrow-checked-color, #F96138);border-left-color:var(--apex-select-arrow-checked-color, #F96138);transform:rotate(45deg)}\n"] }); }
|
|
47
|
+
}
|
|
48
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: ApexFilterPillComponent, decorators: [{
|
|
49
|
+
type: Component,
|
|
50
|
+
args: [{ selector: 'apex-filter-pill', template: "<button\n type=\"button\"\n class=\"filter-pill\"\n [class.is-open]=\"open()\"\n [class.has-value]=\"hasValue()\"\n [disabled]=\"disabled()\"\n aria-haspopup=\"dialog\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-label]=\"hasValue() ? label() + ': ' + value() : label()\"\n (click)=\"onClick()\">\n @if (hasValue()) {\n <span class=\"filter-pill-stack\" aria-hidden=\"true\">\n <span class=\"filter-pill-label\">{{ label() }}</span>\n <span class=\"filter-pill-value\">{{ value() }}</span>\n </span>\n } @else {\n <span class=\"filter-pill-placeholder\">{{ label() }}</span>\n }\n\n @if (showClear()) {\n <span class=\"filter-pill-clear\" role=\"button\" [attr.aria-label]=\"'Clear ' + label()\" (click)=\"onClear($event)\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path d=\"M3 3 9 9M9 3 3 9\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n </svg>\n </span>\n }\n\n @if (showCaret()) {\n <span class=\"filter-pill-arrow-wrapper\" aria-hidden=\"true\"><span class=\"filter-pill-arrow\"></span></span>\n }\n</button>\n", styles: [":host{display:block;min-width:0}.filter-pill{width:100%;height:44px;box-sizing:border-box;position:relative;display:flex;align-items:center;gap:8px;border:1px solid var(--apex-select-inset-border-color, #D3D3D3);border-radius:4px;background:transparent;font-family:inherit;cursor:pointer;transition:border .15s ease;padding:0 16px}.filter-pill:not(:disabled):hover{border-color:var(--apex-select-input-border-hover-color, #4B5368)}.filter-pill:disabled{background-color:var(--apex-select-inset-disabled-background-color, #F3F3F3);border-color:var(--apex-select-inset-disabled-border-color, #E4E4E4);cursor:not-allowed}.filter-pill-placeholder{overflow:hidden;flex:1;text-align:left;font-size:13px;font-weight:500;line-height:1;color:var(--apex-select-input-placeholder-color, #7C8182);white-space:nowrap;text-overflow:ellipsis}.filter-pill-stack{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;gap:4px;padding:0 38px 0 16px;pointer-events:none}.filter-pill-label{font-size:var(--apex-select-inset-label-font-size, 10px);font-weight:600;letter-spacing:.04em;text-transform:uppercase;line-height:1;color:var(--apex-select-inset-label-color, #7C8182)}.filter-pill-value{overflow:hidden;font-size:var(--apex-select-inset-value-font-size, 13px);font-weight:600;line-height:1;color:var(--apex-select-inset-value-color, #141414);white-space:nowrap;text-overflow:ellipsis}.filter-pill-clear{position:absolute;top:50%;right:12px;transform:translateY(-50%);width:18px;height:18px;display:inline-grid;place-items:center;border-radius:999px;color:var(--apex-select-inset-clear-color, #7C8182);cursor:pointer}.filter-pill-clear:hover{background:var(--apex-select-inset-clear-hover-background, #141414);color:var(--apex-select-inset-clear-hover-color, #FFFFFF)}.filter-pill-clear svg{width:11px;height:11px;display:block}.filter-pill-arrow-wrapper{width:8px;height:8px;flex:none}.filter-pill-arrow{width:8px;height:8px;display:block;position:relative;bottom:3px;border-top:2px solid var(--apex-select-arrow-color, #5D6068);border-left:2px solid var(--apex-select-arrow-color, #5D6068);border-top-left-radius:3px;border-top-right-radius:1px;border-bottom-left-radius:1px;transition:all .25s ease-in-out;transform-origin:center;transform:rotate(-135deg)}.filter-pill.is-open .filter-pill-arrow{bottom:-2px;border-top-color:var(--apex-select-arrow-checked-color, #F96138);border-left-color:var(--apex-select-arrow-checked-color, #F96138);transform:rotate(45deg)}\n"] }]
|
|
51
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], pillClick: [{ type: i0.Output, args: ["pillClick"] }], clearClick: [{ type: i0.Output, args: ["clearClick"] }] } });
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Generated bundle index. Do not edit.
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
export { ApexFilterPillComponent };
|
|
58
|
+
//# sourceMappingURL=apexara-ng-components-filter-pill.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apexara-ng-components-filter-pill.mjs","sources":["../../../../projects/apexara/ng-components/filter-pill/src/filter-pill.component.ts","../../../../projects/apexara/ng-components/filter-pill/src/filter-pill.component.html","../../../../projects/apexara/ng-components/filter-pill/apexara-ng-components-filter-pill.ts"],"sourcesContent":["import { input, output, computed, Component } from '@angular/core';\n\n/**\n * A filter-bar trigger — the same inset-label chip as apex-select's Inset variant, for controls\n * whose dropdown is a custom panel the consumer owns (a Beds & Baths popover, a More Filters panel)\n * rather than an option list. Empty, it shows the control's name; once a value is set it stacks that\n * name as a small caption above the value, with a clear (×) in place of the caret.\n *\n * It draws its border, caption, value and caret from the same `--apex-select-*` CSS variables as\n * apex-select's Inset variant, so a bar that mixes real selects with these custom filters reads as\n * one set of controls and there is a single visual source of truth — no lookalike CSS to drift.\n */\n@Component({\n selector: 'apex-filter-pill',\n templateUrl: './filter-pill.component.html',\n styleUrls: ['./filter-pill.component.css'],\n})\n\nexport class ApexFilterPillComponent {\n\n // The control's name: shown on its own while empty, then as the caption above the value once set.\n public label = input<string>('');\n\n // The picked value shown under the caption once set; null or empty keeps the name showing alone.\n public value = input<string | null>(null);\n\n // Open state — rotates the caret and (via the consumer) reflects the panel being open.\n public open = input<boolean>(false);\n\n public disabled = input<boolean>(false);\n\n // Whether a clear button replaces the caret once there is a value to clear.\n public clearable = input<boolean>(false);\n\n // The trigger was activated (not the clear button) — the consumer opens or closes its panel.\n public pillClick = output<void>();\n\n // The clear button was activated — the consumer resets the filter.\n public clearClick = output<void>();\n\n public hasValue = computed<boolean>(() => !!this.value());\n\n // The clear button shows only when the chip is clearable and actually has a value set.\n public showClear = computed<boolean>(() => this.clearable() && this.hasValue());\n\n // The caret shows only while empty; a value swaps it for the clear button, matching the Inset select.\n public showCaret = computed<boolean>(() => !this.hasValue());\n\n public onClick(): void {\n if (!this.disabled()) {\n this.pillClick.emit();\n }\n }\n\n public onClear(event: Event): void {\n // Keep the clear from also toggling the panel open.\n event.stopPropagation();\n this.clearClick.emit();\n }\n\n}\n","<button\n type=\"button\"\n class=\"filter-pill\"\n [class.is-open]=\"open()\"\n [class.has-value]=\"hasValue()\"\n [disabled]=\"disabled()\"\n aria-haspopup=\"dialog\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-label]=\"hasValue() ? label() + ': ' + value() : label()\"\n (click)=\"onClick()\">\n @if (hasValue()) {\n <span class=\"filter-pill-stack\" aria-hidden=\"true\">\n <span class=\"filter-pill-label\">{{ label() }}</span>\n <span class=\"filter-pill-value\">{{ value() }}</span>\n </span>\n } @else {\n <span class=\"filter-pill-placeholder\">{{ label() }}</span>\n }\n\n @if (showClear()) {\n <span class=\"filter-pill-clear\" role=\"button\" [attr.aria-label]=\"'Clear ' + label()\" (click)=\"onClear($event)\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path d=\"M3 3 9 9M9 3 3 9\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n </svg>\n </span>\n }\n\n @if (showCaret()) {\n <span class=\"filter-pill-arrow-wrapper\" aria-hidden=\"true\"><span class=\"filter-pill-arrow\"></span></span>\n }\n</button>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;AAEA;;;;;;;;;AASG;MAOU,uBAAuB,CAAA;AANpC,IAAA,WAAA,GAAA;;AASS,QAAA,IAAA,CAAA,KAAK,GAAG,KAAK,CAAS,EAAE,iDAAC;;AAGzB,QAAA,IAAA,CAAA,KAAK,GAAG,KAAK,CAAgB,IAAI,iDAAC;;AAGlC,QAAA,IAAA,CAAA,IAAI,GAAG,KAAK,CAAU,KAAK,gDAAC;AAE5B,QAAA,IAAA,CAAA,QAAQ,GAAG,KAAK,CAAU,KAAK,oDAAC;;AAGhC,QAAA,IAAA,CAAA,SAAS,GAAG,KAAK,CAAU,KAAK,qDAAC;;QAGjC,IAAA,CAAA,SAAS,GAAG,MAAM,EAAQ;;QAG1B,IAAA,CAAA,UAAU,GAAG,MAAM,EAAQ;AAE3B,QAAA,IAAA,CAAA,QAAQ,GAAG,QAAQ,CAAU,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,oDAAC;;AAGlD,QAAA,IAAA,CAAA,SAAS,GAAG,QAAQ,CAAU,MAAM,IAAI,CAAC,SAAS,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE,qDAAC;;AAGxE,QAAA,IAAA,CAAA,SAAS,GAAG,QAAQ,CAAU,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,WAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAC;AAc7D,IAAA;IAZQ,OAAO,GAAA;AACZ,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE;AACpB,YAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;QACvB;IACF;AAEO,IAAA,OAAO,CAAC,KAAY,EAAA;;QAEzB,KAAK,CAAC,eAAe,EAAE;AACvB,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;IACxB;8GAxCW,uBAAuB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAAvB,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,uBAAuB,iwBClBpC,wwCA+BA,EAAA,MAAA,EAAA,CAAA,q7EAAA,CAAA,EAAA,CAAA,CAAA;;2FDba,uBAAuB,EAAA,UAAA,EAAA,CAAA;kBANnC,SAAS;+BACE,kBAAkB,EAAA,QAAA,EAAA,wwCAAA,EAAA,MAAA,EAAA,CAAA,q7EAAA,CAAA,EAAA;;;AEb9B;;AAEG;;;;"}
|
|
@@ -81,7 +81,9 @@ class ApexImageComponent {
|
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
init() {
|
|
84
|
-
|
|
84
|
+
// alt must be PROVIDED, but empty string is valid: it marks the image as
|
|
85
|
+
// decorative (rendered with aria-hidden) instead of suppressing rendering.
|
|
86
|
+
if (!this.src || this.alt === undefined || this.alt === null) {
|
|
85
87
|
return;
|
|
86
88
|
}
|
|
87
89
|
const img = this.imgService.loadImg(this.src);
|
|
@@ -103,6 +105,9 @@ class ApexImageComponent {
|
|
|
103
105
|
const elem = this.element.nativeElement;
|
|
104
106
|
elem.innerHTML = '';
|
|
105
107
|
this.setStyling(img);
|
|
108
|
+
if (this.loading) {
|
|
109
|
+
this.renderer.setAttribute(img, 'loading', this.loading);
|
|
110
|
+
}
|
|
106
111
|
img.src = url;
|
|
107
112
|
this.renderer.appendChild(elem, img);
|
|
108
113
|
this.setAlt(this.alt);
|
|
@@ -119,9 +124,9 @@ class ApexImageComponent {
|
|
|
119
124
|
elem.innerHTML = '';
|
|
120
125
|
this.renderer.appendChild(elem, clonedSvg);
|
|
121
126
|
this.helper.loaded = true;
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
127
|
+
// init() guarantees alt is a string here; '' marks the svg decorative
|
|
128
|
+
// (aria-hidden) instead of leaving it announced with no name.
|
|
129
|
+
this.setAlt(this.alt);
|
|
125
130
|
this.copyNgContentAttribute(elem, clonedSvg);
|
|
126
131
|
}
|
|
127
132
|
setAlt(label) {
|
|
@@ -137,6 +142,7 @@ class ApexImageComponent {
|
|
|
137
142
|
}
|
|
138
143
|
else {
|
|
139
144
|
this.renderer.removeAttribute(child, 'aria-label');
|
|
145
|
+
this.renderer.removeAttribute(child, 'role');
|
|
140
146
|
}
|
|
141
147
|
}
|
|
142
148
|
else {
|
|
@@ -145,7 +151,9 @@ class ApexImageComponent {
|
|
|
145
151
|
this.renderer.setAttribute(child, 'alt', label);
|
|
146
152
|
}
|
|
147
153
|
else {
|
|
154
|
+
// Named inline svg = meaningful image for AT.
|
|
148
155
|
this.renderer.setAttribute(child, 'aria-label', label);
|
|
156
|
+
this.renderer.setAttribute(child, 'role', 'img');
|
|
149
157
|
}
|
|
150
158
|
}
|
|
151
159
|
}
|
|
@@ -186,7 +194,7 @@ class ApexImageComponent {
|
|
|
186
194
|
}
|
|
187
195
|
}
|
|
188
196
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: ApexImageComponent, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: ApexImgService }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
189
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.2", type: ApexImageComponent, isStandalone: true, selector: "apex-img", inputs: { src: "src", alt: "alt" }, usesOnChanges: true, ngImport: i0, template: '<ng-content></ng-content>', isInline: true }); }
|
|
197
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.2", type: ApexImageComponent, isStandalone: true, selector: "apex-img", inputs: { src: "src", alt: "alt", loading: "loading" }, usesOnChanges: true, ngImport: i0, template: '<ng-content></ng-content>', isInline: true }); }
|
|
190
198
|
}
|
|
191
199
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: ApexImageComponent, decorators: [{
|
|
192
200
|
type: Component,
|
|
@@ -201,6 +209,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
201
209
|
type: Input
|
|
202
210
|
}], alt: [{
|
|
203
211
|
type: Input
|
|
212
|
+
}], loading: [{
|
|
213
|
+
type: Input
|
|
204
214
|
}] } });
|
|
205
215
|
|
|
206
216
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apexara-ng-components-image.mjs","sources":["../../../../projects/apexara/ng-components/image/src/apex-img.service.ts","../../../../projects/apexara/ng-components/image/src/apex-img.component.ts","../../../../projects/apexara/ng-components/image/apexara-ng-components-image.ts"],"sourcesContent":["import { Inject, Injectable } from '@angular/core';\nimport { DOCUMENT } from '@angular/common';\n\nimport { HttpClient } from '@angular/common/http';\n\nimport { Observable, of } from 'rxjs';\nimport { tap, finalize, share, map, catchError } from 'rxjs/operators';\n\n@Injectable({\n providedIn: 'root'\n})\n\nexport class ApexImgService {\n\n constructor(private http: HttpClient, @Inject(DOCUMENT) private document: Document) { }\n\n private svgs = new Map<string, SVGElement>();\n private svgsLoading = new Map<string, Observable<SVGElement>>();\n\n public defaultSvg = '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\"><path d=\"m 4 1 c -1.644531 0 -3 1.355469 -3 3 v 1 h 1 v -1 c 0 -1.109375 0.890625 -2 2 -2 h 1 v -1 z m 2 0 v 1 h 4 v -1 z m 5 0 v 1 h 1 c 1.109375 0 2 0.890625 2 2 v 1 h 1 v -1 c 0 -1.644531 -1.355469 -3 -3 -3 z m -5 4 c -0.550781 0 -1 0.449219 -1 1 s 0.449219 1 1 1 s 1 -0.449219 1 -1 s -0.449219 -1 -1 -1 z m -5 1 v 4 h 1 v -4 z m 13 0 v 4 h 1 v -4 z m -4.5 2 l -2 2 l -1.5 -1 l -2 2 v 0.5 c 0 0.5 0.5 0.5 0.5 0.5 h 7 s 0.472656 -0.035156 0.5 -0.5 v -1 z m -8.5 3 v 1 c 0 1.644531 1.355469 3 3 3 h 1 v -1 h -1 c -1.109375 0 -2 -0.890625 -2 -2 v -1 z m 13 0 v 1 c 0 1.109375 -0.890625 2 -2 2 h -1 v 1 h 1 c 1.644531 0 3 -1.355469 3 -3 v -1 z m -8 3 v 1 h 4 v -1 z m 0 0\" fill=\"#2e3434\" fill-opacity=\"0.34902\"/></svg>'; \n\n public loadImg(url: string): Observable<SVGElement> | string {\n if (!url.endsWith('.svg')) {\n return url;\n }\n\n if (this.svgs.has(url)) {\n return of(this.svgs.get(url) as SVGElement);\n }\n\n if (this.svgsLoading.has(url)) {\n return this.svgsLoading.get(url) as Observable<SVGElement>;\n }\n\n const observable = this.getSvg(url)\n .pipe(\n catchError(() => { return of(this.defaultSvg); }),\n map(content => this.createSVG(content)),\n tap(element => this.svgs.set(url, element as SVGElement)),\n finalize(() => this.svgsLoading.delete(url)),\n share()\n );\n\n this.svgsLoading.set(url, observable);\n\n return observable;\n }\n\n private getSvg(url: string): Observable<string> {\n return this.http.get(url, { responseType: 'text' });\n }\n\n private createSVG(content: string): SVGElement {\n const div = this.document.createElement('DIV');\n\n div.innerHTML = content;\n\n return div.querySelector('svg') as SVGElement;\n }\n\n}\n","import { Component, ElementRef, Inject, Input, Renderer2, SimpleChanges } from '@angular/core';\nimport { DOCUMENT } from '@angular/common';\n\nimport { Subscription } from 'rxjs';\n\nimport { ApexImgService } from './apex-img.service';\n\nclass ImageHelper {\n loaded = false;\n imgSub?: Subscription;\n}\n\n@Component({\n selector: 'apex-img',\n template: '<ng-content></ng-content>',\n})\n\nexport class ApexImageComponent {\n\n constructor(\n private element: ElementRef,\n private renderer: Renderer2,\n private imgService: ApexImgService,\n @Inject(DOCUMENT) private document: Document) {\n }\n\n @Input() src!: string;\n @Input() alt!: string;\n\n private helper = new ImageHelper();\n\n public ngOnInit(): void {\n this.init();\n }\n\n public ngOnDestroy(): void {\n this.destroy();\n }\n\n public ngOnChanges(changeRecord: SimpleChanges): void {\n if (!this.helper.loaded) {\n return;\n }\n\n if (changeRecord['src']) {\n this.destroy();\n\n this.init();\n }\n\n if (changeRecord['alt']) {\n this.setAlt(changeRecord['alt'].currentValue);\n }\n }\n\n private init(): void {\n if (!this.src || !this.alt) {\n return;\n }\n\n const img = this.imgService.loadImg(this.src);\n\n if (typeof img === 'string') {\n this.initImage(img);\n\n return;\n }\n\n this.helper.imgSub = img.subscribe(img => { this.initSvg(img); });\n }\n\n private destroy(): void {\n if (this.helper.imgSub) {\n this.helper.imgSub.unsubscribe();\n }\n\n this.helper = new ImageHelper();\n }\n\n private initImage(url: string): void {\n const img = this.document.createElement('img');\n img.onerror = () => { this.onImgError(elem, img); };\n \n const elem = this.element.nativeElement;\n elem.innerHTML = '';\n\n this.setStyling(img);\n\n img.src = url;\n\n this.renderer.appendChild(elem, img);\n this.setAlt(this.alt);\n \n this.helper.loaded = true;\n this.copyNgContentAttribute(elem, img);\n }\n\n private initSvg(svg: SVGElement): void {\n if (this.helper.loaded || !svg) {\n return;\n }\n\n const clonedSvg = svg.cloneNode(true) as SVGElement;\n\n this.setStyling(clonedSvg);\n\n const elem = this.element.nativeElement;\n elem.innerHTML = '';\n\n this.renderer.appendChild(elem, clonedSvg);\n this.helper.loaded = true;\n\n if (!(this.alt === undefined && elem.firstChild.hasAttribute('aria-label')) && this.alt) {\n this.setAlt(this.alt);\n }\n\n this.copyNgContentAttribute(elem, clonedSvg);\n }\n\n private setAlt(label: string): void {\n const child = this.element.nativeElement.firstChild;\n\n if (!child) {\n return;\n }\n\n const isImg = child instanceof HTMLImageElement;\n\n if (label === '') {\n this.renderer.setAttribute(child, 'aria-hidden', 'true');\n\n if (isImg) {\n this.renderer.setAttribute(child, 'alt', '');\n } else {\n this.renderer.removeAttribute(child, 'aria-label');\n }\n } else {\n this.renderer.removeAttribute(child, 'aria-hidden');\n\n if (isImg) {\n this.renderer.setAttribute(child, 'alt', label);\n } else {\n this.renderer.setAttribute(child, 'aria-label', label);\n }\n }\n }\n\n private setStyling(element: SVGElement | HTMLImageElement) {\n this.element.nativeElement.style.display = 'flex';\n this.element.nativeElement.style.justifyContent = 'center';\n this.element.nativeElement.style.alignItems = 'center';\n\n element.style.width = 'inherit';\n element.style.maxWidth = 'inherit';\n\n element.style.height = 'inherit';\n element.style.maxHeight = 'inherit';\n }\n\n private onImgError(element: any, img: HTMLImageElement): void {\n this.renderer.removeChild(element, img);\n\n let svg = document.createRange().createContextualFragment(this.imgService.defaultSvg);\n\n this.renderer.appendChild(element, svg);\n\n setTimeout(() => {\n this.renderer.setAttribute(element.firstChild, 'aria-label', 'A broken or missing image');\n });\n }\n\n private copyNgContentAttribute(hostElem: any, icon: SVGElement | HTMLImageElement) {\n const attributes = hostElem.attributes as NamedNodeMap;\n\n for (let i = 0; i < attributes.length; i += 1) {\n const attribute = attributes.item(i);\n \n if (attribute && attribute.name.startsWith('_ngcontent')) {\n this.setNgContentAttribute(icon, attribute.name);\n break;\n }\n }\n }\n\n private setNgContentAttribute(parent: Node, attributeName: string) {\n this.renderer.setAttribute(parent, attributeName, '');\n\n for (let i = 0; i < parent.childNodes.length; i += 1) {\n const child = parent.childNodes[i];\n\n if (child instanceof Element) {\n this.setNgContentAttribute(child, attributeName);\n }\n }\n }\n\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"apexara-ng-components-image.mjs","sources":["../../../../projects/apexara/ng-components/image/src/apex-img.service.ts","../../../../projects/apexara/ng-components/image/src/apex-img.component.ts","../../../../projects/apexara/ng-components/image/apexara-ng-components-image.ts"],"sourcesContent":["import { Inject, Injectable } from '@angular/core';\nimport { DOCUMENT } from '@angular/common';\n\nimport { HttpClient } from '@angular/common/http';\n\nimport { Observable, of } from 'rxjs';\nimport { tap, finalize, share, map, catchError } from 'rxjs/operators';\n\n@Injectable({\n providedIn: 'root'\n})\n\nexport class ApexImgService {\n\n constructor(private http: HttpClient, @Inject(DOCUMENT) private document: Document) { }\n\n private svgs = new Map<string, SVGElement>();\n private svgsLoading = new Map<string, Observable<SVGElement>>();\n\n public defaultSvg = '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\"><path d=\"m 4 1 c -1.644531 0 -3 1.355469 -3 3 v 1 h 1 v -1 c 0 -1.109375 0.890625 -2 2 -2 h 1 v -1 z m 2 0 v 1 h 4 v -1 z m 5 0 v 1 h 1 c 1.109375 0 2 0.890625 2 2 v 1 h 1 v -1 c 0 -1.644531 -1.355469 -3 -3 -3 z m -5 4 c -0.550781 0 -1 0.449219 -1 1 s 0.449219 1 1 1 s 1 -0.449219 1 -1 s -0.449219 -1 -1 -1 z m -5 1 v 4 h 1 v -4 z m 13 0 v 4 h 1 v -4 z m -4.5 2 l -2 2 l -1.5 -1 l -2 2 v 0.5 c 0 0.5 0.5 0.5 0.5 0.5 h 7 s 0.472656 -0.035156 0.5 -0.5 v -1 z m -8.5 3 v 1 c 0 1.644531 1.355469 3 3 3 h 1 v -1 h -1 c -1.109375 0 -2 -0.890625 -2 -2 v -1 z m 13 0 v 1 c 0 1.109375 -0.890625 2 -2 2 h -1 v 1 h 1 c 1.644531 0 3 -1.355469 3 -3 v -1 z m -8 3 v 1 h 4 v -1 z m 0 0\" fill=\"#2e3434\" fill-opacity=\"0.34902\"/></svg>'; \n\n public loadImg(url: string): Observable<SVGElement> | string {\n if (!url.endsWith('.svg')) {\n return url;\n }\n\n if (this.svgs.has(url)) {\n return of(this.svgs.get(url) as SVGElement);\n }\n\n if (this.svgsLoading.has(url)) {\n return this.svgsLoading.get(url) as Observable<SVGElement>;\n }\n\n const observable = this.getSvg(url)\n .pipe(\n catchError(() => { return of(this.defaultSvg); }),\n map(content => this.createSVG(content)),\n tap(element => this.svgs.set(url, element as SVGElement)),\n finalize(() => this.svgsLoading.delete(url)),\n share()\n );\n\n this.svgsLoading.set(url, observable);\n\n return observable;\n }\n\n private getSvg(url: string): Observable<string> {\n return this.http.get(url, { responseType: 'text' });\n }\n\n private createSVG(content: string): SVGElement {\n const div = this.document.createElement('DIV');\n\n div.innerHTML = content;\n\n return div.querySelector('svg') as SVGElement;\n }\n\n}\n","import { Component, ElementRef, Inject, Input, Renderer2, SimpleChanges } from '@angular/core';\nimport { DOCUMENT } from '@angular/common';\n\nimport { Subscription } from 'rxjs';\n\nimport { ApexImgService } from './apex-img.service';\n\nclass ImageHelper {\n loaded = false;\n imgSub?: Subscription;\n}\n\n@Component({\n selector: 'apex-img',\n template: '<ng-content></ng-content>',\n})\n\nexport class ApexImageComponent {\n\n constructor(\n private element: ElementRef,\n private renderer: Renderer2,\n private imgService: ApexImgService,\n @Inject(DOCUMENT) private document: Document) {\n }\n\n @Input() src!: string;\n @Input() alt!: string;\n @Input() loading?: 'lazy' | 'eager';\n\n private helper = new ImageHelper();\n\n public ngOnInit(): void {\n this.init();\n }\n\n public ngOnDestroy(): void {\n this.destroy();\n }\n\n public ngOnChanges(changeRecord: SimpleChanges): void {\n if (!this.helper.loaded) {\n return;\n }\n\n if (changeRecord['src']) {\n this.destroy();\n\n this.init();\n }\n\n if (changeRecord['alt']) {\n this.setAlt(changeRecord['alt'].currentValue);\n }\n }\n\n private init(): void {\n // alt must be PROVIDED, but empty string is valid: it marks the image as\n // decorative (rendered with aria-hidden) instead of suppressing rendering.\n if (!this.src || this.alt === undefined || this.alt === null) {\n return;\n }\n\n const img = this.imgService.loadImg(this.src);\n\n if (typeof img === 'string') {\n this.initImage(img);\n\n return;\n }\n\n this.helper.imgSub = img.subscribe(img => { this.initSvg(img); });\n }\n\n private destroy(): void {\n if (this.helper.imgSub) {\n this.helper.imgSub.unsubscribe();\n }\n\n this.helper = new ImageHelper();\n }\n\n private initImage(url: string): void {\n const img = this.document.createElement('img');\n img.onerror = () => { this.onImgError(elem, img); };\n \n const elem = this.element.nativeElement;\n elem.innerHTML = '';\n\n this.setStyling(img);\n\n if (this.loading) {\n this.renderer.setAttribute(img, 'loading', this.loading);\n }\n\n img.src = url;\n\n this.renderer.appendChild(elem, img);\n this.setAlt(this.alt);\n \n this.helper.loaded = true;\n this.copyNgContentAttribute(elem, img);\n }\n\n private initSvg(svg: SVGElement): void {\n if (this.helper.loaded || !svg) {\n return;\n }\n\n const clonedSvg = svg.cloneNode(true) as SVGElement;\n\n this.setStyling(clonedSvg);\n\n const elem = this.element.nativeElement;\n elem.innerHTML = '';\n\n this.renderer.appendChild(elem, clonedSvg);\n this.helper.loaded = true;\n\n // init() guarantees alt is a string here; '' marks the svg decorative\n // (aria-hidden) instead of leaving it announced with no name.\n this.setAlt(this.alt);\n\n this.copyNgContentAttribute(elem, clonedSvg);\n }\n\n private setAlt(label: string): void {\n const child = this.element.nativeElement.firstChild;\n\n if (!child) {\n return;\n }\n\n const isImg = child instanceof HTMLImageElement;\n\n if (label === '') {\n this.renderer.setAttribute(child, 'aria-hidden', 'true');\n\n if (isImg) {\n this.renderer.setAttribute(child, 'alt', '');\n } else {\n this.renderer.removeAttribute(child, 'aria-label');\n this.renderer.removeAttribute(child, 'role');\n }\n } else {\n this.renderer.removeAttribute(child, 'aria-hidden');\n\n if (isImg) {\n this.renderer.setAttribute(child, 'alt', label);\n } else {\n // Named inline svg = meaningful image for AT.\n this.renderer.setAttribute(child, 'aria-label', label);\n this.renderer.setAttribute(child, 'role', 'img');\n }\n }\n }\n\n private setStyling(element: SVGElement | HTMLImageElement) {\n this.element.nativeElement.style.display = 'flex';\n this.element.nativeElement.style.justifyContent = 'center';\n this.element.nativeElement.style.alignItems = 'center';\n\n element.style.width = 'inherit';\n element.style.maxWidth = 'inherit';\n\n element.style.height = 'inherit';\n element.style.maxHeight = 'inherit';\n }\n\n private onImgError(element: any, img: HTMLImageElement): void {\n this.renderer.removeChild(element, img);\n\n let svg = document.createRange().createContextualFragment(this.imgService.defaultSvg);\n\n this.renderer.appendChild(element, svg);\n\n setTimeout(() => {\n this.renderer.setAttribute(element.firstChild, 'aria-label', 'A broken or missing image');\n });\n }\n\n private copyNgContentAttribute(hostElem: any, icon: SVGElement | HTMLImageElement) {\n const attributes = hostElem.attributes as NamedNodeMap;\n\n for (let i = 0; i < attributes.length; i += 1) {\n const attribute = attributes.item(i);\n \n if (attribute && attribute.name.startsWith('_ngcontent')) {\n this.setNgContentAttribute(icon, attribute.name);\n break;\n }\n }\n }\n\n private setNgContentAttribute(parent: Node, attributeName: string) {\n this.renderer.setAttribute(parent, attributeName, '');\n\n for (let i = 0; i < parent.childNodes.length; i += 1) {\n const child = parent.childNodes[i];\n\n if (child instanceof Element) {\n this.setNgContentAttribute(child, attributeName);\n }\n }\n }\n\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|