@byuhbll/components 4.3.2 → 4.4.1
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/esm2022/lib/snackbar/snackbar.component.mjs +151 -0
- package/esm2022/lib/snackbar/snackbar.service.mjs +90 -0
- package/esm2022/lib/status-button/status-button.component.mjs +13 -3
- package/esm2022/public-api.mjs +3 -1
- package/fesm2022/byuhbll-components.mjs +249 -5
- package/fesm2022/byuhbll-components.mjs.map +1 -1
- package/lib/snackbar/snackbar.component.d.ts +67 -0
- package/lib/snackbar/snackbar.service.d.ts +20 -0
- package/lib/status-button/status-button.component.d.ts +15 -1
- package/package.json +1 -1
- package/public-api.d.ts +2 -0
- package/styles/scss/_vars.scss +10 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as i1 from '@angular/common';
|
|
2
|
-
import { CommonModule, DatePipe, DOCUMENT, LowerCasePipe, NgIf } from '@angular/common';
|
|
2
|
+
import { CommonModule, DatePipe, DOCUMENT, LowerCasePipe, NgIf, NgClass } from '@angular/common';
|
|
3
3
|
import { toSignal, toObservable } from '@angular/core/rxjs-interop';
|
|
4
4
|
import { HttpClient } from '@angular/common/http';
|
|
5
5
|
import * as i0 from '@angular/core';
|
|
6
|
-
import { Component, ChangeDetectionStrategy, ViewChild, Input, input, EventEmitter, Output, inject, computed, ViewChildren, Pipe, Renderer2, viewChild, HostListener, ElementRef, ViewEncapsulation, booleanAttribute } from '@angular/core';
|
|
6
|
+
import { Component, ChangeDetectionStrategy, ViewChild, Input, input, EventEmitter, Output, inject, computed, ViewChildren, Pipe, Renderer2, viewChild, HostListener, ElementRef, ViewEncapsulation, booleanAttribute, createComponent, Injectable } from '@angular/core';
|
|
7
7
|
import { trigger, transition, group, style, query, animateChild, animate } from '@angular/animations';
|
|
8
8
|
import { map, of, switchMap, shareReplay, combineLatest, Subject, Subscription } from 'rxjs';
|
|
9
9
|
import { BreakpointObserver } from '@angular/cdk/layout';
|
|
@@ -2187,6 +2187,7 @@ class StatusButtonComponent {
|
|
|
2187
2187
|
this._rightIcon = '';
|
|
2188
2188
|
this._hideLeftIcon = false;
|
|
2189
2189
|
this._hideRightIcon = false;
|
|
2190
|
+
this._clearVariant = false;
|
|
2190
2191
|
}
|
|
2191
2192
|
set status(value) {
|
|
2192
2193
|
this._status = value || 'info';
|
|
@@ -2222,6 +2223,12 @@ class StatusButtonComponent {
|
|
|
2222
2223
|
get hideRightIcon() {
|
|
2223
2224
|
return this._hideRightIcon;
|
|
2224
2225
|
}
|
|
2226
|
+
set clearVariant(value) {
|
|
2227
|
+
this._clearVariant = value;
|
|
2228
|
+
}
|
|
2229
|
+
get clearVariant() {
|
|
2230
|
+
return this._clearVariant;
|
|
2231
|
+
}
|
|
2225
2232
|
/** helper for default left icons */
|
|
2226
2233
|
getDefaultLeftIcon(status) {
|
|
2227
2234
|
switch (status) {
|
|
@@ -2240,11 +2247,11 @@ class StatusButtonComponent {
|
|
|
2240
2247
|
}
|
|
2241
2248
|
}
|
|
2242
2249
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.0", ngImport: i0, type: StatusButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2243
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "18.1.0", type: StatusButtonComponent, isStandalone: true, selector: "lib-status-button", inputs: { label: "label", status: "status", leftIcon: "leftIcon", rightIcon: "rightIcon", hideLeftIcon: ["hideLeftIcon", "hideLeftIcon", booleanAttribute], hideRightIcon: ["hideRightIcon", "hideRightIcon", booleanAttribute] }, ngImport: i0, template: "<button\n type=\"button\"\n [
|
|
2250
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "18.1.0", type: StatusButtonComponent, isStandalone: true, selector: "lib-status-button", inputs: { label: "label", status: "status", leftIcon: "leftIcon", rightIcon: "rightIcon", hideLeftIcon: ["hideLeftIcon", "hideLeftIcon", booleanAttribute], hideRightIcon: ["hideRightIcon", "hideRightIcon", booleanAttribute], clearVariant: ["clearVariant", "clearVariant", booleanAttribute] }, ngImport: i0, template: "<button\n type=\"button\"\n [ngClass]=\"[\n status,\n clearVariant ? 'strokeless transparent-bg' : ''\n ]\"\n>\n <span *ngIf=\"leftIcon\" class=\"icon material-symbols-outlined\">{{ leftIcon }}</span>\n {{ label }}\n <span *ngIf=\"rightIcon\" class=\"icon material-symbols-outlined\">{{ rightIcon }}</span>\n</button>\n", styles: ["button{align-items:center;background-color:#ecf2f6;border:1px solid #457fa6;border-radius:4px;color:#3e7295;display:inline-flex;flex-shrink:0;font-size:1em;font-weight:400;gap:.5em;height:2.25em;justify-content:center;padding:var(--status-button-padding, .25em .5em)}button .icon{font-size:1.25em}button:focus{outline:2px solid #b967c7;outline-offset:2px}button:hover{background-color:#a2bfd3;color:#26485f;cursor:pointer}button.success{background-color:#ebf6ee;border:1px solid #3ba35a;color:#1d562e}button.success:hover{background-color:#9dd1ac;color:#1d562e}button.info{background-color:#ecf2f6;border:1px solid #457fa6;color:#3e7295}button.info:hover{background-color:#a2bfd3;color:#26485f}button.warning{background-color:#faf9ec;border:1px solid #d1c844;color:#635f04}button.warning:hover{background-color:#e8e3a1;color:#635f04}button.error{background-color:#f9ecec;border:1px solid #c73e3d;color:#702121}button.error:hover{background-color:#e39e9e;color:#702121}button.disabled{background-color:#e7e7e7;border:1px solid #8f8f8f;color:#767676}button.disabled:hover{background-color:#d0d0d0;color:#141414}button.strokeless{border:0px}button.transparent-bg{background:transparent}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
|
|
2244
2251
|
}
|
|
2245
2252
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.0", ngImport: i0, type: StatusButtonComponent, decorators: [{
|
|
2246
2253
|
type: Component,
|
|
2247
|
-
args: [{ selector: 'lib-status-button', standalone: true, imports: [CommonModule, NgIf], template: "<button\n type=\"button\"\n [
|
|
2254
|
+
args: [{ selector: 'lib-status-button', standalone: true, imports: [CommonModule, NgIf], template: "<button\n type=\"button\"\n [ngClass]=\"[\n status,\n clearVariant ? 'strokeless transparent-bg' : ''\n ]\"\n>\n <span *ngIf=\"leftIcon\" class=\"icon material-symbols-outlined\">{{ leftIcon }}</span>\n {{ label }}\n <span *ngIf=\"rightIcon\" class=\"icon material-symbols-outlined\">{{ rightIcon }}</span>\n</button>\n", styles: ["button{align-items:center;background-color:#ecf2f6;border:1px solid #457fa6;border-radius:4px;color:#3e7295;display:inline-flex;flex-shrink:0;font-size:1em;font-weight:400;gap:.5em;height:2.25em;justify-content:center;padding:var(--status-button-padding, .25em .5em)}button .icon{font-size:1.25em}button:focus{outline:2px solid #b967c7;outline-offset:2px}button:hover{background-color:#a2bfd3;color:#26485f;cursor:pointer}button.success{background-color:#ebf6ee;border:1px solid #3ba35a;color:#1d562e}button.success:hover{background-color:#9dd1ac;color:#1d562e}button.info{background-color:#ecf2f6;border:1px solid #457fa6;color:#3e7295}button.info:hover{background-color:#a2bfd3;color:#26485f}button.warning{background-color:#faf9ec;border:1px solid #d1c844;color:#635f04}button.warning:hover{background-color:#e8e3a1;color:#635f04}button.error{background-color:#f9ecec;border:1px solid #c73e3d;color:#702121}button.error:hover{background-color:#e39e9e;color:#702121}button.disabled{background-color:#e7e7e7;border:1px solid #8f8f8f;color:#767676}button.disabled:hover{background-color:#d0d0d0;color:#141414}button.strokeless{border:0px}button.transparent-bg{background:transparent}\n"] }]
|
|
2248
2255
|
}], propDecorators: { label: [{
|
|
2249
2256
|
type: Input,
|
|
2250
2257
|
args: [{ required: true }]
|
|
@@ -2260,8 +2267,245 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.0", ngImpor
|
|
|
2260
2267
|
}], hideRightIcon: [{
|
|
2261
2268
|
type: Input,
|
|
2262
2269
|
args: [{ transform: booleanAttribute }]
|
|
2270
|
+
}], clearVariant: [{
|
|
2271
|
+
type: Input,
|
|
2272
|
+
args: [{ transform: booleanAttribute }]
|
|
2273
|
+
}] } });
|
|
2274
|
+
|
|
2275
|
+
const purposeToStatusMap = {
|
|
2276
|
+
default: 'info',
|
|
2277
|
+
info: 'info',
|
|
2278
|
+
success: 'success',
|
|
2279
|
+
error: 'error',
|
|
2280
|
+
warning: 'warning',
|
|
2281
|
+
};
|
|
2282
|
+
class SnackbarComponent {
|
|
2283
|
+
constructor() {
|
|
2284
|
+
this.purpose = 'default';
|
|
2285
|
+
this.title = 'Snackbar Title';
|
|
2286
|
+
this.description = 'Lorem ipsum';
|
|
2287
|
+
this.fieldPlaceholder = 'Placeholder';
|
|
2288
|
+
this.titleIcon = 'info';
|
|
2289
|
+
this.showTitle = true;
|
|
2290
|
+
this.showTitleIcon = true;
|
|
2291
|
+
this.titleIconFilled = false;
|
|
2292
|
+
this.showClose = true;
|
|
2293
|
+
this.showProgressBar = true;
|
|
2294
|
+
this.showField = true;
|
|
2295
|
+
this.showButton = true;
|
|
2296
|
+
this.autoDismiss = true;
|
|
2297
|
+
this.visible = true;
|
|
2298
|
+
this.progressMs = 5000;
|
|
2299
|
+
this.y = 24;
|
|
2300
|
+
this.closed = new EventEmitter();
|
|
2301
|
+
this.visibleChange = new EventEmitter();
|
|
2302
|
+
this.buttonClicked = new EventEmitter();
|
|
2303
|
+
this.isOpen = false;
|
|
2304
|
+
this.EXIT_MS = 300;
|
|
2305
|
+
}
|
|
2306
|
+
ngOnInit() {
|
|
2307
|
+
if (this.visible) {
|
|
2308
|
+
// enter on next tick
|
|
2309
|
+
setTimeout(() => (this.isOpen = true), 0);
|
|
2310
|
+
this.startDismissTimer();
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2313
|
+
ngOnChanges(changes) {
|
|
2314
|
+
if ('visible' in changes) {
|
|
2315
|
+
// when parent toggles visible
|
|
2316
|
+
if (this.visible) {
|
|
2317
|
+
// becoming visible -> open + (re)start timer
|
|
2318
|
+
this.isOpen = false;
|
|
2319
|
+
setTimeout(() => (this.isOpen = true), 0);
|
|
2320
|
+
this.startDismissTimer();
|
|
2321
|
+
}
|
|
2322
|
+
else {
|
|
2323
|
+
// becoming hidden -> stop timers and ensure closed state
|
|
2324
|
+
this.clearDismissTimer();
|
|
2325
|
+
this.isOpen = false;
|
|
2326
|
+
}
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
ngOnDestroy() {
|
|
2330
|
+
this.clearDismissTimer();
|
|
2331
|
+
}
|
|
2332
|
+
// used by the × button, done button, and auto-dismiss
|
|
2333
|
+
close(emitButtonClicked = false) {
|
|
2334
|
+
if (!this.isOpen && !this.visible)
|
|
2335
|
+
return;
|
|
2336
|
+
this.clearDismissTimer();
|
|
2337
|
+
this.isOpen = false; // triggers exit transition
|
|
2338
|
+
// after exit animation, hide + notify
|
|
2339
|
+
window.setTimeout(() => {
|
|
2340
|
+
if (this.visible) {
|
|
2341
|
+
this.visible = false;
|
|
2342
|
+
this.visibleChange.emit(false);
|
|
2343
|
+
}
|
|
2344
|
+
if (emitButtonClicked) {
|
|
2345
|
+
this.buttonClicked.emit();
|
|
2346
|
+
}
|
|
2347
|
+
this.closed.emit();
|
|
2348
|
+
}, this.EXIT_MS);
|
|
2349
|
+
}
|
|
2350
|
+
get status() {
|
|
2351
|
+
return purposeToStatusMap[this.purpose];
|
|
2352
|
+
}
|
|
2353
|
+
startDismissTimer() {
|
|
2354
|
+
if (!this.autoDismiss)
|
|
2355
|
+
return;
|
|
2356
|
+
this.clearDismissTimer();
|
|
2357
|
+
this.dismissTimer = window.setTimeout(() => this.close(), this.progressMs);
|
|
2358
|
+
}
|
|
2359
|
+
clearDismissTimer() {
|
|
2360
|
+
if (this.dismissTimer) {
|
|
2361
|
+
clearTimeout(this.dismissTimer);
|
|
2362
|
+
this.dismissTimer = undefined;
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.0", ngImport: i0, type: SnackbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2366
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.1.0", type: SnackbarComponent, isStandalone: true, selector: "lib-snackbar", inputs: { purpose: "purpose", title: "title", description: "description", fieldPlaceholder: "fieldPlaceholder", titleIcon: "titleIcon", showTitle: ["showTitle", "showTitle", booleanAttribute], showTitleIcon: ["showTitleIcon", "showTitleIcon", booleanAttribute], titleIconFilled: ["titleIconFilled", "titleIconFilled", booleanAttribute], showClose: ["showClose", "showClose", booleanAttribute], showProgressBar: ["showProgressBar", "showProgressBar", booleanAttribute], showField: ["showField", "showField", booleanAttribute], showButton: ["showButton", "showButton", booleanAttribute], autoDismiss: ["autoDismiss", "autoDismiss", booleanAttribute], visible: ["visible", "visible", booleanAttribute], progressMs: "progressMs", y: "y", statusButtonInputs: "statusButtonInputs" }, outputs: { closed: "closed", visibleChange: "visibleChange", buttonClicked: "buttonClicked" }, usesOnChanges: true, ngImport: i0, template: "@if (visible) {\n <section\n class=\"snackbar\"\n [ngClass]=\"{\n 'is-default': purpose === 'default',\n 'is-info': purpose === 'info',\n 'is-success': purpose === 'success',\n 'is-error': purpose === 'error',\n 'is-warning': purpose === 'warning',\n 'is-open': isOpen,\n }\"\n role=\"status\"\n aria-live=\"polite\"\n [style.--snackbar-progress-duration]=\"progressMs + 'ms'\"\n [style.top.px]=\"y\"\n >\n <div class=\"snackbar__left\">\n @if(showTitle) {\n <div class=\"snackbar__title-row\">\n <span \n [ngClass]=\"{\n 'snackbar__title-icon': true,\n 'has-icon': showTitle && showTitleIcon\n }\"\n aria-hidden=\"true\"\n >\n @if (showTitle && showTitleIcon) {\n <i [ngClass]=\"titleIconFilled ? 'material-icons' : 'material-icons-outlined'\"\n id=\"snackbar-title-icon\"\n aria-hidden=\"true\"\n >\n {{ titleIcon }}\n </i>\n }\n </span>\n @if (showTitle) {\n <h3 class=\"snackbar__title\">{{ title }}</h3>\n }\n </div>\n }\n <p class=\"snackbar__desc\">\n {{ description }}\n </p>\n @if (showField) {\n <input class=\"snackbar__input\" type=\"text\" [placeholder]=\"fieldPlaceholder\" />\n }\n @if (showButton) {\n <lib-status-button\n label={{statusButtonInputs?.label}}\n [status]=\"status\"\n leftIcon={{statusButtonInputs?.leftIcon}}\n rightIcon={{statusButtonInputs?.rightIcon}}\n [hideLeftIcon]=\"statusButtonInputs?.hideLeftIcon\"\n [hideRightIcon]=\"statusButtonInputs?.hideRightIcon\"\n [clearVariant]=\"statusButtonInputs?.clearVariant\"\n (click)=\"close(true)\"\n ></lib-status-button>\n\n }\n </div>\n <button \n type=\"button\"\n (click)=\"close()\"\n class=\"snackbar__close\"\n aria-label=\"Dismiss\"\n [style.visibility]=\"showClose ? 'visible' : 'hidden'\"\n >\n \u00D7\n </button>\n @if (showProgressBar) {\n <div class=\"snackbar__progress\">\n <div class=\"snackbar__progress-fill\"></div>\n </div>\n }\n </section>\n}\n", styles: [":root{--border-radius-md: 4px;--colors-border-primary: #d0d0d0;--colors-surface-primary: white;--colors-border-information: #457fa6;--colors-surface-information: #ecf2f6;--colors-border-success: #3ba35a;--colors-surface-success: #ebf6ee;--colors-border-warning: #d1c844;--colors-surface-warning: #faf9ec;--colors-border-error: #c73e3d;--colors-surface-error: #f9ecec}.snackbar{--snackbar-border-color: var(--colors-border-primary);--snackbar-bg: var(--colors-surface-primary);--snackbar-text: #141414;--snackbar-title-color: var(--snackbar-text);--snackbar-icon-bg: #e5edf8;--snackbar-accent: #0047ba;--snackbar-input-border: var(--snackbar-border-color);--snackbar-progress: var(--snackbar-accent);display:flex;width:26.25rem;padding:1.25rem 1rem;justify-content:space-between;align-items:flex-start;gap:.25rem;position:relative;border-radius:var(--border-radius-md, 4px);border:1px solid var(--snackbar-border-color);background:var(--snackbar-bg);box-shadow:1px 1px 4px #00000040;color:var(--snackbar-text)}.snackbar__left{display:grid;gap:.5rem;flex:1 1 auto}.snackbar__left>.snackbar__title-row~*{margin-left:var(--snackbar-right-gutter, 1.85rem)}.snackbar__title-row{display:flex;align-items:center;gap:.25rem}.snackbar__title{margin:0;font-weight:400;font-size:1.2rem;line-height:1.2;color:var(--snackbar-title-color)}.snackbar__title-icon{display:inline-flex;align-items:center;justify-content:center;width:1.5em;height:1.5em}.snackbar__title-icon.has-icon{border-radius:50%;color:var(--snackbar-accent)}.snackbar__icon{font-weight:700;font-size:1rem;line-height:1}.snackbar__desc{margin:0;opacity:.9}.snackbar__input{width:100%;max-width:100%;box-sizing:border-box;padding:.5em;border-radius:4px;border:1px solid var(--snackbar-input-border);background:#fff;color:inherit}.snackbar__close{margin-left:.5em;border:0;background:transparent;color:inherit;opacity:.7;font-size:1.5rem;padding:.25rem;line-height:1;cursor:pointer}.snackbar__progress{position:absolute;left:0;right:0;bottom:-1px;height:4px;overflow:hidden;border-bottom-left-radius:inherit;border-bottom-right-radius:inherit}.snackbar__progress-fill{height:100%;width:0%;background:var(--snackbar-progress);animation:fill var(--snackbar-progress-duration, 4s) linear forwards}@keyframes fill{to{width:100%}}.snackbar.is-default{--snackbar-border-color: var(--colors-border-primary, #d0d0d0);--snackbar-bg: var(--colors-surface-primary, white);--snackbar-text: #141414;--snackbar-title-color: #003995;--snackbar-icon-bg: #e5edf8;--snackbar-accent: #003995;--snackbar-input-border: #d0d0d0;--snackbar-progress: #003995}.snackbar.is-info{--snackbar-border-color: var(--colors-border-information, #457fa6);--snackbar-bg: var(--colors-surface-information, #ecf2f6);--snackbar-text: #24495c;--snackbar-title-color: #24495c;--snackbar-icon-bg: #a2bfd3;--snackbar-accent: #306a88;--snackbar-input-border: #a2bfd3;--snackbar-progress: #306a88}.snackbar.is-success{--snackbar-border-color: var(--colors-border-success, #3ba35a);--snackbar-bg: var(--colors-surface-success, #ebf6ee);--snackbar-text: #20522e;--snackbar-title-color: #20522e;--snackbar-icon-bg: #9dd1ac;--snackbar-accent: #2e7d3f;--snackbar-input-border: #9dd1ac;--snackbar-progress: #2e7d3f}.snackbar.is-warning{--snackbar-border-color: var(--colors-border-warning, #d1c844);--snackbar-bg: var(--colors-surface-warning, #faf9ec);--snackbar-text: #514a18;--snackbar-title-color: #514a18;--snackbar-icon-bg: #e8e3a1;--snackbar-accent: #7a6f13;--snackbar-input-border: #d1c844;--snackbar-progress: #7a6f13}.snackbar.is-error{--snackbar-border-color: var(--colors-border-error, #c73e3d);--snackbar-bg: var(--colors-surface-error, #f9ecec);--snackbar-text: #611a1a;--snackbar-title-color: #611a1a;--snackbar-icon-bg: #e39e9e;--snackbar-accent: #912525;--snackbar-input-border: #c73e3d;--snackbar-progress: #912525}.snackbar{position:fixed;top:24px;right:24px;z-index:1000;transform:translate(120%);transition:transform .6s ease}.snackbar.is-open{transform:translate(0)}lib-status-button{--status-button-padding: .25em .5em .25em 0}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: StatusButtonComponent, selector: "lib-status-button", inputs: ["label", "status", "leftIcon", "rightIcon", "hideLeftIcon", "hideRightIcon", "clearVariant"] }] }); }
|
|
2367
|
+
}
|
|
2368
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.0", ngImport: i0, type: SnackbarComponent, decorators: [{
|
|
2369
|
+
type: Component,
|
|
2370
|
+
args: [{ selector: 'lib-snackbar', standalone: true, imports: [NgClass, StatusButtonComponent], template: "@if (visible) {\n <section\n class=\"snackbar\"\n [ngClass]=\"{\n 'is-default': purpose === 'default',\n 'is-info': purpose === 'info',\n 'is-success': purpose === 'success',\n 'is-error': purpose === 'error',\n 'is-warning': purpose === 'warning',\n 'is-open': isOpen,\n }\"\n role=\"status\"\n aria-live=\"polite\"\n [style.--snackbar-progress-duration]=\"progressMs + 'ms'\"\n [style.top.px]=\"y\"\n >\n <div class=\"snackbar__left\">\n @if(showTitle) {\n <div class=\"snackbar__title-row\">\n <span \n [ngClass]=\"{\n 'snackbar__title-icon': true,\n 'has-icon': showTitle && showTitleIcon\n }\"\n aria-hidden=\"true\"\n >\n @if (showTitle && showTitleIcon) {\n <i [ngClass]=\"titleIconFilled ? 'material-icons' : 'material-icons-outlined'\"\n id=\"snackbar-title-icon\"\n aria-hidden=\"true\"\n >\n {{ titleIcon }}\n </i>\n }\n </span>\n @if (showTitle) {\n <h3 class=\"snackbar__title\">{{ title }}</h3>\n }\n </div>\n }\n <p class=\"snackbar__desc\">\n {{ description }}\n </p>\n @if (showField) {\n <input class=\"snackbar__input\" type=\"text\" [placeholder]=\"fieldPlaceholder\" />\n }\n @if (showButton) {\n <lib-status-button\n label={{statusButtonInputs?.label}}\n [status]=\"status\"\n leftIcon={{statusButtonInputs?.leftIcon}}\n rightIcon={{statusButtonInputs?.rightIcon}}\n [hideLeftIcon]=\"statusButtonInputs?.hideLeftIcon\"\n [hideRightIcon]=\"statusButtonInputs?.hideRightIcon\"\n [clearVariant]=\"statusButtonInputs?.clearVariant\"\n (click)=\"close(true)\"\n ></lib-status-button>\n\n }\n </div>\n <button \n type=\"button\"\n (click)=\"close()\"\n class=\"snackbar__close\"\n aria-label=\"Dismiss\"\n [style.visibility]=\"showClose ? 'visible' : 'hidden'\"\n >\n \u00D7\n </button>\n @if (showProgressBar) {\n <div class=\"snackbar__progress\">\n <div class=\"snackbar__progress-fill\"></div>\n </div>\n }\n </section>\n}\n", styles: [":root{--border-radius-md: 4px;--colors-border-primary: #d0d0d0;--colors-surface-primary: white;--colors-border-information: #457fa6;--colors-surface-information: #ecf2f6;--colors-border-success: #3ba35a;--colors-surface-success: #ebf6ee;--colors-border-warning: #d1c844;--colors-surface-warning: #faf9ec;--colors-border-error: #c73e3d;--colors-surface-error: #f9ecec}.snackbar{--snackbar-border-color: var(--colors-border-primary);--snackbar-bg: var(--colors-surface-primary);--snackbar-text: #141414;--snackbar-title-color: var(--snackbar-text);--snackbar-icon-bg: #e5edf8;--snackbar-accent: #0047ba;--snackbar-input-border: var(--snackbar-border-color);--snackbar-progress: var(--snackbar-accent);display:flex;width:26.25rem;padding:1.25rem 1rem;justify-content:space-between;align-items:flex-start;gap:.25rem;position:relative;border-radius:var(--border-radius-md, 4px);border:1px solid var(--snackbar-border-color);background:var(--snackbar-bg);box-shadow:1px 1px 4px #00000040;color:var(--snackbar-text)}.snackbar__left{display:grid;gap:.5rem;flex:1 1 auto}.snackbar__left>.snackbar__title-row~*{margin-left:var(--snackbar-right-gutter, 1.85rem)}.snackbar__title-row{display:flex;align-items:center;gap:.25rem}.snackbar__title{margin:0;font-weight:400;font-size:1.2rem;line-height:1.2;color:var(--snackbar-title-color)}.snackbar__title-icon{display:inline-flex;align-items:center;justify-content:center;width:1.5em;height:1.5em}.snackbar__title-icon.has-icon{border-radius:50%;color:var(--snackbar-accent)}.snackbar__icon{font-weight:700;font-size:1rem;line-height:1}.snackbar__desc{margin:0;opacity:.9}.snackbar__input{width:100%;max-width:100%;box-sizing:border-box;padding:.5em;border-radius:4px;border:1px solid var(--snackbar-input-border);background:#fff;color:inherit}.snackbar__close{margin-left:.5em;border:0;background:transparent;color:inherit;opacity:.7;font-size:1.5rem;padding:.25rem;line-height:1;cursor:pointer}.snackbar__progress{position:absolute;left:0;right:0;bottom:-1px;height:4px;overflow:hidden;border-bottom-left-radius:inherit;border-bottom-right-radius:inherit}.snackbar__progress-fill{height:100%;width:0%;background:var(--snackbar-progress);animation:fill var(--snackbar-progress-duration, 4s) linear forwards}@keyframes fill{to{width:100%}}.snackbar.is-default{--snackbar-border-color: var(--colors-border-primary, #d0d0d0);--snackbar-bg: var(--colors-surface-primary, white);--snackbar-text: #141414;--snackbar-title-color: #003995;--snackbar-icon-bg: #e5edf8;--snackbar-accent: #003995;--snackbar-input-border: #d0d0d0;--snackbar-progress: #003995}.snackbar.is-info{--snackbar-border-color: var(--colors-border-information, #457fa6);--snackbar-bg: var(--colors-surface-information, #ecf2f6);--snackbar-text: #24495c;--snackbar-title-color: #24495c;--snackbar-icon-bg: #a2bfd3;--snackbar-accent: #306a88;--snackbar-input-border: #a2bfd3;--snackbar-progress: #306a88}.snackbar.is-success{--snackbar-border-color: var(--colors-border-success, #3ba35a);--snackbar-bg: var(--colors-surface-success, #ebf6ee);--snackbar-text: #20522e;--snackbar-title-color: #20522e;--snackbar-icon-bg: #9dd1ac;--snackbar-accent: #2e7d3f;--snackbar-input-border: #9dd1ac;--snackbar-progress: #2e7d3f}.snackbar.is-warning{--snackbar-border-color: var(--colors-border-warning, #d1c844);--snackbar-bg: var(--colors-surface-warning, #faf9ec);--snackbar-text: #514a18;--snackbar-title-color: #514a18;--snackbar-icon-bg: #e8e3a1;--snackbar-accent: #7a6f13;--snackbar-input-border: #d1c844;--snackbar-progress: #7a6f13}.snackbar.is-error{--snackbar-border-color: var(--colors-border-error, #c73e3d);--snackbar-bg: var(--colors-surface-error, #f9ecec);--snackbar-text: #611a1a;--snackbar-title-color: #611a1a;--snackbar-icon-bg: #e39e9e;--snackbar-accent: #912525;--snackbar-input-border: #c73e3d;--snackbar-progress: #912525}.snackbar{position:fixed;top:24px;right:24px;z-index:1000;transform:translate(120%);transition:transform .6s ease}.snackbar.is-open{transform:translate(0)}lib-status-button{--status-button-padding: .25em .5em .25em 0}\n"] }]
|
|
2371
|
+
}], propDecorators: { purpose: [{
|
|
2372
|
+
type: Input
|
|
2373
|
+
}], title: [{
|
|
2374
|
+
type: Input
|
|
2375
|
+
}], description: [{
|
|
2376
|
+
type: Input
|
|
2377
|
+
}], fieldPlaceholder: [{
|
|
2378
|
+
type: Input
|
|
2379
|
+
}], titleIcon: [{
|
|
2380
|
+
type: Input
|
|
2381
|
+
}], showTitle: [{
|
|
2382
|
+
type: Input,
|
|
2383
|
+
args: [{ transform: booleanAttribute }]
|
|
2384
|
+
}], showTitleIcon: [{
|
|
2385
|
+
type: Input,
|
|
2386
|
+
args: [{ transform: booleanAttribute }]
|
|
2387
|
+
}], titleIconFilled: [{
|
|
2388
|
+
type: Input,
|
|
2389
|
+
args: [{ transform: booleanAttribute }]
|
|
2390
|
+
}], showClose: [{
|
|
2391
|
+
type: Input,
|
|
2392
|
+
args: [{ transform: booleanAttribute }]
|
|
2393
|
+
}], showProgressBar: [{
|
|
2394
|
+
type: Input,
|
|
2395
|
+
args: [{ transform: booleanAttribute }]
|
|
2396
|
+
}], showField: [{
|
|
2397
|
+
type: Input,
|
|
2398
|
+
args: [{ transform: booleanAttribute }]
|
|
2399
|
+
}], showButton: [{
|
|
2400
|
+
type: Input,
|
|
2401
|
+
args: [{ transform: booleanAttribute }]
|
|
2402
|
+
}], autoDismiss: [{
|
|
2403
|
+
type: Input,
|
|
2404
|
+
args: [{ transform: booleanAttribute }]
|
|
2405
|
+
}], visible: [{
|
|
2406
|
+
type: Input,
|
|
2407
|
+
args: [{ transform: booleanAttribute }]
|
|
2408
|
+
}], progressMs: [{
|
|
2409
|
+
type: Input
|
|
2410
|
+
}], y: [{
|
|
2411
|
+
type: Input
|
|
2412
|
+
}], statusButtonInputs: [{
|
|
2413
|
+
type: Input
|
|
2414
|
+
}], closed: [{
|
|
2415
|
+
type: Output
|
|
2416
|
+
}], visibleChange: [{
|
|
2417
|
+
type: Output
|
|
2418
|
+
}], buttonClicked: [{
|
|
2419
|
+
type: Output
|
|
2263
2420
|
}] } });
|
|
2264
2421
|
|
|
2422
|
+
class SnackbarService {
|
|
2423
|
+
constructor(appRef, env) {
|
|
2424
|
+
this.appRef = appRef;
|
|
2425
|
+
this.env = env;
|
|
2426
|
+
}
|
|
2427
|
+
/**
|
|
2428
|
+
* This open method is what consuming code will use to create a snackbar
|
|
2429
|
+
* @param snackbarOptions interface
|
|
2430
|
+
* @param anchor HTML Element, optional. The snackbar's entrance and exit animations will happen on this element's Y axis (px)
|
|
2431
|
+
* @returns void.
|
|
2432
|
+
*/
|
|
2433
|
+
open(snackbarOptions = {}, anchor) {
|
|
2434
|
+
const statusButtonInputs = {
|
|
2435
|
+
label: 'Done',
|
|
2436
|
+
hideLeftIcon: true,
|
|
2437
|
+
clearVariant: true,
|
|
2438
|
+
};
|
|
2439
|
+
const compRef = createComponent(SnackbarComponent, {
|
|
2440
|
+
environmentInjector: this.env,
|
|
2441
|
+
});
|
|
2442
|
+
const desiredY = anchor // could be clamped if above or below viewport
|
|
2443
|
+
? anchor.getBoundingClientRect().top
|
|
2444
|
+
: snackbarOptions.y ?? 24;
|
|
2445
|
+
Object.assign(compRef.instance, {
|
|
2446
|
+
purpose: 'warning',
|
|
2447
|
+
title: 'Snackbar Title',
|
|
2448
|
+
description: 'Lorem ipsum is the standard dummy text in the design industry',
|
|
2449
|
+
titleIcon: 'info',
|
|
2450
|
+
fieldPlaceholder: 'Placeholder',
|
|
2451
|
+
showTitle: true,
|
|
2452
|
+
showTitleIcon: true,
|
|
2453
|
+
titleIconFilled: false,
|
|
2454
|
+
showClose: true,
|
|
2455
|
+
showProgressBar: true,
|
|
2456
|
+
showField: true,
|
|
2457
|
+
showButton: true,
|
|
2458
|
+
progressMs: 5000,
|
|
2459
|
+
autoDismiss: true,
|
|
2460
|
+
y: desiredY,
|
|
2461
|
+
right: 24,
|
|
2462
|
+
zIndex: 10000,
|
|
2463
|
+
visible: true,
|
|
2464
|
+
statusButtonInputs,
|
|
2465
|
+
...snackbarOptions,
|
|
2466
|
+
});
|
|
2467
|
+
this.appRef.attachView(compRef.hostView);
|
|
2468
|
+
document.body.appendChild(compRef.location.nativeElement);
|
|
2469
|
+
compRef.changeDetectorRef.detectChanges();
|
|
2470
|
+
// Clamp Y after it’s in the DOM
|
|
2471
|
+
const margin = 8;
|
|
2472
|
+
const adjustY = () => {
|
|
2473
|
+
const host = compRef.location.nativeElement.querySelector('section.snackbar') ??
|
|
2474
|
+
compRef.location.nativeElement;
|
|
2475
|
+
const h = host.offsetHeight || 0;
|
|
2476
|
+
const maxTop = Math.max(margin, window.innerHeight - h - margin);
|
|
2477
|
+
const clamped = Math.min(Math.max(desiredY, margin), maxTop);
|
|
2478
|
+
if (compRef.instance.y !== clamped) {
|
|
2479
|
+
compRef.instance.y = clamped;
|
|
2480
|
+
compRef.changeDetectorRef.detectChanges();
|
|
2481
|
+
}
|
|
2482
|
+
};
|
|
2483
|
+
// Measure on next frame (styles applied)
|
|
2484
|
+
const rafId = requestAnimationFrame(adjustY);
|
|
2485
|
+
// re-clamp on resize (in case viewport changes while visible)
|
|
2486
|
+
const onResize = () => adjustY();
|
|
2487
|
+
window.addEventListener('resize', onResize);
|
|
2488
|
+
// Cleanup when closed
|
|
2489
|
+
const sub = compRef.instance.closed.subscribe(() => {
|
|
2490
|
+
sub.unsubscribe();
|
|
2491
|
+
cancelAnimationFrame(rafId);
|
|
2492
|
+
window.removeEventListener('resize', onResize);
|
|
2493
|
+
this.appRef.detachView(compRef.hostView);
|
|
2494
|
+
compRef.destroy();
|
|
2495
|
+
});
|
|
2496
|
+
return {
|
|
2497
|
+
close: () => compRef.instance.close(),
|
|
2498
|
+
buttonClicked: compRef.instance.buttonClicked,
|
|
2499
|
+
};
|
|
2500
|
+
}
|
|
2501
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.0", ngImport: i0, type: SnackbarService, deps: [{ token: i0.ApplicationRef }, { token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2502
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.1.0", ngImport: i0, type: SnackbarService, providedIn: 'root' }); }
|
|
2503
|
+
}
|
|
2504
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.0", ngImport: i0, type: SnackbarService, decorators: [{
|
|
2505
|
+
type: Injectable,
|
|
2506
|
+
args: [{ providedIn: 'root' }]
|
|
2507
|
+
}], ctorParameters: () => [{ type: i0.ApplicationRef }, { type: i0.EnvironmentInjector }] });
|
|
2508
|
+
|
|
2265
2509
|
/*
|
|
2266
2510
|
* Public API Surface of components
|
|
2267
2511
|
*/
|
|
@@ -2270,5 +2514,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.0", ngImpor
|
|
|
2270
2514
|
* Generated bundle index. Do not edit.
|
|
2271
2515
|
*/
|
|
2272
2516
|
|
|
2273
|
-
export { ADVANCED_SEARCH_FIELD_MAP, ADVANCED_SEARCH_OPTIONS, ADVANCED_SEARCH_QUALIFIER_MAP, HbllFooterComponent, HbllHeaderComponent, HbllItemTypeIconPipe, HeaderWithImpersonationComponent, ImpersonateModalComponent, ImpersonateUserPipe, ImpersonationBannerComponent, LIBRARY_HOURS_API_URL, SsSearchBarComponent, StatusButtonComponent, defaultOidcBaseUri, defaultOidcDefaultIdp, getUserStatusFromRoles, isAdvancedSearchExternalFieldOption, isAdvancedSearchFieldOption, isAdvancedSearchLocalFieldOption, isSearchScope };
|
|
2517
|
+
export { ADVANCED_SEARCH_FIELD_MAP, ADVANCED_SEARCH_OPTIONS, ADVANCED_SEARCH_QUALIFIER_MAP, HbllFooterComponent, HbllHeaderComponent, HbllItemTypeIconPipe, HeaderWithImpersonationComponent, ImpersonateModalComponent, ImpersonateUserPipe, ImpersonationBannerComponent, LIBRARY_HOURS_API_URL, SnackbarComponent, SnackbarService, SsSearchBarComponent, StatusButtonComponent, defaultOidcBaseUri, defaultOidcDefaultIdp, getUserStatusFromRoles, isAdvancedSearchExternalFieldOption, isAdvancedSearchFieldOption, isAdvancedSearchLocalFieldOption, isSearchScope };
|
|
2274
2518
|
//# sourceMappingURL=byuhbll-components.mjs.map
|