@underlayerdev/ui 0.8.2 → 0.9.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.
|
@@ -2970,6 +2970,14 @@ class ModalComponent {
|
|
|
2970
2970
|
/** Optional CSS class for the panel (e.g. for custom variant). */
|
|
2971
2971
|
customClass = input(undefined, /* @ts-ignore */
|
|
2972
2972
|
...(ngDevMode ? [{ debugName: "customClass" }] : /* istanbul ignore next */ []));
|
|
2973
|
+
/**
|
|
2974
|
+
* Below the phone breakpoint, fills the entire viewport edge-to-edge (no
|
|
2975
|
+
* margin, no rounded corners, no visible backdrop) instead of the default
|
|
2976
|
+
* bottom-pinned sheet every variant otherwise gets there. Has no effect
|
|
2977
|
+
* above that breakpoint — desktop/tablet layout is unchanged either way.
|
|
2978
|
+
*/
|
|
2979
|
+
fullScreenInMobile = input(false, /* @ts-ignore */
|
|
2980
|
+
...(ngDevMode ? [{ debugName: "fullScreenInMobile" }] : /* istanbul ignore next */ []));
|
|
2973
2981
|
/** Emitted when the modal is closed (button, backdrop, or escape). */
|
|
2974
2982
|
closed = output();
|
|
2975
2983
|
/** Emitted when the user confirms in the confirmation variant. */
|
|
@@ -2980,6 +2988,9 @@ class ModalComponent {
|
|
|
2980
2988
|
const variant = this.variant();
|
|
2981
2989
|
const custom = this.customClass();
|
|
2982
2990
|
const classes = ['ul-modal__panel', `ul-modal__panel--${variant}`];
|
|
2991
|
+
if (this.fullScreenInMobile()) {
|
|
2992
|
+
classes.push('ul-modal__panel--fullscreen-mobile');
|
|
2993
|
+
}
|
|
2983
2994
|
if (custom) {
|
|
2984
2995
|
classes.push(custom);
|
|
2985
2996
|
}
|
|
@@ -3025,14 +3036,14 @@ class ModalComponent {
|
|
|
3025
3036
|
}
|
|
3026
3037
|
}
|
|
3027
3038
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: ModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3028
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.0", type: ModalComponent, isStandalone: true, selector: "ul-modal", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, closeOnBackdropClick: { classPropertyName: "closeOnBackdropClick", publicName: "closeOnBackdropClick", isSignal: true, isRequired: false, transformFunction: null }, showCloseButton: { classPropertyName: "showCloseButton", publicName: "showCloseButton", isSignal: true, isRequired: false, transformFunction: null }, confirmLabel: { classPropertyName: "confirmLabel", publicName: "confirmLabel", isSignal: true, isRequired: false, transformFunction: null }, cancelLabel: { classPropertyName: "cancelLabel", publicName: "cancelLabel", isSignal: true, isRequired: false, transformFunction: null }, customClass: { classPropertyName: "customClass", publicName: "customClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", closed: "closed", confirmed: "confirmed", cancelled: "cancelled" }, host: { listeners: { "document:keydown.escape": "onEscape()" }, properties: { "attr.aria-hidden": "!open()" } }, ngImport: i0, template: "@if (open()) {\n <div\n class=\"ul-modal ul-modal--backdrop\"\n role=\"dialog\"\n [attr.aria-modal]=\"true\"\n [attr.aria-labelledby]=\"title() ? titleId : null\"\n [attr.aria-describedby]=\"bodyId\"\n (click)=\"onBackdropClick($event)\"\n >\n <div [class]=\"panelClass()\" cdkTrapFocus (click)=\"$event.stopPropagation()\">\n @if (modalTitle() || showCloseButton()) {\n <header class=\"ul-modal__header\">\n @if (modalTitle()) {\n <h2 [id]=\"titleId\" class=\"ul-modal__title\">{{ title() }}</h2>\n }\n @if (showCloseButton()) {\n <ul-button\n type=\"button\"\n theme=\"ghost-white\"\n [iconOnly]=\"true\"\n ariaLabel=\"Close\"\n class=\"ul-modal__close\"\n (buttonClick)=\"close()\"\n >\n <ul-icon icon=\"close\" size=\"6\" />\n </ul-button>\n }\n </header>\n }\n <div class=\"ul-modal__body\" [id]=\"bodyId\">\n @if (isSuccess() || isError()) {\n <div class=\"ul-modal__status\" aria-hidden=\"true\">\n <ul-icon\n class=\"ul-modal__status-icon\"\n [icon]=\"isSuccess() ? 'check_circle' : 'cross_circle'\"\n size=\"16\"\n />\n </div>\n }\n <ng-content />\n </div>\n <div class=\"ul-modal__footer\">\n @if (isConfirmation()) {\n <ul-button theme=\"ghost-white\" (buttonClick)=\"onCancel()\">\n {{ cancelLabel() }}\n </ul-button>\n <ul-button theme=\"fill-purple\" (buttonClick)=\"onConfirm()\">\n {{ confirmLabel() }}\n </ul-button>\n } @else {\n <ng-content select=\"[ul-modal-footer]\" />\n }\n </div>\n </div>\n </div>\n}\n", styles: [".ul-rich-text{font-family:Ultra Nunito Sans;line-height:28px;font-size:18px;letter-spacing:0px;font-weight:400;color:#fff}.ul-rich-text p,.ul-rich-text ul,.ul-rich-text ol,.ul-rich-text blockquote,.ul-rich-text pre{margin-top:0;margin-bottom:16px}.ul-rich-text:last-child,.ul-rich-text p:last-child,.ul-rich-text ul:last-child,.ul-rich-text ol:last-child,.ul-rich-text blockquote:last-child,.ul-rich-text pre:last-child{margin-bottom:0}.ul-rich-text h1,.ul-rich-text h2,.ul-rich-text h3,.ul-rich-text h4,.ul-rich-text h5,.ul-rich-text h6{margin-top:32px;margin-bottom:12px;font-weight:1000}.ul-rich-text h1{font-family:Ultra Nunito Sans;line-height:48px;font-size:48px;letter-spacing:-.48px;font-weight:1000}.ul-rich-text h2{font-family:Ultra Nunito Sans;line-height:48px;font-size:40px;letter-spacing:-.4px;font-weight:1000}.ul-rich-text h3{font-family:Ultra Nunito Sans;line-height:44px;font-size:36px;letter-spacing:-.36px;font-weight:1000}.ul-rich-text h4{font-family:Ultra Nunito Sans;line-height:40px;font-size:32px;letter-spacing:-.32px;font-weight:1000}.ul-rich-text h5{font-family:Ultra Nunito Sans;line-height:36px;font-size:28px;letter-spacing:-.28px;font-weight:1000}.ul-rich-text h6{font-family:Ultra Nunito Sans;line-height:36px;font-size:24px;letter-spacing:-.24px;font-weight:1000}.ul-rich-text ul,.ul-rich-text ol{padding-left:24px}.ul-rich-text ul ul,.ul-rich-text ul ol,.ul-rich-text ol ul,.ul-rich-text ol ol{margin-top:8px;margin-bottom:8px}.ul-rich-text li{margin-top:4px;margin-bottom:4px}.ul-rich-text strong{font-weight:800}.ul-rich-text code{font-family:Roboto Mono;line-height:20px;font-size:14px;letter-spacing:0px;font-weight:400}.ul-rich-text em{font-style:italic}.ul-rich-text a{color:#c2a8ff;text-decoration:underline;text-decoration-thickness:1px}.ul-rich-text a:hover{color:#d6c5ff}.ul-rich-text a:active{color:#a781ff}.ul-rich-text pre{padding:16px;border-radius:8px;background-color:#3b3b3b;overflow-x:auto}.ul-rich-text pre code{font-family:Roboto Mono;line-height:20px;font-size:14px;letter-spacing:0px;font-weight:400}.ul-rich-text blockquote{margin-left:0;padding-left:16px;border-left-width:2px;border-left-style:solid;border-left-color:#ffffff1a;color:#ffffffb3}.ul-rich-text--muted{color:#ffffffb3}.ul-rich-text--inverse,.ul-rich-text--inverse a{color:#000}.ul-rich-text--inverse a:hover,.ul-rich-text--inverse a:active{color:#000000b3}.ul-rich-text--body-m{font-family:Ultra Nunito Sans;line-height:24px;font-size:16px;letter-spacing:0px;font-weight:400}.ul-rich-text--compact p,.ul-rich-text--compact ul,.ul-rich-text--compact ol,.ul-rich-text--compact blockquote,.ul-rich-text--compact pre{margin-bottom:8px}.ul-rich-text--compact h1,.ul-rich-text--compact h2,.ul-rich-text--compact h3,.ul-rich-text--compact h4,.ul-rich-text--compact h5,.ul-rich-text--compact h6{margin-top:16px;margin-bottom:8px}.ul-modal--backdrop{position:fixed;inset:0;z-index:1100;display:flex;align-items:center;justify-content:center;padding:16px;background-color:#000000b3;transition:opacity .25s cubic-bezier(.4,0,.2,1)}.ul-modal__panel{position:relative;display:flex;flex-direction:column;max-height:calc(100% - 32px);overflow:auto;border-radius:16px;font-family:Ultra Nunito Sans;line-height:24px;font-size:16px;letter-spacing:0px;font-weight:400;color:#fff;transition:opacity .25s cubic-bezier(.4,0,.2,1),transform .25s cubic-bezier(.4,0,.2,1);background-color:#232323;padding:24px;border:1px solid rgba(255,255,255,.1)}.ul-modal__panel--confirmation{border:1px solid rgba(255,255,255,.1)}@media(max-width:767px){.ul-modal__panel--success{border:1px solid #7edc96}.ul-modal__panel--error{border:1px solid #f69d9d}}.ul-modal__panel--custom,.ul-modal__panel--bottom-sheet{border:1px solid rgba(255,255,255,.1)}.ul-modal__header{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:16px;flex-shrink:0}.ul-modal__title{margin:0;font-family:Ultra Nunito Sans;line-height:36px;font-size:24px;letter-spacing:-.24px;font-weight:800;color:#fff}.ul-modal__status{display:flex;align-items:center;justify-content:center;gap:12px;margin-bottom:12px}.ul-modal__status-icon{flex-shrink:0}.ul-modal__close{flex-shrink:0;margin-left:auto}.ul-modal__body{flex:1 1 auto;min-height:0;color:#ffffffb3}.ul-modal__panel--success .ul-modal__status-icon{color:#7edc96}.ul-modal__panel--error .ul-modal__status-icon{color:#f69d9d}.ul-modal__panel--success .ul-modal__body,.ul-modal__panel--error .ul-modal__body{text-align:center;font-family:Ultra Nunito Sans;line-height:28px;font-size:18px;letter-spacing:0px;font-weight:400}@media(min-width:768px){.ul-modal--backdrop{padding:24px}.ul-modal__panel{width:100%;max-width:512px}}@media(max-width:767px){.ul-modal--backdrop{align-items:flex-end;padding:0}.ul-modal__panel{width:100%;max-width:100%;border-radius:24px 24px 0 0;max-height:calc(100dvh - 32px);margin-top:auto;border-bottom:none}.ul-modal__panel--bottom-sheet{border-bottom:none}}.ul-modal__footer{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-top:16px;flex-shrink:0;justify-content:flex-end}\n"], dependencies: [{ kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: ButtonComponent, selector: "ul-button", inputs: ["size", "theme", "iconOnly", "vertical", "disabled", "type", "ariaLabel"], outputs: ["buttonClick"] }, { kind: "component", type: IconComponent, selector: "ul-icon", inputs: ["size", "weight", "icon"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
3039
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.0", type: ModalComponent, isStandalone: true, selector: "ul-modal", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, closeOnBackdropClick: { classPropertyName: "closeOnBackdropClick", publicName: "closeOnBackdropClick", isSignal: true, isRequired: false, transformFunction: null }, showCloseButton: { classPropertyName: "showCloseButton", publicName: "showCloseButton", isSignal: true, isRequired: false, transformFunction: null }, confirmLabel: { classPropertyName: "confirmLabel", publicName: "confirmLabel", isSignal: true, isRequired: false, transformFunction: null }, cancelLabel: { classPropertyName: "cancelLabel", publicName: "cancelLabel", isSignal: true, isRequired: false, transformFunction: null }, customClass: { classPropertyName: "customClass", publicName: "customClass", isSignal: true, isRequired: false, transformFunction: null }, fullScreenInMobile: { classPropertyName: "fullScreenInMobile", publicName: "fullScreenInMobile", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", closed: "closed", confirmed: "confirmed", cancelled: "cancelled" }, host: { listeners: { "document:keydown.escape": "onEscape()" }, properties: { "attr.aria-hidden": "!open()" } }, ngImport: i0, template: "@if (open()) {\n <div\n class=\"ul-modal ul-modal--backdrop\"\n role=\"dialog\"\n [attr.aria-modal]=\"true\"\n [attr.aria-labelledby]=\"title() ? titleId : null\"\n [attr.aria-describedby]=\"bodyId\"\n (click)=\"onBackdropClick($event)\"\n >\n <div [class]=\"panelClass()\" cdkTrapFocus (click)=\"$event.stopPropagation()\">\n @if (modalTitle() || showCloseButton()) {\n <header class=\"ul-modal__header\">\n @if (modalTitle()) {\n <h2 [id]=\"titleId\" class=\"ul-modal__title\">{{ title() }}</h2>\n }\n @if (showCloseButton()) {\n <ul-button\n type=\"button\"\n theme=\"ghost-white\"\n [iconOnly]=\"true\"\n ariaLabel=\"Close\"\n class=\"ul-modal__close\"\n (buttonClick)=\"close()\"\n >\n <ul-icon icon=\"close\" size=\"6\" />\n </ul-button>\n }\n </header>\n }\n <div class=\"ul-modal__body\" [id]=\"bodyId\">\n @if (isSuccess() || isError()) {\n <div class=\"ul-modal__status\" aria-hidden=\"true\">\n <ul-icon\n class=\"ul-modal__status-icon\"\n [icon]=\"isSuccess() ? 'check_circle' : 'cross_circle'\"\n size=\"16\"\n />\n </div>\n }\n <ng-content />\n </div>\n <div class=\"ul-modal__footer\">\n @if (isConfirmation()) {\n <ul-button theme=\"ghost-white\" (buttonClick)=\"onCancel()\">\n {{ cancelLabel() }}\n </ul-button>\n <ul-button theme=\"fill-purple\" (buttonClick)=\"onConfirm()\">\n {{ confirmLabel() }}\n </ul-button>\n } @else {\n <ng-content select=\"[ul-modal-footer]\" />\n }\n </div>\n </div>\n </div>\n}\n", styles: [".ul-rich-text{font-family:Ultra Nunito Sans;line-height:28px;font-size:18px;letter-spacing:0px;font-weight:400;color:#fff}.ul-rich-text p,.ul-rich-text ul,.ul-rich-text ol,.ul-rich-text blockquote,.ul-rich-text pre{margin-top:0;margin-bottom:16px}.ul-rich-text:last-child,.ul-rich-text p:last-child,.ul-rich-text ul:last-child,.ul-rich-text ol:last-child,.ul-rich-text blockquote:last-child,.ul-rich-text pre:last-child{margin-bottom:0}.ul-rich-text h1,.ul-rich-text h2,.ul-rich-text h3,.ul-rich-text h4,.ul-rich-text h5,.ul-rich-text h6{margin-top:32px;margin-bottom:12px;font-weight:1000}.ul-rich-text h1{font-family:Ultra Nunito Sans;line-height:48px;font-size:48px;letter-spacing:-.48px;font-weight:1000}.ul-rich-text h2{font-family:Ultra Nunito Sans;line-height:48px;font-size:40px;letter-spacing:-.4px;font-weight:1000}.ul-rich-text h3{font-family:Ultra Nunito Sans;line-height:44px;font-size:36px;letter-spacing:-.36px;font-weight:1000}.ul-rich-text h4{font-family:Ultra Nunito Sans;line-height:40px;font-size:32px;letter-spacing:-.32px;font-weight:1000}.ul-rich-text h5{font-family:Ultra Nunito Sans;line-height:36px;font-size:28px;letter-spacing:-.28px;font-weight:1000}.ul-rich-text h6{font-family:Ultra Nunito Sans;line-height:36px;font-size:24px;letter-spacing:-.24px;font-weight:1000}.ul-rich-text ul,.ul-rich-text ol{padding-left:24px}.ul-rich-text ul ul,.ul-rich-text ul ol,.ul-rich-text ol ul,.ul-rich-text ol ol{margin-top:8px;margin-bottom:8px}.ul-rich-text li{margin-top:4px;margin-bottom:4px}.ul-rich-text strong{font-weight:800}.ul-rich-text code{font-family:Roboto Mono;line-height:20px;font-size:14px;letter-spacing:0px;font-weight:400}.ul-rich-text em{font-style:italic}.ul-rich-text a{color:#c2a8ff;text-decoration:underline;text-decoration-thickness:1px}.ul-rich-text a:hover{color:#d6c5ff}.ul-rich-text a:active{color:#a781ff}.ul-rich-text pre{padding:16px;border-radius:8px;background-color:#3b3b3b;overflow-x:auto}.ul-rich-text pre code{font-family:Roboto Mono;line-height:20px;font-size:14px;letter-spacing:0px;font-weight:400}.ul-rich-text blockquote{margin-left:0;padding-left:16px;border-left-width:2px;border-left-style:solid;border-left-color:#ffffff1a;color:#ffffffb3}.ul-rich-text--muted{color:#ffffffb3}.ul-rich-text--inverse,.ul-rich-text--inverse a{color:#000}.ul-rich-text--inverse a:hover,.ul-rich-text--inverse a:active{color:#000000b3}.ul-rich-text--body-m{font-family:Ultra Nunito Sans;line-height:24px;font-size:16px;letter-spacing:0px;font-weight:400}.ul-rich-text--compact p,.ul-rich-text--compact ul,.ul-rich-text--compact ol,.ul-rich-text--compact blockquote,.ul-rich-text--compact pre{margin-bottom:8px}.ul-rich-text--compact h1,.ul-rich-text--compact h2,.ul-rich-text--compact h3,.ul-rich-text--compact h4,.ul-rich-text--compact h5,.ul-rich-text--compact h6{margin-top:16px;margin-bottom:8px}.ul-modal--backdrop{position:fixed;inset:0;z-index:1100;display:flex;align-items:center;justify-content:center;padding:16px;background-color:#000000b3;transition:opacity .25s cubic-bezier(.4,0,.2,1)}.ul-modal__panel{position:relative;display:flex;flex-direction:column;max-height:calc(100% - 32px);overflow:auto;border-radius:16px;font-family:Ultra Nunito Sans;line-height:24px;font-size:16px;letter-spacing:0px;font-weight:400;color:#fff;transition:opacity .25s cubic-bezier(.4,0,.2,1),transform .25s cubic-bezier(.4,0,.2,1);background-color:#232323;padding:24px;border:1px solid rgba(255,255,255,.1)}.ul-modal__panel--confirmation{border:1px solid rgba(255,255,255,.1)}@media(max-width:767px){.ul-modal__panel--success{border:1px solid #7edc96}.ul-modal__panel--error{border:1px solid #f69d9d}}.ul-modal__panel--custom,.ul-modal__panel--bottom-sheet{border:1px solid rgba(255,255,255,.1)}.ul-modal__header{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:16px;flex-shrink:0}.ul-modal__title{margin:0;font-family:Ultra Nunito Sans;line-height:36px;font-size:24px;letter-spacing:-.24px;font-weight:800;color:#fff}.ul-modal__status{display:flex;align-items:center;justify-content:center;gap:12px;margin-bottom:12px}.ul-modal__status-icon{flex-shrink:0}.ul-modal__close{flex-shrink:0;margin-left:auto}.ul-modal__body{flex:1 1 auto;min-height:0;color:#ffffffb3}.ul-modal__panel--success .ul-modal__status-icon{color:#7edc96}.ul-modal__panel--error .ul-modal__status-icon{color:#f69d9d}.ul-modal__panel--success .ul-modal__body,.ul-modal__panel--error .ul-modal__body{text-align:center;font-family:Ultra Nunito Sans;line-height:28px;font-size:18px;letter-spacing:0px;font-weight:400}@media(min-width:768px){.ul-modal--backdrop{padding:24px}.ul-modal__panel{width:100%;max-width:512px}}@media(max-width:767px){.ul-modal--backdrop{align-items:flex-end;padding:0}.ul-modal__panel{width:100%;max-width:100%;border-radius:24px 24px 0 0;max-height:calc(100dvh - 32px);margin-top:auto;border-bottom:none}.ul-modal__panel--bottom-sheet{border-bottom:none}.ul-modal__panel--fullscreen-mobile{position:fixed;inset:0;width:100%;max-width:100%;height:100dvh;max-height:100dvh;margin:0;border-radius:0;border:none}}.ul-modal__footer{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-top:16px;flex-shrink:0;justify-content:flex-end}\n"], dependencies: [{ kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: ButtonComponent, selector: "ul-button", inputs: ["size", "theme", "iconOnly", "vertical", "disabled", "type", "ariaLabel"], outputs: ["buttonClick"] }, { kind: "component", type: IconComponent, selector: "ul-icon", inputs: ["size", "weight", "icon"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
3029
3040
|
}
|
|
3030
3041
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: ModalComponent, decorators: [{
|
|
3031
3042
|
type: Component,
|
|
3032
3043
|
args: [{ selector: 'ul-modal', imports: [CdkTrapFocus, ButtonComponent, IconComponent], encapsulation: ViewEncapsulation.None, host: {
|
|
3033
3044
|
'[attr.aria-hidden]': '!open()',
|
|
3034
|
-
}, template: "@if (open()) {\n <div\n class=\"ul-modal ul-modal--backdrop\"\n role=\"dialog\"\n [attr.aria-modal]=\"true\"\n [attr.aria-labelledby]=\"title() ? titleId : null\"\n [attr.aria-describedby]=\"bodyId\"\n (click)=\"onBackdropClick($event)\"\n >\n <div [class]=\"panelClass()\" cdkTrapFocus (click)=\"$event.stopPropagation()\">\n @if (modalTitle() || showCloseButton()) {\n <header class=\"ul-modal__header\">\n @if (modalTitle()) {\n <h2 [id]=\"titleId\" class=\"ul-modal__title\">{{ title() }}</h2>\n }\n @if (showCloseButton()) {\n <ul-button\n type=\"button\"\n theme=\"ghost-white\"\n [iconOnly]=\"true\"\n ariaLabel=\"Close\"\n class=\"ul-modal__close\"\n (buttonClick)=\"close()\"\n >\n <ul-icon icon=\"close\" size=\"6\" />\n </ul-button>\n }\n </header>\n }\n <div class=\"ul-modal__body\" [id]=\"bodyId\">\n @if (isSuccess() || isError()) {\n <div class=\"ul-modal__status\" aria-hidden=\"true\">\n <ul-icon\n class=\"ul-modal__status-icon\"\n [icon]=\"isSuccess() ? 'check_circle' : 'cross_circle'\"\n size=\"16\"\n />\n </div>\n }\n <ng-content />\n </div>\n <div class=\"ul-modal__footer\">\n @if (isConfirmation()) {\n <ul-button theme=\"ghost-white\" (buttonClick)=\"onCancel()\">\n {{ cancelLabel() }}\n </ul-button>\n <ul-button theme=\"fill-purple\" (buttonClick)=\"onConfirm()\">\n {{ confirmLabel() }}\n </ul-button>\n } @else {\n <ng-content select=\"[ul-modal-footer]\" />\n }\n </div>\n </div>\n </div>\n}\n", styles: [".ul-rich-text{font-family:Ultra Nunito Sans;line-height:28px;font-size:18px;letter-spacing:0px;font-weight:400;color:#fff}.ul-rich-text p,.ul-rich-text ul,.ul-rich-text ol,.ul-rich-text blockquote,.ul-rich-text pre{margin-top:0;margin-bottom:16px}.ul-rich-text:last-child,.ul-rich-text p:last-child,.ul-rich-text ul:last-child,.ul-rich-text ol:last-child,.ul-rich-text blockquote:last-child,.ul-rich-text pre:last-child{margin-bottom:0}.ul-rich-text h1,.ul-rich-text h2,.ul-rich-text h3,.ul-rich-text h4,.ul-rich-text h5,.ul-rich-text h6{margin-top:32px;margin-bottom:12px;font-weight:1000}.ul-rich-text h1{font-family:Ultra Nunito Sans;line-height:48px;font-size:48px;letter-spacing:-.48px;font-weight:1000}.ul-rich-text h2{font-family:Ultra Nunito Sans;line-height:48px;font-size:40px;letter-spacing:-.4px;font-weight:1000}.ul-rich-text h3{font-family:Ultra Nunito Sans;line-height:44px;font-size:36px;letter-spacing:-.36px;font-weight:1000}.ul-rich-text h4{font-family:Ultra Nunito Sans;line-height:40px;font-size:32px;letter-spacing:-.32px;font-weight:1000}.ul-rich-text h5{font-family:Ultra Nunito Sans;line-height:36px;font-size:28px;letter-spacing:-.28px;font-weight:1000}.ul-rich-text h6{font-family:Ultra Nunito Sans;line-height:36px;font-size:24px;letter-spacing:-.24px;font-weight:1000}.ul-rich-text ul,.ul-rich-text ol{padding-left:24px}.ul-rich-text ul ul,.ul-rich-text ul ol,.ul-rich-text ol ul,.ul-rich-text ol ol{margin-top:8px;margin-bottom:8px}.ul-rich-text li{margin-top:4px;margin-bottom:4px}.ul-rich-text strong{font-weight:800}.ul-rich-text code{font-family:Roboto Mono;line-height:20px;font-size:14px;letter-spacing:0px;font-weight:400}.ul-rich-text em{font-style:italic}.ul-rich-text a{color:#c2a8ff;text-decoration:underline;text-decoration-thickness:1px}.ul-rich-text a:hover{color:#d6c5ff}.ul-rich-text a:active{color:#a781ff}.ul-rich-text pre{padding:16px;border-radius:8px;background-color:#3b3b3b;overflow-x:auto}.ul-rich-text pre code{font-family:Roboto Mono;line-height:20px;font-size:14px;letter-spacing:0px;font-weight:400}.ul-rich-text blockquote{margin-left:0;padding-left:16px;border-left-width:2px;border-left-style:solid;border-left-color:#ffffff1a;color:#ffffffb3}.ul-rich-text--muted{color:#ffffffb3}.ul-rich-text--inverse,.ul-rich-text--inverse a{color:#000}.ul-rich-text--inverse a:hover,.ul-rich-text--inverse a:active{color:#000000b3}.ul-rich-text--body-m{font-family:Ultra Nunito Sans;line-height:24px;font-size:16px;letter-spacing:0px;font-weight:400}.ul-rich-text--compact p,.ul-rich-text--compact ul,.ul-rich-text--compact ol,.ul-rich-text--compact blockquote,.ul-rich-text--compact pre{margin-bottom:8px}.ul-rich-text--compact h1,.ul-rich-text--compact h2,.ul-rich-text--compact h3,.ul-rich-text--compact h4,.ul-rich-text--compact h5,.ul-rich-text--compact h6{margin-top:16px;margin-bottom:8px}.ul-modal--backdrop{position:fixed;inset:0;z-index:1100;display:flex;align-items:center;justify-content:center;padding:16px;background-color:#000000b3;transition:opacity .25s cubic-bezier(.4,0,.2,1)}.ul-modal__panel{position:relative;display:flex;flex-direction:column;max-height:calc(100% - 32px);overflow:auto;border-radius:16px;font-family:Ultra Nunito Sans;line-height:24px;font-size:16px;letter-spacing:0px;font-weight:400;color:#fff;transition:opacity .25s cubic-bezier(.4,0,.2,1),transform .25s cubic-bezier(.4,0,.2,1);background-color:#232323;padding:24px;border:1px solid rgba(255,255,255,.1)}.ul-modal__panel--confirmation{border:1px solid rgba(255,255,255,.1)}@media(max-width:767px){.ul-modal__panel--success{border:1px solid #7edc96}.ul-modal__panel--error{border:1px solid #f69d9d}}.ul-modal__panel--custom,.ul-modal__panel--bottom-sheet{border:1px solid rgba(255,255,255,.1)}.ul-modal__header{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:16px;flex-shrink:0}.ul-modal__title{margin:0;font-family:Ultra Nunito Sans;line-height:36px;font-size:24px;letter-spacing:-.24px;font-weight:800;color:#fff}.ul-modal__status{display:flex;align-items:center;justify-content:center;gap:12px;margin-bottom:12px}.ul-modal__status-icon{flex-shrink:0}.ul-modal__close{flex-shrink:0;margin-left:auto}.ul-modal__body{flex:1 1 auto;min-height:0;color:#ffffffb3}.ul-modal__panel--success .ul-modal__status-icon{color:#7edc96}.ul-modal__panel--error .ul-modal__status-icon{color:#f69d9d}.ul-modal__panel--success .ul-modal__body,.ul-modal__panel--error .ul-modal__body{text-align:center;font-family:Ultra Nunito Sans;line-height:28px;font-size:18px;letter-spacing:0px;font-weight:400}@media(min-width:768px){.ul-modal--backdrop{padding:24px}.ul-modal__panel{width:100%;max-width:512px}}@media(max-width:767px){.ul-modal--backdrop{align-items:flex-end;padding:0}.ul-modal__panel{width:100%;max-width:100%;border-radius:24px 24px 0 0;max-height:calc(100dvh - 32px);margin-top:auto;border-bottom:none}.ul-modal__panel--bottom-sheet{border-bottom:none}}.ul-modal__footer{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-top:16px;flex-shrink:0;justify-content:flex-end}\n"] }]
|
|
3035
|
-
}], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], closeOnBackdropClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnBackdropClick", required: false }] }], showCloseButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCloseButton", required: false }] }], confirmLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmLabel", required: false }] }], cancelLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelLabel", required: false }] }], customClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "customClass", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], confirmed: [{ type: i0.Output, args: ["confirmed"] }], cancelled: [{ type: i0.Output, args: ["cancelled"] }], onEscape: [{
|
|
3045
|
+
}, template: "@if (open()) {\n <div\n class=\"ul-modal ul-modal--backdrop\"\n role=\"dialog\"\n [attr.aria-modal]=\"true\"\n [attr.aria-labelledby]=\"title() ? titleId : null\"\n [attr.aria-describedby]=\"bodyId\"\n (click)=\"onBackdropClick($event)\"\n >\n <div [class]=\"panelClass()\" cdkTrapFocus (click)=\"$event.stopPropagation()\">\n @if (modalTitle() || showCloseButton()) {\n <header class=\"ul-modal__header\">\n @if (modalTitle()) {\n <h2 [id]=\"titleId\" class=\"ul-modal__title\">{{ title() }}</h2>\n }\n @if (showCloseButton()) {\n <ul-button\n type=\"button\"\n theme=\"ghost-white\"\n [iconOnly]=\"true\"\n ariaLabel=\"Close\"\n class=\"ul-modal__close\"\n (buttonClick)=\"close()\"\n >\n <ul-icon icon=\"close\" size=\"6\" />\n </ul-button>\n }\n </header>\n }\n <div class=\"ul-modal__body\" [id]=\"bodyId\">\n @if (isSuccess() || isError()) {\n <div class=\"ul-modal__status\" aria-hidden=\"true\">\n <ul-icon\n class=\"ul-modal__status-icon\"\n [icon]=\"isSuccess() ? 'check_circle' : 'cross_circle'\"\n size=\"16\"\n />\n </div>\n }\n <ng-content />\n </div>\n <div class=\"ul-modal__footer\">\n @if (isConfirmation()) {\n <ul-button theme=\"ghost-white\" (buttonClick)=\"onCancel()\">\n {{ cancelLabel() }}\n </ul-button>\n <ul-button theme=\"fill-purple\" (buttonClick)=\"onConfirm()\">\n {{ confirmLabel() }}\n </ul-button>\n } @else {\n <ng-content select=\"[ul-modal-footer]\" />\n }\n </div>\n </div>\n </div>\n}\n", styles: [".ul-rich-text{font-family:Ultra Nunito Sans;line-height:28px;font-size:18px;letter-spacing:0px;font-weight:400;color:#fff}.ul-rich-text p,.ul-rich-text ul,.ul-rich-text ol,.ul-rich-text blockquote,.ul-rich-text pre{margin-top:0;margin-bottom:16px}.ul-rich-text:last-child,.ul-rich-text p:last-child,.ul-rich-text ul:last-child,.ul-rich-text ol:last-child,.ul-rich-text blockquote:last-child,.ul-rich-text pre:last-child{margin-bottom:0}.ul-rich-text h1,.ul-rich-text h2,.ul-rich-text h3,.ul-rich-text h4,.ul-rich-text h5,.ul-rich-text h6{margin-top:32px;margin-bottom:12px;font-weight:1000}.ul-rich-text h1{font-family:Ultra Nunito Sans;line-height:48px;font-size:48px;letter-spacing:-.48px;font-weight:1000}.ul-rich-text h2{font-family:Ultra Nunito Sans;line-height:48px;font-size:40px;letter-spacing:-.4px;font-weight:1000}.ul-rich-text h3{font-family:Ultra Nunito Sans;line-height:44px;font-size:36px;letter-spacing:-.36px;font-weight:1000}.ul-rich-text h4{font-family:Ultra Nunito Sans;line-height:40px;font-size:32px;letter-spacing:-.32px;font-weight:1000}.ul-rich-text h5{font-family:Ultra Nunito Sans;line-height:36px;font-size:28px;letter-spacing:-.28px;font-weight:1000}.ul-rich-text h6{font-family:Ultra Nunito Sans;line-height:36px;font-size:24px;letter-spacing:-.24px;font-weight:1000}.ul-rich-text ul,.ul-rich-text ol{padding-left:24px}.ul-rich-text ul ul,.ul-rich-text ul ol,.ul-rich-text ol ul,.ul-rich-text ol ol{margin-top:8px;margin-bottom:8px}.ul-rich-text li{margin-top:4px;margin-bottom:4px}.ul-rich-text strong{font-weight:800}.ul-rich-text code{font-family:Roboto Mono;line-height:20px;font-size:14px;letter-spacing:0px;font-weight:400}.ul-rich-text em{font-style:italic}.ul-rich-text a{color:#c2a8ff;text-decoration:underline;text-decoration-thickness:1px}.ul-rich-text a:hover{color:#d6c5ff}.ul-rich-text a:active{color:#a781ff}.ul-rich-text pre{padding:16px;border-radius:8px;background-color:#3b3b3b;overflow-x:auto}.ul-rich-text pre code{font-family:Roboto Mono;line-height:20px;font-size:14px;letter-spacing:0px;font-weight:400}.ul-rich-text blockquote{margin-left:0;padding-left:16px;border-left-width:2px;border-left-style:solid;border-left-color:#ffffff1a;color:#ffffffb3}.ul-rich-text--muted{color:#ffffffb3}.ul-rich-text--inverse,.ul-rich-text--inverse a{color:#000}.ul-rich-text--inverse a:hover,.ul-rich-text--inverse a:active{color:#000000b3}.ul-rich-text--body-m{font-family:Ultra Nunito Sans;line-height:24px;font-size:16px;letter-spacing:0px;font-weight:400}.ul-rich-text--compact p,.ul-rich-text--compact ul,.ul-rich-text--compact ol,.ul-rich-text--compact blockquote,.ul-rich-text--compact pre{margin-bottom:8px}.ul-rich-text--compact h1,.ul-rich-text--compact h2,.ul-rich-text--compact h3,.ul-rich-text--compact h4,.ul-rich-text--compact h5,.ul-rich-text--compact h6{margin-top:16px;margin-bottom:8px}.ul-modal--backdrop{position:fixed;inset:0;z-index:1100;display:flex;align-items:center;justify-content:center;padding:16px;background-color:#000000b3;transition:opacity .25s cubic-bezier(.4,0,.2,1)}.ul-modal__panel{position:relative;display:flex;flex-direction:column;max-height:calc(100% - 32px);overflow:auto;border-radius:16px;font-family:Ultra Nunito Sans;line-height:24px;font-size:16px;letter-spacing:0px;font-weight:400;color:#fff;transition:opacity .25s cubic-bezier(.4,0,.2,1),transform .25s cubic-bezier(.4,0,.2,1);background-color:#232323;padding:24px;border:1px solid rgba(255,255,255,.1)}.ul-modal__panel--confirmation{border:1px solid rgba(255,255,255,.1)}@media(max-width:767px){.ul-modal__panel--success{border:1px solid #7edc96}.ul-modal__panel--error{border:1px solid #f69d9d}}.ul-modal__panel--custom,.ul-modal__panel--bottom-sheet{border:1px solid rgba(255,255,255,.1)}.ul-modal__header{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:16px;flex-shrink:0}.ul-modal__title{margin:0;font-family:Ultra Nunito Sans;line-height:36px;font-size:24px;letter-spacing:-.24px;font-weight:800;color:#fff}.ul-modal__status{display:flex;align-items:center;justify-content:center;gap:12px;margin-bottom:12px}.ul-modal__status-icon{flex-shrink:0}.ul-modal__close{flex-shrink:0;margin-left:auto}.ul-modal__body{flex:1 1 auto;min-height:0;color:#ffffffb3}.ul-modal__panel--success .ul-modal__status-icon{color:#7edc96}.ul-modal__panel--error .ul-modal__status-icon{color:#f69d9d}.ul-modal__panel--success .ul-modal__body,.ul-modal__panel--error .ul-modal__body{text-align:center;font-family:Ultra Nunito Sans;line-height:28px;font-size:18px;letter-spacing:0px;font-weight:400}@media(min-width:768px){.ul-modal--backdrop{padding:24px}.ul-modal__panel{width:100%;max-width:512px}}@media(max-width:767px){.ul-modal--backdrop{align-items:flex-end;padding:0}.ul-modal__panel{width:100%;max-width:100%;border-radius:24px 24px 0 0;max-height:calc(100dvh - 32px);margin-top:auto;border-bottom:none}.ul-modal__panel--bottom-sheet{border-bottom:none}.ul-modal__panel--fullscreen-mobile{position:fixed;inset:0;width:100%;max-width:100%;height:100dvh;max-height:100dvh;margin:0;border-radius:0;border:none}}.ul-modal__footer{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-top:16px;flex-shrink:0;justify-content:flex-end}\n"] }]
|
|
3046
|
+
}], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], closeOnBackdropClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnBackdropClick", required: false }] }], showCloseButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCloseButton", required: false }] }], confirmLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmLabel", required: false }] }], cancelLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelLabel", required: false }] }], customClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "customClass", required: false }] }], fullScreenInMobile: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullScreenInMobile", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], confirmed: [{ type: i0.Output, args: ["confirmed"] }], cancelled: [{ type: i0.Output, args: ["cancelled"] }], onEscape: [{
|
|
3036
3047
|
type: HostListener,
|
|
3037
3048
|
args: ['document:keydown.escape']
|
|
3038
3049
|
}] } });
|
|
@@ -3734,6 +3745,264 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImpor
|
|
|
3734
3745
|
args: ['focusout']
|
|
3735
3746
|
}] } });
|
|
3736
3747
|
|
|
3748
|
+
/**
|
|
3749
|
+
* Open/focus/highlight state and keyboard navigation shared by combobox-
|
|
3750
|
+
* style inputs (a text field paired with a listbox of options) —
|
|
3751
|
+
* `ul-search-select` (closed list, one selection) and `ul-search-input`
|
|
3752
|
+
* (free text plus suggestions/results) need identical open/close timing and
|
|
3753
|
+
* arrow-key/Escape mechanics despite having different value semantics. This
|
|
3754
|
+
* holds only that shared mechanics; each consumer still owns its own list,
|
|
3755
|
+
* selection, and what Enter does when nothing is highlighted.
|
|
3756
|
+
*/
|
|
3757
|
+
class ComboboxState {
|
|
3758
|
+
isOpen = signal(false, /* @ts-ignore */
|
|
3759
|
+
...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
|
|
3760
|
+
isFocused = signal(false, /* @ts-ignore */
|
|
3761
|
+
...(ngDevMode ? [{ debugName: "isFocused" }] : /* istanbul ignore next */ []));
|
|
3762
|
+
highlightedIndex = signal(0, /* @ts-ignore */
|
|
3763
|
+
...(ngDevMode ? [{ debugName: "highlightedIndex" }] : /* istanbul ignore next */ []));
|
|
3764
|
+
closeTimeout = null;
|
|
3765
|
+
/** Cancels any pending blur-close and opens immediately — for focus/typing. */
|
|
3766
|
+
open() {
|
|
3767
|
+
this.cancelScheduledClose();
|
|
3768
|
+
this.isFocused.set(true);
|
|
3769
|
+
this.isOpen.set(true);
|
|
3770
|
+
}
|
|
3771
|
+
/**
|
|
3772
|
+
* Closes after a short delay instead of immediately, so a mousedown on an
|
|
3773
|
+
* option (which fires before the field's blur) can still register before
|
|
3774
|
+
* the panel disappears. `onClosed` runs once the delay elapses, unless a
|
|
3775
|
+
* subsequent `open()`/`close()` cancels it first.
|
|
3776
|
+
*/
|
|
3777
|
+
scheduleClose(onClosed, delay = 150) {
|
|
3778
|
+
this.isFocused.set(false);
|
|
3779
|
+
this.closeTimeout = setTimeout(() => {
|
|
3780
|
+
this.closeTimeout = null;
|
|
3781
|
+
this.isOpen.set(false);
|
|
3782
|
+
onClosed?.();
|
|
3783
|
+
}, delay);
|
|
3784
|
+
}
|
|
3785
|
+
/** Closes immediately — for selecting an option, submitting, or Escape. */
|
|
3786
|
+
close() {
|
|
3787
|
+
this.cancelScheduledClose();
|
|
3788
|
+
this.isOpen.set(false);
|
|
3789
|
+
}
|
|
3790
|
+
cancelScheduledClose() {
|
|
3791
|
+
if (this.closeTimeout != null) {
|
|
3792
|
+
clearTimeout(this.closeTimeout);
|
|
3793
|
+
this.closeTimeout = null;
|
|
3794
|
+
}
|
|
3795
|
+
}
|
|
3796
|
+
resetHighlight() {
|
|
3797
|
+
this.highlightedIndex.set(0);
|
|
3798
|
+
}
|
|
3799
|
+
/**
|
|
3800
|
+
* Handles ArrowDown/ArrowUp (cycling over `listLength`) and Escape
|
|
3801
|
+
* (closes). Returns whether it handled the key, so the caller's own
|
|
3802
|
+
* keydown handler knows whether to fall through to its own Enter logic —
|
|
3803
|
+
* Enter is deliberately not handled here, since selecting the highlighted
|
|
3804
|
+
* option vs. falling back to something else (e.g. `ul-search-input`'s
|
|
3805
|
+
* free-text submit) is caller-specific.
|
|
3806
|
+
*/
|
|
3807
|
+
handleNavigationKey(event, listLength) {
|
|
3808
|
+
switch (event.key) {
|
|
3809
|
+
case 'ArrowDown':
|
|
3810
|
+
if (listLength === 0)
|
|
3811
|
+
return false;
|
|
3812
|
+
event.preventDefault();
|
|
3813
|
+
this.highlightedIndex.set((this.highlightedIndex() + 1) % listLength);
|
|
3814
|
+
return true;
|
|
3815
|
+
case 'ArrowUp':
|
|
3816
|
+
if (listLength === 0)
|
|
3817
|
+
return false;
|
|
3818
|
+
event.preventDefault();
|
|
3819
|
+
this.highlightedIndex.set(this.highlightedIndex() <= 0 ? listLength - 1 : this.highlightedIndex() - 1);
|
|
3820
|
+
return true;
|
|
3821
|
+
case 'Escape':
|
|
3822
|
+
event.preventDefault();
|
|
3823
|
+
this.close();
|
|
3824
|
+
return true;
|
|
3825
|
+
default:
|
|
3826
|
+
return false;
|
|
3827
|
+
}
|
|
3828
|
+
}
|
|
3829
|
+
}
|
|
3830
|
+
/** DOM id for the option at `index` inside the listbox owned by `controlId`. */
|
|
3831
|
+
function comboboxOptionId(controlId, index) {
|
|
3832
|
+
return `${controlId}-option-${index}`;
|
|
3833
|
+
}
|
|
3834
|
+
/**
|
|
3835
|
+
* `aria-activedescendant` value for a combobox's current highlight, or
|
|
3836
|
+
* `undefined` when there's nothing to point at (empty list).
|
|
3837
|
+
*/
|
|
3838
|
+
function comboboxActiveDescendantId(controlId, listLength, highlightedIndex) {
|
|
3839
|
+
if (listLength === 0)
|
|
3840
|
+
return undefined;
|
|
3841
|
+
const safeIndex = Math.min(Math.max(0, highlightedIndex), listLength - 1);
|
|
3842
|
+
return comboboxOptionId(controlId, safeIndex);
|
|
3843
|
+
}
|
|
3844
|
+
|
|
3845
|
+
/**
|
|
3846
|
+
* Free-text search box with a results panel: `suggestions` (e.g. recent
|
|
3847
|
+
* searches) while the query is empty, swapped for `results` as soon as the
|
|
3848
|
+
* user types. On desktop the panel is an anchored dropdown below the field.
|
|
3849
|
+
* Below the phone breakpoint, tapping the field opens a full-screen `ul-modal`
|
|
3850
|
+
* (via `fullScreenInMobile`) instead — the same pattern as X/Twitter, Google,
|
|
3851
|
+
* etc.: a back button and the real field pinned to the top, results filling
|
|
3852
|
+
* the rest of the screen edge to edge, no card, no backdrop. `ul-modal`
|
|
3853
|
+
* supplies the focus trap, dialog role, and Escape-to-close; this component
|
|
3854
|
+
* just projects its own header/results as the modal's body content.
|
|
3855
|
+
* Consumers never branch on viewport or manage this themselves.
|
|
3856
|
+
*
|
|
3857
|
+
* Implements FormValueControl for Signal Forms. Use `[(value)]` for two-way
|
|
3858
|
+
* binding.
|
|
3859
|
+
*/
|
|
3860
|
+
class SearchInputComponent {
|
|
3861
|
+
size = input('md', /* @ts-ignore */
|
|
3862
|
+
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
3863
|
+
label = input(null, /* @ts-ignore */
|
|
3864
|
+
...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
3865
|
+
helperText = input(null, /* @ts-ignore */
|
|
3866
|
+
...(ngDevMode ? [{ debugName: "helperText" }] : /* istanbul ignore next */ []));
|
|
3867
|
+
errorText = input(null, /* @ts-ignore */
|
|
3868
|
+
...(ngDevMode ? [{ debugName: "errorText" }] : /* istanbul ignore next */ []));
|
|
3869
|
+
error = input(false, /* @ts-ignore */
|
|
3870
|
+
...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
|
|
3871
|
+
disabled = input(false, /* @ts-ignore */
|
|
3872
|
+
...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
3873
|
+
placeholder = input('Search...', /* @ts-ignore */
|
|
3874
|
+
...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
3875
|
+
/** Aria-label for the back button shown in the mobile takeover. */
|
|
3876
|
+
backLabel = input('Back', /* @ts-ignore */
|
|
3877
|
+
...(ngDevMode ? [{ debugName: "backLabel" }] : /* istanbul ignore next */ []));
|
|
3878
|
+
/** Aria-label for the clear button shown in the mobile takeover when query is not empty. */
|
|
3879
|
+
clearLabel = input('Clear', /* @ts-ignore */
|
|
3880
|
+
...(ngDevMode ? [{ debugName: "clearLabel" }] : /* istanbul ignore next */ []));
|
|
3881
|
+
/** Shown while the query is empty — e.g. recent searches. Replaced by `results` as soon as the user types. The consumer owns the data/persistence; this component only renders and reports selection. */
|
|
3882
|
+
suggestions = input([], /* @ts-ignore */
|
|
3883
|
+
...(ngDevMode ? [{ debugName: "suggestions" }] : /* istanbul ignore next */ []));
|
|
3884
|
+
/** Heading shown above `suggestions`, e.g. "Recent searches". Not shown once `results` takes over. */
|
|
3885
|
+
suggestionsLabel = input(null, /* @ts-ignore */
|
|
3886
|
+
...(ngDevMode ? [{ debugName: "suggestionsLabel" }] : /* istanbul ignore next */ []));
|
|
3887
|
+
/** Shown once the query is non-empty — e.g. live search results. The consumer computes/fetches these as `value` changes (via `[(value)]`/`valueChange`). */
|
|
3888
|
+
results = input([], /* @ts-ignore */
|
|
3889
|
+
...(ngDevMode ? [{ debugName: "results" }] : /* istanbul ignore next */ []));
|
|
3890
|
+
/**
|
|
3891
|
+
* Overrides `results` once the query is non-empty, projecting arbitrary
|
|
3892
|
+
* content (e.g. rich cards with images/prices) instead of the built-in
|
|
3893
|
+
* plain-text rows. `suggestions` (shown while the query is empty) are
|
|
3894
|
+
* unaffected and keep rendering as plain `SearchSuggestion` rows regardless.
|
|
3895
|
+
* When set, arrow-key/Enter option-highlighting is skipped — Enter always
|
|
3896
|
+
* falls through to `searchSubmit` since the projected content owns its own
|
|
3897
|
+
* selection interaction.
|
|
3898
|
+
*/
|
|
3899
|
+
resultsTemplate = input(null, /* @ts-ignore */
|
|
3900
|
+
...(ngDevMode ? [{ debugName: "resultsTemplate" }] : /* istanbul ignore next */ []));
|
|
3901
|
+
invalid = input(false, /* @ts-ignore */
|
|
3902
|
+
...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
|
|
3903
|
+
errors = input([], /* @ts-ignore */
|
|
3904
|
+
...(ngDevMode ? [{ debugName: "errors" }] : /* istanbul ignore next */ []));
|
|
3905
|
+
value = model('', /* @ts-ignore */
|
|
3906
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
3907
|
+
/** Emitted when the user picks a suggestion, by click or keyboard. */
|
|
3908
|
+
suggestionSelected = output();
|
|
3909
|
+
/** Emitted on Enter when no suggestion is highlighted — the free-typed query. */
|
|
3910
|
+
searchSubmit = output();
|
|
3911
|
+
ids = createFormFieldIds('ul-search-input');
|
|
3912
|
+
/** Open/focus/highlight state and arrow-key/Escape mechanics shared with ul-search-select. */
|
|
3913
|
+
combobox = new ComboboxState();
|
|
3914
|
+
mobileInput = viewChild('mobileInput', /* @ts-ignore */
|
|
3915
|
+
...(ngDevMode ? [{ debugName: "mobileInput" }] : /* istanbul ignore next */ []));
|
|
3916
|
+
/** Phone-sized viewport — below this, tapping the field opens the full-screen takeover instead of the anchored dropdown. */
|
|
3917
|
+
isMobile = toSignal(inject(BreakpointObserver)
|
|
3918
|
+
.observe('(max-width: 767px)')
|
|
3919
|
+
.pipe(map((state) => state.matches)), { initialValue: false });
|
|
3920
|
+
listId = `${this.ids.controlId}-list`;
|
|
3921
|
+
hasError = computed(() => this.error() || this.invalid(), /* @ts-ignore */
|
|
3922
|
+
...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
|
|
3923
|
+
describedBy = computed(() => getFormFieldDescribedBy(this.ids.helperId, this.ids.errorId, !!this.helperText(), this.hasError(), !!this.errorText() || this.errors().length > 0), /* @ts-ignore */
|
|
3924
|
+
...(ngDevMode ? [{ debugName: "describedBy" }] : /* istanbul ignore next */ []));
|
|
3925
|
+
/** Whether the query is non-empty — `results` replaces `suggestions` (and its heading) once true. */
|
|
3926
|
+
hasQuery = computed(() => this.value().trim().length > 0, /* @ts-ignore */
|
|
3927
|
+
...(ngDevMode ? [{ debugName: "hasQuery" }] : /* istanbul ignore next */ []));
|
|
3928
|
+
activeList = computed(() => this.hasQuery() ? this.results() : this.suggestions(), /* @ts-ignore */
|
|
3929
|
+
...(ngDevMode ? [{ debugName: "activeList" }] : /* istanbul ignore next */ []));
|
|
3930
|
+
activeListLabel = computed(() => this.hasQuery() ? null : this.suggestionsLabel(), /* @ts-ignore */
|
|
3931
|
+
...(ngDevMode ? [{ debugName: "activeListLabel" }] : /* istanbul ignore next */ []));
|
|
3932
|
+
hasCustomResults = computed(() => this.hasQuery() && !!this.resultsTemplate(), /* @ts-ignore */
|
|
3933
|
+
...(ngDevMode ? [{ debugName: "hasCustomResults" }] : /* istanbul ignore next */ []));
|
|
3934
|
+
shouldShowPanel = computed(() => this.combobox.isOpen() && (this.activeList().length > 0 || this.hasCustomResults()), /* @ts-ignore */
|
|
3935
|
+
...(ngDevMode ? [{ debugName: "shouldShowPanel" }] : /* istanbul ignore next */ []));
|
|
3936
|
+
optionId = (index) => comboboxOptionId(this.ids.controlId, index);
|
|
3937
|
+
activeDescendantId = computed(() => {
|
|
3938
|
+
if (!this.shouldShowPanel() || this.hasCustomResults())
|
|
3939
|
+
return undefined;
|
|
3940
|
+
return comboboxActiveDescendantId(this.ids.controlId, this.activeList().length, this.combobox.highlightedIndex());
|
|
3941
|
+
}, /* @ts-ignore */
|
|
3942
|
+
...(ngDevMode ? [{ debugName: "activeDescendantId" }] : /* istanbul ignore next */ []));
|
|
3943
|
+
onValueChange(text) {
|
|
3944
|
+
this.value.set(text);
|
|
3945
|
+
this.combobox.isOpen.set(true);
|
|
3946
|
+
this.combobox.resetHighlight();
|
|
3947
|
+
}
|
|
3948
|
+
onInputFocus() {
|
|
3949
|
+
this.combobox.open();
|
|
3950
|
+
}
|
|
3951
|
+
onInputBlur() {
|
|
3952
|
+
this.combobox.scheduleClose();
|
|
3953
|
+
}
|
|
3954
|
+
/** The visible field on mobile is a read-only trigger — typing happens in the takeover's own field, focused once it renders. */
|
|
3955
|
+
openMobileSearch() {
|
|
3956
|
+
this.combobox.isOpen.set(true);
|
|
3957
|
+
setTimeout(() => this.mobileInput()?.focus());
|
|
3958
|
+
}
|
|
3959
|
+
closeMobileSearch() {
|
|
3960
|
+
this.combobox.close();
|
|
3961
|
+
}
|
|
3962
|
+
clearInput() {
|
|
3963
|
+
this.onValueChange('');
|
|
3964
|
+
}
|
|
3965
|
+
onKeydown(event) {
|
|
3966
|
+
const list = this.activeList();
|
|
3967
|
+
const panelActive = this.shouldShowPanel() && list.length > 0;
|
|
3968
|
+
if (panelActive && this.combobox.handleNavigationKey(event, list.length))
|
|
3969
|
+
return;
|
|
3970
|
+
if (event.key === 'Enter') {
|
|
3971
|
+
event.preventDefault();
|
|
3972
|
+
if (panelActive) {
|
|
3973
|
+
this.selectSuggestion(list[this.combobox.highlightedIndex()]);
|
|
3974
|
+
}
|
|
3975
|
+
else {
|
|
3976
|
+
this.submitSearch();
|
|
3977
|
+
}
|
|
3978
|
+
}
|
|
3979
|
+
}
|
|
3980
|
+
selectSuggestion(suggestion) {
|
|
3981
|
+
this.combobox.close();
|
|
3982
|
+
this.value.set(suggestion.label);
|
|
3983
|
+
this.suggestionSelected.emit(suggestion);
|
|
3984
|
+
}
|
|
3985
|
+
submitSearch() {
|
|
3986
|
+
this.combobox.close();
|
|
3987
|
+
this.searchSubmit.emit(this.value());
|
|
3988
|
+
}
|
|
3989
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: SearchInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3990
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.0", type: SearchInputComponent, isStandalone: true, selector: "ul-search-input", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, helperText: { classPropertyName: "helperText", publicName: "helperText", isSignal: true, isRequired: false, transformFunction: null }, errorText: { classPropertyName: "errorText", publicName: "errorText", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, backLabel: { classPropertyName: "backLabel", publicName: "backLabel", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, suggestions: { classPropertyName: "suggestions", publicName: "suggestions", isSignal: true, isRequired: false, transformFunction: null }, suggestionsLabel: { classPropertyName: "suggestionsLabel", publicName: "suggestionsLabel", isSignal: true, isRequired: false, transformFunction: null }, results: { classPropertyName: "results", publicName: "results", isSignal: true, isRequired: false, transformFunction: null }, resultsTemplate: { classPropertyName: "resultsTemplate", publicName: "resultsTemplate", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", suggestionSelected: "suggestionSelected", searchSubmit: "searchSubmit" }, viewQueries: [{ propertyName: "mobileInput", first: true, predicate: ["mobileInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-template #resultsList>\n @if (activeListLabel()) {\n <div class=\"ul-search-input__list-label\" role=\"presentation\">{{ activeListLabel() }}</div>\n }\n @for (result of activeList(); track result.value; let i = $index) {\n <div\n class=\"ul-search-input__option\"\n [class.ul-search-input__option--highlighted]=\"combobox.highlightedIndex() === i\"\n [id]=\"optionId(i)\"\n role=\"option\"\n [attr.aria-selected]=\"value() === result.label\"\n (mousedown)=\"selectSuggestion(result)\"\n >\n <ul-list-item theme=\"ghost-white\" [hideFocusOutline]=\"true\">\n @if (result.icon) {\n <ng-container ul-list-item-before-label>\n <ul-icon size=\"5\" [icon]=\"result.icon\" />\n </ng-container>\n }\n <ng-container ul-list-item-label>{{ result.label }}</ng-container>\n </ul-list-item>\n </div>\n }\n</ng-template>\n\n<div\n class=\"ul-search-input ul-search-input--{{ size() }}\"\n [class.ul-search-input--error]=\"hasError()\"\n [class.ul-search-input--disabled]=\"disabled()\"\n>\n <ul-form-field-label\n [label]=\"label()\"\n [for]=\"ids.controlId\"\n [size]=\"size()\"\n [showRequiredIndicator]=\"false\"\n />\n\n @if (isMobile()) {\n <ul-input\n [controlId]=\"ids.controlId\"\n [value]=\"value()\"\n [readOnly]=\"true\"\n [size]=\"size()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [label]=\"null\"\n [helperText]=\"null\"\n (click)=\"openMobileSearch()\"\n >\n <ng-container ul-input-right-elements>\n <ul-icon size=\"5\" icon=\"search\" />\n </ng-container>\n </ul-input>\n\n <ul-modal [(open)]=\"combobox.isOpen\" [fullScreenInMobile]=\"true\" [showCloseButton]=\"false\">\n <div\n class=\"ul-search-input__combobox ul-search-input__combobox--takeover\"\n role=\"combobox\"\n [attr.aria-expanded]=\"shouldShowPanel()\"\n [attr.aria-controls]=\"listId\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n (keydown)=\"onKeydown($event)\"\n >\n <div class=\"ul-search-input__header\">\n <ul-button\n type=\"button\"\n theme=\"ghost-white\"\n size=\"sm\"\n [iconOnly]=\"true\"\n [ariaLabel]=\"backLabel()\"\n (buttonClick)=\"closeMobileSearch()\"\n >\n <ul-icon icon=\"arrow_left\" size=\"6\" />\n </ul-button>\n\n <ul-input\n #mobileInput\n class=\"ul-search-input__field\"\n [value]=\"value()\"\n (valueChange)=\"onValueChange($event)\"\n [size]=\"size()\"\n [placeholder]=\"placeholder()\"\n [label]=\"null\"\n [helperText]=\"null\"\n [autocomplete]=\"'off'\"\n >\n <ng-container ul-input-right-elements>\n @if (hasQuery()) {\n <ul-button\n type=\"button\"\n theme=\"ghost-white\"\n size=\"sm\"\n [iconOnly]=\"true\"\n [ariaLabel]=\"clearLabel()\"\n (buttonClick)=\"clearInput()\"\n >\n <ul-icon icon=\"cross\" size=\"4\" />\n </ul-button>\n } @else {\n <ul-icon size=\"5\" icon=\"search\" />\n }\n </ng-container>\n </ul-input>\n </div>\n\n @if (shouldShowPanel()) {\n <div\n class=\"ul-search-input__list ul-search-input__list--takeover ul-scrollable\"\n [id]=\"listId\"\n [attr.role]=\"hasCustomResults() ? null : 'listbox'\"\n [attr.aria-label]=\"hasCustomResults() ? null : activeListLabel()\"\n >\n @if (hasCustomResults()) {\n <ng-container *ngTemplateOutlet=\"resultsTemplate()!\" />\n } @else {\n <ng-container *ngTemplateOutlet=\"resultsList\" />\n }\n </div>\n }\n </div>\n </ul-modal>\n } @else {\n <div\n class=\"ul-search-input__combobox\"\n role=\"combobox\"\n [attr.aria-expanded]=\"shouldShowPanel()\"\n [attr.aria-controls]=\"listId\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n (keydown)=\"onKeydown($event)\"\n >\n <ul-input\n [controlId]=\"ids.controlId\"\n [value]=\"value()\"\n (valueChange)=\"onValueChange($event)\"\n (inputFocus)=\"onInputFocus()\"\n (inputBlur)=\"onInputBlur()\"\n [size]=\"size()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [label]=\"null\"\n [helperText]=\"null\"\n [autocomplete]=\"'off'\"\n >\n <ng-container ul-input-right-elements>\n @if (hasQuery()) {\n <ul-button\n type=\"button\"\n theme=\"ghost-white\"\n size=\"sm\"\n [iconOnly]=\"true\"\n [ariaLabel]=\"clearLabel()\"\n (buttonClick)=\"clearInput()\"\n >\n <ul-icon icon=\"cross\" size=\"4\" />\n </ul-button>\n } @else {\n <ul-icon size=\"5\" icon=\"search\" />\n }\n </ng-container>\n </ul-input>\n\n @if (shouldShowPanel()) {\n <div\n class=\"ul-search-input__list ul-scrollable\"\n [id]=\"listId\"\n [attr.role]=\"hasCustomResults() ? null : 'listbox'\"\n [attr.aria-label]=\"hasCustomResults() ? null : activeListLabel()\"\n >\n @if (hasCustomResults()) {\n <ng-container *ngTemplateOutlet=\"resultsTemplate()!\" />\n } @else {\n <ng-container *ngTemplateOutlet=\"resultsList\" />\n }\n </div>\n }\n </div>\n }\n\n <ul-form-field-helper\n [id]=\"ids.helperId\"\n [helperText]=\"helperText()\"\n [errorText]=\"errorText() || (hasError() && errors().length ? errors()[0].message : '') || null\"\n [error]=\"hasError()\"\n />\n</div>\n", styles: [".ul-rich-text{font-family:Ultra Nunito Sans;line-height:28px;font-size:18px;letter-spacing:0px;font-weight:400;color:#fff}.ul-rich-text p,.ul-rich-text ul,.ul-rich-text ol,.ul-rich-text blockquote,.ul-rich-text pre{margin-top:0;margin-bottom:16px}.ul-rich-text:last-child,.ul-rich-text p:last-child,.ul-rich-text ul:last-child,.ul-rich-text ol:last-child,.ul-rich-text blockquote:last-child,.ul-rich-text pre:last-child{margin-bottom:0}.ul-rich-text h1,.ul-rich-text h2,.ul-rich-text h3,.ul-rich-text h4,.ul-rich-text h5,.ul-rich-text h6{margin-top:32px;margin-bottom:12px;font-weight:1000}.ul-rich-text h1{font-family:Ultra Nunito Sans;line-height:48px;font-size:48px;letter-spacing:-.48px;font-weight:1000}.ul-rich-text h2{font-family:Ultra Nunito Sans;line-height:48px;font-size:40px;letter-spacing:-.4px;font-weight:1000}.ul-rich-text h3{font-family:Ultra Nunito Sans;line-height:44px;font-size:36px;letter-spacing:-.36px;font-weight:1000}.ul-rich-text h4{font-family:Ultra Nunito Sans;line-height:40px;font-size:32px;letter-spacing:-.32px;font-weight:1000}.ul-rich-text h5{font-family:Ultra Nunito Sans;line-height:36px;font-size:28px;letter-spacing:-.28px;font-weight:1000}.ul-rich-text h6{font-family:Ultra Nunito Sans;line-height:36px;font-size:24px;letter-spacing:-.24px;font-weight:1000}.ul-rich-text ul,.ul-rich-text ol{padding-left:24px}.ul-rich-text ul ul,.ul-rich-text ul ol,.ul-rich-text ol ul,.ul-rich-text ol ol{margin-top:8px;margin-bottom:8px}.ul-rich-text li{margin-top:4px;margin-bottom:4px}.ul-rich-text strong{font-weight:800}.ul-rich-text code{font-family:Roboto Mono;line-height:20px;font-size:14px;letter-spacing:0px;font-weight:400}.ul-rich-text em{font-style:italic}.ul-rich-text a{color:#c2a8ff;text-decoration:underline;text-decoration-thickness:1px}.ul-rich-text a:hover{color:#d6c5ff}.ul-rich-text a:active{color:#a781ff}.ul-rich-text pre{padding:16px;border-radius:8px;background-color:#3b3b3b;overflow-x:auto}.ul-rich-text pre code{font-family:Roboto Mono;line-height:20px;font-size:14px;letter-spacing:0px;font-weight:400}.ul-rich-text blockquote{margin-left:0;padding-left:16px;border-left-width:2px;border-left-style:solid;border-left-color:#ffffff1a;color:#ffffffb3}.ul-rich-text--muted{color:#ffffffb3}.ul-rich-text--inverse,.ul-rich-text--inverse a{color:#000}.ul-rich-text--inverse a:hover,.ul-rich-text--inverse a:active{color:#000000b3}.ul-rich-text--body-m{font-family:Ultra Nunito Sans;line-height:24px;font-size:16px;letter-spacing:0px;font-weight:400}.ul-rich-text--compact p,.ul-rich-text--compact ul,.ul-rich-text--compact ol,.ul-rich-text--compact blockquote,.ul-rich-text--compact pre{margin-bottom:8px}.ul-rich-text--compact h1,.ul-rich-text--compact h2,.ul-rich-text--compact h3,.ul-rich-text--compact h4,.ul-rich-text--compact h5,.ul-rich-text--compact h6{margin-top:16px;margin-bottom:8px}.ul-search-input{display:flex;flex-direction:column;gap:4px;width:100%}.ul-search-input__combobox{position:relative;display:flex;flex-direction:column;width:100%}.ul-search-input__combobox .ul-list-item:focus-visible,.ul-search-input__combobox .ul-list-item:focus{outline:none}.ul-search-input__combobox--takeover{height:100%}.ul-search-input__header{display:flex;align-items:center;flex-shrink:0;gap:8px;width:100%}.ul-search-input__field{flex:1;min-width:0}.ul-search-input__list{position:absolute;top:100%;left:0;right:0;z-index:1;display:flex;flex-direction:column;gap:4px;background-color:#232323;border-radius:16px;padding:4px;margin-top:4px;max-height:316px;overflow-y:auto;border:2px solid rgba(255,255,255,.1)}.ul-search-input__list--takeover{position:static;flex:1;min-height:0;margin-top:16px;max-height:none;padding:0;border:none;background-color:transparent}.ul-search-input__list-label{font-weight:400;color:#ffffffb3;padding:4px 8px}.ul-search-input__option{cursor:pointer;border-radius:8px}.ul-search-input__option--highlighted .ul-list-item{background-color:#fff3}.ul-search-input--disabled .ul-search-input__combobox{opacity:.6;cursor:not-allowed}.ul-search-input--error .ul-input__group{border-color:#f69d9d}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: InputComponent, selector: "ul-input", inputs: ["type", "size", "appearance", "error", "disabled", "readOnly", "required", "showRequiredIndicator", "placeholder", "label", "helperText", "errorText", "maxLength", "minLength", "pattern", "step", "autocomplete", "controlId", "showPasswordLabel", "hidePasswordLabel", "invalid", "errors", "touched", "value"], outputs: ["touchedChange", "touch", "valueChange", "inputBlur", "inputFocus", "inputEnter"] }, { kind: "component", type: IconComponent, selector: "ul-icon", inputs: ["size", "weight", "icon"] }, { kind: "component", type: ButtonComponent, selector: "ul-button", inputs: ["size", "theme", "iconOnly", "vertical", "disabled", "type", "ariaLabel"], outputs: ["buttonClick"] }, { kind: "component", type: ListItemComponent, selector: "ul-list-item", inputs: ["theme", "disabled", "hideFocusOutline", "selected", "loading"] }, { kind: "component", type: ModalComponent, selector: "ul-modal", inputs: ["open", "variant", "title", "closeOnBackdropClick", "showCloseButton", "confirmLabel", "cancelLabel", "customClass", "fullScreenInMobile"], outputs: ["openChange", "closed", "confirmed", "cancelled"] }, { kind: "component", type: FormFieldLabelComponent, selector: "ul-form-field-label", inputs: ["label", "required", "for", "size", "showRequiredIndicator"] }, { kind: "component", type: FormFieldHelperComponent, selector: "ul-form-field-helper", inputs: ["id", "helperText", "errorText", "error"] }] });
|
|
3991
|
+
}
|
|
3992
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: SearchInputComponent, decorators: [{
|
|
3993
|
+
type: Component,
|
|
3994
|
+
args: [{ selector: 'ul-search-input', imports: [
|
|
3995
|
+
NgTemplateOutlet,
|
|
3996
|
+
InputComponent,
|
|
3997
|
+
IconComponent,
|
|
3998
|
+
ButtonComponent,
|
|
3999
|
+
ListItemComponent,
|
|
4000
|
+
ModalComponent,
|
|
4001
|
+
FormFieldLabelComponent,
|
|
4002
|
+
FormFieldHelperComponent,
|
|
4003
|
+
], template: "<ng-template #resultsList>\n @if (activeListLabel()) {\n <div class=\"ul-search-input__list-label\" role=\"presentation\">{{ activeListLabel() }}</div>\n }\n @for (result of activeList(); track result.value; let i = $index) {\n <div\n class=\"ul-search-input__option\"\n [class.ul-search-input__option--highlighted]=\"combobox.highlightedIndex() === i\"\n [id]=\"optionId(i)\"\n role=\"option\"\n [attr.aria-selected]=\"value() === result.label\"\n (mousedown)=\"selectSuggestion(result)\"\n >\n <ul-list-item theme=\"ghost-white\" [hideFocusOutline]=\"true\">\n @if (result.icon) {\n <ng-container ul-list-item-before-label>\n <ul-icon size=\"5\" [icon]=\"result.icon\" />\n </ng-container>\n }\n <ng-container ul-list-item-label>{{ result.label }}</ng-container>\n </ul-list-item>\n </div>\n }\n</ng-template>\n\n<div\n class=\"ul-search-input ul-search-input--{{ size() }}\"\n [class.ul-search-input--error]=\"hasError()\"\n [class.ul-search-input--disabled]=\"disabled()\"\n>\n <ul-form-field-label\n [label]=\"label()\"\n [for]=\"ids.controlId\"\n [size]=\"size()\"\n [showRequiredIndicator]=\"false\"\n />\n\n @if (isMobile()) {\n <ul-input\n [controlId]=\"ids.controlId\"\n [value]=\"value()\"\n [readOnly]=\"true\"\n [size]=\"size()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [label]=\"null\"\n [helperText]=\"null\"\n (click)=\"openMobileSearch()\"\n >\n <ng-container ul-input-right-elements>\n <ul-icon size=\"5\" icon=\"search\" />\n </ng-container>\n </ul-input>\n\n <ul-modal [(open)]=\"combobox.isOpen\" [fullScreenInMobile]=\"true\" [showCloseButton]=\"false\">\n <div\n class=\"ul-search-input__combobox ul-search-input__combobox--takeover\"\n role=\"combobox\"\n [attr.aria-expanded]=\"shouldShowPanel()\"\n [attr.aria-controls]=\"listId\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n (keydown)=\"onKeydown($event)\"\n >\n <div class=\"ul-search-input__header\">\n <ul-button\n type=\"button\"\n theme=\"ghost-white\"\n size=\"sm\"\n [iconOnly]=\"true\"\n [ariaLabel]=\"backLabel()\"\n (buttonClick)=\"closeMobileSearch()\"\n >\n <ul-icon icon=\"arrow_left\" size=\"6\" />\n </ul-button>\n\n <ul-input\n #mobileInput\n class=\"ul-search-input__field\"\n [value]=\"value()\"\n (valueChange)=\"onValueChange($event)\"\n [size]=\"size()\"\n [placeholder]=\"placeholder()\"\n [label]=\"null\"\n [helperText]=\"null\"\n [autocomplete]=\"'off'\"\n >\n <ng-container ul-input-right-elements>\n @if (hasQuery()) {\n <ul-button\n type=\"button\"\n theme=\"ghost-white\"\n size=\"sm\"\n [iconOnly]=\"true\"\n [ariaLabel]=\"clearLabel()\"\n (buttonClick)=\"clearInput()\"\n >\n <ul-icon icon=\"cross\" size=\"4\" />\n </ul-button>\n } @else {\n <ul-icon size=\"5\" icon=\"search\" />\n }\n </ng-container>\n </ul-input>\n </div>\n\n @if (shouldShowPanel()) {\n <div\n class=\"ul-search-input__list ul-search-input__list--takeover ul-scrollable\"\n [id]=\"listId\"\n [attr.role]=\"hasCustomResults() ? null : 'listbox'\"\n [attr.aria-label]=\"hasCustomResults() ? null : activeListLabel()\"\n >\n @if (hasCustomResults()) {\n <ng-container *ngTemplateOutlet=\"resultsTemplate()!\" />\n } @else {\n <ng-container *ngTemplateOutlet=\"resultsList\" />\n }\n </div>\n }\n </div>\n </ul-modal>\n } @else {\n <div\n class=\"ul-search-input__combobox\"\n role=\"combobox\"\n [attr.aria-expanded]=\"shouldShowPanel()\"\n [attr.aria-controls]=\"listId\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n (keydown)=\"onKeydown($event)\"\n >\n <ul-input\n [controlId]=\"ids.controlId\"\n [value]=\"value()\"\n (valueChange)=\"onValueChange($event)\"\n (inputFocus)=\"onInputFocus()\"\n (inputBlur)=\"onInputBlur()\"\n [size]=\"size()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [label]=\"null\"\n [helperText]=\"null\"\n [autocomplete]=\"'off'\"\n >\n <ng-container ul-input-right-elements>\n @if (hasQuery()) {\n <ul-button\n type=\"button\"\n theme=\"ghost-white\"\n size=\"sm\"\n [iconOnly]=\"true\"\n [ariaLabel]=\"clearLabel()\"\n (buttonClick)=\"clearInput()\"\n >\n <ul-icon icon=\"cross\" size=\"4\" />\n </ul-button>\n } @else {\n <ul-icon size=\"5\" icon=\"search\" />\n }\n </ng-container>\n </ul-input>\n\n @if (shouldShowPanel()) {\n <div\n class=\"ul-search-input__list ul-scrollable\"\n [id]=\"listId\"\n [attr.role]=\"hasCustomResults() ? null : 'listbox'\"\n [attr.aria-label]=\"hasCustomResults() ? null : activeListLabel()\"\n >\n @if (hasCustomResults()) {\n <ng-container *ngTemplateOutlet=\"resultsTemplate()!\" />\n } @else {\n <ng-container *ngTemplateOutlet=\"resultsList\" />\n }\n </div>\n }\n </div>\n }\n\n <ul-form-field-helper\n [id]=\"ids.helperId\"\n [helperText]=\"helperText()\"\n [errorText]=\"errorText() || (hasError() && errors().length ? errors()[0].message : '') || null\"\n [error]=\"hasError()\"\n />\n</div>\n", styles: [".ul-rich-text{font-family:Ultra Nunito Sans;line-height:28px;font-size:18px;letter-spacing:0px;font-weight:400;color:#fff}.ul-rich-text p,.ul-rich-text ul,.ul-rich-text ol,.ul-rich-text blockquote,.ul-rich-text pre{margin-top:0;margin-bottom:16px}.ul-rich-text:last-child,.ul-rich-text p:last-child,.ul-rich-text ul:last-child,.ul-rich-text ol:last-child,.ul-rich-text blockquote:last-child,.ul-rich-text pre:last-child{margin-bottom:0}.ul-rich-text h1,.ul-rich-text h2,.ul-rich-text h3,.ul-rich-text h4,.ul-rich-text h5,.ul-rich-text h6{margin-top:32px;margin-bottom:12px;font-weight:1000}.ul-rich-text h1{font-family:Ultra Nunito Sans;line-height:48px;font-size:48px;letter-spacing:-.48px;font-weight:1000}.ul-rich-text h2{font-family:Ultra Nunito Sans;line-height:48px;font-size:40px;letter-spacing:-.4px;font-weight:1000}.ul-rich-text h3{font-family:Ultra Nunito Sans;line-height:44px;font-size:36px;letter-spacing:-.36px;font-weight:1000}.ul-rich-text h4{font-family:Ultra Nunito Sans;line-height:40px;font-size:32px;letter-spacing:-.32px;font-weight:1000}.ul-rich-text h5{font-family:Ultra Nunito Sans;line-height:36px;font-size:28px;letter-spacing:-.28px;font-weight:1000}.ul-rich-text h6{font-family:Ultra Nunito Sans;line-height:36px;font-size:24px;letter-spacing:-.24px;font-weight:1000}.ul-rich-text ul,.ul-rich-text ol{padding-left:24px}.ul-rich-text ul ul,.ul-rich-text ul ol,.ul-rich-text ol ul,.ul-rich-text ol ol{margin-top:8px;margin-bottom:8px}.ul-rich-text li{margin-top:4px;margin-bottom:4px}.ul-rich-text strong{font-weight:800}.ul-rich-text code{font-family:Roboto Mono;line-height:20px;font-size:14px;letter-spacing:0px;font-weight:400}.ul-rich-text em{font-style:italic}.ul-rich-text a{color:#c2a8ff;text-decoration:underline;text-decoration-thickness:1px}.ul-rich-text a:hover{color:#d6c5ff}.ul-rich-text a:active{color:#a781ff}.ul-rich-text pre{padding:16px;border-radius:8px;background-color:#3b3b3b;overflow-x:auto}.ul-rich-text pre code{font-family:Roboto Mono;line-height:20px;font-size:14px;letter-spacing:0px;font-weight:400}.ul-rich-text blockquote{margin-left:0;padding-left:16px;border-left-width:2px;border-left-style:solid;border-left-color:#ffffff1a;color:#ffffffb3}.ul-rich-text--muted{color:#ffffffb3}.ul-rich-text--inverse,.ul-rich-text--inverse a{color:#000}.ul-rich-text--inverse a:hover,.ul-rich-text--inverse a:active{color:#000000b3}.ul-rich-text--body-m{font-family:Ultra Nunito Sans;line-height:24px;font-size:16px;letter-spacing:0px;font-weight:400}.ul-rich-text--compact p,.ul-rich-text--compact ul,.ul-rich-text--compact ol,.ul-rich-text--compact blockquote,.ul-rich-text--compact pre{margin-bottom:8px}.ul-rich-text--compact h1,.ul-rich-text--compact h2,.ul-rich-text--compact h3,.ul-rich-text--compact h4,.ul-rich-text--compact h5,.ul-rich-text--compact h6{margin-top:16px;margin-bottom:8px}.ul-search-input{display:flex;flex-direction:column;gap:4px;width:100%}.ul-search-input__combobox{position:relative;display:flex;flex-direction:column;width:100%}.ul-search-input__combobox .ul-list-item:focus-visible,.ul-search-input__combobox .ul-list-item:focus{outline:none}.ul-search-input__combobox--takeover{height:100%}.ul-search-input__header{display:flex;align-items:center;flex-shrink:0;gap:8px;width:100%}.ul-search-input__field{flex:1;min-width:0}.ul-search-input__list{position:absolute;top:100%;left:0;right:0;z-index:1;display:flex;flex-direction:column;gap:4px;background-color:#232323;border-radius:16px;padding:4px;margin-top:4px;max-height:316px;overflow-y:auto;border:2px solid rgba(255,255,255,.1)}.ul-search-input__list--takeover{position:static;flex:1;min-height:0;margin-top:16px;max-height:none;padding:0;border:none;background-color:transparent}.ul-search-input__list-label{font-weight:400;color:#ffffffb3;padding:4px 8px}.ul-search-input__option{cursor:pointer;border-radius:8px}.ul-search-input__option--highlighted .ul-list-item{background-color:#fff3}.ul-search-input--disabled .ul-search-input__combobox{opacity:.6;cursor:not-allowed}.ul-search-input--error .ul-input__group{border-color:#f69d9d}\n"] }]
|
|
4004
|
+
}], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], helperText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helperText", required: false }] }], errorText: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorText", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], backLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "backLabel", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], suggestions: [{ type: i0.Input, args: [{ isSignal: true, alias: "suggestions", required: false }] }], suggestionsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "suggestionsLabel", required: false }] }], results: [{ type: i0.Input, args: [{ isSignal: true, alias: "results", required: false }] }], resultsTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "resultsTemplate", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], suggestionSelected: [{ type: i0.Output, args: ["suggestionSelected"] }], searchSubmit: [{ type: i0.Output, args: ["searchSubmit"] }], mobileInput: [{ type: i0.ViewChild, args: ['mobileInput', { isSignal: true }] }] } });
|
|
4005
|
+
|
|
3737
4006
|
/**
|
|
3738
4007
|
* Combobox: search input with filterable dropdown. User types to filter options and selects a result.
|
|
3739
4008
|
* Implements FormValueControl for use with Signal Forms [formField]. Use [(value)] for two-way binding.
|
|
@@ -3770,13 +4039,8 @@ class SearchSelectComponent {
|
|
|
3770
4039
|
ids = createFormFieldIds('ul-search-select');
|
|
3771
4040
|
query = signal('', /* @ts-ignore */
|
|
3772
4041
|
...(ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []));
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
isFocused = signal(false, /* @ts-ignore */
|
|
3776
|
-
...(ngDevMode ? [{ debugName: "isFocused" }] : /* istanbul ignore next */ []));
|
|
3777
|
-
highlightedIndex = signal(0, /* @ts-ignore */
|
|
3778
|
-
...(ngDevMode ? [{ debugName: "highlightedIndex" }] : /* istanbul ignore next */ []));
|
|
3779
|
-
blurCloseTimeout = null;
|
|
4042
|
+
/** Open/focus/highlight state and arrow-key/Escape mechanics shared with ul-search-input. */
|
|
4043
|
+
combobox = new ComboboxState();
|
|
3780
4044
|
listId = `${this.ids.controlId}-list`;
|
|
3781
4045
|
hasError = computed(() => this.error() || this.invalid(), /* @ts-ignore */
|
|
3782
4046
|
...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
|
|
@@ -3800,7 +4064,7 @@ class SearchSelectComponent {
|
|
|
3800
4064
|
}, /* @ts-ignore */
|
|
3801
4065
|
...(ngDevMode ? [{ debugName: "filteredOptions" }] : /* istanbul ignore next */ []));
|
|
3802
4066
|
displayText = computed(() => {
|
|
3803
|
-
if (this.isOpen())
|
|
4067
|
+
if (this.combobox.isOpen())
|
|
3804
4068
|
return this.query();
|
|
3805
4069
|
if (this.value() != null)
|
|
3806
4070
|
return this.selectedLabel();
|
|
@@ -3808,7 +4072,7 @@ class SearchSelectComponent {
|
|
|
3808
4072
|
}, /* @ts-ignore */
|
|
3809
4073
|
...(ngDevMode ? [{ debugName: "displayText" }] : /* istanbul ignore next */ []));
|
|
3810
4074
|
shouldShowPanel = computed(() => {
|
|
3811
|
-
if (!this.isOpen())
|
|
4075
|
+
if (!this.combobox.isOpen())
|
|
3812
4076
|
return false;
|
|
3813
4077
|
const min = this.minCharsToOpen();
|
|
3814
4078
|
return this.query().trim().length >= min;
|
|
@@ -3816,40 +4080,28 @@ class SearchSelectComponent {
|
|
|
3816
4080
|
...(ngDevMode ? [{ debugName: "shouldShowPanel" }] : /* istanbul ignore next */ []));
|
|
3817
4081
|
hasNoResults = computed(() => this.shouldShowPanel() && this.filteredOptions().length === 0, /* @ts-ignore */
|
|
3818
4082
|
...(ngDevMode ? [{ debugName: "hasNoResults" }] : /* istanbul ignore next */ []));
|
|
3819
|
-
optionId = (index) =>
|
|
3820
|
-
activeDescendantId = computed(() =>
|
|
3821
|
-
const list = this.filteredOptions();
|
|
3822
|
-
const idx = this.highlightedIndex();
|
|
3823
|
-
if (list.length === 0)
|
|
3824
|
-
return undefined;
|
|
3825
|
-
const safeIdx = Math.min(Math.max(0, idx), list.length - 1);
|
|
3826
|
-
return this.optionId(safeIdx);
|
|
3827
|
-
}, /* @ts-ignore */
|
|
4083
|
+
optionId = (index) => comboboxOptionId(this.ids.controlId, index);
|
|
4084
|
+
activeDescendantId = computed(() => comboboxActiveDescendantId(this.ids.controlId, this.filteredOptions().length, this.combobox.highlightedIndex()), /* @ts-ignore */
|
|
3828
4085
|
...(ngDevMode ? [{ debugName: "activeDescendantId" }] : /* istanbul ignore next */ []));
|
|
3829
4086
|
onInputValueChange(text) {
|
|
3830
4087
|
this.query.set(text);
|
|
3831
|
-
this.isOpen.set(true);
|
|
3832
|
-
this.
|
|
4088
|
+
this.combobox.isOpen.set(true);
|
|
4089
|
+
this.combobox.resetHighlight();
|
|
3833
4090
|
if (this.value() != null && text !== this.selectedLabel()) {
|
|
3834
4091
|
this.value.set(null);
|
|
3835
4092
|
}
|
|
3836
4093
|
}
|
|
3837
4094
|
onInputFocus() {
|
|
3838
|
-
this.
|
|
3839
|
-
this.isFocused.set(true);
|
|
4095
|
+
this.combobox.open();
|
|
3840
4096
|
if (this.value() != null)
|
|
3841
4097
|
this.query.set(this.selectedLabel());
|
|
3842
|
-
this.
|
|
3843
|
-
this.highlightedIndex.set(0);
|
|
4098
|
+
this.combobox.resetHighlight();
|
|
3844
4099
|
}
|
|
3845
4100
|
onInputBlur() {
|
|
3846
|
-
this.
|
|
3847
|
-
this.blurCloseTimeout = setTimeout(() => {
|
|
3848
|
-
this.blurCloseTimeout = null;
|
|
3849
|
-
this.isOpen.set(false);
|
|
4101
|
+
this.combobox.scheduleClose(() => {
|
|
3850
4102
|
if (this.value() != null)
|
|
3851
4103
|
this.query.set(this.selectedLabel());
|
|
3852
|
-
}
|
|
4104
|
+
});
|
|
3853
4105
|
}
|
|
3854
4106
|
onKeydown(event) {
|
|
3855
4107
|
if (!this.shouldShowPanel())
|
|
@@ -3857,41 +4109,20 @@ class SearchSelectComponent {
|
|
|
3857
4109
|
const list = this.filteredOptions();
|
|
3858
4110
|
if (list.length === 0)
|
|
3859
4111
|
return;
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
case 'ArrowUp':
|
|
3866
|
-
event.preventDefault();
|
|
3867
|
-
this.highlightedIndex.set(this.highlightedIndex() <= 0 ? list.length - 1 : this.highlightedIndex() - 1);
|
|
3868
|
-
break;
|
|
3869
|
-
case 'Enter':
|
|
3870
|
-
event.preventDefault();
|
|
3871
|
-
this.selectOption(list[this.highlightedIndex()]);
|
|
3872
|
-
break;
|
|
3873
|
-
case 'Escape':
|
|
3874
|
-
event.preventDefault();
|
|
3875
|
-
this.isOpen.set(false);
|
|
3876
|
-
break;
|
|
3877
|
-
default:
|
|
3878
|
-
break;
|
|
4112
|
+
if (this.combobox.handleNavigationKey(event, list.length))
|
|
4113
|
+
return;
|
|
4114
|
+
if (event.key === 'Enter') {
|
|
4115
|
+
event.preventDefault();
|
|
4116
|
+
this.selectOption(list[this.combobox.highlightedIndex()]);
|
|
3879
4117
|
}
|
|
3880
4118
|
}
|
|
3881
4119
|
selectOption(opt) {
|
|
3882
|
-
this.
|
|
4120
|
+
this.combobox.close();
|
|
3883
4121
|
this.value.set(opt.value);
|
|
3884
4122
|
this.query.set(opt.label);
|
|
3885
|
-
this.isOpen.set(false);
|
|
3886
|
-
}
|
|
3887
|
-
cancelBlurClose() {
|
|
3888
|
-
if (this.blurCloseTimeout != null) {
|
|
3889
|
-
clearTimeout(this.blurCloseTimeout);
|
|
3890
|
-
this.blurCloseTimeout = null;
|
|
3891
|
-
}
|
|
3892
4123
|
}
|
|
3893
4124
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: SearchSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3894
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.0", type: SearchSelectComponent, isStandalone: true, selector: "ul-search-select", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, helperText: { classPropertyName: "helperText", publicName: "helperText", isSignal: true, isRequired: false, transformFunction: null }, errorText: { classPropertyName: "errorText", publicName: "errorText", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, showRequiredIndicator: { classPropertyName: "showRequiredIndicator", publicName: "showRequiredIndicator", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, minCharsToOpen: { classPropertyName: "minCharsToOpen", publicName: "minCharsToOpen", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, ngImport: i0, template: "<div\n class=\"ul-search-select ul-search-select--{{ size() }}\"\n [class.ul-search-select--open]=\"isOpen()\"\n [class.ul-search-select--error]=\"hasError()\"\n [class.ul-search-select--disabled]=\"disabled()\"\n [class.ul-search-select--required]=\"required()\"\n [attr.aria-invalid]=\"hasError()\"\n [attr.aria-required]=\"required()\"\n [attr.aria-describedby]=\"describedBy()\"\n>\n <ul-form-field-label\n [label]=\"label()\"\n [required]=\"required()\"\n [for]=\"ids.controlId\"\n [size]=\"size()\"\n [showRequiredIndicator]=\"showRequiredIndicator()\"\n />\n\n <div\n class=\"ul-search-select__control\"\n [class.ul-search-select__control--focused]=\"isFocused()\"\n role=\"combobox\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"listId\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n (keydown)=\"onKeydown($event)\"\n >\n <ul-input\n [controlId]=\"ids.controlId\"\n [value]=\"displayText()\"\n (valueChange)=\"onInputValueChange($event)\"\n (inputFocus)=\"onInputFocus()\"\n (inputBlur)=\"onInputBlur()\"\n [size]=\"size()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [label]=\"null\"\n [helperText]=\"null\"\n [autocomplete]=\"'off'\"\n >\n <ng-container ul-input-right-elements>\n <ul-icon size=\"5\" icon=\"search\" />\n </ng-container>\n </ul-input>\n\n @if (shouldShowPanel()) {\n <div\n class=\"ul-search-select__list ul-scrollable\"\n [class.ul-search-select__list--empty]=\"hasNoResults()\"\n [id]=\"listId\"\n role=\"listbox\"\n >\n @if (hasNoResults()) {\n <div class=\"ul-search-select__empty\" role=\"status\">No results</div>\n } @else {\n @for (opt of filteredOptions(); track opt.value; let i = $index) {\n <div\n class=\"ul-search-select__option\"\n [class.ul-search-select__option--highlighted]=\"highlightedIndex() === i\"\n [id]=\"optionId(i)\"\n role=\"option\"\n [attr.aria-selected]=\"value() === opt.value\"\n (mousedown)=\"selectOption(opt)\"\n >\n <ul-list-item\n theme=\"ghost-white\"\n [selected]=\"value() === opt.value\"\n [hideFocusOutline]=\"true\"\n >\n <ng-container ul-list-item-label>{{ opt.label }}</ng-container>\n </ul-list-item>\n </div>\n }\n }\n </div>\n }\n </div>\n\n <ul-form-field-helper\n [id]=\"ids.helperId\"\n [helperText]=\"helperText()\"\n [errorText]=\"errorText() || (hasError() && errors().length ? errors()[0].message : '') || null\"\n [error]=\"hasError()\"\n />\n</div>\n", styles: [".ul-rich-text{font-family:Ultra Nunito Sans;line-height:28px;font-size:18px;letter-spacing:0px;font-weight:400;color:#fff}.ul-rich-text p,.ul-rich-text ul,.ul-rich-text ol,.ul-rich-text blockquote,.ul-rich-text pre{margin-top:0;margin-bottom:16px}.ul-rich-text:last-child,.ul-rich-text p:last-child,.ul-rich-text ul:last-child,.ul-rich-text ol:last-child,.ul-rich-text blockquote:last-child,.ul-rich-text pre:last-child{margin-bottom:0}.ul-rich-text h1,.ul-rich-text h2,.ul-rich-text h3,.ul-rich-text h4,.ul-rich-text h5,.ul-rich-text h6{margin-top:32px;margin-bottom:12px;font-weight:1000}.ul-rich-text h1{font-family:Ultra Nunito Sans;line-height:48px;font-size:48px;letter-spacing:-.48px;font-weight:1000}.ul-rich-text h2{font-family:Ultra Nunito Sans;line-height:48px;font-size:40px;letter-spacing:-.4px;font-weight:1000}.ul-rich-text h3{font-family:Ultra Nunito Sans;line-height:44px;font-size:36px;letter-spacing:-.36px;font-weight:1000}.ul-rich-text h4{font-family:Ultra Nunito Sans;line-height:40px;font-size:32px;letter-spacing:-.32px;font-weight:1000}.ul-rich-text h5{font-family:Ultra Nunito Sans;line-height:36px;font-size:28px;letter-spacing:-.28px;font-weight:1000}.ul-rich-text h6{font-family:Ultra Nunito Sans;line-height:36px;font-size:24px;letter-spacing:-.24px;font-weight:1000}.ul-rich-text ul,.ul-rich-text ol{padding-left:24px}.ul-rich-text ul ul,.ul-rich-text ul ol,.ul-rich-text ol ul,.ul-rich-text ol ol{margin-top:8px;margin-bottom:8px}.ul-rich-text li{margin-top:4px;margin-bottom:4px}.ul-rich-text strong{font-weight:800}.ul-rich-text code{font-family:Roboto Mono;line-height:20px;font-size:14px;letter-spacing:0px;font-weight:400}.ul-rich-text em{font-style:italic}.ul-rich-text a{color:#c2a8ff;text-decoration:underline;text-decoration-thickness:1px}.ul-rich-text a:hover{color:#d6c5ff}.ul-rich-text a:active{color:#a781ff}.ul-rich-text pre{padding:16px;border-radius:8px;background-color:#3b3b3b;overflow-x:auto}.ul-rich-text pre code{font-family:Roboto Mono;line-height:20px;font-size:14px;letter-spacing:0px;font-weight:400}.ul-rich-text blockquote{margin-left:0;padding-left:16px;border-left-width:2px;border-left-style:solid;border-left-color:#ffffff1a;color:#ffffffb3}.ul-rich-text--muted{color:#ffffffb3}.ul-rich-text--inverse,.ul-rich-text--inverse a{color:#000}.ul-rich-text--inverse a:hover,.ul-rich-text--inverse a:active{color:#000000b3}.ul-rich-text--body-m{font-family:Ultra Nunito Sans;line-height:24px;font-size:16px;letter-spacing:0px;font-weight:400}.ul-rich-text--compact p,.ul-rich-text--compact ul,.ul-rich-text--compact ol,.ul-rich-text--compact blockquote,.ul-rich-text--compact pre{margin-bottom:8px}.ul-rich-text--compact h1,.ul-rich-text--compact h2,.ul-rich-text--compact h3,.ul-rich-text--compact h4,.ul-rich-text--compact h5,.ul-rich-text--compact h6{margin-top:16px;margin-bottom:8px}.ul-search-select{white-space:nowrap;box-sizing:border-box;display:flex;flex-direction:column;gap:4px;width:100%}.ul-search-select__control{position:relative;display:flex;flex-direction:column;width:100%}.ul-search-select__control .ul-list-item:focus-visible,.ul-search-select__control .ul-list-item:focus{outline:none}.ul-search-select__list{position:absolute;top:100%;left:0;right:0;z-index:1;display:flex;flex-direction:column;gap:4px;background-color:#232323;border-radius:16px;padding:4px;margin-top:4px;max-height:316px;overflow-y:auto;border:2px solid rgba(255,255,255,.1)}.ul-search-select__list--empty{padding:12px}.ul-search-select__option{cursor:pointer;border-radius:8px}.ul-search-select__option--highlighted .ul-list-item{background-color:#fff3}.ul-search-select__empty{font-family:Ultra Nunito Sans;line-height:24px;font-size:16px;letter-spacing:0px;font-weight:400;color:#ffffffb3}.ul-search-select--disabled .ul-search-select__control{opacity:.6;cursor:not-allowed}.ul-search-select--error .ul-input__group{border-color:#f69d9d}@media(max-width:1023px){.ul-search-select__list{max-height:316px}}@media(min-width:1024px){.ul-search-select__control{max-width:100%}}\n"], dependencies: [{ kind: "component", type: InputComponent, selector: "ul-input", inputs: ["type", "size", "appearance", "error", "disabled", "readOnly", "required", "showRequiredIndicator", "placeholder", "label", "helperText", "errorText", "maxLength", "minLength", "pattern", "step", "autocomplete", "controlId", "showPasswordLabel", "hidePasswordLabel", "invalid", "errors", "touched", "value"], outputs: ["touchedChange", "touch", "valueChange", "inputBlur", "inputFocus", "inputEnter"] }, { kind: "component", type: IconComponent, selector: "ul-icon", inputs: ["size", "weight", "icon"] }, { kind: "component", type: ListItemComponent, selector: "ul-list-item", inputs: ["theme", "disabled", "hideFocusOutline", "selected", "loading"] }, { kind: "component", type: FormFieldLabelComponent, selector: "ul-form-field-label", inputs: ["label", "required", "for", "size", "showRequiredIndicator"] }, { kind: "component", type: FormFieldHelperComponent, selector: "ul-form-field-helper", inputs: ["id", "helperText", "errorText", "error"] }] });
|
|
4125
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.0", type: SearchSelectComponent, isStandalone: true, selector: "ul-search-select", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, helperText: { classPropertyName: "helperText", publicName: "helperText", isSignal: true, isRequired: false, transformFunction: null }, errorText: { classPropertyName: "errorText", publicName: "errorText", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, showRequiredIndicator: { classPropertyName: "showRequiredIndicator", publicName: "showRequiredIndicator", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, minCharsToOpen: { classPropertyName: "minCharsToOpen", publicName: "minCharsToOpen", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, ngImport: i0, template: "<div\n class=\"ul-search-select ul-search-select--{{ size() }}\"\n [class.ul-search-select--open]=\"combobox.isOpen()\"\n [class.ul-search-select--error]=\"hasError()\"\n [class.ul-search-select--disabled]=\"disabled()\"\n [class.ul-search-select--required]=\"required()\"\n [attr.aria-invalid]=\"hasError()\"\n [attr.aria-required]=\"required()\"\n [attr.aria-describedby]=\"describedBy()\"\n>\n <ul-form-field-label\n [label]=\"label()\"\n [required]=\"required()\"\n [for]=\"ids.controlId\"\n [size]=\"size()\"\n [showRequiredIndicator]=\"showRequiredIndicator()\"\n />\n\n <div\n class=\"ul-search-select__control\"\n [class.ul-search-select__control--focused]=\"combobox.isFocused()\"\n role=\"combobox\"\n [attr.aria-expanded]=\"combobox.isOpen()\"\n [attr.aria-controls]=\"listId\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n (keydown)=\"onKeydown($event)\"\n >\n <ul-input\n [controlId]=\"ids.controlId\"\n [value]=\"displayText()\"\n (valueChange)=\"onInputValueChange($event)\"\n (inputFocus)=\"onInputFocus()\"\n (inputBlur)=\"onInputBlur()\"\n [size]=\"size()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [label]=\"null\"\n [helperText]=\"null\"\n [autocomplete]=\"'off'\"\n >\n <ng-container ul-input-right-elements>\n <ul-icon size=\"5\" icon=\"search\" />\n </ng-container>\n </ul-input>\n\n @if (shouldShowPanel()) {\n <div\n class=\"ul-search-select__list ul-scrollable\"\n [class.ul-search-select__list--empty]=\"hasNoResults()\"\n [id]=\"listId\"\n role=\"listbox\"\n >\n @if (hasNoResults()) {\n <div class=\"ul-search-select__empty\" role=\"status\">No results</div>\n } @else {\n @for (opt of filteredOptions(); track opt.value; let i = $index) {\n <div\n class=\"ul-search-select__option\"\n [class.ul-search-select__option--highlighted]=\"combobox.highlightedIndex() === i\"\n [id]=\"optionId(i)\"\n role=\"option\"\n [attr.aria-selected]=\"value() === opt.value\"\n (mousedown)=\"selectOption(opt)\"\n >\n <ul-list-item\n theme=\"ghost-white\"\n [selected]=\"value() === opt.value\"\n [hideFocusOutline]=\"true\"\n >\n <ng-container ul-list-item-label>{{ opt.label }}</ng-container>\n </ul-list-item>\n </div>\n }\n }\n </div>\n }\n </div>\n\n <ul-form-field-helper\n [id]=\"ids.helperId\"\n [helperText]=\"helperText()\"\n [errorText]=\"errorText() || (hasError() && errors().length ? errors()[0].message : '') || null\"\n [error]=\"hasError()\"\n />\n</div>\n", styles: [".ul-rich-text{font-family:Ultra Nunito Sans;line-height:28px;font-size:18px;letter-spacing:0px;font-weight:400;color:#fff}.ul-rich-text p,.ul-rich-text ul,.ul-rich-text ol,.ul-rich-text blockquote,.ul-rich-text pre{margin-top:0;margin-bottom:16px}.ul-rich-text:last-child,.ul-rich-text p:last-child,.ul-rich-text ul:last-child,.ul-rich-text ol:last-child,.ul-rich-text blockquote:last-child,.ul-rich-text pre:last-child{margin-bottom:0}.ul-rich-text h1,.ul-rich-text h2,.ul-rich-text h3,.ul-rich-text h4,.ul-rich-text h5,.ul-rich-text h6{margin-top:32px;margin-bottom:12px;font-weight:1000}.ul-rich-text h1{font-family:Ultra Nunito Sans;line-height:48px;font-size:48px;letter-spacing:-.48px;font-weight:1000}.ul-rich-text h2{font-family:Ultra Nunito Sans;line-height:48px;font-size:40px;letter-spacing:-.4px;font-weight:1000}.ul-rich-text h3{font-family:Ultra Nunito Sans;line-height:44px;font-size:36px;letter-spacing:-.36px;font-weight:1000}.ul-rich-text h4{font-family:Ultra Nunito Sans;line-height:40px;font-size:32px;letter-spacing:-.32px;font-weight:1000}.ul-rich-text h5{font-family:Ultra Nunito Sans;line-height:36px;font-size:28px;letter-spacing:-.28px;font-weight:1000}.ul-rich-text h6{font-family:Ultra Nunito Sans;line-height:36px;font-size:24px;letter-spacing:-.24px;font-weight:1000}.ul-rich-text ul,.ul-rich-text ol{padding-left:24px}.ul-rich-text ul ul,.ul-rich-text ul ol,.ul-rich-text ol ul,.ul-rich-text ol ol{margin-top:8px;margin-bottom:8px}.ul-rich-text li{margin-top:4px;margin-bottom:4px}.ul-rich-text strong{font-weight:800}.ul-rich-text code{font-family:Roboto Mono;line-height:20px;font-size:14px;letter-spacing:0px;font-weight:400}.ul-rich-text em{font-style:italic}.ul-rich-text a{color:#c2a8ff;text-decoration:underline;text-decoration-thickness:1px}.ul-rich-text a:hover{color:#d6c5ff}.ul-rich-text a:active{color:#a781ff}.ul-rich-text pre{padding:16px;border-radius:8px;background-color:#3b3b3b;overflow-x:auto}.ul-rich-text pre code{font-family:Roboto Mono;line-height:20px;font-size:14px;letter-spacing:0px;font-weight:400}.ul-rich-text blockquote{margin-left:0;padding-left:16px;border-left-width:2px;border-left-style:solid;border-left-color:#ffffff1a;color:#ffffffb3}.ul-rich-text--muted{color:#ffffffb3}.ul-rich-text--inverse,.ul-rich-text--inverse a{color:#000}.ul-rich-text--inverse a:hover,.ul-rich-text--inverse a:active{color:#000000b3}.ul-rich-text--body-m{font-family:Ultra Nunito Sans;line-height:24px;font-size:16px;letter-spacing:0px;font-weight:400}.ul-rich-text--compact p,.ul-rich-text--compact ul,.ul-rich-text--compact ol,.ul-rich-text--compact blockquote,.ul-rich-text--compact pre{margin-bottom:8px}.ul-rich-text--compact h1,.ul-rich-text--compact h2,.ul-rich-text--compact h3,.ul-rich-text--compact h4,.ul-rich-text--compact h5,.ul-rich-text--compact h6{margin-top:16px;margin-bottom:8px}.ul-search-select{white-space:nowrap;box-sizing:border-box;display:flex;flex-direction:column;gap:4px;width:100%}.ul-search-select__control{position:relative;display:flex;flex-direction:column;width:100%}.ul-search-select__control .ul-list-item:focus-visible,.ul-search-select__control .ul-list-item:focus{outline:none}.ul-search-select__list{position:absolute;top:100%;left:0;right:0;z-index:1;display:flex;flex-direction:column;gap:4px;background-color:#232323;border-radius:16px;padding:4px;margin-top:4px;max-height:316px;overflow-y:auto;border:2px solid rgba(255,255,255,.1)}.ul-search-select__list--empty{padding:12px}.ul-search-select__option{cursor:pointer;border-radius:8px}.ul-search-select__option--highlighted .ul-list-item{background-color:#fff3}.ul-search-select__empty{font-family:Ultra Nunito Sans;line-height:24px;font-size:16px;letter-spacing:0px;font-weight:400;color:#ffffffb3}.ul-search-select--disabled .ul-search-select__control{opacity:.6;cursor:not-allowed}.ul-search-select--error .ul-input__group{border-color:#f69d9d}@media(max-width:1023px){.ul-search-select__list{max-height:316px}}@media(min-width:1024px){.ul-search-select__control{max-width:100%}}\n"], dependencies: [{ kind: "component", type: InputComponent, selector: "ul-input", inputs: ["type", "size", "appearance", "error", "disabled", "readOnly", "required", "showRequiredIndicator", "placeholder", "label", "helperText", "errorText", "maxLength", "minLength", "pattern", "step", "autocomplete", "controlId", "showPasswordLabel", "hidePasswordLabel", "invalid", "errors", "touched", "value"], outputs: ["touchedChange", "touch", "valueChange", "inputBlur", "inputFocus", "inputEnter"] }, { kind: "component", type: IconComponent, selector: "ul-icon", inputs: ["size", "weight", "icon"] }, { kind: "component", type: ListItemComponent, selector: "ul-list-item", inputs: ["theme", "disabled", "hideFocusOutline", "selected", "loading"] }, { kind: "component", type: FormFieldLabelComponent, selector: "ul-form-field-label", inputs: ["label", "required", "for", "size", "showRequiredIndicator"] }, { kind: "component", type: FormFieldHelperComponent, selector: "ul-form-field-helper", inputs: ["id", "helperText", "errorText", "error"] }] });
|
|
3895
4126
|
}
|
|
3896
4127
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: SearchSelectComponent, decorators: [{
|
|
3897
4128
|
type: Component,
|
|
@@ -3901,7 +4132,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImpor
|
|
|
3901
4132
|
ListItemComponent,
|
|
3902
4133
|
FormFieldLabelComponent,
|
|
3903
4134
|
FormFieldHelperComponent,
|
|
3904
|
-
], template: "<div\n class=\"ul-search-select ul-search-select--{{ size() }}\"\n [class.ul-search-select--open]=\"isOpen()\"\n [class.ul-search-select--error]=\"hasError()\"\n [class.ul-search-select--disabled]=\"disabled()\"\n [class.ul-search-select--required]=\"required()\"\n [attr.aria-invalid]=\"hasError()\"\n [attr.aria-required]=\"required()\"\n [attr.aria-describedby]=\"describedBy()\"\n>\n <ul-form-field-label\n [label]=\"label()\"\n [required]=\"required()\"\n [for]=\"ids.controlId\"\n [size]=\"size()\"\n [showRequiredIndicator]=\"showRequiredIndicator()\"\n />\n\n <div\n class=\"ul-search-select__control\"\n [class.ul-search-select__control--focused]=\"isFocused()\"\n role=\"combobox\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"listId\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n (keydown)=\"onKeydown($event)\"\n >\n <ul-input\n [controlId]=\"ids.controlId\"\n [value]=\"displayText()\"\n (valueChange)=\"onInputValueChange($event)\"\n (inputFocus)=\"onInputFocus()\"\n (inputBlur)=\"onInputBlur()\"\n [size]=\"size()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [label]=\"null\"\n [helperText]=\"null\"\n [autocomplete]=\"'off'\"\n >\n <ng-container ul-input-right-elements>\n <ul-icon size=\"5\" icon=\"search\" />\n </ng-container>\n </ul-input>\n\n @if (shouldShowPanel()) {\n <div\n class=\"ul-search-select__list ul-scrollable\"\n [class.ul-search-select__list--empty]=\"hasNoResults()\"\n [id]=\"listId\"\n role=\"listbox\"\n >\n @if (hasNoResults()) {\n <div class=\"ul-search-select__empty\" role=\"status\">No results</div>\n } @else {\n @for (opt of filteredOptions(); track opt.value; let i = $index) {\n <div\n class=\"ul-search-select__option\"\n [class.ul-search-select__option--highlighted]=\"highlightedIndex() === i\"\n [id]=\"optionId(i)\"\n role=\"option\"\n [attr.aria-selected]=\"value() === opt.value\"\n (mousedown)=\"selectOption(opt)\"\n >\n <ul-list-item\n theme=\"ghost-white\"\n [selected]=\"value() === opt.value\"\n [hideFocusOutline]=\"true\"\n >\n <ng-container ul-list-item-label>{{ opt.label }}</ng-container>\n </ul-list-item>\n </div>\n }\n }\n </div>\n }\n </div>\n\n <ul-form-field-helper\n [id]=\"ids.helperId\"\n [helperText]=\"helperText()\"\n [errorText]=\"errorText() || (hasError() && errors().length ? errors()[0].message : '') || null\"\n [error]=\"hasError()\"\n />\n</div>\n", styles: [".ul-rich-text{font-family:Ultra Nunito Sans;line-height:28px;font-size:18px;letter-spacing:0px;font-weight:400;color:#fff}.ul-rich-text p,.ul-rich-text ul,.ul-rich-text ol,.ul-rich-text blockquote,.ul-rich-text pre{margin-top:0;margin-bottom:16px}.ul-rich-text:last-child,.ul-rich-text p:last-child,.ul-rich-text ul:last-child,.ul-rich-text ol:last-child,.ul-rich-text blockquote:last-child,.ul-rich-text pre:last-child{margin-bottom:0}.ul-rich-text h1,.ul-rich-text h2,.ul-rich-text h3,.ul-rich-text h4,.ul-rich-text h5,.ul-rich-text h6{margin-top:32px;margin-bottom:12px;font-weight:1000}.ul-rich-text h1{font-family:Ultra Nunito Sans;line-height:48px;font-size:48px;letter-spacing:-.48px;font-weight:1000}.ul-rich-text h2{font-family:Ultra Nunito Sans;line-height:48px;font-size:40px;letter-spacing:-.4px;font-weight:1000}.ul-rich-text h3{font-family:Ultra Nunito Sans;line-height:44px;font-size:36px;letter-spacing:-.36px;font-weight:1000}.ul-rich-text h4{font-family:Ultra Nunito Sans;line-height:40px;font-size:32px;letter-spacing:-.32px;font-weight:1000}.ul-rich-text h5{font-family:Ultra Nunito Sans;line-height:36px;font-size:28px;letter-spacing:-.28px;font-weight:1000}.ul-rich-text h6{font-family:Ultra Nunito Sans;line-height:36px;font-size:24px;letter-spacing:-.24px;font-weight:1000}.ul-rich-text ul,.ul-rich-text ol{padding-left:24px}.ul-rich-text ul ul,.ul-rich-text ul ol,.ul-rich-text ol ul,.ul-rich-text ol ol{margin-top:8px;margin-bottom:8px}.ul-rich-text li{margin-top:4px;margin-bottom:4px}.ul-rich-text strong{font-weight:800}.ul-rich-text code{font-family:Roboto Mono;line-height:20px;font-size:14px;letter-spacing:0px;font-weight:400}.ul-rich-text em{font-style:italic}.ul-rich-text a{color:#c2a8ff;text-decoration:underline;text-decoration-thickness:1px}.ul-rich-text a:hover{color:#d6c5ff}.ul-rich-text a:active{color:#a781ff}.ul-rich-text pre{padding:16px;border-radius:8px;background-color:#3b3b3b;overflow-x:auto}.ul-rich-text pre code{font-family:Roboto Mono;line-height:20px;font-size:14px;letter-spacing:0px;font-weight:400}.ul-rich-text blockquote{margin-left:0;padding-left:16px;border-left-width:2px;border-left-style:solid;border-left-color:#ffffff1a;color:#ffffffb3}.ul-rich-text--muted{color:#ffffffb3}.ul-rich-text--inverse,.ul-rich-text--inverse a{color:#000}.ul-rich-text--inverse a:hover,.ul-rich-text--inverse a:active{color:#000000b3}.ul-rich-text--body-m{font-family:Ultra Nunito Sans;line-height:24px;font-size:16px;letter-spacing:0px;font-weight:400}.ul-rich-text--compact p,.ul-rich-text--compact ul,.ul-rich-text--compact ol,.ul-rich-text--compact blockquote,.ul-rich-text--compact pre{margin-bottom:8px}.ul-rich-text--compact h1,.ul-rich-text--compact h2,.ul-rich-text--compact h3,.ul-rich-text--compact h4,.ul-rich-text--compact h5,.ul-rich-text--compact h6{margin-top:16px;margin-bottom:8px}.ul-search-select{white-space:nowrap;box-sizing:border-box;display:flex;flex-direction:column;gap:4px;width:100%}.ul-search-select__control{position:relative;display:flex;flex-direction:column;width:100%}.ul-search-select__control .ul-list-item:focus-visible,.ul-search-select__control .ul-list-item:focus{outline:none}.ul-search-select__list{position:absolute;top:100%;left:0;right:0;z-index:1;display:flex;flex-direction:column;gap:4px;background-color:#232323;border-radius:16px;padding:4px;margin-top:4px;max-height:316px;overflow-y:auto;border:2px solid rgba(255,255,255,.1)}.ul-search-select__list--empty{padding:12px}.ul-search-select__option{cursor:pointer;border-radius:8px}.ul-search-select__option--highlighted .ul-list-item{background-color:#fff3}.ul-search-select__empty{font-family:Ultra Nunito Sans;line-height:24px;font-size:16px;letter-spacing:0px;font-weight:400;color:#ffffffb3}.ul-search-select--disabled .ul-search-select__control{opacity:.6;cursor:not-allowed}.ul-search-select--error .ul-input__group{border-color:#f69d9d}@media(max-width:1023px){.ul-search-select__list{max-height:316px}}@media(min-width:1024px){.ul-search-select__control{max-width:100%}}\n"] }]
|
|
4135
|
+
], template: "<div\n class=\"ul-search-select ul-search-select--{{ size() }}\"\n [class.ul-search-select--open]=\"combobox.isOpen()\"\n [class.ul-search-select--error]=\"hasError()\"\n [class.ul-search-select--disabled]=\"disabled()\"\n [class.ul-search-select--required]=\"required()\"\n [attr.aria-invalid]=\"hasError()\"\n [attr.aria-required]=\"required()\"\n [attr.aria-describedby]=\"describedBy()\"\n>\n <ul-form-field-label\n [label]=\"label()\"\n [required]=\"required()\"\n [for]=\"ids.controlId\"\n [size]=\"size()\"\n [showRequiredIndicator]=\"showRequiredIndicator()\"\n />\n\n <div\n class=\"ul-search-select__control\"\n [class.ul-search-select__control--focused]=\"combobox.isFocused()\"\n role=\"combobox\"\n [attr.aria-expanded]=\"combobox.isOpen()\"\n [attr.aria-controls]=\"listId\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n (keydown)=\"onKeydown($event)\"\n >\n <ul-input\n [controlId]=\"ids.controlId\"\n [value]=\"displayText()\"\n (valueChange)=\"onInputValueChange($event)\"\n (inputFocus)=\"onInputFocus()\"\n (inputBlur)=\"onInputBlur()\"\n [size]=\"size()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [label]=\"null\"\n [helperText]=\"null\"\n [autocomplete]=\"'off'\"\n >\n <ng-container ul-input-right-elements>\n <ul-icon size=\"5\" icon=\"search\" />\n </ng-container>\n </ul-input>\n\n @if (shouldShowPanel()) {\n <div\n class=\"ul-search-select__list ul-scrollable\"\n [class.ul-search-select__list--empty]=\"hasNoResults()\"\n [id]=\"listId\"\n role=\"listbox\"\n >\n @if (hasNoResults()) {\n <div class=\"ul-search-select__empty\" role=\"status\">No results</div>\n } @else {\n @for (opt of filteredOptions(); track opt.value; let i = $index) {\n <div\n class=\"ul-search-select__option\"\n [class.ul-search-select__option--highlighted]=\"combobox.highlightedIndex() === i\"\n [id]=\"optionId(i)\"\n role=\"option\"\n [attr.aria-selected]=\"value() === opt.value\"\n (mousedown)=\"selectOption(opt)\"\n >\n <ul-list-item\n theme=\"ghost-white\"\n [selected]=\"value() === opt.value\"\n [hideFocusOutline]=\"true\"\n >\n <ng-container ul-list-item-label>{{ opt.label }}</ng-container>\n </ul-list-item>\n </div>\n }\n }\n </div>\n }\n </div>\n\n <ul-form-field-helper\n [id]=\"ids.helperId\"\n [helperText]=\"helperText()\"\n [errorText]=\"errorText() || (hasError() && errors().length ? errors()[0].message : '') || null\"\n [error]=\"hasError()\"\n />\n</div>\n", styles: [".ul-rich-text{font-family:Ultra Nunito Sans;line-height:28px;font-size:18px;letter-spacing:0px;font-weight:400;color:#fff}.ul-rich-text p,.ul-rich-text ul,.ul-rich-text ol,.ul-rich-text blockquote,.ul-rich-text pre{margin-top:0;margin-bottom:16px}.ul-rich-text:last-child,.ul-rich-text p:last-child,.ul-rich-text ul:last-child,.ul-rich-text ol:last-child,.ul-rich-text blockquote:last-child,.ul-rich-text pre:last-child{margin-bottom:0}.ul-rich-text h1,.ul-rich-text h2,.ul-rich-text h3,.ul-rich-text h4,.ul-rich-text h5,.ul-rich-text h6{margin-top:32px;margin-bottom:12px;font-weight:1000}.ul-rich-text h1{font-family:Ultra Nunito Sans;line-height:48px;font-size:48px;letter-spacing:-.48px;font-weight:1000}.ul-rich-text h2{font-family:Ultra Nunito Sans;line-height:48px;font-size:40px;letter-spacing:-.4px;font-weight:1000}.ul-rich-text h3{font-family:Ultra Nunito Sans;line-height:44px;font-size:36px;letter-spacing:-.36px;font-weight:1000}.ul-rich-text h4{font-family:Ultra Nunito Sans;line-height:40px;font-size:32px;letter-spacing:-.32px;font-weight:1000}.ul-rich-text h5{font-family:Ultra Nunito Sans;line-height:36px;font-size:28px;letter-spacing:-.28px;font-weight:1000}.ul-rich-text h6{font-family:Ultra Nunito Sans;line-height:36px;font-size:24px;letter-spacing:-.24px;font-weight:1000}.ul-rich-text ul,.ul-rich-text ol{padding-left:24px}.ul-rich-text ul ul,.ul-rich-text ul ol,.ul-rich-text ol ul,.ul-rich-text ol ol{margin-top:8px;margin-bottom:8px}.ul-rich-text li{margin-top:4px;margin-bottom:4px}.ul-rich-text strong{font-weight:800}.ul-rich-text code{font-family:Roboto Mono;line-height:20px;font-size:14px;letter-spacing:0px;font-weight:400}.ul-rich-text em{font-style:italic}.ul-rich-text a{color:#c2a8ff;text-decoration:underline;text-decoration-thickness:1px}.ul-rich-text a:hover{color:#d6c5ff}.ul-rich-text a:active{color:#a781ff}.ul-rich-text pre{padding:16px;border-radius:8px;background-color:#3b3b3b;overflow-x:auto}.ul-rich-text pre code{font-family:Roboto Mono;line-height:20px;font-size:14px;letter-spacing:0px;font-weight:400}.ul-rich-text blockquote{margin-left:0;padding-left:16px;border-left-width:2px;border-left-style:solid;border-left-color:#ffffff1a;color:#ffffffb3}.ul-rich-text--muted{color:#ffffffb3}.ul-rich-text--inverse,.ul-rich-text--inverse a{color:#000}.ul-rich-text--inverse a:hover,.ul-rich-text--inverse a:active{color:#000000b3}.ul-rich-text--body-m{font-family:Ultra Nunito Sans;line-height:24px;font-size:16px;letter-spacing:0px;font-weight:400}.ul-rich-text--compact p,.ul-rich-text--compact ul,.ul-rich-text--compact ol,.ul-rich-text--compact blockquote,.ul-rich-text--compact pre{margin-bottom:8px}.ul-rich-text--compact h1,.ul-rich-text--compact h2,.ul-rich-text--compact h3,.ul-rich-text--compact h4,.ul-rich-text--compact h5,.ul-rich-text--compact h6{margin-top:16px;margin-bottom:8px}.ul-search-select{white-space:nowrap;box-sizing:border-box;display:flex;flex-direction:column;gap:4px;width:100%}.ul-search-select__control{position:relative;display:flex;flex-direction:column;width:100%}.ul-search-select__control .ul-list-item:focus-visible,.ul-search-select__control .ul-list-item:focus{outline:none}.ul-search-select__list{position:absolute;top:100%;left:0;right:0;z-index:1;display:flex;flex-direction:column;gap:4px;background-color:#232323;border-radius:16px;padding:4px;margin-top:4px;max-height:316px;overflow-y:auto;border:2px solid rgba(255,255,255,.1)}.ul-search-select__list--empty{padding:12px}.ul-search-select__option{cursor:pointer;border-radius:8px}.ul-search-select__option--highlighted .ul-list-item{background-color:#fff3}.ul-search-select__empty{font-family:Ultra Nunito Sans;line-height:24px;font-size:16px;letter-spacing:0px;font-weight:400;color:#ffffffb3}.ul-search-select--disabled .ul-search-select__control{opacity:.6;cursor:not-allowed}.ul-search-select--error .ul-input__group{border-color:#f69d9d}@media(max-width:1023px){.ul-search-select__list{max-height:316px}}@media(min-width:1024px){.ul-search-select__control{max-width:100%}}\n"] }]
|
|
3905
4136
|
}], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], helperText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helperText", required: false }] }], errorText: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorText", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], showRequiredIndicator: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRequiredIndicator", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], minCharsToOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "minCharsToOpen", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
|
|
3906
4137
|
|
|
3907
4138
|
/**
|
|
@@ -4445,5 +4676,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImpor
|
|
|
4445
4676
|
* Generated bundle index. Do not edit.
|
|
4446
4677
|
*/
|
|
4447
4678
|
|
|
4448
|
-
export { AccordionComponent, AccordionItemComponent, AreaCodeComponent, AvatarComponent, AvatarGroupComponent, BreadcrumbComponent, ButtonComponent, CalendarComponent, CardComponent, CarouselComponent, CarouselItemComponent, CheckboxComponent, CollapseComponent, CustomCurrencyPipe, DockComponent, DockItemComponent, DockItemContentSlotDirective, DropdownComponent, FileInputComponent, FooterComponent, FormFieldHelperComponent, FormFieldLabelComponent, HeroComponent, IconComponent, ImageNotFoundDirective, InputComponent, ListItemComponent, LongPressDirective, MenuComponent, MenuItemsComponent, MenuTriggerComponent, ModalComponent, NavbarAppNameSlotDirective, NavbarAvatarSlotDirective, NavbarComponent, NavbarLogoSlotDirective, NavbarSearchSlotDirective, PeHeroActionsSlotDirective, PeHeroBadgesSlotDirective, PeHeroContentSlotDirective, PeHeroSubtitleSlotDirective, PeHeroTitleSlotDirective, PillComponent, PriceButtonComponent, RadialComponent, RadioComponent, RadioGroupComponent, RichTextComponent, SearchSelectComponent, SelectComponent, SelectableRowComponent, SidebarComponent, SkeletonComponent, StatusComponent, TableComponent, TextareaComponent, TextareaFieldDirective, ToastContainerComponent, ToastService, TooltipComponent, createFormFieldIds, getFormFieldDescribedBy, toastIcon };
|
|
4679
|
+
export { AccordionComponent, AccordionItemComponent, AreaCodeComponent, AvatarComponent, AvatarGroupComponent, BreadcrumbComponent, ButtonComponent, CalendarComponent, CardComponent, CarouselComponent, CarouselItemComponent, CheckboxComponent, CollapseComponent, CustomCurrencyPipe, DockComponent, DockItemComponent, DockItemContentSlotDirective, DropdownComponent, FileInputComponent, FooterComponent, FormFieldHelperComponent, FormFieldLabelComponent, HeroComponent, IconComponent, ImageNotFoundDirective, InputComponent, ListItemComponent, LongPressDirective, MenuComponent, MenuItemsComponent, MenuTriggerComponent, ModalComponent, NavbarAppNameSlotDirective, NavbarAvatarSlotDirective, NavbarComponent, NavbarLogoSlotDirective, NavbarSearchSlotDirective, PeHeroActionsSlotDirective, PeHeroBadgesSlotDirective, PeHeroContentSlotDirective, PeHeroSubtitleSlotDirective, PeHeroTitleSlotDirective, PillComponent, PriceButtonComponent, RadialComponent, RadioComponent, RadioGroupComponent, RichTextComponent, SearchInputComponent, SearchSelectComponent, SelectComponent, SelectableRowComponent, SidebarComponent, SkeletonComponent, StatusComponent, TableComponent, TextareaComponent, TextareaFieldDirective, ToastContainerComponent, ToastService, TooltipComponent, createFormFieldIds, getFormFieldDescribedBy, toastIcon };
|
|
4449
4680
|
//# sourceMappingURL=underlayerdev-ui.mjs.map
|