@c-code/c-code-fw 1.3.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +118 -104
- package/fesm2022/c-code-c-code-fw-ui.mjs +586 -141
- package/fesm2022/c-code-c-code-fw-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/ui/lib/components/button/button.component.d.ts +24 -0
- package/ui/lib/components/category-menu/category-menu.component.d.ts +12 -3
- package/ui/lib/components/faq/faq.component.d.ts +11 -4
- package/ui/lib/components/faq-item/faq-item.component.d.ts +21 -0
- package/ui/lib/components/gallery/gallery.component.d.ts +7 -3
- package/ui/lib/components/info-item/info-item.component.d.ts +10 -2
- package/ui/lib/components/lightbox/lightbox.component.d.ts +18 -3
- package/ui/lib/components/notice/notice.component.d.ts +17 -0
- package/ui/lib/components/page-banner/page-banner.component.d.ts +9 -3
- package/ui/lib/components/plan-card/plan-card.component.d.ts +29 -6
- package/ui/lib/components/plan-catalog/plan-catalog.component.d.ts +43 -19
- package/ui/lib/components/plan-details/plan-details.component.d.ts +26 -11
- package/ui/lib/components/plan-filter-form/plan-filter-form.component.d.ts +15 -5
- package/ui/lib/components/promo-modal/promo-modal.component.d.ts +39 -7
- package/ui/lib/components/search-box/search-box.component.d.ts +6 -1
- package/ui/lib/components/section-heading/section-heading.component.d.ts +34 -0
- package/ui/lib/components/social-links/social-links.component.d.ts +10 -6
- package/ui/lib/components/whatsapp-button/whatsapp-button.component.d.ts +12 -2
- package/ui/lib/utils/text.utils.d.ts +10 -0
- package/ui/public-api.d.ts +4 -0
- package/ui/theme/component-base.css +136 -0
- package/ui/theme/tokens.css +111 -45
package/package.json
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
export type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'whatsapp' | 'inverse';
|
|
3
|
+
export type ButtonSize = 'sm' | 'md' | 'lg';
|
|
4
|
+
/**
|
|
5
|
+
* Shared button look for links and buttons. Every component in the library uses it,
|
|
6
|
+
* so all calls to action share size, focus and colors.
|
|
7
|
+
*
|
|
8
|
+
* ```html
|
|
9
|
+
* <a ccButton [href]="whatsapp" target="_blank">Reservar</a>
|
|
10
|
+
* <button ccButton variant="secondary" size="sm" type="button">Limpiar</button>
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* Tokens: --cc-btn-bg, --cc-btn-color, --cc-btn-hover-bg, --cc-btn-hover-color,
|
|
14
|
+
* --cc-btn-border, --cc-btn-radius, --cc-btn-padding-x, --cc-btn-font-weight,
|
|
15
|
+
* --cc-btn-letter-spacing, --cc-btn-text-transform.
|
|
16
|
+
*/
|
|
17
|
+
export declare class ButtonComponent {
|
|
18
|
+
readonly variant: import("@angular/core").InputSignal<ButtonVariant>;
|
|
19
|
+
readonly size: import("@angular/core").InputSignal<ButtonSize>;
|
|
20
|
+
/** Full width. */
|
|
21
|
+
readonly block: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
22
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ButtonComponent, never>;
|
|
23
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<ButtonComponent, "a[ccButton], button[ccButton]", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "block": { "alias": "block"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
24
|
+
}
|
|
@@ -1,19 +1,28 @@
|
|
|
1
1
|
import { CategoryOption } from '../../models/plan.models';
|
|
2
2
|
import * as i0 from "@angular/core";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Category selector with a single selected option. Each option is a toggle button
|
|
5
|
+
* (`aria-pressed`), so it works with Tab and Enter/Space.
|
|
6
|
+
*
|
|
7
|
+
* `layout`:
|
|
8
|
+
* - `list`: vertical list, for sidebars.
|
|
9
|
+
* - `chips`: one scrollable row of pills, for small screens.
|
|
10
|
+
* - `auto` (default): chips below 1024px, list from 1024px.
|
|
6
11
|
*
|
|
7
12
|
* ```html
|
|
8
13
|
* <cc-category-menu [options]="categories" [(selected)]="category" />
|
|
9
14
|
* ```
|
|
15
|
+
*
|
|
16
|
+
* Tokens: --cc-category-color, --cc-category-hover-bg, --cc-category-active-bg,
|
|
17
|
+
* --cc-category-active-color, --cc-category-chip-border.
|
|
10
18
|
*/
|
|
11
19
|
export declare class CategoryMenuComponent<T = unknown> {
|
|
12
20
|
readonly options: import("@angular/core").InputSignal<CategoryOption<T>[]>;
|
|
13
21
|
/** Selected value. Use `[(selected)]` to bind both ways. */
|
|
14
22
|
readonly selected: import("@angular/core").ModelSignal<T | null>;
|
|
15
23
|
readonly title: import("@angular/core").InputSignal<string>;
|
|
24
|
+
readonly layout: import("@angular/core").InputSignal<"auto" | "list" | "chips">;
|
|
16
25
|
select(value: T): void;
|
|
17
26
|
static ɵfac: i0.ɵɵFactoryDeclaration<CategoryMenuComponent<any>, never>;
|
|
18
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<CategoryMenuComponent<any>, "cc-category-menu", never, { "options": { "alias": "options"; "required": true; "isSignal": true; }; "selected": { "alias": "selected"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; }, { "selected": "selectedChange"; }, never, never, true, never>;
|
|
27
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<CategoryMenuComponent<any>, "cc-category-menu", never, { "options": { "alias": "options"; "required": true; "isSignal": true; }; "selected": { "alias": "selected"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "layout": { "alias": "layout"; "required": false; "isSignal": true; }; }, { "selected": "selectedChange"; }, never, never, true, never>;
|
|
19
28
|
}
|
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
import { FaqItem } from '../../models/ui.models';
|
|
2
2
|
import * as i0 from "@angular/core";
|
|
3
3
|
/**
|
|
4
|
-
* Frequently asked questions as native `<details>` elements, so the answers
|
|
5
|
-
*
|
|
4
|
+
* Frequently asked questions as native `<details>` elements, so the answers stay in
|
|
5
|
+
* the prerendered HTML for search engines. Pass plain `items`, or project
|
|
6
|
+
* `<cc-faq-item>` elements when an answer needs links.
|
|
6
7
|
*
|
|
7
8
|
* ```html
|
|
8
|
-
* <cc-faq title="
|
|
9
|
+
* <cc-faq title="Preguntas frecuentes" [items]="faq" />
|
|
10
|
+
* <cc-faq title="Preguntas frecuentes">
|
|
11
|
+
* <cc-faq-item question="¿Qué planes tienen?">Míralos en <a routerLink="/planes">planes</a>.</cc-faq-item>
|
|
12
|
+
* </cc-faq>
|
|
9
13
|
* ```
|
|
14
|
+
*
|
|
15
|
+
* Tokens: --cc-faq-title-color, --cc-faq-gap, plus the ones of `cc-faq-item`.
|
|
10
16
|
*/
|
|
11
17
|
export declare class FaqComponent {
|
|
12
18
|
readonly items: import("@angular/core").InputSignal<FaqItem[]>;
|
|
13
19
|
readonly title: import("@angular/core").InputSignal<string>;
|
|
20
|
+
readonly headingLevel: import("@angular/core").InputSignal<"h2" | "h3">;
|
|
14
21
|
static ɵfac: i0.ɵɵFactoryDeclaration<FaqComponent, never>;
|
|
15
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<FaqComponent, "cc-faq", never, { "items": { "alias": "items"; "required":
|
|
22
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<FaqComponent, "cc-faq", never, { "items": { "alias": "items"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "headingLevel": { "alias": "headingLevel"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
16
23
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
/**
|
|
3
|
+
* One question of `cc-faq`. The answer is projected, so it can contain links.
|
|
4
|
+
*
|
|
5
|
+
* ```html
|
|
6
|
+
* <cc-faq title="Preguntas frecuentes">
|
|
7
|
+
* <cc-faq-item question="¿Qué planes tienen?">
|
|
8
|
+
* Míralos todos en <a routerLink="/planes">planes</a>.
|
|
9
|
+
* </cc-faq-item>
|
|
10
|
+
* </cc-faq>
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* Tokens: --cc-faq-bg, --cc-faq-question-color, --cc-faq-answer-color.
|
|
14
|
+
*/
|
|
15
|
+
export declare class FaqItemComponent {
|
|
16
|
+
readonly question: import("@angular/core").InputSignal<string>;
|
|
17
|
+
/** Starts expanded. */
|
|
18
|
+
readonly open: import("@angular/core").InputSignal<boolean>;
|
|
19
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<FaqItemComponent, never>;
|
|
20
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<FaqItemComponent, "cc-faq-item", never, { "question": { "alias": "question"; "required": true; "isSignal": true; }; "open": { "alias": "open"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
21
|
+
}
|
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
import { GalleryImage } from '../../models/ui.models';
|
|
2
2
|
import * as i0 from "@angular/core";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Grid of square thumbnails that opens a lightbox on click.
|
|
5
5
|
*
|
|
6
6
|
* ```html
|
|
7
|
-
* <cc-gallery [images]="images" />
|
|
7
|
+
* <cc-gallery [images]="images" [columns]="4" />
|
|
8
8
|
* ```
|
|
9
9
|
*
|
|
10
10
|
* `numberedImages()` builds the list for folders named 1.jpeg, 2.jpeg, …
|
|
11
|
+
*
|
|
12
|
+
* Tokens: --cc-gallery-gap, --cc-gallery-radius, --cc-gallery-bg.
|
|
11
13
|
*/
|
|
12
14
|
export declare class GalleryComponent {
|
|
13
15
|
readonly images: import("@angular/core").InputSignal<GalleryImage[]>;
|
|
16
|
+
/** Columns from 1024px. Small screens use 2, tablets 3. */
|
|
17
|
+
readonly columns: import("@angular/core").InputSignal<number>;
|
|
14
18
|
readonly backgroundImage: import("@angular/core").InputSignal<string>;
|
|
15
19
|
readonly openLabel: import("@angular/core").InputSignal<string>;
|
|
16
20
|
protected readonly open: import("@angular/core").WritableSignal<number | null>;
|
|
17
21
|
static ɵfac: i0.ɵɵFactoryDeclaration<GalleryComponent, never>;
|
|
18
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<GalleryComponent, "cc-gallery", never, { "images": { "alias": "images"; "required": true; "isSignal": true; }; "backgroundImage": { "alias": "backgroundImage"; "required": false; "isSignal": true; }; "openLabel": { "alias": "openLabel"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
22
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<GalleryComponent, "cc-gallery", never, { "images": { "alias": "images"; "required": true; "isSignal": true; }; "columns": { "alias": "columns"; "required": false; "isSignal": true; }; "backgroundImage": { "alias": "backgroundImage"; "required": false; "isSignal": true; }; "openLabel": { "alias": "openLabel"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
19
23
|
}
|
|
20
24
|
/**
|
|
21
25
|
* Builds a gallery list for numbered files.
|
|
@@ -5,14 +5,22 @@ import * as i0 from "@angular/core";
|
|
|
5
5
|
*
|
|
6
6
|
* ```html
|
|
7
7
|
* <cc-info-item title="Pagos" text="Aceptamos Nequi, Daviplata y efectivo." />
|
|
8
|
-
* <cc-info-item title="
|
|
8
|
+
* <cc-info-item title="Bonos Spa" [text]="texto" headingId="bonos">
|
|
9
9
|
* <ul><li>…</li></ul>
|
|
10
10
|
* </cc-info-item>
|
|
11
11
|
* ```
|
|
12
|
+
*
|
|
13
|
+
* Tokens: --cc-info-title-color, --cc-info-text-color, --cc-info-text-align, --cc-info-max-width.
|
|
12
14
|
*/
|
|
13
15
|
export declare class InfoItemComponent {
|
|
14
16
|
readonly title: import("@angular/core").InputSignal<string>;
|
|
15
17
|
readonly text: import("@angular/core").InputSignal<string>;
|
|
18
|
+
/** `accent` colors the title with the accent text color, `neutral` with the heading color. */
|
|
19
|
+
readonly tone: import("@angular/core").InputSignal<"accent" | "neutral">;
|
|
20
|
+
readonly size: import("@angular/core").InputSignal<"sm" | "md">;
|
|
21
|
+
readonly headingLevel: import("@angular/core").InputSignal<"h2" | "h3">;
|
|
22
|
+
/** Id of the heading, for anchors from a table of contents. */
|
|
23
|
+
readonly headingId: import("@angular/core").InputSignal<string | null>;
|
|
16
24
|
static ɵfac: i0.ɵɵFactoryDeclaration<InfoItemComponent, never>;
|
|
17
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<InfoItemComponent, "cc-info-item", never, { "title": { "alias": "title"; "required": true; "isSignal": true; }; "text": { "alias": "text"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
25
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<InfoItemComponent, "cc-info-item", never, { "title": { "alias": "title"; "required": true; "isSignal": true; }; "text": { "alias": "text"; "required": false; "isSignal": true; }; "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "headingLevel": { "alias": "headingLevel"; "required": false; "isSignal": true; }; "headingId": { "alias": "headingId"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
18
26
|
}
|
|
@@ -2,11 +2,15 @@ import { GalleryImage } from '../../models/ui.models';
|
|
|
2
2
|
import * as i0 from "@angular/core";
|
|
3
3
|
/**
|
|
4
4
|
* Full-screen image viewer. It is open while `index` is not null.
|
|
5
|
-
* Arrow keys move between images and
|
|
5
|
+
* Arrow keys and swipe move between images; Escape and the backdrop close it.
|
|
6
|
+
* Focus moves into the viewer on open, stays inside while open, and returns to the
|
|
7
|
+
* element that opened it on close.
|
|
6
8
|
*
|
|
7
9
|
* ```html
|
|
8
10
|
* <cc-lightbox [images]="images" [(index)]="openIndex" />
|
|
9
11
|
* ```
|
|
12
|
+
*
|
|
13
|
+
* Tokens: --cc-lightbox-backdrop, --cc-lightbox-control-bg, --cc-lightbox-color.
|
|
10
14
|
*/
|
|
11
15
|
export declare class LightboxComponent {
|
|
12
16
|
readonly images: import("@angular/core").InputSignal<GalleryImage[]>;
|
|
@@ -15,12 +19,23 @@ export declare class LightboxComponent {
|
|
|
15
19
|
readonly closeLabel: import("@angular/core").InputSignal<string>;
|
|
16
20
|
readonly prevLabel: import("@angular/core").InputSignal<string>;
|
|
17
21
|
readonly nextLabel: import("@angular/core").InputSignal<string>;
|
|
22
|
+
/** Text of the position counter, for example "3 de 18". */
|
|
23
|
+
readonly counterSeparator: import("@angular/core").InputSignal<string>;
|
|
18
24
|
protected readonly current: import("@angular/core").Signal<GalleryImage | null>;
|
|
19
|
-
|
|
25
|
+
/** Changes only on open/close, not when moving between images. */
|
|
26
|
+
private readonly isOpen;
|
|
27
|
+
private readonly document;
|
|
28
|
+
private readonly dialog;
|
|
29
|
+
private readonly closeButton;
|
|
30
|
+
private touchStartX;
|
|
20
31
|
constructor();
|
|
21
32
|
close(): void;
|
|
22
33
|
next(): void;
|
|
23
34
|
prev(): void;
|
|
35
|
+
/** Keeps Tab and Shift+Tab inside the viewer. */
|
|
36
|
+
protected trapFocus(event: KeyboardEvent): void;
|
|
37
|
+
protected onTouchStart(event: TouchEvent): void;
|
|
38
|
+
protected onTouchEnd(event: TouchEvent): void;
|
|
24
39
|
static ɵfac: i0.ɵɵFactoryDeclaration<LightboxComponent, never>;
|
|
25
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<LightboxComponent, "cc-lightbox", never, { "images": { "alias": "images"; "required": true; "isSignal": true; }; "index": { "alias": "index"; "required": false; "isSignal": true; }; "closeLabel": { "alias": "closeLabel"; "required": false; "isSignal": true; }; "prevLabel": { "alias": "prevLabel"; "required": false; "isSignal": true; }; "nextLabel": { "alias": "nextLabel"; "required": false; "isSignal": true; }; }, { "index": "indexChange"; }, never, never, true, never>;
|
|
40
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<LightboxComponent, "cc-lightbox", never, { "images": { "alias": "images"; "required": true; "isSignal": true; }; "index": { "alias": "index"; "required": false; "isSignal": true; }; "closeLabel": { "alias": "closeLabel"; "required": false; "isSignal": true; }; "prevLabel": { "alias": "prevLabel"; "required": false; "isSignal": true; }; "nextLabel": { "alias": "nextLabel"; "required": false; "isSignal": true; }; "counterSeparator": { "alias": "counterSeparator"; "required": false; "isSignal": true; }; }, { "index": "indexChange"; }, never, never, true, never>;
|
|
26
41
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
/**
|
|
3
|
+
* Highlighted note for important conditions, warnings or tips. The content is projected.
|
|
4
|
+
*
|
|
5
|
+
* ```html
|
|
6
|
+
* <cc-notice tone="warning" title="Importante">Su bono tiene vigencia de 30 días.</cc-notice>
|
|
7
|
+
* ```
|
|
8
|
+
*
|
|
9
|
+
* Tokens: --cc-notice-bg, --cc-notice-border, --cc-notice-color.
|
|
10
|
+
*/
|
|
11
|
+
export declare class NoticeComponent {
|
|
12
|
+
/** `info` uses the brand colors, `warning` a red accent, `success` the primary color. */
|
|
13
|
+
readonly tone: import("@angular/core").InputSignal<"info" | "warning" | "success">;
|
|
14
|
+
readonly title: import("@angular/core").InputSignal<string>;
|
|
15
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<NoticeComponent, never>;
|
|
16
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<NoticeComponent, "cc-notice", never, { "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
17
|
+
}
|
|
@@ -6,18 +6,24 @@ import * as i0 from "@angular/core";
|
|
|
6
6
|
*
|
|
7
7
|
* ```html
|
|
8
8
|
* <cc-page-banner title="Reserva tu plan - Pareja" />
|
|
9
|
-
* <cc-page-banner [title]="plan.name" backLink="/planes" iconSrc="assets/icons/hoja.png"
|
|
9
|
+
* <cc-page-banner [title]="plan.name" backLink="/planes" iconSrc="assets/icons/hoja.png" size="lg" italic />
|
|
10
10
|
* ```
|
|
11
|
+
*
|
|
12
|
+
* Tokens: --cc-banner-bg, --cc-banner-color, --cc-banner-padding.
|
|
11
13
|
*/
|
|
12
14
|
export declare class PageBannerComponent {
|
|
13
15
|
readonly title: import("@angular/core").InputSignal<string>;
|
|
14
|
-
|
|
16
|
+
readonly subtitle: import("@angular/core").InputSignal<string>;
|
|
17
|
+
/** `band` draws a surface-colored strip; `plain` has no background. */
|
|
15
18
|
readonly variant: import("@angular/core").InputSignal<"band" | "plain">;
|
|
19
|
+
readonly size: import("@angular/core").InputSignal<"sm" | "md" | "lg">;
|
|
20
|
+
readonly italic: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
21
|
+
readonly align: import("@angular/core").InputSignal<"start" | "center">;
|
|
16
22
|
readonly iconSrc: import("@angular/core").InputSignal<string>;
|
|
17
23
|
/** Shows a back arrow that links here. */
|
|
18
24
|
readonly backLink: import("@angular/core").InputSignal<LinkTarget | null>;
|
|
19
25
|
readonly backIconSrc: import("@angular/core").InputSignal<string>;
|
|
20
26
|
readonly backLabel: import("@angular/core").InputSignal<string>;
|
|
21
27
|
static ɵfac: i0.ɵɵFactoryDeclaration<PageBannerComponent, never>;
|
|
22
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<PageBannerComponent, "cc-page-banner", never, { "title": { "alias": "title"; "required": true; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "iconSrc": { "alias": "iconSrc"; "required": false; "isSignal": true; }; "backLink": { "alias": "backLink"; "required": false; "isSignal": true; }; "backIconSrc": { "alias": "backIconSrc"; "required": false; "isSignal": true; }; "backLabel": { "alias": "backLabel"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
28
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<PageBannerComponent, "cc-page-banner", never, { "title": { "alias": "title"; "required": true; "isSignal": true; }; "subtitle": { "alias": "subtitle"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "italic": { "alias": "italic"; "required": false; "isSignal": true; }; "align": { "alias": "align"; "required": false; "isSignal": true; }; "iconSrc": { "alias": "iconSrc"; "required": false; "isSignal": true; }; "backLink": { "alias": "backLink"; "required": false; "isSignal": true; }; "backIconSrc": { "alias": "backIconSrc"; "required": false; "isSignal": true; }; "backLabel": { "alias": "backLabel"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
23
29
|
}
|
|
@@ -1,23 +1,46 @@
|
|
|
1
1
|
import { LinkTarget } from '../../models/ui.models';
|
|
2
|
+
import { PriceFormat } from '../../utils/text.utils';
|
|
3
|
+
import { ButtonVariant } from '../button/button.component';
|
|
2
4
|
import * as i0 from "@angular/core";
|
|
3
5
|
/**
|
|
4
|
-
* Plan card:
|
|
5
|
-
* With `link
|
|
6
|
+
* Plan card: photo, name, details, price and a call to action.
|
|
7
|
+
* With `link`, the whole card is clickable and navigates with the router; without it,
|
|
8
|
+
* the button emits `ctaClick`. With `skeleton`, it renders a loading placeholder.
|
|
6
9
|
*
|
|
7
10
|
* ```html
|
|
8
|
-
* <cc-plan-card [name]="plan.name" [imageSrc]="plan.imgPath" [
|
|
11
|
+
* <cc-plan-card [name]="plan.name" [imageSrc]="plan.imgPath" [price]="plan.price"
|
|
12
|
+
* meta="2 h · 2 personas" [link]="['/planes', slug]" />
|
|
9
13
|
* ```
|
|
14
|
+
*
|
|
15
|
+
* Tokens: --cc-plan-card-bg, --cc-plan-card-color, --cc-plan-card-border,
|
|
16
|
+
* --cc-plan-card-radius, --cc-plan-card-shadow, --cc-plan-card-image-ratio,
|
|
17
|
+
* --cc-plan-card-price-color.
|
|
10
18
|
*/
|
|
11
19
|
export declare class PlanCardComponent {
|
|
12
20
|
readonly name: import("@angular/core").InputSignal<string>;
|
|
13
21
|
readonly imageSrc: import("@angular/core").InputSignal<string>;
|
|
14
22
|
/** Defaults to `name`. */
|
|
15
23
|
readonly imageAlt: import("@angular/core").InputSignal<string>;
|
|
16
|
-
/**
|
|
17
|
-
readonly
|
|
24
|
+
/** Short line under the name, for example "2 h 20 min · 2 personas". */
|
|
25
|
+
readonly meta: import("@angular/core").InputSignal<string>;
|
|
26
|
+
/** Price to show. Leave it null to hide it. */
|
|
27
|
+
readonly price: import("@angular/core").InputSignal<number | null>;
|
|
28
|
+
/** Text before the price, for example "Desde". */
|
|
29
|
+
readonly priceLabel: import("@angular/core").InputSignal<string>;
|
|
30
|
+
readonly priceFormat: import("@angular/core").InputSignal<PriceFormat>;
|
|
18
31
|
readonly link: import("@angular/core").InputSignal<LinkTarget | null>;
|
|
32
|
+
/** Query params of `link`, for example `{ categoria: 'pareja' }`. */
|
|
33
|
+
readonly queryParams: import("@angular/core").InputSignal<Record<string, string> | null>;
|
|
19
34
|
readonly ctaLabel: import("@angular/core").InputSignal<string>;
|
|
35
|
+
readonly ctaVariant: import("@angular/core").InputSignal<ButtonVariant>;
|
|
36
|
+
/** `filled` uses the surface color, `outlined` a border on white, `plain` no box. */
|
|
37
|
+
readonly appearance: import("@angular/core").InputSignal<"plain" | "filled" | "outlined">;
|
|
38
|
+
/** Heading level of the name inside the page outline. */
|
|
39
|
+
readonly headingLevel: import("@angular/core").InputSignal<"h2" | "h3">;
|
|
40
|
+
/** Renders a loading placeholder instead of the content. */
|
|
41
|
+
readonly skeleton: import("@angular/core").InputSignal<boolean>;
|
|
20
42
|
readonly ctaClick: import("@angular/core").OutputEmitterRef<void>;
|
|
43
|
+
protected readonly formattedPrice: import("@angular/core").Signal<string>;
|
|
21
44
|
static ɵfac: i0.ɵɵFactoryDeclaration<PlanCardComponent, never>;
|
|
22
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<PlanCardComponent, "cc-plan-card", never, { "name": { "alias": "name"; "required":
|
|
45
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<PlanCardComponent, "cc-plan-card", never, { "name": { "alias": "name"; "required": false; "isSignal": true; }; "imageSrc": { "alias": "imageSrc"; "required": false; "isSignal": true; }; "imageAlt": { "alias": "imageAlt"; "required": false; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "price": { "alias": "price"; "required": false; "isSignal": true; }; "priceLabel": { "alias": "priceLabel"; "required": false; "isSignal": true; }; "priceFormat": { "alias": "priceFormat"; "required": false; "isSignal": true; }; "link": { "alias": "link"; "required": false; "isSignal": true; }; "queryParams": { "alias": "queryParams"; "required": false; "isSignal": true; }; "ctaLabel": { "alias": "ctaLabel"; "required": false; "isSignal": true; }; "ctaVariant": { "alias": "ctaVariant"; "required": false; "isSignal": true; }; "appearance": { "alias": "appearance"; "required": false; "isSignal": true; }; "headingLevel": { "alias": "headingLevel"; "required": false; "isSignal": true; }; "skeleton": { "alias": "skeleton"; "required": false; "isSignal": true; }; }, { "ctaClick": "ctaClick"; }, never, never, true, never>;
|
|
23
46
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { TemplateRef } from '@angular/core';
|
|
2
2
|
import { AdditionalService, CategoryOption, Plan, PlanCategory, PlanFilter, PriceRange } from '../../models/plan.models';
|
|
3
3
|
import { LinkTarget } from '../../models/ui.models';
|
|
4
|
+
import { PriceFormat } from '../../utils/text.utils';
|
|
5
|
+
import { ButtonVariant } from '../button/button.component';
|
|
4
6
|
import * as i0 from "@angular/core";
|
|
5
7
|
/** Context of a custom card template: `<ng-template ccPlanCard let-plan let-link="link">`. */
|
|
6
8
|
export interface PlanCardContext {
|
|
@@ -13,25 +15,30 @@ export declare class PlanCardTemplateDirective {
|
|
|
13
15
|
static ɵfac: i0.ɵɵFactoryDeclaration<PlanCardTemplateDirective, never>;
|
|
14
16
|
static ɵdir: i0.ɵɵDirectiveDeclaration<PlanCardTemplateDirective, "ng-template[ccPlanCard]", never, {}, {}, never, never, true, never>;
|
|
15
17
|
}
|
|
18
|
+
/** Default detail line of a card: "2 horas 20 minutos · 2 personas". */
|
|
19
|
+
export declare function defaultPlanMeta(plan: Plan): string;
|
|
16
20
|
/**
|
|
17
21
|
* Full plan list page: title, name search, category menu, filter and card grid.
|
|
18
22
|
* It only needs the plans; the rest has Spanish defaults you can override.
|
|
19
23
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
24
|
+
* - `plans` set to `null` means "loading" and shows placeholder cards.
|
|
25
|
+
* - `[(category)]` is two-way, so a page can keep it in the URL (`?categoria=pareja`).
|
|
26
|
+
* - Selecting a category shows its plans. Searching by name or filtering looks across
|
|
27
|
+
* every category; clearing the search goes back to the selected category.
|
|
22
28
|
*
|
|
23
29
|
* ```html
|
|
24
|
-
* <cc-plan-catalog
|
|
25
|
-
* [plans]="plans()"
|
|
26
|
-
* [services]="services()"
|
|
27
|
-
* [priceRanges]="ranges()"
|
|
28
|
-
* imageAltSuffix=" - Laurel Spa Medellín"
|
|
29
|
-
* />
|
|
30
|
+
* <cc-plan-catalog [plans]="plans()" [services]="services()" [priceRanges]="ranges()" [(category)]="category" />
|
|
30
31
|
* ```
|
|
32
|
+
*
|
|
33
|
+
* Tokens: --cc-catalog-panel-bg, --cc-catalog-sidebar-width, --cc-catalog-column-min,
|
|
34
|
+
* --cc-catalog-gap.
|
|
31
35
|
*/
|
|
32
36
|
export declare class PlanCatalogComponent {
|
|
33
|
-
|
|
37
|
+
/** The plans, or `null` while they load. */
|
|
38
|
+
readonly plans: import("@angular/core").InputSignal<Plan[] | null>;
|
|
34
39
|
readonly categories: import("@angular/core").InputSignal<CategoryOption<number>[]>;
|
|
40
|
+
/** Selected category. Use `[(category)]` to bind it; `null` means `initialCategory`. */
|
|
41
|
+
readonly category: import("@angular/core").ModelSignal<number | null>;
|
|
35
42
|
readonly initialCategory: import("@angular/core").InputSignal<number>;
|
|
36
43
|
/** Shows how many plans each category has, counted from `plans`. */
|
|
37
44
|
readonly showCounts: import("@angular/core").InputSignal<boolean>;
|
|
@@ -40,30 +47,43 @@ export declare class PlanCatalogComponent {
|
|
|
40
47
|
readonly priceRanges: import("@angular/core").InputSignal<PriceRange[]>;
|
|
41
48
|
/** Where each card links to. Defaults to `/planes/<slug>`. */
|
|
42
49
|
readonly detailsLink: import("@angular/core").InputSignal<(plan: Plan) => LinkTarget>;
|
|
50
|
+
readonly showPrice: import("@angular/core").InputSignal<boolean>;
|
|
51
|
+
readonly priceLabel: import("@angular/core").InputSignal<string>;
|
|
52
|
+
readonly priceFormat: import("@angular/core").InputSignal<PriceFormat>;
|
|
53
|
+
/** Detail line of each card. Defaults to duration and number of people. */
|
|
54
|
+
readonly planMeta: import("@angular/core").InputSignal<(plan: Plan) => string>;
|
|
55
|
+
readonly cardAppearance: import("@angular/core").InputSignal<"plain" | "filled" | "outlined">;
|
|
56
|
+
readonly ctaLabel: import("@angular/core").InputSignal<string>;
|
|
57
|
+
readonly ctaVariant: import("@angular/core").InputSignal<ButtonVariant>;
|
|
58
|
+
/** Added after the plan name in each image's alt text. */
|
|
59
|
+
readonly imageAltSuffix: import("@angular/core").InputSignal<string>;
|
|
60
|
+
readonly skeletonCount: import("@angular/core").InputSignal<number>;
|
|
43
61
|
readonly showBanner: import("@angular/core").InputSignal<boolean>;
|
|
44
62
|
readonly showSearch: import("@angular/core").InputSignal<boolean>;
|
|
45
63
|
readonly titlePrefix: import("@angular/core").InputSignal<string>;
|
|
46
64
|
readonly resultsTitle: import("@angular/core").InputSignal<string>;
|
|
47
65
|
readonly categoriesTitle: import("@angular/core").InputSignal<string>;
|
|
66
|
+
readonly categoriesLayout: import("@angular/core").InputSignal<"auto" | "list" | "chips">;
|
|
48
67
|
readonly searchPlaceholder: import("@angular/core").InputSignal<string>;
|
|
49
68
|
readonly searchIconSrc: import("@angular/core").InputSignal<string>;
|
|
50
69
|
readonly filterTitle: import("@angular/core").InputSignal<string>;
|
|
51
70
|
readonly filterIconSrc: import("@angular/core").InputSignal<string>;
|
|
52
|
-
readonly ctaLabel: import("@angular/core").InputSignal<string>;
|
|
53
|
-
/** Added after the plan name in each image's alt text. */
|
|
54
|
-
readonly imageAltSuffix: import("@angular/core").InputSignal<string>;
|
|
55
71
|
readonly emptyMessage: import("@angular/core").InputSignal<string>;
|
|
56
|
-
readonly
|
|
72
|
+
readonly emptyActionLabel: import("@angular/core").InputSignal<string>;
|
|
73
|
+
/** Optional contact link shown in the empty state, for example WhatsApp. */
|
|
74
|
+
readonly contactHref: import("@angular/core").InputSignal<string>;
|
|
75
|
+
readonly contactLabel: import("@angular/core").InputSignal<string>;
|
|
57
76
|
protected readonly cardTemplate: import("@angular/core").Signal<TemplateRef<any> | undefined>;
|
|
58
|
-
|
|
77
|
+
private readonly filterForm;
|
|
59
78
|
protected readonly query: import("@angular/core").WritableSignal<string>;
|
|
60
79
|
protected readonly filter: import("@angular/core").WritableSignal<PlanFilter | null>;
|
|
61
80
|
protected readonly filterOpen: import("@angular/core").WritableSignal<boolean>;
|
|
62
81
|
/** Set when the user searched or filtered; results then cover every category. */
|
|
63
82
|
protected readonly searching: import("@angular/core").WritableSignal<boolean>;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
83
|
+
protected readonly loading: import("@angular/core").Signal<boolean>;
|
|
84
|
+
protected readonly skeletons: import("@angular/core").Signal<number[]>;
|
|
85
|
+
/** Category shown in the menu: none while searching. */
|
|
86
|
+
protected readonly activeCategory: import("@angular/core").Signal<number | null>;
|
|
67
87
|
protected readonly categoryOptions: import("@angular/core").Signal<CategoryOption<number>[]>;
|
|
68
88
|
protected readonly hasFilter: import("@angular/core").Signal<boolean>;
|
|
69
89
|
protected readonly visiblePlans: import("@angular/core").Signal<Plan[]>;
|
|
@@ -71,8 +91,12 @@ export declare class PlanCatalogComponent {
|
|
|
71
91
|
protected selectCategory(value: PlanCategory | number | null): void;
|
|
72
92
|
protected onSearch(query: string): void;
|
|
73
93
|
protected onFilter(filter: PlanFilter): void;
|
|
94
|
+
/** Clears search and filter and shows the selected category again. */
|
|
95
|
+
protected showAll(): void;
|
|
74
96
|
protected linkFor(plan: Plan): LinkTarget;
|
|
75
|
-
|
|
97
|
+
protected metaFor(plan: Plan): string;
|
|
98
|
+
private clearSearch;
|
|
99
|
+
private updateSearching;
|
|
76
100
|
static ɵfac: i0.ɵɵFactoryDeclaration<PlanCatalogComponent, never>;
|
|
77
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<PlanCatalogComponent, "cc-plan-catalog", never, { "plans": { "alias": "plans"; "required": true; "isSignal": true; }; "categories": { "alias": "categories"; "required": false; "isSignal": true; }; "initialCategory": { "alias": "initialCategory"; "required": false; "isSignal": true; }; "showCounts": { "alias": "showCounts"; "required": false; "isSignal": true; }; "services": { "alias": "services"; "required": false; "isSignal": true; }; "priceRanges": { "alias": "priceRanges"; "required": false; "isSignal": true; }; "detailsLink": { "alias": "detailsLink"; "required": false; "isSignal": true; }; "showBanner": { "alias": "showBanner"; "required": false; "isSignal": true; }; "showSearch": { "alias": "showSearch"; "required": false; "isSignal": true; }; "titlePrefix": { "alias": "titlePrefix"; "required": false; "isSignal": true; }; "resultsTitle": { "alias": "resultsTitle"; "required": false; "isSignal": true; }; "categoriesTitle": { "alias": "categoriesTitle"; "required": false; "isSignal": true; }; "searchPlaceholder": { "alias": "searchPlaceholder"; "required": false; "isSignal": true; }; "searchIconSrc": { "alias": "searchIconSrc"; "required": false; "isSignal": true; }; "filterTitle": { "alias": "filterTitle"; "required": false; "isSignal": true; }; "filterIconSrc": { "alias": "filterIconSrc"; "required": false; "isSignal": true; }; "
|
|
101
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<PlanCatalogComponent, "cc-plan-catalog", never, { "plans": { "alias": "plans"; "required": true; "isSignal": true; }; "categories": { "alias": "categories"; "required": false; "isSignal": true; }; "category": { "alias": "category"; "required": false; "isSignal": true; }; "initialCategory": { "alias": "initialCategory"; "required": false; "isSignal": true; }; "showCounts": { "alias": "showCounts"; "required": false; "isSignal": true; }; "services": { "alias": "services"; "required": false; "isSignal": true; }; "priceRanges": { "alias": "priceRanges"; "required": false; "isSignal": true; }; "detailsLink": { "alias": "detailsLink"; "required": false; "isSignal": true; }; "showPrice": { "alias": "showPrice"; "required": false; "isSignal": true; }; "priceLabel": { "alias": "priceLabel"; "required": false; "isSignal": true; }; "priceFormat": { "alias": "priceFormat"; "required": false; "isSignal": true; }; "planMeta": { "alias": "planMeta"; "required": false; "isSignal": true; }; "cardAppearance": { "alias": "cardAppearance"; "required": false; "isSignal": true; }; "ctaLabel": { "alias": "ctaLabel"; "required": false; "isSignal": true; }; "ctaVariant": { "alias": "ctaVariant"; "required": false; "isSignal": true; }; "imageAltSuffix": { "alias": "imageAltSuffix"; "required": false; "isSignal": true; }; "skeletonCount": { "alias": "skeletonCount"; "required": false; "isSignal": true; }; "showBanner": { "alias": "showBanner"; "required": false; "isSignal": true; }; "showSearch": { "alias": "showSearch"; "required": false; "isSignal": true; }; "titlePrefix": { "alias": "titlePrefix"; "required": false; "isSignal": true; }; "resultsTitle": { "alias": "resultsTitle"; "required": false; "isSignal": true; }; "categoriesTitle": { "alias": "categoriesTitle"; "required": false; "isSignal": true; }; "categoriesLayout": { "alias": "categoriesLayout"; "required": false; "isSignal": true; }; "searchPlaceholder": { "alias": "searchPlaceholder"; "required": false; "isSignal": true; }; "searchIconSrc": { "alias": "searchIconSrc"; "required": false; "isSignal": true; }; "filterTitle": { "alias": "filterTitle"; "required": false; "isSignal": true; }; "filterIconSrc": { "alias": "filterIconSrc"; "required": false; "isSignal": true; }; "emptyMessage": { "alias": "emptyMessage"; "required": false; "isSignal": true; }; "emptyActionLabel": { "alias": "emptyActionLabel"; "required": false; "isSignal": true; }; "contactHref": { "alias": "contactHref"; "required": false; "isSignal": true; }; "contactLabel": { "alias": "contactLabel"; "required": false; "isSignal": true; }; }, { "category": "categoryChange"; }, ["cardTemplate"], never, true, never>;
|
|
78
102
|
}
|
|
@@ -1,20 +1,32 @@
|
|
|
1
1
|
import { Plan } from '../../models/plan.models';
|
|
2
2
|
import { LinkTarget } from '../../models/ui.models';
|
|
3
|
+
import { PriceFormat } from '../../utils/text.utils';
|
|
4
|
+
import { ButtonVariant } from '../button/button.component';
|
|
3
5
|
import * as i0 from "@angular/core";
|
|
4
6
|
/**
|
|
5
|
-
* Plan detail view: title with a back link, photo, price
|
|
6
|
-
* number of people, included services
|
|
7
|
-
*
|
|
7
|
+
* Plan detail view: title with a back link, photo, price with an early booking button,
|
|
8
|
+
* description, duration, number of people, included services and a gift box.
|
|
9
|
+
* On screens below 1024px a bar with the price and the booking button stays fixed at
|
|
10
|
+
* the bottom while the plan is on screen. It only renders; the page loads the plan and
|
|
11
|
+
* handles SEO.
|
|
8
12
|
*
|
|
9
13
|
* ```html
|
|
10
|
-
* <cc-plan-details [plan]="plan" [bookingUrl]="
|
|
14
|
+
* <cc-plan-details [plan]="plan" [bookingUrl]="bookingFor" imageAltSuffix=" en Laurel Spa" />
|
|
11
15
|
* ```
|
|
16
|
+
*
|
|
17
|
+
* Tokens: --cc-details-panel-bg, --cc-details-price-bg, --cc-details-price-color,
|
|
18
|
+
* --cc-details-gift-border, --cc-details-bar-bg, --cc-details-image-ratio.
|
|
12
19
|
*/
|
|
13
20
|
export declare class PlanDetailsComponent {
|
|
14
21
|
readonly plan: import("@angular/core").InputSignal<Plan>;
|
|
15
|
-
/**
|
|
16
|
-
readonly bookingUrl: import("@angular/core").InputSignal<string>;
|
|
22
|
+
/** Booking link, usually WhatsApp. A function receives the plan, to mention it in the message. */
|
|
23
|
+
readonly bookingUrl: import("@angular/core").InputSignal<string | ((plan: Plan) => string)>;
|
|
17
24
|
readonly bookingLabel: import("@angular/core").InputSignal<string>;
|
|
25
|
+
/** Shorter label for the bottom bar on small screens. */
|
|
26
|
+
readonly barBookingLabel: import("@angular/core").InputSignal<string>;
|
|
27
|
+
readonly bookingVariant: import("@angular/core").InputSignal<ButtonVariant>;
|
|
28
|
+
/** Keeps a bar with price and booking button at the bottom on small screens. */
|
|
29
|
+
readonly stickyBar: import("@angular/core").InputSignal<boolean>;
|
|
18
30
|
readonly showBanner: import("@angular/core").InputSignal<boolean>;
|
|
19
31
|
readonly backLink: import("@angular/core").InputSignal<LinkTarget | null>;
|
|
20
32
|
readonly backLabel: import("@angular/core").InputSignal<string>;
|
|
@@ -22,13 +34,14 @@ export declare class PlanDetailsComponent {
|
|
|
22
34
|
readonly titleIconSrc: import("@angular/core").InputSignal<string>;
|
|
23
35
|
/** Added after the plan name in the photo's alt text. */
|
|
24
36
|
readonly imageAltSuffix: import("@angular/core").InputSignal<string>;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
readonly
|
|
28
|
-
readonly currencyDigits: import("@angular/core").InputSignal<string>;
|
|
37
|
+
readonly priceFormat: import("@angular/core").InputSignal<PriceFormat>;
|
|
38
|
+
/** Small text under the price. Defaults to "Precio por plan". */
|
|
39
|
+
readonly priceNote: import("@angular/core").InputSignal<string>;
|
|
29
40
|
readonly durationIconSrc: import("@angular/core").InputSignal<string>;
|
|
30
41
|
readonly personIconSrc: import("@angular/core").InputSignal<string>;
|
|
31
42
|
readonly peopleIconSrc: import("@angular/core").InputSignal<string>;
|
|
43
|
+
readonly durationLabel: import("@angular/core").InputSignal<string>;
|
|
44
|
+
readonly peopleCaption: import("@angular/core").InputSignal<string>;
|
|
32
45
|
readonly personLabel: import("@angular/core").InputSignal<string>;
|
|
33
46
|
readonly peopleLabel: import("@angular/core").InputSignal<string>;
|
|
34
47
|
readonly includesLabel: import("@angular/core").InputSignal<string>;
|
|
@@ -39,6 +52,8 @@ export declare class PlanDetailsComponent {
|
|
|
39
52
|
readonly perksImageAlt: import("@angular/core").InputSignal<string>;
|
|
40
53
|
protected readonly people: import("@angular/core").Signal<number>;
|
|
41
54
|
protected readonly services: import("@angular/core").Signal<import("@c-code/c-code-fw/ui").AdditionalService[]>;
|
|
55
|
+
protected readonly price: import("@angular/core").Signal<string>;
|
|
56
|
+
protected readonly booking: import("@angular/core").Signal<string>;
|
|
42
57
|
static ɵfac: i0.ɵɵFactoryDeclaration<PlanDetailsComponent, never>;
|
|
43
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<PlanDetailsComponent, "cc-plan-details", never, { "plan": { "alias": "plan"; "required": true; "isSignal": true; }; "bookingUrl": { "alias": "bookingUrl"; "required": true; "isSignal": true; }; "bookingLabel": { "alias": "bookingLabel"; "required": false; "isSignal": true; }; "showBanner": { "alias": "showBanner"; "required": false; "isSignal": true; }; "backLink": { "alias": "backLink"; "required": false; "isSignal": true; }; "backLabel": { "alias": "backLabel"; "required": false; "isSignal": true; }; "backIconSrc": { "alias": "backIconSrc"; "required": false; "isSignal": true; }; "titleIconSrc": { "alias": "titleIconSrc"; "required": false; "isSignal": true; }; "imageAltSuffix": { "alias": "imageAltSuffix"; "required": false; "isSignal": true; }; "
|
|
58
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<PlanDetailsComponent, "cc-plan-details", never, { "plan": { "alias": "plan"; "required": true; "isSignal": true; }; "bookingUrl": { "alias": "bookingUrl"; "required": true; "isSignal": true; }; "bookingLabel": { "alias": "bookingLabel"; "required": false; "isSignal": true; }; "barBookingLabel": { "alias": "barBookingLabel"; "required": false; "isSignal": true; }; "bookingVariant": { "alias": "bookingVariant"; "required": false; "isSignal": true; }; "stickyBar": { "alias": "stickyBar"; "required": false; "isSignal": true; }; "showBanner": { "alias": "showBanner"; "required": false; "isSignal": true; }; "backLink": { "alias": "backLink"; "required": false; "isSignal": true; }; "backLabel": { "alias": "backLabel"; "required": false; "isSignal": true; }; "backIconSrc": { "alias": "backIconSrc"; "required": false; "isSignal": true; }; "titleIconSrc": { "alias": "titleIconSrc"; "required": false; "isSignal": true; }; "imageAltSuffix": { "alias": "imageAltSuffix"; "required": false; "isSignal": true; }; "priceFormat": { "alias": "priceFormat"; "required": false; "isSignal": true; }; "priceNote": { "alias": "priceNote"; "required": false; "isSignal": true; }; "durationIconSrc": { "alias": "durationIconSrc"; "required": false; "isSignal": true; }; "personIconSrc": { "alias": "personIconSrc"; "required": false; "isSignal": true; }; "peopleIconSrc": { "alias": "peopleIconSrc"; "required": false; "isSignal": true; }; "durationLabel": { "alias": "durationLabel"; "required": false; "isSignal": true; }; "peopleCaption": { "alias": "peopleCaption"; "required": false; "isSignal": true; }; "personLabel": { "alias": "personLabel"; "required": false; "isSignal": true; }; "peopleLabel": { "alias": "peopleLabel"; "required": false; "isSignal": true; }; "includesLabel": { "alias": "includesLabel"; "required": false; "isSignal": true; }; "perksTitle": { "alias": "perksTitle"; "required": false; "isSignal": true; }; "perks": { "alias": "perks"; "required": false; "isSignal": true; }; "perksImageSrc": { "alias": "perksImageSrc"; "required": false; "isSignal": true; }; "perksImageAlt": { "alias": "perksImageAlt"; "required": false; "isSignal": true; }; }, {}, never, ["[ccDetailsMedia]", "*"], true, never>;
|
|
44
59
|
}
|
|
@@ -4,25 +4,35 @@ import * as i0 from "@angular/core";
|
|
|
4
4
|
* Filter by included service and price range. The options come in as inputs,
|
|
5
5
|
* so the form does not load data by itself.
|
|
6
6
|
*
|
|
7
|
+
* `mode`:
|
|
8
|
+
* - `instant` (default): emits `filterChange` as soon as an option changes.
|
|
9
|
+
* - `submit`: emits when the user presses the submit button.
|
|
10
|
+
*
|
|
7
11
|
* ```html
|
|
8
12
|
* <cc-plan-filter-form [services]="services" [priceRanges]="ranges" (filterChange)="apply($event)" />
|
|
9
13
|
* ```
|
|
14
|
+
*
|
|
15
|
+
* Tokens: --cc-filter-field-bg, --cc-filter-field-border, --cc-filter-label-color.
|
|
10
16
|
*/
|
|
11
17
|
export declare class PlanFilterFormComponent {
|
|
12
18
|
readonly services: import("@angular/core").InputSignal<AdditionalService[]>;
|
|
13
19
|
readonly priceRanges: import("@angular/core").InputSignal<PriceRange[]>;
|
|
20
|
+
readonly mode: import("@angular/core").InputSignal<"instant" | "submit">;
|
|
14
21
|
readonly serviceLabel: import("@angular/core").InputSignal<string>;
|
|
15
22
|
readonly priceLabel: import("@angular/core").InputSignal<string>;
|
|
16
23
|
readonly anyLabel: import("@angular/core").InputSignal<string>;
|
|
17
24
|
readonly submitLabel: import("@angular/core").InputSignal<string>;
|
|
18
25
|
readonly resetLabel: import("@angular/core").InputSignal<string>;
|
|
19
|
-
/** Emits
|
|
26
|
+
/** Emits the current filter, and an empty filter on reset. */
|
|
20
27
|
readonly filterChange: import("@angular/core").OutputEmitterRef<PlanFilter>;
|
|
21
|
-
protected serviceIndex: import("@angular/core").WritableSignal<number>;
|
|
22
|
-
protected rangeIndex: import("@angular/core").WritableSignal<number>;
|
|
23
|
-
protected
|
|
28
|
+
protected readonly serviceIndex: import("@angular/core").WritableSignal<number>;
|
|
29
|
+
protected readonly rangeIndex: import("@angular/core").WritableSignal<number>;
|
|
30
|
+
protected readonly hasSelection: import("@angular/core").Signal<boolean>;
|
|
31
|
+
protected onServiceChange(event: Event): void;
|
|
32
|
+
protected onRangeChange(event: Event): void;
|
|
24
33
|
submit(): void;
|
|
25
34
|
reset(): void;
|
|
35
|
+
private toIndex;
|
|
26
36
|
static ɵfac: i0.ɵɵFactoryDeclaration<PlanFilterFormComponent, never>;
|
|
27
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<PlanFilterFormComponent, "cc-plan-filter-form", never, { "services": { "alias": "services"; "required": false; "isSignal": true; }; "priceRanges": { "alias": "priceRanges"; "required": false; "isSignal": true; }; "serviceLabel": { "alias": "serviceLabel"; "required": false; "isSignal": true; }; "priceLabel": { "alias": "priceLabel"; "required": false; "isSignal": true; }; "anyLabel": { "alias": "anyLabel"; "required": false; "isSignal": true; }; "submitLabel": { "alias": "submitLabel"; "required": false; "isSignal": true; }; "resetLabel": { "alias": "resetLabel"; "required": false; "isSignal": true; }; }, { "filterChange": "filterChange"; }, never, never, true, never>;
|
|
37
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<PlanFilterFormComponent, "cc-plan-filter-form", never, { "services": { "alias": "services"; "required": false; "isSignal": true; }; "priceRanges": { "alias": "priceRanges"; "required": false; "isSignal": true; }; "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "serviceLabel": { "alias": "serviceLabel"; "required": false; "isSignal": true; }; "priceLabel": { "alias": "priceLabel"; "required": false; "isSignal": true; }; "anyLabel": { "alias": "anyLabel"; "required": false; "isSignal": true; }; "submitLabel": { "alias": "submitLabel"; "required": false; "isSignal": true; }; "resetLabel": { "alias": "resetLabel"; "required": false; "isSignal": true; }; }, { "filterChange": "filterChange"; }, never, never, true, never>;
|
|
28
38
|
}
|