wj-elements 0.3.8 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/base-path.js +16 -2
- package/dist/base-path.js.map +1 -1
- package/dist/dark.css +9 -0
- package/dist/{icon-DVyMc4Wv.js → icon-CReYMzAK.js} +2 -2
- package/dist/{icon-DVyMc4Wv.js.map → icon-CReYMzAK.js.map} +1 -1
- package/dist/light.css +9 -0
- package/dist/packages/utils/permissions.d.ts +9 -9
- package/dist/packages/wje-accordion/accordion.element.d.ts +3 -6
- package/dist/packages/wje-accordion-item/accordion-item.element.d.ts +27 -6
- package/dist/packages/wje-animation/animation.element.d.ts +10 -2
- package/dist/packages/wje-aside/aside.element.d.ts +10 -6
- package/dist/packages/wje-avatar/avatar.element.d.ts +19 -11
- package/dist/packages/wje-carousel/carousel.element.d.ts +78 -3
- package/dist/packages/wje-carousel-item/carousel-item.element.d.ts +5 -0
- package/dist/packages/wje-input/input.element.d.ts +2 -0
- package/dist/packages/wje-textarea/textarea.element.d.ts +2 -0
- package/dist/packages/wje-toast/toast.element.d.ts +80 -10
- package/dist/permissions.js +7 -7
- package/dist/permissions.js.map +1 -1
- package/dist/styles.css +58 -5
- package/dist/wje-accordion-item.js +18 -18
- package/dist/wje-accordion-item.js.map +1 -1
- package/dist/wje-accordion.js.map +1 -1
- package/dist/wje-animation.js +2 -2
- package/dist/wje-animation.js.map +1 -1
- package/dist/wje-aside.js +1 -1
- package/dist/wje-aside.js.map +1 -1
- package/dist/wje-avatar.js.map +1 -1
- package/dist/wje-button.js +1 -1
- package/dist/wje-carousel-item.js +19 -1
- package/dist/wje-carousel-item.js.map +1 -1
- package/dist/wje-carousel.js +208 -57
- package/dist/wje-carousel.js.map +1 -1
- package/dist/wje-element.js +4 -4
- package/dist/wje-element.js.map +1 -1
- package/dist/wje-file-upload-item.js +1 -1
- package/dist/wje-icon.js +1 -1
- package/dist/wje-img-comparer.js +1 -1
- package/dist/wje-input.js +14 -3
- package/dist/wje-input.js.map +1 -1
- package/dist/wje-master.js +1 -1
- package/dist/wje-option.js +1 -1
- package/dist/wje-pagination.js +1 -1
- package/dist/wje-select.js +2 -2
- package/dist/wje-textarea.js +1 -1
- package/dist/wje-textarea.js.map +1 -1
- package/dist/wje-toast.js +383 -11
- package/dist/wje-toast.js.map +1 -1
- package/package.json +4 -3
package/dist/wje-avatar.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wje-avatar.js","sources":["../packages/wje-avatar/service/service.js","../packages/wje-avatar/avatar.element.js","../packages/wje-avatar/avatar.js"],"sourcesContent":["/**\n * Generates an HSL color value based on the input text.\n * @param {string} text The input text to generate the HSL color.\n * @param {number} [s] The saturation value (in percentage) for the HSL color.\n * @param {number} [l] The lightness value (in percentage) for the HSL color.\n * @returns {string} - The HSL color string in the format `hsl(h, s%, l%)`.\n * @description\n * This function computes a hash from the input text and uses it to generate\n * a hue value. The hue is combined with the provided saturation and lightness\n * values to create an HSL color. This can be useful for consistently assigning\n * colors based on text input, such as for avatars or tags.\n * @example\n * // Returns 'hsl(180, 40%, 65%)'\n * getHsl('example');\n * @example\n * // Returns 'hsl(300, 50%, 70%)'\n * getHsl('test', 50, 70);\n */\nexport function getHsl(text, s = 40, l = 75) {\n let str = text;\n let hash = 0;\n\n for (let i = 0; i < str?.length; i++) {\n hash = str.charCodeAt(i) + hash * 31;\n }\n\n let h = hash % 360;\n\n return `hsl(${h}, ${s}%, ${l}%)`;\n}\n\n/**\n * Generates background and text HSL colors for avatars based on input text.\n * The text color is a darker, more saturated variant of the background color\n * to ensure sufficient contrast while keeping the same hue.\n *\n * @param {string} text The input text (e.g. initials or name).\n * @returns {{ background: string, color: string }}\n */\nexport function getAvatarColors(text) {\n let hash = 0;\n for (let i = 0; i < text?.length; i++) {\n hash = text.charCodeAt(i) + hash * 31;\n }\n\n const h = Math.abs(hash) % 360;\n\n // 👇 Figma-like pastel background\n const bgS = 30;\n const bgL = 88;\n\n // 👇 Softer text color (same hue)\n const textS = 50;\n const textL = 48;\n\n return {\n background: `hsl(${h}, ${bgS}%, ${bgL}%)`,\n color: `hsl(${h}, ${textS}%, ${textL}%)`\n };\n}\n\n/**\n * Generates initials from a given string.\n * @param {string} string The input string, typically a full name.\n * @param {number} [length] The desired number of initials (default is 2).\n * @returns {string} - The generated initials in uppercase.\n * @description\n * This function takes a string, splits it by spaces, and generates initials.\n * It always includes the first character of the first word. If the input string\n * contains more than one word and the `length` parameter is greater than 1, it\n * also includes the first character of the last word.\n * @example\n * // Returns 'JD'\n * getInitials('John Doe');\n * @example\n * // Returns 'J'\n * getInitials('John');\n * @example\n * // Returns 'JM'\n * getInitials('John Michael Doe', 2);\n */\nexport function getInitials(string, length = 2) {\n let names = string.split(' ');\n let initials = names[0].substring(0, 1).toUpperCase();\n\n if (names.length > 1 && length > 1) {\n initials += names[names.length - 1].substring(0, 1).toUpperCase();\n }\n return initials;\n}\n","import { default as WJElement } from '../wje-element/element.js';\nimport { getHsl, getInitials, getAvatarColors } from './service/service.js';\nimport styles from './styles/styles.css?inline';\n\n/**\n * @summary This class represents an Avatar element, extending the WJElement class.\n * @documentation https://elements.webjet.sk/components/avatar\n * @status stable\n * @augments WJElement\n * @slot - The avatar main content.\n * @csspart native - The component's native wrapper.\n * @cssproperty --wje-avatar-width;\n * @cssproperty --wje-avatar-height;\n * @cssproperty --wje-avatar-font-size;\n * @cssproperty --wje-avatar-font-weight;\n * @cssproperty --wje-avatar-color;\n * @cssproperty --wje-avatar-background-color;\n * @cssproperty --wje-avatar-border-radius;\n * @cssproperty --wje-avatar-border-color;\n * @cssproperty --wje-avatar-border-width;\n * @cssproperty --wje-avatar-border-style;\n * @tag wje-avatar\n */\nexport default class Avatar extends WJElement {\n /**\n * Avatar class constructor.\n */\n constructor() {\n super();\n }\n\n /**\n * Sets the value of the 'label' attribute for the element.\n * @param {string} value The new value to be set for the 'label' attribute.\n */\n set label(value) {\n this.setAttribute('label', value);\n }\n\n /**\n * Retrieves the value of the 'label' attribute for the element.\n * If the attribute is not set, it defaults to an empty string.\n * @returns {string} The value of the 'label' attribute or an empty string if not defined.\n */\n get label() {\n return this.getAttribute('label') || '';\n }\n\n /**\n * Sets the value of initials for the element by updating\n * the 'initials' attribute with the provided value.\n * @param {string} value The value to be set as the initials.\n */\n set initials(value) {\n this.setAttribute('initials', '');\n }\n\n /**\n * Retrieves the value of the 'initials' attribute if it exists.\n * @returns {boolean} Returns true if the 'initials' attribute is present, otherwise false.\n */\n get initials() {\n return this.hasAttribute('initials') || false;\n }\n\n /**\n * Sets the size attribute for the element.\n * @param {string | number} value The value to set for the size attribute.\n */\n set size(value) {\n this.setAttribute('size', value);\n }\n\n /**\n * Retrieves the size attribute of the element. If the size attribute\n * is not defined, it returns the default value 'medium'.\n * @returns {string} The size value of the element or 'medium' if not specified.\n */\n get size() {\n return this.getAttribute('size') || 'medium';\n }\n\n /**\n * Class name for the Avatar element.\n */\n className = 'Avatar';\n\n /**\n * Getter for cssStyleSheet.\n * @returns {string} styles\n */\n static get cssStyleSheet() {\n return styles;\n }\n\n /**\n * Returns the list of attributes to observe for changes.\n * @static\n * @returns {Array<string>}\n */\n static get observedAttributes() {\n return ['initials', 'label'];\n }\n\n /**\n * Method to setup attributes.\n */\n setupAttributes() {\n this.isShadowRoot = 'open';\n this.syncAria();\n }\n\n attributeChangedCallback(name, oldValue, newValue) {\n super.attributeChangedCallback?.(name, oldValue, newValue);\n if (name === 'label' || name === 'initials') {\n this.syncAria();\n }\n }\n\n /**\n * Method to draw the avatar element and return a document fragment.\n * @returns {object} fragment - The document fragment\n */\n draw() {\n let fragment = document.createDocumentFragment();\n\n let element = document.createElement('div');\n element.setAttribute('part', 'native');\n element.classList.add('native-avatar');\n\n let slot = document.createElement('slot');\n\n element.appendChild(slot);\n\n if (this.initials) {\n let initials = getInitials(this.label);\n const { background, color } = getAvatarColors(initials);\n\n this.style.setProperty('--wje-avatar-background-color', background);\n this.style.setProperty('--wje-avatar-color', color);\n\n element.innerText = initials;\n } else {\n let slotIcon = document.createElement('slot');\n slotIcon.setAttribute('name', 'icon');\n\n element.appendChild(slotIcon);\n }\n\n let status = document.createElement('slot');\n status.setAttribute('name', 'status');\n status.setAttribute('part', 'status');\n\n let secondary = document.createElement('slot');\n secondary.setAttribute('name', 'secondary');\n secondary.setAttribute('part', 'secondary');\n\n element.appendChild(status);\n element.appendChild(secondary);\n\n fragment.appendChild(element);\n\n return fragment;\n }\n\n /**\n * Syncs ARIA attributes on the host element.\n */\n syncAria() {\n const label = this.label?.trim();\n if (label) {\n this.setAriaState({ label });\n }\n }\n\n /**\n * Method to check if the avatar is an image.\n * @returns {boolean} - True if the avatar is an image, false otherwise\n */\n isImage() {\n return this.getElementsByTagName('wje-img').length > 0;\n }\n}\n","import Avatar from './avatar.element.js';\n\nexport default Avatar;\n\nAvatar.define('wje-avatar', Avatar);\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"wje-avatar.js","sources":["../packages/wje-avatar/service/service.js","../packages/wje-avatar/avatar.element.js","../packages/wje-avatar/avatar.js"],"sourcesContent":["/**\n * Generates an HSL color value based on the input text.\n * @param {string} text The input text to generate the HSL color.\n * @param {number} [s] The saturation value (in percentage) for the HSL color.\n * @param {number} [l] The lightness value (in percentage) for the HSL color.\n * @returns {string} - The HSL color string in the format `hsl(h, s%, l%)`.\n * @description\n * This function computes a hash from the input text and uses it to generate\n * a hue value. The hue is combined with the provided saturation and lightness\n * values to create an HSL color. This can be useful for consistently assigning\n * colors based on text input, such as for avatars or tags.\n * @example\n * // Returns 'hsl(180, 40%, 65%)'\n * getHsl('example');\n * @example\n * // Returns 'hsl(300, 50%, 70%)'\n * getHsl('test', 50, 70);\n */\nexport function getHsl(text, s = 40, l = 75) {\n let str = text;\n let hash = 0;\n\n for (let i = 0; i < str?.length; i++) {\n hash = str.charCodeAt(i) + hash * 31;\n }\n\n let h = hash % 360;\n\n return `hsl(${h}, ${s}%, ${l}%)`;\n}\n\n/**\n * Generates background and text HSL colors for avatars based on input text.\n * The text color is a darker, more saturated variant of the background color\n * to ensure sufficient contrast while keeping the same hue.\n *\n * @param {string} text The input text (e.g. initials or name).\n * @returns {{ background: string, color: string }}\n */\nexport function getAvatarColors(text) {\n let hash = 0;\n for (let i = 0; i < text?.length; i++) {\n hash = text.charCodeAt(i) + hash * 31;\n }\n\n const h = Math.abs(hash) % 360;\n\n // 👇 Figma-like pastel background\n const bgS = 30;\n const bgL = 88;\n\n // 👇 Softer text color (same hue)\n const textS = 50;\n const textL = 48;\n\n return {\n background: `hsl(${h}, ${bgS}%, ${bgL}%)`,\n color: `hsl(${h}, ${textS}%, ${textL}%)`\n };\n}\n\n/**\n * Generates initials from a given string.\n * @param {string} string The input string, typically a full name.\n * @param {number} [length] The desired number of initials (default is 2).\n * @returns {string} - The generated initials in uppercase.\n * @description\n * This function takes a string, splits it by spaces, and generates initials.\n * It always includes the first character of the first word. If the input string\n * contains more than one word and the `length` parameter is greater than 1, it\n * also includes the first character of the last word.\n * @example\n * // Returns 'JD'\n * getInitials('John Doe');\n * @example\n * // Returns 'J'\n * getInitials('John');\n * @example\n * // Returns 'JM'\n * getInitials('John Michael Doe', 2);\n */\nexport function getInitials(string, length = 2) {\n let names = string.split(' ');\n let initials = names[0].substring(0, 1).toUpperCase();\n\n if (names.length > 1 && length > 1) {\n initials += names[names.length - 1].substring(0, 1).toUpperCase();\n }\n return initials;\n}\n","import { default as WJElement } from '../wje-element/element.js';\nimport { getHsl, getInitials, getAvatarColors } from './service/service.js';\nimport styles from './styles/styles.css?inline';\n\n/**\n * @summary This class represents an Avatar element, extending the WJElement class.\n * @documentation https://elements.webjet.sk/components/avatar\n * @status stable\n * @augments WJElement\n * @attribute {boolean} initials - Renders generated initials from `label` instead of the default slotted content.\n * @attribute {string} label - Provides the source text for generated initials and the accessible label of the avatar.\n * @attribute {string} size - Selects a predefined avatar size such as `small`, `medium`, `normal`, `large`, or larger variants.\n * @attribute {string} status-placement - Positions the `status` slot on one of the avatar corners.\n * @slot default - Slot for the main avatar content, typically an image.\n * @slot icon - Slot for an icon rendered inside the avatar.\n * @slot status - Slot for a status badge or indicator positioned on the avatar edge.\n * @slot secondary - Slot for additional secondary content rendered with the avatar.\n * @csspart native - The component's native wrapper.\n * @csspart status - The positioned slot container for status content.\n * @csspart secondary - The slot container for secondary avatar content.\n * @cssproperty [--wje-avatar-size] - Controls the overall rendered size of the avatar shell.\n * @cssproperty [--wje-avatar-font-size] - Controls the font size used for initials and text content.\n * @cssproperty [--wje-avatar-font-weight] - Controls the font weight used for initials and text content.\n * @cssproperty [--wje-avatar-color] - Controls the text color inside the avatar.\n * @cssproperty [--wje-avatar-background-color] - Controls the background color of the avatar surface.\n * @cssproperty [--wje-avatar-border-radius] - Controls the avatar border radius.\n * @cssproperty [--wje-avatar-border-color] - Controls the avatar border color when a border is applied.\n * @cssproperty [--wje-avatar-border-width] - Controls the avatar border width when a border is applied.\n * @cssproperty [--wje-avatar-border-style] - Controls the avatar border style when a border is applied.\n * @tag wje-avatar\n */\nexport default class Avatar extends WJElement {\n /**\n * Avatar class constructor.\n */\n constructor() {\n super();\n }\n\n /**\n * Sets the value of the 'label' attribute for the element.\n * @param {string} value The new value to be set for the 'label' attribute.\n */\n set label(value) {\n this.setAttribute('label', value);\n }\n\n /**\n * Retrieves the value of the 'label' attribute for the element.\n * If the attribute is not set, it defaults to an empty string.\n * @returns {string} The value of the 'label' attribute or an empty string if not defined.\n */\n get label() {\n return this.getAttribute('label') || '';\n }\n\n /**\n * Sets the value of initials for the element by updating\n * the 'initials' attribute with the provided value.\n * @param {string} value The value to be set as the initials.\n */\n set initials(value) {\n this.setAttribute('initials', '');\n }\n\n /**\n * Retrieves the value of the 'initials' attribute if it exists.\n * @returns {boolean} Returns true if the 'initials' attribute is present, otherwise false.\n */\n get initials() {\n return this.hasAttribute('initials') || false;\n }\n\n /**\n * Sets the size attribute for the element.\n * @param {string | number} value The value to set for the size attribute.\n */\n set size(value) {\n this.setAttribute('size', value);\n }\n\n /**\n * Retrieves the size attribute of the element. If the size attribute\n * is not defined, it returns the default value 'medium'.\n * @returns {string} The size value of the element or 'medium' if not specified.\n */\n get size() {\n return this.getAttribute('size') || 'medium';\n }\n\n /**\n * Class name for the Avatar element.\n */\n className = 'Avatar';\n\n /**\n * Getter for cssStyleSheet.\n * @returns {string} styles\n */\n static get cssStyleSheet() {\n return styles;\n }\n\n /**\n * Returns the list of attributes to observe for changes.\n * @static\n * @returns {Array<string>}\n */\n static get observedAttributes() {\n return ['initials', 'label'];\n }\n\n /**\n * Method to setup attributes.\n */\n setupAttributes() {\n this.isShadowRoot = 'open';\n this.syncAria();\n }\n\n attributeChangedCallback(name, oldValue, newValue) {\n super.attributeChangedCallback?.(name, oldValue, newValue);\n if (name === 'label' || name === 'initials') {\n this.syncAria();\n }\n }\n\n /**\n * Method to draw the avatar element and return a document fragment.\n * @returns {object} fragment - The document fragment\n */\n draw() {\n let fragment = document.createDocumentFragment();\n\n let element = document.createElement('div');\n element.setAttribute('part', 'native');\n element.classList.add('native-avatar');\n\n let slot = document.createElement('slot');\n\n element.appendChild(slot);\n\n if (this.initials) {\n let initials = getInitials(this.label);\n const { background, color } = getAvatarColors(initials);\n\n this.style.setProperty('--wje-avatar-background-color', background);\n this.style.setProperty('--wje-avatar-color', color);\n\n element.innerText = initials;\n } else {\n let slotIcon = document.createElement('slot');\n slotIcon.setAttribute('name', 'icon');\n\n element.appendChild(slotIcon);\n }\n\n let status = document.createElement('slot');\n status.setAttribute('name', 'status');\n status.setAttribute('part', 'status');\n\n let secondary = document.createElement('slot');\n secondary.setAttribute('name', 'secondary');\n secondary.setAttribute('part', 'secondary');\n\n element.appendChild(status);\n element.appendChild(secondary);\n\n fragment.appendChild(element);\n\n return fragment;\n }\n\n /**\n * Syncs ARIA attributes on the host element.\n */\n syncAria() {\n const label = this.label?.trim();\n if (label) {\n this.setAriaState({ label });\n }\n }\n\n /**\n * Method to check if the avatar is an image.\n * @returns {boolean} - True if the avatar is an image, false otherwise\n */\n isImage() {\n return this.getElementsByTagName('wje-img').length > 0;\n }\n}\n","import Avatar from './avatar.element.js';\n\nexport default Avatar;\n\nAvatar.define('wje-avatar', Avatar);\n"],"names":[],"mappings":"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"}
|
package/dist/wje-button.js
CHANGED
|
@@ -11,7 +11,7 @@ var _Button_instances, populateCustomEvent_fn;
|
|
|
11
11
|
import { b as bindRouterLinks } from "./router-links-wjqCnncc.js";
|
|
12
12
|
import { bool } from "./utils.js";
|
|
13
13
|
import WJElement from "./wje-element.js";
|
|
14
|
-
import { I as Icon } from "./icon-
|
|
14
|
+
import { I as Icon } from "./icon-CReYMzAK.js";
|
|
15
15
|
import { WjElementUtils } from "./element-utils.js";
|
|
16
16
|
import { event } from "./event.js";
|
|
17
17
|
const styles = "/*\n[ WJ Button ]\n*/\n\n/*PRIMARY*/\n.wje-button-solid.wje-color-primary {\n background-color: var(--wje-color-primary-9);\n border-color: var(--wje-color-primary-9);\n color: var(--wje-color-contrast-0);\n}\n\n.wje-button-outline.wje-color-primary {\n background-color: var(--wje-color-primary-1);\n border-color: var(--wje-color-primary-9);\n color: var(--wje-color-primary-9);\n}\n\n.wje-button-link.wje-color-primary {\n background-color: transparent;\n border-color: transparent;\n color: var(--wje-color-primary-9);\n}\n\n/*COMPLETE*/\n.wje-button-solid.wje-color-complete {\n background-color: var(--wje-color-complete-9);\n border-color: var(--wje-color-complete-9);\n color: var(--wje-color-contrast-0);\n}\n\n.wje-button-outline.wje-color-complete {\n background-color: var(--wje-color-complete-1);\n border-color: var(--wje-color-complete-9);\n color: var(--wje-color-complete-9);\n}\n\n.wje-button-link.wje-color-complete {\n background-color: transparent;\n border-color: transparent;\n color: var(--wje-color-complete-9);\n}\n\n/*SUCCESS*/\n.wje-button-solid.wje-color-success {\n background-color: var(--wje-color-success-9);\n border-color: var(--wje-color-success-9);\n color: var(--wje-color-contrast-0);\n}\n\n.wje-button-outline.wje-color-success {\n background-color: var(--wje-color-success-1);\n border-color: var(--wje-color-success-9);\n color: var(--wje-color-success-9);\n}\n\n.wje-button-link.wje-color-success {\n background-color: transparent;\n border-color: transparent;\n color: var(--wje-color-success-9);\n}\n\n/*WARNING*/\n.wje-button-solid.wje-color-warning {\n background-color: var(--wje-color-warning-9);\n border-color: var(--wje-color-warning-9);\n color: var(--wje-color-black);\n}\n\n.wje-button-outline.wje-color-warning {\n background-color: var(--wje-color-warning-1);\n border-color: var(--wje-color-warning-11);\n color: var(--wje-color-warning-11);\n}\n\n.wje-button-link.wje-color-warning {\n background-color: transparent;\n border-color: transparent;\n color: var(--wje-color-warning-11);\n}\n\n/*DANGER*/\n.wje-button-solid.wje-color-danger {\n background-color: var(--wje-color-danger-9);\n border-color: var(--wje-color-danger-9);\n color: var(--wje-color-contrast-0);\n}\n\n.wje-button-outline.wje-color-danger {\n background-color: var(--wje-color-danger-1);\n border-color: var(--wje-color-danger-9);\n color: var(--wje-color-danger-9);\n}\n\n.wje-button-link.wje-color-danger {\n background-color: transparent;\n border-color: transparent;\n color: var(--wje-color-danger-9);\n}\n\n/*NEUTRAL*/\n.wje-button-solid.wje-color-info {\n background-color: var(--wje-color-contrast-9);\n border-color: var(--wje-color-contrast-9);\n color: var(--wje-color-contrast-0);\n}\n\n.wje-button-outline.wje-color-info {\n background-color: var(--wje-color-contrast-1);\n border-color: var(--wje-color-contrast-9);\n color: var(--wje-color-contrast-9);\n}\n\n.wje-button-link.wje-color-info {\n background-color: transparent;\n border-color: transparent;\n color: var(--wje-color-contrast-9);\n}\n\n/*DEFAULT*/\n.wje-button-solid.wje-color-default {\n background-color: var(--wje-color-contrast-0);\n border-color: var(--wje-color-contrast-3);\n color: var(--wje-color-contrast-11);\n}\n\n.wje-button-outline.wje-color-default {\n background-color: var(--wje-color-contrast-1);\n border-color: var(--wje-color-contrast-5);\n color: var(--wje-color-contrast-11);\n}\n\n.wje-button-link.wje-color-default {\n background-color: transparent;\n border-color: transparent;\n color: var(--wje-color-contrast-11);\n}\n\n:host {\n --wje-padding-top: 0.4rem;\n --wje-padding-start: 0.5rem;\n --wje-padding-end: 0.5rem;\n --wje-padding-bottom: 0.4rem;\n\n display: inline-flex;\n position: relative;\n width: auto;\n cursor: pointer;\n margin-inline: var(--wje-button-margin-inline);\n}\n\n:host(.wje-button-group-button) {\n display: block;\n}\n\n.native-button {\n font-family: var(--wje-font-family);\n font-size: var(--wje-font-size);\n display: flex;\n position: relative;\n align-items: center;\n width: 100%;\n height: 100%;\n min-height: inherit;\n /*overflow: hidden;*/ /* Sposobovalo problemy s badge a tooltip */\n border-width: var(--wje-button-border-width);\n border-style: var(--wje-button-border-style);\n border-color: var(--wje-button-border-color);\n background-color: transparent;\n /*color: var(--wje-button-color);*/\n line-height: 1;\n contain: layout style;\n cursor: pointer;\n z-index: 0;\n box-sizing: border-box;\n appearance: none;\n margin: 0;\n border-radius: var(--wje-button-border-radius);\n padding-top: var(--wje-padding-top);\n padding-bottom: var(--wje-padding-bottom);\n padding-inline: var(--wje-padding-start) var(--wje-padding-end);\n white-space: nowrap;\n}\n\n.native-button:hover {\n outline-style: solid;\n outline-width: var(--wje-button-outline-width);\n transition: outline-width 0.1s linear;\n}\n\n@media (any-hover: hover) {\n .wje-button-solid.wje-color-primary:hover {\n background-color: var(--wje-color-primary-9);\n border-color: var(--wje-color-primary-9);\n color: var(--wje-color-contrast-0);\n outline-color: var(--wje-color-primary-2);\n }\n\n .wje-button-outline.wje-color-primary:hover {\n background-color: var(--wje-color-primary-1);\n border-color: var(--wje-color-primary-9);\n color: var(--wje-color-primary-9);\n outline-color: var(--wje-color-primary-2);\n }\n\n .wje-button-link.wje-color-primary:hover {\n background-color: var(--wje-color-primary-1);\n border-color: transparent;\n color: var(--wje-color-primary-9);\n outline-color: transparent;\n outline-width: 0;\n }\n\n .wje-button-solid.wje-color-complete:hover {\n background-color: var(--wje-color-complete-9);\n border-color: var(--wje-color-complete-9);\n color: var(--wje-color-contrast-0);\n outline-color: var(--wje-color-complete-2);\n }\n\n .wje-button-outline.wje-color-complete:hover {\n background-color: var(--wje-color-complete-1);\n border-color: var(--wje-color-complete-9);\n color: var(--wje-color-complete-9);\n outline-color: var(--wje-color-complete-2);\n }\n\n .wje-button-link.wje-color-complete:hover {\n background-color: var(--wje-color-complete-1);\n border-color: transparent;\n color: var(--wje-color-complete-9);\n outline-color: transparent;\n outline-width: 0;\n }\n\n .wje-button-solid.wje-color-success:hover {\n background-color: var(--wje-color-success-9);\n border-color: var(--wje-color-success-9);\n color: var(--wje-color-contrast-0);\n outline-color: var(--wje-color-success-2);\n }\n\n .wje-button-outline.wje-color-success:hover {\n background-color: var(--wje-color-success-1);\n border-color: var(--wje-color-success-9);\n color: var(--wje-color-success-9);\n outline-color: var(--wje-color-success-2);\n }\n\n .wje-button-link.wje-color-success:hover {\n background-color: var(--wje-color-success-1);\n border-color: transparent;\n color: var(--wje-color-success-9);\n outline-color: transparent;\n outline-width: 0;\n }\n\n .wje-button-solid.wje-color-warning:hover {\n background-color: var(--wje-color-warning-9);\n border-color: var(--wje-color-warning-9);\n color: var(--wje-color-black);\n outline-color: var(--wje-color-warning-2);\n }\n\n .wje-button-outline.wje-color-warning:hover {\n background-color: var(--wje-color-warning-1);\n border-color: var(--wje-color-warning-11);\n color: var(--wje-color-warning-11);\n outline-color: var(--wje-color-warning-2);\n }\n\n .wje-button-link.wje-color-warning:hover {\n background-color: var(--wje-color-warning-1);\n border-color: transparent;\n color: var(--wje-color-warning-11);\n outline-color: transparent;\n outline-width: 0;\n }\n\n .wje-button-solid.wje-color-danger:hover {\n background-color: var(--wje-color-danger-9);\n border-color: var(--wje-color-danger-9);\n color: var(--wje-color-contrast-0);\n outline-color: var(--wje-color-danger-2);\n }\n\n .wje-button-outline.wje-color-danger:hover {\n background-color: var(--wje-color-danger-1);\n border-color: var(--wje-color-danger-9);\n color: var(--wje-color-danger-9);\n outline-color: var(--wje-color-danger-2);\n }\n\n .wje-button-link.wje-color-danger:hover {\n background-color: var(--wje-color-danger-1);\n border-color: transparent;\n color: var(--wje-color-danger-9);\n outline-color: transparent;\n outline-width: 0;\n }\n\n .wje-button-solid.wje-color-info:hover {\n background-color: var(--wje-color-contrast-9);\n border-color: var(--wje-color-contrast-9);\n color: var(--wje-color-contrast-0);\n outline-color: var(--wje-color-contrast-3);\n }\n\n .wje-button-outline.wje-color-info:hover {\n background-color: var(--wje-color-contrast-1);\n border-color: var(--wje-color-contrast-9);\n color: var(--wje-color-contrast-9);\n outline-color: var(--wje-color-contrast-3);\n }\n\n .wje-button-link.wje-color-info:hover {\n background-color: var(--wje-color-contrast-3);\n border-color: transparent;\n color: var(--wje-color-contrast-11);\n outline-color: transparent;\n outline-width: 0;\n }\n\n .wje-button-solid.wje-color-default:hover {\n background-color: var(--wje-color-contrast-0);\n border-color: var(--wje-color-contrast-3);\n color: var(--wje-color-contrast-11);\n outline-color: var(--wje-color-contrast-3);\n }\n\n .wje-button-outline.wje-color-default:hover {\n background-color: var(--wje-color-contrast-2);\n border-color: var(--wje-color-contrast-5);\n color: var(--wje-color-contrast-11);\n outline-color: var(--wje-color-contrast-3);\n }\n\n .wje-button-link.wje-color-default:hover {\n background-color: var(--wje-color-contrast-3);\n border-color: transparent;\n color: var(--wje-color-contrast-11);\n outline-color: transparent;\n outline-width: 0;\n }\n}\n\n.button-inner {\n display: flex;\n position: relative;\n flex-flow: row nowrap;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n z-index: 1;\n line-height: normal;\n}\n\n/*\n[ Link ]\n*/\n\n.wje-button-link {\n border-width: var(--wje-button-border-width);\n border-radius: var(--wje-button-border-radius);\n border-color: transparent;\n background-color: transparent;\n}\n\n/*\n[ Disabled ]\n*/\n\n.wje-button-disabled {\n cursor: default;\n opacity: 0.5;\n pointer-events: none;\n}\n\n/*\n[ Round ]\n*/\n\n:host([round]) .native-button {\n border-radius: var(--wje-border-radius-pill);\n}\n\n:host([circle]) .native-button {\n border-radius: var(--wje-border-radius-circle);\n aspect-ratio: 1/1;\n width: 1.988rem;\n display: flex;\n align-items: center;\n --wje-padding-top: 0;\n --wje-padding-start: 0;\n --wje-padding-end: 0;\n --wje-padding-bottom: 0;\n}\n\n:host([size='small']) .native-button {\n --wje-padding-top: 0.25rem;\n --wje-padding-start: 0.25rem;\n --wje-padding-end: 0.25rem;\n --wje-padding-bottom: 0.25rem;\n}\n\n:host([size='large']) .native-button {\n --wje-padding-top: 0.6rem;\n --wje-padding-start: 0.7rem;\n --wje-padding-end: 0.7rem;\n --wje-padding-bottom: 0.6rem;\n}\n\n:host([size='small'][circle]) .native-button {\n width: 1.688rem;\n --wje-padding-top: 0;\n --wje-padding-start: 0;\n --wje-padding-end: 0;\n --wje-padding-bottom: 0;\n}\n\n:host([size='large'][circle]) .native-button {\n width: 2.388rem;\n --wje-padding-top: 0;\n --wje-padding-start: 0;\n --wje-padding-end: 0;\n --wje-padding-bottom: 0;\n}\n\n::slotted(wje-icon[slot='start']) {\n margin: 0 0.3rem 0 0;\n}\n\n::slotted(wje-icon[slot='end']) {\n margin: 0 -0.2rem 0 0.3rem;\n}\n\n:host(:not([only-caret])) slot[name='caret'] {\n padding: 0 0 0 0.3rem;\n}\n\n:host([only-caret]) {\n .native-button {\n aspect-ratio: 1/1;\n width: 1.988rem;\n display: flex;\n align-items: center;\n }\n slot[name='caret'] {\n padding: 0;\n display: block;\n }\n}\n\n::slotted([slot='toggle']) {\n display: none;\n}\n\n::slotted([slot='toggle'].show) {\n display: block;\n}\n";
|
|
@@ -3,7 +3,7 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
|
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
import WJElement from "./wje-element.js";
|
|
5
5
|
import { event } from "./event.js";
|
|
6
|
-
const styles = "/*\n[ WJ Carousel Item ]\n*/\n\n:host {\n display: flex;\n align-items:
|
|
6
|
+
const styles = "/*\n[ WJ Carousel Item ]\n*/\n\n:host {\n display: flex;\n align-items: stretch;\n justify-content: flex-start;\n flex-direction: column;\n width: var(--wje-carousel-item-basis, var(--wje-carousel-size, 100%));\n min-width: 0;\n max-width: 100%;\n max-height: 100%;\n align-self: stretch;\n aspect-ratio: var(--wje-carousel-item-aspect-ratio, inherit);\n scroll-snap-align: start;\n scroll-snap-stop: always;\n box-sizing: border-box;\n}\n\n.native-carousel-item {\n width: 100%;\n height: 100%;\n display: flex;\n flex: 1 1 auto;\n align-items: stretch;\n justify-content: flex-start;\n min-width: 0;\n box-sizing: border-box;\n}\n\nslot {\n display: flex;\n width: 100%;\n height: 100%;\n flex: 1 1 auto;\n align-items: stretch;\n justify-content: center;\n min-width: 0;\n}\n\n:host([single-content]) ::slotted(*) {\n width: 100%;\n min-width: 0;\n flex: 1 1 auto;\n}\n\n::slotted(wje-img) {\n width: 100% !important;\n height: 100% !important;\n object-fit: contain;\n display: flex;\n}\n";
|
|
7
7
|
class CarouselItem extends WJElement {
|
|
8
8
|
/**
|
|
9
9
|
* CarouselItem constructor method.
|
|
@@ -46,6 +46,7 @@ class CarouselItem extends WJElement {
|
|
|
46
46
|
native.classList.add("native-carousel-item");
|
|
47
47
|
native.setAttribute("part", "native");
|
|
48
48
|
let slot = document.createElement("slot");
|
|
49
|
+
this.defaultSlot = slot;
|
|
49
50
|
native.appendChild(slot);
|
|
50
51
|
fragment.appendChild(native);
|
|
51
52
|
return fragment;
|
|
@@ -55,6 +56,23 @@ class CarouselItem extends WJElement {
|
|
|
55
56
|
*/
|
|
56
57
|
afterDraw() {
|
|
57
58
|
event.addListener(this, "click", "wje-carousel-item:click");
|
|
59
|
+
this.syncContentLayoutMode();
|
|
60
|
+
if (this.defaultSlot && !this.defaultSlot.dataset.wjeCarouselItemBound) {
|
|
61
|
+
this.defaultSlot.addEventListener("slotchange", () => this.syncContentLayoutMode());
|
|
62
|
+
this.defaultSlot.dataset.wjeCarouselItemBound = "true";
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Keeps a simple layout hint for single-wrapper content.
|
|
67
|
+
*/
|
|
68
|
+
syncContentLayoutMode() {
|
|
69
|
+
var _a;
|
|
70
|
+
const assignedElements = ((_a = this.defaultSlot) == null ? void 0 : _a.assignedElements({ flatten: true })) || [];
|
|
71
|
+
if (assignedElements.length === 1) {
|
|
72
|
+
this.setAttribute("single-content", "");
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
this.removeAttribute("single-content");
|
|
58
76
|
}
|
|
59
77
|
}
|
|
60
78
|
WJElement.define("wje-carousel-item", CarouselItem);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wje-carousel-item.js","sources":["../packages/wje-carousel-item/carousel-item.element.js","../packages/wje-carousel-item/carousel-item.js"],"sourcesContent":["import { default as WJElement, event } from '../wje-element/element.js';\n\nimport styles from './styles/styles.css?inline';\n\n/**\n * @summary This class represents CarouselItem element, extending the WJElement class.\n * @documentation https://elements.webjet.sk/components/carousel-item\n * @status stable\n * @augments WJElement\n * @slot - The carousel item main content.\n * @csspart native - The component's native wrapper.\n * @cssproperty [--wje-carousel-item-background-color=transparent] - Background color of the component;\n * @cssproperty [--wje-carousel-item-border-color=--wje-color-contrast-4] - Border color of the component;\n * @cssproperty [--wje-carousel-item-color=--wje-color-contrast-11] - Color of the component;\n * @cssproperty [--wje-carousel-item-border-radius=--wje-border-radius-medium] - Border radius of the component;\n * @cssproperty [--wje-carousel-item-border-width=1px] - Border width of the component;\n * @cssproperty [--wje-carousel-item-border-style=solid] - Border style of the component;\n * @cssproperty [--wje-carousel-item-border-color=--wje-color-contrast-1] - Border color of the component;\n * @cssproperty [--wje-carousel-item-margin-inline=0] - Margin inline of the component;\n */\nexport default class CarouselItem extends WJElement {\n /**\n * CarouselItem constructor method.\n */\n constructor() {\n super();\n }\n\n /**\n * Class name for the CarouselItem element.\n * @type {string}\n */\n className = 'CarouselItem';\n\n /**\n * Getter for the CSS stylesheet.\n * @returns {*}\n */\n static get cssStyleSheet() {\n return styles;\n }\n\n /**\n * Getter for the observed attributes.\n * @returns {*[]}\n */\n static get observedAttributes() {\n return [];\n }\n\n /**\n * Sets up the attributes for the CarouselItem.\n */\n setupAttributes() {\n this.isShadowRoot = 'open';\n }\n\n /**\n * Draws the CarouselItem element.\n * @returns {DocumentFragment}\n */\n draw() {\n let fragment = document.createDocumentFragment();\n\n let native = document.createElement('div');\n native.classList.add('native-carousel-item');\n native.setAttribute('part', 'native');\n\n let slot = document.createElement('slot');\n\n native.appendChild(slot);\n\n fragment.appendChild(native);\n\n return fragment;\n }\n\n /**\n * After draw event for the CarouselItem element.\n */\n afterDraw() {\n event.addListener(this, 'click', 'wje-carousel-item:click');\n }\n}\n","import { default as WJElement } from '../wje-element/element.js';\nimport CarouselItem from './carousel-item.element.js';\n\n// export * from \"./carousel-item.element.js\";\nexport default CarouselItem;\n\nWJElement.define('wje-carousel-item', CarouselItem);\n"],"names":[],"mappings":";;;;;;AAoBe,MAAM,qBAAqB,UAAU;AAAA;AAAA;AAAA;AAAA,EAIhD,cAAc;AACV,UAAK;AAOT;AAAA;AAAA;AAAA;AAAA,qCAAY;AAAA,EANZ;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,WAAW,gBAAgB;AACvB,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAW,qBAAqB;AAC5B,WAAO,CAAA;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAkB;AACd,SAAK,eAAe;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO;AACH,QAAI,WAAW,SAAS,uBAAsB;AAE9C,QAAI,SAAS,SAAS,cAAc,KAAK;AACzC,WAAO,UAAU,IAAI,sBAAsB;AAC3C,WAAO,aAAa,QAAQ,QAAQ;AAEpC,QAAI,OAAO,SAAS,cAAc,MAAM;
|
|
1
|
+
{"version":3,"file":"wje-carousel-item.js","sources":["../packages/wje-carousel-item/carousel-item.element.js","../packages/wje-carousel-item/carousel-item.js"],"sourcesContent":["import { default as WJElement, event } from '../wje-element/element.js';\n\nimport styles from './styles/styles.css?inline';\n\n/**\n * @summary This class represents CarouselItem element, extending the WJElement class.\n * @documentation https://elements.webjet.sk/components/carousel-item\n * @status stable\n * @augments WJElement\n * @slot - The carousel item main content.\n * @csspart native - The component's native wrapper.\n * @cssproperty [--wje-carousel-item-background-color=transparent] - Background color of the component;\n * @cssproperty [--wje-carousel-item-border-color=--wje-color-contrast-4] - Border color of the component;\n * @cssproperty [--wje-carousel-item-color=--wje-color-contrast-11] - Color of the component;\n * @cssproperty [--wje-carousel-item-border-radius=--wje-border-radius-medium] - Border radius of the component;\n * @cssproperty [--wje-carousel-item-border-width=1px] - Border width of the component;\n * @cssproperty [--wje-carousel-item-border-style=solid] - Border style of the component;\n * @cssproperty [--wje-carousel-item-border-color=--wje-color-contrast-1] - Border color of the component;\n * @cssproperty [--wje-carousel-item-margin-inline=0] - Margin inline of the component;\n */\nexport default class CarouselItem extends WJElement {\n /**\n * CarouselItem constructor method.\n */\n constructor() {\n super();\n }\n\n /**\n * Class name for the CarouselItem element.\n * @type {string}\n */\n className = 'CarouselItem';\n\n /**\n * Getter for the CSS stylesheet.\n * @returns {*}\n */\n static get cssStyleSheet() {\n return styles;\n }\n\n /**\n * Getter for the observed attributes.\n * @returns {*[]}\n */\n static get observedAttributes() {\n return [];\n }\n\n /**\n * Sets up the attributes for the CarouselItem.\n */\n setupAttributes() {\n this.isShadowRoot = 'open';\n }\n\n /**\n * Draws the CarouselItem element.\n * @returns {DocumentFragment}\n */\n draw() {\n let fragment = document.createDocumentFragment();\n\n let native = document.createElement('div');\n native.classList.add('native-carousel-item');\n native.setAttribute('part', 'native');\n\n let slot = document.createElement('slot');\n this.defaultSlot = slot;\n\n native.appendChild(slot);\n\n fragment.appendChild(native);\n\n return fragment;\n }\n\n /**\n * After draw event for the CarouselItem element.\n */\n afterDraw() {\n event.addListener(this, 'click', 'wje-carousel-item:click');\n this.syncContentLayoutMode();\n\n if (this.defaultSlot && !this.defaultSlot.dataset.wjeCarouselItemBound) {\n this.defaultSlot.addEventListener('slotchange', () => this.syncContentLayoutMode());\n this.defaultSlot.dataset.wjeCarouselItemBound = 'true';\n }\n }\n\n /**\n * Keeps a simple layout hint for single-wrapper content.\n */\n syncContentLayoutMode() {\n const assignedElements = this.defaultSlot?.assignedElements({ flatten: true }) || [];\n\n if (assignedElements.length === 1) {\n this.setAttribute('single-content', '');\n return;\n }\n\n this.removeAttribute('single-content');\n }\n}\n","import { default as WJElement } from '../wje-element/element.js';\nimport CarouselItem from './carousel-item.element.js';\n\n// export * from \"./carousel-item.element.js\";\nexport default CarouselItem;\n\nWJElement.define('wje-carousel-item', CarouselItem);\n"],"names":[],"mappings":";;;;;;AAoBe,MAAM,qBAAqB,UAAU;AAAA;AAAA;AAAA;AAAA,EAIhD,cAAc;AACV,UAAK;AAOT;AAAA;AAAA;AAAA;AAAA,qCAAY;AAAA,EANZ;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,WAAW,gBAAgB;AACvB,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAW,qBAAqB;AAC5B,WAAO,CAAA;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAkB;AACd,SAAK,eAAe;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO;AACH,QAAI,WAAW,SAAS,uBAAsB;AAE9C,QAAI,SAAS,SAAS,cAAc,KAAK;AACzC,WAAO,UAAU,IAAI,sBAAsB;AAC3C,WAAO,aAAa,QAAQ,QAAQ;AAEpC,QAAI,OAAO,SAAS,cAAc,MAAM;AACxC,SAAK,cAAc;AAEnB,WAAO,YAAY,IAAI;AAEvB,aAAS,YAAY,MAAM;AAE3B,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY;AACR,UAAM,YAAY,MAAM,SAAS,yBAAyB;AAC1D,SAAK,sBAAqB;AAE1B,QAAI,KAAK,eAAe,CAAC,KAAK,YAAY,QAAQ,sBAAsB;AACpE,WAAK,YAAY,iBAAiB,cAAc,MAAM,KAAK,uBAAuB;AAClF,WAAK,YAAY,QAAQ,uBAAuB;AAAA,IACpD;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,wBAAwB;;AACpB,UAAM,qBAAmB,UAAK,gBAAL,mBAAkB,iBAAiB,EAAE,SAAS,KAAI,OAAO,CAAA;AAElF,QAAI,iBAAiB,WAAW,GAAG;AAC/B,WAAK,aAAa,kBAAkB,EAAE;AACtC;AAAA,IACJ;AAEA,SAAK,gBAAgB,gBAAgB;AAAA,EACzC;AACJ;AClGA,UAAU,OAAO,qBAAqB,YAAY;"}
|
package/dist/wje-carousel.js
CHANGED
|
@@ -2,7 +2,7 @@ var __defProp = Object.defineProperty;
|
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
import WJElement from "./wje-element.js";
|
|
5
|
-
const styles = '/*\n[ Carousel ]\n*/\n\n
|
|
5
|
+
const styles = '/*\n[ Carousel ]\n*/\n\n:host {\n display: block;\n width: var(--wje-carousel-width, 100%);\n max-width: 100%;\n box-sizing: border-box;\n}\n\n.native-carousel {\n position: relative;\n width: 100%;\n height: var(--wje-carousel-height, 300px);\n scroll-behavior: smooth;\n box-sizing: border-box;\n}\n\n.slides-wrapper {\n position: relative;\n display: flex;\n align-items: stretch;\n width: 100%;\n height: var(--wje-carousel-height, 300px);\n box-sizing: border-box;\n}\n\n.carousel-slides {\n display: flex;\n flex: 1 1 auto;\n transition: transform 0.5s ease;\n align-items: stretch;\n overflow: auto;\n overscroll-behavior-x: contain;\n scrollbar-width: none;\n -ms-overflow-style: none;\n aspect-ratio: var(--wje-aspect-ratio, 4 / 3);\n scroll-snap-type: x mandatory;\n scroll-padding-inline: var(--wje-spacing-inline, 0);\n overflow-y: hidden;\n padding-inline: var(--wje-spacing-inline, 0);\n gap: var(--wje-carousel-gap, 0.5rem);\n width: 100%;\n height: 100%;\n min-width: 0;\n min-height: 0;\n box-sizing: border-box;\n}\n\n.carousel-slides::-webkit-scrollbar {\n display: none;\n}\n\n::slotted(wje-carousel-item) {\n flex: 0 0 var(--wje-carousel-item-basis, var(--wje-carousel-size));\n width: var(--wje-carousel-item-basis, var(--wje-carousel-size));\n min-width: 0;\n max-width: 100%;\n align-self: stretch;\n height: 100%;\n box-sizing: border-box;\n}\n\n/*NAVIGATION*/\n\n[name="prev"], [name="next"] {\n display: block;\n position: absolute;\n top: 50%;\n border: none;\n cursor: pointer;\n z-index: 2;\n}\n\n[name="prev"] {\n left: -1rem;\n transform: translate(-100%, -50%);\n}\n\n[name="next"] {\n right: -1rem;\n transform: translate(100%, -50%);\n}\n\n/*PAGINATION*/\n\n.pagination {\n position: relative;\n left: 50%;\n transform: translate(-50%, 0);\n display: flex;\n z-index: 2;\n justify-content: center;\n padding-block: 1rem;\n}\n.pagination-item {\n cursor: pointer;\n height: 15px;\n width: 15px;\n margin: 0 2px;\n background-color: var(--wje-color-contrast-4);\n display: inline-block;\n border-radius: 50%;\n}\n.pagination-item.active {\n background-color: var(--wje-color);\n}\n\n/*THUMBNAILS*/\n\n.thumbnails {\n display: flex;\n justify-content: center;\n align-items: center;\n overflow-x: auto;\n gap: 0.5rem;\n padding: 0 0.5rem;\n margin-top: 0.5rem;\n margin-bottom: 0.5rem;\n box-sizing: border-box;\n overflow-y: hidden;\n wje-thumbnail {\n --wje-thumbnail-width: 48px;\n --wje-thumbnail-height: 48px;\n --wje-thumbnail-border-radius: 0;\n cursor: pointer;\n border: 1px solid transparent;\n }\n .active {\n border: 1px solid var(--wje-color-primary-11);\n }\n}\n';
|
|
6
6
|
class Carousel extends WJElement {
|
|
7
7
|
/**
|
|
8
8
|
* Carousel constructor method.
|
|
@@ -58,6 +58,13 @@ class Carousel extends WJElement {
|
|
|
58
58
|
get loop() {
|
|
59
59
|
return this.hasAttribute("loop");
|
|
60
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Continuous loop attribute.
|
|
63
|
+
* @returns {boolean}
|
|
64
|
+
*/
|
|
65
|
+
get continuousLoop() {
|
|
66
|
+
return this.hasAttribute("continuous-loop");
|
|
67
|
+
}
|
|
61
68
|
/**
|
|
62
69
|
* Getter for the CSS stylesheet.
|
|
63
70
|
* @returns {*}
|
|
@@ -70,7 +77,7 @@ class Carousel extends WJElement {
|
|
|
70
77
|
* @returns {string[]}
|
|
71
78
|
*/
|
|
72
79
|
static get observedAttributes() {
|
|
73
|
-
return ["active-slide"];
|
|
80
|
+
return ["active-slide", "slide-per-page", "continuous-loop"];
|
|
74
81
|
}
|
|
75
82
|
/**
|
|
76
83
|
* Sets up the attributes for the Carousel.
|
|
@@ -83,6 +90,14 @@ class Carousel extends WJElement {
|
|
|
83
90
|
if (this.pagination) this.changePagination();
|
|
84
91
|
if (this.thumbnails) this.changeThumbnails();
|
|
85
92
|
}
|
|
93
|
+
if (["slide-per-page", "continuous-loop"].includes(name) && old !== newName && this.slides) {
|
|
94
|
+
this.syncSlideMetrics();
|
|
95
|
+
if (this.loop) {
|
|
96
|
+
this.refresh();
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
this.goToSlide(this.activeSlide, "auto");
|
|
100
|
+
}
|
|
86
101
|
}
|
|
87
102
|
/**
|
|
88
103
|
* Sets up the attributes for the Carousel.
|
|
@@ -95,6 +110,8 @@ class Carousel extends WJElement {
|
|
|
95
110
|
* Before draw method for the Carousel.
|
|
96
111
|
*/
|
|
97
112
|
beforeDraw() {
|
|
113
|
+
this.syncSlideMetrics();
|
|
114
|
+
this.removeLoopClones();
|
|
98
115
|
this.cloneFirstAndLastItems();
|
|
99
116
|
}
|
|
100
117
|
/**
|
|
@@ -149,31 +166,28 @@ class Carousel extends WJElement {
|
|
|
149
166
|
this.getSlidesWithClones().forEach((slide, i) => {
|
|
150
167
|
this.intersectionObserver.observe(slide);
|
|
151
168
|
});
|
|
152
|
-
this.
|
|
153
|
-
let carouselSize = 100 / +this.slidePerPage;
|
|
154
|
-
this.style.setProperty("--wje-carousel-size", carouselSize + "%");
|
|
169
|
+
this.syncSlideMetrics();
|
|
155
170
|
this.goToSlide(this.activeSlide, "auto");
|
|
156
|
-
requestAnimationFrame(() => requestAnimationFrame(() => this.
|
|
171
|
+
requestAnimationFrame(() => requestAnimationFrame(() => this.syncActiveToSnapStart()));
|
|
157
172
|
this.slides.addEventListener("scrollend", (e) => {
|
|
158
|
-
this.
|
|
173
|
+
this.syncActiveToSnapStart();
|
|
159
174
|
});
|
|
160
175
|
this.syncAria();
|
|
161
176
|
}
|
|
162
177
|
/**
|
|
163
|
-
* Sync `activeSlide` to the slide whose
|
|
178
|
+
* Sync `activeSlide` to the slide whose leading edge is closest to the snap start.
|
|
164
179
|
*/
|
|
165
|
-
|
|
180
|
+
syncActiveToSnapStart() {
|
|
166
181
|
this.getSlides();
|
|
167
182
|
const withClones = this.getSlidesWithClones();
|
|
168
183
|
if (!withClones.length) return;
|
|
169
184
|
const containerRect = this.slides.getBoundingClientRect();
|
|
170
|
-
const
|
|
185
|
+
const snapStartX = containerRect.left + this.getScrollPaddingInlineStart();
|
|
171
186
|
let best = null;
|
|
172
187
|
let bestDist = Infinity;
|
|
173
188
|
withClones.forEach((el) => {
|
|
174
189
|
const r = el.getBoundingClientRect();
|
|
175
|
-
const
|
|
176
|
-
const dist = Math.abs(center - containerCenterX);
|
|
190
|
+
const dist = Math.abs(r.left - snapStartX);
|
|
177
191
|
if (dist < bestDist) {
|
|
178
192
|
bestDist = dist;
|
|
179
193
|
best = el;
|
|
@@ -184,10 +198,42 @@ class Carousel extends WJElement {
|
|
|
184
198
|
if (vIndex === -1) return;
|
|
185
199
|
const logicalIndex = this.getLogicalIndexForVisual(vIndex);
|
|
186
200
|
this.activeSlide = logicalIndex;
|
|
187
|
-
|
|
201
|
+
this.setActiveVisualSlide(vIndex);
|
|
202
|
+
const canonicalVisualIndex = this.getVisualIndexForLogical(logicalIndex);
|
|
203
|
+
if (canonicalVisualIndex !== vIndex) {
|
|
188
204
|
this.goToSlide(logicalIndex, "auto");
|
|
189
205
|
}
|
|
190
206
|
}
|
|
207
|
+
/**
|
|
208
|
+
* Syncs computed CSS variables derived from `slide-per-page`.
|
|
209
|
+
*/
|
|
210
|
+
syncSlideMetrics() {
|
|
211
|
+
this.slidePerPage = Math.max(parseInt(this.getAttribute("slide-per-page"), 10) || 1, 1);
|
|
212
|
+
const visibleGapCount = Math.max(this.slidePerPage - 1, 0);
|
|
213
|
+
const computedItemSize = `calc((100% - (${visibleGapCount} * var(--wje-carousel-gap, 0.5rem))) / ${this.slidePerPage})`;
|
|
214
|
+
this.style.setProperty("--wje-carousel-slides-per-page", `${this.slidePerPage}`);
|
|
215
|
+
this.style.setProperty("--wje-carousel-visible-gap-count", `${visibleGapCount}`);
|
|
216
|
+
this.style.setProperty("--wje-carousel-size", computedItemSize);
|
|
217
|
+
this.style.setProperty("--wje-carousel-item-basis", "var(--wje-carousel-size)");
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Returns the inline scroll padding used by the snap area.
|
|
221
|
+
* @returns {number}
|
|
222
|
+
*/
|
|
223
|
+
getScrollPaddingInlineStart() {
|
|
224
|
+
if (!this.slides) return 0;
|
|
225
|
+
const styles2 = getComputedStyle(this.slides);
|
|
226
|
+
return parseFloat(styles2.scrollPaddingInlineStart || styles2.scrollPaddingLeft || "0") || 0;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Returns the interaction scroll behavior for UI controls.
|
|
230
|
+
* Continuous multi-slide loops use instant snapping to avoid blank edge states
|
|
231
|
+
* while the browser is still animating a previous smooth scroll.
|
|
232
|
+
* @returns {ScrollBehavior|string}
|
|
233
|
+
*/
|
|
234
|
+
getControlBehavior() {
|
|
235
|
+
return this.continuousLoop && this.slidePerPage > 1 ? "auto" : "smooth";
|
|
236
|
+
}
|
|
191
237
|
/**
|
|
192
238
|
* Sets up the IntersectionObserver for the Carousel.
|
|
193
239
|
*/
|
|
@@ -218,11 +264,10 @@ class Carousel extends WJElement {
|
|
|
218
264
|
goToSlide(index, behavior = "smooth", next = true) {
|
|
219
265
|
const slides = this.getSlides();
|
|
220
266
|
const withClones = this.getSlidesWithClones();
|
|
221
|
-
|
|
222
|
-
const maxIndex = Math.max(slides.length - 1, 0);
|
|
267
|
+
const maxIndex = this.getMaxVisibleStartIndex(slides.length);
|
|
223
268
|
let logical;
|
|
224
269
|
if (this.loop && slides.length > 0) {
|
|
225
|
-
logical = (index
|
|
270
|
+
logical = this.normalizeLoopIndex(index, slides.length);
|
|
226
271
|
} else {
|
|
227
272
|
logical = Math.min(Math.max(index, 0), maxIndex);
|
|
228
273
|
}
|
|
@@ -230,22 +275,25 @@ class Carousel extends WJElement {
|
|
|
230
275
|
const vIndex = this.getVisualIndexForLogical(logical);
|
|
231
276
|
const targetEl = withClones[vIndex];
|
|
232
277
|
if (!targetEl) return;
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
const containerRect = this.slides.getBoundingClientRect();
|
|
236
|
-
this.slides.scrollTo({
|
|
237
|
-
left: targetRect.left - containerRect.left + this.slides.scrollLeft,
|
|
238
|
-
top: targetRect.top - containerRect.top + this.slides.scrollTop,
|
|
239
|
-
behavior: behavior === "smooth" ? "smooth" : "auto"
|
|
240
|
-
});
|
|
278
|
+
this.setActiveVisualSlide(vIndex);
|
|
279
|
+
this.scrollToVisualIndex(vIndex, behavior);
|
|
241
280
|
if (this.navigation && !this.loop) {
|
|
242
281
|
this.nextButton.removeAttribute("disabled");
|
|
243
282
|
this.prevButton.removeAttribute("disabled");
|
|
244
|
-
if (this.activeSlide ===
|
|
283
|
+
if (this.activeSlide === maxIndex) this.nextButton.setAttribute("disabled", "");
|
|
245
284
|
if (this.activeSlide === 0) this.prevButton.setAttribute("disabled", "");
|
|
246
285
|
}
|
|
247
286
|
this.syncAria();
|
|
248
287
|
}
|
|
288
|
+
/**
|
|
289
|
+
* Sets the active class on the currently targeted visual slide and removes it elsewhere.
|
|
290
|
+
* @param {number} vIndex
|
|
291
|
+
*/
|
|
292
|
+
setActiveVisualSlide(vIndex) {
|
|
293
|
+
this.getSlidesWithClones().forEach((slide, index) => {
|
|
294
|
+
slide.classList.toggle("active", index === vIndex);
|
|
295
|
+
});
|
|
296
|
+
}
|
|
249
297
|
/**
|
|
250
298
|
* Syncs ARIA attributes on the carousel and slides.
|
|
251
299
|
*/
|
|
@@ -273,14 +321,88 @@ class Carousel extends WJElement {
|
|
|
273
321
|
cloneFirstAndLastItems() {
|
|
274
322
|
const items = this.getSlides();
|
|
275
323
|
if (items.length && this.loop) {
|
|
276
|
-
const
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
324
|
+
const cloneCount = this.getLoopCloneCount(items.length);
|
|
325
|
+
const firstOriginal = items[0];
|
|
326
|
+
items.slice(items.length - cloneCount).forEach((item) => {
|
|
327
|
+
const clone = this.createLoopClone(item);
|
|
328
|
+
this.insertBefore(clone, firstOriginal);
|
|
329
|
+
});
|
|
330
|
+
items.slice(0, cloneCount).forEach((item) => {
|
|
331
|
+
const clone = this.createLoopClone(item);
|
|
332
|
+
this.append(clone);
|
|
333
|
+
});
|
|
282
334
|
}
|
|
283
335
|
}
|
|
336
|
+
/**
|
|
337
|
+
* Creates a sanitized loop clone that does not inherit transient render state
|
|
338
|
+
* such as inline `visibility: hidden` from the source slide.
|
|
339
|
+
* @param {HTMLElement} item
|
|
340
|
+
* @returns {HTMLElement}
|
|
341
|
+
*/
|
|
342
|
+
createLoopClone(item) {
|
|
343
|
+
var _a;
|
|
344
|
+
const clone = item.cloneNode(true);
|
|
345
|
+
clone.classList.add("clone");
|
|
346
|
+
clone.classList.remove("active");
|
|
347
|
+
clone.style.removeProperty("visibility");
|
|
348
|
+
if (!((_a = clone.getAttribute("style")) == null ? void 0 : _a.trim())) {
|
|
349
|
+
clone.removeAttribute("style");
|
|
350
|
+
}
|
|
351
|
+
return clone;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Removes loop clones so they can be rebuilt for the current configuration.
|
|
355
|
+
*/
|
|
356
|
+
removeLoopClones() {
|
|
357
|
+
this.querySelectorAll("wje-carousel-item.clone").forEach((clone) => clone.remove());
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Returns how many slides should be cloned on each side when loop is enabled.
|
|
361
|
+
* @param {number} totalSlides
|
|
362
|
+
* @returns {number}
|
|
363
|
+
*/
|
|
364
|
+
getLoopCloneCount(totalSlides = this.getSlides().length) {
|
|
365
|
+
if (!this.loop || !totalSlides) return 0;
|
|
366
|
+
return this.continuousLoop ? Math.min(this.slidePerPage, totalSlides) : 1;
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Scrolls the carousel to a visual slide index.
|
|
370
|
+
* @param {number} vIndex
|
|
371
|
+
* @param {ScrollBehavior|string} behavior
|
|
372
|
+
*/
|
|
373
|
+
scrollToVisualIndex(vIndex, behavior = "smooth") {
|
|
374
|
+
const withClones = this.getSlidesWithClones();
|
|
375
|
+
const firstEl = withClones[0];
|
|
376
|
+
const targetEl = withClones[vIndex];
|
|
377
|
+
if (!firstEl || !targetEl || !this.slides) return;
|
|
378
|
+
const firstRect = firstEl.getBoundingClientRect();
|
|
379
|
+
const targetRect = targetEl.getBoundingClientRect();
|
|
380
|
+
const contentOffsetLeft = targetRect.left - firstRect.left;
|
|
381
|
+
const nextLeft = contentOffsetLeft - this.getScrollPaddingInlineStart();
|
|
382
|
+
const targetLeft = Math.max(nextLeft, 0);
|
|
383
|
+
if (behavior === "smooth") {
|
|
384
|
+
this.slides.scrollTo({
|
|
385
|
+
left: targetLeft,
|
|
386
|
+
top: this.slides.scrollTop,
|
|
387
|
+
behavior: "smooth"
|
|
388
|
+
});
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
if (this.snapRestoreFrame) {
|
|
392
|
+
cancelAnimationFrame(this.snapRestoreFrame);
|
|
393
|
+
}
|
|
394
|
+
const inlineSnapType = this.slides.style.scrollSnapType;
|
|
395
|
+
this.slides.style.scrollSnapType = "none";
|
|
396
|
+
this.slides.scrollTo({
|
|
397
|
+
left: targetLeft,
|
|
398
|
+
top: this.slides.scrollTop,
|
|
399
|
+
behavior: "auto"
|
|
400
|
+
});
|
|
401
|
+
this.snapRestoreFrame = requestAnimationFrame(() => {
|
|
402
|
+
this.slides.style.scrollSnapType = inlineSnapType;
|
|
403
|
+
this.snapRestoreFrame = null;
|
|
404
|
+
});
|
|
405
|
+
}
|
|
284
406
|
/**
|
|
285
407
|
* Goes to the next slide.
|
|
286
408
|
*/
|
|
@@ -304,11 +426,8 @@ class Carousel extends WJElement {
|
|
|
304
426
|
*/
|
|
305
427
|
changePagination() {
|
|
306
428
|
if (this.pagination) {
|
|
307
|
-
this.removeActiveSlide();
|
|
308
429
|
this.context.querySelectorAll(".pagination-item").forEach((item, i) => {
|
|
309
|
-
|
|
310
|
-
item.classList.add("active");
|
|
311
|
-
}
|
|
430
|
+
item.classList.toggle("active", i === this.activeSlide);
|
|
312
431
|
});
|
|
313
432
|
}
|
|
314
433
|
}
|
|
@@ -317,11 +436,8 @@ class Carousel extends WJElement {
|
|
|
317
436
|
*/
|
|
318
437
|
changeThumbnails() {
|
|
319
438
|
if (this.thumbnails) {
|
|
320
|
-
this.removeActiveSlide();
|
|
321
439
|
this.context.querySelectorAll("wje-thumbnail").forEach((item, i) => {
|
|
322
|
-
|
|
323
|
-
item.classList.add("active");
|
|
324
|
-
}
|
|
440
|
+
item.classList.toggle("active", i === this.activeSlide);
|
|
325
441
|
});
|
|
326
442
|
}
|
|
327
443
|
}
|
|
@@ -337,9 +453,6 @@ class Carousel extends WJElement {
|
|
|
337
453
|
nextButton.setAttribute("slot", "next");
|
|
338
454
|
nextButton.innerHTML = '<wje-icon name="chevron-right" size="large"></wje-icon>';
|
|
339
455
|
nextButton.classList.add("next");
|
|
340
|
-
nextButton.addEventListener("click", (e) => {
|
|
341
|
-
this.nextSlide();
|
|
342
|
-
});
|
|
343
456
|
return nextButton;
|
|
344
457
|
}
|
|
345
458
|
/**
|
|
@@ -354,9 +467,6 @@ class Carousel extends WJElement {
|
|
|
354
467
|
previousButton.setAttribute("slot", "prev");
|
|
355
468
|
previousButton.innerHTML = '<wje-icon name="chevron-left" size="large"></wje-icon>';
|
|
356
469
|
previousButton.classList.add("prev");
|
|
357
|
-
previousButton.addEventListener("click", (e) => {
|
|
358
|
-
this.previousSlide();
|
|
359
|
-
});
|
|
360
470
|
return previousButton;
|
|
361
471
|
}
|
|
362
472
|
/**
|
|
@@ -367,14 +477,13 @@ class Carousel extends WJElement {
|
|
|
367
477
|
const pagination = document.createElement("div");
|
|
368
478
|
pagination.setAttribute("part", "pagination");
|
|
369
479
|
pagination.classList.add("pagination");
|
|
370
|
-
|
|
371
|
-
slides.forEach((slide, i) => {
|
|
480
|
+
this.getPaginationIndexes().forEach((i) => {
|
|
372
481
|
const paginationItem = document.createElement("div");
|
|
373
482
|
paginationItem.classList.add("pagination-item");
|
|
374
483
|
paginationItem.addEventListener("click", (e) => {
|
|
375
484
|
this.removeActiveSlide();
|
|
376
485
|
e.target.classList.add("active");
|
|
377
|
-
this.goToSlide(i);
|
|
486
|
+
this.goToSlide(i, this.getControlBehavior());
|
|
378
487
|
});
|
|
379
488
|
pagination.append(paginationItem);
|
|
380
489
|
});
|
|
@@ -394,7 +503,7 @@ class Carousel extends WJElement {
|
|
|
394
503
|
thumbnail.addEventListener("click", (e) => {
|
|
395
504
|
this.removeActiveSlide();
|
|
396
505
|
e.target.closest("wje-thumbnail").classList.add("active");
|
|
397
|
-
this.goToSlide(i);
|
|
506
|
+
this.goToSlide(i, this.getControlBehavior());
|
|
398
507
|
});
|
|
399
508
|
thumbnails.append(thumbnail);
|
|
400
509
|
});
|
|
@@ -404,13 +513,13 @@ class Carousel extends WJElement {
|
|
|
404
513
|
* Goes to the next slide.
|
|
405
514
|
*/
|
|
406
515
|
nextSlide() {
|
|
407
|
-
this.goToSlide(this.activeSlide + this.
|
|
516
|
+
this.goToSlide(this.activeSlide + 1, this.getControlBehavior());
|
|
408
517
|
}
|
|
409
518
|
/**
|
|
410
519
|
* Goes to the previous slide.
|
|
411
520
|
*/
|
|
412
521
|
previousSlide() {
|
|
413
|
-
this.goToSlide(this.activeSlide - this.
|
|
522
|
+
this.goToSlide(this.activeSlide - 1, this.getControlBehavior());
|
|
414
523
|
}
|
|
415
524
|
/**
|
|
416
525
|
* Goes to the slide.
|
|
@@ -428,16 +537,58 @@ class Carousel extends WJElement {
|
|
|
428
537
|
}
|
|
429
538
|
/** Maps logical index -> visual index (accounts for leading clone when loop=true) */
|
|
430
539
|
getVisualIndexForLogical(index) {
|
|
431
|
-
return this.loop ? index +
|
|
540
|
+
return this.loop ? index + this.getLoopCloneCount() : index;
|
|
432
541
|
}
|
|
433
542
|
/** Maps visual index -> logical index (handles clones at 0 and last when loop=true) */
|
|
434
543
|
getLogicalIndexForVisual(vIndex) {
|
|
435
544
|
const slides = this.getSlides();
|
|
436
|
-
const
|
|
437
|
-
|
|
438
|
-
if (
|
|
439
|
-
if (
|
|
440
|
-
|
|
545
|
+
const maxIndex = this.getMaxVisibleStartIndex(slides.length);
|
|
546
|
+
const cloneCount = this.getLoopCloneCount(slides.length);
|
|
547
|
+
if (!this.loop) return Math.min(Math.max(vIndex, 0), maxIndex);
|
|
548
|
+
if (this.continuousLoop) {
|
|
549
|
+
if (vIndex < cloneCount) return slides.length - cloneCount + vIndex;
|
|
550
|
+
if (vIndex >= cloneCount + slides.length) return vIndex - (cloneCount + slides.length);
|
|
551
|
+
return vIndex - cloneCount;
|
|
552
|
+
}
|
|
553
|
+
if (vIndex < cloneCount) return maxIndex;
|
|
554
|
+
if (vIndex >= cloneCount + slides.length) return 0;
|
|
555
|
+
return Math.min(Math.max(vIndex - cloneCount, 0), maxIndex);
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Returns the maximum logical slide index that can still render a full viewport.
|
|
559
|
+
* @param {number} totalSlides
|
|
560
|
+
* @returns {number}
|
|
561
|
+
*/
|
|
562
|
+
getMaxVisibleStartIndex(totalSlides = this.getSlides().length) {
|
|
563
|
+
const visibleSlides = Math.min(this.slidePerPage, totalSlides);
|
|
564
|
+
return Math.max(totalSlides - visibleSlides, 0);
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* Normalizes a logical index for the active loop mode.
|
|
568
|
+
* @param {number} index
|
|
569
|
+
* @param {number} totalSlides
|
|
570
|
+
* @returns {number}
|
|
571
|
+
*/
|
|
572
|
+
normalizeLoopIndex(index, totalSlides = this.getSlides().length) {
|
|
573
|
+
const logicalCount = this.getLoopLogicalCount(totalSlides);
|
|
574
|
+
if (!logicalCount) return 0;
|
|
575
|
+
return (index % logicalCount + logicalCount) % logicalCount;
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
578
|
+
* Returns how many logical positions are reachable for the current loop mode.
|
|
579
|
+
* @param {number} totalSlides
|
|
580
|
+
* @returns {number}
|
|
581
|
+
*/
|
|
582
|
+
getLoopLogicalCount(totalSlides = this.getSlides().length) {
|
|
583
|
+
if (!totalSlides) return 0;
|
|
584
|
+
return this.continuousLoop ? totalSlides : this.getMaxVisibleStartIndex(totalSlides) + 1;
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Returns the pagination indexes for the current carousel mode.
|
|
588
|
+
* @returns {number[]}
|
|
589
|
+
*/
|
|
590
|
+
getPaginationIndexes() {
|
|
591
|
+
return Array.from({ length: this.getLoopLogicalCount() }, (_, index) => index);
|
|
441
592
|
}
|
|
442
593
|
/**
|
|
443
594
|
* Goes to the slide.
|