UNPKG

@postnord/web-components

Version:
438 lines (437 loc) 17.3 kB
/*! * Built with Stencil * By PostNord. */ import { Host, h } from "@stencil/core"; import { arrow_right, open_in_new } from "pn-design-assets/pn-assets/icons.js"; import { ripple, uuidv4 } from "../../../index"; /** * The card component is more than just a navigational element. * It is a flexible component that can be used as a product item, a clickable link card, etc... * * Setting the `href` prop will transform the entire `pn-card` into a clickable element. * If you need content to be interactable inside the card, do not use the `href` prop. * * @slot - The default slot is the primary content of the card. This is the same area where the `text` prop is located. * @slot image - Set a custom image/svg/illustration. Simply use an `img` tag with the slot "image". * @slot tags - Add `pn-tags` that will be positioned above the `label` and `overline` if used. * @slot header - The header content, same area that the `label` and `overline` props will appear. * @slot navigation - This slot is intended for one or more `pn-button` components. * Only use **without** the `href` prop. Having both at the same time makes the component inaccessible. * * @since v7.12.0 */ export class PnCard { id = `pn-card-${uuidv4()}`; idTitle = `${this.id}-title`; visibleOutline = false; hostElement; /** Headline of the card. Will act as label for the link if there is no `href-label` set. */ label; /** The label HTML tag. Default is `h3`. */ labelTag = 'h3'; /** Set a smaller text above the `label` text. */ overline; /** Text content of the card. */ text; /** Set a HTML id for the card. Optional and not required. */ cardId = null; /** * Uee the horizontal card layout. * @category Features * */ horizontal = false; /** Reverse the order of which the image will wrap. @category Features */ reverse = false; /** * Select image aspect ratio. Example: '3/3', '16/9'. * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio CSS documentation.} * @category Features * */ aspectRatio = ''; /** The card link. @category Href */ href; /** The link text. @category Href */ hrefLabel; /** The target attribute of the link. @category Href */ target; /** The rel attribute of the link. @category Href */ rel = 'noopener noreferrer'; /** The link icon. Defaults to `arrow_right` or `open_in_new` if `target="_blank"`. @category Href */ icon = null; watchCardId() { const id = this.cardId || this.id; this.idTitle = `${id}-title`; } /** Emitted when you click on the card link (if you use the `href` prop). */ pnCard; componentWillLoad() { this.watchCardId(); } isExternal() { return this.target === '_blank'; } showTitle() { return !!this.label; } showHref() { return !!this.href && (this.hrefLabel || this.showTitle()); } getTitleId() { return this.hrefLabel ? null : this.idTitle; } getLabelledby() { return this.hrefLabel ? null : this.showTitle() ? this.idTitle : null; } getIcon() { if (!!this.icon) return this.icon; return this.isExternal() ? open_in_new : arrow_right; } getHeadingTag() { const tags = ['h2', 'h3', 'h4', 'h5', 'h6', 'p']; return tags.includes(this.labelTag) ? this.labelTag : 'h3'; } handleFocus({ type, target }) { this.visibleOutline = type === 'focus' && target.matches(':focus-visible'); } handleClick(event) { ripple(event, this.hostElement, '.pn-card'); this.pnCard.emit({ click: event }); } render() { const TitleTag = this.getHeadingTag(); return (h(Host, { key: '65ed28a0a625760d11f9bd7961978af7573f7062' }, h("article", { key: '2f05480099b5bedddba115a3f00174d0ed4f9658', id: this.cardId, class: "pn-card", "data-link": !!this.href, "data-horizontal": this.horizontal, "data-reverse": this.reverse, "data-focus": this.visibleOutline }, h("div", { key: '1ec2a31f2e71b9f4a511efb49461541f141ff077', class: "pn-card-image" }, h("picture", { key: '869648c55b9e64091b55f501b759ffcddc33a8c5', class: "pn-card-picture", style: { '--pn-card-aspect-ratio': this.aspectRatio || 'unset' } }, h("slot", { key: '9e31feb5e4c486159fb4f9ebb57cefbd7d156988', name: "image" }))), h("div", { key: 'e2cfd35b304c05fb569da26aa7f248ed53b1e7aa', class: "pn-card-content" }, h("header", { key: 'a5730ce876dd1b5fa0c6c37ba400801530bf99ea', class: "pn-card-header" }, h("div", { key: '4e9566e679185db1704e313002d20d7016558c25', class: "pn-card-tags" }, h("slot", { key: '0c4863c1ef7b69ef8a333dd7ac834f76b8a3fc00', name: "tags" })), !!this.overline && h("p", { key: '8129ee0e178e4db9fcbf9895e75d64c02279a0a6', class: "pn-card-label-overline" }, this.overline), !!this.label && (h(TitleTag, { key: '62a8d9c1512683f3e4248eac05bf2f33e0374fe9', id: this.getTitleId(), class: "pn-card-label" }, this.label)), h("slot", { key: '13f3c2e3e182ce134dc7be0af3c8c2dec1c1f751', name: "header" })), h("section", { key: 'c34ddb8484423b65927ace2e0b46deed6b1d3b64', class: "pn-card-section" }, !!this.text && h("p", { key: '8370b223a2af93f64eb2efd84dda0b172324be54', class: "pn-card-section-paragraph" }, this.text), h("slot", { key: '363cc14089263d2e640f35707a6503aeb77ae8a6' })), h("nav", { key: '5636561cc2dc0eb1a1f42d213e87e73da9a3ce98', class: "pn-card-navigation" }, this.showHref() && (h("a", { key: '9c7be2037e54320ccb2668170828e7ffc8fd7d25', class: "pn-card-link", href: this.href, target: this.target, rel: this.rel, "aria-labelledby": this.getLabelledby(), onClick: event => this.handleClick(event), onFocus: event => this.handleFocus(event), onBlur: event => this.handleFocus(event) }, this.hrefLabel, h("pn-icon", { key: 'd77e3349eb1ed2cb3e8e72418c70d66b93ad5b20', color: "blue700", icon: this.getIcon() }))), h("slot", { key: 'c28d4208e146a77f334fc326e7abbbf53e86e028', name: "navigation" })))))); } static get is() { return "pn-card"; } static get originalStyleUrls() { return { "$": ["pn-card.scss"] }; } static get styleUrls() { return { "$": ["pn-card.css"] }; } static get properties() { return { "label": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Headline of the card. Will act as label for the link if there is no `href-label` set." }, "getter": false, "setter": false, "reflect": false, "attribute": "label" }, "labelTag": { "type": "string", "mutable": false, "complexType": { "original": "'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p'", "resolved": "\"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"p\"", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "The label HTML tag. Default is `h3`." }, "getter": false, "setter": false, "reflect": false, "attribute": "label-tag", "defaultValue": "'h3'" }, "overline": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "Set a smaller text above the `label` text." }, "getter": false, "setter": false, "reflect": false, "attribute": "overline" }, "text": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "Text content of the card." }, "getter": false, "setter": false, "reflect": false, "attribute": "text" }, "cardId": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "Set a HTML id for the card. Optional and not required." }, "getter": false, "setter": false, "reflect": false, "attribute": "card-id", "defaultValue": "null" }, "horizontal": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Features" }], "text": "Uee the horizontal card layout." }, "getter": false, "setter": false, "reflect": false, "attribute": "horizontal", "defaultValue": "false" }, "reverse": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Features" }], "text": "Reverse the order of which the image will wrap." }, "getter": false, "setter": false, "reflect": false, "attribute": "reverse", "defaultValue": "false" }, "aspectRatio": { "type": "string", "mutable": false, "complexType": { "original": "string | '3/3' | '16/9'", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "see", "text": "{@link https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio CSS documentation.}" }, { "name": "category", "text": "Features" }], "text": "Select image aspect ratio. Example: '3/3', '16/9'." }, "getter": false, "setter": false, "reflect": false, "attribute": "aspect-ratio", "defaultValue": "''" }, "href": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Href" }], "text": "The card link." }, "getter": false, "setter": false, "reflect": false, "attribute": "href" }, "hrefLabel": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Href" }], "text": "The link text." }, "getter": false, "setter": false, "reflect": false, "attribute": "href-label" }, "target": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Href" }], "text": "The target attribute of the link." }, "getter": false, "setter": false, "reflect": false, "attribute": "target" }, "rel": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Href" }], "text": "The rel attribute of the link." }, "getter": false, "setter": false, "reflect": false, "attribute": "rel", "defaultValue": "'noopener noreferrer'" }, "icon": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Href" }], "text": "The link icon. Defaults to `arrow_right` or `open_in_new` if `target=\"_blank\"`." }, "getter": false, "setter": false, "reflect": false, "attribute": "icon", "defaultValue": "null" } }; } static get states() { return { "visibleOutline": {} }; } static get events() { return [{ "method": "pnCard", "name": "pnCard", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "Emitted when you click on the card link (if you use the `href` prop)." }, "complexType": { "original": "{ click: MouseEvent }", "resolved": "{ click: MouseEvent; }", "references": { "MouseEvent": { "location": "global", "id": "global::MouseEvent" } } } }]; } static get elementRef() { return "hostElement"; } static get watchers() { return [{ "propName": "cardId", "methodName": "watchCardId" }]; } }